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