PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.6.4
WP 2FA – Two-factor authentication for WordPress v2.6.4
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 2 years ago index.php 2 years ago login-header.php 2 years ago
core.php
324 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;
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 WP2FA::init();
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 // Data array.
229 $data_array = array(
230 'ajaxURL' => admin_url( 'admin-ajax.php' ),
231 'roles' => WP2FA::wp_2fa_get_roles(),
232 'nonce' => wp_create_nonce( 'wp-2fa-settings-nonce' ),
233 'codeValidatedHeading' => esc_html__( 'Congratulations', 'wp-2fa' ),
234 'codeValidatedText' => esc_html__( 'Your account just got more secure', 'wp-2fa' ),
235 'codeValidatedButton' => esc_html__( 'Close Wizard & Refresh', 'wp-2fa' ),
236 'processingText' => esc_html__( 'Processing Update', 'wp-2fa' ),
237 'email_sent_success' => esc_html__( 'Email successfully sent', 'wp-2fa' ),
238 'email_sent_failure' => esc_html__( 'Email delivery failed', 'wp-2fa' ),
239 'invalidEmail' => esc_html__( 'Please use a valid email address', 'wp-2fa' ),
240 'license_validation_in_progress' => esc_html__( 'Validating your license, please wait...', 'wp-2fa' ),
241 );
242 wp_localize_script( 'wp_2fa_admin', 'wp2faData', $data_array );
243
244 $data_array = array(
245 'ajaxURL' => admin_url( 'admin-ajax.php' ),
246 'nonce' => wp_create_nonce( 'wp2fa-verify-wizard-page' ),
247 'codesPreamble' => esc_html__( 'These are the 2FA backup codes for the user', 'wp-2fa' ),
248 'readyText' => esc_html__( 'I\'m ready', 'wp-2fa' ),
249 'codeReSentText' => esc_html__( 'New code sent', 'wp-2fa' ),
250 'backupCodesSent' => esc_html__( 'Backup codes sent', 'wp-2fa' ),
251 );
252 wp_localize_script( 'wp_2fa_admin', 'wp2faWizardData', $data_array );
253 }
254
255 /**
256 * Enqueue Select2 jQuery library
257 *
258 * @return void
259 */
260 function enqueue_select2_scripts() {
261 wp_enqueue_style( 'select2', style_url( 'select2.min', 'admin' ), array(), WP_2FA_VERSION );
262 wp_enqueue_script( 'select2', script_url( 'select2.min', 'admin' ), array( 'jquery' ), WP_2FA_VERSION, false );
263 }
264
265 /**
266 * Enqueue styles for admin.
267 *
268 * @return void
269 */
270 function admin_styles() {
271
272 wp_enqueue_style(
273 'wp_2fa_admin',
274 style_url( 'admin-style', 'admin' ),
275 array(),
276 WP_2FA_VERSION
277 );
278 }
279
280 /**
281 * Add async/defer attributes to enqueued scripts that have the specified script_execution flag.
282 *
283 * @link https://core.trac.wordpress.org/ticket/12009
284 * @param string $tag The script tag.
285 * @param string $handle The script handle.
286 * @return string
287 */
288 function script_loader_tag( $tag, $handle ) {
289 $script_execution = wp_scripts()->get_data( $handle, 'script_execution' );
290
291 if ( ! $script_execution ) {
292 return $tag;
293 }
294
295 if ( 'async' !== $script_execution && 'defer' !== $script_execution ) {
296 return $tag;
297 }
298
299 // Abort adding async/defer for scripts that have this script as a dependency. _doing_it_wrong()?
300 foreach ( wp_scripts()->registered as $script ) {
301 if ( in_array( $handle, $script->deps, true ) ) {
302 return $tag;
303 }
304 }
305
306 // Add the attribute if it hasn't already been added.
307 if ( ! preg_match( ":\s$script_execution(=|>|\s):", $tag ) ) {
308 $tag = preg_replace( ':(?=></script>):', " $script_execution", $tag, 1 );
309 }
310
311 return $tag;
312 }
313
314 /**
315 * Generates random string used to salt the key
316 *
317 * @return string
318 *
319 * @since 2.3.0
320 */
321 function wp_salt(): string {
322 return WP2FA::get_secret_key();
323 }
324