1jQuery(function($) { 2 3 var username_requires_otp = []; 4 5 /** 6 * Returns the jQuery identifiers for finding the username field. Abstracted here to avoid maintaining multiple lists. 7 * 8 * @return String 9 */ 10 function get_username_identifiers() { 11 // 'username' is used by WooCommerce 12 return '[name="log"], [name="username"], #user_login, #affwp-login-user-login, #affwp-user-login, #gform_fields_login input[type="text"]'; 13 } 14 15 /** 16 * Process the results of a check for whether the user has TFA enabled or not 17 * 18 * @param Object form - jQuery form object 19 * @param Object response - the response from the check; must have the property (boolean) "status" and potentially user_(boolean) "can_trust" and (boolean) user_can_trust. 20 */ 21 function process_user_tfa_enabled_check_results(form, response) { 22 23 if (true === response.status) { 24 // Don't bother to remove the spinner if the form is being submitted. 25 $('.simbaotp_spinner').remove(); 26 27 var user_can_trust = (response.hasOwnProperty('user_can_trust') && response.user_can_trust) ? true : false; 28 29 var user_already_trusted = (response.hasOwnProperty('user_already_trusted') && response.user_can_trust) ? true : false; 30 31 console.log("Simba TFA: User has OTP enabled: showing OTP field (user_can_trust="+user_can_trust+")"); 32 33 show_otp_field(form, user_can_trust, user_already_trusted); 34 35 return true; 36 37 } else { 38 console.log("Simba TFA: User does not have OTP enabled: submitting form"); 39 // For some reason, .submit() stopped working with TML 7.x. N.B. Used to do this only for form_type == 2 ("TML shortcode or widget, WP Members, bbPress, Ultimate Membership Pro, WooCommerce or Elementor login form") 40 $(form).find('input[type="submit"], button[type="submit"]').first().trigger('click'); 41 // $('#wp-submit').parents('form').first().trigger('submit'); 42 } 43 return false; 44 } 45 46 /** 47 * Check if the user requires an OTP field and if so, display it 48 * 49 * @param String form - DOM selector string 50 * @param Boolean only_cache_the_results - if true, then nothing more will be done that caching the results (in the variable username_requires_otp will be updated) 51 * 52 * @uses show_otp_field() 53 * 54 * @return Boolean - true if we got involved 55 */ 56 function check_and_possibly_show_otp_field(form, only_cache_the_results) { 57 58 // If this is a "lost password" form, then exit 59 if ($(form).attr('id') === 'lostpasswordform' || $(form).attr('id') === 'resetpasswordform') return false; 60 61 var username = $(form).find(get_username_identifiers()).first().val(); 62 63 if (!username.length) return false; 64 65 // Is the result already known? 66 if ('object' === typeof username_requires_otp[username]) { 67 if (!only_cache_the_results) { 68 // Process the already-known result 69 return process_user_tfa_enabled_check_results($(form), username_requires_otp[username]); 70 } 71 // No further processing 72 return true; 73 } 74 75 var $submit_button = $(form).find('input[name="wp-submit"], input[type="submit"], button[type="submit"]').first(); 76 77 if (simba_tfasettings.hasOwnProperty('spinnerimg') && $('.simbaotp_spinner').length === 0) { 78 var styling = 'float:right; margin:6px 12px; width: 20px; height: 20px;'; 79 if ($('#theme-my-login #wp-submit').length >0) { 80 styling = 'margin-left: 4px; position: relative; top: 4px; width: 20px; height: 20px; border:0px; box-shadow:none;'; 81 } 82 $submit_button.after('<img class="simbaotp_spinner" src="'+simba_tfasettings.spinnerimg+'" style="'+styling+'">'); 83 } 84 85 $.ajax({ 86 url: simba_tfasettings.ajaxurl, 87 type: 'POST', 88 data: { 89 action: 'simbatfa-init-otp', 90 user: username 91 }, 92 dataType: 'text', 93 success: function(resp) { 94 try { 95 var json_begins = resp.search('{"jsonstarter":"justhere"'); 96 if (json_begins > -1) { 97 if (json_begins > 0) { 98 console.log("Expected JSON marker found at position: "+json_begins); 99 resp = resp.substring(json_begins); 100 } 101 } else { 102 console.log("Expected JSON marker not found"); 103 console.log(resp); 104 } 105 106 response = JSON.parse(resp); 107 108 if (response.hasOwnProperty('php_output')) { 109 console.log("PHP output was returned (follows)"); 110 console.log(response.php_output); 111 } 112 113 if (response.hasOwnProperty('extra_output')) { 114 console.log("Extra output was returned (follows)"); 115 console.log(response.extra_output); 116 } 117 118 if (only_cache_the_results) { 119 // Save the result for later processing 120 username_requires_otp[username] = response; 121 $('.simbaotp_spinner').remove(); 122 } else { 123 process_user_tfa_enabled_check_results($(form), response); 124 } 125 126 } catch(err) { 127 $('#login').html(resp); 128 console.log("Simba TFA: Error when processing response"); 129 console.log(err); 130 console.log(resp); 131 } 132 }, 133 error: function(jq_xhr, text_status, error_thrown) { 134 console.log("Simba TFA: AJAX error: "+error_thrown+": "+text_status); 135 console.log(jq_xhr); 136 if (jq_xhr.hasOwnProperty('responseText')) { 137 console.log(jq_xhr.responseText); 138 $(form).append('<p class="error" style="clear:left;">
138'+simba_tfasettings.error+'</p>'); 139 } 140 } 141 }); 142 return true; 143 } 144 145 // Parameters: see check_and_possibly_show_otp_field 146 function show_otp_field(form, user_can_trust, user_already_trusted) { 147 148 var $submit_button; 149 150 user_can_trust = ('undefined' == typeof user_can_trust) ? false : user_can_trust; 151 user_already_trusted = ('undefined' == typeof user_already_trusted) ? false : user_already_trusted; 152 153 if ('https:' != window.location.protocol && 'localhost' !== location.hostname && '127.0.0.1' !== location.hostname && /^\.localdomain$/.test(location.hostname)) { 154 user_can_trust = false; 155 } 156 157 if (!user_can_trust) { user_already_trusted = false; } 158 159 var form_is_gravity_forms = ('object' == typeof window['gform_gravityforms'] && 'undefined' !== typeof $(form).attr('id') && 'gform_' === $(form).attr('id').substring(0, 6)); 160 161 // Gravity Forms won't submit if the elements are hidden 162 var form_retain_existing_elements = form_is_gravity_forms ? true : false; 163 164 // name="Submit" is WP-Members. 'submit' is Theme My Login starting from 7.x 165 $submit_button = $(form).find('input[name="wp-submit"], input[name="Submit"], input[name="submit"]'); 166 // This hasn't been needed for anything yet (Jul 2018), but is a decent back-stop that would have prevented some breakage in the past that needed manual attention: 167 if (0 == $submit_button.length) { 168 $submit_button = $(form).find('input[type="submit"], button[type="submit"]').first(); 169 } 170 171 if (!form_retain_existing_elements) { 172 // Hide all elements in a browser-safe way 173 // .user-pass-wrap is the wrapper used (instead of a paragraph) on wp-login.php from WP 5.3 174 $submit_button.parents('form').first().find('p, .impu-form-line-fr, .tml-field-wrap, .user-pass-wrap, .elementor-field-type-text, .elementor-field-type-submit, .elementor-remember-me, .bbp-username, .bbp-password, .bbp-submit-wrapper, .gform_body').each(function(i) { 175 $(this).css('visibility', 'hidden').css('position', 'absolute'); 176 // On the WooCommerce form, the 'required' asterisk in the child <span> still shows without this 177 $(this).find('span').css('visibility', 'hidden').css('position', 'absolute'); 178 }); 179 180 // WP-Members 181 $submit_button.parents('#wpmem_login').find('fieldset').css('visibility', 'hidden').css('position', 'absolute'); 182 183 } 184 185 // Add new field and controls 186 var html = ''; 187 188 if (user_already_trusted) { 189 190 html += '<br><span class="simbaotp_is_trusted">'+simba_tfasettings.is_trusted+'</span>'; 191 192 } else { 193 194 html += '<label '; 195 196 if (form_is_gravity_forms) { 197 html += 'class="gfield_label"'; 198 } 199 200 html += 'for="simba_two_factor_auth">' + simba_tfasettings.otp + '<br><input type="text" name="two_factor_code" id="simba_two_factor_auth" autocomplete="off" data-lpignore="true"'; 201 202 if ($(form).hasClass('woocommerce-form-login')) { 203 // Retain compatibility with previous full-width layout 204 html += ' style="width: 100%;"'; 205 } 206 207 html += '></label>'; 208 209 html += '<p class="forgetmenot'; 210 if (form_is_gravity_forms) html += ' gfield'; 211 html += '" style="font-size:small;'; 212 if (!$(form).hasClass('woocommerce-form-login')) { 213 // Retain compatibility with previous full-width layout 214 html += ' max-width: 60%;'; 215 } 216 html += '">'; 217 218 // Would need further styling investigations to display this 219 if (!form_is_gravity_forms) { 220 html += '<span class="simba_tfa_otp_login_help">'+simba_tfasettings.otp_login_help+'</span>'; 221 } 222 223 if (user_can_trust) { 224 225 html += '<input type="checkbox" name="simba_tfa_mark_as_trusted" id="simba_tfa_mark_as_trusted" value="1"><label for="simba_tfa_mark_as_trusted">'+ simba_tfasettings.mark_as_trusted+'</label>'; 226 227 } 228 } 229 230 html += '</p>'; 231 232 var submit_button_text; 233 var submit_button_name; 234 235 // Gravity forms doesn't like its button being disabled 236 if (!form_is_gravity_forms) { 237 238 if ('button' == $submit_button.prop('nodeName').toLowerCase()) { 239 submit_button_text = $submit_button.text().trim(); 240 submit_button_name = $submit_button.attr('name'); 241 } else { 242 submit_button_text = $submit_button.val(); 243 submit_button_name = $submit_button.attr('name'); 244 } 245 246 html += '<p class="submit"><input id="tfa_login_btn" class="button button-primary button-large" type="submit" '; 247 if ('undefined' !== typeof submit_button_name && '' != submit_button_name) { html += 'name="'+submit_button_name+'" '; } 248 html += 'value="' + submit_button_text + '"></p>'; 249 250 $submit_button.prop('disabled', true).hide(); 251 252 } 253 254 if (form_retain_existing_elements && form_is_gravity_forms) { 255 // $submit_button.parents('form').first().append(html); 256 //$('<div style="clear:both;">
256'+html+'</div>').insertBefore($submit_button); 257 $(form).find('#gform_fields_login').append(html); 258 } else { 259 $submit_button.parents('form').first().prepend(html); 260 } 261 262 $('#login_error').hide(); 263 264 if (user_already_trusted) { 265 if (form_retain_existing_elements) { 266 $submit_button.trigger('click'); 267 } else { 268 $('#tfa_login_btn').trigger('click'); 269 } 270 } else { 271 272 $('#simba_two_factor_auth').trigger('focus'); 273 274 // Hide extra boxes of third party plugins 275 jQuery('.hide-when-displaying-tfa-input').hide(); 276 } 277 278 } 279 280 /** 281 * This function gets attached to a form submission handler and decides whether to add an OTP field or not. 282 * 283 * @param Object e - submission event 284 * 285 * @return Boolean - whether to proceed with the submission or not 286 */ 287 var form_submit_handler = function(e) { 288 289 console.log('Simba TFA: form submit request'); 290 291 var form = e.target; 292 293 var form_is_gravity_forms = ('object' == typeof window['gform_gravityforms'] && 'undefined' !== typeof $(form).attr('id') && 'gform_' === $(form).attr('id').substring(0, 6)); 294 295 // Turn off everything 296 $(form).off(); 297 298 if (0 == $(form).find('#simba_two_factor_auth').length && check_and_possibly_show_otp_field(form)) { 299 300 if (form_is_gravity_forms) { 301 var form_id = $(form).attr('id').substring(6); 302 // Gravity Forms won't allow the form to submit if this is already true 303 window['gf_submitting_'+form_id] = false; 304 } 305 306 e.preventDefault(); 307 return false; 308 309 } 310 311 return true; 312 313 }; 314 315 if (simba_tfasettings.login_form_off_selectors) { 316 $(simba_tfasettings.login_form_off_selectors).off('submit'); 317 } 318 319 $(simba_tfasettings.login_form_selectors).on('submit', form_submit_handler); 320 321 $(simba_tfasettings.login_form_selectors).find(get_username_identifiers()).on('blur', function() { 322 var $form = $(this).parents('form').first(); 323 check_and_possibly_show_otp_field($form, true); 324 }); 325 326});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.