PageSourceSearch

https://diana-paxson.com/wp-content/plugins/two-factor-authentication/simba-tfa/includes/tfa.js?ver=1765299670

js diana-paxson.com collected 2026-09-25 00:25:03 UTC 13,169 bytes, 361 lines download raw bytes

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 and RegistrationMagic
12		return '[name="log"], [name="username"], #user_login, #affwp-login-user-login, #affwp-user-login, #gform_fields_login input[type="text"], .um-field-username input[type="text"], [name="edd_user_login"]';
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			// The un-disabling is for Ultimate Member, which for unknown reasons outputs the login button in a disabled state
41			$(form).find('input[type="submit"], button[type="submit"]').first().prop('disabled', false).trigger('click');
42			// $('#wp-submit').parents('form').first().trigger('submit');
43		}
44		return false;
45	}
46	
47	/**
48	 * Check if the user requires an OTP field and if so, display it
49	 *
50	 * @param String  form					   - DOM selector string
51	 * @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)
52	 *
53	 * @uses show_otp_field()
54	 *
55	 * @return Boolean - true if we got involved
56	 */
57	function check_and_possibly_show_otp_field(form, only_cache_the_results) {
58
59		// If this is a "lost password" form, then exit
60		if ($(form).attr('id') === 'lostpasswordform' || $(form).attr('id') === 'resetpasswordform') return false;
61
62		var username = $(form).find(get_username_identifiers()).first().val();
63		
64		if (!username.length) return false;
65		
66		// Is the result already known?
67		if ('object' === typeof username_requires_otp[username]) {
68			if (!only_cache_the_results) {
69				// Process the already-known result
70				return process_user_tfa_enabled_check_results($(form), username_requires_otp[username]);
71			}
72			// No further processing
73			return true;
74		}
75		
76		var $submit_button = $(form).find('input[name="wp-submit"], input[type="submit"], button[type="submit"]').first();
77		
78		if (simba_tfasettings.hasOwnProperty('spinnerimg') && $('.simbaotp_spinner').length === 0) {
79			var styling = 'float:right; margin:6px 12px; width: 20px; height: 20px;';
80			if ($('#theme-my-login #wp-submit').length >0) {
81				styling = 'margin-left: 4px; position: relative; top: 4px; width: 20px; height: 20px; border:0px; box-shadow:none;';
82			}	
83			$submit_button.after('<img class="simbaotp_spinner" src="'+simba_tfasettings.spinnerimg+'" style="'+styling+'">');
84		}
85
86		$.ajax({
87			url: simba_tfasettings.ajaxurl,
88			type: 'POST',
89			data: {
90				action: 'simbatfa-init-otp',
91				user: username
92			},
93			dataType: 'text',
94			success: function(resp) {
95				try {
96					var json_begins = resp.search('{"jsonstarter":"justhere"');
97					if (json_begins > -1) {
98						if (json_begins > 0) {
99							console.log("Expected JSON marker found at position: "+json_begins);
100							resp = resp.substring(json_begins);
101						}
102					} else {
103						console.log("Expected JSON marker not found");
104						console.log(resp);
105					}
106					
107					response = JSON.parse(resp);
108					
109					if (response.hasOwnProperty('php_output')) {
110						console.log("PHP output was returned (follows)");
111						console.log(response.php_output);
112					}
113					
114					if (response.hasOwnProperty('extra_output')) {
115						console.log("Extra output was returned (follows)");
116						console.log(response.extra_output);
117					}
118					
119					if (only_cache_the_results) {
120						// Save the result for later processing
121						username_requires_otp[username] = response;
122						$('.simbaotp_spinner').remove();
123					} else {
124						process_user_tfa_enabled_check_results($(form), response);
125					}
126					
127				} catch(err) {
128					$('#login').html(resp);
129					console.log("Simba TFA: Error when processing response");
130					console.log(err);
131					console.log(resp);
132				}
133			},
134			error: function(jq_xhr, text_status, error_thrown) {
135				console.log("Simba TFA: AJAX error: "+error_thrown+": "+text_status);
136				console.log(jq_xhr);
137				if (jq_xhr.hasOwnProperty('responseText')) {
138					console.log(jq_xhr.responseText);
139					$(form).append('<p class="error" style="clear:left;">
139'+simba_tfasettings.error+'</p>');
140				}
141			}
142		});
143		return true;
144	}
145	
146	// Parameters: see check_and_possibly_show_otp_field
147	function show_otp_field(form, user_can_trust, user_already_trusted) {
148		
149		var $submit_button;
150		
151		user_can_trust = ('undefined' == typeof user_can_trust) ? false : user_can_trust;
152		user_already_trusted = ('undefined' == typeof user_already_trusted) ? false : user_already_trusted;
153		
154		if ('https:' != window.location.protocol && 'localhost' !== location.hostname && '127.0.0.1' !== location.hostname && /^\.localdomain$/.test(location.hostname)) {
155			user_can_trust = false;
156		}
157		
158		if (!user_can_trust) { user_already_trusted = false; }
159		
160		var form_is_gravity_forms = ('object' == typeof window['gform_gravityforms'] && 'undefined' !== typeof $(form).attr('id') && 'gform_' === $(form).attr('id').substring(0, 6));
161		
162		// This is used just for applying similar styling (via adding structure/CSS classes)
163		var form_is_ultimate_member = ($(form).find('.um-row').length > 0) ? true : false;
164
165		// This is used just for applying styling if .js-login-form class exists inside form
166		var form_is_login_form = ($(form).find('.js-login-form').length > 0) ? true : false;
167
168		// Gravity Forms won't submit if the elements are hidden
169		var form_retain_existing_elements = form_is_gravity_forms ? true : false;
170		
171		// name="Submit" is WP-Members. 'submit' is Theme My Login starting from 7.x
172		$submit_button = $(form).find('input[name="wp-submit"], input[name="Submit"], input[name="submit"]');
173		// 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:
174		if (0 == $submit_button.length) {
175			$submit_button = $(form).find('input[type="submit"], button[type="submit"]').first();
176		}
177
178		if (!form_retain_existing_elements) {
179			// Hide all elements in a browser-safe way
180			// .user-pass-wrap is the wrapper used (instead of a paragraph) on wp-login.php from WP 5.3
181			// .um-row : Ultimate Member
182            // .rmrow : RegistrationMagic
183			$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, .um-row, .um-button, .js-login-form, .rmrow').each(function(i) {
184				$(this).css('visibility', 'hidden').css('position', 'absolute');
185				// On the WooCommerce form, the 'required' asterisk in the child <span> still shows without this
186				$(this).find('span').css('visibility', 'hidden').css('position', 'absolute');
187			});
188			
189			// WP-Members
190			$submit_button.parents('#wpmem_login').find('fieldset').css('visibility', 'hidden').css('position', 'absolute');
191			
192		}
193		
194		// Add new field and controls
195		var html = '';
196		
197		if (form_is_ultimate_member) {
198			html += '<div class="um-row">';
199		}
200		
201		if (user_already_trusted) {
202			
203			html += '<br><span class="simbaotp_is_trusted">'+simba_tfasettings.is_trusted+'</span>';
204			
205		} else {
206			
207			if (form_is_ultimate_member) { html += '<div class="um-field um-field-text um-field-type_text"><div class="um-field-label">'; }
208			
209			html += '<label ';
210			
211			if (form_is_gravity_forms) {
212				html += 'class="gfield_label"';
213			}
214			
215			html += 'for="simba_two_factor_auth">';
216			
217			html += simba_tfasettings.otp + '</label><input type="text" name="two_factor_code" id="simba_two_factor_auth" autocomplete="off" data-lpignore="true"';
218			
219			if ($(form).hasClass('woocommerce-form-login')) {
220				// Retain compatibility with previous full-width layout
221				html += ' style="width: 100%;"';
222			}
223			
224			html += '>';
225			
226			if (form_is_ultimate_member) { html += '</div>'; }
227			
228			html += '<p class="forgetmenot';
229			if (form_is_gravity_forms) html += ' gfield';
230			html += '" style="font-size:small;';
231			if (!$(form).hasClass('woocommerce-form-login')) {
232				// Retain compatibility with previous full-width layout
233				html += ' max-width: 60%;';
234			}
235			html += '">';
236			
237			if (form_is_ultimate_member) { html += '</div>'; }
238			
239			// Would need further styling investigations to display this
240			if (!form_is_gravity_forms) {
241				html += '<span class="simba_tfa_otp_login_help">'+simba_tfasettings.otp_login_help+'</span>';
242			}
243			
244			if (form_is_ultimate_member) {
245				html += '</div>';
246			}
247			
248			if (user_can_trust) {
249			
250				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>';
251				
252			}
253		}
254		
255		html += '</p>';
256		
257		var submit_button_text;
258		var submit_button_name;
259		
260		// Gravity forms doesn't like its button being disabled
261		if (!form_is_gravity_forms) {
262		
263			if ('button' == $submit_button.prop('nodeName').toLowerCase()) {
264				submit_button_text = $submit_button.text().trim();
265				submit_button_name = $submit_button.attr('name');
266			} else {
267				submit_button_text = $submit_button.val();
268				submit_button_name = $submit_button.attr('name');
269			}
270			
271			html += '<p class="submit';
272			
273			if (form_is_ultimate_member) { html += ' um-center'; }
274			
275			html += '"><input id="tfa_login_btn" class="button button-primary button-large';
276			
277			if (form_is_ultimate_member) { html += ' um-button'; }
278
279			if (form_is_login_form) { html += ' c-btn-rg hover:bg-main focus:bg-main'; }
280			
281			html += '" type="submit" ';
282			if ('undefined' !== typeof submit_button_name && '' != submit_button_name) { html += 'name="'+submit_button_name+'" '; }
283			html += 'value="' + submit_button_text + '"></p>';
284			
285			$submit_button.prop('disabled', true).hide();
286		
287		}
288		
289		if (form_retain_existing_elements && form_is_gravity_forms) {
290			// $submit_button.parents('form').first().append(html);
291			//$('<div style="clear:both;">
291'+html+'</div>').insertBefore($submit_button);
292			$(form).find('#gform_fields_login').append(html);
293		} else {
294			$submit_button.parents('form').first().prepend(html);
295		}
296
297		$('#login_error').hide();
298			
299		if (user_already_trusted) {
300			if (form_retain_existing_elements) {
301				$submit_button.trigger('click');
302			} else {
303				$('#tfa_login_btn').trigger('click');
304			}
305		} else {
306
307			$('#simba_two_factor_auth').trigger('focus');
308
309			// Hide extra boxes of third party plugins
310			jQuery('.hide-when-displaying-tfa-input').hide();
311		}
312
313	}
314	
315	/**
316	 * This function gets attached to a form submission handler and decides whether to add an OTP field or not.
317	 *
318	 * @param Object e - submission event
319	 *
320	 * @return Boolean - whether to proceed with the submission or not
321	 */
322	var form_submit_handler = function(e) {
323		
324		console.log('Simba TFA: form submit request');
325
326		var form = e.target;
327		
328		var form_is_gravity_forms = ('object' == typeof window['gform_gravityforms'] && 'undefined' !== typeof $(form).attr('id') && 'gform_' === $(form).attr('id').substring(0, 6));
329		
330		// Turn off everything
331		$(form).off();
332
333		if (0 == $(form).find('#simba_two_factor_auth').length && check_and_possibly_show_otp_field(form)) {
334			
335			if (form_is_gravity_forms) {
336				var form_id = $(form).attr('id').substring(6);
337				// Gravity Forms won't allow the form to submit if this is already true
338				window['gf_submitting_'+form_id] = false;
339			}
340			
341			e.preventDefault();
342			return false;
343			
344		}
345		
346		return true;
347		
348	};
349	
350	if (simba_tfasettings.login_form_off_selectors) {
351		$(simba_tfasettings.login_form_off_selectors).off('submit');
352	}
353	
354	$(simba_tfasettings.login_form_selectors).on('submit', form_submit_handler);
355	
356	$(simba_tfasettings.login_form_selectors).find(get_username_identifiers()).on('blur', function() {
357		var $form = $(this).parents('form').first();
358		check_and_possibly_show_otp_field($form, true);
359	});
360	
361});

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.