1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-02-12 19:11:51 +00:00

Improved Windows agent crash logs and mobile phone login page

This commit is contained in:
Ylian Saint-Hilaire 2018-05-23 21:43:44 -07:00
parent 328a6ff4d6
commit 098841fdc1
12 changed files with 129 additions and 143 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.1.7-r", "version": "0.1.7-s",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -29,23 +29,19 @@
<div id=container> <div id=container>
<div id=mastheadx></div> <div id=mastheadx></div>
<div id=masthead style="background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"> <div id=masthead style="background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden">
<div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px"> <div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px">
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong> <strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
</div> </div>
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px"> <div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px">
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong> <strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
</div> </div>
</div> </div>
<div id=page_content style="overflow-y:scroll;position:absolute;bottom:32px;top:50px"> <div id=page_content style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%;display:flex;align-items:center">
<div id=column_l style="padding:10px"> <div id=column_l style="padding:10px;width:100%">
<div align=center> <table style="width:100%">
<img alt="" src=images/icons50.png width=300 height=50 />
</div>
<p>Connect to your devices anywhere using MeshCentral, the remote monitoring and management web site. Get started by creating an account if you don't have one already.</p>
<table style=width:100%>
<tr> <tr>
<td align=center> <td align=center>
<div id=loginpanel style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none"> <div id=loginpanel style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;display:none">
<form action="login" method=post> <form action="login" method=post>
<div id=message1> <div id=message1>
{{{message}}} {{{message}}}
@ -76,50 +72,52 @@
</div> </div>
</form> </form>
</div> </div>
<div id=createpanel style="background-color: #979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none"> <div id=createpanel style="display:none">
<form action=createaccount method=post> <div style="background-color: #979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both">
<div id=message2> <form action=createaccount method=post>
{{{message}}} <div id=message2>
</div> {{{message}}}
<div> </div>
<b>Account Creation</b> <div>
</div> <b>Account Creation</b>
<table> </div>
<tr> <table>
<td align=right width=100>Username:</td> <tr>
<td><input id=ausername type=text name=username onchange=validateCreate(1) maxlength=64 onkeydown=haltReturn(event) onkeyup=validateCreate(1,event) /></td> <td align=right width=100>Username:</td>
</tr> <td><input id=ausername type=text name=username onchange=validateCreate(1) maxlength=64 onkeydown=haltReturn(event) onkeyup=validateCreate(1,event) /></td>
<tr> </tr>
<td align=right width=100>Email:</td> <tr>
<td><input id=aemail type=text name=email onchange=validateCreate(2) maxlength=256 onkeydown=haltReturn(event) onkeyup=validateCreate(2,event) /></td> <td align=right width=100>Email:</td>
</tr> <td><input id=aemail type=text name=email onchange=validateCreate(2) maxlength=256 onkeydown=haltReturn(event) onkeyup=validateCreate(2,event) /></td>
<tr> </tr>
<td align=right>Password:</td> <tr>
<td><input id=apassword1 type=password name=password1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(3) onkeyup=validateCreate(3,event) /></td> <td align=right>Password:</td>
</tr> <td><input id=apassword1 type=password name=password1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(3) onkeyup=validateCreate(3,event) /></td>
<tr> </tr>
<td align=right>Password:</td> <tr>
<td><input id=apassword2 type=password name=password2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(4) onkeyup=validateCreate(4,event) /></td> <td align=right>Password:</td>
</tr> <td><input id=apassword2 type=password name=password2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(4) onkeyup=validateCreate(4,event) /></td>
<tr> </tr>
<td align=right>Pass Hint:</td> <tr>
<td><input id=apasswordhint type=text name=apasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(5) onkeyup=validateCreate(5,event) /></td> <td align=right>Pass Hint:</td>
</tr> <td><input id=apasswordhint type=text name=apasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(5) onkeyup=validateCreate(5,event) /></td>
<tr id=newAccountPass title="Enter the account creation token"> </tr>
<td align=right>Creation Token:</td> <tr id=newAccountPass title="Enter the account creation token">
<td><input id=anewaccountpass type=password name=anewaccountpass autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6) onkeyup=validateCreate(6,event) /></td> <td align=right>Creation Token:</td>
</tr> <td><input id=anewaccountpass type=password name=anewaccountpass autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6) onkeyup=validateCreate(6,event) /></td>
<tr> </tr>
<td colspan=2> <tr>
<div style=float:right><input id=createButton type=submit value="Create Account" disabled="disabled" /></div> <td colspan=2>
<div id=passWarning style="padding-top:6px"></div> <div style=float:right><input id=createButton type=submit value="Create Account" disabled="disabled" /></div>
</td> <div id=passWarning style="padding-top:6px"></div>
</tr> </td>
</table> </tr>
<hr /><a onclick=xgo(1) style=cursor:pointer>Back to login</a> </table>
</form> <hr /><a onclick=xgo(1) style=cursor:pointer>Back to login</a>
</form>
</div>
</div> </div>
<div id=resetpanel style="background-color: #979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none"> <div id=resetpanel style="background-color: #979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
<form action=resetaccount method=post> <form action=resetaccount method=post>
<div id=message3> <div id=message3>
{{{message}}} {{{message}}}

View file

@ -24,7 +24,7 @@
} }
</style> </style>
</head> </head>
<body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif"> <body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif">
<div id="container"> <div id="container">
<!-- Begin Masthead --> <!-- Begin Masthead -->
<div id=masthead style="background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"> <div id=masthead style="background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden">
@ -146,12 +146,6 @@
<p class="MsoNormal"> <p class="MsoNormal">
<span>This software uses code from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a> licensed under the <a href="http://creativecommons.org/licenses/by/2.0/uk/legalcode">http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> and its source can be downloaded from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span> <span>This software uses code from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a> licensed under the <a href="http://creativecommons.org/licenses/by/2.0/uk/legalcode">http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> and its source can be downloaded from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span>
</p> </p>
<p class="MsoNormal">
<b>8.Android LibJPEG</b>
</p>
<p class="MsoNormal">
This software uses code from <span style="color:#1F497D"><a href="https://github.com/android/platform_external_jpeg">https://github.com/android/platform_external_jpeg</a> </span>licensed under<span style="color:#1F497D"> <a href="https://github.com/android/platform_external_jpeg/blob/master/NOTICE">https://github.com/android/platform_external_jpeg/blob/master/NOTICE</a><o:p></o:p></span>
</p>
<br /> <br />
</div> </div>
</div> </div>
@ -159,7 +153,7 @@
<table cellpadding=0 cellspacing=6 style=width:100%> <table cellpadding=0 cellspacing=6 style=width:100%>
<tr> <tr>
<td style=text-align:left;color:white>{{{footer}}}</td> <td style=text-align:left;color:white>{{{footer}}}</td>
<td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href="/">Login</a></td> <td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href="/">Back</a></td>
</tr> </tr>
</table> </table>
</div> </div>

View file

@ -131,12 +131,6 @@
<p class="MsoNormal"> <p class="MsoNormal">
<span>This software uses code from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a> licensed under the <a href="http://creativecommons.org/licenses/by/2.0/uk/legalcode">http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> and its source can be downloaded from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span> <span>This software uses code from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a> licensed under the <a href="http://creativecommons.org/licenses/by/2.0/uk/legalcode">http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> and its source can be downloaded from <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span>
</p> </p>
<p class="MsoNormal">
<b>8.Android LibJPEG</b>
</p>
<p class="MsoNormal">
This software uses code from <span style="color:#1F497D"><a href="https://github.com/android/platform_external_jpeg">https://github.com/android/platform_external_jpeg</a> </span>licensed under<span style="color:#1F497D"> <a href="https://github.com/android/platform_external_jpeg/blob/master/NOTICE">https://github.com/android/platform_external_jpeg/blob/master/NOTICE</a><o:p></o:p></span>
</p>
<br /> <br />
</div> </div>
</div> </div>
@ -144,7 +138,7 @@
<table cellpadding="0" cellspacing="10" style="width: 100%"> <table cellpadding="0" cellspacing="10" style="width: 100%">
<tr> <tr>
<td style="text-align:left"></td> <td style="text-align:left"></td>
<td style="text-align:right"><a href="/">Login</a></td> <td style="text-align:right"><a href="/">Back</a></td>
</tr> </tr>
</table> </table>
</div> </div>

View file

@ -479,7 +479,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'Verified email <b>' + EscapeHtml(user.email) + '</b> for user account <b>' + EscapeHtml(user.name) + '</b>. <a href="' + domain.url + '">Go to login page</a>.' }); res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'Verified email <b>' + EscapeHtml(user.email) + '</b> for user account <b>' + EscapeHtml(user.name) + '</b>. <a href="' + domain.url + '">Go to login page</a>.' });
// Send a notification // Send a notification
obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(userinfo.email) + '</b>.' , nolog: 1 }) obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(userinfo.email) + '</b>.', nolog: 1 })
} }
}); });
} }
@ -719,7 +719,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
delete req.session.loginmode; // Clear this state, if the user hits refresh, we want to go back to the login page. delete req.session.loginmode; // Clear this state, if the user hits refresh, we want to go back to the login page.
if ((parent.config != null) && (parent.config.settings != null) && (parent.config.settings.allowframing == true)) { features += 32; } // Allow site within iframe if ((parent.config != null) && (parent.config.settings != null) && (parent.config.settings.allowframing == true)) { features += 32; } // Allow site within iframe
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
res.render(obj.path.join(__dirname, isModuleBrowser(req) ?'views/login-mobile':'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, footer: (domain.footer == null) ? '' : domain.footer }); res.render(obj.path.join(__dirname, isModuleBrowser(req) ? 'views/login-mobile' : 'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, footer: (domain.footer == null) ? '' : domain.footer });
} }
} }
@ -738,9 +738,9 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
if (req.session && req.session.userid) { if (req.session && req.session.userid) {
if (req.session.domainid != domain.id) { req.session.destroy(function () { res.redirect(domain.url); }); return; } // Check is the session is for the correct domain if (req.session.domainid != domain.id) { req.session.destroy(function () { res.redirect(domain.url); }); return; } // Check is the session is for the correct domain
var user = obj.users[req.session.userid]; var user = obj.users[req.session.userid];
res.render(obj.path.join(__dirname, isModuleBrowser(req)?'views/terms-mobile':'views/terms'), { title: domain.title, title2: domain.title2, logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' }); res.render(obj.path.join(__dirname, isModuleBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2, logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' });
} else { } else {
res.render(obj.path.join(__dirname, isModuleBrowser(req)?'views/terms-mobile':'views/terms'), { title: domain.title, title2: domain.title2 }); res.render(obj.path.join(__dirname, isModuleBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2 });
} }
} }
@ -855,7 +855,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' }); res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' });
try { res.sendFile(obj.path.resolve(__dirname, path)); } catch (e) { res.sendStatus(404); } try { res.sendFile(obj.path.resolve(__dirname, path)); } catch (e) { res.sendStatus(404); }
} else { } else {
res.render(obj.path.join(__dirname, 'views/download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "<a href='" + req.path + "?download=1'>" + filename + "</a>, " + stat.size + " byte" + ((stat.size < 2)?'':'s') + "." }); res.render(obj.path.join(__dirname, 'views/download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "<a href='" + req.path + "?download=1'>" + filename + "</a>, " + stat.size + " byte" + ((stat.size < 2) ? '' : 's') + "." });
} }
} else { } else {
res.render(obj.path.join(__dirname, 'views/download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "Invalid file link, please check the URL again." }); res.render(obj.path.join(__dirname, 'views/download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "Invalid file link, please check the URL again." });
@ -863,7 +863,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
} }
// Take a "user/domain/userid/path/file" format and return the actual server disk file path if access is allowed // Take a "user/domain/userid/path/file" format and return the actual server disk file path if access is allowed
obj.getServerFilePath = function(user, domain, path) { obj.getServerFilePath = function (user, domain, path) {
var splitpath = path.split('/'), serverpath = obj.path.join(obj.filespath, 'domain'), filename = ''; var splitpath = path.split('/'), serverpath = obj.path.join(obj.filespath, 'domain'), filename = '';
if ((splitpath.length < 3) || (splitpath[0] != 'user' && splitpath[0] != 'mesh') || (splitpath[1] != domain.id)) return null; // Basic validation if ((splitpath.length < 3) || (splitpath[0] != 'user' && splitpath[0] != 'mesh') || (splitpath[1] != domain.id)) return null; // Basic validation
var objid = splitpath[0] + '/' + splitpath[1] + '/' + splitpath[2]; var objid = splitpath[0] + '/' + splitpath[1] + '/' + splitpath[2];
@ -877,7 +877,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
} }
// Return the maximum number of bytes allowed in the user account "My Files". // Return the maximum number of bytes allowed in the user account "My Files".
obj.getQuota = function(objid, domain) { obj.getQuota = function (objid, domain) {
if (objid == null) return 0; if (objid == null) return 0;
if (objid.startsWith('user/')) { if (objid.startsWith('user/')) {
var user = obj.users[objid]; var user = obj.users[objid];
@ -1646,7 +1646,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Setup all HTTP handlers // Setup all HTTP handlers
obj.app.get('/backup.zip', handleBackupRequest); obj.app.get('/backup.zip', handleBackupRequest);
obj.app.post('/restoreserver.ashx', handleRestoreRequest); obj.app.post('/restoreserver.ashx', handleRestoreRequest);
if (parent.multiServer != null) { obj.app.ws('/meshserver.ashx', function (ws, req) { parent.multiServer.CreatePeerInServer(parent.multiServer, ws, req); } ); } if (parent.multiServer != null) { obj.app.ws('/meshserver.ashx', function (ws, req) { parent.multiServer.CreatePeerInServer(parent.multiServer, ws, req); }); }
for (var i in parent.config.domains) { for (var i in parent.config.domains) {
if (parent.config.domains[i].dns != null) { continue; } // This is a subdomain with a DNS name, no added HTTP bindings needed. if (parent.config.domains[i].dns != null) { continue; } // This is a subdomain with a DNS name, no added HTTP bindings needed.
var url = parent.config.domains[i].url; var url = parent.config.domains[i].url;
@ -1713,7 +1713,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
} }
// Force mesh agent disconnection // Force mesh agent disconnection
obj.forceMeshAgentDisconnect = function(user, domain, nodeid, disconnectMode) { obj.forceMeshAgentDisconnect = function (user, domain, nodeid, disconnectMode) {
if (nodeid == null) return; if (nodeid == null) return;
var splitnode = nodeid.split('/'); var splitnode = nodeid.split('/');
if ((splitnode.length != 3) || (splitnode[1] != domain.id)) return; // Check that nodeid is valid and part of our domain if ((splitnode.length != 3) || (splitnode[1] != domain.id)) return; // Check that nodeid is valid and part of our domain
@ -1726,7 +1726,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
} }
// Send the core module to the mesh agent // Send the core module to the mesh agent
obj.sendMeshAgentCore = function(user, domain, nodeid, core) { obj.sendMeshAgentCore = function (user, domain, nodeid, core) {
if (nodeid == null) return; if (nodeid == null) return;
var splitnode = nodeid.split('/'); var splitnode = nodeid.split('/');
if ((splitnode.length != 3) || (splitnode[1] != domain.id)) return; // Check that nodeid is valid and part of our domain if ((splitnode.length != 3) || (splitnode[1] != domain.id)) return; // Check that nodeid is valid and part of our domain
@ -1806,13 +1806,13 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Start server on a free port // Start server on a free port
CheckListenPort(obj.args.port, StartWebServer); CheckListenPort(obj.args.port, StartWebServer);
/* /*
obj.wssessions = {}; // UserId --> Array Of Sessions obj.wssessions = {}; // UserId --> Array Of Sessions
obj.wssessions2 = {}; // "UserId + SessionRnd" --> Session (Note that the SessionId is the UserId + / + SessionRnd) obj.wssessions2 = {}; // "UserId + SessionRnd" --> Session (Note that the SessionId is the UserId + / + SessionRnd)
obj.wsPeerSessions = {}; // ServerId --> Array Of "UserId + SessionRnd" obj.wsPeerSessions = {}; // ServerId --> Array Of "UserId + SessionRnd"
obj.wsPeerSessions2 = {}; // "UserId + SessionRnd" --> ServerId obj.wsPeerSessions2 = {}; // "UserId + SessionRnd" --> ServerId
obj.wsPeerSessions3 = {}; // ServerId --> UserId --> [ SessionId ] obj.wsPeerSessions3 = {}; // ServerId --> UserId --> [ SessionId ]
*/ */
// Count sessions and event any changes // Count sessions and event any changes
obj.recountSessions = function (changedSessionId) { obj.recountSessions = function (changedSessionId) {
@ -1872,10 +1872,10 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
} }
// Return true if a mobile browser is detected. // Return true if a mobile browser is detected.
// This code comes from "http://detectmobilebrowsers.com/", This is free and unencumbered software released into the public domain. For more information, please refer to the http://unlicense.org/ // This code comes from "http://detectmobilebrowsers.com/" and was modified, This is free and unencumbered software released into the public domain. For more information, please refer to the http://unlicense.org/
function isModuleBrowser(req) { function isModuleBrowser(req) {
var ua = req.headers['user-agent'].toLowerCase(); var ua = req.headers['user-agent'].toLowerCase();
return (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0, 4))); return (/(android|bb\d+|meego).+mobile|mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0, 4)));
} }
return obj; return obj;