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