1/** 2 * JavaScript Functions related to Logging In with Multi-Factor Authentication 3 * Found on Login Page (/np-templates/views/login/welcome.inc) 4 * Author: Dinah C. 2022.09.21 5 */ 6 7// Toggle between using an authenticator code and using an emergency backup code 8function useAltCode(e) { 9 document.getElementById("mfaAuthInfo").classList.toggle("hide"); 10 document.getElementById("mfaBackupInfo").classList.toggle("show"); 11 let btn = document.getElementById("mfaUseCode"); 12 if (e.dataset.code === "backup") { 13 btn.innerHTML = "Authenticator"; 14 e.dataset.code = "auth"; 15 } else { 16 btn.innerHTML = "Emergency Backup"; 17 e.dataset.code = "backup"; 18 } 19 //centerPopup__2020(); 20 clearCode(e.dataset.code); 21} 22 23// Listen to paste on the document, paste the code into individual boxes on form 24window.addEventListener("paste", function(e) { 25 // if the target is a text input 26 if (e.target.type === "tel") { 27 e.preventDefault(); 28 var data = e.clipboardData.getData('Text'); 29 clipboardPaste(e, data); 30 } 31}); 32 33// If user is trying to "paste" from a mobile clipboard, check if code can be entered 34function clipboardPaste(e, data) { 35 // split clipboard text into single characters 36 data = data.split(''); 37 // find all other text inputs 38 [].forEach.call(document.querySelectorAll("input[name='"+e.target.name+"']"), (node, index) => { 39 // And set input value to the relative character 40 if (Number.isInteger(parseInt(data[index]))) { 41 node.value = data[index]; 42 } 43 }); 44 45 if (e.target.name === "auth[]") { 46 checkCode(e); 47 } 48} 49 50// Check if a value was pasted into the designated field, perform paste action if so 51function isPaste(evt) { 52 let e = evt.target; 53 if (evt.type === "change") { 54 if ((e.name === "auth[]" && e.value.length === 6) || (e.name === "backup[]" && e.value.length === 8)) { 55 clipboardPaste(evt, e.value); 56 } else if (e.value.length !== 1) { 57 let ind = e.value.search(/[0-9]/); 58 if (ind > -1) { 59 e.value = e.value[ind]; 60 } else { 61 // Otherwise, do not insert the value 62 e.value = ''; 63 } 64 } else { 65 validateNum(evt); 66 } 67 } else if (evt.inputType === "insertText") { 68 if ((e.name === "auth[]" && evt.data.length === 6) || (e.name === "backup[]" && evt.data.length === 8)) { 69 clipboardPaste(evt, evt.data); 70 } else { 71 validateNum(evt); 72 } 73 } 74} 75 76// Validate if the value entered into the box is a number 77function validateNum(evt) { 78 let e = evt.target;
79 // If the character is not a number, clear the input 80 if (evt.data) { 81 // Check if the input is a valid int 82 if (evt.data.length === 1 && Number.isInteger(parseInt(evt.data))) { 83 if (e.value !== evt.data) e.value = evt.data; 84 // If there is another input following the current one, focus that input 85 if (e.nextElementSibling) { 86 e.nextElementSibling.focus(); 87 } 88 } else { 89 let ind = e.value.search(/[0-9]/); 90 if (e.value.length > 1 && ind > -1) { 91 if (e.value !== e.value[ind]) e.value = e.value[ind]; 92 // If there is another input following the current one, focus that input 93 if (e.nextElementSibling) { 94 e.nextElementSibling.focus(); 95 } 96 } else { 97 // Otherwise, do not insert the value 98 e.value = ''; 99 } 100 } 101 } else { 102 if (!Number.isInteger(parseInt(e.value))) { 103 e.value = ''; 104 } else { 105 // If there is another input following the current one, focus that input 106 if (evt.type === "change" && e.nextElementSibling) { 107 e.nextElementSibling.focus(); 108 } 109 } 110 } 111} 112 113// If the user enters a valid value into an input box, proceed to the next input box 114function moveFocus(evt) { 115 let e = evt.target; 116 // Return if the user presses enter, so that form is submitted properly 117 if (evt.key === "Enter") { 118 return; 119 } 120 // If the user presses right arrow key or any valid number key 121 if (evt.key === "ArrowRight"/* || (parseInt(evt.key) >= 0 && parseInt(evt.key) <= 9)*/) { 122 // If the key is a number, and it does not already match the input value, update the input value 123 /*if (evt.key !== "ArrowRight" && e.value !== evt.key) { 124 e.value = evt.key; 125 }*/ 126 // If there is another input following the current one, focus that input 127 if (e.nextElementSibling) { 128 e.nextElementSibling.focus(); 129 } 130 } else if (evt.key === "Backspace") { 131 if (e.value === '' && e.previousElementSibling) { 132 e.previousElementSibling.setSelectionRange(1,1); 133 e.previousElementSibling.focus(); 134 e.previousElementSibling.value = ''; 135 } else { 136 e.value = ''; 137 } 138 } else if (evt.key === "ArrowLeft") { 139 // Other wise, if the user presses the left arrow key, go back to the previous sibling 140 // and reset to the "beginning" of the input 141 if (e.previousElementSibling) { 142 e.previousElementSibling.setSelectionRange(0,0); 143 e.previousElementSibling.focus(); 144 } 145 } 146} 147 148// Clears the code input (for authenticator or backup codes based on name) 149function clearCode(code) { 150 document.querySelectorAll("input[name='"+code+"[]']").forEach(function(e) { 151 // And set input value to the relative character 152 e.value = ''; 153 }); 154 document.querySelector("input[name='"+code+"[]']").focus(); 155} 156 157// Check if the code fields all contain a value and submit the form if so 158function checkCode(evt) { 159 // If the user pressed Enter key, submit normally 160 if (evt.which === 13) return; 161 162 let el = evt.target; 163 let code = el.name; 164 var submit = true; 165 // Iterate over input fields and check for empty values 166 document.querySelectorAll("input[name='"+code+"']").forEach(function(e) { 167 // And set input value to the relative character 168 if (!submit || e.value === '' || !Number.isInteger(parseInt(e.value))) { 169 submit = false; 170 return; // Return if any empty value found 171 } else { 172 submit = true; 173 } 174 }); 175 176 // If the form is ready to submit, call submitForm (on welcome.inc) 177 if (submit) { 178 submitForm(el.form); 179 } 180} 181 182// If the user must wait before trying to submit another code, start a countdown 183// timer using the values returned from the ajax call 184function delaySubmit(waitTime, divId) { 185 if (lockClock.ticking) return; 186 187 lockClock.hours = waitTime.hr; 188 lockClock.minutes = waitTime.min; 189 lockClock.seconds = waitTime.sec; 190 lockClock.ticking = true; 191 lockClock.clear = divId; 192 lockClock.interval = setInterval("lockClock.tick()", 1000); 193 194} 195 196/** 197 * Countdown Clock 198 * @type {{hours: number, seconds: number, minutes: number, display: acClock.display, tick: ((function(): (boolean|undefined))|*)}} 199 */ 200var lockClock = { 201 hours: 0, 202 minutes: 0, 203 seconds: 0, 204 ticking: false, 205 clear: "", 206 interval: null, 207 tick: function() { 208 if (this.seconds <= 0) { 209 this.seconds = 59; 210 if (this.minutes <= 0) { 211 this.minutes = 59; 212 if (this.hours <= 0) { 213 document.getElementById(this.clear).innerHTML = ""; 214 clearInterval(this.interval); 215 this.ticking = false; 216 return false; 217 } else { 218 this.hours = this.hours - 1; 219 } 220 } else { 221 this.minutes = this.minutes - 1; 222 } 223 } else { 224 this.seconds = this.seconds - 1; 225 } 226 227 if (this.ticking) { 228 this.display(); 229 } 230 },
231 display: function() { 232 var hourText = document.getElementById('lockHour'); 233 var minuteTen = document.getElementById('lockMinTen'); 234 var minuteOne = document.getElementById('lockMinOne'); 235 var minuteText = document.getElementById('lockMinutes'); 236 var secondTen = document.getElementById('lockSecTen'); 237 var secondOne = document.getElementById('lockSecOne'); 238 var secondText = document.getElementById('lockSeconds'); 239 var mt = Math.floor(this.minutes / 10) > 0 ? (Math.floor(this.minutes / 10)).toString() : ""; 240 var mo = this.minutes > 0 ? (Math.floor(this.minutes % 10)).toString() : ""; 241 var st = Math.floor(this.seconds / 10) > 0 ? (Math.floor(this.seconds / 10)).toString() : ""; 242 var so = (Math.floor(this.seconds % 10)).toString(); 243 244 if (this.hours >= 2) { 245 if (hourText.innerHTML != "a long while" && this.hours <= 1) hourText.innerHTML = "a long while"; 246 } else if (this.hours === 1) { 247 if (hourText.innerHTML != "1 hour" && this.hours <= 1) hourText.innerHTML = "1 hour"; 248 if (minuteText.innerHTML != " min") minuteText.innerHTML = " min"; 249 } else { 250 if (hourText.innerHTML != "") hourText.innerHTML = ""; 251 } 252 if (this.hours <= 1 && this.minutes > 0) { 253 if (minuteTen.innerHTML != mt) minuteTen.innerHTML = mt; 254 if (minuteOne.innerHTML != mo) minuteOne.innerHTML = mo; 255 } else { 256 if (minuteText.innerHTML != "" && this.minutes === 0) minuteText.innerHTML = ""; 257 if (minuteOne.innerHTML != "" && this.minutes === 0) minuteOne.innerHTML = ""; 258 } 259 if (this.hours === 0) { 260 if (this.minutes > 0 && minuteText.innerHTML != " min ") minuteText.innerHTML = " min "; 261 if (secondTen.innerHTML != st) secondTen.innerHTML = st; 262 if (secondOne.innerHTML != so) secondOne.innerHTML = so; 263 if (secondText.innerHTML != " sec.") secondText.innerHTML = " sec."; 264 } else { 265 if (secondText.innerHTML != ".") secondText.innerHTML = "."; 266 } 267 268 } 269};
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.