mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-23 21:55:52 -05:00
Added portuguese, translate.js merge command.
This commit is contained in:
parent
2494f1b1d4
commit
a7c39f30c7
4
db.js
4
db.js
@ -682,7 +682,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
obj.RemoveMeshDocuments = function (id) { obj.file.deleteMany({ meshid: id }, { multi: true }); obj.file.deleteOne({ _id: 'nt' + id }); };
|
||||
obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if (docs.length == 1) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); };
|
||||
obj.DeleteDomain = function (domain, func) { obj.file.deleteMany({ domain: domain }, { multi: true }, func); };
|
||||
obj.SetUser = function (user) { if (u.subscriptions != null) { var u = Clone(user); if (u.subscriptions) { delete u.subscriptions; } obj.Set(u); } else { obj.Set(user); } };
|
||||
obj.SetUser = function (user) { if (user.subscriptions != null) { var u = Clone(user); if (u.subscriptions) { delete u.subscriptions; } obj.Set(u); } else { obj.Set(user); } };
|
||||
obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } };
|
||||
obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }).toArray(func); };
|
||||
obj.getAmtUuidMeshNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }).toArray(func); };
|
||||
@ -816,7 +816,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
obj.RemoveMeshDocuments = function (id) { obj.file.remove({ meshid: id }, { multi: true }); obj.file.remove({ _id: 'nt' + id }); };
|
||||
obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if (docs.length == 1) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); };
|
||||
obj.DeleteDomain = function (domain, func) { obj.file.remove({ domain: domain }, { multi: true }, func); };
|
||||
obj.SetUser = function (user) { if (u.subscriptions != null) { var u = Clone(user); if (u.subscriptions) { delete u.subscriptions; } obj.Set(u); } else { obj.Set(user); } };
|
||||
obj.SetUser = function (user) { if (user.subscriptions != null) { var u = Clone(user); if (u.subscriptions) { delete u.subscriptions; } obj.Set(u); } else { obj.Set(user); } };
|
||||
obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } };
|
||||
obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); };
|
||||
obj.getAmtUuidMeshNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); };
|
||||
|
72
meshrelay.js
72
meshrelay.js
@ -22,13 +22,13 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
obj.req = req; // Used in multi-server.js
|
||||
|
||||
// Check relay authentication
|
||||
if ((user == null) && (req.query.rauth != null)) {
|
||||
const rcookie = parent.parent.decodeCookie(req.query.rauth, parent.parent.loginCookieEncryptionKey, 240); // Cookie with 4 hour timeout
|
||||
if ((user == null) && (obj.req.query != null) && (obj.req.query.rauth != null)) {
|
||||
const rcookie = parent.parent.decodeCookie(obj.req.query.rauth, parent.parent.loginCookieEncryptionKey, 240); // Cookie with 4 hour timeout
|
||||
if (rcookie.ruserid != null) { obj.ruserid = rcookie.ruserid; }
|
||||
}
|
||||
|
||||
// If there is no authentication, drop this connection
|
||||
if ((obj.id != null) && (obj.id.startsWith('meshmessenger/') == false) && (obj.user == null) && (obj.ruserid == null)) { try { ws.close(); parent.parent.debug('relay', 'Relay: Connection with no authentication (' + cleanRemoteAddr(req.ip) + ')'); } catch (e) { console.log(e); } return; }
|
||||
if ((obj.id != null) && (obj.id.startsWith('meshmessenger/') == false) && (obj.user == null) && (obj.ruserid == null)) { try { ws.close(); parent.parent.debug('relay', 'Relay: Connection with no authentication (' + cleanRemoteAddr(obj.req.ip) + ')'); } catch (e) { console.log(e); } return; }
|
||||
|
||||
// Relay session count (we may remove this in the future)
|
||||
obj.relaySessionCounted = true;
|
||||
@ -58,8 +58,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
|
||||
// Disconnect this agent
|
||||
obj.close = function (arg) {
|
||||
if ((arg == 1) || (arg == null)) { try { ws.close(); parent.parent.debug('relay', 'Relay: Soft disconnect (' + cleanRemoteAddr(req.ip) + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
||||
if (arg == 2) { try { ws._socket._parent.end(); parent.parent.debug('relay', 'Relay: Hard disconnect (' + cleanRemoteAddr(req.ip) + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
||||
if ((arg == 1) || (arg == null)) { try { ws.close(); parent.parent.debug('relay', 'Relay: Soft disconnect (' + cleanRemoteAddr(obj.req.ip) + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
||||
if (arg == 2) { try { ws._socket._parent.end(); parent.parent.debug('relay', 'Relay: Hard disconnect (' + cleanRemoteAddr(obj.req.ip) + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
||||
|
||||
// Aggressive cleanup
|
||||
delete obj.id;
|
||||
@ -153,7 +153,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
// Check that at least one connection is authenticated
|
||||
if ((obj.authenticated != true) && (relayinfo.peer1.authenticated != true)) {
|
||||
ws.close();
|
||||
parent.parent.debug('relay', 'Relay without-auth: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
|
||||
parent.parent.debug('relay', 'Relay without-auth: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
|
||||
delete obj.id;
|
||||
delete obj.ws;
|
||||
delete obj.peer;
|
||||
@ -170,7 +170,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
}
|
||||
if (u1 != u2) {
|
||||
ws.close();
|
||||
parent.parent.debug('relay', 'Relay auth mismatch (' + u1 + ' != ' + u2 + '): ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
|
||||
parent.parent.debug('relay', 'Relay auth mismatch (' + u1 + ' != ' + u2 + '): ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
|
||||
delete obj.id;
|
||||
delete obj.ws;
|
||||
delete obj.peer;
|
||||
@ -196,9 +196,9 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
// Setup session recording
|
||||
var sessionUser = obj.user;
|
||||
if (sessionUser == null) { sessionUser = obj.peer.user; }
|
||||
if ((sessionUser != null) && (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(parseInt(req.query.p)) >= 0))))) {
|
||||
if ((sessionUser != null) && (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(parseInt(obj.req.query.p)) >= 0))))) {
|
||||
// Get the computer name
|
||||
parent.db.Get(req.query.nodeid, function (err, nodes) {
|
||||
parent.db.Get(obj.req.query.nodeid, function (err, nodes) {
|
||||
var xusername = '', xdevicename = '', xdevicename2 = null;
|
||||
if ((nodes != null) && (nodes.length == 1)) { xdevicename2 = nodes[0].name; xdevicename = '-' + parent.common.makeFilename(nodes[0].name); }
|
||||
|
||||
@ -222,10 +222,10 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
|
||||
} else {
|
||||
// Write the recording file header
|
||||
var metadata = { magic: 'MeshCentralRelaySession', ver: 1, userid: sessionUser._id, username: sessionUser.name, sessionid: obj.id, ipaddr1: cleanRemoteAddr(req.ip), ipaddr2: cleanRemoteAddr(obj.peer.req.ip), time: new Date().toLocaleString(), protocol: (((req == null) || (req.query == null)) ? null : req.query.p), nodeid: (((req == null) || (req.query == null)) ? null : req.query.nodeid ) };
|
||||
var metadata = { magic: 'MeshCentralRelaySession', ver: 1, userid: sessionUser._id, username: sessionUser.name, sessionid: obj.id, ipaddr1: cleanRemoteAddr(obj.req.ip), ipaddr2: cleanRemoteAddr(obj.peer.req.ip), time: new Date().toLocaleString(), protocol: (((obj.req == null) || (obj.req.query == null)) ? null : obj.req.query.p), nodeid: (((obj.req == null) || (obj.req.query == null)) ? null : obj.req.query.nodeid ) };
|
||||
if (xdevicename2 != null) { metadata.devicename = xdevicename2; }
|
||||
var firstBlock = JSON.stringify(metadata);
|
||||
recordingEntry(fd, 1, ((req.query.browser) ? 2 : 0), firstBlock, function () {
|
||||
recordingEntry(fd, 1, ((obj.req.query.browser) ? 2 : 0), firstBlock, function () {
|
||||
try { relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false }; } catch (ex) {
|
||||
try { ws.send('c'); } catch (ex) { } // Send connect to both peers, 'cr' indicates the session is being recorded.
|
||||
try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
|
||||
@ -243,21 +243,21 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
|
||||
}
|
||||
|
||||
parent.parent.debug('relay', 'Relay connected: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ' --> ' + cleanRemoteAddr(obj.peer.req.ip) + ')');
|
||||
parent.parent.debug('relay', 'Relay connected: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ' --> ' + cleanRemoteAddr(obj.peer.req.ip) + ')');
|
||||
|
||||
// Log the connection
|
||||
if (sessionUser != null) {
|
||||
var msg = 'Started relay session';
|
||||
if (req.query.p == 1) { msg = 'Started terminal session'; }
|
||||
else if (req.query.p == 2) { msg = 'Started desktop session'; }
|
||||
else if (req.query.p == 5) { msg = 'Started file management session'; }
|
||||
if (obj.req.query.p == 1) { msg = 'Started terminal session'; }
|
||||
else if (obj.req.query.p == 2) { msg = 'Started desktop session'; }
|
||||
else if (obj.req.query.p == 5) { msg = 'Started file management session'; }
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: sessionUser._id, username: sessionUser.name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.req.ip) + ' to ' + cleanRemoteAddr(req.ip), protocol: req.query.p, nodeid: req.query.nodeid };
|
||||
parent.parent.DispatchEvent(['*', sessionUser._id], obj, event);
|
||||
}
|
||||
} else {
|
||||
// Connected already, drop (TODO: maybe we should re-connect?)
|
||||
ws.close();
|
||||
parent.parent.debug('relay', 'Relay duplicate: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
|
||||
parent.parent.debug('relay', 'Relay duplicate: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
|
||||
delete obj.id;
|
||||
delete obj.ws;
|
||||
delete obj.peer;
|
||||
@ -267,14 +267,14 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
// Wait for other relay connection
|
||||
ws._socket.pause(); // Hold traffic until the other connection
|
||||
parent.wsrelays[obj.id] = { peer1: obj, state: 1, timeout: setTimeout(function () { closeBothSides(); }, 30000) };
|
||||
parent.parent.debug('relay', 'Relay holding: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ') ' + (obj.authenticated ? 'Authenticated' : ''));
|
||||
parent.parent.debug('relay', 'Relay holding: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ') ' + (obj.authenticated ? 'Authenticated' : ''));
|
||||
|
||||
// Check if a peer server has this connection
|
||||
if (parent.parent.multiServer != null) {
|
||||
var rsession = parent.wsPeerRelays[obj.id];
|
||||
if ((rsession != null) && (rsession.serverId > parent.parent.serverId)) {
|
||||
// We must initiate the connection to the peer
|
||||
parent.parent.multiServer.createPeerRelay(ws, req, rsession.serverId, req.session.userid);
|
||||
parent.parent.multiServer.createPeerRelay(ws, req, rsession.serverId, obj.req.session.userid);
|
||||
delete parent.wsrelays[obj.id];
|
||||
} else {
|
||||
// Send message to other peers that we have this connection
|
||||
@ -297,7 +297,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
if (this.logfile != null) {
|
||||
// Write data to log file then perform relay
|
||||
var xthis = this;
|
||||
recordingEntry(this.logfile.fd, 2, ((req.query.browser) ? 2 : 0), data, function () { xthis.peer.send(data, ws.flushSink); });
|
||||
recordingEntry(this.logfile.fd, 2, ((obj.req.query.browser) ? 2 : 0), data, function () { xthis.peer.send(data, ws.flushSink); });
|
||||
} else {
|
||||
// Perform relay
|
||||
this.peer.send(data, ws.flushSink);
|
||||
@ -310,7 +310,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
ws.on('error', function (err) {
|
||||
parent.relaySessionErrorCount++;
|
||||
if (obj.relaySessionCounted) { parent.relaySessionCount--; delete obj.relaySessionCounted; }
|
||||
console.log('Relay error from ' + cleanRemoteAddr(req.ip) + ', ' + err.toString().split('\r')[0] + '.');
|
||||
console.log('Relay error from ' + cleanRemoteAddr(obj.req.ip) + ', ' + err.toString().split('\r')[0] + '.');
|
||||
closeBothSides();
|
||||
});
|
||||
|
||||
@ -333,21 +333,21 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
|
||||
// Disconnect the peer
|
||||
try { if (peer.relaySessionCounted) { parent.relaySessionCount--; delete peer.relaySessionCounted; } } catch (ex) { console.log(ex); }
|
||||
parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ' --> ' + cleanRemoteAddr(peer.req.ip) + ')');
|
||||
parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ' --> ' + cleanRemoteAddr(peer.req.ip) + ')');
|
||||
try { peer.ws.close(); } catch (e) { } // Soft disconnect
|
||||
try { peer.ws._socket._parent.end(); } catch (e) { } // Hard disconnect
|
||||
|
||||
// Log the disconnection
|
||||
if (ws.time) {
|
||||
var msg = 'Ended relay session';
|
||||
if (req.query.p == 1) { msg = 'Ended terminal session'; }
|
||||
else if (req.query.p == 2) { msg = 'Ended desktop session'; }
|
||||
else if (req.query.p == 5) { msg = 'Ended file management session'; }
|
||||
if (obj.req.query.p == 1) { msg = 'Ended terminal session'; }
|
||||
else if (obj.req.query.p == 2) { msg = 'Ended desktop session'; }
|
||||
else if (obj.req.query.p == 5) { msg = 'Ended file management session'; }
|
||||
if (user) {
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: user._id, username: parent.users[user._id].name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.req.ip) + ' to ' + cleanRemoteAddr(req.ip) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: req.query.p, nodeid: req.query.nodeid };
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: user._id, username: parent.users[user._id].name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.req.ip) + ' to ' + cleanRemoteAddr(obj.req.ip) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: obj.req.query.p, nodeid: obj.req.query.nodeid };
|
||||
parent.parent.DispatchEvent(['*', user._id], obj, event);
|
||||
} else if (peer.user) {
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: peer.user._id, username: parent.users[peer.user._id].name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.req.ip) + ' to ' + cleanRemoteAddr(req.ip) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: req.query.p, nodeid: req.query.nodeid };
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: peer.user._id, username: parent.users[peer.user._id].name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.req.ip) + ' to ' + cleanRemoteAddr(obj.req.ip) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: obj.req.query.p, nodeid: obj.req.query.nodeid };
|
||||
parent.parent.DispatchEvent(['*', peer.user._id], obj, event);
|
||||
}
|
||||
}
|
||||
@ -357,7 +357,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
delete peer.ws;
|
||||
delete peer.peer;
|
||||
} else {
|
||||
parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
|
||||
parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
|
||||
}
|
||||
try { ws.close(); } catch (ex) { }
|
||||
delete parent.wsrelays[obj.id];
|
||||
@ -415,13 +415,13 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
if (obj.id == undefined) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one.
|
||||
const command = { nodeid: cookie.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id + '&rauth=' + rcookie, tcpport: cookie.tcpport, tcpaddr: cookie.tcpaddr };
|
||||
parent.parent.debug('relay', 'Relay: Sending agent tunnel command: ' + JSON.stringify(command));
|
||||
if (obj.sendAgentMessage(command, user._id, cookie.domainid) == false) { delete obj.id; parent.parent.debug('relay', 'Relay: Unable to contact this agent (' + cleanRemoteAddr(req.ip) + ')'); }
|
||||
if (obj.sendAgentMessage(command, user._id, cookie.domainid) == false) { delete obj.id; parent.parent.debug('relay', 'Relay: Unable to contact this agent (' + cleanRemoteAddr(obj.req.ip) + ')'); }
|
||||
performRelay();
|
||||
});
|
||||
return obj;
|
||||
} else if ((req.query.nodeid != null) && ((req.query.tcpport != null) || (req.query.udpport != null))) {
|
||||
} else if ((obj.req.query.nodeid != null) && ((obj.req.query.tcpport != null) || (obj.req.query.udpport != null))) {
|
||||
// We have routing instructions in the URL arguments, but first, check user access for this node.
|
||||
parent.db.Get(req.query.nodeid, function (err, docs) {
|
||||
parent.db.Get(obj.req.query.nodeid, function (err, docs) {
|
||||
if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
|
||||
const node = docs[0];
|
||||
|
||||
@ -433,14 +433,14 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
if (obj.id == null) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one.
|
||||
const rcookie = parent.parent.encodeCookie({ ruserid: user._id }, parent.parent.loginCookieEncryptionKey);
|
||||
|
||||
if (req.query.tcpport != null) {
|
||||
const command = { nodeid: req.query.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id + '&rauth=' + rcookie, tcpport: req.query.tcpport, tcpaddr: ((req.query.tcpaddr == null) ? '127.0.0.1' : req.query.tcpaddr) };
|
||||
if (obj.req.query.tcpport != null) {
|
||||
const command = { nodeid: obj.req.query.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id + '&rauth=' + rcookie, tcpport: obj.req.query.tcpport, tcpaddr: ((obj.req.query.tcpaddr == null) ? '127.0.0.1' : obj.req.query.tcpaddr) };
|
||||
parent.parent.debug('relay', 'Relay: Sending agent TCP tunnel command: ' + JSON.stringify(command));
|
||||
if (obj.sendAgentMessage(command, user._id, domain.id) == false) { delete obj.id; parent.parent.debug('relay', 'Relay: Unable to contact this agent (' + cleanRemoteAddr(req.ip) + ')'); }
|
||||
} else if (req.query.udpport != null) {
|
||||
const command = { nodeid: req.query.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id + '&rauth=' + rcookie, udpport: req.query.udpport, udpaddr: ((req.query.udpaddr == null) ? '127.0.0.1' : req.query.udpaddr) };
|
||||
if (obj.sendAgentMessage(command, user._id, domain.id) == false) { delete obj.id; parent.parent.debug('relay', 'Relay: Unable to contact this agent (' + cleanRemoteAddr(obj.req.ip) + ')'); }
|
||||
} else if (obj.req.query.udpport != null) {
|
||||
const command = { nodeid: obj.req.query.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id + '&rauth=' + rcookie, udpport: obj.req.query.udpport, udpaddr: ((obj.req.query.udpaddr == null) ? '127.0.0.1' : obj.req.query.udpaddr) };
|
||||
parent.parent.debug('relay', 'Relay: Sending agent UDP tunnel command: ' + JSON.stringify(command));
|
||||
if (obj.sendAgentMessage(command, user._id, domain.id) == false) { delete obj.id; parent.parent.debug('relay', 'Relay: Unable to contact this agent (' + cleanRemoteAddr(req.ip) + ')'); }
|
||||
if (obj.sendAgentMessage(command, user._id, domain.id) == false) { delete obj.id; parent.parent.debug('relay', 'Relay: Unable to contact this agent (' + cleanRemoteAddr(obj.req.ip) + ')'); }
|
||||
}
|
||||
performRelay();
|
||||
});
|
||||
|
1
public/translations/player-min_pt.htm
Normal file
1
public/translations/player-min_pt.htm
Normal file
File diff suppressed because one or more lines are too long
537
public/translations/player_pt.htm
Normal file
537
public/translations/player_pt.htm
Normal file
@ -0,0 +1,537 @@
|
||||
<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
|
||||
<script type="text/javascript" src="scripts/amt-desktop-0.0.2.js"></script>
|
||||
<script type="text/javascript" src="scripts/amt-terminal-0.0.2.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib-inflate.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib-adler32.js"></script>
|
||||
<script type="text/javascript" src="scripts/zlib-crc32.js"></script>
|
||||
</head>
|
||||
<body style="overflow:hidden;background-color:black">
|
||||
<div id="p11" class="noselect" style="overflow:hidden">
|
||||
<div id="deskarea0">
|
||||
<div id="deskarea1" class="areaHead">
|
||||
<div class="toright2">
|
||||
<div class="deskareaicon" title="Alternar modo de exibição" onclick="toggleAspectRatio(1)">⇲</div>
|
||||
</div>
|
||||
<div>
|
||||
<input id="OpenFileButton" type="button" value="Abrir arquivo..." onclick="openfile()">
|
||||
<span id="deskstatus"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="deskarea2" style="">
|
||||
<div class="areaProgress"><div id="progressbar" style=""></div></div>
|
||||
</div>
|
||||
<div id="deskarea3x" style="max-height:calc(100vh - 54px);height:calc(100vh - 54px);" onclick="togglePause()">
|
||||
<div id="bigok" style="display:none;left:calc((100vh / 2))"><b>✓</b></div>
|
||||
<div id="bigfail" style="display:none;left:calc((100vh / 2))"><b>✗</b></div>
|
||||
<div id="metadatadiv" style="padding:20px;color:lightgrey;text-align:left;display:none"></div>
|
||||
<div id="DeskParent">
|
||||
<canvas id="Desk" width="640" height="480"></canvas>
|
||||
</div>
|
||||
<div id="TermParent" style="display:none">
|
||||
<pre id="Term"></pre>
|
||||
</div>
|
||||
<div id="p11DeskConsoleMsg" style="display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick="clearConsoleMsg()"></div>
|
||||
</div>
|
||||
<div id="deskarea4" class="areaFoot">
|
||||
<div class="toright2">
|
||||
<div id="timespan" style="padding-top:4px;padding-right:4px">00:00:00</div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<input id="PlayButton" type="button" value="Play" disabled="disabled" onclick="play()">
|
||||
<input id="PauseButton" type="button" value="Pausa" disabled="disabled" onclick="pause()">
|
||||
<input id="RestartButton" type="button" value="Reiniciar" disabled="disabled" onclick="restart()">
|
||||
<select id="PlaySpeed" onchange="this.blur();">
|
||||
<option value="4">1/4 de velocidade</option>
|
||||
<option value="2">1/2 velocidade</option>
|
||||
<option value="1" selected="">Velocidade normal</option>
|
||||
<option value="0.5">2x velocidade</option>
|
||||
<option value="0.25">4x velocidade</option>
|
||||
<option value="0.1">10x Velocidade</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dialog" class="noselect" style="display:none">
|
||||
<div id="dialogHeader">
|
||||
<div tabindex="0" id="id_dialogclose" onclick="setDialogMode()" onkeypress="if (event.key == 'Enter') setDialogMode()">✖</div>
|
||||
<div id="id_dialogtitle"></div>
|
||||
</div>
|
||||
<div id="dialogBody">
|
||||
<div id="dialog1">
|
||||
<div id="id_dialogMessage" style=""></div>
|
||||
</div>
|
||||
<div id="dialog2" style="">
|
||||
<div id="id_dialogOptions"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="idx_dlgButtonBar">
|
||||
<input id="idx_dlgCancelButton" type="button" value="Cancelar" style="" onclick="dialogclose(0)">
|
||||
<input id="idx_dlgOkButton" type="button" value="Ok" style="" onclick="dialogclose(1)">
|
||||
<div><input id="idx_dlgDeleteButton" type="button" value="Deletar" style="display:none" onclick="dialogclose(2)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var recFile = null;
|
||||
var recFilePtr = 0;
|
||||
var recFileStartTime = 0;
|
||||
var recFileLastTime = 0;
|
||||
var recFileEndTime = 0;
|
||||
var recFileMetadata = null;
|
||||
var recFileProtocol = 0;
|
||||
var agentDesktop = null;
|
||||
var amtDesktop = null;
|
||||
var playing = false;
|
||||
var readState = 0;
|
||||
var waitTimer = null;
|
||||
var waitTimerArgs = null;
|
||||
var deskAspectRatio = 0;
|
||||
var currentDeltaTimeTotalSec = 0;
|
||||
|
||||
function start() {
|
||||
window.onresize = deskAdjust;
|
||||
document.ondrop = ondrop;
|
||||
document.ondragover = ondragover;
|
||||
document.ondragleave = ondragleave;
|
||||
document.onkeypress = onkeypress;
|
||||
Q('PlaySpeed').value = 1;
|
||||
cleanup();
|
||||
}
|
||||
|
||||
function readNextBlock(func) {
|
||||
if ((recFilePtr + 16) > recFile.size) { QS('progressbar').width = '100%'; func(-1); } else {
|
||||
var fr = new FileReader();
|
||||
fr.onload = function () {
|
||||
var type = ReadShort(this.result, 0);
|
||||
var flags = ReadShort(this.result, 2);
|
||||
var size = ReadInt(this.result, 4);
|
||||
var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
|
||||
if ((recFilePtr + 16 + size) > recFile.size) { QS('progressbar').width = '100%'; func(-1); } else {
|
||||
var fr2 = new FileReader();
|
||||
fr2.onload = function () {
|
||||
recFilePtr += (16 + size);
|
||||
if (recFileEndTime == 0) {
|
||||
// File pointer progress bar
|
||||
QS('progressbar').width = Math.floor(100 * (recFilePtr / recFile.size)) + '%';
|
||||
} else {
|
||||
// Time progress bar
|
||||
QS('progressbar').width = Math.floor(((recFileLastTime - recFileStartTime) / (recFileEndTime - recFileStartTime)) * 100) + '%';
|
||||
}
|
||||
func(type, flags, time, this.result);
|
||||
};
|
||||
fr2.readAsBinaryString(recFile.slice(recFilePtr + 16, recFilePtr + 16 + size));
|
||||
}
|
||||
};
|
||||
fr.readAsBinaryString(recFile.slice(recFilePtr, recFilePtr + 16));
|
||||
}
|
||||
}
|
||||
|
||||
function readLastBlock(func) {
|
||||
if (recFile.size < 32) { func(-1); } else {
|
||||
var fr = new FileReader();
|
||||
fr.onload = function () {
|
||||
var type = ReadShort(this.result, 0);
|
||||
var flags = ReadShort(this.result, 2);
|
||||
var size = ReadInt(this.result, 4);
|
||||
var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
|
||||
if ((type == 3) && (size == 16) && (this.result.substring(16, 32) == 'MeshCentralMCREC')) { func(type, flags, time); } else { func(-1); }
|
||||
};
|
||||
fr.readAsBinaryString(recFile.slice(recFile.size - 32, recFile.size));
|
||||
}
|
||||
}
|
||||
|
||||
function addInfo(name, value) { if (value == null) return ''; return addInfoNoEsc(name, EscapeHtml(value)); }
|
||||
|
||||
function addInfoNoEsc(name, value) {
|
||||
if (value == null) return '';
|
||||
return '<span style=color:gray>' + EscapeHtml(name) + '</span>: <span style=font-size:20px>' + value + '</span><br/>';
|
||||
}
|
||||
|
||||
function processFirstBlock(type, flags, time, data) {
|
||||
recFileProtocol = 0;
|
||||
if ((type != 1) || (flags != 0)) { cleanup(); return; }
|
||||
try { recFileMetadata = JSON.parse(data) } catch (ex) { cleanup(); return; }
|
||||
if ((recFileMetadata == null) || (recFileMetadata.magic != 'MeshCentralRelaySession') || (recFileMetadata.ver != 1)) { cleanup(); return; }
|
||||
var x = '';
|
||||
x += addInfo("Tempo", recFileMetadata.time);
|
||||
if (recFileEndTime != 0) { var secs = Math.floor((recFileEndTime - time) / 1000); x += addInfo("Duração", format("{0} segundo{1}", secs, (secs > 1) ? 's' : '')); }
|
||||
x += addInfo("Nome de usuário", recFileMetadata.username);
|
||||
x += addInfo("ID do usuário", recFileMetadata.userid);
|
||||
x += addInfo("ID da sessão", recFileMetadata.sessionid);
|
||||
if (recFileMetadata.ipaddr1 && recFileMetadata.ipaddr2) { x += addInfo("Endereços", format("{0} para {1}", recFileMetadata.ipaddr1, recFileMetadata.ipaddr2)); }
|
||||
if (recFileMetadata.devicename) { x += addInfo("Nome do Dispositivo", recFileMetadata.devicename); }
|
||||
x += addInfo("NodeID", recFileMetadata.nodeid);
|
||||
if (recFileMetadata.protocol) {
|
||||
var p = recFileMetadata.protocol;
|
||||
if (p == 1) { p = "MeshCentral Terminal"; }
|
||||
else if (p == 2) { p = "MeshCentral Desktop"; }
|
||||
else if (p == 100) { p = "Intel® AMT WSMAN"; }
|
||||
else if (p == 101) { p = "Intel® Redirecionamento AMT"; }
|
||||
x += addInfoNoEsc("Protocolo", p);
|
||||
}
|
||||
QV('DeskParent', true);
|
||||
QV('TermParent', false);
|
||||
if (recFileMetadata.protocol == 1) {
|
||||
// MeshCentral remote terminal
|
||||
recFileProtocol = 1;
|
||||
x += '<br /><br /><span style=color:gray>' + "Pressione [espaço] para reproduzir / pausar." + '</span>';
|
||||
QE('PlayButton', true);
|
||||
QE('PauseButton', false);
|
||||
QE('RestartButton', false);
|
||||
recFileStartTime = recFileLastTime = time;
|
||||
}
|
||||
else if (recFileMetadata.protocol == 2) {
|
||||
// MeshCentral remote desktop
|
||||
recFileProtocol = 2;
|
||||
x += '<br /><br /><span style=color:gray>' + "Pressione [espaço] para reproduzir / pausar." + '</span>';
|
||||
QE('PlayButton', true);
|
||||
QE('PauseButton', false);
|
||||
QE('RestartButton', false);
|
||||
recFileStartTime = recFileLastTime = time;
|
||||
agentDesktop = CreateAgentRemoteDesktop('Desk');
|
||||
agentDesktop.onScreenSizeChange = deskAdjust;
|
||||
agentDesktop.State = 3;
|
||||
deskAdjust();
|
||||
}
|
||||
else if (recFileMetadata.protocol == 101) {
|
||||
// Intel AMT Redirection
|
||||
recFileProtocol = 101;
|
||||
x += '<br /><br /><span style=color:gray>Press [space] to play/pause.</span>';
|
||||
QE('PlayButton', true);
|
||||
QE('PauseButton', false);
|
||||
QE('RestartButton', false);
|
||||
recFileStartTime = recFileLastTime = time;
|
||||
amtDesktop = CreateAmtRemoteDesktop('Desk');
|
||||
amtDesktop.onScreenSizeChange = deskAdjust;
|
||||
amtDesktop.State = 3;
|
||||
amtDesktop.Start();
|
||||
deskAdjust();
|
||||
}
|
||||
QV('metadatadiv', true);
|
||||
QH('metadatadiv', x);
|
||||
QH('deskstatus', recFile.name);
|
||||
}
|
||||
|
||||
function processBlock(type, flags, time, data) {
|
||||
if (type < 0) { pause(); return; }
|
||||
var waitTime = Math.round((time - recFileLastTime) * parseFloat(Q('PlaySpeed').value));
|
||||
if (waitTime < 5) {
|
||||
processBlockEx(type, flags, time, data);
|
||||
} else {
|
||||
waitTimerArgs = [type, flags, time, data]
|
||||
waitTimer = setTimeout(function () { waitTimer = null; processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]); }, waitTime);
|
||||
}
|
||||
}
|
||||
|
||||
function processBlockEx(type, flags, time, data) {
|
||||
if (playing == false) return;
|
||||
var flagBinary = (flags & 1) != 0, flagUser = (flags & 2) != 0;
|
||||
|
||||
// Update the clock
|
||||
var deltaTimeTotalSec = Math.floor((time - recFileStartTime) / 1000);
|
||||
if (currentDeltaTimeTotalSec != deltaTimeTotalSec) {
|
||||
currentDeltaTimeTotalSec = deltaTimeTotalSec;
|
||||
var deltaTimeHours = Math.floor(deltaTimeTotalSec / 3600);
|
||||
deltaTimeTotalSec -= (deltaTimeHours * 3600)
|
||||
var deltaTimeMinutes = Math.floor(deltaTimeTotalSec / 60);
|
||||
deltaTimeTotalSec -= (deltaTimeHours * 60)
|
||||
var deltaTimeSeconds = Math.floor(deltaTimeTotalSec);
|
||||
QH('timespan', pad2(deltaTimeHours) + ':' + pad2(deltaTimeMinutes) + ':' + pad2(deltaTimeSeconds))
|
||||
}
|
||||
|
||||
if ((type == 2) && flagBinary && !flagUser) {
|
||||
// Device --> User data
|
||||
if (recFileProtocol == 1) {
|
||||
// MeshCentral Terminal
|
||||
agentTerminal.ProcessData(data);
|
||||
} else if (recFileProtocol == 2) {
|
||||
// MeshCentral Remote Desktop
|
||||
agentDesktop.ProcessData(data);
|
||||
} else if (recFileProtocol == 101) {
|
||||
// Intel AMT KVM
|
||||
if ((readState == 0) && (rstr2hex(data) == '4100000000000000')) {
|
||||
// We are not authenticated, KVM data starts here.
|
||||
readState = 1;
|
||||
if (data.length > 8) { amtDesktop.ProcessData(data.substring(8)); }
|
||||
} else if (readState == 1) {
|
||||
amtDesktop.ProcessData(data);
|
||||
}
|
||||
}
|
||||
} else if ((type == 2) && flagBinary && flagUser) {
|
||||
// User --> Device data
|
||||
if (recFileProtocol == 101) {
|
||||
// Intel AMT KVM
|
||||
if (rstr2hex(data) == '0000000008080001000700070003050200000000') { amtDesktop.bpp = 1; } // Switch to 1 byte per pixel.
|
||||
}
|
||||
}
|
||||
|
||||
recFileLastTime = time;
|
||||
if (playing) { readNextBlock(processBlock); }
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
recFile = null;
|
||||
recFilePtr = 0;
|
||||
recFileMetadata = null;
|
||||
playing = false;
|
||||
if (agentDesktop != null) { agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height); agentDesktop = null; }
|
||||
if (amtDesktop != null) { amtDesktop.canvas.clearRect(0, 0, amtDesktop.CanvasId.width, amtDesktop.CanvasId.height); amtDesktop = null; }
|
||||
readState = 0;
|
||||
waitTimerArgs = null;
|
||||
currentDeltaTimeTotalSec = 0;
|
||||
recFileEndTime = 0;
|
||||
agentTerminal = null;
|
||||
if (waitTimer != null) { clearTimeout(waitTimer); waitTimer = null; }
|
||||
QH('deskstatus', '');
|
||||
QE('PlayButton', false);
|
||||
QE('PauseButton', false);
|
||||
QE('RestartButton', false);
|
||||
QS('progressbar').width = '0px';
|
||||
QH('timespan', '00:00:00');
|
||||
QV('metadatadiv', true);
|
||||
QH('metadatadiv', '<span style=\"font-family:Arial,Helvetica Neue,Helvetica,sans-serif;font-size:28px\">MeshCentral Session Player</span><br /><br /><span style=color:gray>' + "Arraste e solte um arquivo .mcrec ou clique em \"Abrir arquivo...\"" + '</span>');
|
||||
QV('DeskParent', true);
|
||||
QV('TermParent', false);
|
||||
}
|
||||
|
||||
function ondrop(e) {
|
||||
haltEvent(e);
|
||||
QV('bigfail', false);
|
||||
QV('bigok', false);
|
||||
|
||||
// Check if these are files we can upload, remove all folders.
|
||||
if (e.dataTransfer == null) return;
|
||||
var files = [];
|
||||
for (var i in e.dataTransfer.files) {
|
||||
if ((e.dataTransfer.files[i].type != null) && (e.dataTransfer.files[i].size != null) && (e.dataTransfer.files[i].size != 0) && (e.dataTransfer.files[i].name.endsWith('.mcrec'))) {
|
||||
files.push(e.dataTransfer.files[i]);
|
||||
}
|
||||
}
|
||||
if (files.length == 0) return;
|
||||
cleanup();
|
||||
recFile = files[0];
|
||||
recFilePtr = 0;
|
||||
readNextBlock(processFirstBlock);
|
||||
readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
|
||||
}
|
||||
|
||||
var dragtimer = null;
|
||||
function ondragover(e) {
|
||||
haltEvent(e);
|
||||
if (dragtimer != null) { clearTimeout(dragtimer); dragtimer = null; }
|
||||
var ac = true;
|
||||
QV('bigok', ac);
|
||||
QV('bigfail', !ac);
|
||||
}
|
||||
|
||||
function ondragleave(e) {
|
||||
haltEvent(e);
|
||||
dragtimer = setTimeout(function () { QV('bigfail', false); QV('bigok', false); dragtimer = null; }, 10);
|
||||
}
|
||||
|
||||
function onkeypress(e) {
|
||||
if (xxdialogMode) return;
|
||||
if (e.key == ' ') { togglePause(); haltEvent(e); }
|
||||
if (e.key == '1') { Q('PlaySpeed').value = 4; haltEvent(e); }
|
||||
if (e.key == '2') { Q('PlaySpeed').value = 2; haltEvent(e); }
|
||||
if (e.key == '3') { Q('PlaySpeed').value = 1; haltEvent(e); }
|
||||
if (e.key == '4') { Q('PlaySpeed').value = 0.5; haltEvent(e); }
|
||||
if (e.key == '5') { Q('PlaySpeed').value = 0.25; haltEvent(e); }
|
||||
if (e.key == '6') { Q('PlaySpeed').value = 0.1; haltEvent(e); }
|
||||
if (e.key == '0') { pause(); restart(); haltEvent(e); }
|
||||
}
|
||||
|
||||
function openfile() {
|
||||
var x = '<input type=file name=files id=p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />';
|
||||
setDialogMode(2, "Abrir arquivo...", 3, openfileEx, x);
|
||||
QE('idx_dlgOkButton', false);
|
||||
}
|
||||
|
||||
function openfileEx() {
|
||||
var xfiles = Q('p2fileinput').files;
|
||||
if (xfiles != null) { var files = []; for (var i in xfiles) { if ((xfiles[i].type != null) && (xfiles[i].size != null) && (xfiles[i].size != 0) && (xfiles[i].name.endsWith('.mcrec'))) { files.push(xfiles[i]); } } }
|
||||
if (files.length == 0) return;
|
||||
cleanup();
|
||||
recFile = files[0];
|
||||
recFilePtr = 0;
|
||||
readNextBlock(processFirstBlock);
|
||||
readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
|
||||
Q('OpenFileButton').blur();
|
||||
}
|
||||
|
||||
function openfileChanged() {
|
||||
var xfiles = Q('p2fileinput').files;
|
||||
if (xfiles != null) { var files = []; for (var i in xfiles) { if ((xfiles[i].type != null) && (xfiles[i].size != null) && (xfiles[i].size != 0) && (xfiles[i].name.endsWith('.mcrec'))) { files.push(xfiles[i]); } } }
|
||||
QE('idx_dlgOkButton', files.length == 1);
|
||||
}
|
||||
|
||||
function togglePause() {
|
||||
if (recFile != null) { if (playing == true) { pause(); } else { if (recFilePtr != recFile.size) { play(); } } } return false;
|
||||
}
|
||||
|
||||
function play() {
|
||||
Q('PlayButton').blur();
|
||||
if ((playing == true) || (recFileProtocol == 0)) return;
|
||||
playing = true;
|
||||
QV('metadatadiv', false);
|
||||
QE('PlayButton', false);
|
||||
QE('PauseButton', true);
|
||||
QE('RestartButton', false);
|
||||
if ((recFileProtocol == 1) && (agentTerminal == null)) {
|
||||
QV('DeskParent', false);
|
||||
QV('TermParent', true);
|
||||
agentTerminal = CreateAmtRemoteTerminal('Term', {});
|
||||
agentTerminal.State = 3;
|
||||
}
|
||||
readNextBlock(processBlock);
|
||||
}
|
||||
|
||||
function pause() {
|
||||
Q('PauseButton').blur();
|
||||
if (playing == false) return;
|
||||
playing = false;
|
||||
QE('PlayButton', recFilePtr != recFile.size);
|
||||
QE('PauseButton', false);
|
||||
QE('RestartButton', recFilePtr != 0);
|
||||
if (waitTimer != null) {
|
||||
clearTimeout(waitTimer);
|
||||
waitTimer = null;
|
||||
processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]);
|
||||
waitTimerArgs = null;
|
||||
}
|
||||
}
|
||||
|
||||
function restart() {
|
||||
Q('RestartButton').blur();
|
||||
if (playing == true) return;
|
||||
recFilePtr = 0;
|
||||
readState = 0;
|
||||
currentDeltaTimeTotalSec = 0;
|
||||
QV('metadatadiv', true);
|
||||
QE('PlayButton', true);
|
||||
QE('PauseButton', false);
|
||||
QE('RestartButton', false);
|
||||
QS('progressbar').width = '0px';
|
||||
QH('timespan', '00:00:00');
|
||||
QV('DeskParent', true);
|
||||
QV('TermParent', false);
|
||||
if (agentDesktop) {
|
||||
agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height);
|
||||
} else if (amtDesktop) {
|
||||
amtDesktop.canvas.clearRect(0, 0, amtDesktop.CanvasId.width, amtDesktop.CanvasId.height);
|
||||
amtDesktop = CreateAmtRemoteDesktop('Desk');
|
||||
amtDesktop.onScreenSizeChange = deskAdjust;
|
||||
amtDesktop.State = 3;
|
||||
amtDesktop.Start();
|
||||
} else if (agentTerminal) {
|
||||
agentTerminal = null;
|
||||
}
|
||||
}
|
||||
|
||||
function clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); }
|
||||
|
||||
// Toggle the web page to full screen
|
||||
function toggleAspectRatio(toggle) {
|
||||
if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); }
|
||||
deskAdjust();
|
||||
}
|
||||
|
||||
function deskAdjust() {
|
||||
var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
|
||||
var deskH = Q('Desk').height, deskW = Q('Desk').width;
|
||||
|
||||
if (deskAspectRatio == 2) {
|
||||
// Scale mode
|
||||
QS('Desk')['margin-top'] = null;
|
||||
QS('Desk').height = '100%';
|
||||
QS('Desk').width = '100%';
|
||||
QS('DeskParent').overflow = 'hidden';
|
||||
} else if (deskAspectRatio == 1) {
|
||||
// Zoomed mode
|
||||
QS('Desk')['margin-top'] = '0px';
|
||||
//QS('Desk')['margin-left'] = '0px';
|
||||
QS('Desk').height = deskH + 'px';
|
||||
QS('Desk').width = deskW + 'px';
|
||||
QS('DeskParent').overflow = 'scroll';
|
||||
} else {
|
||||
// Fixed aspect ratio
|
||||
if ((parentH / parentW) > (deskH / deskW)) {
|
||||
var hNew = ((deskH * parentW) / deskW) + 'px';
|
||||
//if (webPageFullScreen || fullscreen) {
|
||||
//QS('deskarea3x').height = null;
|
||||
//} else {
|
||||
// QS('deskarea3x').height = hNew;
|
||||
//QS('deskarea3x').height = null;
|
||||
//}
|
||||
QS('Desk').height = hNew;
|
||||
QS('Desk').width = '100%';
|
||||
} else {
|
||||
var wNew = ((deskW * parentH) / deskH) + 'px';
|
||||
//if (webPageFullScreen || fullscreen) {
|
||||
//QS('Desk').height = null;
|
||||
//} else {
|
||||
QS('Desk').height = '100%';
|
||||
//}
|
||||
QS('Desk').width = wNew;
|
||||
}
|
||||
QS('Desk')['margin-top'] = null;
|
||||
QS('DeskParent').overflow = 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// POPUP DIALOG
|
||||
//
|
||||
|
||||
// null = Hidden, 1 = Generic Message
|
||||
var xxdialogMode;
|
||||
var xxdialogFunc;
|
||||
var xxdialogButtons;
|
||||
var xxdialogTag;
|
||||
var xxcurrentView = -1;
|
||||
|
||||
// Display a dialog box
|
||||
// Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
|
||||
function setDialogMode(x, y, b, f, c, tag) {
|
||||
xxdialogMode = x;
|
||||
xxdialogFunc = f;
|
||||
xxdialogButtons = b;
|
||||
xxdialogTag = tag;
|
||||
QE('idx_dlgOkButton', true);
|
||||
QV('idx_dlgOkButton', b & 1);
|
||||
QV('idx_dlgCancelButton', b & 2);
|
||||
QV('id_dialogclose', (b & 2) || (b & 8));
|
||||
QV('idx_dlgDeleteButton', b & 4);
|
||||
QV('idx_dlgButtonBar', b & 7);
|
||||
if (y) QH('id_dialogtitle', y);
|
||||
for (var i = 1; i < 3; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
|
||||
QV('dialog', x);
|
||||
if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
|
||||
}
|
||||
|
||||
function dialogclose(x) {
|
||||
var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag;
|
||||
setDialogMode();
|
||||
if (((b & 8) || x) && f) f(x, t);
|
||||
}
|
||||
|
||||
function messagebox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
|
||||
function statusbox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t); }
|
||||
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
||||
function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }
|
||||
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
|
||||
|
||||
start();
|
||||
</script>
|
||||
|
||||
</body></html>
|
@ -53,7 +53,7 @@ function start() {
|
||||
|
||||
var command = null;
|
||||
if (process.argv.length > 2) { command = process.argv[2].toLowerCase(); }
|
||||
if (['check', 'extract', 'extractall', 'translate', 'translateall', 'minifyall'].indexOf(command) == -1) { command = null; }
|
||||
if (['check', 'extract', 'extractall', 'translate', 'translateall', 'minifyall', 'merge'].indexOf(command) == -1) { command = null; }
|
||||
|
||||
console.log('MeshCentral web site translator');
|
||||
if (command == null) {
|
||||
@ -77,6 +77,9 @@ function start() {
|
||||
console.log('');
|
||||
console.log(' MINIFYALL');
|
||||
console.log(' Minify the main MeshCentral english web pages.');
|
||||
console.log('');
|
||||
console.log(' MERGE [sourcefile] [tartgetfile] [language code]');
|
||||
console.log(' Merge a language from a translation file into another translation file.');
|
||||
process.exit();
|
||||
return;
|
||||
}
|
||||
@ -105,6 +108,18 @@ function start() {
|
||||
extract(process.argv[3], sources);
|
||||
}
|
||||
|
||||
// Merge one language from a language file into another language file.
|
||||
if (command == 'merge') {
|
||||
if ((process.argv.length == 6)) {
|
||||
if (fs.existsSync(process.argv[3]) == false) { console.log('Unable to find: ' + process.argv[3]); return; }
|
||||
if (fs.existsSync(process.argv[4]) == false) { console.log('Unable to find: ' + process.argv[4]); return; }
|
||||
merge(process.argv[3], process.argv[4], process.argv[5]);
|
||||
} else {
|
||||
console.log('Usage: MERGE [sourcefile] [tartgetfile] [language code]');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract or translate all MeshCentral strings
|
||||
if (command == 'extractall') { extract("translate.json", meshCentralSourceFiles); }
|
||||
if (command == 'translateall') {
|
||||
@ -180,6 +195,39 @@ function start() {
|
||||
}
|
||||
}
|
||||
|
||||
function merge(source, target, lang) {
|
||||
// Load the source language file
|
||||
var sourceLangFileData = null;
|
||||
try { sourceLangFileData = JSON.parse(fs.readFileSync(source)); } catch (ex) { }
|
||||
if ((sourceLangFileData == null) || (sourceLangFileData.strings == null)) { console.log("Invalid source language file."); process.exit(); return; }
|
||||
|
||||
// Load the target language file
|
||||
var targetLangFileData = null;
|
||||
try { targetLangFileData = JSON.parse(fs.readFileSync(target)); } catch (ex) { }
|
||||
if ((targetLangFileData == null) || (targetLangFileData.strings == null)) { console.log("Invalid target language file."); process.exit(); return; }
|
||||
|
||||
console.log('Merging ' + lang + '...');
|
||||
|
||||
// Index the target file
|
||||
var index = {};
|
||||
for (var i in targetLangFileData.strings) { if (targetLangFileData.strings[i].en != null) { index[targetLangFileData.strings[i].en] = targetLangFileData.strings[i]; } }
|
||||
|
||||
// Merge the translation
|
||||
for (var i in sourceLangFileData.strings) {
|
||||
if ((sourceLangFileData.strings[i].en != null) && (sourceLangFileData.strings[i][lang] != null) && (index[sourceLangFileData.strings[i].en] != null)) {
|
||||
index[sourceLangFileData.strings[i].en][lang] = sourceLangFileData.strings[i][lang];
|
||||
}
|
||||
}
|
||||
|
||||
// Deindex the new target file
|
||||
var targetData = { strings: [] };
|
||||
for (var i in index) { targetData.strings.push(index[i]); }
|
||||
|
||||
// Save the target back
|
||||
fs.writeFileSync(target, JSON.stringify(targetData, null, ' '), { flag: 'w+' });
|
||||
console.log('Done.');
|
||||
}
|
||||
|
||||
function translate(lang, langFile, sources, createSubDir) {
|
||||
// Load the language file
|
||||
var langFileData = null;
|
||||
|
File diff suppressed because it is too large
Load Diff
1
views/translations/agentinvite-min_pt.handlebars
Normal file
1
views/translations/agentinvite-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
294
views/translations/agentinvite_pt.handlebars
Normal file
294
views/translations/agentinvite_pt.handlebars
Normal file
@ -0,0 +1,294 @@
|
||||
<!DOCTYPE html><html><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<title>MeshCentral - Agent Installation</title>
|
||||
<style>
|
||||
.tab {
|
||||
overflow: hidden;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.tab button {
|
||||
background-color: inherit;
|
||||
float: left;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 14px 16px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.tab button:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.tab button.active {
|
||||
background-color: #8f8;
|
||||
}
|
||||
|
||||
.tabcontent {
|
||||
display: none;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
|
||||
<div id="container">
|
||||
<!-- Begin Masthead -->
|
||||
<div id="masthead" class="noselect" style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden;">
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
|
||||
<strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
|
||||
<strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
<p id="logoutControl" style="color:white;font-size:11px;margin: 10px 10px 0;">{{{logoutControl}}}</p>
|
||||
</div>
|
||||
<div id="page_leftbar">
|
||||
<div style="height:16px"></div>
|
||||
</div>
|
||||
<div id="topbar" class="noselect style3" style="height:24px;position:relative">
|
||||
<div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
|
||||
♦
|
||||
<div id="uiMenu" style="display:none">
|
||||
<div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
|
||||
<div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
|
||||
<div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
|
||||
<div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
|
||||
<h1>Instalação remota do agente<span id="groupname"></span></h1>
|
||||
<p>
|
||||
Você foi convidado a instalar um software que permitirá que um operador remoto acesse totalmente seu computador remotamente, incluindo a área de trabalho e os arquivos.
|
||||
Siga apenas as instruções abaixo se esse convite for esperado e você sabe quem acessará seu computador.
|
||||
Selecionando seu sistema operacional e siga as instruções abaixo.
|
||||
</p>
|
||||
<div>
|
||||
<div class="tab">
|
||||
<button id="twintab64" class="tablinks" onclick="openTab(event, 'wintab64')">Windows 64 Bits</button>
|
||||
<button id="twintab32" class="tablinks" onclick="openTab(event, 'wintab32')">Windows 32 Bits</button>
|
||||
<button id="tlinuxtab" class="tablinks" onclick="openTab(event, 'linuxtab')">Linux</button>
|
||||
<button id="tmacostab" class="tablinks" onclick="openTab(event, 'macostab')">MacOS</button>
|
||||
</div>
|
||||
|
||||
<div id="wintab64" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Microsoft™ Windows 64 bits</h3>
|
||||
<p><a id="win64url">Faça o download do software aqui</a>, execute-o e pressione "Install" or "Connect".</p>
|
||||
<div style="text-align:center">
|
||||
<img class="winagent-img" src="images/winagent.png">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="wintab32" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Microsoft™ Windows 32 bits</h3>
|
||||
<p><a id="win32url">Faça o download do software aqui</a>, execute-o e pressione "Install" or "Connect".</p>
|
||||
<div style="text-align:center">
|
||||
<img class="winagent-img" src="images/winagent.png">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="linuxtab" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Linux</h3>
|
||||
<p>Para instalar, recorte e cole o seguinte comando em um terminal raiz.</p>
|
||||
<div id="linuxinstall" style="font-family:courier,'courier new',monospace;margin-left:30px"></div>
|
||||
<input type="button" value="Copiar para área de transferência" style="margin-left:30px;margin-top:4px" onclick="copyToClipLinuxInstall()">
|
||||
<p>Para desinstalar, recorte e cole o seguinte comando como raiz.</p>
|
||||
<div id="unlinuxinstall" style="font-family:courier,'courier new',monospace;margin-left:30px"></div>
|
||||
<input type="button" value="Copiar para área de transferência" style="margin-left:30px;margin-top:4px" onclick="copyToClipLinuxUnInstall()">
|
||||
<br><br>
|
||||
</div>
|
||||
|
||||
<div id="macostab" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Apple™ MacOS</h3>
|
||||
<p><a id="macosurl">Faça o download do instalador aqui</a>, clique com o botão direito do mouse ou pressione "control".Em seguida, selecione "Open".</p>
|
||||
<div style="text-align:center">
|
||||
<img src="images/macosagent.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<table cellpadding="0" cellspacing="10" style="width: 100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left"></td>
|
||||
<td style="text-align:right"></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var uiMode = parseInt(getstore('uiMode', 1));
|
||||
var webPageStackMenu = false;
|
||||
var webPageFullScreen = true;
|
||||
var nightMode = (getstore('_nightMode', '0') == '1');
|
||||
var domain = '{{{domain}}}';
|
||||
var domainUrl = '{{{domainurl}}}';
|
||||
var meshid = '{{{meshid}}}';
|
||||
var serverPort = '{{{serverport}}}';
|
||||
var serverHttps = '{{{serverhttps}}}';
|
||||
var serverNoProxy = '{{{servernoproxy}}}';
|
||||
var installFlags = '{{{installflags}}}';
|
||||
var groupName = decodeURIComponent('{{{meshname}}}');
|
||||
if (groupName != '') { QH('groupname', ' for ' + groupName); }
|
||||
userInterfaceSelectMenu();
|
||||
setup();
|
||||
|
||||
// Toggle user interface menu
|
||||
function showUserInterfaceSelectMenu() {
|
||||
Q('uiViewButton1').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton2').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton3').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton4').classList.remove('uiSelectorSel');
|
||||
try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
|
||||
QV('uiMenu', (QS('uiMenu').display == 'none'));
|
||||
if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
|
||||
}
|
||||
|
||||
function userInterfaceSelectMenu(s) {
|
||||
if (s) { uiMode = s; putstore('uiMode', uiMode); }
|
||||
webPageFullScreen = (uiMode < 3);
|
||||
webPageStackMenu = true;//(uiMode > 1);
|
||||
toggleFullScreen(0);
|
||||
toggleStackMenu(0);
|
||||
QC('column_l').add('room4submenu');
|
||||
}
|
||||
|
||||
function toggleNightMode() {
|
||||
nightMode = !nightMode;
|
||||
if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
|
||||
putstore('_nightMode', nightMode ? '1' : '0');
|
||||
}
|
||||
|
||||
// Toggle the web page to full screen
|
||||
function toggleFullScreen(toggle) {
|
||||
if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
|
||||
var hide = 0;
|
||||
//if (args.hide) { hide = parseInt(args.hide); }
|
||||
if (webPageFullScreen == false) {
|
||||
QC('body').remove('menu_stack');
|
||||
QC('body').remove('fullscreen');
|
||||
QC('body').remove('arg_hide');
|
||||
//if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
|
||||
//QV('UserDummyMenuSpan', false);
|
||||
//QV('page_leftbar', false);
|
||||
} else {
|
||||
QC('body').add('fullscreen');
|
||||
if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
|
||||
//QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
|
||||
//QV('page_leftbar', true);
|
||||
}
|
||||
QV('body', true);
|
||||
}
|
||||
|
||||
// If FullScreen, toggle menu to be horisontal or vertical
|
||||
function toggleStackMenu(toggle) {
|
||||
if (webPageFullScreen == true) {
|
||||
if (toggle === 1) {
|
||||
webPageStackMenu = !webPageStackMenu;
|
||||
putstore('webPageStackMenu', webPageStackMenu);
|
||||
}
|
||||
if (webPageStackMenu == false) {
|
||||
QC('body').remove('menu_stack');
|
||||
} else {
|
||||
QC('body').add('menu_stack');
|
||||
//if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
|
||||
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
|
||||
|
||||
function openTab(evt, tabname) {
|
||||
// Declare all variables
|
||||
var i, tabcontent, tablinks;
|
||||
|
||||
// Get all elements with class="tabcontent" and hide them
|
||||
tabcontent = document.getElementsByClassName('tabcontent');
|
||||
for (i = 0; i < tabcontent.length; i++) {
|
||||
tabcontent[i].style.display = 'none';
|
||||
}
|
||||
|
||||
// Get all elements with class="tablinks" and remove the class "active"
|
||||
tablinks = document.getElementsByClassName('tablinks');
|
||||
for (i = 0; i < tablinks.length; i++) {
|
||||
tablinks[i].className = tablinks[i].className.replace(' active', '');
|
||||
}
|
||||
|
||||
// Show the current tab, and add an "active" class to the button that opened the tab
|
||||
document.getElementById(tabname).style.display = 'block';
|
||||
if (evt != null) { evt.currentTarget.className += ' active'; } else { document.getElementById('t' + tabname).className += ' active'; }
|
||||
}
|
||||
|
||||
var linuxInstall, linuxUnInstall;
|
||||
function setup() {
|
||||
var servername = window.location.hostname;
|
||||
var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
||||
|
||||
// Windows 64bit Setup
|
||||
var url = 'meshagents?id=4&meshid=' + meshid;
|
||||
if (installFlags != 0) { url += ('&installflags=' + installFlags); }
|
||||
Q('win64url').href = url;
|
||||
|
||||
// Windows 32bit Setup
|
||||
url = 'meshagents?id=3&meshid=' + meshid;
|
||||
if (installFlags != 0) { url += ('&installflags=' + installFlags); }
|
||||
Q('win32url').href = url;
|
||||
|
||||
// MacOS Setup
|
||||
url = 'meshosxagent?id=16&meshid=' + meshid;
|
||||
Q('macosurl').href = url;
|
||||
|
||||
// Linux Setup
|
||||
if (serverHttps == 1) {
|
||||
var portStr = (serverPort == 443) ? '' : (":" + serverPort);
|
||||
if (serverNoProxy == 0) {
|
||||
linuxInstall = '(wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid + '\'\r\n';
|
||||
linuxUnInstall = '(wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
|
||||
} else {
|
||||
// Server asked that agent be installed to preferably not use a HTTP proxy.
|
||||
linuxInstall = 'wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid + '\'\r\n';
|
||||
linuxUnInstall = 'wget https://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
|
||||
}
|
||||
} else {
|
||||
var portStr = (serverPort == 80) ? '' : (':' + serverPort);
|
||||
if (serverNoProxy == 0) {
|
||||
linuxInstall = '(wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 -O ./meshinstall.sh || wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid + '\'\r\n';
|
||||
linuxUnInstall = '(wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 -O ./meshinstall.sh || wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
|
||||
} else {
|
||||
// Server asked that agent be installed to preferably not use a HTTP proxy.
|
||||
linuxInstall = 'wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid + '\'\r\n';
|
||||
linuxUnInstall = 'wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
|
||||
}
|
||||
}
|
||||
QH('linuxinstall', linuxInstall);
|
||||
QH('unlinuxinstall', linuxUnInstall);
|
||||
|
||||
// Attempt to detect the most likely operating system for this browser
|
||||
if (navigator.userAgent.indexOf('Win64') >= 0) { openTab(null, 'wintab64'); }
|
||||
else if (navigator.userAgent.indexOf('Windows') >= 0) { openTab(null, 'wintab32'); }
|
||||
else if (navigator.userAgent.indexOf('Linux') >= 0) { openTab(null, 'linuxtab'); }
|
||||
else if (navigator.userAgent.indexOf('Macintosh') >= 0) { openTab(null, 'macostab'); }
|
||||
else { openTab(null, 'wintab64'); }
|
||||
}
|
||||
|
||||
function copyToClipLinuxInstall() { copyTextToClip(linuxInstall); }
|
||||
function copyToClipLinuxUnInstall() { copyTextToClip(linuxUnInstall); }
|
||||
function copyTextToClip(txt) { function selectElementText(e) { if (document.selection) { var range = document.body.createTextRange(); range.moveToElementText(e); range.select(); } else if (window.getSelection) { var range = document.createRange(); range.selectNode(e); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); } } var e = document.createElement('DIV'); e.textContent = txt; document.body.appendChild(e); selectElementText(e); document.execCommand('copy'); e.remove(); }
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body></html>
|
8706
views/translations/default-min_pt.handlebars
Normal file
8706
views/translations/default-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
1
views/translations/default-mobile-min_pt.handlebars
Normal file
1
views/translations/default-mobile-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
3391
views/translations/default-mobile_pt.handlebars
Normal file
3391
views/translations/default-mobile_pt.handlebars
Normal file
File diff suppressed because it is too large
Load Diff
9720
views/translations/default_pt.handlebars
Normal file
9720
views/translations/default_pt.handlebars
Normal file
File diff suppressed because it is too large
Load Diff
1
views/translations/download-min_pt.handlebars
Normal file
1
views/translations/download-min_pt.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>MeshCentral - Download</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>Baixar</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right>{{{rootCertLink}}} <a href=terms>Termos & Privacidade</a></table></div></div></div>
|
41
views/translations/download_pt.handlebars
Normal file
41
views/translations/download_pt.handlebars
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link type="text/css" href="/styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<title>MeshCentral - Download</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container" style="max-height:100vh">
|
||||
<div id="mastheadx"></div>
|
||||
<div id="masthead" style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden">
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px">
|
||||
<strong><font style="font-size:46px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px">
|
||||
<strong><font style="font-size:14px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_content" style="max-height:calc(100vh-138px)">
|
||||
<div id="column_l">
|
||||
<h1>Baixar</h1>
|
||||
<p style="margin-left:20px">{{{message}}}</p>
|
||||
<br>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<table cellpadding="0" cellspacing="10" style="width:100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left"></td>
|
||||
<td style="text-align:right">
|
||||
{{{rootCertLink}}}
|
||||
<a href="terms">Termos & Privacidade</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
1
views/translations/error404-min_pt.handlebars
Normal file
1
views/translations/error404-min_pt.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><title>MeshCentral</title><body id=body onload='"undefined"!=typeof startup&&startup()'style=display:none;overflow:hidden><div id=container><div id=masthead class=noselect style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_leftbar><div style=height:16px></div></div><div id=topbar class="noselect style3"style=height:24px;position:relative><div id=uiMenuButton title="Seleção da interface do usuário"onclick=showUserInterfaceSelectMenu()>♦<div id=uiMenu style=display:none><div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Interface da barra esquerda"><div class=uiSelector1></div></div><div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Interface da barra superior"><div class=uiSelector2></div></div><div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Interface de largura fixa"><div class=uiSelector3></div></div><div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Alternar modo noturno"><div class=uiSelector4></div></div></div></div></div><div id=column_l style="max-height:calc(100vh - 135px);overflow-y:auto"><div style=text-align:center;padding-top:30px;font-size:200px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:20px;font-family:Arial;color:#999>Esta página não existe</div><div style=text-align:center;padding-top:20px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Ir para o site principal</b></a></div></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=/ >Voltar</a></table></div></div><script>"use strict";var uiMode=parseInt(getstore("uiMode",1)),webPageStackMenu=!1,webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),terms="{{{terms}}}";function showUserInterfaceSelectMenu(){Q("uiViewButton1").classList.remove("uiSelectorSel"),Q("uiViewButton2").classList.remove("uiSelectorSel"),Q("uiViewButton3").classList.remove("uiSelectorSel"),Q("uiViewButton4").classList.remove("uiSelectorSel");try{Q("uiViewButton"+uiMode).classList.add("uiSelectorSel")}catch(e){}QV("uiMenu","none"==QS("uiMenu").display),nightMode&&Q("uiViewButton4").classList.add("uiSelectorSel")}function userInterfaceSelectMenu(e){e&&putstore("uiMode",uiMode=e),webPageFullScreen=uiMode<3,webPageStackMenu=!0,toggleFullScreen(0),toggleStackMenu(0),QC("column_l").add("room4submenu")}function toggleNightMode(){(nightMode=!nightMode)?QC("body").add("night"):QC("body").remove("night"),putstore("_nightMode",nightMode?"1":"0")}function toggleFullScreen(e){1===e&&putstore("webPageFullScreen",webPageFullScreen=!webPageFullScreen);0==webPageFullScreen?(QC("body").remove("menu_stack"),QC("body").remove("fullscreen"),QC("body").remove("arg_hide")):QC("body").add("fullscreen"),QV("body",!0)}function toggleStackMenu(e){1==webPageFullScreen&&(1===e&&putstore("webPageStackMenu",webPageStackMenu=!webPageStackMenu),0==webPageStackMenu?QC("body").remove("menu_stack"):QC("body").add("menu_stack"))}function putstore(e,t){try{if("undefined"==typeof localStorage)return;localStorage.setItem(e,t)}catch(e){}}function getstore(e,t){try{if("undefined"==typeof localStorage)return t;var o=localStorage.getItem(e);return null==o||null==o?t:o}catch(e){return t}}""!=terms&&QH("column_l",decodeURIComponent(terms)),QV("column_l",!0),userInterfaceSelectMenu()</script>
|
1
views/translations/error404-mobile-min_pt.handlebars
Normal file
1
views/translations/error404-mobile-min_pt.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><title>MeshCentral</title><style type=text/css>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:#000;font-size:13px;font-family:\'Trebuchet MS\',Arial,Helvetica,sans-serif"><div id=container><div id=masthead style="background:url(logo.png) 0 0;background-size:341px 50px;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><strong><font style=font-size:36px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px><strong><font style=font-size:12px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%><div id=column_l style=padding-left:10px;padding-right:10px><div style=text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:16px;font-family:Arial;color:#999>Esta página não existe</div><div style=text-align:center;padding-top:16px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Ir para o site principal</b></a></div></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table cellpadding=0 cellspacing=6 style=width:100%><tr><td style=text-align:left;color:#fff>{{{footer}}}<td style=text-align:right>{{{rootCertLink}}} <a href=/ >Voltar</a></table></div></div>
|
54
views/translations/error404-mobile_pt.handlebars
Normal file
54
views/translations/error404-mobile_pt.handlebars
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html><html><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<title>MeshCentral</title>
|
||||
<style type="text/css">
|
||||
a {
|
||||
color: #036;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a:hover {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<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">
|
||||
<!-- Begin Masthead -->
|
||||
<div id="masthead" style="background:url(logo.png) 0px 0px;background-size:341px 50px;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">
|
||||
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px">
|
||||
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
|
||||
<div id="column_l" style="padding-left:10px;padding-right:10px">
|
||||
<div style="text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb"><b>404</b></div>
|
||||
<div style="text-align:center;font-size:16px;font-family:Arial;color:#999">Esta página não existe</div>
|
||||
<div style="text-align:center;padding-top:16px;font-size:20px;font-family:Arial;color:#999"><a href="/" style="text-decoration:none"><b>Ir para o site principal</b></a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
|
||||
<table cellpadding="0" cellspacing="6" style="width:100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left;color:white">{{{footer}}}</td>
|
||||
<td style="text-align:right">{{{rootCertLink}}} <a href="/">Voltar</a></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body></html>
|
131
views/translations/error404_pt.handlebars
Normal file
131
views/translations/error404_pt.handlebars
Normal file
@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html><html><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<title>MeshCentral</title>
|
||||
</head>
|
||||
<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
|
||||
<div id="container">
|
||||
<!-- Begin Masthead -->
|
||||
<div id="masthead" class="noselect" style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden;">
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
|
||||
<strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
|
||||
<strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_leftbar">
|
||||
<div style="height:16px"></div>
|
||||
</div>
|
||||
<div id="topbar" class="noselect style3" style="height:24px;position:relative">
|
||||
<div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
|
||||
♦
|
||||
<div id="uiMenu" style="display:none">
|
||||
<div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
|
||||
<div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
|
||||
<div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
|
||||
<div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
|
||||
<div style="text-align:center;padding-top:30px;font-size:200px;font-family:Arial;color:#bbb"><b>404</b></div>
|
||||
<div style="text-align:center;font-size:20px;font-family:Arial;color:#999">Esta página não existe</div>
|
||||
<div style="text-align:center;padding-top:20px;font-size:20px;font-family:Arial;color:#999"><a href="/" style="text-decoration:none"><b>Ir para o site principal</b></a></div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<table cellpadding="0" cellspacing="10" style="width: 100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left"></td>
|
||||
<td style="text-align:right"><a href="/">Voltar</a></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var uiMode = parseInt(getstore('uiMode', 1));
|
||||
var webPageStackMenu = false;
|
||||
var webPageFullScreen = true;
|
||||
var nightMode = (getstore('_nightMode', '0') == '1');
|
||||
|
||||
var terms = '{{{terms}}}';
|
||||
if (terms != '') { QH('column_l', decodeURIComponent(terms)); }
|
||||
QV('column_l', true);
|
||||
userInterfaceSelectMenu();
|
||||
|
||||
// Toggle user interface menu
|
||||
function showUserInterfaceSelectMenu() {
|
||||
Q('uiViewButton1').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton2').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton3').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton4').classList.remove('uiSelectorSel');
|
||||
try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
|
||||
QV('uiMenu', (QS('uiMenu').display == 'none'));
|
||||
if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
|
||||
}
|
||||
|
||||
function userInterfaceSelectMenu(s) {
|
||||
if (s) { uiMode = s; putstore('uiMode', uiMode); }
|
||||
webPageFullScreen = (uiMode < 3);
|
||||
webPageStackMenu = true;//(uiMode > 1);
|
||||
toggleFullScreen(0);
|
||||
toggleStackMenu(0);
|
||||
QC('column_l').add('room4submenu');
|
||||
}
|
||||
|
||||
function toggleNightMode() {
|
||||
nightMode = !nightMode;
|
||||
if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
|
||||
putstore('_nightMode', nightMode ? '1' : '0');
|
||||
}
|
||||
|
||||
// Toggle the web page to full screen
|
||||
function toggleFullScreen(toggle) {
|
||||
if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
|
||||
var hide = 0;
|
||||
//if (args.hide) { hide = parseInt(args.hide); }
|
||||
if (webPageFullScreen == false) {
|
||||
QC('body').remove('menu_stack');
|
||||
QC('body').remove('fullscreen');
|
||||
QC('body').remove('arg_hide');
|
||||
//if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
|
||||
//QV('UserDummyMenuSpan', false);
|
||||
//QV('page_leftbar', false);
|
||||
} else {
|
||||
QC('body').add('fullscreen');
|
||||
if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
|
||||
//QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
|
||||
//QV('page_leftbar', true);
|
||||
}
|
||||
QV('body', true);
|
||||
}
|
||||
|
||||
// If FullScreen, toggle menu to be horisontal or vertical
|
||||
function toggleStackMenu(toggle) {
|
||||
if (webPageFullScreen == true) {
|
||||
if (toggle === 1) {
|
||||
webPageStackMenu = !webPageStackMenu;
|
||||
putstore('webPageStackMenu', webPageStackMenu);
|
||||
}
|
||||
if (webPageStackMenu == false) {
|
||||
QC('body').remove('menu_stack');
|
||||
} else {
|
||||
QC('body').add('menu_stack');
|
||||
//if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
|
||||
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body></html>
|
1
views/translations/login-min_pt.handlebars
Normal file
1
views/translations/login-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
1
views/translations/login-mobile-min_pt.handlebars
Normal file
1
views/translations/login-mobile-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
647
views/translations/login-mobile_pt.handlebars
Normal file
647
views/translations/login-mobile_pt.handlebars
Normal file
@ -0,0 +1,647 @@
|
||||
<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico">
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<script type="text/javascript" src="scripts/u2f-api.js"></script>
|
||||
<title>MeshCentral - Login</title>
|
||||
<style>
|
||||
a {
|
||||
color: #036;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a:hover {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</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">
|
||||
<div id="container">
|
||||
<div id="mastheadx"></div>
|
||||
<div id="masthead" style="background:url(logo.png) 0px 0px;background-size:341px 50px;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:6px">
|
||||
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<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;width:100%">
|
||||
<table style="width:100%">
|
||||
<tbody><tr>
|
||||
<td align="center">
|
||||
<div id="loginpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;display:none">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="login">
|
||||
<div id="message1"></div>
|
||||
<div>
|
||||
<b>Entrar</b>
|
||||
</div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td id="loginusername" align="right" width="100">Nome de usuário:</td>
|
||||
<td><input id="username" type="text" maxlength="64" name="username" onchange="validateLogin(1)" onkeyup="validateLogin(1,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Senha:</td>
|
||||
<td><input id="password" type="password" maxlength="256" name="password" autocomplete="off" onchange="validateLogin(2)" onkeyup="validateLogin(2,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div id="showPassHintLink" style="display:none"><a onclick="showPassHint()" style="cursor:pointer">Mostrar dica</a></div></td>
|
||||
<td align="right"><input id="loginButton" type="submit" value="Entrar" disabled="disabled"></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<div id="hrAccountDiv" style="display:none"><hr></div>
|
||||
<div id="resetAccountDiv" style="display:none;padding:2px">
|
||||
<span id="resetAccountSpan">Esqueceu usuário / senha?</span> <a onclick="xgo(3)" style="cursor:pointer">Redefinir conta</a>.
|
||||
</div>
|
||||
<div id="newAccountDiv" style="display:none;padding:2px">
|
||||
Não possui uma conta? <a onclick="xgo(2)" style="cursor:pointer">Crie um</a>.
|
||||
</div>
|
||||
<input id="loginformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div id="createpanel" style="display:none">
|
||||
<div style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;position:relative">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="createaccount">
|
||||
<div id="message2"></div>
|
||||
<div>
|
||||
<b>Criação de conta</b>
|
||||
</div>
|
||||
<div id="passwordPolicyCallout" style="left:-5px;top:10px;width:100px;position:absolute;background-color:#FFC;border-radius:5px;padding:5px;box-shadow:0px 0px 15px #666;font-size:10px"></div>
|
||||
<table>
|
||||
<tbody><tr id="nuUserRow">
|
||||
<td align="right" width="100">Nome de usuário:</td>
|
||||
<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>
|
||||
<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">Senha:</td>
|
||||
<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">Senha:</td>
|
||||
<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 id="createPanelHint" style="display:none">
|
||||
<td align="right">Dica de passe:</td>
|
||||
<td><input id="apasswordhint" type="text" name="apasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(5)" onkeyup="validateCreate(5,event)"></td>
|
||||
</tr>
|
||||
<tr id="newAccountPass" title="Insira o token de criação da conta">
|
||||
<td align="right">Token de criação</td>
|
||||
<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">
|
||||
<div style="float:right"><input id="createButton" type="submit" value="Criar conta" disabled="disabled"></div>
|
||||
<div id="passWarning" style="padding-top:6px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="createformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="resetpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="resetaccount">
|
||||
<div id="message3"></div>
|
||||
<div>
|
||||
<b>Redefinição de conta</b>
|
||||
</div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td align="right" width="100">Email:</td>
|
||||
<td><input id="remail" type="text" name="email" maxlength="256" onchange="validateReset()" onkeyup="validateReset(event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="eresetButton" type="submit" value="Redefinir Conta" disabled="disabled"></div>
|
||||
<div id="passWarning" style="padding-top:6px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="resetformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div id="tokenpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
|
||||
<form method="post" autocomplete="off">
|
||||
<input type="hidden" name="action" value="tokenlogin">
|
||||
<input type="hidden" name="hwstate" value="{{{hwstate}}}">
|
||||
<div id="message4"></div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td align="right" width="100">Token de logon:</td>
|
||||
<td>
|
||||
<input id="tokenInput" type="text" name="token" maxlength="50" onchange="checkToken(event)" onkeyup="checkToken(event)" onkeydown="checkToken(event)" onfocus="checkTokenTimer(1)" onblur="checkTokenTimer(0)">
|
||||
<input id="hwtokenInput" type="text" name="hwtoken" style="display:none">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="align-content:center">
|
||||
<label><input id="tokenInputRemember" name="remembertoken" type="checkbox">Remember this device for 30 days.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="tokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
|
||||
<div style="float:right"><input style="display:none;float:right" id="securityKeyButton" type="button" value="Use Security Key" onclick="useSecurityKey()"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="tokenformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="resettokenpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
|
||||
<form method="post" autocomplete="off">
|
||||
<input type="hidden" name="action" value="resetaccount">
|
||||
<div id="message5"></div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td align="right" width="100">Token de logon:</td>
|
||||
<td>
|
||||
<input id="resetTokenInput" type="text" name="token" maxlength="50" onchange="resetCheckToken(event)" onpaste="resetCheckToken(event)" onkeyup="resetCheckToken(event)" onkeydown="resetCheckToken(event)">
|
||||
<input id="resetHwtokenInput" type="text" name="hwtoken" style="display:none">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="resetTokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="resettokenformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="resetpasswordpanel" style="position:relative;background-color:#979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="resetpassword">
|
||||
<div id="message6"></div>
|
||||
<div id="rpasswordPolicyCallout" style="left:-10px;width:100px;display:none;position:absolute;background-color:#FFC;border-radius:5px;padding:5px;box-shadow:0px 0px 15px #666;font-size:10px"></div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td id="rnuPass1" width="100" align="right">Senha:</td>
|
||||
<td><input id="rapassword1" type="password" name="rpassword1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(3,event)" onkeyup="validatePassReset(3,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="rnuPass2" align="right">Senha:</td>
|
||||
<td><input id="rapassword2" type="password" name="rpassword2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(4,event)" onkeyup="validatePassReset(4,event)"></td>
|
||||
</tr>
|
||||
<tr id="resetpasswordpanelHint" style="display:none">
|
||||
<td id="rnuHint" align="right">Dica de senha</td>
|
||||
<td><input id="rapasswordhint" type="text" name="rpasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(5,event)" onkeyup="validatePassReset(5,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="resetPassButton" type="submit" value="Redefinir senha" disabled="disabled"></div>
|
||||
<div id="rpassWarning" style="padding-top:6px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="resetpasswordformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
|
||||
<table cellpadding="0" cellspacing="6" style="width:100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left;color:white">{{{footer}}}</td>
|
||||
<td style="text-align:right">{{{rootCertLink}}} <a href="terms">Termos & Privacidade</a></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dialog" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:180px;width:400px;display:none">
|
||||
<div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
|
||||
<div id="id_dialogclose" style="float:right;padding:5px;cursor:pointer" onclick="setDialogMode()"><b>X</b></div>
|
||||
<div id="id_dialogtitle" style="padding:5px"></div>
|
||||
<div style="width:100%;margin:6px"></div>
|
||||
</div>
|
||||
<div style="margin-right:16px;margin-left:8px">
|
||||
<div id="dialog1" style="margin:auto;text-align:center;margin:3px">
|
||||
<div id="id_dialogMessage" style="padding:10px"></div>
|
||||
</div>
|
||||
<div id="dialog2" style="margin:auto;margin:3px">
|
||||
<div id="id_dialogOptions"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="idx_dlgButtonBar" style="padding:10px;margin-bottom:20px">
|
||||
<input id="idx_dlgCancelButton" type="button" value="Cancelar" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
|
||||
<input id="idx_dlgOkButton" type="button" value="Ok" style="float:right;width:80px" onclick="dialogclose(1)">
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var loginMode = '{{{loginmode}}}';
|
||||
var newAccount = '{{{newAccount}}}';
|
||||
var passhint = '{{{passhint}}}';
|
||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||
var emailCheck = ('{{{emailcheck}}}' == 'true');
|
||||
var features = parseInt('{{{features}}}');
|
||||
var passRequirements = '{{{passRequirements}}}';
|
||||
if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
|
||||
var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
|
||||
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
||||
var publicKeyCredentialRequestOptions = null;
|
||||
var currentpanel = 0;
|
||||
|
||||
// Display the right server message
|
||||
var messageid = parseInt('{{{messageid}}}');
|
||||
var okmessages = ['', "Hold on, reset mail sent."];
|
||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."];
|
||||
if (messageid > 0) {
|
||||
var msg = '';
|
||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||
else if ((messageid >= 100) && ((messageid - 100) < failmessages.length)) { msg = failmessages[messageid - 100]; }
|
||||
if (msg != '') {
|
||||
if (messageid >= 100) { msg = ('<span class="msg error"><b style=color:#8C001A>' + msg + '<b></span><br /><br />'); } else { msg = ('<span class="msg success"><b>' + msg + '</b></span><br /><br />'); }
|
||||
for (var i = 1; i < 7; i++) { QH('message' + i, msg); }
|
||||
}
|
||||
}
|
||||
|
||||
// If URL arguments are provided, add them to form posts
|
||||
if (window.location.href.indexOf('?') > 0) {
|
||||
var urlargs = window.location.href.substring(window.location.href.indexOf('?'));
|
||||
Q('loginformargs').value = urlargs;
|
||||
Q('createformargs').value = urlargs;
|
||||
Q('resetformargs').value = urlargs;
|
||||
Q('tokenformargs').value = urlargs;
|
||||
Q('resettokenformargs').value = urlargs;
|
||||
Q('resetpasswordformargs').value = urlargs;
|
||||
}
|
||||
|
||||
function startup() {
|
||||
if ((features & 32) == 0) {
|
||||
// Guard against other site's top frames (web bugs).
|
||||
var loc = null;
|
||||
try { loc = top.location.toString().toLowerCase(); } catch (e) { }
|
||||
if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
|
||||
}
|
||||
|
||||
if (features & 0x200000) { // Email is username
|
||||
QH('loginusername', "Email:");
|
||||
QH('resetAccountSpan', "Esqueceu a senha?");
|
||||
QV('nuUserRow', false);
|
||||
}
|
||||
|
||||
QV('createPanelHint', passRequirements.hint === true);
|
||||
QV('resetpasswordpanelHint', passRequirements.hint === true);
|
||||
|
||||
window.onresize = center;
|
||||
center();
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
|
||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passRequirements.hint === true) && (passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||
QV('newAccountPass', (newAccountPass == 1));
|
||||
QV('resetAccountDiv', (emailCheck == true));
|
||||
QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
|
||||
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
|
||||
}
|
||||
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
|
||||
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('resetHwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('resetTokenOkButton', true);
|
||||
Q('resetTokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use a hardware security key
|
||||
function useSecurityKey() {
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
|
||||
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPassHint() {
|
||||
if (passRequirements.hint === true) { messagebox("Dica de Senha", passhint); }
|
||||
}
|
||||
|
||||
function xgo(x) {
|
||||
QV('message1', false);
|
||||
QV('message2', false);
|
||||
QV('message3', false);
|
||||
QV('message4', false);
|
||||
QV('message5', false);
|
||||
QV('message6', false);
|
||||
go(x);
|
||||
}
|
||||
|
||||
function go(x) {
|
||||
currentpanel = x;
|
||||
setDialogMode(0);
|
||||
QV('showPassHintLink', false);
|
||||
QV('loginpanel', x == 1);
|
||||
QV('createpanel', x == 2);
|
||||
QV('resetpanel', x == 3);
|
||||
QV('tokenpanel', x == 4);
|
||||
QV('resettokenpanel', x == 5);
|
||||
QV('resetpasswordpanel', x == 6);
|
||||
if (x == 1) { Q('username').focus(); }
|
||||
if (x == 2) { if (features & 0x200000) { Q('aemail').focus(); } else { Q('ausername').focus(); } } // Email is username
|
||||
if (x == 3) { Q('remail').focus(); }
|
||||
if (x == 4) { Q('tokenInput').focus(); }
|
||||
if (x == 5) { Q('resetTokenInput').focus(); }
|
||||
if (x == 6) { Q('rapassword1').focus(); }
|
||||
}
|
||||
|
||||
function validateLogin(box, e) {
|
||||
var ok = ((Q('username').value.length > 0) && (Q('username').value.indexOf(' ') == -1) && (Q('password').value.length > 0));
|
||||
QE('loginButton', ok);
|
||||
setDialogMode(0);
|
||||
if ((e != null) && (e.keyCode == 13)) { if (box == 1) { Q('password').focus(); } else if (box == 2) { Q('loginButton').click(); } }
|
||||
if (e != null) { haltEvent(e); }
|
||||
}
|
||||
|
||||
function validateCreate(box,e) {
|
||||
setDialogMode(0);
|
||||
var ok = false;
|
||||
if (features & 0x200000) { ok = true; } else { ok = (Q('ausername').value.length > 0) && (Q('ausername').value.indexOf(' ') == -1) && (Q('ausername').value.indexOf('"') == -1) && (Q('ausername').value.indexOf(',') == -1); }
|
||||
ok &= ((validateEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
|
||||
if ((newAccountPass == 1) && (Q('anewaccountpass').value.length == 0)) { ok = false; }
|
||||
if (Q('apassword1').value == '') {
|
||||
QH('passWarning', '');
|
||||
QV('passwordPolicyCallout', false);
|
||||
} else {
|
||||
if (!passRequirementsEx) {
|
||||
// No password requirements, display password strength
|
||||
var passStrength = checkPasswordStrength(Q('apassword1').value);
|
||||
if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
|
||||
else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
|
||||
else { QH('passWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
|
||||
} else {
|
||||
// Password requirements provided, use that
|
||||
var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
|
||||
if (passReq == false) {
|
||||
ok = false;
|
||||
//QS('nuPass1').color = '#7b241c';
|
||||
//QS('nuPass2').color = '#7b241c';
|
||||
QH('passWarning', '<span style=color:red><b>' + "Política de senha" + '</b><span>'); // TODO: Display problem hint
|
||||
QV('passwordPolicyCallout', true);
|
||||
QH('passwordPolicyCallout', passwordPolicyText(Q('apassword1').value));
|
||||
} else {
|
||||
QH('passWarning', '');
|
||||
QV('passwordPolicyCallout', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
QE('createButton', ok);
|
||||
if ((e != null) && (e.keyCode == 13)) {
|
||||
if (box == 1) { Q('aemail').focus(); }
|
||||
if (box == 2) { Q('apassword1').focus(); }
|
||||
if (box == 3) { Q('apassword2').focus(); }
|
||||
if (box == 4) { Q('apasswordhint').focus(); }
|
||||
if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { Q('createButton').click(); } }
|
||||
if (box == 6) { Q('createButton').click(); }
|
||||
}
|
||||
if (e != null) { haltEvent(e); }
|
||||
}
|
||||
|
||||
function validatePassReset(box, e) {
|
||||
setDialogMode(0);
|
||||
var pass1ok = (Q('rapassword1').value.length > 0);
|
||||
var pass2ok = (Q('rapassword2').value.length > 0) && (Q('rapassword2').value == Q('rapassword1').value);
|
||||
var ok = (pass1ok && pass2ok);
|
||||
|
||||
// Color the fields
|
||||
QS('rnuPass1').color = pass1ok ? 'black' : '#7b241c';
|
||||
QS('rnuPass2').color = pass2ok ? 'black' : '#7b241c';
|
||||
|
||||
if (Q('rapassword1').value == '') {
|
||||
QH('rpassWarning', '');
|
||||
QV('rpasswordPolicyCallout', false);
|
||||
} else {
|
||||
if (!passRequirementsEx) {
|
||||
// No password requirements, display password strength
|
||||
var passStrength = checkPasswordStrength(Q('rapassword1').value);
|
||||
if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
|
||||
else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
|
||||
else { QH('rpassWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
|
||||
} else {
|
||||
// Password requirements provided, use that
|
||||
var passReq = checkPasswordRequirements(Q('rapassword1').value, passRequirements);
|
||||
if (passReq == false) {
|
||||
ok = false;
|
||||
QS('rnuPass1').color = '#7b241c';
|
||||
QS('rnuPass2').color = '#7b241c';
|
||||
QH('rpassWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>' + "Política de senha" + '</b><div>'); // This is also a link to the password policy
|
||||
QV('rpasswordPolicyCallout', true);
|
||||
QH('rpasswordPolicyCallout', passwordPolicyText(Q('rapassword1').value));
|
||||
} else {
|
||||
QH('rpassWarning', '');
|
||||
QV('rpasswordPolicyCallout', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((e != null) && (e.keyCode == 13)) {
|
||||
if (box == 2) { Q('rapassword1').focus(); }
|
||||
if (box == 3) { Q('rapassword2').focus(); }
|
||||
if (box == 4) { Q('rapasswordhint').focus(); }
|
||||
if (box == 6) { Q('resetPassButton').click(); }
|
||||
}
|
||||
if (e != null) { haltEvent(e); }
|
||||
QE('resetPassButton', ok);
|
||||
}
|
||||
|
||||
function validateReset(e) {
|
||||
setDialogMode(0);
|
||||
var x = validateEmail(Q('remail').value);
|
||||
QE('eresetButton', x);
|
||||
if ((e != null) && (e.keyCode == 13) && (x == true)) { Q('eresetButton').click(); }
|
||||
if (e != null) { haltEvent(e); }
|
||||
}
|
||||
|
||||
function passwordPolicyText(pass) {
|
||||
var policy = '<div style=text-align:left>';
|
||||
var counts = strCount(pass);
|
||||
if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += format("Comprimento mínimo de {0}", passRequirements.min) + '<br />'; }
|
||||
if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += format("Comprimento máximo de {0}", passRequirements.max) + '<br />'; }
|
||||
if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += format("{0} maiúsculas", passRequirements.upper) + '<br />'; }
|
||||
if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += format("{0} letras minúsculas", passRequirements.lower) + '<br />'; }
|
||||
if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += format("{0} numérico", passRequirements.numeric) + '<br />'; }
|
||||
if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += format("{0} não alfanumérico", passRequirements.nonalpha) + '<br />'; }
|
||||
policy += '</div>';
|
||||
return policy;
|
||||
}
|
||||
|
||||
// Return a password strength score
|
||||
function checkPasswordStrength(password) {
|
||||
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) }
|
||||
if (!password) return 0;
|
||||
for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
|
||||
for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
|
||||
return parseInt(r + (varCount - 1) * 10);
|
||||
}
|
||||
|
||||
// Check password requirements
|
||||
function checkPasswordRequirements(password, requirements) {
|
||||
if ((requirements == null) || (requirements == '') || (typeof requirements != 'object')) return true;
|
||||
if (requirements.min) { if (password.length < requirements.min) return false; }
|
||||
if (requirements.max) { if (password.length > requirements.max) return false; }
|
||||
var counts = strCount(password);
|
||||
if (requirements.numeric && (counts.numeric < requirements.numeric)) return false;
|
||||
if (requirements.lower && (counts.lower < requirements.lower)) return false;
|
||||
if (requirements.upper && (counts.upper < requirements.upper)) return false;
|
||||
if (requirements.nonalpha && (counts.nonalpha < requirements.nonalpha)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function strCount(password) {
|
||||
var counts = { numeric: 0, lower: 0, upper: 0, nonalpha: 0 };
|
||||
if (typeof password != 'string') return counts;
|
||||
for (var i = 0; i < password.length; i++) {
|
||||
if (/\d/.test(password[i])) { counts.numeric++; }
|
||||
if (/[a-z]/.test(password[i])) { counts.lower++; }
|
||||
if (/[A-Z]/.test(password[i])) { counts.upper++; }
|
||||
if (/\W/.test(password[i])) { counts.nonalpha++; }
|
||||
}
|
||||
return counts;
|
||||
}
|
||||
|
||||
var xcheckTokenTimer = null;
|
||||
function checkTokenTimer(enter) {
|
||||
if ((enter == 0) && (xcheckTokenTimer != null)) { clearInterval(xcheckTokenTimer); xcheckTokenTimer = null; }
|
||||
if ((enter == 1) && (xcheckTokenTimer == null)) { xcheckTokenTimer = setInterval(checkToken, 200); }
|
||||
}
|
||||
|
||||
function checkToken() {
|
||||
var t1 = Q('tokenInput').value, t2 = t1.split(' ').join('');
|
||||
if (t1 != t2) { Q('tokenInput').value = t2; }
|
||||
QE('tokenOkButton', (Q('tokenInput').value.length == 6) || (Q('tokenInput').value.length == 8) || (Q('tokenInput').value.length == 44));
|
||||
}
|
||||
|
||||
function resetCheckToken() {
|
||||
var t1 = Q('resetTokenInput').value, t2 = t1.split(' ').join('');
|
||||
if (t1 != t2) { Q('resetTokenInput').value = t2; }
|
||||
QE('resetTokenOkButton', (Q('resetTokenInput').value.length == 6) || (Q('resetTokenInput').value.length == 8) || (Q('resetTokenInput').value.length == 44));
|
||||
}
|
||||
|
||||
//
|
||||
// POPUP DIALOG
|
||||
//
|
||||
|
||||
// undefined = Hidden, 1 = Generic Message
|
||||
var xxdialogMode;
|
||||
var xxdialogFunc;
|
||||
var xxdialogButtons;
|
||||
var xxdialogTag;
|
||||
var xxcurrentView = 0;
|
||||
|
||||
// Display a dialog box
|
||||
// Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
|
||||
function setDialogMode(x, y, b, f, c, tag) {
|
||||
xxdialogMode = x;
|
||||
xxdialogFunc = f;
|
||||
xxdialogButtons = b;
|
||||
xxdialogTag = tag;
|
||||
QE('idx_dlgOkButton', true);
|
||||
QV('idx_dlgOkButton', b & 1);
|
||||
QV('idx_dlgCancelButton', b & 2);
|
||||
QV('id_dialogclose', (b & 2) || (b & 8));
|
||||
QV('idx_dlgButtonBar', b & 7);
|
||||
if (y) QH('id_dialogtitle', y);
|
||||
for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
|
||||
QV('dialog', x);
|
||||
if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
|
||||
}
|
||||
|
||||
function dialogclose(x) {
|
||||
var f = xxdialogFunc;
|
||||
var b = xxdialogButtons;
|
||||
var t = xxdialogTag;
|
||||
setDialogMode();
|
||||
if (((b & 8) || x) && f) f(x, t);
|
||||
}
|
||||
|
||||
function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + 'px'); }
|
||||
function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
|
||||
function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
|
||||
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; }
|
||||
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
||||
function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
|
||||
function validateEmail(v) { var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(v); } // New version
|
||||
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
|
||||
|
||||
</script>
|
||||
|
||||
</body></html>
|
727
views/translations/login_pt.handlebars
Normal file
727
views/translations/login_pt.handlebars
Normal file
@ -0,0 +1,727 @@
|
||||
<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico">
|
||||
<link keeplink="1" type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<script keeplink="1" type="text/javascript" src="scripts/u2f-api.js"></script>
|
||||
<title>{{{title}}} - Login</title>
|
||||
</head>
|
||||
<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" class="arg_hide login">
|
||||
<div id="container">
|
||||
<div id="masthead">
|
||||
<div class="title">{{{title}}}</div>
|
||||
<div class="title2">{{{title2}}}</div>
|
||||
</div>
|
||||
<div id="topbar" class="noselect style3" style="height:24px">
|
||||
<div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
|
||||
♦
|
||||
<div id="uiMenu" style="display:none">
|
||||
<div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
|
||||
<div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
|
||||
<div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
|
||||
<div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="column_l">
|
||||
<h1>Bem vindo</h1>
|
||||
<div id="welcomeText" style="display:none">Connect to your home or office devices from anywhere in the world using MeshCentral, the real time, open source remote monitoring and management web site. You will need to download and install a management agent on your computers. Once installed, computers will show up in the "My Devices" section of this web site and you will be able to monitor them and take control of them.</div>
|
||||
<table id="centralTable" style="">
|
||||
<tbody><tr>
|
||||
<td id="welcomeimage">
|
||||
<picture>
|
||||
<img alt="" src="welcome.jpg" style="border-radius:20px">
|
||||
</picture>
|
||||
</td>
|
||||
<td id="logincell">
|
||||
<div id="loginpanel" style="display:none">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="login">
|
||||
<div id="message1"></div>
|
||||
<div>
|
||||
<b>Entrar</b>
|
||||
</div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td id="loginusername" align="right" width="100">Nome de usuário:</td>
|
||||
<td><input id="username" type="text" maxlength="64" name="username" onchange="validateLogin(1)" onkeyup="validateLogin(1,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Senha:</td>
|
||||
<td><input id="password" type="password" maxlength="256" name="password" autocomplete="off" onchange="validateLogin(2)" onkeyup="validateLogin(2,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div id="showPassHintLink" style="display:none"><a onclick="return showPassHint(event);" href="#" style="cursor:pointer">Mostrar dica</a></div></td>
|
||||
<td align="right"><input id="loginButton" type="submit" value="Entrar" disabled="disabled"></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<div id="hrAccountDiv" style="display:none"><hr></div>
|
||||
<div id="resetAccountDiv" style="display:none;padding:2px">
|
||||
<span id="resetAccountSpan">Esqueceu seu nome de usuário / senha?</span> <a onclick="return xgo(3,event);" href="#" style="cursor:pointer">Redefinir conta</a>.
|
||||
</div>
|
||||
<div id="newAccountDiv" style="display:none;padding:2px">
|
||||
Não possui uma conta? <a onclick="return xgo(2,event);" href="#" style="cursor:pointer">Crie um</a>.
|
||||
</div>
|
||||
<input id="loginformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div id="createpanel" style="display:none;position:relative">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="createaccount">
|
||||
<div id="message2"></div>
|
||||
<div>
|
||||
<b>Criação de conta</b>
|
||||
</div>
|
||||
<div id="passwordPolicyCallout" style="display:none"></div>
|
||||
<table>
|
||||
<tbody><tr id="nuUserRow">
|
||||
<td id="nuUser" align="right" width="100">Nome de usuário:</td>
|
||||
<td><input id="ausername" type="text" name="username" onchange="validateCreate(1)" maxlength="64" onkeydown="haltReturn(event)" onkeyup="validateCreate(1,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="nuEmail" align="right" width="100">Email:</td>
|
||||
<td><input id="aemail" type="text" name="email" onchange="validateCreate(2)" maxlength="256" onkeydown="haltReturn(event)" onkeyup="validateCreate(2,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="nuPass1" align="right">Senha:</td>
|
||||
<td><input id="apassword1" type="password" name="password1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(3,event)" onkeyup="validateCreate(3,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="nuPass2" align="right">Senha:</td>
|
||||
<td><input id="apassword2" type="password" name="password2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(4,event)" onkeyup="validateCreate(4,event)"></td>
|
||||
</tr>
|
||||
<tr id="createPanelHint" style="display:none">
|
||||
<td id="nuHint" align="right">Dica de senha</td>
|
||||
<td><input id="apasswordhint" type="text" name="apasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(5,event)" onkeyup="validateCreate(5,event)"></td>
|
||||
</tr>
|
||||
<tr id="newAccountPass" title="Insira o token de criação da conta">
|
||||
<td id="nuToken" align="right">Token de criação</td>
|
||||
<td><input id="anewaccountpass" type="password" name="anewaccountpass" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(6,event)" onkeyup="validateCreate(6,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="createButton" type="submit" value="Criar conta" disabled="disabled"></div>
|
||||
<div id="passWarning" style="padding-top:6px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="createformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div id="resetpanel" style="display:none">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="resetaccount">
|
||||
<div id="message3"></div>
|
||||
<div>
|
||||
<b>Redefinição de conta</b>
|
||||
</div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td align="right" width="100">Email:</td>
|
||||
<td><input id="remail" type="text" name="email" maxlength="256" onchange="validateReset()" onkeyup="validateReset(event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="eresetButton" type="submit" value="Redefinir Conta" disabled="disabled"></div>
|
||||
<div id="passWarning" style="padding-top:6px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="resetformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div id="tokenpanel" style="display:none">
|
||||
<form method="post" autocomplete="off">
|
||||
<input type="hidden" name="action" value="tokenlogin">
|
||||
<input type="hidden" name="hwstate" value="{{{hwstate}}}">
|
||||
<div id="message4"></div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td align="right" width="100">Token de logon:</td>
|
||||
<td>
|
||||
<input id="tokenInput" type="text" name="token" maxlength="50" onchange="checkToken(event)" onpaste="resetCheckToken(event)" onkeyup="checkToken(event)" onkeydown="checkToken(event)"><br>
|
||||
<input id="hwtokenInput" type="text" name="hwtoken" style="display:none">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="align-content:center">
|
||||
<label><input id="tokenInputRemember" name="remembertoken" type="checkbox">Remember this device for 30 days.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="tokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
|
||||
<div style="float:right"><input style="display:none;float:right" id="securityKeyButton" type="button" value="Use Security Key" onclick="useSecurityKey()"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="tokenformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div id="resettokenpanel" style="display:none">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="resetaccount">
|
||||
<div id="message5"></div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td align="right" width="100">Token de logon:</td>
|
||||
<td>
|
||||
<input id="resetTokenInput" type="text" name="token" maxlength="50" onchange="resetCheckToken(event)" onkeyup="resetCheckToken(event)" onkeydown="resetCheckToken(event)">
|
||||
<input id="resetHwtokenInput" type="text" name="hwtoken" style="display:none">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="resetTokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="resettokenformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div id="resetpasswordpanel" style="display:none;position:relative">
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="resetpassword">
|
||||
<div id="message6"></div>
|
||||
<div id="rpasswordPolicyCallout" style="display:none"></div>
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<td id="rnuPass1" width="100" align="right">Senha:</td>
|
||||
<td><input id="rapassword1" type="password" name="rpassword1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(3,event)" onkeyup="validatePassReset(3,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="rnuPass2" align="right">Senha:</td>
|
||||
<td><input id="rapassword2" type="password" name="rpassword2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(4,event)" onkeyup="validatePassReset(4,event)"></td>
|
||||
</tr>
|
||||
<tr id="resetpasswordpanelHint" style="display:none">
|
||||
<td id="rnuHint" align="right">Dica de senha</td>
|
||||
<td><input id="rapasswordhint" type="text" name="rpasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(5,event)" onkeyup="validatePassReset(5,event)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="resetPassButton" type="submit" value="Redefinir senha" disabled="disabled"></div>
|
||||
<div id="rpassWarning" style="padding-top:6px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
|
||||
<input id="resetpasswordformargs" name="urlargs" type="hidden" value="">
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<br>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<div class="footer1">{{{footer}}}</div>
|
||||
<div class="footer2">
|
||||
{{{rootCertLink}}}
|
||||
<a href="terms">Termos & Privacidade</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="dialog" style="display:none">
|
||||
<div id="dialogHeader">
|
||||
<div id="id_dialogclose" style="float:right;padding:5px;cursor:pointer" onclick="setDialogMode()"><b>X</b></div>
|
||||
<div id="id_dialogtitle" style="padding:5px"></div>
|
||||
<div style="width:100%;margin:6px"></div>
|
||||
</div>
|
||||
<div id="dialogBody">
|
||||
<div id="dialog1">
|
||||
<div id="id_dialogMessage" style=""></div>
|
||||
</div>
|
||||
<div id="dialog2" style="">
|
||||
<div id="id_dialogOptions"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="idx_dlgButtonBar" style="">
|
||||
<input id="idx_dlgCancelButton" type="button" value="Cancelar" style="" onclick="dialogclose(0)">
|
||||
<input id="idx_dlgOkButton" type="button" value="Ok" style="" onclick="dialogclose(1)">
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var passhint = '{{{passhint}}}';
|
||||
var loginMode = '{{{loginmode}}}';
|
||||
var newAccount = '{{{newAccount}}}';
|
||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||
var emailCheck = ('{{{emailcheck}}}' == 'true');
|
||||
var passRequirements = '{{{passRequirements}}}';
|
||||
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
||||
if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
|
||||
var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
|
||||
var features = parseInt('{{{features}}}');
|
||||
var welcomeText = decodeURIComponent('{{{welcometext}}}');
|
||||
var currentpanel = 0;
|
||||
var uiMode = parseInt(getstore('uiMode', '1'));
|
||||
var webPageFullScreen = true;
|
||||
var nightMode = (getstore('_nightMode', '0') == '1');
|
||||
var publicKeyCredentialRequestOptions = null;
|
||||
|
||||
// Display the right server message
|
||||
var messageid = parseInt('{{{messageid}}}');
|
||||
var okmessages = ['', "Hold on, reset mail sent."];
|
||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."];
|
||||
if (messageid > 0) {
|
||||
var msg = '';
|
||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||
else if ((messageid >= 100) && ((messageid - 100) < failmessages.length)) { msg = failmessages[messageid - 100]; }
|
||||
if (msg != '') {
|
||||
if (messageid >= 100) { msg = ('<span class="msg error"><b style=color:#8C001A>' + msg + '<b></span><br /><br />'); } else { msg = ('<span class="msg success"><b>' + msg + '</b></span><br /><br />'); }
|
||||
for (var i = 1; i < 7; i++) { QH('message' + i, msg); }
|
||||
}
|
||||
}
|
||||
|
||||
// If URL arguments are provided, add them to form posts
|
||||
if (window.location.href.indexOf('?') > 0) {
|
||||
var urlargs = window.location.href.substring(window.location.href.indexOf('?'));
|
||||
Q('loginformargs').value = urlargs;
|
||||
Q('createformargs').value = urlargs;
|
||||
Q('resetformargs').value = urlargs;
|
||||
Q('tokenformargs').value = urlargs;
|
||||
Q('resettokenformargs').value = urlargs;
|
||||
Q('resetpasswordformargs').value = urlargs;
|
||||
}
|
||||
|
||||
//var webPageFullScreen = getstore('webPageFullScreen', true);
|
||||
//if (webPageFullScreen == 'false') { webPageFullScreen = false; }
|
||||
//if (webPageFullScreen == 'true') { webPageFullScreen = true; }
|
||||
//toggleFullScreen();
|
||||
|
||||
function startup() {
|
||||
if ((features & 32) == 0) {
|
||||
// Guard against other site's top frames (web bugs).
|
||||
var loc = null;
|
||||
try { loc = top.location.toString().toLowerCase(); } catch (e) { }
|
||||
if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
|
||||
}
|
||||
|
||||
if (features & 0x200000) { // Email is username
|
||||
QH('loginusername', "Email:");
|
||||
QH('resetAccountSpan', "Esqueceu a senha?");
|
||||
QV('nuUserRow', false);
|
||||
}
|
||||
|
||||
if (nightMode) { QC('body').add('night'); }
|
||||
|
||||
QV('createPanelHint', passRequirements.hint === true);
|
||||
QV('resetpasswordpanelHint', passRequirements.hint === true);
|
||||
|
||||
// Display the welcome text
|
||||
if (welcomeText) { QH('welcomeText', welcomeText); }
|
||||
QH('welcomeText', addTextLink('MeshCentral', Q('welcomeText').innerHTML, 'http://www.meshcommander.com/meshcentral2'));
|
||||
QV('welcomeText', true);
|
||||
|
||||
window.onresize = center;
|
||||
center();
|
||||
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
|
||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||
QV('newAccountPass', (newAccountPass == 1));
|
||||
QV('resetAccountDiv', (emailCheck == true));
|
||||
QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
|
||||
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
|
||||
}
|
||||
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
|
||||
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('resetHwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('resetTokenOkButton', true);
|
||||
Q('resetTokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the user interface in the right mode
|
||||
userInterfaceSelectMenu();
|
||||
}
|
||||
|
||||
// Use a hardware security key
|
||||
function useSecurityKey() {
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
|
||||
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPassHint(e) {
|
||||
messagebox("Dica de Senha", passhint);
|
||||
haltEvent(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
function xgo(x, e) {
|
||||
QV('message1', false);
|
||||
QV('message2', false);
|
||||
QV('message3', false);
|
||||
QV('message4', false);
|
||||
QV('message5', false);
|
||||
QV('message6', false);
|
||||
go(x);
|
||||
haltEvent(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
function go(x) {
|
||||
currentpanel = x;
|
||||
setDialogMode(0);
|
||||
QV('showPassHintLink', false);
|
||||
QV('loginpanel', x == 1);
|
||||
QV('createpanel', x == 2);
|
||||
QV('resetpanel', x == 3);
|
||||
QV('tokenpanel', x == 4);
|
||||
QV('resettokenpanel', x == 5);
|
||||
QV('resetpasswordpanel', x == 6);
|
||||
if (x == 1) { Q('username').focus(); }
|
||||
if (x == 2) { if (features & 0x200000) { Q('aemail').focus(); } else { Q('ausername').focus(); } } // Email is username
|
||||
if (x == 3) { Q('remail').focus(); }
|
||||
if (x == 4) { Q('tokenInput').focus(); }
|
||||
if (x == 5) { Q('resetTokenInput').focus(); }
|
||||
if (x == 6) { Q('rapassword1').focus(); }
|
||||
}
|
||||
|
||||
function validateLogin(box, e) {
|
||||
var ok = ((Q('username').value.length > 0) && (Q('username').value.indexOf(' ') == -1) && (Q('password').value.length > 0));
|
||||
QE('loginButton', ok);
|
||||
setDialogMode(0);
|
||||
if ((e != null) && (e.keyCode == 13)) { if ((box == 1) && (Q('username').value != '')) { Q('password').focus(); } else if ((box == 2) && (Q('password').value != '')) { Q('loginButton').click(); } }
|
||||
if (e != null) { haltEvent(e); }
|
||||
}
|
||||
|
||||
function validateCreate(box, e) {
|
||||
setDialogMode(0);
|
||||
var userok = false;
|
||||
if (features & 0x200000) { userok = true; } else { userok = (Q('ausername').value.length > 0) && (Q('ausername').value.indexOf(' ') == -1) && (Q('ausername').value.indexOf('"') == -1) && (Q('ausername').value.indexOf(',') == -1); }
|
||||
var emailok = (validateEmail(Q('aemail').value) == true);
|
||||
var pass1ok = (Q('apassword1').value.length > 0);
|
||||
var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
|
||||
var newAccOk = (newAccountPass == 0) || (Q('anewaccountpass').value.length > 0);
|
||||
var ok = (userok && emailok && pass1ok && pass2ok && newAccOk);
|
||||
|
||||
// Color the fields
|
||||
QS('nuUser').color = userok?'black':'#7b241c';
|
||||
QS('nuEmail').color = emailok?'black':'#7b241c';
|
||||
QS('nuPass1').color = pass1ok?'black':'#7b241c';
|
||||
QS('nuPass2').color = pass2ok?'black':'#7b241c';
|
||||
QS('nuToken').color = newAccOk?'black':'#7b241c';
|
||||
|
||||
if (Q('apassword1').value == '') {
|
||||
QH('passWarning', '');
|
||||
QV('passwordPolicyCallout', false);
|
||||
} else {
|
||||
if (!passRequirementsEx) {
|
||||
// No password requirements, display password strength
|
||||
var passStrength = checkPasswordStrength(Q('apassword1').value);
|
||||
if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
|
||||
else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
|
||||
else { QH('passWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
|
||||
} else {
|
||||
// Password requirements provided, use that
|
||||
var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
|
||||
if (passReq == false) {
|
||||
ok = false;
|
||||
QS('nuPass1').color = '#7b241c';
|
||||
QS('nuPass2').color = '#7b241c';
|
||||
QH('passWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>' + "Política de senha" + '</b><div>'); // This is also a link to the password policy
|
||||
QV('passwordPolicyCallout', true);
|
||||
QH('passwordPolicyCallout', passwordPolicyText(Q('apassword1').value));
|
||||
} else {
|
||||
QH('passWarning', '');
|
||||
QV('passwordPolicyCallout', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((e != null) && (e.keyCode == 13)) {
|
||||
|
||||
if ((box == 1) && userok) { Q('aemail').focus(); }
|
||||
if ((box == 2) && emailok) { Q('apassword1').focus(); }
|
||||
if ((box == 3) && pass1ok) { Q('apassword2').focus(); }
|
||||
if ((box == 4) && pass2ok) { if (passRequirements.hint === true) { Q('apasswordhint').focus(); } else { box = 5; } }
|
||||
if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { box = 6; } }
|
||||
if (box == 6) { Q('createButton').click(); }
|
||||
}
|
||||
if (e != null) { haltEvent(e); }
|
||||
QE('createButton', ok);
|
||||
}
|
||||
|
||||
function validatePassReset(box, e) {
|
||||
setDialogMode(0);
|
||||
var pass1ok = (Q('rapassword1').value.length > 0);
|
||||
var pass2ok = (Q('rapassword2').value.length > 0) && (Q('rapassword2').value == Q('rapassword1').value);
|
||||
var ok = (pass1ok && pass2ok);
|
||||
|
||||
// Color the fields
|
||||
QS('rnuPass1').color = pass1ok ? 'black' : '#7b241c';
|
||||
QS('rnuPass2').color = pass2ok ? 'black' : '#7b241c';
|
||||
|
||||
if (Q('rapassword1').value == '') {
|
||||
QH('rpassWarning', '');
|
||||
QV('rpasswordPolicyCallout', false);
|
||||
} else {
|
||||
if (!passRequirementsEx) {
|
||||
// No password requirements, display password strength
|
||||
var passStrength = checkPasswordStrength(Q('rapassword1').value);
|
||||
if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
|
||||
else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
|
||||
else { QH('rpassWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
|
||||
} else {
|
||||
// Password requirements provided, use that
|
||||
var passReq = checkPasswordRequirements(Q('rapassword1').value, passRequirements);
|
||||
if (passReq == false) {
|
||||
ok = false;
|
||||
QS('rnuPass1').color = '#7b241c';
|
||||
QS('rnuPass2').color = '#7b241c';
|
||||
QH('rpassWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>' + "Política de senha" + '</b><div>'); // This is also a link to the password policy
|
||||
QV('rpasswordPolicyCallout', true);
|
||||
QH('rpasswordPolicyCallout', passwordPolicyText(Q('rapassword1').value));
|
||||
} else {
|
||||
QH('rpassWarning', '');
|
||||
QV('rpasswordPolicyCallout', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((e != null) && (e.keyCode == 13)) {
|
||||
if (box == 2) { Q('rapassword1').focus(); }
|
||||
if (box == 3) { Q('rapassword2').focus(); }
|
||||
if (box == 4) { Q('rapasswordhint').focus(); }
|
||||
if (box == 6) { Q('resetPassButton').click(); }
|
||||
}
|
||||
if (e != null) { haltEvent(e); }
|
||||
QE('resetPassButton', ok);
|
||||
}
|
||||
|
||||
function passwordPolicyText(pass) {
|
||||
var policy = '<div style=text-align:left>';
|
||||
var counts = strCount(pass);
|
||||
if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += format("Comprimento mínimo de {0}", passRequirements.min) + '<br />'; }
|
||||
if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += format("Comprimento máximo de {0}", passRequirements.max) + '<br />'; }
|
||||
if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += format("{0} maiúsculas", passRequirements.upper) + '<br />'; }
|
||||
if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += format("{0} letras minúsculas", passRequirements.lower) + '<br />'; }
|
||||
if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += format("{0} numérico", passRequirements.numeric) + '<br />'; }
|
||||
if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += format("{0} não alfanumérico", passRequirements.nonalpha) + '<br />'; }
|
||||
policy += '</div>';
|
||||
return policy;
|
||||
}
|
||||
|
||||
function showPasswordPolicy() {
|
||||
messagebox("Política de senha", passwordPolicyText());
|
||||
}
|
||||
|
||||
function validateReset(e) {
|
||||
setDialogMode(0);
|
||||
var x = validateEmail(Q('remail').value);
|
||||
QE('eresetButton', x);
|
||||
if ((e != null) && (e.keyCode == 13) && (x == true)) {
|
||||
Q('eresetButton').click();
|
||||
}
|
||||
if (e != null) { haltEvent(e); }
|
||||
}
|
||||
|
||||
// Return a password strength score
|
||||
function checkPasswordStrength(password) {
|
||||
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) }
|
||||
if (!password) return 0;
|
||||
for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
|
||||
for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
|
||||
return parseInt(r + (varCount - 1) * 10);
|
||||
}
|
||||
|
||||
// Check password requirements
|
||||
function checkPasswordRequirements(password, requirements) {
|
||||
if ((requirements == null) || (requirements == '') || (typeof requirements != 'object')) return true;
|
||||
if (requirements.min) { if (password.length < requirements.min) return false; }
|
||||
if (requirements.max) { if (password.length > requirements.max) return false; }
|
||||
var counts = strCount(password);
|
||||
if (requirements.numeric && (counts.numeric < requirements.numeric)) return false;
|
||||
if (requirements.lower && (counts.lower < requirements.lower)) return false;
|
||||
if (requirements.upper && (counts.upper < requirements.upper)) return false;
|
||||
if (requirements.nonalpha && (counts.nonalpha < requirements.nonalpha)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function strCount(password) {
|
||||
var counts = { numeric: 0, lower: 0, upper: 0, nonalpha: 0 };
|
||||
if (typeof password != 'string') return counts;
|
||||
for (var i = 0; i < password.length; i++) {
|
||||
if (/\d/.test(password[i])) { counts.numeric++; }
|
||||
if (/[a-z]/.test(password[i])) { counts.lower++; }
|
||||
if (/[A-Z]/.test(password[i])) { counts.upper++; }
|
||||
if (/\W/.test(password[i])) { counts.nonalpha++; }
|
||||
}
|
||||
return counts;
|
||||
}
|
||||
|
||||
function checkToken() {
|
||||
var t1 = Q('tokenInput').value;
|
||||
var t2 = t1.split(' ').join('');
|
||||
if (t1 != t2) { Q('tokenInput').value = t2; }
|
||||
QE('tokenOkButton', (Q('tokenInput').value.length == 6) || (Q('tokenInput').value.length == 8) || (Q('tokenInput').value.length == 44));
|
||||
}
|
||||
|
||||
function resetCheckToken() {
|
||||
var t1 = Q('resetTokenInput').value;
|
||||
var t2 = t1.split(' ').join('');
|
||||
if (t1 != t2) { Q('resetTokenInput').value = t2; }
|
||||
QE('resetTokenOkButton', (Q('resetTokenInput').value.length == 6) || (Q('resetTokenInput').value.length == 8) || (Q('resetTokenInput').value.length == 44));
|
||||
}
|
||||
|
||||
//
|
||||
// POPUP DIALOG
|
||||
//
|
||||
|
||||
// undefined = Hidden, 1 = Generic Message
|
||||
var xxdialogMode;
|
||||
var xxdialogFunc;
|
||||
var xxdialogButtons;
|
||||
var xxdialogTag;
|
||||
var xxcurrentView = 0;
|
||||
|
||||
// Display a dialog box
|
||||
// Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
|
||||
function setDialogMode(x, y, b, f, c, tag) {
|
||||
xxdialogMode = x;
|
||||
xxdialogFunc = f;
|
||||
xxdialogButtons = b;
|
||||
xxdialogTag = tag;
|
||||
QE('idx_dlgOkButton', true);
|
||||
QV('idx_dlgOkButton', b & 1);
|
||||
QV('idx_dlgCancelButton', b & 2);
|
||||
QV('id_dialogclose', (b & 2) || (b & 8));
|
||||
QV('idx_dlgButtonBar', b & 7);
|
||||
if (y) QH('id_dialogtitle', y);
|
||||
for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
|
||||
QV('dialog', x);
|
||||
if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
|
||||
}
|
||||
|
||||
function dialogclose(x) {
|
||||
var f = xxdialogFunc;
|
||||
var b = xxdialogButtons;
|
||||
var t = xxdialogTag;
|
||||
setDialogMode();
|
||||
if (((b & 8) || x) && f) f(x, t);
|
||||
}
|
||||
|
||||
// Toggle the web page to full screen
|
||||
function toggleFullScreen(toggle) {
|
||||
//if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
|
||||
if (webPageFullScreen == false) {
|
||||
// By adding body class, it will change a style of all ellements using CSS selector
|
||||
// No need for JS anymore and it will be consistent style for all the templates.
|
||||
QC('body').remove('fullscreen');
|
||||
} else {
|
||||
QC('body').add('fullscreen');
|
||||
}
|
||||
QV('body', true);
|
||||
center();
|
||||
}
|
||||
|
||||
// Toggle user interface menu
|
||||
function showUserInterfaceSelectMenu() {
|
||||
Q('uiViewButton1').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton2').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton3').classList.remove('uiSelectorSel');
|
||||
try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
|
||||
QV('uiMenu', (QS('uiMenu').display == 'none'));
|
||||
if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
|
||||
}
|
||||
|
||||
function userInterfaceSelectMenu(s) {
|
||||
if (s) { uiMode = s; putstore('uiMode', uiMode); }
|
||||
webPageFullScreen = (uiMode < 3);
|
||||
//webPageStackMenu = (uiMode > 1);
|
||||
toggleFullScreen(0);
|
||||
//toggleStackMenu(0);
|
||||
}
|
||||
|
||||
function toggleNightMode() {
|
||||
nightMode = !nightMode;
|
||||
if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
|
||||
putstore('_nightMode', (nightMode ? '1' : '0'));
|
||||
}
|
||||
|
||||
function center() {
|
||||
/* Now we use CSS media to achive the same effect as deleted JS */
|
||||
if (webPageFullScreen == false) {
|
||||
QS('centralTable')['margin-top'] = '';
|
||||
} else {
|
||||
var h = ((Q('column_l').clientHeight) / 2) - 220;
|
||||
if (h < 0) h = 0;
|
||||
QS('centralTable')['margin-top'] = h + 'px';
|
||||
}
|
||||
}
|
||||
function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
|
||||
function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
|
||||
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; }
|
||||
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
||||
function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
|
||||
function validateEmail(v) { var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(v); } // New version
|
||||
function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
|
||||
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
|
||||
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
|
||||
function addTextLink(subtext, text, link) { var i = text.toLowerCase().indexOf(subtext.toLowerCase()); if (i == -1) { return text; } return text.substring(0, i) + '<a href=\"' + link + '\">' + subtext + '</a>' + text.substring(i + subtext.length); }
|
||||
|
||||
</script>
|
||||
|
||||
</body></html>
|
1
views/translations/message-min_pt.handlebars
Normal file
1
views/translations/message-min_pt.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>MeshCentral - {{{title3}}}</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>{{{title3}}}</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=terms>Termos & Privacidade</a></table></div></div></div>
|
40
views/translations/message_pt.handlebars
Normal file
40
views/translations/message_pt.handlebars
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link type="text/css" href="/styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<title>MeshCentral - {{{title3}}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container" style="max-height:100vh">
|
||||
<div id="mastheadx"></div>
|
||||
<div id="masthead" style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden">
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px">
|
||||
<strong><font style="font-size:46px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px">
|
||||
<strong><font style="font-size:14px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_content" style="max-height:calc(100vh-138px)">
|
||||
<div id="column_l">
|
||||
<h1>{{{title3}}}</h1>
|
||||
<p style="margin-left:20px">{{{message}}}</p>
|
||||
<br>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<table cellpadding="0" cellspacing="10" style="width:100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left"></td>
|
||||
<td style="text-align:right">
|
||||
<a href="terms">Termos & Privacidade</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
1
views/translations/messenger-min_pt.handlebars
Normal file
1
views/translations/messenger-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
642
views/translations/messenger_pt.handlebars
Normal file
642
views/translations/messenger_pt.handlebars
Normal file
@ -0,0 +1,642 @@
|
||||
<!DOCTYPE html><html style="height:100%"><head>
|
||||
<title>MeshMessenger</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<link type="text/css" href="styles/messenger.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<script type="text/javascript" src="scripts/filesaver.js"></script>
|
||||
</head>
|
||||
<body style="font-family:Arial,Helvetica,sans-serif">
|
||||
<div id="xtop" style="position:absolute;left:0;right:0;top:0;height:38px;background-color:#036;color:#c8c8c8;box-shadow:3px 3px 10px gray">
|
||||
<div style="position:absolute;background-color:#036;right:0;height:38px">
|
||||
<div id="notifyButton" class="icon13 topButton" style="margin-right:4px;display:none" title="Ativar notificação do navegador" onclick="enableNotificationsButtonClick()"></div>
|
||||
<div id="fileButton" class="icon4 topButton" title="Compartilhar um arquivo" style="display:none" onclick="fileButtonClick()"></div>
|
||||
<div id="camButton" class="icon2 topButton" title="Ativar câmera e microfone" style="display:none" onclick="camButtonClick()"></div>
|
||||
<div id="micButton" class="icon6 topButton" title="Ativar microfone" style="display:none" onclick="micButtonClick()"></div>
|
||||
<div id="hangupButton" class="icon11 topRedButton" title="Desligar" style="display:none" onclick="hangUpButtonClick(1)"></div>
|
||||
</div>
|
||||
<div style="padding-top:9px;padding-left:6px;font-size:20px;display:inline-block"><b><span id="xtitle">MeshMessenger</span></b></div>
|
||||
</div>
|
||||
<div id="xmiddle" style="position:absolute;left:0;right:0;top:38px;bottom:30px">
|
||||
<div style="position:absolute;left:0;right:0;top:0;bottom:0;overflow-y:scroll">
|
||||
<div id="xmsg" style="position:absolute;left:0;right:0;bottom:0;padding:5px"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="xbottom" style="position:absolute;left:0;right:0;bottom:0px;height:30px;background-color:#036">
|
||||
<div style="position:absolute;left:5px;right:215px;bottom:4px;top:4px;background-color:aliceblue"><input id="xouttext" type="text" style="width:calc(100% - 5px)" onfocus="onUserInputFocus(1)" onblur="onUserInputFocus(0)"></div>
|
||||
<input type="button" id="sendButton" value="Enviar" style="position:absolute;right:110px;width:100px;top:4px;" onclick="xsend(event)">
|
||||
<input type="button" id="clearButton" value="Limpo" style="position:absolute;right:5px;width:100px;top:4px;" onclick="displayClear()">
|
||||
</div>
|
||||
<div id="remoteVideo" style="position:absolute;right:24px;top:45px;width:320px;height:calc(240px + 30px);background-color:gray;border-radius:12px 12px 12px 12px;box-shadow:3px 3px 10px gray;display:none">
|
||||
<div style="position:absolute;right:0;left:0;top:2.5px;text-align:center">Remoto</div>
|
||||
<video id="remoteVideoCanvas" autoplay="" style="position:absolute;top:20px;left:0;width:100%;height:calc(100% - 30px);background-color:black"></video>
|
||||
</div>
|
||||
<div id="localVideo" style="position:absolute;right:24px;top:320px;width:160px;height:calc(120px + 30px);background-color:gray;border-radius:12px 12px 12px 12px;box-shadow:3px 3px 10px gray;display:none">
|
||||
<div style="position:absolute;right:0;left:0;top:2.5px;text-align:center">Local</div>
|
||||
<video id="localVideoCanvas" autoplay="" muted="" style="position:absolute;top:20px;left:0;width:100%;height:calc(100% - 30px);background-color:black"></video>
|
||||
</div>
|
||||
<input id="uploadFileInput" type="file" multiple="" style="display:none">
|
||||
<script type="text/javascript" onunload="onUnLoad()">
|
||||
var userInputFocus = 0;
|
||||
var args = parseUriArgs();
|
||||
var socket = null; // Websocket object
|
||||
var state = 0; // Connection state. 0 = Disconnected, 1 = Connecting, 2 = Connected.
|
||||
|
||||
// WebRTC sessions and data, audio and video channels
|
||||
var random = Math.random(); // Selected random, larger value initiates WebRTC.
|
||||
var webrtcSessions = { }; // WebRTC objects: 0 for data, 1 for outbound audio/video, 2 for inbound audio/video
|
||||
var webchannel = null; // WebRTC data channel
|
||||
var localStream = null;
|
||||
var remoteStream = null;
|
||||
var multiWebRtc = true; // if set to true, multiple WebRTC sessions will be setup. If false, everything uses one session.
|
||||
var userMediaSupport = 0;
|
||||
var notification = null;
|
||||
getUserMediaSupport(function (x) { userMediaSupport = x; })
|
||||
var webrtcconfiguration = '{{{webrtconfig}}}';
|
||||
if (webrtcconfiguration == '') { webrtcconfiguration = null; } else { try { webrtcconfiguration = JSON.parse(decodeURIComponent(webrtcconfiguration)); } catch (ex) { console.log('Invalid WebRTC config: \"' + webrtcconfiguration + '\".'); webrtcconfiguration = null; } }
|
||||
|
||||
// File transfer state
|
||||
var fileUploads = [];
|
||||
var fileDownloads = {};
|
||||
var currentFileUpload = null;
|
||||
var currentFileDownload = null;
|
||||
|
||||
// Set the title
|
||||
if (args.title) { QH('xtitle', args.title.split(' ').join(' ')); document.title = document.title + ' - ' + args.title; }
|
||||
|
||||
// Setup web notifications
|
||||
if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
|
||||
|
||||
// Listen to drag & drop events
|
||||
document.addEventListener('dragover', haltEvent, false);
|
||||
document.addEventListener('dragleave', haltEvent, false);
|
||||
document.addEventListener('drop', fileDrop, false);
|
||||
|
||||
document.onclick = function (e) {
|
||||
if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
|
||||
if (notification != null) { notification.close(); notification = null; }
|
||||
}
|
||||
|
||||
// Trap document key up events
|
||||
document.onkeyup = function ondockeypress(e) {
|
||||
if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
|
||||
if (notification != null) { notification.close(); notification = null; }
|
||||
if (state == 2) {
|
||||
if ((e.keyCode == 8) && (userInputFocus == 0)) {
|
||||
// Backspace
|
||||
var outtext = Q('xouttext').value;
|
||||
if (outtext.length > 0) { Q('xouttext').value = outtext.substring(0, outtext.length - 1); }
|
||||
}
|
||||
}
|
||||
if (userInputFocus == 0) { haltEvent(e); return false; }
|
||||
}
|
||||
|
||||
// Trap document key presses
|
||||
document.onkeypress = function ondockeypress(e) {
|
||||
if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
|
||||
if (notification != null) { notification.close(); notification = null; }
|
||||
if (state == 2) {
|
||||
if (e.keyCode == 13) {
|
||||
// Return
|
||||
xsend(e);
|
||||
} else {
|
||||
// Any other key
|
||||
if ((userInputFocus == 0) && (e.key.length == 1)) { Q('xouttext').value = Q('xouttext').value + e.key; }
|
||||
}
|
||||
}
|
||||
if (userInputFocus == 0) { haltEvent(e); return false; }
|
||||
}
|
||||
|
||||
function onUserInputFocus(x) { userInputFocus = x; }
|
||||
function displayClear() { QH('xmsg', ''); cancelAllFileTransfers(); fileUploads = [], fileDownloads = {}; }
|
||||
|
||||
// Polyfill FileReader if needed
|
||||
if (!FileReader.prototype.readAsBinaryString) {
|
||||
FileReader.prototype.readAsBinaryString = function (fileData) {
|
||||
var binary = '', self = this, reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
var bytes = new Uint8Array(reader.result);
|
||||
for (var i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); }
|
||||
self.onload({ target: { result: binary } });
|
||||
}
|
||||
reader.readAsArrayBuffer(fileData);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect if microphone & camera are present
|
||||
// 0 = nomedia, 1 = miconly, 2 = mic&cam
|
||||
function getUserMediaSupport(func) {
|
||||
try {
|
||||
navigator.mediaDevices.enumerateDevices().then(function (devices) {
|
||||
try {
|
||||
var mic = 0, cam = 0;
|
||||
devices.forEach(function (device) {
|
||||
if (device.kind === 'audioinput') { mic = 1; }
|
||||
if (device.kind === 'videoinput') { cam = 1; }
|
||||
});
|
||||
if (mic == 0) { func(0); }
|
||||
func(mic + cam);
|
||||
} catch (ex) { }
|
||||
})
|
||||
} catch (ex) { }
|
||||
}
|
||||
|
||||
// Display a control message
|
||||
function displayControl(msg) {
|
||||
QA('xmsg', '<div style="clear:both"><div style="color:gray;float:left;margin-bottom:2px">' + msg + '</div><div></div></div>');
|
||||
Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
|
||||
}
|
||||
|
||||
function displayLocalVideo(active) { QV('localVideo', active); adjustVideoWindows(); }
|
||||
function displayRemoteVideo(active) { QV('remoteVideo', active); adjustVideoWindows(); }
|
||||
function adjustVideoWindows() {
|
||||
//var lv = (QS('localVideo')['display'] != 'none');
|
||||
var rv = (QS('remoteVideo')['display'] != 'none');
|
||||
QS('localVideo')['top'] = rv ? '320px' : '45px';
|
||||
}
|
||||
|
||||
// Display a message from the remote user
|
||||
function displayRemote(msg) {
|
||||
QA('xmsg', '<div style="clear:both"><div class="remoteBubble">' + msg + '</div><div></div></div>');
|
||||
Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
|
||||
|
||||
// If web notifications are granted, use it.
|
||||
if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
|
||||
if (Notification && (Notification.permission == 'granted')) {
|
||||
if (notification != null) { notification.close(); notification = null; }
|
||||
if (args.title) {
|
||||
notification = new Notification("MeshMessenger" + ' - ' + args.title, { body: msg });
|
||||
} else {
|
||||
notification = new Notification("MeshMessenger", { body: msg });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display and send a message from the local user
|
||||
function xsend(event) {
|
||||
if (notification != null) { notification.close(); notification = null; }
|
||||
if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
|
||||
var outtext = Q('xouttext').value;
|
||||
if (outtext.length > 0) {
|
||||
Q('xouttext').value = '';
|
||||
QA('xmsg', '<div style="clear:both"><div class="localBubble">' + outtext + '</div><div></div></div>');
|
||||
Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
|
||||
send({ action: 'chat', msg: outtext });
|
||||
}
|
||||
}
|
||||
|
||||
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
||||
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 = decodeURIComponent(parsedUri[x]); break; } case 1: { r[name] = decodeURIComponent(parsedUri[x]); var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } default: { break; } } } return r; }
|
||||
|
||||
// Update user controls
|
||||
function updateControls() {
|
||||
QE('sendButton', state == 2);
|
||||
QE('clearButton', state == 2);
|
||||
QE('xouttext', state == 2);
|
||||
QV('fileButton', state == 2);
|
||||
QV('camButton', webchannel && webchannel.ok && !localStream && (userMediaSupport == 2));
|
||||
QV('micButton', webchannel && webchannel.ok && !localStream && (userMediaSupport > 0));
|
||||
QV('hangupButton', webchannel && webchannel.ok && localStream);
|
||||
}
|
||||
|
||||
// This is the WebRTC setup
|
||||
function startWebRTC(id, startDataChannel) {
|
||||
if ((webrtcSessions[0] != null) && (multiWebRtc == false)) { return webrtcSessions[0]; };
|
||||
|
||||
// Setup the WebRTC object
|
||||
var webrtc = null;
|
||||
if (typeof RTCPeerConnection !== 'undefined') { webrtc = new RTCPeerConnection(webrtcconfiguration); }
|
||||
else if (typeof webkitRTCPeerConnection !== 'undefined') { webrtc = new webkitRTCPeerConnection(webrtcconfiguration); }
|
||||
if (webrtc == null) return null; // No WebRTC support.
|
||||
|
||||
webrtc.id = id;
|
||||
webrtc.onicecandidate = function (e) { try { if (e.candidate != null) { sendws({ action: 'webRtcIce', ice: e.candidate, id: this.id }); } } catch (ex) { } }
|
||||
webrtc.oniceconnectionstatechange = function () { if (webrtc && webrtc.iceConnectionState == 'failed') { webrtc.close(); if (webrtcSessions[webrtc.id]) { delete webrtcSessions[webrtc.id]; } } }
|
||||
webrtc.ondatachannel = function (ev) {
|
||||
//console.log('ondatachannel');
|
||||
webchannel = ev.channel;
|
||||
webchannel.onmessage = function (event) { processMessage(event.data, 2); };
|
||||
webchannel.onopen = function () { webchannel.ok = true; updateControls(); sendws({ action: 'rtcSwitch', v: 0 }); };
|
||||
webchannel.onclose = function (event) { if (webchannel && webchannel.ok) { disconnect(); } else { hangUpButtonClick(0); } }
|
||||
}
|
||||
webrtc.onnegotiationneeded = function (event) {
|
||||
if (webrtc.holdTimer != null) return;
|
||||
webrtc.holdTimer = setTimeout(function () { // This time is needed to keep Chrome from being to excited. Wait until we add all tracks before kicking this off.
|
||||
//console.log('onnegotiationneeded', id);
|
||||
webrtc.holdTimer = null;
|
||||
webrtc.createOffer(function (offer) { /*console.log('offer', offer.sdp.length);*/ webrtc.setLocalDescription(offer, function () { sendws({ action: 'webRtcSdp', sdp: offer, id: id }); }, function () { hangUpButtonClick(id); }); }, function () { hangUpButtonClick(id); });
|
||||
}, 20);
|
||||
}
|
||||
webrtc.ontrack = function (event) {
|
||||
//console.log('ontrack', id);
|
||||
var video = Q('remoteVideoCanvas');
|
||||
video.srcObject = remoteStream = event.streams[0];
|
||||
video.onloadedmetadata = function (e) { video.play(); };
|
||||
displayRemoteVideo(true);
|
||||
}
|
||||
//webrtc.onremovetrack = function (event) { console.log('onremovetrack'); }
|
||||
//webrtc.onicegatheringstatechange = function (event) { console.log('onicegatheringstatechange', event); }
|
||||
//webrtc.onsignalingstatechange = function (event) { console.log('onsignalingstatechange', event); }
|
||||
|
||||
// Initiate the WebRTC offer or handle the offer from the peer.
|
||||
if (startDataChannel == true) {
|
||||
webchannel = webrtc.createDataChannel('DataChannel', {}); // { ordered: false, maxRetransmits: 2 }
|
||||
webchannel.onmessage = function (event) { processMessage(event.data, 2); };
|
||||
webchannel.onopen = function () { webchannel.ok = true; updateControls(); sendws({ action: 'rtcSwitch', v: 0 }); };
|
||||
webchannel.onclose = function (event) { if (webchannel && webchannel.ok) { disconnect(); } else { hangUpButtonClick(0); } }
|
||||
}
|
||||
|
||||
webrtcSessions[id] = webrtc;
|
||||
return webrtc;
|
||||
}
|
||||
|
||||
function webRtcHandleOffer(id, description) {
|
||||
//console.log('webRtcHandleOffer', description.sdp.length);
|
||||
var webrtc = webrtcSessions[id];
|
||||
if (webrtc) {
|
||||
webrtc.setRemoteDescription(new RTCSessionDescription(description), function () {
|
||||
if (description.type == 'offer') {
|
||||
webrtc.createAnswer(function (answer) {
|
||||
webrtc.setLocalDescription(answer, function (a, b) {
|
||||
try { sendws({ action: 'webRtcSdp', sdp: answer, id: id }); } catch (ex) { }
|
||||
}, function () { hangUpButtonClick(id); });
|
||||
}, function () { hangUpButtonClick(id); });
|
||||
}
|
||||
}, function () { hangUpButtonClick(id); });
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate to peer that data traffic will no longer be sent over websocket and start holding traffic.
|
||||
function performWebRtcSwitch() {
|
||||
if (webchannel && webchannel.ok) { sendws({ action: 'rtcSwitch', v: 1 }); webchannel.xoutBuffer = []; }
|
||||
}
|
||||
|
||||
// Disconnect everything
|
||||
function disconnect() {
|
||||
if (state > 0) { displayControl("Conexão fechada."); }
|
||||
if (state > 1) { setTimeout(start, 500); }
|
||||
cancelAllFileTransfers();
|
||||
hangUpButtonClick(0, true); // Data channel
|
||||
hangUpButtonClick(1, true); // Local audio/video
|
||||
hangUpButtonClick(2, true); // Remote audio/video
|
||||
if (socket != null) { socket.close(); socket = null; }
|
||||
updateControls();
|
||||
state = 0;
|
||||
}
|
||||
|
||||
// Send data over the current transport (WebRTC first)
|
||||
function send(data) {
|
||||
if (state != 2) return; // If not in connected state, ignore this.
|
||||
if (typeof data == 'object') { data = JSON.stringify(data); } // If this is an object, convert it to a string.
|
||||
if (webchannel && webchannel.ok) { if (webchannel.xoutBuffer != null) { webchannel.xoutBuffer.push(data); } else { webchannel.send(data); } } // If WebRTC channel is possible, use it or hold until we can use it.
|
||||
else { if (socket != null) { try { socket.send(data); } catch (ex) { } } } // If a websocket channel is present, use that.
|
||||
}
|
||||
|
||||
// Send data over the websocket transport (WebSocket only)
|
||||
function sendws(data) {
|
||||
if (state != 2) return;
|
||||
//console.log('SEND', data);
|
||||
if (typeof data == 'object') { data = JSON.stringify(data); }
|
||||
if (socket != null) { socket.send(data); }
|
||||
}
|
||||
|
||||
// WebRTC id switcher (0 -> 0, 1 -> 2, 2 -> 1)
|
||||
function webRtcIdSwitch(id) { if (id == 0) { return 0; } return 3 - id; }
|
||||
|
||||
// Process incoming messages
|
||||
function processMessage(data, transport) {
|
||||
if (typeof data == 'string') {
|
||||
try { data = JSON.parse(data); } catch (ex) { console.log('Unable to parse', data); return; }
|
||||
//console.log('RECV', data);
|
||||
switch (data.action) {
|
||||
case 'chat': { displayRemote(data.msg); break; } // Incoming chat message.
|
||||
case 'random': { if (random > data.random) { startWebRTC(0, true); } break; } // If we have a larger random value, we start WebRTC.
|
||||
case 'webRtcSdp': { if (!webrtcSessions[webRtcIdSwitch(data.id)]) { startWebRTC(webRtcIdSwitch(data.id), false); } webRtcHandleOffer(webRtcIdSwitch(data.id), data.sdp); break; } // Remote WebRTC offer or answer.
|
||||
case 'webRtcIce': { var webrtc = webrtcSessions[webRtcIdSwitch(data.id)]; if (webrtc) { try { webrtc.addIceCandidate(new RTCIceCandidate(data.ice)); } catch (ex) { } } break; } // Remote ICE candidate
|
||||
case 'videoStop': { hangUpButtonClick(webRtcIdSwitch(data.id), true); break; }
|
||||
case 'rtcSwitch': { // WebRTC switch over commands.
|
||||
switch (data.v) {
|
||||
case 0: { performWebRtcSwitch(); break; } // Other side is ready for switch over to WebRTC
|
||||
case 1: { sendws({ action: 'rtcSwitch', v: 2 }); break; } // Other side no longer sending data on websocket, confirm we got the end marker
|
||||
case 2: { for (var i in webchannel.xoutBuffer) { webchannel.send(webchannel.xoutBuffer[i]); } delete webchannel.xoutBuffer; break; } // Send any pending data over WebRTC and start using WebRTC with all traffic
|
||||
default: { console.log('Unknown rtcSwitch value: ' + data.action); break; } //
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'file': { startFileDownload(data); break; }
|
||||
case 'fileUploadCancel': { cancelFileTransfer(data.id); break; }
|
||||
case 'fileUploadStart': {
|
||||
if (fileDownloads[data.id]) {
|
||||
currentFileDownload = fileDownloads[data.id];
|
||||
currentFileDownload.data = '';
|
||||
changeFileInfo(data.id, 2, 0);
|
||||
continueFileDownload(data);
|
||||
send({ action: 'fileUploadAck', id: data.id });
|
||||
} break;
|
||||
}
|
||||
case 'fileUploadEnd': {
|
||||
if (currentFileDownload && (currentFileDownload.id == data.id)) {
|
||||
changeFileInfo(data.id, 3, 200);
|
||||
currentFileDownload.done = 1;
|
||||
currentFileDownload = null;
|
||||
send({ action: 'fileUploadAck', id: data.id });
|
||||
}
|
||||
currentFileDownload = null;
|
||||
break;
|
||||
}
|
||||
case 'fileUploadAck': {
|
||||
continueFileUpload();
|
||||
break;
|
||||
}
|
||||
case 'fileData': {
|
||||
if (currentFileDownload && (currentFileDownload.id == data.id)) {
|
||||
currentFileDownload.data += data.data;
|
||||
changeFileInfo(data.id, 2, (currentFileDownload.data.length * 200 / currentFileDownload.size));
|
||||
send({ action: 'fileUploadAck', id: data.id });
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { console.log('Unhandled object data', data); break; }
|
||||
}
|
||||
} else {
|
||||
console.log('Unhandled data', typeof data, data);
|
||||
}
|
||||
}
|
||||
|
||||
// File sharing button
|
||||
function fileButtonClick() {
|
||||
var chooser = Q('uploadFileInput');
|
||||
if (chooser.getAttribute('eventset') != 1) {
|
||||
chooser.setAttribute('eventset', '1');
|
||||
chooser.addEventListener('change', fileSelect, false);
|
||||
}
|
||||
chooser.value = null;
|
||||
chooser.click();
|
||||
}
|
||||
|
||||
// User selected one or more files to upload to remote user.
|
||||
function fileSelect() {
|
||||
if (state != 2) return;
|
||||
var x = Q('uploadFileInput');
|
||||
if (x.files.length > 10) {
|
||||
displayControl("Limite de 10 uploads de arquivos ao mesmo tempo.");
|
||||
} else {
|
||||
for (var i = 0; i < x.files.length; i++) {
|
||||
if (x.files[i].size > 0) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
|
||||
reader.xfile = x.files[i];
|
||||
reader.readAsBinaryString(x.files[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User drag & droped one or more files to upload to remote user.
|
||||
function fileDrop(e) {
|
||||
haltEvent(e);
|
||||
if ((state != 2) || (e.dataTransfer == null)) return;
|
||||
if (e.dataTransfer.files.length > 10) {
|
||||
displayControl("Limite de 10 uploads de arquivos ao mesmo tempo.");
|
||||
} else {
|
||||
for (var i = 0; i < e.dataTransfer.files.length; i++) {
|
||||
if (e.dataTransfer.files[i].size > 0) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
|
||||
reader.xfile = e.dataTransfer.files[i];
|
||||
reader.readAsBinaryString(e.dataTransfer.files[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startFileUpload(file) {
|
||||
if (state != 2) return;
|
||||
file.id = Math.random();
|
||||
fileUploads.push(file);
|
||||
QA('xmsg', '<div style="clear:both"></div><div id="FILEUP-' + file.id + '" class="localBubble" style="width:240px;cursor:pointer" onclick="cancelFileTransfer(\'' + file.id + '\')"><div id="FILEUP-ICON-' + file.id + '" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-' + file.id + '" style="height:16px;overflow:hidden;white-space:nowrap;" title="' + file.name + '">' + file.name + '</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-' + file.id + '" style="width:0px;background-color:green;border-radius:3px;height:11px"> </div></div></div></div>');
|
||||
Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
|
||||
send({ action: 'file', size: file.size, id: file.id, type: file.type, name: file.name });
|
||||
if (currentFileUpload == null) continueFileUpload();
|
||||
}
|
||||
|
||||
function startFileDownload(file) {
|
||||
if (state != 2) return;
|
||||
fileDownloads[file.id] = file;
|
||||
QA('xmsg', '<div style="clear:both"></div><div id="FILEUP-' + file.id + '" class="remoteBubble" style="width:240px;cursor:pointer" onclick="saveFileTransfer(\'' + file.id + '\')"><div id="FILEUP-ICON-' + file.id + '" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-' + file.id + '" style="height:16px;overflow:hidden;white-space:nowrap;" title="' + file.name + '">' + file.name + '</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-' + file.id + '" style="width:0px;background-color:green;border-radius:3px;height:11px"> </div></div></div></div>');
|
||||
Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
|
||||
}
|
||||
|
||||
// Change the file icon and progress
|
||||
function changeFileInfo(id, icon, progress, progressColor) {
|
||||
if (icon) {
|
||||
Q('FILEUP-ICON-' + id).classList.remove('fileicon');
|
||||
Q('FILEUP-ICON-' + id).classList.remove('fileiconx');
|
||||
Q('FILEUP-ICON-' + id).classList.remove('fileicontransfer');
|
||||
Q('FILEUP-ICON-' + id).classList.remove('fileicondone');
|
||||
Q('FILEUP-ICON-' + id).classList.add(['fileicon', 'fileiconx', 'fileicontransfer', 'fileicondone'][icon]);
|
||||
}
|
||||
if (progress) { QS('FILEUP-PROGRESS-' + id)['width'] = progress + 'px'; }
|
||||
if (progressColor) { QS('FILEUP-PROGRESS-' + id)['background-color'] = progressColor; }
|
||||
}
|
||||
|
||||
// Convert a string into a blob
|
||||
function data2blob(data) {
|
||||
var bytes = new Array(data.length);
|
||||
for (var i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i);
|
||||
return new Blob([new Uint8Array(bytes)]);
|
||||
};
|
||||
|
||||
function saveFileTransfer(id) {
|
||||
var f = fileDownloads[id];
|
||||
if (f && f.done == 1) { saveAs(data2blob(f.data), f.name); }
|
||||
}
|
||||
|
||||
function cancelFileTransfer(id) {
|
||||
if ((currentFileUpload != null) && (currentFileUpload.id == id)) { currentFileUpload = null; }
|
||||
if ((currentFileDownload != null) && (currentFileDownload.id == id)) { currentFileDownload = null; }
|
||||
|
||||
var found = false;
|
||||
if (fileDownloads[id] && (fileDownloads[id].done != 1)) {
|
||||
delete fileDownloads[id];
|
||||
found = true;
|
||||
} else {
|
||||
for (var i in fileUploads) {
|
||||
if (fileUploads[i].id == id) {
|
||||
send({ action: 'fileUploadCancel', id: id });
|
||||
fileUploads.splice(i, 1);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) { changeFileInfo(id, 1, 200, 'gray'); } // Only cancel a file if it was in the file queue.
|
||||
}
|
||||
|
||||
function cancelAllFileTransfers() {
|
||||
for (var i in fileDownloads) { cancelFileTransfer(fileDownloads[i].id); }
|
||||
for (var i in fileUploads) { cancelFileTransfer(fileUploads[i].id); }
|
||||
}
|
||||
|
||||
function continueFileUpload() {
|
||||
if (currentFileUpload == null) {
|
||||
// Select the next file to upload
|
||||
if (fileUploads.length == 0) { return; } // Nothing to do
|
||||
currentFileUpload = fileUploads[0];
|
||||
currentFileUpload.ptr = 0;
|
||||
|
||||
// Indicate that we are sending this file
|
||||
send({ action: 'fileUploadStart', size: currentFileUpload.size, id: currentFileUpload.id, type: currentFileUpload.type, name: currentFileUpload.name });
|
||||
} else {
|
||||
if (currentFileUpload.size <= currentFileUpload.ptr) {
|
||||
// If we are done, send the end marker
|
||||
send({ action: 'fileUploadEnd', size: currentFileUpload.size, id: currentFileUpload.id, type: currentFileUpload.type, name: currentFileUpload.name });
|
||||
changeFileInfo(currentFileUpload.id, 3, 200);
|
||||
fileUploads.splice(0, 1);
|
||||
currentFileUpload = null;
|
||||
continueFileUpload(); // Send the next file
|
||||
} else {
|
||||
// Send the next block
|
||||
var nextBlockLen = Math.min(4000, currentFileUpload.data.length - currentFileUpload.ptr);
|
||||
var data = currentFileUpload.data.substring(currentFileUpload.ptr, currentFileUpload.ptr + nextBlockLen);
|
||||
send({ action: 'fileData', id: currentFileUpload.id, data: data });
|
||||
currentFileUpload.ptr += nextBlockLen;
|
||||
changeFileInfo(currentFileUpload.id, 0, (currentFileUpload.ptr * 200 / currentFileUpload.size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function continueFileDownload(msg) {
|
||||
send({ action: 'fileUploadAck', id: msg.id });
|
||||
}
|
||||
|
||||
// Toggle notification
|
||||
function enableNotificationsButtonClick() {
|
||||
if (Notification) { Notification.requestPermission().then(function (permission) { QV('notifyButton', permission != 'granted'); }); }
|
||||
return false;
|
||||
}
|
||||
|
||||
// Camera button
|
||||
function camButtonClick() {
|
||||
if (localStream == null) { startLocalStream({ video: true, audio: true }); }
|
||||
}
|
||||
|
||||
// Microphone
|
||||
function micButtonClick() {
|
||||
if (localStream == null) { startLocalStream({ video: false, audio: true }); }
|
||||
}
|
||||
|
||||
function hangUpButtonClick(id, fromRemote) {
|
||||
//console.log('hangUpButtonClick', id);
|
||||
var localVideo = Q('localVideoCanvas');
|
||||
var remoteVideo = Q('remoteVideoCanvas');
|
||||
var webrtc = webrtcSessions[(multiWebRtc == true)? id : 0];
|
||||
|
||||
if ((id == 0) && (webchannel != null)) { try { webchannel.close(); } catch (e) { } webchannel = null; }
|
||||
|
||||
if (webrtc) {
|
||||
if ((multiWebRtc == true) || (id == 0)) {
|
||||
webrtc.ontrack = null;
|
||||
webrtc.onremovetrack = null;
|
||||
webrtc.onremovestream = null;
|
||||
webrtc.onnicecandidate = null;
|
||||
webrtc.oniceconnectionstatechange = null;
|
||||
webrtc.onsignalingstatechange = null;
|
||||
webrtc.onicegatheringstatechange = null;
|
||||
webrtc.onnotificationneeded = null;
|
||||
}
|
||||
|
||||
if ((id == 1) && localStream) { var tracks = localStream.getTracks(); for (var i in tracks) { tracks[i].stop(); } localStream = null; }
|
||||
if ((id == 2) && remoteStream) { var tracks = remoteStream.getTracks(); for (var i in tracks) { tracks[i].stop(); } remoteStream = null; }
|
||||
|
||||
if ((multiWebRtc == true) || (id == 0)) {
|
||||
webrtc.close();
|
||||
delete webrtcSessions[id];
|
||||
}
|
||||
}
|
||||
|
||||
if (id == 1) {
|
||||
localVideo.removeAttribute('src');
|
||||
localVideo.removeAttribute('srcObject');
|
||||
if (localStream != null) { localStream = null; }
|
||||
displayLocalVideo(false);
|
||||
} else if (id == 2) {
|
||||
remoteVideo.removeAttribute('src');
|
||||
remoteVideo.removeAttribute('srcObject');
|
||||
displayRemoteVideo(false);
|
||||
}
|
||||
|
||||
if (fromRemote != true) { send({ action: 'videoStop', id: id }); }
|
||||
updateControls();
|
||||
}
|
||||
|
||||
// Setup local audio/video
|
||||
function startLocalStream(constraints) {
|
||||
var channel = (multiWebRtc == true) ? 1 : 0;
|
||||
if (localStream != null) return;
|
||||
if ((multiWebRtc == true) && (webrtcSessions[1] != null)) return;
|
||||
if (navigator.mediaDevices.getUserMedia) {
|
||||
localStream = 1;
|
||||
updateControls();
|
||||
navigator.mediaDevices.getUserMedia(constraints)
|
||||
.then(function (stream) {
|
||||
localStream = stream;
|
||||
var tracks = localStream.getTracks();
|
||||
var webrtc = startWebRTC(channel);
|
||||
if (constraints.video == true) {
|
||||
var video = Q('localVideoCanvas');
|
||||
video.srcObject = stream;
|
||||
video.onloadedmetadata = function (e) { video.play(); };
|
||||
displayLocalVideo(true);
|
||||
}
|
||||
for (var i in tracks) { webrtc.addTrack(tracks[i], localStream); }
|
||||
}, function (err) {
|
||||
displayControl(err.message + '.');
|
||||
hangUpButtonClick(1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This is the main start
|
||||
function start() {
|
||||
// Get started
|
||||
updateControls();
|
||||
if ((typeof args.id == 'string') && (args.id.length > 0)) {
|
||||
var url = window.location.protocol.replace('http', 'ws') + '//' + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + '/meshrelay.ashx?id=' + args.id;
|
||||
if ((args.auth != null) && (args.auth != '')) { url += '&auth=' + args.auth; }
|
||||
socket = new WebSocket(url);
|
||||
socket.onopen = function () { state = 1; displayControl("Aguardando outro usuário ..."); }
|
||||
socket.onerror = function (e) { /*console.error(e);*/ }
|
||||
socket.onclose = function () { disconnect(); }
|
||||
socket.onmessage = function (msg) {
|
||||
if ((state < 2) && (typeof msg.data == 'string') && ((msg.data == 'c') || (msg.data == 'cr'))) {
|
||||
hangUpButtonClick(0, true);
|
||||
hangUpButtonClick(1, true);
|
||||
hangUpButtonClick(2, true);
|
||||
displayControl("Conectado.");
|
||||
state = 2;
|
||||
updateControls();
|
||||
sendws({ action: 'random', random: random }); // Send a random number. Higher number starts the WebRTC session.
|
||||
return;
|
||||
}
|
||||
if (state == 2) { processMessage(msg.data, 1); }
|
||||
}
|
||||
} else {
|
||||
displayControl("Erro: Nenhuma chave de conexão especificada.");
|
||||
}
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
function onUnLoad() {
|
||||
for (var i = 0; i < 3; i++) { if (webrtcSessions[i]) { webrtcSessions[i].close(); delete webrtcSessions[i]; } }
|
||||
if (webchannel != null) { try { webchannel.close(); } catch (e) { } webchannel = null; }
|
||||
if (socket != null) { try { socket.close(); } catch (e) { } socket = null; }
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body></html>
|
84
views/translations/terms-min_pt.handlebars
Normal file
84
views/translations/terms-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
1
views/translations/terms-mobile-min_pt.handlebars
Normal file
1
views/translations/terms-mobile-min_pt.handlebars
Normal file
File diff suppressed because one or more lines are too long
160
views/translations/terms-mobile_pt.handlebars
Normal file
160
views/translations/terms-mobile_pt.handlebars
Normal file
@ -0,0 +1,160 @@
|
||||
<!DOCTYPE html><html><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<title>MeshCentral - Terms of use</title>
|
||||
<style type="text/css">
|
||||
a {
|
||||
color: #036;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a:hover {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<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">
|
||||
<!-- Begin Masthead -->
|
||||
<div id="masthead" style="background:url(logo.png) 0px 0px;background-size:341px 50px;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">
|
||||
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px">
|
||||
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px">
|
||||
<div id="column_l" style="padding-left:10px;padding-right:10px">
|
||||
<h1>Termos de uso</h1>
|
||||
<p>Entre em contato com o administrador do site para obter os termos de uso.</p>
|
||||
<hr>
|
||||
<p class="MsoNormal">
|
||||
A seguir, são apresentadas as divulgações necessárias de componentes e software de código aberto incorporados neste software.
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>1.AJAX Control Toolkit - Nova licença BSD</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>A redistribuição e uso nas formas de origem e binárias, com ou sem modificação, são permitidas desde que as seguintes condições sejam atendidas:<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>1.As redistribuições do código-fonte devem manter o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>2.As redistribuições em formato binário devem reproduzir o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir na documentação e / ou outros materiais fornecidos com a distribuição.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>3.Nem o nome da CodePlex Foundation nem os nomes de seus colaboradores podem ser usados \u200b\u200bpara endossar ou promover produtos derivados deste software sem permissão prévia por escrito específica.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>ESTE SOFTWARE É FORNECIDO PELOS TITULARES DE DIREITOS AUTORAIS E CONTRIBUIDORES "TAL COMO ESTÁ" E QUALQUER GARANTIA EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A, AS GARANTIAS IMPLÍCITAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UM PROPÓSITO ESPECÍFICO. EM NENHUM CASO O DIVISOR DE DIREITOS AUTORAIS OU OS CONTRIBUIDORES SERÃO RESPONSÁVEIS POR QUALQUER DANO DIRETO, INDIRETO, INCIDENTAL, ESPECIAL, EXEMPLAR OU CONSEQÜENCIAL (INCLUINDO, MAS NÃO SE LIMITANDO A, PROCURAÇÃO DE BENS OU SERVIÇOS SUBSTITUTOS; PERDA DE USO, DADOS, LUCROS DE USO); OU INTERRUPÇÃO DE NEGÓCIOS), CAUSADA E QUALQUER TEORIA DE RESPONSABILIDADE, CONTRATADA, RESPONSABILIDADE ESTIMATIVA OU ATRIBUIÇÃO (INCLUINDO NEGLIGÊNCIA OU DE OUTRA FORMA), surgindo de qualquer maneira fora do uso deste software, mesmo que seja aconselhável a possibilidade de tal conteúdo.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>2.OpenSSL - Licença OpenSSL e SSLeay</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span><a href="http://www.openssl.org/source/license.html">http://www.openssl.org/source/license.html</a> </span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>A redistribuição e uso nas formas de origem e binárias, com ou sem modificação, são permitidas desde que as seguintes condições sejam atendidas:<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>1.As redistribuições do código-fonte devem manter o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>2.As redistribuições em formato binário devem reproduzir o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir na documentação e / ou outros materiais fornecidos com a distribuição. <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>3.Todos os materiais publicitários que mencionam os recursos ou o uso deste software devem exibir o seguinte reconhecimento: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>4.The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>5.Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>6.As redistribuições de qualquer forma devem manter o seguinte reconhecimento: "Este produto inclui software desenvolvido pelo OpenSSL Project para uso no OpenSSL Toolkit (http://www.openssl.org/)". <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>ESTE SOFTWARE É FORNECIDO PELO PROJETO OpenSSL `` COMO ESTÁ '' E QUALQUER GARANTIA EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A, AS GARANTIAS IMPLÍCITAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA. EM NENHUM CASO O PROJETO OpenSSL OU SEUS CONTRIBUIDORES SERÃO RESPONSÁVEIS POR QUALQUER DANO DIRETO, INDIRETO, INCIDENTAL, ESPECIAL, EXEMPLAR OU CONSEQÜENCIAL (INCLUINDO DANOS ESPECIAIS, EXEMPLARES OU CONSEQÜENCIAIS (INCLUINDO, PROCESSOS, MAS NÃO LIMITADOS OU SERVIÇOS; PERDA DE USO, DADOS OU LUCROS; OU INTERRUPÇÃO DE NEGÓCIOS), CAUSADOS E QUALQUER TEORIA DE RESPONSABILIDADE, CONTRATOS, RESPONSABILIDADE ESTIMATIVA OU ATORT (INCLUINDO NEGLIGÊNCIA OU DE OUTRA FORMA) QUE POSSUEM DE QUALQUER FORMA DESTE USO SOFTWARE, MESMO SE AVISADO DA POSSIBILIDADE DE TAIS DANOS.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>3.jQuery Foundation - Licença MIT</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright 2013 jQuery Foundation e outros colaboradores <a href="http://jquery.com/">http://jquery.com/</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRACÇÃO. EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS RESPONSABILIZARÃO POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, TORT OU OUTRA FORMA, DECORRENTE DE, FORA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTROS NEGÓCIOS NO PROGRAMAS.</span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>4.Interface do Usuário jQuery - Licença MIT</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright 2013 jQuery Foundation e outros colaboradores, <a href="http://jqueryui.com/">http://jqueryui.com/</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Este software consiste em contribuições voluntárias feitas por muitos indivíduos (AUTORES.txt, http://jqueryui.com/about ). Para obter o histórico exato de contribuições, consulte o histórico de revisões e os logs, disponíveis em http://jquery-ui.googlecode.com/svn/ <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRACÇÃO. EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS RESPONSABILIZARÃO POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, TORT OU OUTRA FORMA, DECORRENTE DE, FORA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTROS NEGÓCIOS NO PROGRAMAS.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>5.noVNC - Licença Pública Mozilla 2.0 0</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span><a href="https://github.com/kanaka/noVNC/blob/master/LICENSE.txt">https://github.com/kanaka/noVNC/blob/master/LICENSE.txt</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright (C) 2011 Joel Martin Este formulário de código-fonte está sujeito aos termos da Licença Pública Mozilla, v.2.0 0.Se uma cópia da MPL não foi distribuída com este arquivo, você pode obter uma em http: // mozilla.org / MPL / 2.0 /.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>6.Rcarousel - License MIT</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span><a href="https://github.com/ryrych/rcarousel/blob/master/widget/license">https://github.com/ryrych/rcarousel/blob/master/widget/license</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright (c) 2010 Wojciech 'RRH' Ryrych<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRACÇÃO. EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS RESPONSABILIZARÃO POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, TORT OU OUTRA FORMA, DECORRENTE DE, FORA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTROS NEGÓCIOS NO PROGRAMAS.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>7.Webtoolkit Javascript Base 64 - Licença Creative Commons Attribution 2.0 UK</span></b><span><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Este software usa código de <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a> licenciado sob o <a href="http://creativecommons.org/licenses/by/2.0/uk/legalcode">http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> e sua fonte pode ser baixada de <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span>
|
||||
</p>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
|
||||
<table cellpadding="0" cellspacing="6" style="width:100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left;color:white">{{{footer}}}</td>
|
||||
<td style="text-align:right">{{{rootCertLink}}} <a href="/">Voltar</a></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body></html>
|
246
views/translations/terms_pt.handlebars
Normal file
246
views/translations/terms_pt.handlebars
Normal file
@ -0,0 +1,246 @@
|
||||
<!DOCTYPE html><html><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<title>MeshCentral - Terms of use</title>
|
||||
</head>
|
||||
<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
|
||||
<div id="container">
|
||||
<!-- Begin Masthead -->
|
||||
<div id="masthead" class="noselect" style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden;">
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
|
||||
<strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
|
||||
<strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
<p id="logoutControl" style="color:white;font-size:11px;margin: 10px 10px 0;"></p>
|
||||
</div>
|
||||
<div id="page_leftbar">
|
||||
<div style="height:16px"></div>
|
||||
</div>
|
||||
<div id="topbar" class="noselect style3" style="height:24px;position:relative">
|
||||
<div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
|
||||
♦
|
||||
<div id="uiMenu" style="display:none">
|
||||
<div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
|
||||
<div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
|
||||
<div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
|
||||
<div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
|
||||
<h1>Termos de uso</h1>
|
||||
<p>Entre em contato com o administrador do site para obter os termos de uso.</p>
|
||||
<hr>
|
||||
<p class="MsoNormal">
|
||||
A seguir, são apresentadas as divulgações necessárias de componentes e software de código aberto incorporados neste software.
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>1.AJAX Control Toolkit - Nova licença BSD</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>A redistribuição e uso nas formas de origem e binárias, com ou sem modificação, são permitidas desde que as seguintes condições sejam atendidas:<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>1.As redistribuições do código-fonte devem manter o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>2.As redistribuições em formato binário devem reproduzir o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir na documentação e / ou outros materiais fornecidos com a distribuição.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>3.Nem o nome da CodePlex Foundation nem os nomes de seus colaboradores podem ser usados \u200b\u200bpara endossar ou promover produtos derivados deste software sem permissão prévia por escrito específica.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>ESTE SOFTWARE É FORNECIDO PELOS TITULARES DE DIREITOS AUTORAIS E CONTRIBUIDORES "TAL COMO ESTÁ" E QUALQUER GARANTIA EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A, AS GARANTIAS IMPLÍCITAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UM PROPÓSITO ESPECÍFICO. EM NENHUM CASO O DIVISOR DE DIREITOS AUTORAIS OU OS CONTRIBUIDORES SERÃO RESPONSÁVEIS POR QUALQUER DANO DIRETO, INDIRETO, INCIDENTAL, ESPECIAL, EXEMPLAR OU CONSEQÜENCIAL (INCLUINDO, MAS NÃO SE LIMITANDO A, PROCURAÇÃO DE BENS OU SERVIÇOS SUBSTITUTOS; PERDA DE USO, DADOS, LUCROS DE USO); OU INTERRUPÇÃO DE NEGÓCIOS), CAUSADA E QUALQUER TEORIA DE RESPONSABILIDADE, CONTRATADA, RESPONSABILIDADE ESTIMATIVA OU ATRIBUIÇÃO (INCLUINDO NEGLIGÊNCIA OU DE OUTRA FORMA), surgindo de qualquer maneira fora do uso deste software, mesmo que seja aconselhável a possibilidade de tal conteúdo.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>2.OpenSSL - Licença OpenSSL e SSLeay</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span><a href="http://www.openssl.org/source/license.html">http://www.openssl.org/source/license.html</a> </span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>A redistribuição e uso nas formas de origem e binárias, com ou sem modificação, são permitidas desde que as seguintes condições sejam atendidas:<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>1.As redistribuições do código-fonte devem manter o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>2.As redistribuições em formato binário devem reproduzir o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir na documentação e / ou outros materiais fornecidos com a distribuição. <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>3.Todos os materiais publicitários que mencionam os recursos ou o uso deste software devem exibir o seguinte reconhecimento: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>4.The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>5.Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>6.As redistribuições de qualquer forma devem manter o seguinte reconhecimento: "Este produto inclui software desenvolvido pelo OpenSSL Project para uso no OpenSSL Toolkit (http://www.openssl.org/)". <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>ESTE SOFTWARE É FORNECIDO PELO PROJETO OpenSSL `` COMO ESTÁ '' E QUALQUER GARANTIA EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A, AS GARANTIAS IMPLÍCITAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA. EM NENHUM CASO O PROJETO OpenSSL OU SEUS CONTRIBUIDORES SERÃO RESPONSÁVEIS POR QUALQUER DANO DIRETO, INDIRETO, INCIDENTAL, ESPECIAL, EXEMPLAR OU CONSEQÜENCIAL (INCLUINDO DANOS ESPECIAIS, EXEMPLARES OU CONSEQÜENCIAIS (INCLUINDO, PROCESSOS, MAS NÃO LIMITADOS OU SERVIÇOS; PERDA DE USO, DADOS OU LUCROS; OU INTERRUPÇÃO DE NEGÓCIOS), CAUSADOS E QUALQUER TEORIA DE RESPONSABILIDADE, CONTRATOS, RESPONSABILIDADE ESTIMATIVA OU ATORT (INCLUINDO NEGLIGÊNCIA OU DE OUTRA FORMA) QUE POSSUEM DE QUALQUER FORMA DESTE USO SOFTWARE, MESMO SE AVISADO DA POSSIBILIDADE DE TAIS DANOS.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>3.jQuery Foundation - Licença MIT</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright 2013 jQuery Foundation e outros colaboradores <a href="http://jquery.com/">http://jquery.com/</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRACÇÃO. EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS RESPONSABILIZARÃO POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, TORT OU OUTRA FORMA, DECORRENTE DE, FORA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTROS NEGÓCIOS NO PROGRAMAS.</span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>4.Interface do Usuário jQuery - Licença MIT</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright 2013 jQuery Foundation e outros colaboradores, <a href="http://jqueryui.com/">http://jqueryui.com/</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Este software consiste em contribuições voluntárias feitas por muitos indivíduos (AUTORES.txt, http://jqueryui.com/about ). Para obter o histórico exato de contribuições, consulte o histórico de revisões e os logs, disponíveis em http://jquery-ui.googlecode.com/svn/ <o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRACÇÃO. EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS RESPONSABILIZARÃO POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, TORT OU OUTRA FORMA, DECORRENTE DE, FORA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTROS NEGÓCIOS NO PROGRAMAS.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>5.noVNC - Licença Pública Mozilla 2.0 0</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span><a href="https://github.com/kanaka/noVNC/blob/master/LICENSE.txt">https://github.com/kanaka/noVNC/blob/master/LICENSE.txt</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright (C) 2011 Joel Martin Este formulário de código-fonte está sujeito aos termos da Licença Pública Mozilla, v.2.0 0.Se uma cópia da MPL não foi distribuída com este arquivo, você pode obter uma em http: // mozilla.org / MPL / 2.0 /.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>6.Rcarousel - License MIT</span></b><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Times New Roman""><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span><a href="https://github.com/ryrych/rcarousel/blob/master/widget/license">https://github.com/ryrych/rcarousel/blob/master/widget/license</a></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Copyright (c) 2010 Wojciech 'RRH' Ryrych<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRACÇÃO. EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS RESPONSABILIZARÃO POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, TORT OU OUTRA FORMA, DECORRENTE DE, FORA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTROS NEGÓCIOS NO PROGRAMAS.<o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<b><span>7.Webtoolkit Javascript Base 64 - Licença Creative Commons Attribution 2.0 UK</span></b><span><o:p></o:p></span>
|
||||
</p>
|
||||
<p class="MsoNormal">
|
||||
<span>Este software usa código de <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a> licenciado sob o <a href="http://creativecommons.org/licenses/by/2.0/uk/legalcode">http://creativecommons.org/licenses/by/2.0/uk/legalcode</a> e sua fonte pode ser baixada de <a href="http://www.webtoolkit.info/javascript-base64.html">http://www.webtoolkit.info/javascript-base64.html</a>.<o:p></o:p></span>
|
||||
</p>
|
||||
<br>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<table cellpadding="0" cellspacing="10" style="width: 100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left"></td>
|
||||
<td style="text-align:right"><a href="/">Voltar</a></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var uiMode = parseInt(getstore('uiMode', 1));
|
||||
var webPageStackMenu = false;
|
||||
var webPageFullScreen = true;
|
||||
var nightMode = (getstore('_nightMode', '0') == '1');
|
||||
var logoutControls = {{{logoutControls}}};
|
||||
|
||||
var terms = '{{{terms}}}';
|
||||
if (terms != '') { QH('column_l', decodeURIComponent(terms)); }
|
||||
QV('column_l', true);
|
||||
userInterfaceSelectMenu();
|
||||
|
||||
// Setup logout control
|
||||
var logoutControl = '';
|
||||
if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); }
|
||||
if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Sair" + '</a>'); }
|
||||
QH('logoutControl', logoutControl);
|
||||
|
||||
// Toggle user interface menu
|
||||
function showUserInterfaceSelectMenu() {
|
||||
Q('uiViewButton1').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton2').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton3').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton4').classList.remove('uiSelectorSel');
|
||||
try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
|
||||
QV('uiMenu', (QS('uiMenu').display == 'none'));
|
||||
if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
|
||||
}
|
||||
|
||||
function userInterfaceSelectMenu(s) {
|
||||
if (s) { uiMode = s; putstore('uiMode', uiMode); }
|
||||
webPageFullScreen = (uiMode < 3);
|
||||
webPageStackMenu = true;//(uiMode > 1);
|
||||
toggleFullScreen(0);
|
||||
toggleStackMenu(0);
|
||||
QC('column_l').add('room4submenu');
|
||||
}
|
||||
|
||||
function toggleNightMode() {
|
||||
nightMode = !nightMode;
|
||||
if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
|
||||
putstore('_nightMode', nightMode ? '1' : '0');
|
||||
}
|
||||
|
||||
// Toggle the web page to full screen
|
||||
function toggleFullScreen(toggle) {
|
||||
if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
|
||||
var hide = 0;
|
||||
//if (args.hide) { hide = parseInt(args.hide); }
|
||||
if (webPageFullScreen == false) {
|
||||
QC('body').remove('menu_stack');
|
||||
QC('body').remove('fullscreen');
|
||||
QC('body').remove('arg_hide');
|
||||
//if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
|
||||
//QV('UserDummyMenuSpan', false);
|
||||
//QV('page_leftbar', false);
|
||||
} else {
|
||||
QC('body').add('fullscreen');
|
||||
if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
|
||||
//QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
|
||||
//QV('page_leftbar', true);
|
||||
}
|
||||
QV('body', true);
|
||||
}
|
||||
|
||||
// If FullScreen, toggle menu to be horisontal or vertical
|
||||
function toggleStackMenu(toggle) {
|
||||
if (webPageFullScreen == true) {
|
||||
if (toggle === 1) {
|
||||
webPageStackMenu = !webPageStackMenu;
|
||||
putstore('webPageStackMenu', webPageStackMenu);
|
||||
}
|
||||
if (webPageStackMenu == false) {
|
||||
QC('body').remove('menu_stack');
|
||||
} else {
|
||||
QC('body').add('menu_stack');
|
||||
//if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
|
||||
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
|
||||
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body></html>
|
@ -1690,9 +1690,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
var logoutcontrols = { name: user.name };
|
||||
var extras = (req.query.key != null) ? ('&key=' + req.query.key) : '';
|
||||
if ((domain.ldap == null) && (domain.sspi == null) && (obj.args.user == null) && (obj.args.nousers != true)) { logoutcontrols.logoutUrl = (domain.url + 'logout?' + Math.random() + extras); } // If a default user is in use or no user mode, don't display the logout button
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()), logoutControls: JSON.stringify(logoutcontrols) });
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()).split('\'').join('\\\''), logoutControls: JSON.stringify(logoutcontrols) });
|
||||
} else {
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()), logoutControls: '{}' });
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()).split('\'').join('\\\''), logoutControls: '{}' });
|
||||
}
|
||||
} else {
|
||||
// See if there is a terms.txt file in meshcentral-data
|
||||
@ -1709,9 +1709,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
var logoutcontrols = { name: user.name };
|
||||
var extras = (req.query.key != null) ? ('&key=' + req.query.key) : '';
|
||||
if ((domain.ldap == null) && (domain.sspi == null) && (obj.args.user == null) && (obj.args.nousers != true)) { logoutcontrols.logoutUrl = (domain.url + 'logout?' + Math.random() + extras); } // If a default user is in use or no user mode, don't display the logout button
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data), logoutControls: JSON.stringify(logoutcontrols) });
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: JSON.stringify(logoutcontrols) });
|
||||
} else {
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data), logoutControls: '{}' });
|
||||
render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: '{}' });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user