PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.9.2
WP 2FA – Two-factor authentication for WordPress v2.9.2
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Admin / SettingsPages / class-settings-page-white-label.php
wp-2fa / includes / classes / Admin / SettingsPages Last commit date
class-settings-page-email.php 11 months ago class-settings-page-general.php 11 months ago class-settings-page-policies.php 11 months ago class-settings-page-render.php 11 months ago class-settings-page-white-label.php 11 months ago index.php 11 months ago
class-settings-page-white-label.php
411 lines
1 <?php
2 /**
3 * White label settings class.
4 *
5 * @package wp2fa
6 * @subpackage settings-pages
7 * @copyright 2025 Melapress
8 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
9 * @link https://wordpress.org/plugins/wp-2fa/
10 */
11
12 namespace WP2FA\Admin\SettingsPages;
13
14 use WP2FA\WP2FA;
15 use WP2FA\Utils\Debugging;
16
17 /**
18 * White labeling settings tab
19 */
20 if ( ! class_exists( '\WP2FA\Admin\SettingsPages\Settings_Page_White_Label' ) ) {
21 /**
22 * Settings_Page_White_Label - Class for handling settings
23 *
24 * @since 2.0.0
25 */
26 class Settings_Page_White_Label {
27
28 /**
29 * Render the settings
30 *
31 * @return void
32 *
33 * @since 2.0.0
34 */
35 public static function render() {
36 if ( ! current_user_can( 'manage_options' ) ) {
37 wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-2fa' ) );
38 }
39 settings_fields( WP_2FA_WHITE_LABEL_SETTINGS_NAME );
40 self::white_labelling_tabs_wrapper();
41 submit_button();
42 }
43
44 /**
45 * Validate options before saving
46 *
47 * @param array $input The settings array.
48 *
49 * @return array|void
50 *
51 * @since 2.0.0
52 */
53 public static function validate_and_sanitize( $input ) {
54
55 // Bail if user doesn't have permissions to be here.
56 if ( ! current_user_can( 'manage_options' ) || ! isset( $_POST['action'] ) && ! check_admin_referer( 'wp2fa-step-choose-method' ) ) {
57 return;
58 }
59
60 Debugging::log( 'The following settings will be processed (White Label): ' . "\n" . wp_json_encode( $input ) );
61
62 $output = array();
63
64 $output['default-text-code-page'] = WP2FA::get_wp2fa_white_label_setting( 'default-text-code-page', false, false );
65
66 if ( isset( $input['default-text-code-page'] ) && '' !== trim( (string) $input['default-text-code-page'] ) ) {
67 $output['default-text-code-page'] = \wp_kses_post( $input['default-text-code-page'] );
68 }
69
70 $output['default-backup-code-page'] = WP2FA::get_wp2fa_white_label_setting( 'default-backup-code-page', false, false );
71
72 if ( isset( $input['default-backup-code-page'] ) && '' !== trim( (string) $input['default-backup-code-page'] ) ) {
73 $output['default-backup-code-page'] = \wp_strip_all_tags( $input['default-backup-code-page'] );
74 }
75
76 $output['login-to-view-area'] = WP2FA::get_wp2fa_white_label_setting( 'login-to-view-area', false, false );
77
78 if ( isset( $input['login-to-view-area'] ) && '' !== trim( (string) $input['login-to-view-area'] ) ) {
79 $output['login-to-view-area'] = \wp_strip_all_tags( $input['login-to-view-area'] );
80 }
81
82 $output['use_custom_2fa_message'] = WP2FA::get_wp2fa_white_label_setting( 'use_custom_2fa_message', false, false );
83
84 if ( isset( $input['use_custom_2fa_message'] ) && '' !== trim( (string) $input['use_custom_2fa_message'] ) ) {
85 $output['use_custom_2fa_message'] = \wp_strip_all_tags( $input['use_custom_2fa_message'] );
86 }
87
88 $output['custom-text-app-code-page'] = WP2FA::get_wp2fa_white_label_setting( 'custom-text-app-code-page', false, false );
89 $output['custom-text-email-code-page'] = WP2FA::get_wp2fa_white_label_setting( 'custom-text-email-code-page', false, false );
90 $output['custom-text-authy-code-page-intro'] = WP2FA::get_wp2fa_white_label_setting( 'custom-text-authy-code-page-intro', false, false );
91 $output['custom-text-authy-code-page-awaiting'] = WP2FA::get_wp2fa_white_label_setting( 'custom-text-authy-code-page-awaiting', false, false );
92 $output['custom-text-authy-code-page'] = WP2FA::get_wp2fa_white_label_setting( 'custom-text-authy-code-page', false, false );
93 $output['custom-text-twilio-code-page'] = WP2FA::get_wp2fa_white_label_setting( 'custom-text-twilio-code-page', false, false );
94
95 if ( isset( $input['custom-text-app-code-page'] ) && '' !== trim( (string) $input['custom-text-app-code-page'] ) ) {
96 $output['custom-text-app-code-page'] = \wp_strip_all_tags( $input['custom-text-app-code-page'] );
97 }
98
99 if ( isset( $input['custom-text-email-code-page'] ) && '' !== trim( (string) $input['custom-text-email-code-page'] ) ) {
100 $output['custom-text-email-code-page'] = \wp_strip_all_tags( $input['custom-text-email-code-page'] );
101 }
102
103 if ( isset( $input['custom-text-authy-code-page'] ) && '' !== trim( (string) $input['custom-text-authy-code-page'] ) ) {
104 $output['custom-text-authy-code-page'] = \wp_strip_all_tags( $input['custom-text-authy-code-page'] );
105 }
106
107 if ( isset( $input['custom-text-authy-code-page-intro'] ) && '' !== trim( (string) $input['custom-text-authy-code-page-intro'] ) ) {
108 $output['custom-text-authy-code-page-intro'] = \wp_strip_all_tags( $input['custom-text-authy-code-page-intro'] );
109 }
110
111 if ( isset( $input['custom-text-authy-code-page-awaiting'] ) && '' !== trim( (string) $input['custom-text-authy-code-page-awaiting'] ) ) {
112 $output['custom-text-authy-code-page-awaiting'] = \wp_strip_all_tags( $input['custom-text-authy-code-page-awaiting'] );
113 }
114
115 if ( isset( $input['custom-text-twilio-code-page'] ) && '' !== trim( (string) $input['custom-text-twilio-code-page'] ) ) {
116 $output['custom-text-twilio-code-page'] = \wp_strip_all_tags( $input['custom-text-twilio-code-page'] );
117 }
118
119 if ( isset( $_REQUEST['_wp_http_referer'] ) ) {
120 $request_area = \wp_parse_url( \sanitize_text_field( \wp_unslash( $_REQUEST['_wp_http_referer'] ) ) );
121 $request_area_path = strpos( $request_area['query'], 'white-label-section' );
122
123 // If we have the input POSTed, we are on the right page so grab it.
124 if ( isset( $input['enable_wizard_styling'] ) && '' !== trim( (string) $input['enable_wizard_styling'] ) ) {
125 $output['enable_wizard_styling'] = \wp_strip_all_tags( $input['enable_wizard_styling'] );
126 } else {
127 // Are we on either the white labelling page (free and premium) or the custom CSS area (premium only)?
128 if ( ! $request_area_path || $request_area_path && strpos( $request_area['query'], 'custom-css' ) ) {
129 $output['enable_wizard_styling'] = '';
130 $input['enable_wizard_styling'] = '';
131 } else {
132 $input['enable_wizard_styling'] = WP2FA::get_wp2fa_white_label_setting( 'enable_wizard_styling', false );
133 $output['enable_wizard_styling'] = WP2FA::get_wp2fa_white_label_setting( 'enable_wizard_styling', false );
134 }
135 }
136
137 if ( isset( $input['show_help_text'] ) && '' !== trim( (string) $input['show_help_text'] ) ) {
138 $output['show_help_text'] = \wp_strip_all_tags( $input['show_help_text'] );
139 } else {
140 // Nothing was POSTed, check where we are in case that means we simple an empty/disabled checkbox.
141 if ( $request_area_path && ! strpos( $request_area['query'], 'method_selection' ) ) {
142 $input['show_help_text'] = WP2FA::get_wp2fa_white_label_setting( 'show_help_text', false );
143 $output['show_help_text'] = WP2FA::get_wp2fa_white_label_setting( 'show_help_text', false );
144 } else {
145 $output['show_help_text'] = '';
146 $input['show_help_text'] = '';
147 }
148 }
149
150 // Same as above, but for the optional welcome.
151 if ( isset( $input['enable_welcome'] ) && '' !== trim( (string) $input['enable_welcome'] ) ) {
152 $output['enable_welcome'] = \wp_strip_all_tags( $input['enable_welcome'] );
153 } elseif ( strpos( $request_area['query'], 'white-label-sub-section' ) && strpos( $request_area['query'], 'welcome' ) ) {
154 $input['enable_welcome'] = '';
155 $output['enable_welcome'] = '';
156 } else {
157 $input['enable_welcome'] = WP2FA::get_wp2fa_white_label_setting( 'enable_welcome', false );
158 $output['enable_welcome'] = WP2FA::get_wp2fa_white_label_setting( 'enable_welcome', false );
159 }
160
161 if ( isset( $input['enable_wizard_logo'] ) && '' !== trim( (string) $input['enable_wizard_logo'] ) ) {
162 $output['enable_wizard_logo'] = \wp_strip_all_tags( $input['enable_wizard_logo'] );
163 } elseif ( strpos( $request_area['query'], 'white-label-sub-section' ) && strpos( $request_area['query'], 'welcome' ) ) {
164 $input['enable_wizard_logo'] = '';
165 $output['enable_wizard_logo'] = '';
166 } else {
167 $input['enable_wizard_logo'] = WP2FA::get_wp2fa_white_label_setting( 'enable_wizard_logo', false );
168 $output['enable_wizard_logo'] = WP2FA::get_wp2fa_white_label_setting( 'enable_wizard_logo', false );
169 }
170
171 if ( isset( $input['hide_page_generated_by'] ) && '' !== trim( (string) $input['hide_page_generated_by'] ) ) {
172 $output['hide_page_generated_by'] = 'hide_page_generated_by';
173 } else {
174 $input['hide_page_generated_by'] = false;
175 }
176 }
177
178
179 if ( isset( $input['login_custom_css'] ) && ! empty( $input['login_custom_css'] ) ) {
180 if ( preg_match( '#</?\w+#', $input['login_custom_css'] ) ) {
181 add_settings_error(
182 WP_2FA_SETTINGS_NAME,
183 \esc_attr( 'markup_invalid_settings_error' ),
184 \esc_html__( 'Markup is not allowed in Login area CSS.', 'wp-2fa' ),
185 'error'
186 );
187 $output['login_custom_css'] = WP2FA::get_wp2fa_white_label_setting( 'login_custom_css', false );
188 $input['login_custom_css'] = WP2FA::get_wp2fa_white_label_setting( 'login_custom_css', false );
189 } else {
190 $output['login_custom_css'] = \wp_strip_all_tags( $input['login_custom_css'] );
191 $input['login_custom_css'] = \wp_strip_all_tags( $input['login_custom_css'] );
192 }
193 }
194
195 if ( isset( $input['disable_login_css'] ) && '' !== trim( (string) $input['disable_login_css'] ) ) {
196 $output['disable_login_css'] = \wp_strip_all_tags( $input['disable_login_css'] );
197 } else {
198 // Nothing was POSTed, check where we are in case that means we simple an empty/disabled checkbox.
199 if ( $request_area_path && ! strpos( $request_area['query'], 'method_selection' ) ) {
200 $input['disable_login_css'] = WP2FA::get_wp2fa_white_label_setting( 'disable_login_css', false );
201 $output['disable_login_css'] = WP2FA::get_wp2fa_white_label_setting( 'disable_login_css', false );
202 } else {
203 $output['disable_login_css'] = '';
204 $input['disable_login_css'] = '';
205 }
206 }
207
208 // Remove duplicates from settings errors. We do this as this sanitization callback is actually fired twice, so we end up with duplicates when saving the settings for the FIRST TIME only. The issue is not present once the settings are in the DB as the sanitization wont fire again. For details on this core issue - https://core.trac.wordpress.org/ticket/21989.
209 global $wp_settings_errors;
210 if ( isset( $wp_settings_errors ) ) {
211 $errors = array_map( 'unserialize', array_unique( array_map( 'serialize', $wp_settings_errors ) ) );
212 $wp_settings_errors = $errors; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
213 }
214
215 /**
216 * Filter the values we are about to store in the plugin settings.
217 *
218 * @param array $output - The output array with all the data we will store in the settings.
219 * @param array $input - The input array with all the data we received from the user.
220 *
221 * @since 2.0.0
222 */
223 $output = \apply_filters( WP_2FA_PREFIX . 'filter_output_content_white_label', $output, $input );
224
225 Debugging::log( 'The following settings are being saved (White Label): ' . "\n" . wp_json_encode( $output ) );
226
227 return $output;
228 }
229
230 /**
231 * Updates global white label network options
232 *
233 * @return void
234 *
235 * @since 2.0.0
236 */
237 public static function update_wp2fa_network_options() {
238 if ( ! \current_user_can( 'manage_options' ) ) {
239 \wp_die( \esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-2fa' ) );
240 }
241
242 if ( isset( $_POST[ WP_2FA_WHITE_LABEL_SETTINGS_NAME ] ) ) {
243 check_admin_referer( 'wp_2fa_white_label-options' );
244 $options = self::validate_and_sanitize( \wp_unslash( $_POST[ WP_2FA_WHITE_LABEL_SETTINGS_NAME ] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
245 $settings_errors = get_settings_errors( WP_2FA_WHITE_LABEL_SETTINGS_NAME );
246 if ( ! empty( $settings_errors ) ) {
247
248 // redirect back to our options page.
249 wp_safe_redirect(
250 add_query_arg(
251 array(
252 'page' => 'wp-2fa-settings',
253 'wp_2fa_network_settings_error' => urlencode_deep( $settings_errors[0]['message'] ),
254 ),
255 network_admin_url( 'settings.php' )
256 )
257 );
258 exit;
259
260 }
261 WP2FA::update_plugin_settings( $options, false, WP_2FA_WHITE_LABEL_SETTINGS_NAME );
262
263 // redirect back to our options page.
264 wp_safe_redirect(
265 add_query_arg(
266 array(
267 'page' => 'wp-2fa-settings',
268 'tab' => 'white-label-settings',
269 'wp_2fa_network_settings_updated' => 'true',
270 ),
271 network_admin_url( 'admin.php' )
272 )
273 );
274 exit;
275 }
276 }
277
278 /**
279 * Wrapper which adds special tabbed navigation and content
280 *
281 * @return void
282 *
283 * @since 2.3.0
284 */
285 private static function white_labelling_tabs_wrapper() {
286 /**
287 * Fires right before the white label settings tab HTML, handles tabbed nav.
288 *
289 * @since 2.3.0
290 */
291 do_action( WP_2FA_PREFIX . 'white_labeling_tabbed_navigation' );
292 self::change_default_text_area();
293 }
294
295 /**
296 * Shows default settings input to the user
297 *
298 * @return void
299 *
300 * @since 2.0.0
301 */
302 private static function change_default_text_area() {
303 /**
304 * Fires right before the white label settings tab HTML rendering.
305 *
306 * @since 2.0.0
307 */
308 do_action( WP_2FA_PREFIX . 'white_labeling_settings_page_before_default_text' );
309 ?>
310
311 <h3><?php \esc_html_e( 'Change the default text used in the 2FA code page', 'wp-2fa' ); ?></h3>
312 <p class="description">
313 <?php \esc_html_e( 'This is the text shown to the users on the page when they are asked to enter the 2FA code. To change the default text, simply type it in the below placeholder.', 'wp-2fa' ); ?>
314 </p>
315
316 <table class="form-table">
317 <tbody>
318 <tr>
319 <th><label for="2fa-method"><?php \esc_html_e( '2FA code page text', 'wp-2fa' ); ?></label></th>
320 <td>
321 <?php
322
323 echo self::create_standard_editor( 'default-text-code-page' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
324
325 ?>
326 <div style="margin-top: 5px;"><span><strong><i><?php \esc_html_e( 'Note:', 'wp-2fa' ); ?></i></strong> <?php \esc_html_e( 'Only plain text is allowed.', 'wp-2fa' ); ?></span></div>
327 </td>
328 </tr>
329 <tr>
330 <th><label for="backup-method"><?php \esc_html_e( 'Backup code page text', 'wp-2fa' ); ?></label></th>
331 <td>
332 <?php
333
334 echo self::create_standard_editor( 'default-backup-code-page' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
335
336 ?>
337 <div style="margin-top: 5px;"><span><strong><i><?php \esc_html_e( 'Note:', 'wp-2fa' ); ?></i></strong> <?php \esc_html_e( 'Only plain text is allowed.', 'wp-2fa' ); ?></span></div>
338 </td>
339 </tr>
340
341 <tr>
342 <th><label for="backup-method"><?php \esc_html_e( 'Text for logged out users trying to access the 2FA configuration page', 'wp-2fa' ); ?></label></th>
343 <td>
344 <?php
345 echo self::create_standard_editor( 'login-to-view-area' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
346 ?>
347 </td>
348 </tr>
349
350 <?php
351 /**
352 * Gives the ability for the 3rd party extensions to add additional white label settings
353 */
354 do_action( WP_2FA_PREFIX . 'white_labeling_settings_page_after_code_page' );
355 ?>
356 </tbody>
357 </table>
358 <h3><?php \esc_html_e( 'Change the styling of the user 2FA wizards', 'wp-2fa' ); ?></h3>
359 <p class="description">
360 <?php \esc_html_e( 'By default, the user 2FA wizards which the users see and use to set up 2FA have our own styling. Disable the below setting so the wizards use the styling of your website\'s theme.', 'wp-2fa' ); ?>
361 </p>
362 <table class="form-table">
363 <tbody>
364 <tr>
365 <th><label for="enable_wizard_styling"><?php \esc_html_e( 'Enable styling', 'wp-2fa' ); ?></label></th>
366 <td>
367 <fieldset>
368 <input type="checkbox" id="enable_wizard_styling" name="wp_2fa_white_label[enable_wizard_styling]" value="enable_wizard_styling"
369 <?php \checked( 'enable_wizard_styling', WP2FA::get_wp2fa_white_label_setting( 'enable_wizard_styling' ), true ); ?>
370 >
371 <?php \esc_html_e( 'Enable our CSS within user wizards', 'wp-2fa' ); ?>
372 </fieldset>
373 </td>
374 </tr>
375 </tbody>
376 </table>
377
378 <?php
379 /**
380 * Fires after the white label settings tab is rendered.
381 *
382 * @since 2.0.0
383 */
384 \do_action( WP_2FA_PREFIX . 'white_labeling_settings_page_after_default_text' );
385 }
386
387 /**
388 * Simple function to create a neat text editor in free.
389 *
390 * @param string $requested_slide - The slide.
391 *
392 * @return void
393 *
394 * @since 2.8.1
395 */
396 public static function create_standard_editor( $requested_slide = 'welcome' ) {
397 $settings = array(
398 'media_buttons' => false,
399 'editor_height' => 200,
400 'textarea_name' => 'wp_2fa_white_label[' . sanitize_key( $requested_slide ) . ']',
401 );
402
403 $content = WP2FA::get_wp2fa_white_label_setting( sanitize_key( $requested_slide ), true );
404
405 if ( isset( $content ) ) {
406 \wp_editor( ( $content ), sanitize_key( $requested_slide ), $settings );
407 }
408 }
409 }
410 }
411