PluginProbe
Two Factor Authentication / 1.2.6
Two Factor Authentication v1.2.6
1.12.2 1.13.0 1.14.10 1.14.11 1.14.14 1.14.15 1.14.16 1.14.17 1.14.23 1.14.24 1.14.26 1.14.27 1.14.3 1.14.4 1.14.5 1.14.7 1.14.8 1.15.5 1.16.0 1.2.10 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 All 98 releases
← All changes | two-factor-login.php +766 -200 1.14.141.2.6 View file →
@@ -2,269 +2,835 @@
2 2 /*
3 3 Plugin Name: Two Factor Authentication
4 4 Plugin URI: https://www.simbahosting.co.uk/s3/product/two-factor-authentication/
5 5 Description: Secure your WordPress login forms with two factor authentication - including WooCommerce login forms
6 -Author: David Anderson, original plugin by Oskar Hane and enhanced by Dee Nutbourne
6 +Author: David Nutbourne + David Anderson, original plugin by Oskar Hane
7 7 Author URI: https://www.simbahosting.co.uk
8 -Version: 1.14.14
9 -Text Domain: two-factor-authentication
10 -Domain Path: /languages
8 +Version: 1.2.6
11 9 License: GPLv2 or later
12 10 */
13 11
14 -register_activation_hook(__FILE__, 'simba_two_factor_authentication_activation');
12 +define('SIMBA_TFA_TEXT_DOMAIN', 'two-factor-authentication');
13 +define('SIMBA_TFA_PLUGIN_DIR', dirname( __FILE__ ));
14 +define('SIMBA_TFA_PLUGIN_URL', plugins_url('', __FILE__));
15 15
16 -if (!function_exists('simba_two_factor_authentication_activation')) {
17 - function simba_two_factor_authentication_activation() {
18 - if (!empty($GLOBALS['simba_two_factor_authentication'])) {
19 - $is_2fa_plugin_active = false;
20 - $installed_plugins_slugs = array_keys(get_plugins());
21 - foreach ($installed_plugins_slugs as $installed_plugin_slug) {
22 - if (is_plugin_active($installed_plugin_slug)) {
23 - $temp_split_plugin_slug = explode('/', $installed_plugin_slug);
24 - if (isset($temp_split_plugin_slug[1]) && 'two-factor-login.php' == $temp_split_plugin_slug[1]) {
25 - $is_2fa_plugin_active = true;
26 - break;
27 - }
28 - }
29 - }
16 +class Simba_Two_Factor_Authentication {
30 17
31 - // We should prevent activation if and only if either the 2FA Premium or 2FA Free plugin is active.
32 - // We should not prevent activation if either the AIOS plugin is active.
33 - if ($is_2fa_plugin_active) {
34 - if (file_exists(__DIR__.'/simba-tfa/premium/loader.php')) {
35 - wp_die(__('To activate Two Factor Authentication Premium, first de-activate the free version (only one can be active at once).', 'two-factor-authentication'));
36 - } else { // If the 2FA Premium plugin is active and tries to activate the 2FA Free Plugin, it throws a fatal error and stops activating the free version.
37 - wp_die(__("You can't activate Two Factor Authentication (Free) because Two Factor Authentication Premium is active (only one can be active at once).", 'two-factor-authentication'));
38 - }
39 - }
40 - }
41 - }
42 -}
18 + public $version = '1.2.6';
19 + private $php_required = '5.3';
43 20
44 -if (!defined('SIMBA_TFA_TEXT_DOMAIN')) define('SIMBA_TFA_TEXT_DOMAIN', 'two-factor-authentication');
45 -if (!class_exists('Simba_Two_Factor_Authentication_1')) require dirname(__FILE__).'/simba-tfa/simba-tfa.php';
21 + private $frontend;
46 22
47 -if (!class_exists('Simba_Two_Factor_Authentication_Plugin')):
48 -/**
49 - * This parent-child relationship enables the two to be split without affecting backwards compatibility for developers making direct calls
50 - *
51 - * This class is for the plugin encapsulation.
52 - */
53 -class Simba_Two_Factor_Authentication_Plugin extends Simba_Two_Factor_Authentication_1 {
54 -
55 - public $version = '1.14.13';
56 -
57 - const PHP_REQUIRED = '5.6';
58 -
59 - /**
60 - * Constructor, run upon plugin initiation
61 - *
62 - * @uses __FILE__
63 - */
64 23 public function __construct() {
65 -
66 - add_action('plugins_loaded', array($this, 'plugins_loaded_load_textdomain'));
67 -
68 - if (version_compare(PHP_VERSION, self::PHP_REQUIRED, '<' )) {
24 +
25 + if (version_compare(PHP_VERSION, $this->php_required, '<' )) {
69 26 add_action('all_admin_notices', array($this, 'admin_notice_insufficient_php'));
70 27 $abort = true;
71 28 }
72 -
73 - if (!function_exists('mcrypt_get_iv_size') && !function_exists('openssl_cipher_iv_length')) {
74 - add_action('all_admin_notices', array($this, 'admin_notice_missing_mcrypt_and_openssl'));
29 +
30 + if (!function_exists('mcrypt_get_iv_size')) {
31 + add_action('all_admin_notices', array($this, 'admin_notice_missing_mcrypt'));
75 32 $abort = true;
76 33 }
34 +
35 + if (!empty($abort)) return;
36 +
37 + if (file_exists(SIMBA_TFA_PLUGIN_DIR.'/premium.php')) include_once(SIMBA_TFA_PLUGIN_DIR.'/premium.php');
38 +
39 + add_action('wp_ajax_nopriv_simbatfa-init-otp', array($this, 'tfaInitLogin'));
40 +
41 + add_action('wp_ajax_simbatfa_shared_ajax', array($this, 'shared_ajax'));
42 +
43 + add_action('woocommerce_before_customer_login_form', array($this, 'woocommerce_before_customer_login_form'));
44 + // The login form on the checkout doesn't call the woocommerce_before_customer_login_form action
45 + add_action('woocommerce_before_checkout_form', array($this, 'woocommerce_before_customer_login_form'));
46 +
47 + if (is_admin()) {
48 + //Save settings
49 + add_action('admin_init', array($this, 'check_possible_reset'));
50 +
51 + //Add to Settings menu on sites
52 + add_action('admin_menu', array($this, 'menu_entry_for_admin'));
53 +
54 + //Add settings link in plugin list
55 + $plugin = plugin_basename(__FILE__);
56 + add_filter("plugin_action_links_".$plugin, array($this, 'addPluginSettingsLink' ));
57 + add_filter('network_admin_plugin_action_links_'.$plugin, array($this, 'addPluginSettingsLink' ));
58 +
59 + // Entry that everybody gets
60 + add_action('network_admin_menu', array($this, 'admin_menu'));
61 + add_action('admin_menu', array($this, 'admin_menu'));
62 +
63 + } else {
64 + add_action('init', array($this, 'check_possible_reset'));
65 + }
66 +
67 + add_action('plugins_loaded', array($this, 'plugins_loaded'));
68 + add_action('init', array($this, 'init'));
69 +
70 + //Show off sync message for hotp
71 + add_action('admin_notices', array($this, 'tfaShowHOTPOffSyncMessage'));
72 + add_action('login_enqueue_scripts', array($this, 'login_enqueue_scripts'));
73 +
74 + if (!defined('TWO_FACTOR_DISABLE') || !TWO_FACTOR_DISABLE) {
75 + add_filter('authenticate', array($this, 'tfaVerifyCodeAndUser'), 99999999999, 3);
76 + }
77 +
78 + if (file_exists(SIMBA_TFA_PLUGIN_DIR.'/updater/updater.php')) include_once(SIMBA_TFA_PLUGIN_DIR.'/updater/updater.php');
79 +
80 + if (defined('DOING_AJAX') && DOING_AJAX && defined('WP_ADMIN') && WP_ADMIN && !empty($_REQUEST['action']) && 'simbatfa-init-otp' == $_REQUEST['action']) {
81 + // Try to prevent PHP notices breaking the AJAX conversation
82 + $this->output_buffering = true;
83 + $this->logged = array();
84 + set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
85 + ob_start();
86 + }
87 +
88 + }
89 +
90 + public function get_php_errors($errno, $errstr, $errfile, $errline) {
91 + if (0 == error_reporting()) return true;
92 + $logline = $this->php_error_to_logline($errno, $errstr, $errfile, $errline);
93 + $this->logged[] = $logline;
94 + # Don't pass it up the chain (since it's going to be output to the user always)
95 + return true;
96 + }
97 +
98 + public function php_error_to_logline($errno, $errstr, $errfile, $errline) {
99 + switch ($errno) {
100 + case 1: $e_type = 'E_ERROR'; break;
101 + case 2: $e_type = 'E_WARNING'; break;
102 + case 4: $e_type = 'E_PARSE'; break;
103 + case 8: $e_type = 'E_NOTICE'; break;
104 + case 16: $e_type = 'E_CORE_ERROR'; break;
105 + case 32: $e_type = 'E_CORE_WARNING'; break;
106 + case 64: $e_type = 'E_COMPILE_ERROR'; break;
107 + case 128: $e_type = 'E_COMPILE_WARNING'; break;
108 + case 256: $e_type = 'E_USER_ERROR'; break;
109 + case 512: $e_type = 'E_USER_WARNING'; break;
110 + case 1024: $e_type = 'E_USER_NOTICE'; break;
111 + case 2048: $e_type = 'E_STRICT'; break;
112 + case 4096: $e_type = 'E_RECOVERABLE_ERROR'; break;
113 + case 8192: $e_type = 'E_DEPRECATED'; break;
114 + case 16384: $e_type = 'E_USER_DEPRECATED'; break;
115 + case 30719: $e_type = 'E_ALL'; break;
116 + default: $e_type = "E_UNKNOWN ($errno)"; break;
117 + }
118 +
119 + if (!is_string($errstr)) $errstr = serialize($errstr);
120 +
121 + if (0 === strpos($errfile, ABSPATH)) $errfile = substr($errfile, strlen(ABSPATH));
122 +
123 + return "PHP event: code $e_type: $errstr (line $errline, $errfile)";
124 +
125 + }
126 +
127 + public function init() {
128 + if ((!is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) && is_user_logged_in() && file_exists(SIMBA_TFA_PLUGIN_DIR.'/includes/tfa_frontend.php')) {
129 + $this->load_frontend();
130 + } else {
131 + add_shortcode('twofactor_user_settings', array($this, 'shortcode_when_not_logged_in'));
132 + }
133 + }
134 +
135 + public function admin_notice_insufficient_php() {
136 + $this->show_admin_warning('<strong>'.__('Higher PHP version required', 'updraftplus').'</strong><br> '.sprintf(__('The Two Factor Authentication plugin requires PHP version %s or higher - your current version is only %s.', SIMBA_TFA_TEXT_DOMAIN), $this->php_required, PHP_VERSION), 'error');
137 + }
138 +
139 + public function admin_notice_missing_mcrypt() {
140 + $this->show_admin_warning('<strong>'.__('PHP Mcrypt module required', 'updraftplus').'</strong><br> '.__('The Two Factor Authentication plugin requires the PHP mcrypt module to be installed. Please ask your web hosting company to install it.', SIMBA_TFA_TEXT_DOMAIN), 'error');
141 + }
142 +
143 + public function show_admin_warning($message, $class = "updated") {
144 + echo '<div class="tfamessage '.$class.'">'."<p>$message</p></div>";
145 + }
146 +
147 + public function getTFA() {
148 + if (!class_exists('HOTP')) require_once(SIMBA_TFA_PLUGIN_DIR.'/hotp-php-master/hotp.php');
149 + if (!class_exists('Base32')) require_once(SIMBA_TFA_PLUGIN_DIR.'/Base32/Base32.php');
150 + if (!class_exists('Simba_TFA')) require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/class.TFA.php');
77 151
78 - if (!empty($abort)) return;
152 + $tfa = new Simba_TFA(new Base32(), new HOTP());
79 153
80 - // Menu entries
81 - add_action('admin_menu', array($this, 'menu_entry_for_admin'));
82 - add_action('admin_menu', array($this, 'menu_entry_for_user'));
83 - add_action('network_admin_menu', array($this, 'menu_entry_for_user'));
154 + return $tfa;
155 + }
156 +
157 + // "Shared" - i.e. could be called from either front-end or back-end
158 + public function shared_ajax() {
159 + if (empty($_POST['subaction']) || empty($_POST['nonce']) || !is_user_logged_in() || !wp_verify_nonce($_POST['nonce'], 'tfa_shared_nonce')) die('Security check (3).');
160 +
161 + if ($_POST['subaction'] == 'refreshotp') {
162 +
163 + global $current_user;
164 +
165 + $tfa_priv_key_64 = get_user_meta($current_user->ID, 'tfa_priv_key_64', true);
166 +
167 + if (!$tfa_priv_key_64) {
168 + echo json_encode(array('code' => ''));
169 + die;
170 + }
171 +
172 + echo json_encode(array('code' => $this->getTFA()->generateOTP($current_user->ID, $tfa_priv_key_64)));
173 + exit;
174 + }
175 +
176 + }
177 +
178 + public function tfaInitLogin() {
179 +
180 + if (empty($_POST['user'])) die('Security check (2).');
181 +
182 + if (defined('TWO_FACTOR_DISABLE') && TWO_FACTOR_DISABLE) {
183 + $res = false;
184 + } else {
185 + $tfa = $this->getTFA();
186 + $res = $tfa->preAuth(array('log' => (string)$_POST['user']));
187 + }
188 +
189 + $results = array('jsonstarter' => 'justhere', 'status' => $res);
190 +
191 + if (!empty($this->output_buffering)) {
192 + if (!empty($this->logged)) {
193 + $results['php_output'] = $this->logged;
194 + }
195 + restore_error_handler();
196 + $buffered = ob_get_clean();
197 + if ($buffered) $results['extra_output'] = $buffered;
198 + }
199 +
200 + echo json_encode($results);
201 + exit;
202 + }
203 +
204 +
205 + // Here's where the login action happens. Called on the 'authenticate' action.
206 + public function tfaVerifyCodeAndUser($user, $username, $password) {
207 +
208 + $tfa = $this->getTFA();
84 209
85 - // Add settings link in plugin list
86 - $plugin = plugin_basename(__FILE__);
87 - add_filter("plugin_action_links_$plugin", array($this, 'add_plugin_settings_link'));
88 - add_filter("network_admin_plugin_action_links_$plugin", array($this, 'add_plugin_settings_link'));
210 + if (is_wp_error($user)) return $user;
211 +
212 + $params = $_POST;
213 + $params['log'] = $username;
214 + $params['caller'] = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['REQUEST_URI'];
89 215
90 - $this->set_user_settings_page_slug('two-factor-auth-user');
216 + $code_ok = $tfa->authUserFromLogin($params);
91 217
92 - $this->set_plugin_translate_url('https://translate.wordpress.org/projects/wp-plugins/two-factor-authentication/');
218 + if (is_wp_error($code_ok)) return $code_ok;
219 +
220 + if (!$code_ok) return new WP_Error('authentication_failed', '<strong>'.__('Error:', SIMBA_TFA_TEXT_DOMAIN).'</strong> '.__('The one-time password (TFA code) you entered was incorrect.', SIMBA_TFA_TEXT_DOMAIN));
93 221
94 - if (is_multisite() && function_exists('switch_to_blog')) {
95 - $main_site_id = function_exists('get_main_site_id') ? get_main_site_id() : 1;
96 - switch_to_blog($main_site_id);
222 + if ($user) return $user;
223 +
224 + return wp_authenticate_username_password(null, $username, $password);
225 + }
226 +
227 + public function tfaRegisterTwoFactorAuthSettings()
228 + {
229 + global $wp_roles;
230 + if (!isset($wp_roles))
231 + $wp_roles = new WP_Roles();
232 +
233 + foreach($wp_roles->role_names as $id => $name)
234 + {
235 + register_setting('tfa_user_roles_group', 'tfa_'.$id);
236 + register_setting('tfa_user_roles_required_group', 'tfa_required_'.$id);
97 237 }
98 - $this->set_site_wide_administration_url(admin_url('options-general.php?page=two-factor-auth'));
99 - if (is_multisite() && function_exists('restore_current_blog')) restore_current_blog();
100 238
101 - $this->set_premium_version_url('https://www.simbahosting.co.uk/s3/product/two-factor-authentication/');
102 - $this->set_faq_url('https://wordpress.org/plugins/two-factor-authentication/#faq');
103 - parent::__construct();
239 + register_setting('tfa_user_roles_required_group', 'tfa_requireafter');
240 + register_setting('simba_tfa_default_hmac_group', 'tfa_default_hmac');
241 + register_setting('tfa_xmlrpc_status_group', 'tfa_xmlrpc_on');
242 + }
243 +
244 + public function tfaListEnableRadios($user_id, $long_label = false)
245 + {
246 + if(!$user_id)
247 + return;
248 +
249 + $setting = get_user_meta($user_id, 'tfa_enable_tfa', true);
250 + $setting = !$setting ? false : $setting;
104 251
252 + $tfa = $this->getTFA();
253 +
254 + if ($tfa->isRequiredForUser($user_id)) {
255 + $requireafter = absint($this->get_option('tfa_requireafter'));
256 +
257 + echo '<p class="tfa_required_warning" style="font-weight:bold; font-style:italics;">'.sprintf(__('N.B. This site is configured to forbid you to log in if you disable two-factor authentication after your account is %d days old', SIMBA_TFA_TEXT_DOMAIN), $requireafter).'</p>';
258 + }
259 +
260 + $tfa_enabled_label = ($long_label) ? __('Enable two-factor authentication', SIMBA_TFA_TEXT_DOMAIN) : __('Enabled', SIMBA_TFA_TEXT_DOMAIN);
261 + $tfa_disabled_label = ($long_label) ? __('Disable two-factor authentication', SIMBA_TFA_TEXT_DOMAIN) : __('Disabled', SIMBA_TFA_TEXT_DOMAIN);
262 +
263 + print '<input type="radio" class="tfa_enable_radio" id="tfa_enable_tfa_true" name="tfa_enable_tfa" value="true" '.($setting == true ? 'checked="checked"' :'').'> <label class="tfa_enable_radio_label" for="tfa_enable_tfa_true">'.apply_filters('simbatfa_radiolabel_enabled', $tfa_enabled_label, $long_label).'</label> <br>';
264 +
265 + print '<input type="radio" class="tfa_enable_radio" id="tfa_enable_tfa_false" name="tfa_enable_tfa" value="false" '.($setting == false ? 'checked="checked"' :'').'> <label class="tfa_enable_radio_label" for="tfa_enable_tfa_false">'.apply_filters('simbatfa_radiolabel_disabled', $tfa_disabled_label, $long_label).'</label> <br>';
105 266 }
106 -
107 - /**
108 - * Runs upon the WP filters plugin_action_links_(plugin) and network_plugin_action_links_(plugin)
109 - *
110 - * @param Array $links
111 - *
112 - * @return Array
113 - */
114 - public function add_plugin_settings_link($links) {
115 - if (is_multisite()) {
116 - $main_site_id = function_exists('get_main_site_id') ? get_main_site_id() : 1;
117 - switch_to_blog($main_site_id);
118 - $link = $this->get_settings_link();
119 - restore_current_blog();
120 - array_unshift($links, $link);
121 - } else {
122 - $link = $this->get_settings_link();
123 - array_unshift($links, $link);
124 - }
125 267
126 - $link2 = '<a href="admin.php?page=two-factor-auth-user">'.__('User settings', 'two-factor-authentication').'</a>';
127 - array_unshift($links, $link2);
268 +
269 + public function tfaListAlgorithmRadios($user_id)
270 + {
271 + if(!$user_id) return;
272 +
273 + $types = array('totp' => __('TOTP (time based - most common algorithm; used by Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN), 'hotp' => __('HOTP (event based)', SIMBA_TFA_TEXT_DOMAIN));
128 274
129 - return $links;
275 + $setting = get_user_meta($user_id, 'tfa_algorithm_type', true);
276 + $setting = $setting === false || !$setting ? 'totp' : $setting;
277 +
278 + foreach($types as $id => $name) {
279 + print '<input type="radio" id="tfa_algorithm_type_'.esc_attr($id).'" name="tfa_algorithm_type" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> <label for="tfa_algorithm_type_'.esc_attr($id).'">'.$name."</label><br>\n";
280 + }
130 281 }
131 282
132 - /**
133 - * Get 2FA settings anchor tag link.
134 - *
135 - * @return string 2FA settings anchor tag link.
136 - */
137 - private function get_settings_link() {
138 - return '<a href="'.admin_url('options-general.php').'?page=two-factor-auth">'.__('Plugin settings', 'two-factor-authentication').'</a>';
283 + public function get_option($key) {
284 + if (!is_multisite()) return get_option($key);
285 + switch_to_blog(1);
286 + $v = get_option($key);
287 + restore_current_blog();
288 + return $v;
139 289 }
140 -
141 - /**
142 - * Runs upon the WP actions admin_menu and network_admin_menu
143 - */
144 - public function menu_entry_for_user() {
290 +
291 + public function tfaListUserRolesCheckboxes()
292 + {
293 +
294 + if (is_multisite()) {
295 + // Not a real WP role; needs separate handling
296 + $id = '_super_admin';
297 + $name = __('Multisite Super Admin', SIMBA_TFA_TEXT_DOMAIN);
298 + $setting = $this->get_option('tfa_'.$id);
299 + $setting = $setting === false || $setting ? 1 : 0;
300 +
301 + print '<input type="checkbox" id="tfa_'.$id.'" name="tfa_'.$id.'" value="1" '.($setting ? 'checked="checked"' :'').'> <label for="tfa_'.$id.'">'.htmlspecialchars($name)."</label><br>\n";
302 + }
303 +
304 + global $wp_roles;
305 + if (!isset($wp_roles)) $wp_roles = new WP_Roles();
145 306
146 - global $current_user;
147 - if ($this->is_activated_for_user($current_user->ID)) {
148 - add_menu_page(__('Two Factor Authentication', 'two-factor-authentication'), __('Two Factor Auth', 'two-factor-authentication'), 'read', 'two-factor-auth-user', array($this, 'show_dashboard_user_settings_page'), $this->includes_url().'/tfa_admin_icon_16x16.png', 72);
307 + foreach($wp_roles->role_names as $id => $name)
308 + {
309 + $setting = $this->get_option('tfa_'.$id);
310 + $setting = $setting === false || $setting ? 1 : 0;
311 +
312 + print '<input type="checkbox" id="tfa_'.$id.'" name="tfa_'.$id.'" value="1" '.($setting ? 'checked="checked"' :'').'> <label for="tfa_'.$id.'">'.htmlspecialchars($name)."</label><br>\n";
149 313 }
314 +
150 315 }
151 -
152 - /**
153 - * Runs upon the WP action admin_menu
154 - */
155 - public function menu_entry_for_admin() {
316 +
317 + public function tfaListDefaultHMACRadios()
318 + {
319 + $tfa = $this->getTFA();
320 + $setting = $this->get_option('tfa_default_hmac');
321 + $setting = $setting === false || !$setting ? $tfa->default_hmac : $setting;
156 322
157 - $skip_adding_options_menu_entry = (is_multisite() && (!is_super_admin() || !is_main_site()));
323 + $types = array('totp' => __('TOTP (time based - most common algorithm; used by Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN), 'hotp' => __('HOTP (event based)', SIMBA_TFA_TEXT_DOMAIN));
158 324
159 - $skip_adding_options_menu_entry = apply_filters('simba_tfa_skip_adding_options_menu_entry', $skip_adding_options_menu_entry);
325 + foreach($types as $id => $name)
326 + print '<input type="radio" id="tfa_default_hmac_'.esc_attr($id).'" name="tfa_default_hmac" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> '.'<label for="tfa_default_hmac_'.esc_attr($id).'">'."$name</label><br>\n";
327 + }
328 +
329 + public function tfaListXMLRPCStatusRadios()
330 + {
331 + $tfa = $this->getTFA();
332 + $setting = $this->get_option('tfa_xmlrpc_on');
333 + $setting = $setting === false || !$setting ? 0 : 1;
160 334
161 - if ($skip_adding_options_menu_entry) return;
335 + $types = array(
336 + '0' => __('Do not require 2FA over XMLRPC (best option if you must use XMLRPC and your client does not support 2FA)', SIMBA_TFA_TEXT_DOMAIN),
337 + '1' => __('Do require 2FA over XMLRPC (best option if you do not use XMLRPC or are unsure)', SIMBA_TFA_TEXT_DOMAIN)
338 + );
162 339
340 + foreach($types as $id => $name)
341 + print '<input type="radio" name="tfa_xmlrpc_on" id="tfa_xmlrpc_on_'.$id.'" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> <label for="tfa_xmlrpc_on_'.$id.'">'.$name."</label><br>\n";
342 + }
343 +
344 + public function tfaShowAdminSettingsPage()
345 + {
346 + $tfa = $this->getTFA();
347 + require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/admin_settings.php');
348 + }
349 +
350 + public function tfaShowUserSettingsPage()
351 + {
352 + $tfa = $this->getTFA();
353 + include SIMBA_TFA_PLUGIN_DIR.'/includes/user_settings.php';
354 + }
355 +
356 + public function admin_menu()
357 + {
358 + $tfa = $this->getTFA();
359 +
360 + global $current_user;
361 + if(!$tfa->isActivatedForUser($current_user->ID)) return;
362 + add_menu_page(__('Two Factor Authentication', SIMBA_TFA_TEXT_DOMAIN), __('Two Factor Auth', SIMBA_TFA_TEXT_DOMAIN), 'read', 'two-factor-auth-user', array($this, 'tfaShowUserSettingsPage'), SIMBA_TFA_PLUGIN_URL.'/img/tfa_admin_icon_16x16.png', 72);
363 + }
364 +
365 + public function menu_entry_for_admin() {
366 +
367 + // On multisite, only show the entry on site ID 1 - to ensure options get saved in the right place.
368 + global $current_site, $wpdb;
369 + // $current_site is not the right way to do this - it is internal, and could be anything
370 + if (is_multisite() && (!is_super_admin() || !is_object($wpdb) || !isset($wpdb->blogid) || 1 != $wpdb->blogid)) return;
371 +
372 + add_action( 'admin_init', array($this, 'tfaRegisterTwoFactorAuthSettings' ));
373 +
163 374 add_options_page(
164 - __('Two Factor Authentication', 'two-factor-authentication'),
165 - __('Two Factor Authentication', 'two-factor-authentication'),
166 - $this->get_management_capability(),
375 + __('Two Factor Authentication', SIMBA_TFA_TEXT_DOMAIN),
376 + __('Two Factor Authentication', SIMBA_TFA_TEXT_DOMAIN),
377 + 'manage_options',
167 378 'two-factor-auth',
168 - array($this, 'show_admin_settings_page')
379 + array($this, 'tfaShowAdminSettingsPage')
169 380 );
170 381 }
171 -
172 - /**
173 - * Include the admin settings page code
174 - */
175 - public function show_admin_settings_page() {
176 382
177 - if (!is_admin() || !current_user_can($this->get_management_capability())) return;
383 + public function addPluginSettingsLink($links)
384 + {
385 + if (!is_network_admin()) {
386 + $link = '<a href="options-general.php?page=two-factor-auth">'.__('Plugin settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
387 + array_unshift($links, $link);
388 + } else {
389 + switch_to_blog(1);
390 + $link = '<a href="'.admin_url('options-general.php').'?page=two-factor-auth">'.__('Plugin settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
391 + restore_current_blog();
392 + array_unshift($links, $link);
393 + }
178 394
179 - $admin_settings_links = array();
180 - if (!class_exists('Simba_Two_Factor_Authentication_Premium')) {
181 - $admin_settings_links[] = array(
182 - 'url' => 'https://www.simbahosting.co.uk/s3/product/two-factor-authentication/',
183 - 'title' => __('Premium version', 'two-factor-authentication'),
184 - );
395 + $link2 = '<a href="admin.php?page=two-factor-auth-user">'.__('User settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
396 + array_unshift($links, $link2);
397 +
398 + return $links;
399 + }
400 +
401 + public function check_possible_reset() {
402 + if(!empty($_GET['simbatfa_priv_key_reset']) && !empty($_REQUEST['nonce']) && wp_verify_nonce($_REQUEST['nonce'], 'simbatfa_reset_private_key'))
403 + {
404 + $this->reset_private_key_and_emergency_codes();
405 +// if (empty($_REQUEST['noredirect'])) exit;
406 + exit;
185 407 }
186 - $simba_tfa_support_url = apply_filters('simba_tfa_support_url', 'https://wordpress.org/support/plugin/two-factor-authentication/');
408 +
409 + }
187 410
188 - $admin_settings_links[] = array(
189 - 'url' => $simba_tfa_support_url,
190 - 'title' => __('Support', 'two-factor-authentication'),
411 + public function reset_private_key_and_emergency_codes() {
412 + global $current_user;
413 + delete_user_meta($current_user->ID, 'tfa_priv_key_64');
414 + delete_user_meta($current_user->ID, 'simba_tfa_emergency_codes_64');
415 + if (empty($_REQUEST['noredirect'])) {
416 + wp_safe_redirect( admin_url('admin.php').'?page=two-factor-auth-user&settings-updated=1');
417 + } else {
418 + $url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . remove_query_arg(array('simbatfa_priv_key_reset', 'noredirect', 'nonce'));
419 +
420 + wp_redirect(esc_url_raw($url));
421 + }
422 + }
423 +
424 + public function reset_link($admin = true) {
425 +
426 + $url_base = ($admin) ? admin_url('admin.php').'?page=two-factor-auth-user&settings-updated=1' : (( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST']);
427 +
428 + $add_query_args = array(
429 + 'simbatfa_priv_key_reset' => 1,
191 430 );
431 + if (!$admin) $add_query_args['noredirect'] = 1;
432 +
433 + $url = $url_base.add_query_arg($add_query_args);
434 +
435 + $url = wp_nonce_url($url, 'simbatfa_reset_private_key', 'nonce');
436 +
437 + return '<a href="javascript:if(confirm(\''.__('Warning: if you reset this key you will have to update your apps with the new one. Are you sure you want this?', SIMBA_TFA_TEXT_DOMAIN).'\')){ window.location = \''.esc_js($url).'\'; }">'.__('Reset private key', SIMBA_TFA_TEXT_DOMAIN).'</a>';
438 +
439 + }
440 +
441 + public function footer() {
442 + $ajax_url = admin_url('admin-ajax.php');
443 + // It's possible that FORCE_ADMIN_SSL will make that SSL, whilst the user is on the front-end having logged in over non-SSL - and as a result, their login cookies won't get sent, and they're not registered as logged in.
444 + if (!is_admin() && substr(strtolower($ajax_url), 0, 6) == 'https:' && !is_ssl()) {
445 + $also_try = 'http:'.substr($ajax_url, 6);
446 + }
447 + ?>
448 + <script>
449 + jQuery(document).ready(function($) {
450 + $('.simbaotp_qr_container').qrcode({
451 + "render": "image",
452 + "text": $('.simbaotp_qr_container:first').data('qrcode'),
453 + });
454 + $('.simbaotp_refresh').click(function(e) {
455 + e.preventDefault();
456 + $(".simba_current_otp").html('<em><?php echo esc_attr(__('Updating...', SIMBA_TFA_TEXT_DOMAIN));?></em>');
457 + $.post('<?php echo esc_js($ajax_url);?>', {
458 + action: "simbatfa_shared_ajax",
459 + subaction: "refreshotp",
460 + nonce: "<?php echo esc_js(wp_create_nonce("tfa_shared_nonce"));?>"
461 + }, function(response) {
462 + var got_code = '';
463 + try {
464 + var resp = $.parseJSON(response);
465 + got_code = resp.code;
466 + } catch(err) {
467 + <?php if (!isset($also_try)) { ?>
468 + alert("<?php echo esc_js(__('Response:', 'SIMBA_TFA_TEXT_DOMAIN')); ?> "+response);
469 + <?php } ?>
470 + console.log(response);
471 + console.log(err);
472 + }
473 + <?php
474 + if (isset($also_try)) {
475 + ?>
476 + $.post('<?php echo esc_js($also_try);?>', {
477 + action: "simbatfa_shared_ajax",
478 + subaction: "refreshotp",
479 + nonce: "<?php echo esc_js(wp_create_nonce("tfa_shared_nonce"));?>"
480 + }, function(response) {
481 + try {
482 + var resp = $.parseJSON(response);
483 + if (resp.code) {
484 + $(".simba_current_otp").html(resp.code);
485 + } else {
486 + console.log(response);
487 + console.log("TFA: no code found");
488 + }
489 + } catch(err) {
490 + alert("<?php echo esc_js(__('Response:', 'SIMBA_TFA_TEXT_DOMAIN')); ?> "+response);
491 + console.log(response);
492 + console.log(err);
493 + }
494 + });
495 + <?php } else { ?>
496 + if ('' != got_code) {
497 + $(".simba_current_otp").html(got_code);
498 + } else {
499 + console.log("TFA: no code found");
500 + }
501 + <?php } ?>
502 + });
503 + });
504 + });
505 + </script>
506 + <?php
507 + }
508 +
509 + public function print_private_keys($admin, $type = 'full', $user_id = false) {
510 +
511 + $tfa = $this->getTFA();
512 + global $current_user;
513 +
514 + if ($user_id == false) $user_id = $current_user->ID;
515 +
516 + $tfa_priv_key_64 = get_user_meta($user_id, 'tfa_priv_key_64', true);
517 + if(!$tfa_priv_key_64) $tfa_priv_key_64 = $tfa->addPrivateKey($user_id);
518 +
519 + $tfa_priv_key = trim($tfa->getPrivateKeyPlain($tfa_priv_key_64, $user_id));
520 +
521 + $tfa_priv_key_32 = Base32::encode($tfa_priv_key);
522 +
523 + if ('full' == $type) {
524 + ?>
525 + <strong><?php echo __('Private key (base 32 - used by Google Authenticator and Authy):', SIMBA_TFA_TEXT_DOMAIN);?></strong>
526 + <?php echo htmlspecialchars($tfa_priv_key_32); ?><br>
527 +
528 + <strong><?php echo __('Private key:', SIMBA_TFA_TEXT_DOMAIN);?></strong>
529 + <?php echo htmlspecialchars($tfa_priv_key); ?><br>
530 + <?php
531 + } elseif ('plain' == $type) {
532 + echo htmlspecialchars($tfa_priv_key);
533 + } elseif ('base32' == $type) {
534 + echo htmlspecialchars($tfa_priv_key_32);
535 + } elseif ('base64' == $type) {
536 + echo htmlspecialchars($tfa_priv_key_64);
537 + }
538 + }
539 +
540 + public function current_otp_code($tfa, $user_id = false) {
541 + global $current_user;
542 + if (false == $user_id) $user_id = $current_user->ID;
543 + $tfa_priv_key_64 = get_user_meta($user_id, 'tfa_priv_key_64', true);
544 + return '<span class="simba_current_otp">'.$tfa->generateOTP($user_id, $tfa_priv_key_64).'</span>';
545 + }
546 +
547 + public function add_footer($admin) {
548 + static $added_footer;
549 + if (empty($added_footer)) {
550 + $added_footer = true;
551 +// wp_enqueue_script('jquery');
552 + $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $this->version;
553 + $script_file = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? 'jquery.qrcode.js' : 'jquery.qrcode.min.js';
554 + wp_enqueue_script( 'jquery-qrcode', SIMBA_TFA_PLUGIN_URL.'/includes/jquery-qrcode/'.$script_file, array('jquery'), $script_ver);
555 + add_action( $admin ? 'admin_footer' : 'wp_footer' , array($this, 'footer'));
556 + }
557 + }
558 +
559 + public function current_codes_box($admin = true, $user_id = false) {
560 +
561 + global $current_user;
562 +
563 + if (false == $user_id) {
564 + $user_id = $current_user->ID;
565 + }
566 +
567 + $tfa = $this->getTFA();
568 +
569 + $this->add_footer($admin);
570 +
571 + $url = preg_replace('/^https?:\/\//', '', site_url());
192 572
193 - $admin_settings_links[] = array(
194 - 'url' => 'https://profiles.wordpress.org/davidanderson#content-plugins',
195 - 'title' => __('More free plugins', 'two-factor-authentication'),
573 + $tfa_priv_key_64 = get_user_meta($user_id, 'tfa_priv_key_64', true);
574 +
575 + if(!$tfa_priv_key_64) $tfa_priv_key_64 = $tfa->addPrivateKey($user_id);
576 +
577 + $tfa_priv_key = trim($tfa->getPrivateKeyPlain($tfa_priv_key_64, $user_id));
578 +
579 + $tfa_priv_key_32 = Base32::encode($tfa_priv_key);
580 +
581 + $algorithm_type = $tfa->getUserAlgorithm($user_id);
582 +
583 + if ($admin) {
584 + if ($current_user->ID == $user_id) {
585 + echo '<h2>'.__('Current codes', SIMBA_TFA_TEXT_DOMAIN).'</h2>';
586 + } else {
587 + $user = get_user_by('id', $user_id);
588 + $user_descrip = htmlspecialchars($user->user_nicename.' - '.$user->user_email);
589 + echo '<h2>'.sprintf(__('Current codes (login: %s)', SIMBA_TFA_TEXT_DOMAIN), $user_descrip).'</h2>';
590 + }
591 + } else {
592 +// echo '<h2>'.__('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' '.$this->reset_current_otp_link().'</h2>';
593 + }
594 +
595 + ?>
596 + <div class="postbox">
597 +
598 + <?php if ($admin) { ?>
599 + <h3 style="padding: 10px 6px 0px; margin:4px 0 0; cursor: default;">
600 + <span style="cursor: default;"><?php echo __('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' ';
601 + if ($current_user->ID == $user_id) { echo $this->reset_current_otp_link(); } ?>
602 + </span>
603 + <div class="inside">
604 + <p><strong style="font-size: 3em;"><?php echo $this->current_otp_code($tfa, $user_id); ?></strong></p>
605 + </div>
606 + </h3>
607 + <?php } else {
608 + ?>
609 + <div class="inside">
610 + <p class="simbatfa-frontend-current-otp" style="font-size: 1.5em; margin-top:6px;">
611 + <strong>
612 + <?php echo __('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' '.$this->reset_current_otp_link(); ?>
613 + </strong> :
614 +
615 + <span class="simba_current_otp"><?php print $tfa->generateOTP($user_id, $tfa_priv_key_64); ?></span>
616 +
617 + </p>
618 + </div>
619 +
620 + <?php } ?>
621 +
622 + <?php if ($admin) { ?>
623 + <h3 style="padding-left: 10px; cursor: default;">
624 + <span style="cursor: default;"><?php _e('QR code', SIMBA_TFA_TEXT_DOMAIN); ?></span>
625 + </h3>
626 + <?php } else {
627 + echo '<h2>'.__('QR code', SIMBA_TFA_TEXT_DOMAIN).'</h2>';
628 + } ?>
629 + <div class="inside">
630 + <p>
631 + <?php _e('For OTP apps that support scanning, scanning this code is the quickest way to set the app up (e.g. with Duo Mobile, Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN); ?>.
632 +
633 + <?php _e('You are currently using', SIMBA_TFA_TEXT_DOMAIN); ?> <?php print strtoupper($algorithm_type).', '.($algorithm_type == 'totp' ? __('a time based', SIMBA_TFA_TEXT_DOMAIN) : __('an event based', SIMBA_TFA_TEXT_DOMAIN)); ?> <?php _e('algorithm', SIMBA_TFA_TEXT_DOMAIN); ?>.
634 + </p>
635 + <p title="<?php echo sprintf(__("Private key: %s (base 32: %s)", SIMBA_TFA_TEXT_DOMAIN), $tfa_priv_key, $tfa_priv_key_32);?>">
636 + <?php $qr_url = $this->tfa_qr_code_url($algorithm_type, $url, $tfa_priv_key) ?>
637 + <div class="simbaotp_qr_container" data-qrcode="<?php echo esc_attr($qr_url); ?>"></div>
638 + </p>
639 + </div>
640 +
641 + <div class="inside">
642 +
643 + <h3 class="normal" style="cursor: default"><?php _e('Private key - always to be kept secret - type this into your app to set it up (instead of scanning the code)', SIMBA_TFA_TEXT_DOMAIN); ?></h3>
644 +
645 + <p>
646 + <?php
647 + $this->print_private_keys($admin, 'full', $user_id);
648 + if ($current_user->ID == $user_id) { echo $this->reset_link($admin);}
649 + ?>
650 + </p>
651 + </div>
652 +
653 + <?php
654 + if ($admin || apply_filters('simba_tfa_emergency_codes_user_settings', false, $user_id) !== false) {
655 + ?>
656 + <div class="inside">
657 +
658 + <h3 class="normal" style="cursor: default"><?php _e('Emergency codes', SIMBA_TFA_TEXT_DOMAIN); ?></h3>
659 +
660 + <p>
661 + <?php
662 + $default_text = '<a href="https://www.simbahosting.co.uk/s3/product/two-factor-authentication/">'.__('One-time emergency codes are a feature of the Premium version of this plugin.', SIMBA_TFA_TEXT_DOMAIN).'</a>';
663 + echo apply_filters('simba_tfa_emergency_codes_user_settings', $default_text, $user_id);
664 + ?>
665 + </p>
666 +
667 + </div>
668 +
669 + <?php } ?>
670 +
671 + </div>
672 + <?php
673 + }
674 +
675 + public function reset_current_otp_link($admin = true) {
676 + return '<a href="#" class="simbaotp_refresh">'.__('(update)', SIMBA_TFA_TEXT_DOMAIN).'</a>';
677 + }
678 +
679 + public function advanced_settings_box($submit_button_callback = false) {
680 + $tfa = $this->getTFA();
681 +
682 + global $current_user;
683 + $algorithm_type = $tfa->getUserAlgorithm($current_user->ID);
684 +
685 + ?>
686 + <h2><?php _e('Advanced settings', SIMBA_TFA_TEXT_DOMAIN); ?></h2>
687 +
688 + <div id="tfa_advanced_box" class="tfa_settings_form" style="margin-top: 20px;">
689 +
690 + <?php if (false === $submit_button_callback) { ?><form method="post" action="<?php print esc_url(add_query_arg('settings-updated', 'true', $_SERVER['REQUEST_URI'])); ?>"><?php } ?>
691 +
692 + <?php _e('Choose which algorithm for One Time Passwords you want to use.', SIMBA_TFA_TEXT_DOMAIN); ?>
693 + <p>
694 + <?php
695 + $this->tfaListAlgorithmRadios($current_user->ID);
696 + if($algorithm_type == 'hotp')
697 + {
698 + $counter = $tfa->getUserCounter($current_user->ID);
699 + print '<br>'.__('Your counter on the server is currently on', SIMBA_TFA_TEXT_DOMAIN).': '.$counter;
700 + }
701 + ?>
702 +
703 + </p>
704 + <?php if (false === $submit_button_callback) { submit_button(); echo '</form>'; } else { call_user_func($submit_button_callback); } ?>
705 + </div>
706 + <?php
707 + }
708 +
709 + public function login_enqueue_scripts()
710 + {
711 +
712 + if(isset($_GET['action']) && $_GET['action'] != 'logout' && $_GET['action'] != 'login') return;
713 +
714 + // Prevent cacheing when in debug mode
715 + $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $this->version;
716 +
717 + wp_enqueue_script( 'tfa-ajax-request', SIMBA_TFA_PLUGIN_URL . '/includes/tfa.js', array( 'jquery' ), $script_ver );
718 + $localize = array(
719 + 'ajaxurl' => admin_url('admin-ajax.php'),
720 + 'click_to_enter_otp' => __("Click to enter One Time Password", SIMBA_TFA_TEXT_DOMAIN),
721 + 'enter_username_first' => __('You have to enter a username first.', SIMBA_TFA_TEXT_DOMAIN),
722 + 'otp' => __("One Time Password (i.e. 2FA)", SIMBA_TFA_TEXT_DOMAIN),
723 + 'otp_login_help' => __('(check your OTP app to get this password)', SIMBA_TFA_TEXT_DOMAIN),
724 + 'nonce' => wp_create_nonce("simba_tfa_loginform_nonce")
196 725 );
726 + // Spinner exists since WC 3.8. Use the proper functions to avoid SSL warnings.
727 + if (file_exists(ABSPATH.'wp-admin/images/spinner.gif')) {
728 + $localize['spinnerimg'] = admin_url('images/spinner.gif');
729 + } elseif (file_exists(ABSPATH.WPINC.'/images/spinner.gif')) {
730 + $localize['spinnerimg'] = includes_url('images/spinner.gif');
731 + }
732 + wp_localize_script( 'tfa-ajax-request', 'simba_tfasettings', $localize);
733 + }
734 +
735 + public function tfaShowHOTPOffSyncMessage()
736 + {
737 + global $current_user;
738 + $is_off_sync = get_user_meta($current_user->ID, 'tfa_hotp_off_sync', true);
739 + if(!$is_off_sync)
740 + return;
197 741
198 - $admin_settings_links[] = array(
199 - 'url' => 'http://updraftplus.com',
200 - 'title' => 'UpdraftPlus - '.__('WordPress backups', 'two-factor-authentication'),
201 - );
742 + ?>
743 + <div class="error">
744 + <h3><?php _e('Two Factor Authentication re-sync needed', SIMBA_TFA_TEXT_DOMAIN);?></h3>
745 + <p>
746 + <?php _e('You need to resync your device for Two Factor Authentication since the OTP you last used is many steps ahead of the server.', SIMBA_TFA_TEXT_DOMAIN); ?>
747 + <br>
748 + <?php _e('Please re-sync or you might not be able to log in if you generate more OTPs without logging in.', SIMBA_TFA_TEXT_DOMAIN);?>
749 + <br><br>
750 + <a href="admin.php?page=two-factor-auth-user&warning_button_clicked=1" class="button"><?php _e('Click here and re-scan the QR-Code', SIMBA_TFA_TEXT_DOMAIN);?></a>
751 + </p>
752 + </div>
202 753
203 - $admin_settings_links[] = array(
204 - 'url' => 'https://www.simbahosting.co.uk/s3/shop/',
205 - 'title' => __('More premium plugins', 'two-factor-authentication'),
206 - );
754 + <?php
207 755
208 - $admin_settings_links[] = array(
209 - 'url' => 'https://twitter.com/updraftplus',
210 - 'title' => __('Twitter', 'two-factor-authentication'),
211 - );
756 + }
757 +
758 + // QR code image
759 + public function tfa_qr_code_url($algorithm_type, $url, $tfa_priv_key, $user_id = false){
760 + global $current_user;
212 761
213 - $admin_settings_links[] = array(
214 - 'url' => 'https://david.dw-perspective.org.uk',
215 - 'title' => __("Lead developer's homepage", 'two-factor-authentication'),
216 - );
762 + if ($user_id == false) {
763 + $user = $current_user;
764 + } else {
765 + $user = get_user_by('id', $user_id);
766 + }
767 +
768 + $tfa = $this->getTFA();
769 +
770 + // Old
771 +// $encode = 'otpauth://'.$algorithm_type.'/'.$url.':%2520'.$user->user_login.'%3Fsecret%3D'.Base32::encode($tfa_priv_key).'%26issuer='.$url.'%26counter='.$tfa->getUserCounter($user->ID);
772 +//
773 +// $ret = '<img src="https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl='.$encode.'">';
217 774
218 - $admin_settings_links = apply_filters('simba_tfa_admin_settings_links', $admin_settings_links);
775 + // New
776 + $encode = 'otpauth://'.$algorithm_type.'/'.$url.':'.$user->user_login.'?secret='.Base32::encode($tfa_priv_key).'&issuer='.$url.'&counter='.$tfa->getUserCounter($user->ID);
219 777
220 - $this->include_template('admin-settings.php', array(
221 - 'settings_page_heading' => $this->get_settings_page_heading(),
222 - 'admin_settings_links' => $admin_settings_links,
223 - ));
778 +// $ret = '<script>var qr_details = "'.$encode.'"</script>';
779 +
780 + return $encode;
224 781 }
225 -
226 - /**
227 - * Runs conditionally on the WP action all_admin_notices
228 - */
229 - public function admin_notice_insufficient_php() {
230 - $this->show_admin_warning('<strong>'.__('Higher PHP version required', 'two-factor-authentication').'</strong><br> '.sprintf(__('The Two Factor Authentication plugin requires PHP version %s or higher - your current version is only %s.', 'two-factor-authentication'), self::PHP_REQUIRED, PHP_VERSION), 'error');
782 +
783 + public function settings_intro_notices() {
784 + ?>
785 + <p class="simba_tfa_personal_settings_notice simba_tfa_intro_notice">
786 + <?php echo __('These are your personal settings.', SIMBA_TFA_TEXT_DOMAIN).' '.__('Nothing you change here will have any effect on other users.', SIMBA_TFA_TEXT_DOMAIN); ?>
787 + </p>
788 + <p class="simba_tfa_verify_tfa_notice simba_tfa_intro_notice"><strong>
789 + <?php _e('If you activate two-factor authentication, then verify that your two-factor application is showing the same One Time Password as shown on this page before you log out.', SIMBA_TFA_TEXT_DOMAIN); ?></strong> <?php if (current_user_can('manage_options')) { ?><a href="https://wordpress.org/plugins/two-factor-authentication/faq/"><?php _e('You should also bookmark the FAQs, which explain how to de-activate the plugin even if you cannot log in.', SIMBA_TFA_TEXT_DOMAIN);?></a><?php } ?>
790 + </p>
791 + <?php
231 792 }
232 -
233 - /**
234 - * Runs conditionally on the WP action all_admin_notices
235 - */
236 - public function admin_notice_missing_mcrypt_and_openssl() {
237 - $this->show_admin_warning('<strong>'.__('PHP OpenSSL or mcrypt module required', 'two-factor-authentication').'</strong><br> '.__('The Two Factor Authentication plugin requires either the PHP openssl (preferred) or mcrypt module to be installed. Please ask your web hosting company to install one of them.', 'two-factor-authentication'), 'error');
238 - }
239 -
240 - /**
241 - * Run upon the WP plugins_loaded action. This method is called even if main loading aborts - so don't put anything else in it (use a separate method).
242 - */
243 - public function plugins_loaded_load_textdomain() {
793 +
794 + public function plugins_loaded() {
244 795 load_plugin_textdomain(
245 - 'two-factor-authentication',
796 + SIMBA_TFA_TEXT_DOMAIN,
246 797 false,
247 - dirname(plugin_basename(__FILE__)).'/languages/'
798 + dirname( plugin_basename( __FILE__ ) ) . '/languages/'
248 799 );
249 -
250 - $this->set_settings_page_heading(sprintf(__('Two Factor Authentication (Version: %s) - Admin Settings', 'two-factor-authentication'), $this->version));
251 -
252 800 }
253 -}
254 -endif;
255 801
256 -$GLOBALS['simba_two_factor_authentication'] = new Simba_Two_Factor_Authentication_Plugin();
802 + public function load_frontend() {
803 + if (!class_exists('TFA_Frontend')) require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/tfa_frontend.php');
804 + if (empty($this->frontend)) $this->frontend = new TFA_Frontend($this);
805 + return $this->frontend;
806 + }
257 807
258 -if (file_exists(__DIR__.'/simba-tfa/premium/loader.php') && empty($GLOBALS['simba_two_factor_authentication_premium'])) {
259 - if (!class_exists('Simba_Two_Factor_Authentication_Premium')) include_once(__DIR__.'/simba-tfa/premium/loader.php');
808 + public function shortcode_when_not_logged_in() {
809 + return '';
810 + }
260 811
261 - $GLOBALS['simba_two_factor_authentication_premium'] = new Simba_Two_Factor_Authentication_Premium($GLOBALS['simba_two_factor_authentication']);
812 + // WooCommerce login form
813 + public function woocommerce_before_customer_login_form() {
814 + $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $this->version;
815 + wp_enqueue_script( 'tfa-wc-ajax-request', SIMBA_TFA_PLUGIN_URL.'/includes/wooextend.js', array('jquery'), $script_ver);
816 + $localize = array(
817 + 'ajaxurl' => admin_url('admin-ajax.php'),
818 + 'click_to_enter_otp' => __("Enter One Time Password (if you have one)", SIMBA_TFA_TEXT_DOMAIN),
819 + 'enter_username_first' => __('You have to enter a username first.', SIMBA_TFA_TEXT_DOMAIN),
820 + 'otp' => __("One Time Password", SIMBA_TFA_TEXT_DOMAIN),
821 + 'nonce' => wp_create_nonce("simba_tfa_loginform_nonce"),
822 + 'otp_login_help' => __('(check your OTP app to get this password)', SIMBA_TFA_TEXT_DOMAIN),
823 + );
824 + // Spinner exists since WC 3.8. Use the proper functions to avoid SSL warnings.
825 + if (file_exists(ABSPATH.'wp-admin/images/spinner.gif')) {
826 + $localize['spinnerimg'] = admin_url('images/spinner.gif');
827 + } elseif (file_exists(ABSPATH.WPINC.'/images/spinner.gif')) {
828 + $localize['spinnerimg'] = includes_url('images/spinner.gif');
829 + }
262 830
263 - if (!class_exists('Updraft_Manager_Updater_1_8')) require_once(plugin_dir_path(__FILE__).'vendor/davidanderson684/simba-plugin-manager-updater/class-udm-updater.php');
831 + wp_localize_script( 'tfa-wc-ajax-request', 'simbatfa_wc_settings', $localize);
832 + }
264 833
265 - try {
266 - new Updraft_Manager_Updater_1_8('https://www.simbahosting.co.uk/s3', 1, 'two-factor-authentication-premium/two-factor-login.php', array('require_login' => false));
267 - } catch (Exception $e) {
268 - error_log($e->getMessage());
269 - }
270 834 }
835 +
836 +$simba_two_factor_authentication = new Simba_Two_Factor_Authentication();