PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
← All changes | src/view/two-fa/otp.php +412 -344 3.0.1 → 6.3.0 View file →
@@ -1,240 +1,254 @@
1 1 <?php
2 -if ( ! function_exists( 'login_header_otp' ) ) {
3 -//copy from wp-login
4 2 /**
5 - * Output the login page header.
3 + * This template is used to display 2FA OTP field.
6 4 *
7 - * @param string $title Optional. WordPress login Page title to display in the `<title>` element.
8 - * Default 'Log In'.
9 - * @param string $message Optional. Message to display in header. Default empty.
10 - * @param WP_Error $wp_error Optional. The error to pass. Default empty.
5 + * @package WP_Defender
11 6 */
12 -function login_header_otp( $title = 'Log In', $message = '', $wp_error = '' ) {
13 -global $error, $interim_login, $action;
14 7
15 -if ( empty( $wp_error ) ) {
16 - $wp_error = new \WP_Error();
17 -}
8 +if ( ! function_exists( 'login_header_otp' ) ) {
9 + // Copy from wp-login.php.
10 + /**
11 + * Output the login page header.
12 + *
13 + * @param string $title Optional. WordPress login Page title to display in the `<title>` element. Default 'Log In'.
14 + * @param string $message Optional. Message to display in header. Default empty.
15 + * @param bool $show_logo Optional. Show/hide header logo. Default true.
16 + * @param WP_Error $wp_error Optional. The error to pass. Default empty.
17 + */
18 + function login_header_otp( $title = 'Log In', $message = '', $show_logo = true, $wp_error = '' ) {
19 + global $error, $interim_login, $action;
18 20
19 -// Shake it!
20 -$shake_error_codes = array(
21 - 'empty_password',
22 - 'empty_email',
23 - 'invalid_email',
24 - 'invalidcombo',
25 - 'empty_username',
26 - 'invalid_username',
27 - 'incorrect_password',
28 -);
29 -/**
30 - * Filters the error codes array for shaking the login form.
31 - *
32 - * @param array $shake_error_codes Error codes that shake the login form.
33 - *
34 - * @since 3.0.0
35 - *
36 - */
37 -$shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );
21 + if ( ! ( $wp_error instanceof WP_Error ) ) {
22 + $wp_error = new WP_Error();
23 + }
38 24
39 -if ( $shake_error_codes && $wp_error->get_error_code() && in_array( $wp_error->get_error_code(),
40 - $shake_error_codes ) ) {
41 - add_action( 'login_head', 'wp_shake_js', 12 );
42 -}
25 + // Shake it!
26 + $shake_error_codes = array(
27 + 'empty_password',
28 + 'empty_email',
29 + 'invalid_email',
30 + 'invalidcombo',
31 + 'empty_username',
32 + 'invalid_username',
33 + 'incorrect_password',
34 + );
35 + /**
36 + * Filters the error codes array for shaking the login form.
37 + *
38 + * @param array $shake_error_codes Error codes that shake the login form.
39 + *
40 + * @since 3.0.0
41 + */
42 + $shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );
43 + if ( $shake_error_codes && $wp_error->get_error_code() && in_array(
44 + $wp_error->get_error_code(),
45 + $shake_error_codes,
46 + true
47 + ) ) {
48 + add_action( 'login_head', 'wp_shake_js', 12 );
49 + }
43 50
44 -$separator = is_rtl() ? ' &rsaquo; ' : ' &lsaquo; ';
51 + $separator = is_rtl() ? ' &rsaquo; ' : ' &lsaquo; ';
45 52
46 -?><!DOCTYPE html>
53 + ?><!DOCTYPE html>
47 54 <!--[if IE 8]>
48 -<html xmlns="http://www.w3.org/1999/xhtml" class="ie8" <?php
49 -language_attributes(); ?>>
55 +<html xmlns="http://www.w3.org/1999/xhtml" class="ie8"
56 + <?php
57 + language_attributes();
58 + ?>
59 +>
50 60 <![endif]-->
51 61 <!--[if !(IE 8) ]><!-->
52 62 <html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
53 63 <!--<![endif]-->
64 +
54 65 <head>
55 - <meta http-equiv="Content-Type"
56 - content="<?php
57 - bloginfo( 'html_type' ); ?>; charset=<?php
58 - bloginfo( 'charset' ); ?>"/>
59 - <title><?php
60 - echo get_bloginfo( 'name', 'display' ) . $separator . $title; ?></title>
61 - <?php
66 + <meta http-equiv="Content-Type"
67 + content="<?php bloginfo( 'html_type' ); ?>; charset=<?php bloginfo( 'charset' ); ?>"/>
68 + <meta name="viewport" content="width=device-width">
69 + <title>
70 + <?php
71 + printf( '%s%s%s', esc_attr( get_bloginfo( 'name', 'display' ) ), esc_attr( $separator ), esc_attr( $title ) );
72 + ?>
73 + </title>
74 + <?php
62 75
63 - wp_enqueue_style( 'login' );
76 + wp_enqueue_style( 'login' );
64 77
65 - /*
66 - * Remove all stored post data on logging out.
67 - * This could be added by add_action('login_head'...) like wp_shake_js(),
68 - * but maybe better if it's not removable by plugins.
69 - */
70 - if ( 'loggedout' == $wp_error->get_error_code() ) {
71 - ?>
72 - <script>if ("sessionStorage" in window) {
73 - try {
74 - for (var key in sessionStorage) {
75 - if (key.indexOf("wp-autosave-") != -1) {
76 - sessionStorage.removeItem(key)
77 - }
78 - }
79 - } catch (e) {
80 - }
81 - }
82 - ;</script>
83 - <?php
84 - }
78 + /*
79 + * Remove all stored post data on logging out.
80 + * This could be added by add_action('login_head'...) like wp_shake_js(),
81 + * but maybe better if it's not removable by plugins.
82 + */
83 + if ( 'loggedout' === $wp_error->get_error_code() ) {
84 + ?>
85 + <script>if ("sessionStorage" in window) {
86 + try {
87 + for (var key in sessionStorage) {
88 + if (key.indexOf("wp-autosave-") != -1) {
89 + sessionStorage.removeItem(key)
90 + }
91 + }
92 + } catch (e) {
93 + }
94 + }
95 + </script>
96 + <?php
97 + }
85 98
86 - /**
87 - * Enqueue scripts and styles for the login page.
88 - *
89 - * @since 3.1.0
90 - */
91 - do_action( 'login_enqueue_scripts' );
99 + /**
100 + * Enqueue scripts and styles for the login page.
101 + *
102 + * @since 3.1.0
103 + */
104 + do_action( 'login_enqueue_scripts' );
92 105
93 - /**
94 - * Fires in the login page header after scripts are enqueued.
95 - *
96 - * @since 2.1.0
97 - */
98 - do_action( 'login_head' );
106 + /**
107 + * Fires in the login page header after scripts are enqueued.
108 + *
109 + * @since 2.1.0
110 + */
111 + do_action( 'login_head' );
99 112
100 - if ( is_multisite() ) {
101 - $login_header_url = network_home_url();
102 - $login_header_title = get_network()->site_name;
103 - } else {
104 - $login_header_url = __( 'https://wordpress.org/' );
105 - $login_header_title = __( 'Powered by WordPress' );
106 - }
113 + if ( is_multisite() ) {
114 + $login_header_url = network_home_url();
115 + $login_header_title = get_network()->site_name;
116 + } else {
117 + $login_header_url = 'https://wordpress.org/';
118 + $login_header_title = esc_html__( 'Powered by WordPress', 'defender-security' );
119 + }
107 120
108 - /**
109 - * Filters link URL of the header logo above login form.
110 - *
111 - * @param string $login_header_url Login header logo URL.
112 - *
113 - * @since 2.1.0
114 - *
115 - */
116 - $login_header_url = apply_filters( 'login_headerurl', $login_header_url );
121 + /**
122 + * Filters link URL of the header logo above login form.
123 + *
124 + * @param string $login_header_url Login header logo URL.
125 + *
126 + * @since 2.1.0
127 + */
128 + $login_header_url = apply_filters( 'login_headerurl', $login_header_url );
117 129
118 - /**
119 - * Filters the title attribute of the header logo above login form.
120 - *
121 - * @param string $login_header_title Login header logo title attribute.
122 - *
123 - * @since 2.1.0
124 - */
125 - $login_header_title = apply_filters( 'login_headertitle', $login_header_title );
130 + /**
131 + * Filters the title attribute of the header logo above login form.
132 + *
133 + * @param string $login_header_title Login header logo title attribute.
134 + *
135 + * @since 2.1.0
136 + */
137 + $login_header_title = apply_filters( 'login_headertitle', $login_header_title );
126 138
127 - $classes = array( 'login-action-' . $action, 'wp-core-ui' );
128 - if ( is_rtl() ) {
129 - $classes[] = 'rtl';
130 - }
131 - if ( $interim_login ) {
132 - $classes[] = 'interim-login';
133 - ?>
134 - <style type="text/css">html {
135 - background-color: transparent;
136 - }</style>
137 - <?php
139 + $classes = array( 'login-action-' . $action, 'wp-core-ui' );
140 + if ( is_rtl() ) {
141 + $classes[] = 'rtl';
142 + }
143 + if ( $interim_login ) {
144 + $classes[] = 'interim-login';
145 + ?>
146 + <style type="text/css">
147 + html {
148 + background-color: transparent;
149 + }
150 + </style>
151 + <?php
138 152
139 - if ( 'success' === $interim_login ) {
140 - $classes[] = 'interim-login-success';
153 + if ( 'success' === $interim_login ) {
154 + $classes[] = 'interim-login-success';
155 + }
141 156 }
142 - }
143 - $classes[] = ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) );
157 + $classes[] = ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) );
144 158
145 - /**
146 - * Filters the login page body classes.
147 - *
148 - * @param array $classes An array of body classes.
149 - * @param string $action The action that brought the visitor to the login page.
150 - *
151 - * @since 3.5.0
152 - */
153 - $classes = apply_filters( 'login_body_class', $classes, $action );
159 + /**
160 + * Filters the login page body classes.
161 + *
162 + * @param array $classes An array of body classes.
163 + * @param string $action The action that brought the visitor to the login page.
164 + *
165 + * @since 3.5.0
166 + */
167 + $classes = apply_filters( 'login_body_class', $classes, $action );
154 168
155 - ?>
169 + ?>
156 170 </head>
157 -<body class="login <?php
158 -echo esc_attr( implode( ' ', $classes ) ); ?>">
159 -<?php
160 -/**
161 - * Fires in the login page header after the body tag is opened.
162 - *
163 - * @since 4.6.0
164 - */
165 -do_action( 'login_header' );
166 -?>
171 +
172 +<body class="login <?php echo esc_attr( implode( ' ', $classes ) ); ?>">
173 + <?php
174 + /**
175 + * Fires in the login page header after the body tag is opened.
176 + *
177 + * @since 4.6.0
178 + */
179 + do_action( 'login_header' );
180 + ?>
167 181 <div id="login">
182 + <?php if ( true === $show_logo ) { ?>
183 + <h1>
184 + <a id="otp-logo" href="<?php echo esc_url( $login_header_url ); ?>"
185 + title="<?php echo esc_attr( $login_header_title ); ?>" tabindex="-1"><?php bloginfo( 'name' ); ?></a>
186 + </h1>
187 + <div id="notification"></div>
188 + <?php
189 + }
190 + unset( $login_header_url, $login_header_title );
191 + /**
192 + * Filters the message to display above the login form.
193 + *
194 + * @param string $message Login message text.
195 + *
196 + * @since 2.1.0
197 + */
198 + $message = apply_filters( 'login_message', $message );
199 + if ( is_string( $message ) && '' !== trim( $message ) ) {
200 + echo wp_kses_post( $message );
201 + }
168 202
169 - <h1><a id="otp-logo" href="<?php
170 - echo esc_url( $login_header_url ); ?>" title="<?php
171 - echo esc_attr( $login_header_title ); ?>"
172 - tabindex="-1"><?php
173 - bloginfo( 'name' ); ?></a></h1>
174 - <?php
175 - unset( $login_header_url, $login_header_title );
176 - /**
177 - * Filters the message to display above the login form.
178 - *
179 - * @param string $message Login message text.
180 - *
181 - * @since 2.1.0
182 - */
183 - $message = apply_filters( 'login_message', $message );
184 - if ( ! empty( $message ) ) {
185 - echo $message . "\n";
186 - }
203 + // In case a plugin uses $error rather than the $wp_errors object.
204 + if ( $error instanceof WP_Error ) {
205 + $wp_error->add( 'error', $error );
206 + unset( $error );
207 + }
187 208
188 - // In case a plugin uses $error rather than the $wp_errors object
189 - if ( ! empty( $error ) ) {
190 - $wp_error->add( 'error', $error );
191 - unset( $error );
192 - }
193 -
194 - if ( $wp_error->get_error_code() ) {
195 - $errors = '';
196 - $messages = '';
197 - foreach ( $wp_error->get_error_codes() as $code ) {
198 - $severity = $wp_error->get_error_data( $code );
199 - foreach ( $wp_error->get_error_messages( $code ) as $error_message ) {
200 - if ( 'message' == $severity ) {
201 - $messages .= ' ' . $error_message . "<br />\n";
202 - } else {
203 - $errors .= ' ' . $error_message . "<br />\n";
209 + if ( $wp_error->get_error_code() ) {
210 + $errors = '';
211 + $messages = '';
212 + foreach ( $wp_error->get_error_codes() as $code ) {
213 + $severity = $wp_error->get_error_data( $code );
214 + foreach ( $wp_error->get_error_messages( $code ) as $error_message ) {
215 + if ( 'message' === $severity ) {
216 + $messages .= ' ' . $error_message . "<br />\n";
217 + } else {
218 + $errors .= ' ' . $error_message . "<br />\n";
219 + }
204 220 }
205 221 }
222 + if ( '' !== $errors ) {
223 + /**
224 + * Filters the error messages displayed above the login form.
225 + *
226 + * @param string $errors Login error message.
227 + *
228 + * @since 2.1.0
229 + */
230 + echo wp_kses_post( sprintf( '<div id="login_error" class="notice notice-error">%s</div>', apply_filters( 'login_errors', $errors ) ) );
231 + }
232 + if ( '' !== $messages ) {
233 + /**
234 + * Filters instructional messages displayed above the login form.
235 + *
236 + * @param string $messages Login messages.
237 + *
238 + * @since 2.5.0
239 + */
240 + echo wp_kses_post( sprintf( '<p class="message">%s</p>', apply_filters( 'login_messages', $messages ) ) );
241 + }
206 242 }
207 - if ( ! empty( $errors ) ) {
208 - /**
209 - * Filters the error messages displayed above the login form.
210 - *
211 - * @param string $errors Login error message.
212 - *
213 - * @since 2.1.0
214 - *
215 - */
216 - echo '<div id="login_error">' . apply_filters( 'login_errors', $errors ) . "</div>\n";
217 - }
218 - if ( ! empty( $messages ) ) {
219 - /**
220 - * Filters instructional messages displayed above the login form.
221 - *
222 - * @param string $messages Login messages.
223 - *
224 - * @since 2.5.0
225 - *
226 - */
227 - echo '<p class="message">' . apply_filters( 'login_messages', $messages ) . "</p>\n";
228 - }
229 243 }
230 244 }
231 -}
232 245
246 +$show_logo = WP_Defender\Model\Setting\Two_Fa::CUSTOM_GRAPHIC_TYPE_NO !== $custom_graphic_type;
233 247 if ( isset( $interim_login ) && 'success' === $interim_login ) {
234 - login_header_otp( '', $message );
248 + login_header_otp( '', $message, $show_logo );
235 249
236 - $modal_close_script = <<<END
250 + $modal_close_script = <<<'END'
237 251 <script>
238 252 jQuery(function ($) {
239 253 $('.wp-auth-check-close', window.parent.document).trigger('click');
240 254 });
@@ -242,187 +256,241 @@
242 256 END;
243 257
244 258 add_action(
245 259 'wp_print_footer_scripts',
246 - function() use ( $modal_close_script ) {
247 - echo $modal_close_script;
260 + function () use ( $modal_close_script ) {
261 + /**
262 + * Ignore WordPress.Security.EscapeOutput.OutputNotEscaped
263 + * Why?
264 + * We don't want to escape scripts here.
265 + */
266 + echo $modal_close_script; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
248 267 }
249 268 );
250 269 } else {
251 - login_header_otp( '', '', $error );
270 + login_header_otp( '', '', $show_logo, $error );
252 271
253 - if ( ! empty( $providers ) ) {
254 - foreach ( $providers as $slug => $provider ) { ?>
255 - <form method="post" class="wpdef-2fa-form" id="wpdef-2fa-form-<?php esc_attr_e( $slug ); ?>"
256 - action="<?php
257 - echo esc_url( add_query_arg( 'action', 'defender-verify-otp', site_url( 'wp-login.php', 'login_post' ) ) );
258 - ?>">
272 + if ( is_array( $providers ) && array() !== $providers ) {
273 + $nonce = wp_create_nonce( 'verify_otp' );
274 + foreach ( $providers as $slug => $provider ) {
275 + ?>
276 + <form method="post" class="wpdef-2fa-form" id="wpdef-2fa-form-<?php echo esc_attr( $slug ); ?>" action="
277 + <?php
278 + echo esc_url(
279 + add_query_arg(
280 + 'action',
281 + 'defender-verify-otp',
282 + site_url( 'wp-login.php', 'login_post' )
283 + )
284 + );
285 + ?>
286 + ">
259 287
260 288 <?php $provider->authentication_form(); ?>
261 289
262 - <input type="hidden" name="auth_method" value="<?php echo esc_attr( $slug ); ?>"/>
263 - <input type="hidden" name="login_token" value="<?php echo esc_attr( $token ); ?>"/>
264 - <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>"/>
265 - <input type="hidden" name="password" value="<?php echo esc_attr( $password ); ?>"/>
290 + <input type="hidden" name="auth_method" value="<?php echo esc_attr( $slug ); ?>"/>
291 + <input type="hidden" name="login_token" value="<?php echo esc_attr( $token ); ?>"/>
292 + <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>"/>
293 + <input type="hidden" name="password" value="<?php echo esc_attr( $password ); ?>"/>
294 + <input type="hidden" name="requested_user" value="<?php echo esc_attr( $user_id ); ?>"/>
295 + <input type="hidden" id="_wpnonce_<?php echo esc_attr( $slug ); ?>" name="_wpnonce" value="<?php echo esc_attr( $nonce ); ?>" />
266 296 <?php
267 - if ( isset( $_REQUEST['interim-login'] ) ) { ?>
268 - <input type="hidden" name="interim-login" value="1" />
297 + if ( '1' === defender_get_data_from_request( 'interim-login', 'r' ) ) {
298 + ?>
299 + <input type="hidden" name="interim-login" value="1"/>
269 300 <?php
270 301 }
271 - wp_nonce_field( 'verify_otp' ); ?>
272 - </form>
273 - <?php }
274 - if ( (is_array($providers) || $providers instanceof \Countable ? count( $providers ) : 0) > 1 ) { ?>
275 - <div id="wrap-nav">
276 - <p><?php _e('Having problems? Try another way to log in', 'wpdef' ); ?></p>
277 - <ul id="nav">
278 - <?php foreach ( $providers as $slug => $provider ) { ?>
279 - <li class="wpdef-2fa-link" id="wpdef-2fa-link-<?php esc_attr_e( $slug ); ?>"
280 - data-slug="<?php esc_attr_e( $slug ); ?>">
302 + ?>
303 + </form>
304 + <?php
305 + }
306 + if ( ( is_array( $providers ) || $providers instanceof Countable ? count( $providers ) : 0 ) > 1 ) {
307 + ?>
308 + <div id="wrap-nav">
309 + <p><?php esc_attr_e( 'Having problems? Try another way to log in', 'defender-security' ); ?></p>
310 + <ul id="nav">
311 + <?php foreach ( $providers as $slug => $provider ) { ?>
312 + <li class="wpdef-2fa-link" id="wpdef-2fa-link-<?php echo esc_attr( $slug ); ?>"
313 + data-slug="<?php echo esc_attr( $slug ); ?>">
314 + <!-- The label value is escaped on backend. It's safe. -->
315 + <?php echo $provider->get_login_label(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
281 316
282 - <?php echo $provider->get_login_label(); ?>
283 -
284 - </li>
285 - <?php } ?>
286 - </ul>
287 - <img class="def-ajaxloader" src="<?php echo defender_asset_url( '/assets/img/spinner.svg' ); ?>"/>
288 - </div>
317 + </li>
318 + <?php } ?>
319 + </ul>
320 + </div>
321 + <?php } ?>
289 322 <?php } ?>
290 - <p class="notification"></p>
291 - <?php } ?>
292 - <?php if ( $custom_graphic ) { ?>
293 - <style type="text/css">
294 - body.login div#login h1 a {
295 - background-image: url("<?php echo $custom_graphic ?>");
296 - }
297 - </style>
298 - <?php } ?>
299 - <?php
323 + <?php
324 + if ( $custom_graphic ) {
325 + ?>
326 + <style type="text/css">
327 + body.login div#login h1 a {
328 + background-image: url("<?php echo esc_url_raw( $custom_graphic ); ?>");
329 + }
330 + </style>
331 + <?php
332 + }
300 333 $totp_script = <<<END
301 334 <script>
302 335 jQuery(function ($) {
303 - function two_factor_providers( defaultSlug ) {
304 - // Hide all forms and show the one default.
305 - $('.wpdef-2fa-form').hide();
306 - $('#wpdef-2fa-form-' + defaultSlug).show();
307 - // Hide all links and show others except the default.
308 - if ( $('.wpdef-2fa-link').length > 0 ) {
309 - $('.wpdef-2fa-link').hide();
310 - $('.wpdef-2fa-link:not(#wpdef-2fa-link-'+ defaultSlug +')').each(function(){
311 - $(this).show();
312 - });
313 - }
314 - }
315 - var is_sent = false;
316 - // Logic for FallbackEmail method.
317 - function resend_code() {
318 - // Work with the button 'Resen Code'.
319 - var that = $('input[name="button_resend_code"]');
320 - if (is_sent === false) {
321 - is_sent = true;
322 - }
323 - let data = {
324 - data: JSON.stringify({
325 - 'token': '{$token}'
326 - })
327 - };
328 - $.ajax({
329 - type: 'POST',
330 - url: '{$action_fallback_email}',
331 - data: data,
332 - beforeSend: function () {
333 - that.attr('disabled', 'disabled');
334 - $('.def-ajaxloader').show();
335 - },
336 - success: function (data) {
337 - that.removeAttr('disabled');
338 - $('.def-ajaxloader').hide();
339 - $('.notification').text(data.data.message);
340 - is_sent = false;
341 - }
342 - })
343 - }
336 + function two_factor_providers(defaultSlug) {
337 + // Hide all forms and show the one default.
338 + $('.wpdef-2fa-form').hide();
339 + $('#wpdef-2fa-form-' + defaultSlug).show();
340 + // Hide all links and show others except the default.
341 + if ($('.wpdef-2fa-link').length > 0) {
342 + $('.wpdef-2fa-link').hide();
343 + $('.wpdef-2fa-link:not(#wpdef-2fa-link-' + defaultSlug + ')').each(function () {
344 + $(this).show();
345 + });
346 + }
347 + // Focus on the current input-field.
348 + if ($('#wpdef-2fa-form-' + defaultSlug).find('[name="otp"]').length > 0) {
349 + $('#wpdef-2fa-form-' + defaultSlug).find('[name="otp"]').trigger('focus');
350 + }
351 + }
344 352
345 - $('.def-ajaxloader').hide();
346 - // Hide all forms and show the one default.
347 - var defaultSlug = '{$default_slug}';
348 - two_factor_providers( defaultSlug );
349 - // Work with links.
350 - $('body').on('click', '.wpdef-2fa-link', function () {
351 - $('#login_error').remove();
352 - // Clear any previous notification.
353 - $('.notification').empty();
354 - var slug = $(this).data('slug');
355 - two_factor_providers( slug );
356 - // Switch to 'Fallback Email' method.
357 - if ('fallback-email' === slug) {
358 - resend_code();
359 - }
360 - });
361 - // Resend code.
362 - $('body').on('click', 'input[name="button_resend_code"]', function (e) {
363 - e.preventDefault();
364 - resend_code();
365 - })
366 - })
353 + var is_sent = false;
354 + // Logic for FallbackEmail method.
355 + function resend_code() {
356 + // Work with the button 'Resend Code'.
357 + var that = $('#wd-2fa-resend-code');
358 + if (is_sent === false) {
359 + is_sent = true;
360 + }
361 + let data = {
362 + data: JSON.stringify({
363 + 'token': '{$token}',
364 + 'requested_user': '{$user_id}'
365 + })
366 + };
367 + $.ajax({
368 + type: 'POST',
369 + url: '{$action_fallback_email}',
370 + data: data,
371 + beforeSend: function () {
372 + that.prop('disabled', true);
373 + $('.def-ajaxloader').show();
374 + },
375 + success: function (data) {
376 + that.prop('disabled', false);
377 + $('.def-ajaxloader').hide();
378 + $('#notification').removeClass().addClass('notice notice-success').text(data.data.message).show();
379 + is_sent = false;
380 + }
381 + });
382 + }
383 +
384 + $('.def-ajaxloader').hide();
385 + // Hide all forms and show the one default.
386 + var defaultSlug = '{$default_slug}';
387 + if (!defaultSlug && 0 < $('form.wpdef-2fa-form').first().length) {
388 + var twoFaFormId = $('form.wpdef-2fa-form').first().attr('id');
389 + defaultSlug = twoFaFormId.replace('wpdef-2fa-form-', '');
390 + if ('fallback-email' === defaultSlug) {
391 + resend_code();
392 + } else {
393 + $('#notification').hide();
394 + }
395 + }
396 + two_factor_providers(defaultSlug);
397 + // Work with links.
398 + $('body').on('click', '.wpdef-2fa-link', function () {
399 + $('#login_error').remove();
400 + // Clear any previous notification.
401 + var slug = $(this).data('slug');
402 + two_factor_providers(slug);
403 + // Switch to 'Fallback Email' method.
404 + if ('fallback-email' === slug) {
405 + resend_code();
406 + } else {
407 + $('#notification').hide();
408 + }
409 + });
410 + // Resend code.
411 + $('body').on('click', '#wd-2fa-resend-code', function (e) {
412 + e.preventDefault();
413 + resend_code();
414 + });
415 + });
367 416 </script>
368 417 END;
369 418 add_action(
370 419 'wp_print_footer_scripts',
371 - function() use ( $totp_script ) {
372 - echo $totp_script;
420 + function () use ( $totp_script ) {
421 + /**
422 + * Ignore WordPress.Security.EscapeOutput.OutputNotEscaped
423 + * Why?
424 + * We don't want to escape scripts here.
425 + */
426 + echo $totp_script; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
373 427 }
374 428 );
375 429 ?>
376 - <?php
430 + <?php
377 431 }
378 432 ?>
379 433
380 434 <?php
381 435 if ( ! function_exists( 'login_footer' ) ) {
382 - /**
383 - * Outputs the footer for the login page.
384 - *
385 - * @param string $input_id Which input to auto-focus
386 - */
387 - function login_footer( $input_id = '' ) {
388 - global $interim_login;
436 + /**
437 + * Outputs the footer for the login page.
438 + *
439 + * @param string $input_id Which input to auto-focus.
440 + */
441 + function login_footer( $input_id = '' ) {
442 + global $interim_login;
389 443
390 - // Don't allow interim logins to navigate away from the page.
391 - if ( ! $interim_login ): ?>
392 - <p id="backtoblog"><a href="<?php
393 - echo esc_url( home_url( '/' ) ); ?>"><?php
394 - /* translators: %s: site title */
395 - printf( _x( '&larr; Back to %s', 'site' ), get_bloginfo( 'title', 'display' ) );
396 - ?></a></p>
397 - <?php
398 - endif; ?>
444 + // Don't allow interim logins to navigate away from the page.
445 + if ( ! $interim_login ) :
446 + ?>
447 + <p id="backtoblog"><a href="
448 + <?php
449 + echo esc_url( home_url( '/' ) );
450 + ?>
451 + ">
452 + <?php
453 + printf(
454 + /* translators: %s: site title */
455 + esc_html_x( '&larr; Back to %s', 'site', 'defender-security' ),
456 + esc_html( get_bloginfo( 'title', 'display' ) )
457 + );
458 + ?>
459 + </a></p>
460 + <?php
461 + endif;
462 + ?>
399 463
400 464 </div>
401 465
402 -<?php
403 -if ( ! empty( $input_id ) ) : ?>
404 - <script type="text/javascript">
405 - try {
406 - document.getElementById('<?php echo $input_id; ?>').focus();
407 - } catch (e) {
408 - }
409 - if (typeof wpOnload == 'function') wpOnload();
410 - </script>
411 -<?php
412 -endif; ?>
466 + <?php
467 + if ( '' !== trim( $input_id ) ) :
468 + ?>
469 + <script type="text/javascript">
470 + try {
471 + document.getElementById('<?php echo esc_js( $input_id ); ?>').focus();
472 + } catch (e) {
473 + }
474 + if (typeof wpOnload == 'function') wpOnload();
475 + </script>
476 + <?php
477 + endif;
478 + ?>
413 479
414 -<?php
415 -/**
416 - * Fires in the login page footer.
417 - *
418 - * @since 3.1.0
419 - */
420 -do_action( 'login_footer' ); ?>
480 + <?php
481 + /**
482 + * Fires in the login page footer.
483 + *
484 + * @since 3.1.0
485 + */
486 + do_action( 'login_footer' );
487 + ?>
421 488 <div class="clear"></div>
422 489 </body>
490 +
423 491 </html>
424 -<?php
425 -}
426 -}
427 -login_footer();
428 -?>
492 + <?php
493 + }
494 + }
495 + login_footer();
496 + ?>