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