PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.9.0
WP 2FA – Two-factor authentication for WordPress v2.9.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 / functions / core.php
wp-2fa / includes / functions Last commit date
core.php 11 months ago index.php 11 months ago login-header.php 11 months ago
core.php
321 lines
1 <?php
2 /**
3 * Core plugin functionality.
4 *
5 * @package WP2FA
6 */
7
8 namespace WP2FA\Core;
9
10 use WP2FA\WP2FA;
11 use WP2FA\Utils\Settings_Utils;
12 use WP2FA\Admin\Helpers\WP_Helper;
13 use WP2FA\Admin\Views\Re_Login_2FA;
14 use WP2FA\Admin\Helpers\User_Helper;
15
16 /**
17 * Default setup routine
18 *
19 * @return void
20 */
21 function setup() {
22 $n = function ( $function ) {
23 return __NAMESPACE__ . "\\$function";
24 };
25
26 add_action( 'init', $n( 'i18n' ) );
27 add_action( 'init', $n( 'init' ) );
28 add_action( 'admin_enqueue_scripts', $n( 'admin_scripts' ) );
29 add_action( 'admin_enqueue_scripts', $n( 'admin_styles' ) );
30
31 // Hook to allow async or defer on asset loading.
32 add_filter( 'script_loader_tag', $n( 'script_loader_tag' ), 10, 2 );
33
34 /**
35 * Fires after the plugin is loaded.
36 *
37 * @since 2.0.0
38 */
39 do_action( WP_2FA_PREFIX . 'loaded' );
40 }
41
42 /**
43 * Registers the default textdomain.
44 *
45 * @return void
46 */
47 function i18n() {
48 $locale = apply_filters( 'plugin_locale', determine_locale(), 'wp-2fa' );
49 load_textdomain( 'wp-2fa', WP_LANG_DIR . '/wp-2fa/wp-2fa-' . $locale . '.mo' );
50 load_plugin_textdomain( 'wp-2fa', false, plugin_basename( WP_2FA_PATH ) . '/languages/' );
51 }
52
53 /**
54 * Initializes the plugin and fires an action other plugins can hook into.
55 *
56 * @return void
57 */
58 function init() {
59
60 /**
61 * Fires when plugin is initiated.
62 *
63 * @since 2.0.0
64 */
65 do_action( WP_2FA_PREFIX . 'init' );
66 }
67
68 /**
69 * Activate the plugin
70 *
71 * @return void
72 */
73 function activate() {
74 // First load the init scripts in case any rewrite functionality is being loaded.
75 init();
76 flush_rewrite_rules();
77
78 // Check if the user is allowed to manage options for the site.
79 if ( current_user_can( 'manage_options' ) ) {
80 // Add an option to let our plugin know this user has not been through the setup wizard.
81 Settings_Utils::update_option( 'redirect_on_activate', true );
82 }
83
84 // Add plugin version to wp_options.
85 Settings_Utils::update_option( 'plugin_version', WP_2FA_VERSION );
86 }
87
88 /**
89 * Deactivate the plugin
90 *
91 * Uninstall routines should be in uninstall.php
92 *
93 * @return void
94 */
95 function deactivate() {
96 }
97
98 /**
99 * Uninstall the plugin
100 *
101 * @return void
102 */
103 function uninstall() {
104 WP2FA::init();
105 if ( ! empty( WP2FA::get_wp2fa_general_setting( 'delete_data_upon_uninstall' ) ) ) {
106 // Delete settings from wp_options.
107 global $wpdb;
108 if ( WP_Helper::is_multisite() ) {
109 $network_id = get_current_network_id();
110 $wpdb->query(
111 $wpdb->prepare(
112 "
113 DELETE FROM $wpdb->sitemeta
114 WHERE meta_key LIKE %s
115 AND site_id = %d
116 ",
117 '%wp_2fa_%',
118 $network_id
119 )
120 );
121 } else {
122 $wpdb->query(
123 $wpdb->prepare(
124 "
125 DELETE FROM $wpdb->options
126 WHERE option_name LIKE %s
127 ",
128 '%wp_2fa_%'
129 )
130 );
131 }
132
133 $wpdb->query(
134 $wpdb->prepare(
135 "
136 DELETE FROM $wpdb->usermeta
137 WHERE meta_key LIKE %s
138 ",
139 WP_2FA_PREFIX . 'wp_2fa_%'
140 )
141 );
142 }
143 }
144
145 /**
146 * The list of known contexts for enqueuing scripts/styles.
147 *
148 * @return array
149 */
150 function get_enqueue_contexts() {
151 return array( 'admin', 'frontend', 'shared' );
152 }
153
154 /**
155 * Generate an URL to a script, taking into account whether SCRIPT_DEBUG is enabled.
156 *
157 * @param string $script Script file name (no .js extension).
158 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
159 *
160 * @return string|\WP_Error URL
161 */
162 function script_url( $script, $context ) {
163
164 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
165 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA script loader.' );
166 }
167
168 return WP_2FA_URL . 'dist/js/' . sanitize_file_name( $script ) . '.js';
169 }
170
171 /**
172 * Generate an URL to a stylesheet, taking into account whether SCRIPT_DEBUG is enabled.
173 *
174 * @param string $stylesheet Stylesheet file name (no .css extension).
175 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
176 *
177 * @return string|\WP_Error URL
178 */
179 function style_url( $stylesheet, $context ) {
180
181 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
182 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA stylesheet loader.' );
183 }
184
185 return WP_2FA_URL . 'dist/css/' . sanitize_file_name( $stylesheet ) . '.css';
186 }
187
188 /**
189 * Enqueue scripts for admin.
190 *
191 * @return void
192 */
193 function admin_scripts() {
194
195 global $pagenow;
196
197 // Get page argument from $_GET array.
198 $page = ( isset( $_GET['page'] ) ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
199 if ( ( empty( $page ) || false === strpos( $page, 'wp-2fa' ) ) && 'profile.php' !== $pagenow ) {
200 return;
201 }
202
203 \wp_enqueue_script(
204 'wp_2fa_admin',
205 script_url( 'admin', 'admin' ),
206 array( 'jquery-ui-widget', 'jquery-ui-core', 'jquery-ui-autocomplete', 'wp_2fa_micro_modals', 'select2' ),
207 WP_2FA_VERSION,
208 true
209 );
210
211 \wp_enqueue_script(
212 'wp_2fa_micro_modals',
213 script_url( 'micromodal', 'admin' ),
214 array(),
215 WP_2FA_VERSION,
216 true
217 );
218
219 enqueue_select2_scripts();
220
221 // Data array.
222 $data_array = array(
223 'ajaxURL' => \admin_url( 'admin-ajax.php' ),
224 'roles' => WP_Helper::get_roles_wp(),
225 'nonce' => wp_create_nonce( 'wp-2fa-settings-nonce' ),
226 'codeValidatedHeading' => esc_html__( 'Congratulations', 'wp-2fa' ),
227 'codeValidatedText' => esc_html__( 'Your account just got more secure', 'wp-2fa' ),
228 'codeValidatedButton' => esc_html__( 'Close Wizard & Refresh', 'wp-2fa' ),
229 'processingText' => esc_html__( 'Processing Update', 'wp-2fa' ),
230 'email_sent_success' => esc_html__( 'Email successfully sent', 'wp-2fa' ),
231 'email_sent_failure' => esc_html__( 'Email delivery failed', 'wp-2fa' ),
232 'invalidEmail' => esc_html__( 'Please use a valid email address', 'wp-2fa' ),
233 'license_validation_in_progress' => esc_html__( 'Validating your license, please wait...', 'wp-2fa' ),
234 );
235 wp_localize_script( 'wp_2fa_admin', 'wp2faData', $data_array );
236
237 $re_login = Settings_Utils::get_setting_role( User_Helper::get_user_role(), Re_Login_2FA::RE_LOGIN_SETTINGS_NAME );
238
239 $data_array = array(
240 'ajaxURL' =>\admin_url( 'admin-ajax.php' ),
241 'nonce' => wp_create_nonce( 'wp2fa-verify-wizard-page' ),
242 'codesPreamble' => esc_html__( 'These are the 2FA backup codes for the user', 'wp-2fa' ),
243 'readyText' => esc_html__( 'I\'m ready', 'wp-2fa' ),
244 'codeReSentText' => esc_html__( 'New code sent', 'wp-2fa' ),
245 'backupCodesSent' => esc_html__( 'Backup codes sent', 'wp-2fa' ),
246 'reLoginEnabled' => Re_Login_2FA::ENABLED_SETTING_VALUE,
247 'reLogin' => $re_login,
248 );
249 wp_localize_script( 'wp_2fa_admin', 'wp2faWizardData', $data_array );
250 }
251
252 /**
253 * Enqueue Select2 jQuery library
254 *
255 * @return void
256 */
257 function enqueue_select2_scripts() {
258 wp_enqueue_style( 'select2', style_url( 'select2.min', 'admin' ), array(), WP_2FA_VERSION );
259 wp_enqueue_script( 'select2', script_url( 'select2.min', 'admin' ), array( 'jquery' ), WP_2FA_VERSION, false );
260 }
261
262 /**
263 * Enqueue styles for admin.
264 *
265 * @return void
266 */
267 function admin_styles() {
268
269 wp_enqueue_style(
270 'wp_2fa_admin',
271 style_url( 'admin-style', 'admin' ),
272 array(),
273 WP_2FA_VERSION
274 );
275 }
276
277 /**
278 * Add async/defer attributes to enqueued scripts that have the specified script_execution flag.
279 *
280 * @link https://core.trac.wordpress.org/ticket/12009
281 * @param string $tag The script tag.
282 * @param string $handle The script handle.
283 * @return string
284 */
285 function script_loader_tag( $tag, $handle ) {
286 $script_execution = wp_scripts()->get_data( $handle, 'script_execution' );
287
288 if ( ! $script_execution ) {
289 return $tag;
290 }
291
292 if ( 'async' !== $script_execution && 'defer' !== $script_execution ) {
293 return $tag;
294 }
295
296 // Abort adding async/defer for scripts that have this script as a dependency. _doing_it_wrong()?
297 foreach ( wp_scripts()->registered as $script ) {
298 if ( in_array( $handle, $script->deps, true ) ) {
299 return $tag;
300 }
301 }
302
303 // Add the attribute if it hasn't already been added.
304 if ( ! preg_match( ":\s$script_execution(=|>|\s):", $tag ) ) {
305 $tag = preg_replace( ':(?=></script>):', " $script_execution", $tag, 1 );
306 }
307
308 return $tag;
309 }
310
311 /**
312 * Generates random string used to salt the key
313 *
314 * @return string
315 *
316 * @since 2.3.0
317 */
318 function wp_salt(): string {
319 return WP2FA::get_secret_key();
320 }
321