PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.4.2
WP 2FA – Two-factor authentication for WordPress v2.4.2
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 3 years ago index.php 5 years ago login-header.php 4 years ago
core.php
339 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 /**
98 * Uninstall the plugin
99 *
100 * @return void
101 */
102 function uninstall() {
103 if ( ! empty( WP2FA::get_wp2fa_general_setting( 'delete_data_upon_uninstall' ) ) ) {
104 // Delete settings from wp_options.
105 if ( WP_Helper::is_multisite() ) {
106 $network_id = get_current_network_id();
107 global $wpdb;
108 $wpdb->query(
109 $wpdb->prepare(
110 "
111 DELETE FROM $wpdb->sitemeta
112 WHERE meta_key LIKE %s
113 AND site_id = %d
114 ",
115 array(
116 '%wp_2fa_%',
117 $network_id,
118 )
119 )
120 );
121 } else {
122 global $wpdb;
123 $wpdb->query(
124 $wpdb->prepare(
125 "
126 DELETE FROM $wpdb->options
127 WHERE option_name LIKE %s
128 ",
129 array(
130 '%wp_2fa_%',
131 )
132 )
133 );
134 }
135
136 global $wpdb;
137 $wpdb->query(
138 $wpdb->prepare(
139 "
140 DELETE FROM $wpdb->usermeta
141 WHERE 1
142 AND meta_key LIKE %s
143 ",
144 array(
145 WP_2FA_PREFIX . 'wp_2fa_%',
146 )
147 )
148 );
149 }
150 }
151
152 /**
153 * The list of knows contexts for enqueuing scripts/styles.
154 *
155 * @return array
156 */
157 function get_enqueue_contexts() {
158 return array( 'admin', 'frontend', 'shared' );
159 }
160
161 /**
162 * Generate an URL to a script, taking into account whether SCRIPT_DEBUG is enabled.
163 *
164 * @param string $script Script file name (no .js extension).
165 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
166 *
167 * @return string|\WP_Error URL
168 */
169 function script_url( $script, $context ) {
170
171 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
172 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA script loader.' );
173 }
174
175 return WP_2FA_URL . 'dist/js/' . $script . '.js';
176 }
177
178 /**
179 * Generate an URL to a stylesheet, taking into account whether SCRIPT_DEBUG is enabled.
180 *
181 * @param string $stylesheet Stylesheet file name (no .css extension).
182 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
183 *
184 * @return string|\WP_Error URL
185 */
186 function style_url( $stylesheet, $context ) {
187
188 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
189 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA stylesheet loader.' );
190 }
191
192 return WP_2FA_URL . 'dist/css/' . $stylesheet . '.css';
193 }
194
195 /**
196 * Enqueue scripts for admin.
197 *
198 * @return void
199 */
200 function admin_scripts() {
201
202 global $pagenow;
203
204 // Get page argument from $_GET array.
205 $page = ( isset( $_GET['page'] ) ) ? \sanitize_text_field( \wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
206 if ( ( empty( $page ) || false === strpos( $page, 'wp-2fa' ) ) && 'profile.php' !== $pagenow ) {
207 return;
208 }
209
210 wp_enqueue_script(
211 'wp_2fa_admin',
212 script_url( 'admin', 'admin' ),
213 array( 'jquery-ui-widget', 'jquery-ui-core', 'jquery-ui-autocomplete', 'wp_2fa_micro_modals', 'select2' ),
214 WP_2FA_VERSION,
215 true
216 );
217
218 wp_enqueue_script(
219 'wp_2fa_micro_modals',
220 script_url( 'micromodal', 'admin' ),
221 array(),
222 WP_2FA_VERSION,
223 true
224 );
225
226 enqueue_select2_scripts();
227
228 if ( WP_Helper::is_multisite() ) {
229 enqueue_multi_select_scripts();
230 }
231
232 // Data array.
233 $data_array = array(
234 'ajaxURL' => admin_url( 'admin-ajax.php' ),
235 'roles' => WP2FA::wp_2fa_get_roles(),
236 'nonce' => wp_create_nonce( 'wp-2fa-settings-nonce' ),
237 'codeValidatedHeading' => esc_html__( 'Congratulations', 'wp-2fa' ),
238 'codeValidatedText' => esc_html__( 'Your account just got more secure', 'wp-2fa' ),
239 'codeValidatedButton' => esc_html__( 'Close Wizard & Refresh', 'wp-2fa' ),
240 'processingText' => esc_html__( 'Processing Update', 'wp-2fa' ),
241 'email_sent_success' => esc_html__( 'Email successfully sent', 'wp-2fa' ),
242 'email_sent_failure' => esc_html__( 'Email delivery failed', 'wp-2fa' ),
243 'invalidEmail' => esc_html__( 'Please use a valid email address', 'wp-2fa' ),
244 'license_validation_in_progress' => esc_html__( 'Validating your license, please wait...', 'wp-2fa' ),
245 );
246 wp_localize_script( 'wp_2fa_admin', 'wp2faData', $data_array );
247
248 $data_array = array(
249 'ajaxURL' => admin_url( 'admin-ajax.php' ),
250 'nonce' => wp_create_nonce( 'wp2fa-verify-wizard-page' ),
251 'codesPreamble' => esc_html__( 'These are the 2FA backup codes for the user', 'wp-2fa' ),
252 'readyText' => esc_html__( 'I\'m ready', 'wp-2fa' ),
253 'codeReSentText' => esc_html__( 'New code sent', 'wp-2fa' ),
254 'backupCodesSent' => esc_html__( 'Backup codes sent', 'wp-2fa' ),
255 );
256 wp_localize_script( 'wp_2fa_admin', 'wp2faWizardData', $data_array );
257
258 }
259
260 /**
261 * Enqueue multi select for multinetwork WP
262 *
263 * @return void
264 */
265 function enqueue_multi_select_scripts() {
266 wp_enqueue_script( 'multi-site-select', script_url( 'multi-site-select', 'admin' ), array( 'jquery', 'select2' ), WP_2FA_VERSION, false );
267 }
268
269 /**
270 * Enqueue Select2 jQuery library
271 *
272 * @return void
273 */
274 function enqueue_select2_scripts() {
275 wp_enqueue_style( 'select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css', array(), WP_2FA_VERSION );
276 wp_enqueue_script( 'select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js', array( 'jquery' ), WP_2FA_VERSION, false );
277 }
278
279 /**
280 * Enqueue styles for admin.
281 *
282 * @return void
283 */
284 function admin_styles() {
285
286 wp_enqueue_style(
287 'wp_2fa_admin',
288 style_url( 'admin-style', 'admin' ),
289 array(),
290 WP_2FA_VERSION
291 );
292
293 }
294
295 /**
296 * Add async/defer attributes to enqueued scripts that have the specified script_execution flag.
297 *
298 * @link https://core.trac.wordpress.org/ticket/12009
299 * @param string $tag The script tag.
300 * @param string $handle The script handle.
301 * @return string
302 */
303 function script_loader_tag( $tag, $handle ) {
304 $script_execution = wp_scripts()->get_data( $handle, 'script_execution' );
305
306 if ( ! $script_execution ) {
307 return $tag;
308 }
309
310 if ( 'async' !== $script_execution && 'defer' !== $script_execution ) {
311 return $tag;
312 }
313
314 // Abort adding async/defer for scripts that have this script as a dependency. _doing_it_wrong()?
315 foreach ( wp_scripts()->registered as $script ) {
316 if ( in_array( $handle, $script->deps, true ) ) {
317 return $tag;
318 }
319 }
320
321 // Add the attribute if it hasn't already been added.
322 if ( ! preg_match( ":\s$script_execution(=|>|\s):", $tag ) ) {
323 $tag = preg_replace( ':(?=></script>):', " $script_execution", $tag, 1 );
324 }
325
326 return $tag;
327 }
328
329 /**
330 * Generates random string used to salt the key
331 *
332 * @return string
333 *
334 * @since 2.3.0
335 */
336 function wp_salt(): string {
337 return WP2FA::get_secret_key();
338 }
339