Fixed email validation on server and web page

Ylian Saint-Hilaire committed May 16, 2018 at 15:49 UTC 8580f5486111618c32edcf09bc4095130a9cc0aa
6 files changed +79 -108
common.js
+3 -1
@@ -132,4 +132,6 @@ module.exports.validateString = function(str, minlen, maxlen) { return ((str !=
132 module.exports.validateInt = function(int, minval, maxval) { return ((int != null) && (typeof int == 'number') && ((minval == null) || (int >= minval)) && ((maxval == null) || (int <= maxval))); }
133 module.exports.validateArray = function (array, minlen, maxlen) { return ((array != null) && Array.isArray(array) && ((minlen == null) || (array.length >= minlen)) && ((maxlen == null) || (array.length <= maxlen))); }
134 module.exports.validateStrArray = function (array, minlen, maxlen) { if (((array != null) && Array.isArray(array)) == false) return false; for (var i in array) { if ((typeof array[i] != 'string') && ((minlen == null) || (array[i].length >= minlen)) && ((maxlen == null) || (array[i].length <= maxlen))) return false; } return true; }
135 -module.exports.validateObject = function(obj) { return ((obj != null) && (typeof obj == 'object')); }
135 +module.exports.validateObject = function (obj) { return ((obj != null) && (typeof obj == 'object')); }
136 +module.exports.validateEmail = function (email, minlen, maxlen) { if (module.exports.validateString(email, minlen, maxlen) == false) return false; var emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; return emailReg.test(email); }
137 +module.exports.validateUsername = function (username, minlen, maxlen) { return (module.exports.validateString(username, minlen, maxlen) && (username.indexOf(' ') == -1)); }
\ No newline at end of file
meshuser.js
+33 -35
@@ -341,41 +341,38 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
341 case 'changeemail':
342 {
343 // Change the email address
344 - if (obj.common.validateString(command.email, 3, 1024) == false) return;
345 - var x = command.email.split('@');
346 - if ((x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2)) {
347 - if (obj.parent.users[req.session.userid].email != command.email) {
348 - // Check if this email is already validated on a different account
349 - obj.db.GetUserWithVerifiedEmail(domain.id, command.email, function (err, docs) {
350 - if (docs.length > 0) {
351 - // Notify the duplicate email error
352 - ws.send(JSON.stringify({ action: 'msg', type: 'notify', value: 'Failed to change email address, another account already using: <b>' + EscapeHtml(command.email) + '</b>.' }));
344 + if (obj.common.validateEmail(command.email, 1, 256) == false) return;
345 + if (obj.parent.users[req.session.userid].email != command.email) {
346 + // Check if this email is already validated on a different account
347 + obj.db.GetUserWithVerifiedEmail(domain.id, command.email, function (err, docs) {
348 + if (docs.length > 0) {
349 + // Notify the duplicate email error
350 + ws.send(JSON.stringify({ action: 'msg', type: 'notify', value: 'Failed to change email address, another account already using: <b>' + EscapeHtml(command.email) + '</b>.' }));
351 + } else {
352 + // Update the user's email
353 + var oldemail = user.email;
354 + user.email = command.email;
355 + user.emailVerified = false;
356 + obj.parent.db.SetUser(user);
357 +
358 + // Event the change
359 + var userinfo = obj.common.Clone(user);
360 + delete userinfo.hash;
361 + delete userinfo.passhint;
362 + delete userinfo.salt;
363 + delete userinfo.type;
364 + delete userinfo.domain;
365 + delete userinfo.subscriptions;
366 + delete userinfo.passtype;
367 + var message = { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', domain: domain.id };
368 + if (oldemail != null) {
369 + message.msg = 'Changed email of user ' + userinfo.name + ' from ' + oldemail + ' to ' + user.email;
370 } else {
354 - // Update the user's email
355 - var oldemail = user.email;
356 - user.email = command.email;
357 - user.emailVerified = false;
358 - obj.parent.db.SetUser(user);
359 -
360 - // Event the change
361 - var userinfo = obj.common.Clone(user);
362 - delete userinfo.hash;
363 - delete userinfo.passhint;
364 - delete userinfo.salt;
365 - delete userinfo.type;
366 - delete userinfo.domain;
367 - delete userinfo.subscriptions;
368 - delete userinfo.passtype;
369 - var message = { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', domain: domain.id };
370 - if (oldemail != null) {
371 - message.msg = 'Changed email of user ' + userinfo.name + ' from ' + oldemail + ' to ' + user.email;
372 - } else {
373 - message.msg = 'Set email of user ' + userinfo.name + ' to ' + user.email;
374 - }
375 - obj.parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, message);
371 + message.msg = 'Set email of user ' + userinfo.name + ' to ' + user.email;
372 }
377 - });
378 - }
373 + obj.parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, message);
374 + }
375 + });
376 }
377 break;
378 }
@@ -435,13 +432,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
432 {
433 // Add a new user account
434 if ((user.siteadmin & 2) == 0) break;
438 - if (obj.common.validateString(command.username, 1, 64) == false) break; // Username is between 1 and 64 characters
435 + if (obj.common.validateUsername(command.username, 1, 64) == false) break; // Username is between 1 and 64 characters, no spaces
436 if (obj.common.validateString(command.pass, 1, 256) == false) break; // Password is between 1 and 256 characters
437 + if ((command.email != null) && (obj.common.validateEmail(command.email, 1, 256) == false)) break; // Check if this is a valid email address
438 var newusername = command.username, newuserid = 'user/' + domain.id + '/' + command.username.toLowerCase();
439 if (newusername == '~') break; // This is a reserved user name
440 if (!obj.parent.users[newuserid]) {
441 var newuser = { type: 'user', _id: newuserid, name: newusername, creation: Date.now(), domain: domain.id };
444 - if (obj.common.validateString(command.email, 1, 256) == true) { newuser.email = command.email; } // Email is between 1 and 256 characters
442 + if (command.email != null) { newuser.email = command.email; } // Email
443 obj.parent.users[newuserid] = newuser;
444 // Create a user, generate a salt and hash the password
445 require('./pass').hash(command.pass, function (err, salt, hash) {
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.1.7-i",
3 + "version": "0.1.7-k",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
views/default.handlebars
+34 -45
@@ -1952,7 +1952,7 @@
1952 x += "</div>";
1953
1954 // Linux agent install
1955 - x += "<div id=agins_linux style=display:none>To add a computer to " + EscapeHtml(mesh.name) + " run the following command. Root credentails will be needed:<br />";
1955 + x += "<div id=agins_linux style=display:none>To add a computer to " + EscapeHtml(mesh.name) + " run the following command. Root credentials will be needed.<br />";
1956 x += '<textarea id=agins_linux_area rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
1957 x += "</div>";
1958
@@ -1963,7 +1963,7 @@
1963 x += "</div>";
1964
1965 // Linux agent uninstall
1966 - x += "<div id=agins_linux_un style=display:none>To remove a mesh agent, run the following command. Root credentails will be needed:<br />";
1966 + x += "<div id=agins_linux_un style=display:none>To remove a mesh agent, run the following command. Root credentials will be needed.<br />";
1967 x += '<textarea id=agins_linux_area_un rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
1968 x += "</div>";
1969
@@ -4505,7 +4505,7 @@
4505 function account_showChangeEmail() {
4506 if (xxdialogMode) return;
4507 var x = "Change your account e-mail address here.<br /><br />";
4508 - x += addHtmlValue('Email', '<input id=dp2email style=width:230px maxlength=32 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />');
4508 + x += addHtmlValue('Email', '<input id=dp2email style=width:230px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />');
4509 setDialogMode(2, "Email Address Change", 3, account_changeEmail, x);
4510 if (userinfo.email != null) { Q('dp2email').value = userinfo.email; }
4511 account_validateEmail();
@@ -4513,9 +4513,7 @@
4513 }
4514
4515 function account_validateEmail(e, email) {
4516 - var x = Q('dp2email').value.split('@');
4517 - x = (x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2) && (Q('dp2email').value.length < 1024) && (Q('dp2email').value != userinfo.email);
4518 - QE('idx_dlgOkButton', x);
4516 + QE('idx_dlgOkButton', validateEmail(Q('dp2email').value) && (Q('dp2email').value != userinfo.email));
4517 if ((x == true) && (e != null) && (e.keyCode == 13)) { dialogclose(1); }
4518 }
4519
@@ -4526,13 +4524,12 @@
4524 function account_showDeleteAccount() {
4525 if (xxdialogMode) return;
4526 var x = "To delete this account, type in the account password in both boxes below and hit ok.<br /><br />";
4529 - x += "<form action='{{{domainurl}}}deleteaccount' method='post'><table style=margin-left:80px><tr>";
4527 + x += "<form action='{{{domainurl}}}deleteaccount' method=post><table style=margin-left:80px><tr>";
4528 x += "<td align=right>Password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
4531 - x += "</tr><tr>";
4532 - x += "<td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
4533 - x += '</tr></table><br /><div style="padding:10px;margin-bottom:4px">';
4534 - x += '<input id="account_dlgCancelButton" type="button" value="Cancel" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">';
4535 - x += '<input id="account_dlgOkButton" type="submit" value="OK" style="float:right;width:80px" onclick="dialogclose(1)">';
4529 + x += "</tr><tr><td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
4530 + x += '</tr></table><br /><div style=padding:10px;margin-bottom:4px>';
4531 + x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
4532 + x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
4533 x += '</div><br /></form>';
4534 setDialogMode(2, "Delete Account", 0, null, x);
4535 account_validateDeleteAccount();
@@ -4542,15 +4539,13 @@
4539 function account_showChangePassword() {
4540 if (xxdialogMode) return;
4541 var x = "Change your account password by entering the new password twice in the boxes below.<br /><br />";
4545 - x += "<form action='{{{domainurl}}}changepassword' method='post'><table style=margin-left:60px><tr>";
4542 + x += "<form action='{{{domainurl}}}changepassword' method=post><table style=margin-left:60px><tr>";
4543 x += "<td align=right>Password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() /> <b><span id=dxPassWarn></span></b></td>";
4547 - x += "</tr><tr>";
4548 - x += "<td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() /></td>";
4549 - x += "</tr><tr>";
4550 - x += "<td align=right>Password Hint:</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off /></td>";
4551 - x += '</tr></table><br /><div style="padding:10px;margin-bottom:4px">';
4552 - x += '<input id=account_dlgCancelButton type=button value="Cancel" style="float:right;width:80px;margin-left:5px" onclick=dialogclose(0)>';
4553 - x += '<input id=account_dlgOkButton type=submit value="OK" style="float:right;width:80px" onclick="dialogclose(1)">';
4544 + x += "</tr><tr><td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() /></td>";
4545 + x += "</tr><tr><td align=right>Password Hint:</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off /></td>";
4546 + x += '</tr></table><br /><div style=padding:10px;margin-bottom:4px>';
4547 + x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
4548 + x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
4549 x += '</div><br /></form>';
4550 setDialogMode(2, "Change Password", 0, null, x);
4551 account_validateDeleteAccount();
@@ -4704,13 +4699,17 @@
4699
4700 x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>User Authorizations</th><th scope=col style=text-align:left></th></tr>';
4701
4707 - var count = 1;
4708 - for (var i in currentMesh.links) {
4709 - var rights = 'Partial Rights', r = currentMesh.links[i].rights, xusername = i.split('/')[2];
4702 + // Sort the users for this mesh
4703 + var count = 1, sortedusers = [];
4704 + for (var i in currentMesh.links) { sortedusers.push({ id: i, name: i.split('/')[2], rights: currentMesh.links[i].rights }); }
4705 + sortedusers.sort(function(a, b) { if (a.name > b.name) return 1; if (a.name < b.name) return -1; return 0; });
4706 +
4707 + // Display all users for this mesh
4708 + for (var i in sortedusers) {
4709 + var trash = '', rights = 'Partial Rights', r = sortedusers[i].rights;
4710 if (r == 0xFFFFFFFF) rights = 'Full Administrator'; else if (r == 0) rights = 'No Rights';
4711 - var trash = '';
4712 - if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0) && (rights != 0xFFFFFFFF)))) { trash = '<a onclick=p20deleteUser(event,"' + i + '") title="Remote user rights to this mesh" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
4713 - x += '<tr onclick=p20viewuser("' + i + '") style=cursor:pointer' + (((count % 2) == 0)?';background-color:#DDD':'') + '><td><div title="Mesh User" class=m2></div><div>&nbsp;' + xusername + '<div></div></div></td><td><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
4711 + if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") title="Remote user rights to this mesh" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
4712 + x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=cursor:pointer' + (((count % 2) == 0)?';background-color:#DDD':'') + '><td><div title="Mesh User" class=m2></div><div>&nbsp;' + sortedusers[i].name + '<div></div></div></td><td><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
4713 ++count;
4714 }
4715
@@ -4809,9 +4808,8 @@
4808
4809 function p20viewuser(userid) {
4810 if (xxdialogMode) return;
4812 - var cmeshrights = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
4813 - var meshrights = currentMesh.links[userid].rights;
4814 - var r = '';
4811 + userid = decodeURIComponent(userid);
4812 + var r = '', cmeshrights = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights, meshrights = currentMesh.links[userid].rights;
4813 if (meshrights == 0xFFFFFFFF) r = ', Full Administrator (all rights)'; else {
4814 if ((meshrights & 1) != 0) r += ', Edit Mesh';
4815 if ((meshrights & 2) != 0) r += ', Manage Mesh Users';
@@ -4824,26 +4822,15 @@
4822 }
4823 r = r.substring(2);
4824 if (r == '') { r = 'No Rights'; }
4827 - var x = addHtmlValue('User Name', userid.split('/')[2]);
4825 + var buttons = 1, x = addHtmlValue('User Name', userid.split('/')[2]);
4826 x += addHtmlValue('Permissions', r);
4829 - var buttons = 1;
4827 if ((('user/{{{domain}}}/' + userinfo.name.toLowerCase()) != userid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
4828 setDialogMode(2, "Mesh User", buttons, p20viewuserEx, x, userid);
4829 }
4830
4834 - function p20viewuserEx(button, userid) {
4835 - if (button != 2) return;
4836 - setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, "Confirm removal of user " + userid.split('/')[2] + "?", userid);
4837 - }
4838 -
4839 - function p20deleteUser(e, userid) {
4840 - haltEvent(e);
4841 - p20viewuserEx(2, userid);
4842 - }
4843 -
4844 - function p20viewuserEx2(button, userid) {
4845 - meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid});
4846 - }
4831 + function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, "Confirm removal of user " + userid.split('/')[2] + "?", userid); }
4832 + function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
4833 + function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid}); }
4834
4835 //
4836 // MY FILES
@@ -5216,7 +5203,8 @@
5203 }
5204
5205 function showCreateNewAccountDialogValidate() {
5219 - QE('idx_dlgOkButton', (!Q('p4name') || (Q('p4name').value.length > 0)) && Q('p4pass1').value.length > 0 && Q('p4pass1').value == Q('p4pass2').value);
5206 + if ((Q('p4email').value.length > 0) && (validateEmail(Q('p4email').value)) == false) { QE('idx_dlgOkButton', false); return; }
5207 + QE('idx_dlgOkButton', (!Q('p4name') || ((Q('p4name').value.length > 0) && (Q('p4name').value.indexOf(' ') == -1))) && Q('p4pass1').value.length > 0 && Q('p4pass1').value == Q('p4pass2').value);
5208 }
5209
5210 function showCreateNewAccountDialogEx() {
@@ -5784,6 +5772,7 @@
5772 function addHtmlValue2(t, v) { return '<div><div style=display:inline-block;float:right>' + v + '</div><div style=display:inline-block>' + t + '</div></div>'; }
5773 function parseUriArgs() { var name, r = {}, parsedUri = window.document.location.href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = parsedUri[x]; break; } case 1: { r[name] = parsedUri[x]; var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } } } return r; }
5774 function focusTextBox(x) { setTimeout(function(){ Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
5775 + function validateEmail(v) { var emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; return emailReg.test(v); }
5776
5777 </script>
5778 </body>
views/login.handlebars
+7 -25
@@ -215,19 +215,16 @@
215 }
216
217 function validateLogin(box, e) {
218 - var ok = (Q('username').value.length > 0 && Q('password').value.length > 0);
218 + var ok = ((Q('username').value.length > 0) && (Q('username').value.indexOf(' ') == -1) && (Q('password').value.length > 0));
219 QE('loginButton', ok);
220 setDialogMode(0);
221 - if ((e != null) && (e.keyCode == 13)) {
222 - if (box == 1) { Q('password').focus(); }
223 - if (box == 2) { Q('loginButton').click(); }
224 - }
221 + if ((e != null) && (e.keyCode == 13)) { if (box == 1) { Q('password').focus(); } else if (box == 2) { Q('loginButton').click(); } }
222 if (e != null) { haltEvent(e); }
223 }
224
225 function validateCreate(box,e) {
226 setDialogMode(0);
230 - var ok = ((Q('ausername').value.length > 0) && (checkEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
227 + var ok = ((Q('ausername').value.length > 0) && (Q('ausername').value.indexOf(' ') == -1) && (validateEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
228 if ((newAccountPass == 1) && (Q('anewaccountpass').value.length == 0)) { ok = false; }
229 QE('createButton', ok);
230 if (Q('apassword1').value == '') {
@@ -243,23 +240,15 @@
240 if (box == 2) { Q('apassword1').focus(); }
241 if (box == 3) { Q('apassword2').focus(); }
242 if (box == 4) { Q('apasswordhint').focus(); }
246 - if (box == 5) {
247 - if (newAccountPass == 1) {
248 - Q('anewaccountpass').focus();
249 - } else {
250 - Q('createButton').click();
251 - }
252 - }
253 - if (box == 6) {
254 - Q('createButton').click();
255 - }
243 + if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { Q('createButton').click(); } }
244 + if (box == 6) { Q('createButton').click(); }
245 }
246 if (e != null) { haltEvent(e); }
247 }
248
249 function validateReset(e) {
250 setDialogMode(0);
262 - var x = checkEmail(Q('remail').value);
251 + var x = validateEmail(Q('remail').value);
252 QE('eresetButton', x);
253 if ((e != null) && (e.keyCode == 13) && (x == true)) {
254 Q('eresetButton').click();
@@ -267,14 +256,6 @@
256 if (e != null) { haltEvent(e); }
257 }
258
270 - // Return true is the input string looks like an email address
271 - function checkEmail(str) {
272 - var x = str.split('@');
273 - var ok = ((x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2));
274 - if (ok == true) { var y = x[1].split('.'); for (var i in y) { if (y[i].length == 0) { ok = false; } } }
275 - return ok;
276 - }
277 -
259 // Return a password strength score
260 function checkPasswordStrength(password) {
261 var r = 0, letters = {}, varCount = 0, variations = { digits: /\d/.test(password), lower: /[a-z]/.test(password), upper: /[A-Z]/.test(password), nonWords: /\W/.test(password) }
@@ -328,6 +309,7 @@
309 function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
310 function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
311 function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
312 + function validateEmail(v) { var emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; return emailReg.test(v); }
313
314 </script>
315 </body>
webserver.js
+1 -1
@@ -350,7 +350,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
350 var domain = checkUserIpAddress(req, res);
351 if (domain == null) return;
352 if (domain.newaccounts == 0) { res.sendStatus(401); return; }
353 - if (!req.body.username || !req.body.email || !req.body.password1 || !req.body.password2 || (req.body.password1 != req.body.password2) || req.body.username == '~') {
353 + if (!obj.common.validateUsername(req.body.username, 1, 64) || !obj.common.validateEmail(req.body.email, 1, 256) || !obj.common.validateString(req.body.password1, 1, 256) || !obj.common.validateString(req.body.password2, 1, 256) || (req.body.password1 != req.body.password2) || req.body.username == '~') {
354 req.session.loginmode = 2;
355 req.session.error = '<b style=color:#8C001A>Unable to create account.</b>';;
356 res.redirect(domain.url);