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 | includes/tfa_frontend.php +282 -204 1.12.21.2.6 View file →
@@ -1,204 +1,282 @@
1 -<?php
2 -if (!defined('ABSPATH')) die('Access denied.');
3 -
4 -class TFA_Frontend {
5 -
6 - private $mother;
7 -
8 - /**
9 - * Class constructor
10 - *
11 - * @param Object $mother
12 - */
13 - public function __construct($mother) {
14 -
15 - $this->mother = $mother;
16 - add_action('wp_ajax_tfa_frontend', array($this, 'ajax'));
17 - add_shortcode('twofactor_user_settings', array($this, 'tfa_user_settings_front'));
18 - }
19 -
20 - /**
21 - * Runs upon the WP action wp_ajax_tfa_frontend
22 - *
23 - * @uses die()
24 - */
25 - public function ajax() {
26 - $totp_controller = $this->mother->get_totp_controller();
27 - global $current_user;
28 -
29 - $return_array = array();
30 -
31 - if (empty($_POST) || empty($_POST['subaction']) || !isset($_POST['nonce']) || !is_user_logged_in() || !wp_verify_nonce($_POST['nonce'], 'tfa_frontend_nonce')) die('Security check');
32 -
33 - if ('savesettings' == $_POST['subaction']) {
34 - if (empty($_POST['settings']) || !is_string($_POST['settings'])) die;
35 -
36 - parse_str(stripslashes($_POST['settings']), $posted_settings);
37 -
38 - if (isset($posted_settings['tfa_algorithm_type'])) {
39 - $old_algorithm = $totp_controller->get_user_otp_algorithm($current_user->ID);
40 -
41 - if ($old_algorithm != $posted_settings['tfa_algorithm_type'])
42 - $totp_controller->changeUserAlgorithmTo($current_user->ID, $posted_settings['tfa_algorithm_type']);
43 -
44 - //Re-fetch the algorithm type, url and private string
45 - $variables = $this->tfa_fetch_assort_vars();
46 -
47 - $return_array['qr'] = $this->mother->tfa_qr_code_url($variables['algorithm_type'], $variables['url'], $variables['tfa_priv_key']);
48 - $return_array['al_type_disp'] = $this->tfa_algorithm_info($variables['algorithm_type']);
49 - }
50 -
51 - if (isset($posted_settings['tfa_enable_tfa'])) {
52 -
53 - $allow_enable_or_disable = false;
54 -
55 - if (empty($posted_settings['require_current']) || !$posted_settings['tfa_enable_tfa']) {
56 - $allow_enable_or_disable = true;
57 - } else {
58 -
59 - if (!isset($posted_settings['tfa_enable_current']) || '' == $posted_settings['tfa_enable_current']) {
60 - $return_array['message'] = __('To enable TFA, you must enter the current code.', 'two-factor-authentication');
61 - $return_array['error'] = 'code_absent';
62 - } else {
63 - // Third parameter: don't allow emergency codes
64 - if ($totp_controller->check_code_for_user($current_user->ID, $posted_settings['tfa_enable_current'], false)) {
65 - $allow_enable_or_disable = true;
66 - } else {
67 - $return_array['error'] = 'code_wrong';
68 - $return_array['message'] = __('The TFA code you entered was incorrect.', 'two-factor-authentication');
69 - }
70 - }
71 -
72 - }
73 -
74 - if ($allow_enable_or_disable) $this->mother->change_tfa_enabled_status($current_user->ID, $posted_settings['tfa_enable_tfa']);
75 - }
76 -
77 - $return_array['result'] = 'saved';
78 -
79 - echo json_encode($return_array);
80 - }
81 -
82 - die;
83 - }
84 -
85 - /**
86 - * Make the algorithm information string easier to update
87 - *
88 - * @param String $algorithm_type - totp|hotp
89 - */
90 - public function tfa_algorithm_info($algorithm_type) {
91 - $al_type_disp = strtoupper($algorithm_type);
92 - $al_type_desc = ($algorithm_type == 'totp' ? __('a time based', 'two-factor-authentication') : __('an event based', 'two-factor-authentication'));
93 -
94 - return array('disp' => $al_type_disp, 'desc' => $al_type_desc);
95 - }
96 -
97 - /**
98 - * Make the assorted required variables more accessible for ajax
99 - *
100 - * Returns: Site URL, private key, emergency codes, algorithm type
101 - *
102 - * @return Array
103 - */
104 - public function tfa_fetch_assort_vars() {
105 - global $current_user;
106 - $totp_controller = $this->mother->get_totp_controller();
107 -
108 - $url = preg_replace('/^https?:\/\//i', '', site_url());
109 -
110 - $tfa_priv_key_64 = get_user_meta($current_user->ID, 'tfa_priv_key_64', true);
111 -
112 - if (!$tfa_priv_key_64) $tfa_priv_key_64 = $totp_controller->addPrivateKey($current_user->ID);
113 -
114 - $tfa_priv_key = trim($totp_controller->getPrivateKeyPlain($tfa_priv_key_64, $current_user->ID));
115 -
116 - $algorithm_type = $totp_controller->get_user_otp_algorithm($current_user->ID);
117 -
118 - return apply_filters('simba_tfa_fetch_assort_vars', array(
119 - 'url' => $url,
120 - 'tfa_priv_key_64' => $tfa_priv_key_64,
121 - 'tfa_priv_key' => $tfa_priv_key,
122 - 'emergency_str' => '<em>'.__('No emergency codes left. Sorry.', 'two-factor-authentication').'</em>',
123 - 'algorithm_type' => $algorithm_type
124 - ), $totp_controller, $current_user);
125 - }
126 -
127 - /**
128 - * Paints out the 'save settings' button
129 - */
130 - public function save_settings_button() {
131 - echo '<button style="margin-left: 4px;margin-bottom: 10px" class="simbatfa_settings_save button button-primary">'.__('Save Settings', 'two-factor-authentication').'</button>';
132 - }
133 -
134 - /**
135 - * Paint output for the TFA on/off radio
136 - *
137 - * @param String $style - valid values are 'show_current' and 'require_current'
138 - */
139 - public function settings_enable_or_disable_output($style = 'show_current') {
140 - $this->save_settings_javascript_output();
141 - global $current_user;
142 - ?>
143 - <div class="simbatfa_frontend_settings_box tfa_settings_form">
144 - <p><?php $this->mother->paint_enable_tfa_radios($current_user->ID, true, $style); ?></p>
145 - <button style="margin-left: 4px; margin-bottom: 10px;" class="button button-primary simbatfa_settings_save"><?php _e('Save Settings', 'two-factor-authentication'); ?></button>
146 - </div>
147 - <?php
148 - }
149 -
150 - /**
151 - * Enqueue scripts
152 - */
153 - public function save_settings_javascript_output() {
154 -
155 - static $is_already_added = false;
156 - if ($is_already_added) return;
157 - $is_already_added = true;
158 -
159 - $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
160 - wp_register_script('jquery-blockui', SIMBA_TFA_PLUGIN_URL . '/includes/jquery.blockUI' . $suffix . '.js', array('jquery'), '2.60');
161 -
162 - $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $this->mother->version;
163 -
164 - wp_enqueue_script('simba-tfa-frontend-settings', SIMBA_TFA_PLUGIN_URL.'/includes/frontend-settings.js', array('jquery-blockui'), $script_ver);
165 -
166 - $ajax_url = admin_url('admin-ajax.php');
167 - // 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.
168 - if (!is_admin() && substr(strtolower($ajax_url), 0, 6) == 'https:' && !is_ssl()) {
169 - $also_try = 'http:'.substr($ajax_url, 6);
170 - } else {
171 - $also_try = '';
172 - }
173 -
174 - $localize = array(
175 - 'ask' => __('You have unsaved settings.', 'two-factor-authentication'),
176 - 'saving' => __('Saving...', 'two-factor-authentication'),
177 - 'ajax_url' => $ajax_url,
178 - 'also_try' => $also_try,
179 - 'nonce' => wp_create_nonce('tfa_frontend_nonce'),
180 - 'response' => __('Response:', 'two-factor-authentication'),
181 - );
182 -
183 - wp_localize_script('simba-tfa-frontend-settings', 'simba_tfa_frontend', $localize);
184 -
185 - }
186 -
187 - /**
188 - * Shortcode function for twofactor_user_settings
189 - *
190 - * @param Array $atts
191 - * @param Null|String $content
192 - *
193 - * @return String
194 - */
195 - public function tfa_user_settings_front($atts, $content = null) {
196 -
197 - if (!is_user_logged_in()) return '';
198 -
199 - global $current_user;
200 -
201 - return $this->mother->include_template('shortcode-tfa-user-settings.php', array('is_activated_for_user' => $current_user->ID, 'tfa_frontend' => $this), true);
202 -
203 - }
204 -}
1 +<?php
2 +if (!defined('ABSPATH')) die('Access denied.');
3 +
4 +class TFA_Frontend {
5 +
6 + private $mother;
7 +
8 + public function __construct($mother) {
9 +
10 + $this->mother = $mother;
11 + add_action('wp_ajax_tfa_frontend', array($this, 'ajax'));
12 + add_shortcode('twofactor_user_settings', array($this, 'tfa_user_settings_front'));
13 + }
14 +
15 + public function ajax(){
16 + $tfa = $this->mother->getTFA();
17 + global $current_user;
18 +
19 + $return_array = array();
20 +
21 + if (empty($_POST) || empty($_POST['subaction']) || !isset($_POST['nonce']) || !is_user_logged_in() || !wp_verify_nonce($_POST['nonce'], 'tfa_frontend_nonce')) die('Security check');
22 +
23 + if('savesettings' == $_POST['subaction']) {
24 + if (empty($_POST['settings']) || !is_string($_POST['settings'])) die;
25 +
26 + parse_str($_POST['settings'], $posted_settings);
27 +
28 + //Added
29 + if(isset($posted_settings["tfa_enable_tfa"])) {
30 + $tfa->changeEnableTFA($current_user->ID, $posted_settings["tfa_enable_tfa"]);
31 + }
32 +
33 + if(isset($posted_settings["tfa_algorithm_type"])) {
34 + $old_algorithm = $tfa->getUserAlgorithm($current_user->ID);
35 +
36 + if($old_algorithm != $posted_settings['tfa_algorithm_type'])
37 + $tfa->changeUserAlgorithmTo($current_user->ID, $posted_settings['tfa_algorithm_type']);
38 +
39 + //Re-fetch the algorithm type, url and private string
40 + $variables = $this->tfa_fetch_assort_vars();
41 +
42 + $return_array['qr'] = $this->mother->tfa_qr_code_url($variables['algorithm_type'], $variables['url'], $variables['tfa_priv_key']);
43 + $return_array['al_type_disp'] = $this->tfa_algorithm_info($variables['algorithm_type']);
44 + }
45 +
46 + $return_array['result'] = 'saved';
47 +
48 + echo json_encode($return_array);
49 + }
50 +
51 + die;
52 + }
53 +
54 + //Make the algorithm information string easier to update
55 + public function tfa_algorithm_info($algorithm_type) {
56 + $al_type_disp = strtoupper($algorithm_type);
57 + $al_type_desc = ($algorithm_type == 'totp' ? __('a time based', SIMBA_TFA_TEXT_DOMAIN) : __('an event based', SIMBA_TFA_TEXT_DOMAIN));
58 +
59 + return array('disp' => $al_type_disp, 'desc' => $al_type_desc);
60 + }
61 +
62 + /*
63 + Make the assorted required variables more accessible for ajax
64 + Returns: Site URl, private key, emergency codes, algorithm type
65 + */
66 + public function tfa_fetch_assort_vars(){
67 + global $current_user;
68 + $tfa = $this->mother->getTFA();
69 +
70 + $url = preg_replace('/^https?:\/\//', '', site_url());
71 +
72 + $tfa_priv_key_64 = get_user_meta($current_user->ID, 'tfa_priv_key_64', true);
73 +
74 + if(!$tfa_priv_key_64)
75 + $tfa_priv_key_64 = $tfa->addPrivateKey($current_user->ID);
76 +
77 + $tfa_priv_key = trim($tfa->getPrivateKeyPlain($tfa_priv_key_64, $current_user->ID));
78 +
79 + $algorithm_type = $tfa->getUserAlgorithm($current_user->ID);
80 +
81 + return apply_filters('simba_tfa_fetch_assort_vars', array(
82 + 'url' => $url,
83 + 'tfa_priv_key_64' => $tfa_priv_key_64,
84 + 'tfa_priv_key' => $tfa_priv_key,
85 + 'emergency_str' => '<em>'.__('No emergency codes left. Sorry.', SIMBA_TFA_TEXT_DOMAIN).'</em>',
86 + 'algorithm_type' => $algorithm_type
87 + ), $tfa, $current_user);
88 + }
89 +
90 + public function save_settings_button() {
91 + echo '<button style="margin-left: 4px;margin-bottom: 10px" class="simbatfa_settings_save button button-primary">'.__('Save Settings', SIMBA_TFA_TEXT_DOMAIN).'</button>';
92 + }
93 +
94 + private function get_tfa() {
95 + if (empty($this->tfa)) $this->tfa = $this->mother->getTFA();
96 + }
97 +
98 + public function settings_enable_or_disable_output() {
99 + $this->save_settings_javascript_output();
100 + global $current_user;
101 + ?>
102 + <div class="simbatfa_frontend_settings_box tfa_settings_form">
103 + <p><?php $this->mother->tfaListEnableRadios($current_user->ID, true); ?></p>
104 + <button style="margin-left: 4px;margin-bottom: 10px" class="button button-primary simbatfa_settings_save"><?php echo __('Save Settings', SIMBA_TFA_TEXT_DOMAIN); ?></button>
105 + </div>
106 + <?php
107 + }
108 +
109 + public function save_settings_javascript_output() {
110 + static $is_already_added;
111 + if (!empty($is_already_added)) return;
112 + $is_already_added = true;
113 + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
114 + wp_register_script( 'jquery-blockui', SIMBA_TFA_PLUGIN_URL . '/includes/jquery.blockUI' . $suffix . '.js', array('jquery' ), '2.60' );
115 + wp_enqueue_script('jquery-blockui');
116 + add_action('wp_footer', array($this, 'wp_footer'));
117 + }
118 +
119 + public function wp_footer() {
120 + $ajax_url = admin_url('admin-ajax.php');
121 + // 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.
122 + if (!is_admin() && substr(strtolower($ajax_url), 0, 6) == 'https:' && !is_ssl()) {
123 + $also_try = 'http:'.substr($ajax_url, 6);
124 + }
125 + ?>
126 +
127 + <script type="text/javascript">
128 + var tfa_query_leaving = false;
129 +
130 + // Prevent accidental leaving if there are unsaved settings
131 + window.onbeforeunload = function(e) {
132 + if (tfa_query_leaving) {
133 + var ask = "<?php echo esc_js(__('You have unsaved settings.', SIMBA_TFA_TEXT_DOMAIN)); ?>";
134 + e.returnValue = ask;
135 + return ask;
136 + }
137 + }
138 +
139 + jQuery(document).ready(function($) {
140 + $(".tfa_settings_form input, .tfa_settings_form textarea, .tfa_settings_form select" ).change(function() {
141 + tfa_query_leaving = true;
142 + });
143 +
144 + $(".tfa_settings_form input[name='simbatfa_delivery_type']").change(function() {
145 + $(".tfa_third_party_holder").slideToggle();
146 + });
147 +
148 + //Save Settings
149 + $(".simbatfa_settings_save").click(function() {
150 +
151 + $.blockUI({ message: '<div style="margin: 8px;font-size:150%;"><?php echo esc_js(__('Saving...', SIMBA_TFA_TEXT_DOMAIN )); ?></div>' });
152 +
153 + // https://stackoverflow.com/questions/10147149/how-can-i-override-jquerys-serialize-to-include-unchecked-checkboxes
154 + var formData = $(".tfa_settings_form input, .tfa_settings_form textarea, .tfa_settings_form select").serialize();
155 +
156 + // include unchecked checkboxes. use filter to only include unchecked boxes.
157 + $.each($(".tfa_settings_form input[type=checkbox]")
158 + .filter(function(idx){
159 + return $(this).prop("checked") === false
160 + }),
161 + function(idx, el){
162 + // attach matched element names to the formData with a chosen value.
163 + var emptyVal = "0";
164 + formData += "&" + $(el).attr("name") + "=" + emptyVal;
165 + }
166 + );
167 +
168 + $.post('<?php echo esc_js($ajax_url);?>', {
169 + action: "tfa_frontend",
170 + subaction: "savesettings",
171 + settings: formData,
172 + nonce: "<?php echo wp_create_nonce("tfa_frontend_nonce");?>"
173 + }, function(response) {
174 + var settings_saved = false;
175 + try {
176 + var resp = $.parseJSON(response);
177 + if (resp.hasOwnProperty('result')) {
178 + settings_saved = true;
179 + tfa_query_leaving = false;
180 + }
181 + if (resp.hasOwnProperty('qr')) {
182 + $('.simbaotp_qr_container').data('qrcode', resp['qr']).empty().qrcode({
183 + "render": "image",
184 + "text": resp['qr'],
185 + });
186 + }
187 + if (resp.hasOwnProperty('al_type_disp')) {
188 + $("#al_type_name").html(resp['al_type_disp']['disp']);
189 + $("#al_type_desc").html(resp['al_type_disp']['desc']);
190 + }
191 +
192 + } catch(err) {
193 + console.log(err);
194 + console.log(response);
195 + <?php if (!isset($also_try)) { ?> alert("<?php echo esc_js(__('Response:', 'SIMBA_TFA_TEXT_DOMAIN')); ?> "+response);<?php } ?>
196 + }
197 + <?php if (isset($also_try)) { ?>
198 + if (!settings_saved) {
199 + $.post('<?php echo esc_js($also_try);?>', {
200 + action: "tfa_frontend",
201 + subaction: "savesettings",
202 + settings: formData,
203 + nonce: "<?php echo wp_create_nonce("tfa_frontend_nonce");?>"
204 + }, function(response) {
205 +
206 + try {
207 + var resp = $.parseJSON(response);
208 + if (resp.hasOwnProperty('result')) {
209 + settings_saved = true;
210 + tfa_query_leaving = false;
211 + }
212 + if (resp.hasOwnProperty('qr')) {
213 + $('.simbaotp_qr_container').data('qrcode', resp['qr']).empty().qrcode({
214 + "render": "image",
215 + "text": resp['qr'],
216 + });
217 + }
218 + if (resp.hasOwnProperty('al_type_disp')) {
219 + $("#al_type_name").html(resp['al_type_disp']['disp']);
220 + $("#al_type_desc").html(resp['al_type_disp']['desc']);
221 + }
222 +
223 + } catch(err) {
224 + console.log(err);
225 + console.log(response);
226 + alert("<?php echo esc_js(__('Response:', 'SIMBA_TFA_TEXT_DOMAIN')); ?> "+response);
227 + }
228 + $.unblockUI();
229 + });
230 + } else {
231 + $.unblockUI();
232 + }
233 + <?php } else { ?>
234 + $.unblockUI();
235 + <?php } ?>
236 + });
237 +
238 + });
239 + });
240 + </script>
241 + <?php
242 + }
243 +
244 + /* Main Output function*/
245 + public function tfa_user_settings_front($atts, $content = null){
246 +
247 + if (!is_user_logged_in()) return '';
248 +
249 + global $current_user;
250 +
251 + // We want to print to buffer, since the shortcode API wants the value returned, not echoed
252 + ob_start();
253 +
254 + $this->get_tfa();
255 +
256 + if(!$this->tfa->isActivatedForUser($current_user->ID)){
257 + echo __('Two factor authentication is not available for your user.', SIMBA_TFA_TEXT_DOMAIN);
258 + } else {
259 +
260 + ?>
261 +
262 + <div class="wrap" style="padding-bottom:10px">
263 +
264 + <?php $this->mother->settings_intro_notices(); ?>
265 +
266 + <?php $this->settings_enable_or_disable_output(); ?>
267 +
268 + <?php $this->mother->current_codes_box(false); ?>
269 +
270 + <?php $this->mother->advanced_settings_box(array($this, 'save_settings_button')); ?>
271 +
272 + </div>
273 +
274 + <?php $this->save_settings_javascript_output(); ?>
275 +
276 + <?php
277 + }
278 +
279 + return ob_get_clean();
280 +
281 + }
282 +}