blob: eed544b56e99d279a20ac5f22e1d530290421a2f [file] [log] [blame]
Marc Kupietz484ec8e2023-02-25 11:23:07 +01001// Example starter JavaScript for disabling form submissions if there are invalid fields
Marc Kupietzf1903162023-03-10 13:54:23 +01002(function() {
Marc Kupietz484ec8e2023-02-25 11:23:07 +01003 'use strict';
Marc Kupietzf1903162023-03-10 13:54:23 +01004 window.addEventListener('load', function() {
Marc Kupietz4fc9eeb2023-03-21 17:56:34 +01005 const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
6 const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
Marc Kupietz145f5b92023-03-09 20:39:31 +01007 update_total_due();
Marc Kupietz8252b6d2023-03-10 06:46:32 +01008 update_paper_id_field();
Marc Kupietz484ec8e2023-02-25 11:23:07 +01009 // Fetch all the forms we want to apply custom Bootstrap validation styles to
10 var forms = document.getElementsByClassName('needs-validation');
11 // Loop over them and prevent submission
Marc Kupietzf1903162023-03-10 13:54:23 +010012 var validation = Array.prototype.filter.call(forms, function(form) {
13 form.addEventListener('submit', function(event) {
Marc Kupietz484ec8e2023-02-25 11:23:07 +010014 if (form.checkValidity() === false) {
15 event.preventDefault();
16 event.stopPropagation();
17 }
Marc Kupietz8b80c7a2023-03-28 21:41:39 +020018 update_total_due();
Marc Kupietz6eb2c9f2023-03-30 17:13:52 +020019 update_paper_id_field();
Marc Kupietz484ec8e2023-02-25 11:23:07 +010020 form.classList.add('was-validated');
21 }, false);
22 });
23 }, false);
Marc Kupietz8b80c7a2023-03-28 21:41:39 +020024 window.addEventListener('popstate', function(event) {
25 update_total_due();
Marc Kupietz6eb2c9f2023-03-30 17:13:52 +020026 update_paper_id_field();
Marc Kupietz8b80c7a2023-03-28 21:41:39 +020027 }, false);
Marc Kupietz484ec8e2023-02-25 11:23:07 +010028})();
29
Marc Kupietz145f5b92023-03-09 20:39:31 +010030function update_total_due() {
Marc Kupietz0be2b462023-03-08 09:29:11 +010031 var costs = 0;
Marc Kupietz0dbe6b62023-03-21 17:58:11 +010032 var vegetarian_dinner = $("#vegetarian_dinner");
Marc Kupietz0be2b462023-03-08 09:29:11 +010033
Marc Kupietz0dbe6b62023-03-21 17:58:11 +010034 if ($('#conference_dinner').is(":checked")) {
35 vegetarian_dinner.removeAttr('disabled');
36 } else {
37 vegetarian_dinner.attr('disabled', 'disabled');
38 }
Marc Kupietz0be2b462023-03-08 09:29:11 +010039
40 if ($('#participate').is(":checked")) {
Marc Kupietzf1903162023-03-10 13:54:23 +010041 costs += parseInt($("#conference_fee").text(), 10);
Marc Kupietz0be2b462023-03-08 09:29:11 +010042 if ($('#student').is(":checked")) {
43 costs -= parseInt($("#student_discount").text(), 10);
44 }
45 if ($('#conference_dinner').is(":checked")) {
46 costs += parseInt($("#conference_dinner_price").text(), 10);
47 }
Marc Kupietz8b80c7a2023-03-28 21:41:39 +020048 if ($('#excursion').is(":checked")) {
49 costs += parseInt($("#excursion_price").text(), 10);
50 }
Marc Kupietz79eaa0b2023-03-16 17:33:43 +010051 const lunches = ["lunch_day_1", "lunch_day_2", "lunch_day_3"];
52 lunches.forEach(function(lunch) {
53 if ($("input[name='" + lunch + "']:checked").val() != "--") {
54 costs += parseInt($("#lunch_costs").text().replace(/[^0-9]/g, ''), 10) / 100;
55 }
56 });
Marc Kupietz0be2b462023-03-08 09:29:11 +010057 }
Marc Kupietzf1903162023-03-10 13:54:23 +010058 $("#total_due").val(costs.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }));
Marc Kupietz0be2b462023-03-08 09:29:11 +010059}
60
61function update_paper_id_field() {
62 var paper_id = $("#paper_id");
63 if ($('#author').is(":checked")) {
64 paper_id.removeAttr('disabled');
Marc Kupietz6eb2c9f2023-03-30 17:13:52 +020065 paper_id.attr('pattern', '[1-9]\\d{0,3}');
Marc Kupietz0be2b462023-03-08 09:29:11 +010066 paper_id.attr('required', 'required');
Marc Kupietzce13e962023-03-21 17:54:33 +010067 val = paper_id.val();
Marc Kupietz6eb2c9f2023-03-30 17:13:52 +020068 if (!val.match(/^\d{1,4}$/)) {
Marc Kupietzce13e962023-03-21 17:54:33 +010069 paper_id.val('');
70 }
Marc Kupietz0be2b462023-03-08 09:29:11 +010071 } else {
Marc Kupietz0be2b462023-03-08 09:29:11 +010072 paper_id.attr('disabled', 'disabled');
Marc Kupietzce13e962023-03-21 17:54:33 +010073 paper_id.val('');
Marc Kupietz0be2b462023-03-08 09:29:11 +010074 paper_id.removeAttr('placeholder');
75 paper_id.removeAttr('pattern');
76 paper_id.removeAttr('required');
77 }
78}
Marc Kupietz484ec8e2023-02-25 11:23:07 +010079
80function check_password_match() {
81 pass = $("#pw1").val();
82 pass2 = $("#pw2").val();
83
84 if (pass2.length > 0) {
85 $("#pwconfirm")[0].classList.add('was-validated')
86 if (pass != pass2) {
87 $("#pw2")[0].setCustomValidity("Passwords do not match");
88 } else {
89 $("#pw2")[0].setCustomValidity(""); // is valid
90 }
91 } else {
92 $("#pwconfirm")[0].classList.remove('was-validated')
93 }
94 passUpdated();
95}
96
97TOO_SHORT = 'Password too short, still %% characters needed';
98TOO_LONG = 'Password too long, please remove %% characters';
99INVALID_CHARS = 'Password contains invalid characters';
100QUAL_NONE = 'Password is very weak'
101QUAL_LOW = 'Password is weak';
102QUAL_MEDIUM = 'Password is average'
103QUAL_GOOD = 'Password is good';
104QUAL_STRONG = 'Password is strong';
105REP_OK = 'Repetition ok';
106REP_NE = 'Passwords not identical';
107PWNED = 'Password found in public password list';
108
Marc Kupietzf1903162023-03-10 13:54:23 +0100109String.prototype.strReverse = function() {
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100110 var newstring = '';
111 for (var s = 0; s < this.length; s++)
112 newstring = this.charAt(s) + newstring;
113 return newstring;
114};
115
116function isPasswordPwned(pass, callback) {
117 const sha1Hash = CryptoJS.enc.Hex.stringify(CryptoJS.SHA1(pass)).toUpperCase();
118 const passwordChunk1 = sha1Hash.substring(0, 5);
119 const passwordChunk2 = sha1Hash.substring(5);
Marc Kupietzf1903162023-03-10 13:54:23 +0100120 $.get('https://api.pwnedpasswords.com/range/' + passwordChunk1).done(function(data, status) {
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100121 var isPwned = false;
122 if (status == "success") {
123 if (data && data.length) {
124 const chunks = data.split('\r\n');
125 const matches = chunks.filter(s => s.includes(passwordChunk2));
126
127 if (matches.length) {
128 isPwned = true
129 }
130 }
131 callback(isPwned)
132 }
133 });
134}
135
136//var checkTimer;
137
138function passUpdated() {
139 var nScore = 0;
140 var message = '';
141
142 var pass = $('#pw1').val();
143 var pass2 = $('#pw2').val();
144
145 //clearTimeout(checkTimer);
146
147 try {
148 if (!pass)
149 throw '';
150
151 if (pass.match(/[^a-zA-Z0-9!@#$%()_+=:;",.?/-]/))
152 throw INVALID_CHARS;
153
154 var nLength = pass.length;
155 if (nLength < 8)
156 throw TOO_SHORT.replace('%%', 8 - nLength);
157 if (nLength > 20)
158 throw TOO_LONG.replace('%%', nLength - 20);
159
160 nScore = 4 * nLength;
161
162 // check for upper-/lowercase, numeric and special chars pattern matches
Marc Kupietzf1903162023-03-10 13:54:23 +0100163 var nAlphaUC = 0,
164 nAlphaLC = 0,
165 nNumber = 0,
166 nSpecial = 0;
167 var nMidChar = 0,
168 nRepChar = 0,
169 nRepInc = 0;
170 var nConsecAlphaUC = 0,
171 nConsecAlphaLC = 0,
172 nConsecNumber = 0;
173 var nTmpAlphaUC = '',
174 nTmpAlphaLC = '',
175 nTmpNumber = '';
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100176 for (var i = 0; i < nLength; i++) {
Marc Kupietzf1903162023-03-10 13:54:23 +0100177 if (pass[i].match(/[A-Z]/g)) { // uppercase characters
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100178 if (nTmpAlphaUC !== '' && (nTmpAlphaUC + 1) == i) {
179 nConsecAlphaUC++;
180 }
181 nTmpAlphaUC = i;
182 nAlphaUC++;
Marc Kupietzf1903162023-03-10 13:54:23 +0100183 } else if (pass[i].match(/[a-z]/g)) { // lowercase characters
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100184 if (nTmpAlphaLC !== '' && (nTmpAlphaLC + 1) == i) {
185 nConsecAlphaLC++;
186 }
187 nTmpAlphaLC = i;
188 nAlphaLC++;
Marc Kupietzf1903162023-03-10 13:54:23 +0100189 } else if (pass[i].match(/[0-9]/g)) { // numbers
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100190 if (i > 0 && i < (nLength - 1)) {
191 nMidChar++;
192 }
193 if (nTmpNumber !== '' && (nTmpNumber + 1) == i) {
194 nConsecNumber++;
195 }
196 nTmpNumber = i;
197 nNumber++;
Marc Kupietzf1903162023-03-10 13:54:23 +0100198 } else { // special characters
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100199 if (i > 0 && i < (nLength - 1)) {
200 nMidChar++;
201 }
202 nSpecial++;
203 }
204
205 // check for repeated characters
206 var bCharExists = false;
207 for (var j = 0; j < nLength; j++) {
208 if (pass[i] == pass[j] && i != j) {
209 bCharExists = true;
210 nRepInc += Math.abs(nLength / (j - i));
211 }
212 }
213 if (bCharExists) {
214 nRepChar++;
215 var nUnqChar = nLength - nRepChar;
216 nRepInc = (nUnqChar) ? Math.ceil(nRepInc / nUnqChar) : Math.ceil(nRepInc);
217 }
218 }
219
220 // check for sequential alpha string patterns (forward and reverse)
221 var sAlphas = "abcdefghijklmnopqrstuvwxyz";
222 var nSeqAlpha = 0;
223 for (var i = 0; i < 23; i++) {
224 var sFwd = sAlphas.substring(i, i + 3);
225 var sRev = sFwd.strReverse();
Marc Kupietzf1903162023-03-10 13:54:23 +0100226 if (pass.toLowerCase().indexOf(sFwd) != -1 ||
227 pass.toLowerCase().indexOf(sRev) != -1)
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100228 nSeqAlpha++;
229 }
230
231 // check for sequential numeric string patterns (forward and reverse)
232 var sNumerics = "01234567890";
233 var nSeqNumber = 0;
234 for (var i = 0; i < 8; i++) {
235 var sFwd = sNumerics.substring(i, i + 3);
236 var sRev = sFwd.strReverse();
Marc Kupietzf1903162023-03-10 13:54:23 +0100237 if (pass.toLowerCase().indexOf(sFwd) != -1 ||
238 pass.toLowerCase().indexOf(sRev) != -1)
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100239 nSeqNumber++;
240 }
241
242 // general point assignment
Marc Kupietzf1903162023-03-10 13:54:23 +0100243 if (nAlphaUC > 0 && nAlphaUC < nLength) // uppercase characters
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100244 nScore += 2 * (nLength - nAlphaUC);
Marc Kupietzf1903162023-03-10 13:54:23 +0100245 if (nAlphaLC > 0 && nAlphaLC < nLength) // lowercase characters
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100246 nScore += 2 * (nLength - nAlphaLC);
Marc Kupietzf1903162023-03-10 13:54:23 +0100247 if (nNumber > 0 && nNumber < nLength) // numbers
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100248 nScore += 2 * nNumber;
Marc Kupietzf1903162023-03-10 13:54:23 +0100249 if (nSpecial > 0) // special characters
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100250 nScore += 4 * nSpecial;
Marc Kupietzf1903162023-03-10 13:54:23 +0100251 if (nMidChar > 0) // mid numbers/special characters
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100252 nScore += 2 * nMidChar;
253
254 // point deductions for poor practices
Marc Kupietzf1903162023-03-10 13:54:23 +0100255 if ((nAlphaLC > 0 || nAlphaUC > 0) &&
256 nSpecial === 0 && nNumber === 0) // characters only
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100257 nScore -= nLength;
Marc Kupietzf1903162023-03-10 13:54:23 +0100258 if (nAlphaLC === 0 && nAlphaUC === 0 &&
259 nSpecial === 0 && nNumber > 0) // numbers only
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100260 nScore -= nLength;
Marc Kupietzf1903162023-03-10 13:54:23 +0100261 if (nRepChar > 0) // same character exists more than once
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100262 nScore -= nRepInc;
Marc Kupietzf1903162023-03-10 13:54:23 +0100263 if (nConsecAlphaUC > 0) // consecutive uppercase letters exist
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100264 nScore -= 2 * nConsecAlphaUC;
Marc Kupietzf1903162023-03-10 13:54:23 +0100265 if (nConsecAlphaLC > 0) // consecutive lowercase letters exist
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100266 nScore -= 2 * nConsecAlphaLC;
Marc Kupietzf1903162023-03-10 13:54:23 +0100267 if (nConsecNumber > 0) // consecutive numbers exist
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100268 nScore -= 2 * nConsecNumber;
Marc Kupietzf1903162023-03-10 13:54:23 +0100269 if (nSeqAlpha > 0) // sequential alpha strings exist (3 chars or more)
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100270 nScore -= 3 * nSeqAlpha;
Marc Kupietzf1903162023-03-10 13:54:23 +0100271 if (nSeqNumber > 0) // sequential numeric strings exist (3 chars or more)
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100272 nScore -= 3 * nSeqNumber;
273
274 // determine if mandatory requirements have been met
275 var arrChars = [nAlphaUC, nAlphaLC, nNumber, nSpecial];
276 var nReqChar = 0;
277 for (var i = 0; i < arrChars.length; i++) {
278 if (arrChars[i]) {
279 nReqChar++;
280 }
281 }
282 if (nReqChar >= arrChars.length)
283 nScore += 2 * nReqChar;
284 else if (nReqChar < arrChars.length - 1)
285 nScore -= 2 * nReqChar;
286
287 // limit points to 3..100
288 nScore = Math.max(3, Math.min(nScore, 100));
289
290 // set message according to points
291 if (nScore >= 80)
292 message = QUAL_STRONG;
293 else if (nScore >= 60)
294 message = QUAL_GOOD;
295 else if (nScore >= 40)
296 message = QUAL_MEDIUM;
297 else if (nScore >= 10)
298 message = QUAL_LOW;
299 else
300 message = QUAL_NONE;
301 } catch (error) {
302 nScore = 3;
303 message = error;
304 }
305 /*
306 if (pass.length > 0 && pass2.length > 0) {
307 message+=' / ';
308 message+=(pass == pass2) ? REP_OK : REP_NE;
309 }
310 */
311 $('#pwqinfo').val(message);
312
313 var progress = $('#pwqbar');
314 progress.width(nScore + '%');
315 progress.attr('aria-valuenow', nScore);
316 if (nScore >= 60)
317 progress.removeClass('bg-danger bg-warning').addClass('bg-success');
318 else if (nScore >= 40)
319 progress.removeClass('bg-danger bg-success').addClass('bg-warning');
320 else
321 progress.removeClass('bg-warning bg-success').addClass('bg-danger');
322
323 if (nScore >= 40) {
324 $("#password-div")[0].classList.add('was-validated');
325 $('#btn_change').prop('disabled', pass !== pass2);
326 $("#pw1")[0].setCustomValidity("");
Marc Kupietzf1903162023-03-10 13:54:23 +0100327 isPasswordPwned(pass, function(isPwned) {
Marc Kupietz484ec8e2023-02-25 11:23:07 +0100328 if (isPwned) {
329 $('#pwqinfo').val(PWNED);
330 progress.removeClass().addClass('low');
331 progress.val(3);
332 $("#pw1")[0].setCustomValidity("Password is pwned");
333 }
334 });
335 } else {
336 $("#password-div")[0].classList.add('was-validated');
337 $('#btn_change').prop('disabled', 1);
338 $("#pw1")[0].setCustomValidity("Password is to week");
339 }
340
Marc Kupietzf1903162023-03-10 13:54:23 +0100341}