wp-login.php 38.6 KB
Newer Older
godog's avatar
godog committed
1 2 3 4 5 6 7 8 9 10 11
<?php
/**
 * WordPress User Page
 *
 * Handles authentication, registering, resetting passwords, forgot password,
 * and other user handling.
 *
 * @package WordPress
 */

/** Make sure that the WordPress bootstrap has run before continuing. */
samba's avatar
samba committed
12
require( dirname( __FILE__ ) . '/wp-load.php' );
godog's avatar
godog committed
13

samba's avatar
samba committed
14
// Redirect to HTTPS login if forced to use SSL.
lechuck's avatar
lechuck committed
15
if ( force_ssl_admin() && ! is_ssl() ) {
samba's avatar
samba committed
16
	if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
kiki's avatar
kiki committed
17
		wp_safe_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
godog's avatar
godog committed
18 19
		exit();
	} else {
kiki's avatar
kiki committed
20
		wp_safe_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
godog's avatar
godog committed
21 22 23 24 25
		exit();
	}
}

/**
lucha's avatar
lucha committed
26
 * Output the login page header.
godog's avatar
godog committed
27
 *
samba's avatar
samba committed
28 29
 * @since 2.1.0
 *
lechuck's avatar
lechuck committed
30 31
 * @param string   $title    Optional. WordPress login Page title to display in the `<title>` element.
 *                           Default 'Log In'.
lucha's avatar
lucha committed
32
 * @param string   $message  Optional. Message to display in header. Default empty.
lucha's avatar
lucha committed
33
 * @param WP_Error $wp_error Optional. The error to pass. Default is a WP_Error instance.
godog's avatar
godog committed
34
 */
lucha's avatar
lucha committed
35
function login_header( $title = 'Log In', $message = '', $wp_error = null ) {
lucha's avatar
lucha committed
36
	global $error, $interim_login, $action;
godog's avatar
godog committed
37 38

	// Don't index any of these forms
lucha's avatar
lucha committed
39
	add_action( 'login_head', 'wp_sensitive_page_meta' );
godog's avatar
godog committed
40

lucha's avatar
lucha committed
41
	add_action( 'login_head', 'wp_login_viewport_meta' );
lucha's avatar
lucha committed
42

lucha's avatar
lucha committed
43
	if ( ! is_wp_error( $wp_error ) ) {
godog's avatar
godog committed
44
		$wp_error = new WP_Error();
lucha's avatar
lucha committed
45
	}
godog's avatar
godog committed
46 47 48

	// Shake it!
	$shake_error_codes = array( 'empty_password', 'empty_email', 'invalid_email', 'invalidcombo', 'empty_username', 'invalid_username', 'incorrect_password' );
lucha's avatar
lucha committed
49
	/**
lucha's avatar
lucha committed
50
	 * Filters the error codes array for shaking the login form.
lucha's avatar
lucha committed
51 52 53 54 55
	 *
	 * @since 3.0.0
	 *
	 * @param array $shake_error_codes Error codes that shake the login form.
	 */
godog's avatar
godog committed
56 57
	$shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );

samba's avatar
samba committed
58
	if ( $shake_error_codes && $wp_error->has_errors() && in_array( $wp_error->get_error_code(), $shake_error_codes ) ) {
godog's avatar
godog committed
59
		add_action( 'login_head', 'wp_shake_js', 12 );
samba's avatar
samba committed
60
	}
godog's avatar
godog committed
61

lucha's avatar
lucha committed
62 63 64 65 66
	$login_title = get_bloginfo( 'name', 'display' );

	/* translators: Login screen title. 1: Login screen name, 2: Network or site name */
	$login_title = sprintf( __( '%1$s &lsaquo; %2$s &#8212; WordPress' ), $title, $login_title );

agata's avatar
agata committed
67 68 69 70 71
	if ( wp_is_recovery_mode() ) {
		/* translators: %s: Login screen title. */
		$login_title = sprintf( __( 'Recovery Mode &#8212; %s' ), $login_title );
	}

lucha's avatar
lucha committed
72 73 74 75 76 77 78 79 80
	/**
	 * Filters the title tag content for login page.
	 *
	 * @since 4.9.0
	 *
	 * @param string $login_title The page title, with extra context added.
	 * @param string $title       The original page title.
	 */
	$login_title = apply_filters( 'login_title', $login_title, $title );
lechuck's avatar
lechuck committed
81

lechuck's avatar
lechuck committed
82
	?><!DOCTYPE html>
lucha's avatar
lucha committed
83 84 85 86 87 88
	<!--[if IE 8]>
		<html xmlns="http://www.w3.org/1999/xhtml" class="ie8" <?php language_attributes(); ?>>
	<![endif]-->
	<!--[if !(IE 8) ]><!-->
		<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
	<!--<![endif]-->
lechuck's avatar
lechuck committed
89
	<head>
samba's avatar
samba committed
90
	<meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php bloginfo( 'charset' ); ?>" />
lucha's avatar
lucha committed
91
	<title><?php echo $login_title; ?></title>
lechuck's avatar
lechuck committed
92 93
	<?php

lechuck's avatar
lechuck committed
94
	wp_enqueue_style( 'login' );
godog's avatar
godog committed
95

lucha's avatar
lucha committed
96 97 98
	/*
	 * Remove all stored post data on logging out.
	 * This could be added by add_action('login_head'...) like wp_shake_js(),
samba's avatar
samba committed
99
	 * but maybe better if it's not removable by plugins.
lucha's avatar
lucha committed
100
	 */
lechuck's avatar
lechuck committed
101 102 103 104
	if ( 'loggedout' == $wp_error->get_error_code() ) {
		?>
		<script>if("sessionStorage" in window){try{for(var key in sessionStorage){if(key.indexOf("wp-autosave-")!=-1){sessionStorage.removeItem(key)}}}catch(e){}};</script>
		<?php
godog's avatar
godog committed
105 106
	}

lucha's avatar
lucha committed
107 108 109 110 111
	/**
	 * Enqueue scripts and styles for the login page.
	 *
	 * @since 3.1.0
	 */
root's avatar
root committed
112
	do_action( 'login_enqueue_scripts' );
lechuck's avatar
lechuck committed
113

lucha's avatar
lucha committed
114 115 116 117 118
	/**
	 * Fires in the login page header after scripts are enqueued.
	 *
	 * @since 2.1.0
	 */
lechuck's avatar
lechuck committed
119 120
	do_action( 'login_head' );

agata's avatar
agata committed
121
	$login_header_url = __( 'https://wordpress.org/' );
lechuck's avatar
lechuck committed
122

lucha's avatar
lucha committed
123
	/**
lucha's avatar
lucha committed
124
	 * Filters link URL of the header logo above login form.
lucha's avatar
lucha committed
125 126 127 128 129 130
	 *
	 * @since 2.1.0
	 *
	 * @param string $login_header_url Login header logo URL.
	 */
	$login_header_url = apply_filters( 'login_headerurl', $login_header_url );
lucha's avatar
lucha committed
131

agata's avatar
agata committed
132 133
	$login_header_title = '';

lucha's avatar
lucha committed
134
	/**
lucha's avatar
lucha committed
135
	 * Filters the title attribute of the header logo above login form.
lucha's avatar
lucha committed
136 137
	 *
	 * @since 2.1.0
agata's avatar
agata committed
138
	 * @deprecated 5.2.0 Use login_headertext
lucha's avatar
lucha committed
139 140 141
	 *
	 * @param string $login_header_title Login header logo title attribute.
	 */
agata's avatar
agata committed
142 143 144 145 146 147 148
	$login_header_title = apply_filters_deprecated(
		'login_headertitle',
		array( $login_header_title ),
		'5.2.0',
		'login_headertext',
		__( 'Usage of the title attribute on the login logo is not recommended for accessibility reasons. Use the link text instead.' )
	);
lechuck's avatar
lechuck committed
149

agata's avatar
agata committed
150 151 152 153 154 155 156 157
	$login_header_text = empty( $login_header_title ) ? __( 'Powered by WordPress' ) : $login_header_title;

	/**
	 * Filters the link text of the header logo above the login form.
	 *
	 * @since 5.2.0
	 *
	 * @param string $login_header_text The login header logo link text.
lucha's avatar
lucha committed
158
	 */
agata's avatar
agata committed
159
	$login_header_text = apply_filters( 'login_headertext', $login_header_text );
lucha's avatar
lucha committed
160

lechuck's avatar
lechuck committed
161
	$classes = array( 'login-action-' . $action, 'wp-core-ui' );
samba's avatar
samba committed
162
	if ( is_rtl() ) {
lechuck's avatar
lechuck committed
163
		$classes[] = 'rtl';
samba's avatar
samba committed
164
	}
lechuck's avatar
lechuck committed
165 166 167 168 169 170
	if ( $interim_login ) {
		$classes[] = 'interim-login';
		?>
		<style type="text/css">html{background-color: transparent;}</style>
		<?php

samba's avatar
samba committed
171
		if ( 'success' === $interim_login ) {
lechuck's avatar
lechuck committed
172
			$classes[] = 'interim-login-success';
samba's avatar
samba committed
173
		}
lechuck's avatar
lechuck committed
174
	}
samba's avatar
samba committed
175
	$classes[] = ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) );
lechuck's avatar
lechuck committed
176

lucha's avatar
lucha committed
177
	/**
lucha's avatar
lucha committed
178
	 * Filters the login page body classes.
lucha's avatar
lucha committed
179 180 181 182 183 184
	 *
	 * @since 3.5.0
	 *
	 * @param array  $classes An array of body classes.
	 * @param string $action  The action that brought the visitor to the login page.
	 */
lechuck's avatar
lechuck committed
185
	$classes = apply_filters( 'login_body_class', $classes, $action );
lechuck's avatar
lechuck committed
186

lechuck's avatar
lechuck committed
187 188
	?>
	</head>
lechuck's avatar
lechuck committed
189
	<body class="login <?php echo esc_attr( implode( ' ', $classes ) ); ?>">
lucha's avatar
lucha committed
190 191 192 193 194 195 196 197
	<?php
	/**
	 * Fires in the login page header after the body tag is opened.
	 *
	 * @since 4.6.0
	 */
	do_action( 'login_header' );
	?>
lechuck's avatar
lechuck committed
198
	<div id="login">
agata's avatar
agata committed
199
		<h1><a href="<?php echo esc_url( $login_header_url ); ?>"><?php echo $login_header_text; ?></a></h1>
lechuck's avatar
lechuck committed
200
	<?php
lucha's avatar
lucha committed
201
	/**
lucha's avatar
lucha committed
202
	 * Filters the message to display above the login form.
lucha's avatar
lucha committed
203 204 205 206 207 208
	 *
	 * @since 2.1.0
	 *
	 * @param string $message Login message text.
	 */
	$message = apply_filters( 'login_message', $message );
samba's avatar
samba committed
209
	if ( ! empty( $message ) ) {
lechuck's avatar
lechuck committed
210
		echo $message . "\n";
samba's avatar
samba committed
211
	}
godog's avatar
godog committed
212

samba's avatar
samba committed
213 214 215 216
	// In case a plugin uses $error rather than the $wp_errors object.
	if ( ! empty( $error ) ) {
		$wp_error->add( 'error', $error );
		unset( $error );
godog's avatar
godog committed
217 218
	}

samba's avatar
samba committed
219 220
	if ( $wp_error->has_errors() ) {
		$errors   = '';
godog's avatar
godog committed
221 222
		$messages = '';
		foreach ( $wp_error->get_error_codes() as $code ) {
lucha's avatar
lucha committed
223 224
			$severity = $wp_error->get_error_data( $code );
			foreach ( $wp_error->get_error_messages( $code ) as $error_message ) {
samba's avatar
samba committed
225
				if ( 'message' == $severity ) {
lucha's avatar
lucha committed
226
					$messages .= '	' . $error_message . "<br />\n";
samba's avatar
samba committed
227
				} else {
lucha's avatar
lucha committed
228
					$errors .= '	' . $error_message . "<br />\n";
samba's avatar
samba committed
229
				}
godog's avatar
godog committed
230 231
			}
		}
lucha's avatar
lucha committed
232 233
		if ( ! empty( $errors ) ) {
			/**
lucha's avatar
lucha committed
234
			 * Filters the error messages displayed above the login form.
lucha's avatar
lucha committed
235 236 237 238 239 240 241 242 243
			 *
			 * @since 2.1.0
			 *
			 * @param string $errors Login error message.
			 */
			echo '<div id="login_error">' . apply_filters( 'login_errors', $errors ) . "</div>\n";
		}
		if ( ! empty( $messages ) ) {
			/**
lucha's avatar
lucha committed
244
			 * Filters instructional messages displayed above the login form.
lucha's avatar
lucha committed
245 246 247 248 249 250 251
			 *
			 * @since 2.5.0
			 *
			 * @param string $messages Login messages.
			 */
			echo '<p class="message">' . apply_filters( 'login_messages', $messages ) . "</p>\n";
		}
godog's avatar
godog committed
252 253
	}
} // End of login_header()
root's avatar
root committed
254 255 256 257

/**
 * Outputs the footer for the login page.
 *
samba's avatar
samba committed
258 259 260
 * @since 3.1.0
 *
 * @param string $input_id Which input to auto-focus.
root's avatar
root committed
261
 */
samba's avatar
samba committed
262
function login_footer( $input_id = '' ) {
lechuck's avatar
lechuck committed
263 264 265
	global $interim_login;

	// Don't allow interim logins to navigate away from the page.
samba's avatar
samba committed
266 267 268 269
	if ( ! $interim_login ) :
		?>
	<p id="backtoblog"><a href="<?php echo esc_url( home_url( '/' ) ); ?>">
		<?php
lucha's avatar
lucha committed
270 271
		/* translators: %s: site title */
		printf( _x( '&larr; Back to %s', 'site' ), get_bloginfo( 'title', 'display' ) );
samba's avatar
samba committed
272 273 274
		?>
	</a></p>
		<?php the_privacy_policy_link( '<div class="privacy-policy-page-link">', '</div>' ); ?>
lechuck's avatar
lechuck committed
275
	<?php endif; ?>
root's avatar
root committed
276

lechuck's avatar
lechuck committed
277
	</div>
shammash's avatar
shammash committed
278

samba's avatar
samba committed
279
	<?php if ( ! empty( $input_id ) ) : ?>
lechuck's avatar
lechuck committed
280 281 282 283 284 285
	<script type="text/javascript">
	try{document.getElementById('<?php echo $input_id; ?>').focus();}catch(e){}
	if(typeof wpOnload=='function')wpOnload();
	</script>
	<?php endif; ?>

lucha's avatar
lucha committed
286 287 288 289 290 291
	<?php
	/**
	 * Fires in the login page footer.
	 *
	 * @since 3.1.0
	 */
samba's avatar
samba committed
292 293
	do_action( 'login_footer' );
	?>
lechuck's avatar
lechuck committed
294 295 296 297
	<div class="clear"></div>
	</body>
	</html>
	<?php
root's avatar
root committed
298 299
}

lechuck's avatar
lechuck committed
300
/**
samba's avatar
samba committed
301 302
 * Outputs the Javascript to handle the form shaking.
 *
lechuck's avatar
lechuck committed
303 304
 * @since 3.0.0
 */
godog's avatar
godog committed
305
function wp_shake_js() {
samba's avatar
samba committed
306
	?>
godog's avatar
godog committed
307 308 309 310 311 312 313
<script type="text/javascript">
addLoadEvent = function(func){if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
function s(id,pos){g(id).left=pos+'px';}
function g(id){return document.getElementById(id).style;}
function shake(id,a,d){c=a.shift();s(id,c);if(a.length>0){setTimeout(function(){shake(id,a,d);},d);}else{try{g(id).position='static';wp_attempt_focus();}catch(e){}}}
addLoadEvent(function(){ var p=new Array(15,30,15,0,-15,-30,-15,0);p=p.concat(p.concat(p));var i=document.forms[0].id;g(i).position='relative';shake(i,p,20);});
</script>
samba's avatar
samba committed
314
	<?php
godog's avatar
godog committed
315 316
}

lechuck's avatar
lechuck committed
317
/**
samba's avatar
samba committed
318 319
 * Outputs the viewport meta tag.
 *
lechuck's avatar
lechuck committed
320 321
 * @since 3.7.0
 */
lucha's avatar
lucha committed
322 323 324 325 326 327
function wp_login_viewport_meta() {
	?>
	<meta name="viewport" content="width=device-width" />
	<?php
}

godog's avatar
godog committed
328 329 330
/**
 * Handles sending password retrieval email to user.
 *
samba's avatar
samba committed
331 332
 * @since 2.5.0
 *
godog's avatar
godog committed
333 334 335 336 337
 * @return bool|WP_Error True: when finish. WP_Error on error
 */
function retrieve_password() {
	$errors = new WP_Error();

lucha's avatar
lucha committed
338
	if ( empty( $_POST['user_login'] ) || ! is_string( $_POST['user_login'] ) ) {
samba's avatar
samba committed
339
		$errors->add( 'empty_username', __( '<strong>ERROR</strong>: Enter a username or email address.' ) );
ale's avatar
ale committed
340
	} elseif ( strpos( $_POST['user_login'], '@' ) ) {
lucha's avatar
lucha committed
341
		$user_data = get_user_by( 'email', trim( wp_unslash( $_POST['user_login'] ) ) );
samba's avatar
samba committed
342 343 344
		if ( empty( $user_data ) ) {
			$errors->add( 'invalid_email', __( '<strong>ERROR</strong>: There is no account with that username or email address.' ) );
		}
godog's avatar
godog committed
345
	} else {
samba's avatar
samba committed
346 347
		$login     = trim( $_POST['user_login'] );
		$user_data = get_user_by( 'login', $login );
godog's avatar
godog committed
348 349
	}

lucha's avatar
lucha committed
350 351 352 353
	/**
	 * Fires before errors are returned from a password reset request.
	 *
	 * @since 2.1.0
lechuck's avatar
lechuck committed
354 355 356 357
	 * @since 4.4.0 Added the `$errors` parameter.
	 *
	 * @param WP_Error $errors A WP_Error object containing any errors generated
	 *                         by using invalid credentials.
lucha's avatar
lucha committed
358
	 */
lechuck's avatar
lechuck committed
359
	do_action( 'lostpassword_post', $errors );
godog's avatar
godog committed
360

samba's avatar
samba committed
361
	if ( $errors->has_errors() ) {
godog's avatar
godog committed
362
		return $errors;
samba's avatar
samba committed
363
	}
godog's avatar
godog committed
364

samba's avatar
samba committed
365 366
	if ( ! $user_data ) {
		$errors->add( 'invalidcombo', __( '<strong>ERROR</strong>: There is no account with that username or email address.' ) );
godog's avatar
godog committed
367 368 369
		return $errors;
	}

lucha's avatar
lucha committed
370
	// Redefining user_login ensures we return the right case in the email.
godog's avatar
godog committed
371 372
	$user_login = $user_data->user_login;
	$user_email = $user_data->user_email;
samba's avatar
samba committed
373
	$key        = get_password_reset_key( $user_data );
godog's avatar
godog committed
374

lechuck's avatar
lechuck committed
375 376
	if ( is_wp_error( $key ) ) {
		return $key;
ale's avatar
ale committed
377
	}
godog's avatar
godog committed
378

lucha's avatar
lucha committed
379
	if ( is_multisite() ) {
lucha's avatar
lucha committed
380
		$site_name = get_network()->site_name;
lucha's avatar
lucha committed
381
	} else {
lucha's avatar
lucha committed
382 383 384 385
		/*
		 * The blogname option is escaped with esc_html on the way into the database
		 * in sanitize_option we want to reverse this for the plain text arena of emails.
		 */
lucha's avatar
lucha committed
386
		$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
lucha's avatar
lucha committed
387
	}
godog's avatar
godog committed
388

lucha's avatar
lucha committed
389 390
	$message = __( 'Someone has requested a password reset for the following account:' ) . "\r\n\r\n";
	/* translators: %s: site name */
samba's avatar
samba committed
391
	$message .= sprintf( __( 'Site Name: %s' ), $site_name ) . "\r\n\r\n";
lucha's avatar
lucha committed
392
	/* translators: %s: user login */
samba's avatar
samba committed
393
	$message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
lucha's avatar
lucha committed
394 395 396 397
	$message .= __( 'If this was a mistake, just ignore this email and nothing will happen.' ) . "\r\n\r\n";
	$message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
	$message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . ">\r\n";

agata's avatar
agata committed
398
	/* translators: Password reset notification email subject. %s: Site title */
lucha's avatar
lucha committed
399
	$title = sprintf( __( '[%s] Password Reset' ), $site_name );
godog's avatar
godog committed
400

lucha's avatar
lucha committed
401
	/**
lucha's avatar
lucha committed
402
	 * Filters the subject of the password reset email.
lucha's avatar
lucha committed
403 404
	 *
	 * @since 2.8.0
lechuck's avatar
lechuck committed
405
	 * @since 4.4.0 Added the `$user_login` and `$user_data` parameters.
lucha's avatar
lucha committed
406
	 *
lechuck's avatar
lechuck committed
407 408 409
	 * @param string  $title      Default email title.
	 * @param string  $user_login The username for the user.
	 * @param WP_User $user_data  WP_User object.
lucha's avatar
lucha committed
410
	 */
lechuck's avatar
lechuck committed
411
	$title = apply_filters( 'retrieve_password_title', $title, $user_login, $user_data );
lechuck's avatar
lechuck committed
412

lucha's avatar
lucha committed
413
	/**
lucha's avatar
lucha committed
414
	 * Filters the message body of the password reset mail.
lucha's avatar
lucha committed
415
	 *
lucha's avatar
lucha committed
416 417
	 * If the filtered message is empty, the password reset email will not be sent.
	 *
lucha's avatar
lucha committed
418
	 * @since 2.8.0
lechuck's avatar
lechuck committed
419
	 * @since 4.1.0 Added `$user_login` and `$user_data` parameters.
lucha's avatar
lucha committed
420
	 *
lechuck's avatar
lechuck committed
421 422 423 424
	 * @param string  $message    Default mail message.
	 * @param string  $key        The activation key.
	 * @param string  $user_login The username for the user.
	 * @param WP_User $user_data  WP_User object.
lucha's avatar
lucha committed
425
	 */
lechuck's avatar
lechuck committed
426
	$message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
godog's avatar
godog committed
427

samba's avatar
samba committed
428
	if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
agata's avatar
agata committed
429
		wp_die( __( 'The email could not be sent. Possible reason: your host may have disabled the mail() function.' ) );
samba's avatar
samba committed
430
	}
godog's avatar
godog committed
431 432 433 434 435

	return true;
}

//
samba's avatar
samba committed
436
// Main.
godog's avatar
godog committed
437 438
//

samba's avatar
samba committed
439
$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login';
godog's avatar
godog committed
440 441
$errors = new WP_Error();

samba's avatar
samba committed
442
if ( isset( $_GET['key'] ) ) {
godog's avatar
godog committed
443
	$action = 'resetpass';
samba's avatar
samba committed
444
}
godog's avatar
godog committed
445

samba's avatar
samba committed
446
// Validate action so as to default to the login screen.
agata's avatar
agata committed
447
if ( ! in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login', 'confirmaction', WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED ), true ) && false === has_filter( 'login_form_' . $action ) ) {
godog's avatar
godog committed
448
	$action = 'login';
samba's avatar
samba committed
449
}
godog's avatar
godog committed
450 451 452

nocache_headers();

samba's avatar
samba committed
453
header( 'Content-Type: ' . get_bloginfo( 'html_type' ) . '; charset=' . get_bloginfo( 'charset' ) );
godog's avatar
godog committed
454

lechuck's avatar
lechuck committed
455
if ( defined( 'RELOCATE' ) && RELOCATE ) { // Move flag is set
samba's avatar
samba committed
456
	if ( isset( $_SERVER['PATH_INFO'] ) && ( $_SERVER['PATH_INFO'] != $_SERVER['PHP_SELF'] ) ) {
godog's avatar
godog committed
457
		$_SERVER['PHP_SELF'] = str_replace( $_SERVER['PATH_INFO'], '', $_SERVER['PHP_SELF'] );
samba's avatar
samba committed
458
	}
godog's avatar
godog committed
459

samba's avatar
samba committed
460 461
	$url = dirname( set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] ) );
	if ( $url != get_option( 'siteurl' ) ) {
lechuck's avatar
lechuck committed
462
		update_option( 'siteurl', $url );
samba's avatar
samba committed
463
	}
godog's avatar
godog committed
464 465 466
}

//Set a cookie now to see if they are supported by the browser.
lechuck's avatar
lechuck committed
467
$secure = ( 'https' === parse_url( wp_login_url(), PHP_URL_SCHEME ) );
lucha's avatar
lucha committed
468
setcookie( TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN, $secure );
samba's avatar
samba committed
469
if ( SITECOOKIEPATH != COOKIEPATH ) {
lucha's avatar
lucha committed
470
	setcookie( TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN, $secure );
samba's avatar
samba committed
471
}
godog's avatar
godog committed
472

lucha's avatar
lucha committed
473 474 475 476 477
/**
 * Fires when the login form is initialized.
 *
 * @since 3.2.0
 */
shammash's avatar
shammash committed
478
do_action( 'login_init' );
lucha's avatar
lucha committed
479

lucha's avatar
lucha committed
480 481 482
/**
 * Fires before a specified login form action.
 *
lechuck's avatar
lechuck committed
483
 * The dynamic portion of the hook name, `$action`, refers to the action
lucha's avatar
lucha committed
484 485 486 487 488
 * that brought the visitor to the login form. Actions include 'postpass',
 * 'logout', 'lostpassword', etc.
 *
 * @since 2.8.0
 */
lucha's avatar
lucha committed
489
do_action( "login_form_{$action}" );
godog's avatar
godog committed
490

samba's avatar
samba committed
491 492
$http_post     = ( 'POST' == $_SERVER['REQUEST_METHOD'] );
$interim_login = isset( $_REQUEST['interim-login'] );
lechuck's avatar
lechuck committed
493

lucha's avatar
lucha committed
494 495 496 497 498 499 500 501 502
/**
 * Filters the separator used between login form navigation links.
 *
 * @since 4.9.0
 *
 * @param string $login_link_separator The separator used between login form navigation links.
 */
$login_link_separator = apply_filters( 'login_link_separator', ' | ' );

samba's avatar
samba committed
503
switch ( $action ) {
lechuck's avatar
lechuck committed
504

samba's avatar
samba committed
505 506 507 508 509
	case 'postpass':
		if ( ! array_key_exists( 'post_password', $_POST ) ) {
			wp_safe_redirect( wp_get_referer() );
			exit();
		}
lechuck's avatar
lechuck committed
510

samba's avatar
samba committed
511 512
		require_once ABSPATH . WPINC . '/class-phpass.php';
		$hasher = new PasswordHash( 8, true );
lechuck's avatar
lechuck committed
513

samba's avatar
samba committed
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
		/**
		 * Filters the life span of the post password cookie.
		 *
		 * By default, the cookie expires 10 days from creation. To turn this
		 * into a session cookie, return 0.
		 *
		 * @since 3.7.0
		 *
		 * @param int $expires The expiry time, as passed to setcookie().
		 */
		$expire  = apply_filters( 'post_password_expires', time() + 10 * DAY_IN_SECONDS );
		$referer = wp_get_referer();
		if ( $referer ) {
			$secure = ( 'https' === parse_url( $referer, PHP_URL_SCHEME ) );
		} else {
			$secure = false;
		}
		setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure );
lechuck's avatar
lechuck committed
532

samba's avatar
samba committed
533 534
		wp_safe_redirect( wp_get_referer() );
		exit();
ale's avatar
ale committed
535

samba's avatar
samba committed
536 537
	case 'logout':
		check_admin_referer( 'log-out' );
ale's avatar
ale committed
538

samba's avatar
samba committed
539
		$user = wp_get_current_user();
godog's avatar
godog committed
540

samba's avatar
samba committed
541
		wp_logout();
ale's avatar
ale committed
542

samba's avatar
samba committed
543 544 545 546 547 548
		if ( ! empty( $_REQUEST['redirect_to'] ) ) {
			$redirect_to = $requested_redirect_to = $_REQUEST['redirect_to'];
		} else {
			$redirect_to           = 'wp-login.php?loggedout=true';
			$requested_redirect_to = '';
		}
godog's avatar
godog committed
549

samba's avatar
samba committed
550 551 552 553 554 555 556 557 558 559 560 561
		/**
		 * Filters the log out redirect URL.
		 *
		 * @since 4.2.0
		 *
		 * @param string  $redirect_to           The redirect destination URL.
		 * @param string  $requested_redirect_to The requested redirect destination URL passed as a parameter.
		 * @param WP_User $user                  The WP_User object for the user that's logging out.
		 */
		$redirect_to = apply_filters( 'logout_redirect', $redirect_to, $requested_redirect_to, $user );
		wp_safe_redirect( $redirect_to );
		exit();
root's avatar
root committed
562

samba's avatar
samba committed
563 564 565 566 567 568 569 570 571
	case 'lostpassword':
	case 'retrievepassword':
		if ( $http_post ) {
			$errors = retrieve_password();
			if ( ! is_wp_error( $errors ) ) {
				$redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : 'wp-login.php?checkemail=confirm';
				wp_safe_redirect( $redirect_to );
				exit();
			}
godog's avatar
godog committed
572 573
		}

samba's avatar
samba committed
574 575 576 577 578 579
		if ( isset( $_GET['error'] ) ) {
			if ( 'invalidkey' == $_GET['error'] ) {
				$errors->add( 'invalidkey', __( 'Your password reset link appears to be invalid. Please request a new link below.' ) );
			} elseif ( 'expiredkey' == $_GET['error'] ) {
				$errors->add( 'expiredkey', __( 'Your password reset link has expired. Please request a new link below.' ) );
			}
lechuck's avatar
lechuck committed
580
		}
lucha's avatar
lucha committed
581

samba's avatar
samba committed
582 583 584 585 586 587 588 589 590
		$lostpassword_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
		/**
		 * Filters the URL redirected to after submitting the lostpassword/retrievepassword form.
		 *
		 * @since 3.0.0
		 *
		 * @param string $lostpassword_redirect The redirect destination URL.
		 */
		$redirect_to = apply_filters( 'lostpassword_redirect', $lostpassword_redirect );
lucha's avatar
lucha committed
591

samba's avatar
samba committed
592 593 594 595 596 597 598 599 600 601
		/**
		 * Fires before the lost password form.
		 *
		 * @since 1.5.1
		 * @since 5.1.0 Added the `$errors` parameter.
		 *
		 * @param WP_Error $errors A `WP_Error` object containing any errors generated by using invalid
		 *                         credentials. Note that the error object may not contain any errors.
		 */
		do_action( 'lost_password', $errors );
godog's avatar
godog committed
602

samba's avatar
samba committed
603
		login_header( __( 'Lost Password' ), '<p class="message">' . __( 'Please enter your username or email address. You will receive a link to create a new password via email.' ) . '</p>', $errors );
godog's avatar
godog committed
604

samba's avatar
samba committed
605
		$user_login = '';
lucha's avatar
lucha committed
606

samba's avatar
samba committed
607 608 609
		if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) {
			$user_login = wp_unslash( $_POST['user_login'] );
		}
godog's avatar
godog committed
610

samba's avatar
samba committed
611
		?>
godog's avatar
godog committed
612

samba's avatar
samba committed
613
	<form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post">
godog's avatar
godog committed
614
	<p>
lucha's avatar
lucha committed
615
		<label for="user_login" ><?php _e( 'Username or Email Address' ); ?><br />
samba's avatar
samba committed
616
		<input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" /></label>
godog's avatar
godog committed
617
	</p>
samba's avatar
samba committed
618 619 620 621 622 623 624 625 626 627 628
		<?php
		/**
		 * Fires inside the lostpassword form tags, before the hidden fields.
		 *
		 * @since 2.1.0
		 */
		do_action( 'lostpassword_form' );
		?>
		<input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
		<p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" /></p>
	</form>
godog's avatar
godog committed
629

samba's avatar
samba committed
630 631 632 633 634
	<p id="nav">
	<a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
		<?php
		if ( get_option( 'users_can_register' ) ) :
			$registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
lucha's avatar
lucha committed
635

samba's avatar
samba committed
636
			echo esc_html( $login_link_separator );
lucha's avatar
lucha committed
637

samba's avatar
samba committed
638 639 640 641 642
			/** This filter is documented in wp-includes/general-template.php */
			echo apply_filters( 'register', $registration_url );
	endif;
		?>
	</p>
godog's avatar
godog committed
643

samba's avatar
samba committed
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
		<?php
		login_footer( 'user_login' );

		break;

	case 'resetpass':
	case 'rp':
		list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) );
		$rp_cookie       = 'wp-resetpass-' . COOKIEHASH;
		if ( isset( $_GET['key'] ) ) {
			$value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
			setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
			wp_safe_redirect( remove_query_arg( array( 'key', 'login' ) ) );
			exit;
		}
lechuck's avatar
lechuck committed
659

samba's avatar
samba committed
660 661 662 663 664 665 666
		if ( isset( $_COOKIE[ $rp_cookie ] ) && 0 < strpos( $_COOKIE[ $rp_cookie ], ':' ) ) {
			list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 );
			$user                      = check_password_reset_key( $rp_key, $rp_login );
			if ( isset( $_POST['pass1'] ) && ! hash_equals( $rp_key, $_POST['rp_key'] ) ) {
				$user = false;
			}
		} else {
lechuck's avatar
lechuck committed
667 668
			$user = false;
		}
godog's avatar
godog committed
669

samba's avatar
samba committed
670 671 672 673 674 675 676 677 678
		if ( ! $user || is_wp_error( $user ) ) {
			setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
			if ( $user && $user->get_error_code() === 'expired_key' ) {
				wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=expiredkey' ) );
			} else {
				wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=invalidkey' ) );
			}
			exit;
		}
lechuck's avatar
lechuck committed
679

samba's avatar
samba committed
680
		$errors = new WP_Error();
lechuck's avatar
lechuck committed
681

samba's avatar
samba committed
682 683 684
		if ( isset( $_POST['pass1'] ) && $_POST['pass1'] != $_POST['pass2'] ) {
			$errors->add( 'password_reset_mismatch', __( 'The passwords do not match.' ) );
		}
root's avatar
root committed
685

samba's avatar
samba committed
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
		/**
		 * Fires before the password reset procedure is validated.
		 *
		 * @since 3.5.0
		 *
		 * @param object           $errors WP Error object.
		 * @param WP_User|WP_Error $user   WP_User object if the login and reset key match. WP_Error object otherwise.
		 */
		do_action( 'validate_password_reset', $errors, $user );

		if ( ( ! $errors->has_errors() ) && isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) {
			reset_password( $user, $_POST['pass1'] );
			setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
			login_header( __( 'Password Reset' ), '<p class="message reset-pass">' . __( 'Your password has been reset.' ) . ' <a href="' . esc_url( wp_login_url() ) . '">' . __( 'Log in' ) . '</a></p>' );
			login_footer();
			exit;
		}
godog's avatar
godog committed
703

samba's avatar
samba committed
704 705
		wp_enqueue_script( 'utils' );
		wp_enqueue_script( 'user-profile' );
root's avatar
root committed
706

samba's avatar
samba committed
707
		login_header( __( 'Reset Password' ), '<p class="message reset-pass">' . __( 'Enter your new password below.' ) . '</p>', $errors );
root's avatar
root committed
708

samba's avatar
samba committed
709 710
		?>
	<form name="resetpassform" id="resetpassform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=resetpass', 'login_post' ) ); ?>" method="post" autocomplete="off">
lechuck's avatar
lechuck committed
711
	<input type="hidden" id="user_login" value="<?php echo esc_attr( $rp_login ); ?>" autocomplete="off" />
root's avatar
root committed
712

lechuck's avatar
lechuck committed
713 714
	<div class="user-pass1-wrap">
		<p>
samba's avatar
samba committed
715
			<label for="pass1"><?php _e( 'New password' ); ?></label>
lechuck's avatar
lechuck committed
716 717
		</p>

lechuck's avatar
lechuck committed
718
		<div class="wp-pwd">
lucha's avatar
lucha committed
719 720
			<div class="password-input-wrapper">
				<input type="password" data-reveal="1" data-pw="<?php echo esc_attr( wp_generate_password( 16 ) ); ?>" name="pass1" id="pass1" class="input password-input" size="24" value="" autocomplete="off" aria-describedby="pass-strength-result" />
agata's avatar
agata committed
721 722 723
				<button type="button" class="button button-secondary wp-hide-pw hide-if-no-js">
					<span class="dashicons dashicons-hidden" aria-hidden="true"></span>
				</button>
lucha's avatar
lucha committed
724
			</div>
lechuck's avatar
lechuck committed
725 726
			<div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator' ); ?></div>
		</div>
lucha's avatar
lucha committed
727 728 729 730 731 732
		<div class="pw-weak">
			<label>
				<input type="checkbox" name="pw_weak" class="pw-checkbox" />
				<?php _e( 'Confirm use of weak password' ); ?>
			</label>
		</div>
lechuck's avatar
lechuck committed
733 734
	</div>

lechuck's avatar
lechuck committed
735
	<p class="user-pass2-wrap">
samba's avatar
samba committed
736
		<label for="pass2"><?php _e( 'Confirm new password' ); ?></label><br />
lechuck's avatar
lechuck committed
737
		<input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
root's avatar
root committed
738 739
	</p>

lechuck's avatar
lechuck committed
740
	<p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p>
root's avatar
root committed
741
	<br class="clear" />
lechuck's avatar
lechuck committed
742

samba's avatar
samba committed
743 744 745 746 747 748 749 750 751 752
		<?php
		/**
		 * Fires following the 'Strength indicator' meter in the user password reset form.
		 *
		 * @since 3.9.0
		 *
		 * @param WP_User $user User object of the user whose password is being reset.
		 */
		do_action( 'resetpass_form', $user );
		?>
lechuck's avatar
lechuck committed
753
	<input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" />
samba's avatar
samba committed
754 755
	<p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Reset Password' ); ?>" /></p>
	</form>
root's avatar
root committed
756

samba's avatar
samba committed
757 758 759 760 761
	<p id="nav">
	<a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
		<?php
		if ( get_option( 'users_can_register' ) ) :
			$registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
lucha's avatar
lucha committed
762

samba's avatar
samba committed
763
			echo esc_html( $login_link_separator );
lucha's avatar
lucha committed
764

samba's avatar
samba committed
765 766 767 768 769
			/** This filter is documented in wp-includes/general-template.php */
			echo apply_filters( 'register', $registration_url );
	endif;
		?>
	</p>
root's avatar
root committed
770

samba's avatar
samba committed
771 772
		<?php
		login_footer( 'user_pass' );
lucha's avatar
lucha committed
773

samba's avatar
samba committed
774
		break;
godog's avatar
godog committed
775

samba's avatar
samba committed
776 777 778 779 780 781 782 783 784 785 786 787
	case 'register':
		if ( is_multisite() ) {
			/**
			 * Filters the Multisite sign up URL.
			 *
			 * @since 3.0.0
			 *
			 * @param string $sign_up_url The sign up URL.
			 */
			wp_redirect( apply_filters( 'wp_signup_location', network_site_url( 'wp-signup.php' ) ) );
			exit;
		}
godog's avatar
godog committed
788

samba's avatar
samba committed
789 790 791 792
		if ( ! get_option( 'users_can_register' ) ) {
			wp_redirect( site_url( 'wp-login.php?registration=disabled' ) );
			exit();
		}
godog's avatar
godog committed
793

samba's avatar
samba committed
794 795
		$user_login = '';
		$user_email = '';
lucha's avatar
lucha committed
796

samba's avatar
samba committed
797 798 799 800
		if ( $http_post ) {
			if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) {
				$user_login = $_POST['user_login'];
			}
lucha's avatar
lucha committed
801

samba's avatar
samba committed
802 803 804
			if ( isset( $_POST['user_email'] ) && is_string( $_POST['user_email'] ) ) {
				$user_email = wp_unslash( $_POST['user_email'] );
			}
lucha's avatar
lucha committed
805

samba's avatar
samba committed
806 807 808 809 810 811
			$errors = register_new_user( $user_login, $user_email );
			if ( ! is_wp_error( $errors ) ) {
				$redirect_to = ! empty( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : 'wp-login.php?checkemail=registered';
				wp_safe_redirect( $redirect_to );
				exit();
			}
godog's avatar
godog committed
812 813
		}

samba's avatar
samba committed
814 815 816 817 818 819 820 821 822 823 824 825
		$registration_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
		/**
		 * Filters the registration redirect URL.
		 *
		 * @since 3.0.0
		 *
		 * @param string $registration_redirect The redirect destination URL.
		 */
		$redirect_to = apply_filters( 'registration_redirect', $registration_redirect );
		login_header( __( 'Registration Form' ), '<p class="message register">' . __( 'Register For This Site' ) . '</p>', $errors );
		?>
	<form name="registerform" id="registerform" action="<?php echo esc_url( site_url( 'wp-login.php?action=register', 'login_post' ) ); ?>" method="post" novalidate="novalidate">
godog's avatar
godog committed
826
	<p>
samba's avatar
samba committed
827 828
		<label for="user_login"><?php _e( 'Username' ); ?><br />
		<input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( wp_unslash( $user_login ) ); ?>" size="20" autocapitalize="off" /></label>
godog's avatar
godog committed
829 830
	</p>
	<p>
samba's avatar
samba committed
831
		<label for="user_email"><?php _e( 'Email' ); ?><br />
lucha's avatar
lucha committed
832
		<input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( wp_unslash( $user_email ) ); ?>" size="25" /></label>
godog's avatar
godog committed
833
	</p>
samba's avatar
samba committed
834 835 836 837 838 839 840 841
		<?php
		/**
		 * Fires following the 'Email' field in the user registration form.
		 *
		 * @since 2.1.0
		 */
		do_action( 'register_form' );
		?>
lechuck's avatar
lechuck committed
842
	<p id="reg_passmail"><?php _e( 'Registration confirmation will be emailed to you.' ); ?></p>
godog's avatar
godog committed
843 844
	<br class="clear" />
	<input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
samba's avatar
samba committed
845 846
	<p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Register' ); ?>" /></p>
	</form>
godog's avatar
godog committed
847

samba's avatar
samba committed
848 849 850 851 852
	<p id="nav">
	<a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
		<?php echo esc_html( $login_link_separator ); ?>
	<a href="<?php echo esc_url( wp_lostpassword_url() ); ?>"><?php _e( 'Lost your password?' ); ?></a>
	</p>
godog's avatar
godog committed
853

samba's avatar
samba committed
854 855
		<?php
		login_footer( 'user_login' );
kiki's avatar
kiki committed
856

samba's avatar
samba committed
857
		break;
kiki's avatar
kiki committed
858

samba's avatar
samba committed
859 860
	case 'confirmaction':
		if ( ! isset( $_GET['request_id'] ) ) {
agata's avatar
agata committed
861
			wp_die( __( 'Missing request ID.' ) );
samba's avatar
samba committed
862
		}
kiki's avatar
kiki committed
863

agata's avatar
agata committed
864 865
		if ( ! isset( $_GET['confirm_key'] ) ) {
			wp_die( __( 'Missing confirm key.' ) );
samba's avatar
samba committed
866
		}
kiki's avatar
kiki committed
867

agata's avatar
agata committed
868 869 870 871
		$request_id = (int) $_GET['request_id'];
		$key        = sanitize_text_field( wp_unslash( $_GET['confirm_key'] ) );
		$result     = wp_validate_user_request_key( $request_id, $key );

samba's avatar
samba committed
872 873 874
		if ( is_wp_error( $result ) ) {
			wp_die( $result );
		}
kiki's avatar
kiki committed
875

samba's avatar
samba committed
876 877 878 879 880 881 882 883 884 885 886 887 888 889
		/**
		 * Fires an action hook when the account action has been confirmed by the user.
		 *
		 * Using this you can assume the user has agreed to perform the action by
		 * clicking on the link in the confirmation email.
		 *
		 * After firing this action hook the page will redirect to wp-login a callback
		 * redirects or exits first.
		 *
		 * @since 4.9.6
		 *
		 * @param int $request_id Request ID.
		 */
		do_action( 'user_request_action_confirmed', $request_id );
godog's avatar
godog committed
890

samba's avatar
samba committed
891
		$message = _wp_privacy_account_request_confirmed_message( $request_id );
lechuck's avatar
lechuck committed
892

samba's avatar
samba committed
893 894 895
		login_header( __( 'User action confirmed.' ), $message );
		login_footer();
		exit;
lechuck's avatar
lechuck committed
896

samba's avatar
samba committed
897 898 899 900 901 902
	case 'login':
	default:
		$secure_cookie   = '';
		$customize_login = isset( $_REQUEST['customize-login'] );
		if ( $customize_login ) {
			wp_enqueue_script( 'customize-base' );
godog's avatar
godog committed
903 904
		}

samba's avatar
samba committed
905 906 907 908
		// If the user wants SSL but the session is not SSL, force a secure cookie.
		if ( ! empty( $_POST['log'] ) && ! force_ssl_admin() ) {
			$user_name = sanitize_user( $_POST['log'] );
			$user      = get_user_by( 'login', $user_name );
godog's avatar
godog committed
909

samba's avatar
samba committed
910 911 912
			if ( ! $user && strpos( $user_name, '@' ) ) {
				$user = get_user_by( 'email', $user_name );
			}
godog's avatar
godog committed
913

samba's avatar
samba committed
914 915 916 917 918 919 920
			if ( $user ) {
				if ( get_user_option( 'use_ssl', $user->ID ) ) {
					$secure_cookie = true;
					force_ssl_admin( true );
				}
			}
		}
lechuck's avatar
lechuck committed
921

samba's avatar
samba committed
922 923 924 925 926 927 928 929
		if ( isset( $_REQUEST['redirect_to'] ) ) {
			$redirect_to = $_REQUEST['redirect_to'];
			// Redirect to HTTPS if user wants SSL.
			if ( $secure_cookie && false !== strpos( $redirect_to, 'wp-admin' ) ) {
				$redirect_to = preg_replace( '|^http://|', 'https://', $redirect_to );
			}
		} else {
			$redirect_to = admin_url();
lechuck's avatar
lechuck committed
930
		}
lucha's avatar
lucha committed
931

samba's avatar
samba committed
932 933 934 935 936 937 938 939 940 941 942
		$reauth = empty( $_REQUEST['reauth'] ) ? false : true;

		$user = wp_signon( array(), $secure_cookie );

		if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) {
			if ( headers_sent() ) {
				$user = new WP_Error(
					'test_cookie',
					sprintf(
						/* translators: 1: Browser cookie documentation URL, 2: Support forums URL */
						__( '<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>.' ),
agata's avatar
agata committed
943
						__( 'https://wordpress.org/support/article/cookies/' ),
samba's avatar
samba committed
944 945 946 947 948 949 950 951 952 953
						__( 'https://wordpress.org/support/' )
					)
				);
			} elseif ( isset( $_POST['testcookie'] ) && empty( $_COOKIE[ TEST_COOKIE ] ) ) {
				// If cookies are disabled we can't log in even with a valid user+pass
				$user = new WP_Error(
					'test_cookie',
					sprintf(
						/* translators: %s: Browser cookie documentation URL */
						__( '<strong>ERROR</strong>: Cookies are blocked or not supported by your browser. You must <a href="%s">enable cookies</a> to use WordPress.' ),
agata's avatar
agata committed
954
						__( 'https://wordpress.org/support/article/cookies/#enable-cookies-in-your-browser' )
samba's avatar
samba committed
955 956 957 958
					)
				);
			}
		}
godog's avatar
godog committed
959

samba's avatar
samba committed
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
		$requested_redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
		/**
		 * Filters the login redirect URL.
		 *
		 * @since 3.0.0
		 *
		 * @param string           $redirect_to           The redirect destination URL.
		 * @param string           $requested_redirect_to The requested redirect destination URL passed as a parameter.
		 * @param WP_User|WP_Error $user                  WP_User object if login was successful, WP_Error object otherwise.
		 */
		$redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $user );

		if ( ! is_wp_error( $user ) && ! $reauth ) {
			if ( $interim_login ) {
				$message       = '<p class="message">' . __( 'You have logged in successfully.' ) . '</p>';
				$interim_login = 'success';
				login_header( '', $message );
				?>
				</div>
				<?php
				/** This action is documented in wp-login.php */
				do_action( 'login_footer' );
				?>
				<?php if ( $customize_login ) : ?>
lechuck's avatar
lechuck committed
984
				<script type="text/javascript">setTimeout( function(){ new wp.customize.Messenger({ url: '<?php echo wp_customize_url(); ?>', channel: 'login' }).send('login') }, 1000 );</script>
lechuck's avatar
lechuck committed
985
			<?php endif; ?>
samba's avatar
samba committed
986 987 988 989
				</body></html>
				<?php
				exit;
			}
lechuck's avatar
lechuck committed
990

samba's avatar
samba committed
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
			if ( ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' || $redirect_to == admin_url() ) ) {
				// 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.
				if ( is_multisite() && ! get_active_blog_for_user( $user->ID ) && ! is_super_admin( $user->ID ) ) {
					$redirect_to = user_admin_url();
				} elseif ( is_multisite() && ! $user->has_cap( 'read' ) ) {
					$redirect_to = get_dashboard_url( $user->ID );
				} elseif ( ! $user->has_cap( 'edit_posts' ) ) {
					$redirect_to = $user->has_cap( 'read' ) ? admin_url( 'profile.php' ) : home_url();
				}

				wp_redirect( $redirect_to );
				exit();
			}
			wp_safe_redirect( $redirect_to );
lechuck's avatar
lechuck committed
1005
			exit();
root's avatar
root committed
1006
		}
godog's avatar
godog committed
1007

samba's avatar
samba committed
1008 1009 1010 1011 1012
		$errors = $user;
		// Clear errors if loggedout is set.
		if ( ! empty( $_GET['loggedout'] ) || $reauth ) {
			$errors = new WP_Error();
		}
godog's avatar
godog committed
1013

agata's avatar
agata committed
1014 1015 1016 1017
		if ( empty( $_POST ) && $errors->get_error_codes() === array( 'empty_username', 'empty_password' ) ) {
			$errors = new WP_Error( '', '' );
		}

samba's avatar
samba committed
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
		if ( $interim_login ) {
			if ( ! $errors->has_errors() ) {
				$errors->add( 'expired', __( 'Your session has expired. Please log in to continue where you left off.' ), 'message' );
			}
		} else {
			// Some parts of this script use the main login form to display a message.