Added portuguese, translate.js merge command.

Ylian Saint-Hilaire committed Dec 9, 2019 at 13:43 UTC a7c39f30c7d3a1fa203823715f983f1b901a8a1f
31 files changed +28206 -1385
db.js
+2 -2
@@ -682,7 +682,7 @@ module.exports.CreateDB = function (parent, func) {
682 obj.RemoveMeshDocuments = function (id) { obj.file.deleteMany({ meshid: id }, { multi: true }); obj.file.deleteOne({ _id: 'nt' + id }); };
683 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]); } }); };
684 obj.DeleteDomain = function (domain, func) { obj.file.deleteMany({ domain: domain }, { multi: true }, func); };
685 - 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); } };
685 + 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); } };
686 obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } };
687 obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }).toArray(func); };
688 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) {
816 obj.RemoveMeshDocuments = function (id) { obj.file.remove({ meshid: id }, { multi: true }); obj.file.remove({ _id: 'nt' + id }); };
817 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]); } }); };
818 obj.DeleteDomain = function (domain, func) { obj.file.remove({ domain: domain }, { multi: true }, func); };
819 - 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); } };
819 + 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); } };
820 obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } };
821 obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); };
822 obj.getAmtUuidMeshNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); };
meshrelay.js
+36 -36
@@ -22,13 +22,13 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
22 obj.req = req; // Used in multi-server.js
23
24 // Check relay authentication
25 - if ((user == null) && (req.query.rauth != null)) {
26 - const rcookie = parent.parent.decodeCookie(req.query.rauth, parent.parent.loginCookieEncryptionKey, 240); // Cookie with 4 hour timeout
25 + if ((user == null) && (obj.req.query != null) && (obj.req.query.rauth != null)) {
26 + const rcookie = parent.parent.decodeCookie(obj.req.query.rauth, parent.parent.loginCookieEncryptionKey, 240); // Cookie with 4 hour timeout
27 if (rcookie.ruserid != null) { obj.ruserid = rcookie.ruserid; }
28 }
29
30 // If there is no authentication, drop this connection
31 - 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; }
31 + 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; }
32
33 // Relay session count (we may remove this in the future)
34 obj.relaySessionCounted = true;
@@ -58,8 +58,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
58
59 // Disconnect this agent
60 obj.close = function (arg) {
61 - 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
62 - 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
61 + 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
62 + 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
63
64 // Aggressive cleanup
65 delete obj.id;
@@ -153,7 +153,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
153 // Check that at least one connection is authenticated
154 if ((obj.authenticated != true) && (relayinfo.peer1.authenticated != true)) {
155 ws.close();
156 - parent.parent.debug('relay', 'Relay without-auth: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
156 + parent.parent.debug('relay', 'Relay without-auth: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
157 delete obj.id;
158 delete obj.ws;
159 delete obj.peer;
@@ -170,7 +170,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
170 }
171 if (u1 != u2) {
172 ws.close();
173 - parent.parent.debug('relay', 'Relay auth mismatch (' + u1 + ' != ' + u2 + '): ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
173 + parent.parent.debug('relay', 'Relay auth mismatch (' + u1 + ' != ' + u2 + '): ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
174 delete obj.id;
175 delete obj.ws;
176 delete obj.peer;
@@ -196,9 +196,9 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
196 // Setup session recording
197 var sessionUser = obj.user;
198 if (sessionUser == null) { sessionUser = obj.peer.user; }
199 - if ((sessionUser != null) && (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(parseInt(req.query.p)) >= 0))))) {
199 + if ((sessionUser != null) && (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(parseInt(obj.req.query.p)) >= 0))))) {
200 // Get the computer name
201 - parent.db.Get(req.query.nodeid, function (err, nodes) {
201 + parent.db.Get(obj.req.query.nodeid, function (err, nodes) {
202 var xusername = '', xdevicename = '', xdevicename2 = null;
203 if ((nodes != null) && (nodes.length == 1)) { xdevicename2 = nodes[0].name; xdevicename = '-' + parent.common.makeFilename(nodes[0].name); }
204
@@ -222,10 +222,10 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
222 try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
223 } else {
224 // Write the recording file header
225 - 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 ) };
225 + 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 ) };
226 if (xdevicename2 != null) { metadata.devicename = xdevicename2; }
227 var firstBlock = JSON.stringify(metadata);
228 - recordingEntry(fd, 1, ((req.query.browser) ? 2 : 0), firstBlock, function () {
228 + recordingEntry(fd, 1, ((obj.req.query.browser) ? 2 : 0), firstBlock, function () {
229 try { relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false }; } catch (ex) {
230 try { ws.send('c'); } catch (ex) { } // Send connect to both peers, 'cr' indicates the session is being recorded.
231 try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
@@ -243,21 +243,21 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
243 try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
244 }
245
246 - parent.parent.debug('relay', 'Relay connected: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ' --> ' + cleanRemoteAddr(obj.peer.req.ip) + ')');
246 + parent.parent.debug('relay', 'Relay connected: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ' --> ' + cleanRemoteAddr(obj.peer.req.ip) + ')');
247
248 // Log the connection
249 if (sessionUser != null) {
250 var msg = 'Started relay session';
251 - if (req.query.p == 1) { msg = 'Started terminal session'; }
252 - else if (req.query.p == 2) { msg = 'Started desktop session'; }
253 - else if (req.query.p == 5) { msg = 'Started file management session'; }
251 + if (obj.req.query.p == 1) { msg = 'Started terminal session'; }
252 + else if (obj.req.query.p == 2) { msg = 'Started desktop session'; }
253 + else if (obj.req.query.p == 5) { msg = 'Started file management session'; }
254 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 };
255 parent.parent.DispatchEvent(['*', sessionUser._id], obj, event);
256 }
257 } else {
258 // Connected already, drop (TODO: maybe we should re-connect?)
259 ws.close();
260 - parent.parent.debug('relay', 'Relay duplicate: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
260 + parent.parent.debug('relay', 'Relay duplicate: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
261 delete obj.id;
262 delete obj.ws;
263 delete obj.peer;
@@ -267,14 +267,14 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
267 // Wait for other relay connection
268 ws._socket.pause(); // Hold traffic until the other connection
269 parent.wsrelays[obj.id] = { peer1: obj, state: 1, timeout: setTimeout(function () { closeBothSides(); }, 30000) };
270 - parent.parent.debug('relay', 'Relay holding: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ') ' + (obj.authenticated ? 'Authenticated' : ''));
270 + parent.parent.debug('relay', 'Relay holding: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ') ' + (obj.authenticated ? 'Authenticated' : ''));
271
272 // Check if a peer server has this connection
273 if (parent.parent.multiServer != null) {
274 var rsession = parent.wsPeerRelays[obj.id];
275 if ((rsession != null) && (rsession.serverId > parent.parent.serverId)) {
276 // We must initiate the connection to the peer
277 - parent.parent.multiServer.createPeerRelay(ws, req, rsession.serverId, req.session.userid);
277 + parent.parent.multiServer.createPeerRelay(ws, req, rsession.serverId, obj.req.session.userid);
278 delete parent.wsrelays[obj.id];
279 } else {
280 // Send message to other peers that we have this connection
@@ -297,7 +297,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
297 if (this.logfile != null) {
298 // Write data to log file then perform relay
299 var xthis = this;
300 - recordingEntry(this.logfile.fd, 2, ((req.query.browser) ? 2 : 0), data, function () { xthis.peer.send(data, ws.flushSink); });
300 + recordingEntry(this.logfile.fd, 2, ((obj.req.query.browser) ? 2 : 0), data, function () { xthis.peer.send(data, ws.flushSink); });
301 } else {
302 // Perform relay
303 this.peer.send(data, ws.flushSink);
@@ -310,7 +310,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
310 ws.on('error', function (err) {
311 parent.relaySessionErrorCount++;
312 if (obj.relaySessionCounted) { parent.relaySessionCount--; delete obj.relaySessionCounted; }
313 - console.log('Relay error from ' + cleanRemoteAddr(req.ip) + ', ' + err.toString().split('\r')[0] + '.');
313 + console.log('Relay error from ' + cleanRemoteAddr(obj.req.ip) + ', ' + err.toString().split('\r')[0] + '.');
314 closeBothSides();
315 });
316
@@ -333,21 +333,21 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
333
334 // Disconnect the peer
335 try { if (peer.relaySessionCounted) { parent.relaySessionCount--; delete peer.relaySessionCounted; } } catch (ex) { console.log(ex); }
336 - parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ' --> ' + cleanRemoteAddr(peer.req.ip) + ')');
336 + parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ' --> ' + cleanRemoteAddr(peer.req.ip) + ')');
337 try { peer.ws.close(); } catch (e) { } // Soft disconnect
338 try { peer.ws._socket._parent.end(); } catch (e) { } // Hard disconnect
339
340 // Log the disconnection
341 if (ws.time) {
342 var msg = 'Ended relay session';
343 - if (req.query.p == 1) { msg = 'Ended terminal session'; }
344 - else if (req.query.p == 2) { msg = 'Ended desktop session'; }
345 - else if (req.query.p == 5) { msg = 'Ended file management session'; }
343 + if (obj.req.query.p == 1) { msg = 'Ended terminal session'; }
344 + else if (obj.req.query.p == 2) { msg = 'Ended desktop session'; }
345 + else if (obj.req.query.p == 5) { msg = 'Ended file management session'; }
346 if (user) {
347 - 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 };
347 + 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 };
348 parent.parent.DispatchEvent(['*', user._id], obj, event);
349 } else if (peer.user) {
350 - 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 };
350 + 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 };
351 parent.parent.DispatchEvent(['*', peer.user._id], obj, event);
352 }
353 }
@@ -357,7 +357,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
357 delete peer.ws;
358 delete peer.peer;
359 } else {
360 - parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(req.ip) + ')');
360 + parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')');
361 }
362 try { ws.close(); } catch (ex) { }
363 delete parent.wsrelays[obj.id];
@@ -415,13 +415,13 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
415 if (obj.id == undefined) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one.
416 const command = { nodeid: cookie.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id + '&rauth=' + rcookie, tcpport: cookie.tcpport, tcpaddr: cookie.tcpaddr };
417 parent.parent.debug('relay', 'Relay: Sending agent tunnel command: ' + JSON.stringify(command));
418 - 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) + ')'); }
418 + 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) + ')'); }
419 performRelay();
420 });
421 return obj;
422 - } else if ((req.query.nodeid != null) && ((req.query.tcpport != null) || (req.query.udpport != null))) {
422 + } else if ((obj.req.query.nodeid != null) && ((obj.req.query.tcpport != null) || (obj.req.query.udpport != null))) {
423 // We have routing instructions in the URL arguments, but first, check user access for this node.
424 - parent.db.Get(req.query.nodeid, function (err, docs) {
424 + parent.db.Get(obj.req.query.nodeid, function (err, docs) {
425 if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
426 const node = docs[0];
427
@@ -433,14 +433,14 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
433 if (obj.id == null) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one.
434 const rcookie = parent.parent.encodeCookie({ ruserid: user._id }, parent.parent.loginCookieEncryptionKey);
435
436 - if (req.query.tcpport != null) {
437 - 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) };
436 + if (obj.req.query.tcpport != null) {
437 + 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) };
438 parent.parent.debug('relay', 'Relay: Sending agent TCP tunnel command: ' + JSON.stringify(command));
439 - 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) + ')'); }
440 - } else if (req.query.udpport != null) {
441 - 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) };
439 + 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) + ')'); }
440 + } else if (obj.req.query.udpport != null) {
441 + 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) };
442 parent.parent.debug('relay', 'Relay: Sending agent UDP tunnel command: ' + JSON.stringify(command));
443 - 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) + ')'); }
443 + 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) + ')'); }
444 }
445 performRelay();
446 });
public/translations/player-min_pt.htm new
+1
@@ -0,0 +1 @@
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><script src=scripts/common-0.0.1.js></script><script src=scripts/agent-desktop-0.0.2.js></script><script src=scripts/amt-desktop-0.0.2.js></script><script src=scripts/amt-terminal-0.0.2.js></script><script src=scripts/zlib.js></script><script src=scripts/zlib-inflate.js></script><script src=scripts/zlib-adler32.js></script><script src=scripts/zlib-crc32.js></script><body style=overflow:hidden;background-color:#000><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><div class=areaProgress><div id=progressbar></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:#d3d3d3;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:#ff0;background-color:rgba(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>&nbsp; <input id=PlayButton type=button value=Play disabled onclick=play()> <input id=PauseButton type=button value=Pausa disabled onclick=pause()> <input id=RestartButton type=button value=Reiniciar disabled onclick=restart()> <select id=PlaySpeed onchange=this.blur()><option value=4>1/4 de velocidade<option value=2>1/2 velocidade<option value=1 selected>Velocidade normal<option value=0.5>2x velocidade<option value=0.25>4x velocidade<option value=0.1>10x Velocidade</select></div></div></div><div id=dialog class=noselect style=display:none><div id=dialogHeader><div tabindex=0 id=id_dialogclose onclick=setDialogMode() onkeypress='"Enter"==event.key&&setDialogMode()'>✖</div><div id=id_dialogtitle></div></div><div id=dialogBody><div id=dialog1><div id=id_dialogMessage></div></div><div id=dialog2><div id=id_dialogOptions></div></div></div><div id=idx_dlgButtonBar><input id=idx_dlgCancelButton type=button value=Cancelar onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=Ok 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,recFilePtr=0,recFileStartTime=0,recFileLastTime=0,recFileEndTime=0,recFileMetadata=null,recFileProtocol=0,agentDesktop=null,amtDesktop=null,playing=!1,readState=0,waitTimer=null,waitTimerArgs=null,deskAspectRatio=0,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(l){if(recFilePtr+16>recFile.size)QS("progressbar").width="100%",l(-1);else{var e=new FileReader;e.onload=function(){var e=ReadShort(this.result,0),t=ReadShort(this.result,2),a=ReadInt(this.result,4),r=(ReadInt(this.result,8)<<32)+ReadInt(this.result,12);if(recFilePtr+16+a>recFile.size)QS("progressbar").width="100%",l(-1);else{var i=new FileReader;i.onload=function(){recFilePtr+=16+a,QS("progressbar").width=0==recFileEndTime?Math.floor(recFilePtr/recFile.size*100)+"%":Math.floor((recFileLastTime-recFileStartTime)/(recFileEndTime-recFileStartTime)*100)+"%",l(e,t,r,this.result)},i.readAsBinaryString(recFile.slice(recFilePtr+16,recFilePtr+16+a))}},e.readAsBinaryString(recFile.slice(recFilePtr,recFilePtr+16))}}function readLastBlock(i){if(recFile.size<32)i(-1);else{var e=new FileReader;e.onload=function(){var e=ReadShort(this.result,0),t=ReadShort(this.result,2),a=ReadInt(this.result,4),r=(ReadInt(this.result,8)<<32)+ReadInt(this.result,12);3==e&&16==a&&"MeshCentralMCREC"==this.result.substring(16,32)?i(e,t,r):i(-1)},e.readAsBinaryString(recFile.slice(recFile.size-32,recFile.size))}}function addInfo(e,t){return null==t?"":addInfoNoEsc(e,EscapeHtml(t))}function addInfoNoEsc(e,t){return null==t?"":"<span style=color:gray>"+EscapeHtml(e)+"</span>:&nbsp;<span style=font-size:20px>"+t+"</span><br/>"}function processFirstBlock(e,t,a,r){if(recFileProtocol=0,1==e&&0==t){try{recFileMetadata=JSON.parse(r)}catch(e){return void cleanup()}if(null!=recFileMetadata&&"MeshCentralRelaySession"==recFileMetadata.magic&&1==recFileMetadata.ver){var i="";if(i+=addInfo("Tempo",recFileMetadata.time),0!=recFileEndTime){var l=Math.floor((recFileEndTime-a)/1e3);i+=addInfo("Duração",format("{0} segundo{1}",l,1<l?"s":""))}if(i+=addInfo("Nome de usuário",recFileMetadata.username),i+=addInfo("ID do usuário",recFileMetadata.userid),i+=addInfo("ID da sessão",recFileMetadata.sessionid),recFileMetadata.ipaddr1&&recFileMetadata.ipaddr2&&(i+=addInfo("Endereços",format("{0} para {1}",recFileMetadata.ipaddr1,recFileMetadata.ipaddr2))),recFileMetadata.devicename&&(i+=addInfo("Nome do Dispositivo",recFileMetadata.devicename)),i+=addInfo("NodeID",recFileMetadata.nodeid),recFileMetadata.protocol){var o=recFileMetadata.protocol;1==o?o="MeshCentral Terminal":2==o?o="MeshCentral Desktop":100==o?o="Intel&reg; AMT WSMAN":101==o&&(o="Intel&reg; Redirecionamento AMT"),i+=addInfoNoEsc("Protocolo",o)}QV("DeskParent",!0),QV("TermParent",!1),1==recFileMetadata.protocol?(recFileProtocol=1,i+="<br /><br /><span style=color:gray>Pressione [espaço] para reproduzir / pausar.</span>",QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),recFileStartTime=recFileLastTime=a):2==recFileMetadata.protocol?(recFileProtocol=2,i+="<br /><br /><span style=color:gray>Pressione [espaço] para reproduzir / pausar.</span>",QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),recFileStartTime=recFileLastTime=a,(agentDesktop=CreateAgentRemoteDesktop("Desk")).onScreenSizeChange=deskAdjust,agentDesktop.State=3,deskAdjust()):101==recFileMetadata.protocol&&(recFileProtocol=101,i+="<br /><br /><span style=color:gray>Press [space] to play/pause.</span>",QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),recFileStartTime=recFileLastTime=a,(amtDesktop=CreateAmtRemoteDesktop("Desk")).onScreenSizeChange=deskAdjust,amtDesktop.State=3,amtDesktop.Start(),deskAdjust()),QV("metadatadiv",!0),QH("metadatadiv",i),QH("deskstatus",recFile.name)}else cleanup()}else cleanup()}function processBlock(e,t,a,r){if(e<0)pause();else{var i=Math.round((a-recFileLastTime)*parseFloat(Q("PlaySpeed").value));i<5?processBlockEx(e,t,a,r):(waitTimerArgs=[e,t,a,r],waitTimer=setTimeout(function(){waitTimer=null,processBlockEx(waitTimerArgs[0],waitTimerArgs[1],waitTimerArgs[2],waitTimerArgs[3])},i))}}function processBlockEx(e,t,a,r){if(0!=playing){var i=0!=(1&t),l=0!=(2&t),o=Math.floor((a-recFileStartTime)/1e3);if(currentDeltaTimeTotalSec!=o){currentDeltaTimeTotalSec=o;var n=Math.floor(o/3600);o-=3600*n;var s=Math.floor(o/60);o-=60*n;var d=Math.floor(o);QH("timespan",pad2(n)+":"+pad2(s)+":"+pad2(d))}2==e&&i&&!l?1==recFileProtocol?agentTerminal.ProcessData(r):2==recFileProtocol?agentDesktop.ProcessData(r):101==recFileProtocol&&(0==readState&&"4100000000000000"==rstr2hex(r)?(readState=1,8<r.length&&amtDesktop.ProcessData(r.substring(8))):1==readState&&amtDesktop.ProcessData(r)):2==e&&i&&l&&101==recFileProtocol&&"0000000008080001000700070003050200000000"==rstr2hex(r)&&(amtDesktop.bpp=1),recFileLastTime=a,playing&&readNextBlock(processBlock)}}function cleanup(){recFilePtr=0,playing=!1,(recFileMetadata=recFile=null)!=agentDesktop&&(agentDesktop.Canvas.clearRect(0,0,agentDesktop.CanvasId.width,agentDesktop.CanvasId.height),agentDesktop=null),null!=amtDesktop&&(amtDesktop.canvas.clearRect(0,0,amtDesktop.CanvasId.width,amtDesktop.CanvasId.height),amtDesktop=null),recFileEndTime=currentDeltaTimeTotalSec=readState=0,(agentTerminal=waitTimerArgs=null)!=waitTimer&&(clearTimeout(waitTimer),waitTimer=null),QH("deskstatus",""),QE("PlayButton",!1),QE("PauseButton",!1),QE("RestartButton",!1),QS("progressbar").width="0px",QH("timespan","00:00:00"),QV("metadatadiv",!0),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",!0),QV("TermParent",!1)}function ondrop(e){if(haltEvent(e),QV("bigfail",!1),QV("bigok",!1),null!=e.dataTransfer){var t=[];for(var a in e.dataTransfer.files)null!=e.dataTransfer.files[a].type&&null!=e.dataTransfer.files[a].size&&0!=e.dataTransfer.files[a].size&&e.dataTransfer.files[a].name.endsWith(".mcrec")&&t.push(e.dataTransfer.files[a]);0!=t.length&&(cleanup(),recFile=t[0],recFilePtr=0,readNextBlock(processFirstBlock),readLastBlock(function(e,t,a){recFileEndTime=3==e?a:0}))}}var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,dragtimer=null;function ondragover(e){haltEvent(e),null!=dragtimer&&(clearTimeout(dragtimer),dragtimer=null);QV("bigok",!0),QV("bigfail",!1)}function ondragleave(e){haltEvent(e),dragtimer=setTimeout(function(){QV("bigfail",!1),QV("bigok",!1),dragtimer=null},10)}function onkeypress(e){xxdialogMode||(" "==e.key&&(togglePause(),haltEvent(e)),"1"==e.key&&(Q("PlaySpeed").value=4,haltEvent(e)),"2"==e.key&&(Q("PlaySpeed").value=2,haltEvent(e)),"3"==e.key&&(Q("PlaySpeed").value=1,haltEvent(e)),"4"==e.key&&(Q("PlaySpeed").value=.5,haltEvent(e)),"5"==e.key&&(Q("PlaySpeed").value=.25,haltEvent(e)),"6"==e.key&&(Q("PlaySpeed").value=.1,haltEvent(e)),"0"==e.key&&(pause(),restart(),haltEvent(e)))}function openfile(){setDialogMode(2,"Abrir arquivo...",3,openfileEx,'<input type=file name=files id=p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />'),QE("idx_dlgOkButton",!1)}function openfileEx(){var e=Q("p2fileinput").files;if(null!=e){var t=[];for(var a in e)null!=e[a].type&&null!=e[a].size&&0!=e[a].size&&e[a].name.endsWith(".mcrec")&&t.push(e[a])}0!=t.length&&(cleanup(),recFile=t[0],recFilePtr=0,readNextBlock(processFirstBlock),readLastBlock(function(e,t,a){recFileEndTime=3==e?a:0}),Q("OpenFileButton").blur())}function openfileChanged(){var e=Q("p2fileinput").files;if(null!=e){var t=[];for(var a in e)null!=e[a].type&&null!=e[a].size&&0!=e[a].size&&e[a].name.endsWith(".mcrec")&&t.push(e[a])}QE("idx_dlgOkButton",1==t.length)}function togglePause(){return null!=recFile&&(1==playing?pause():recFilePtr!=recFile.size&&play()),!1}function play(){Q("PlayButton").blur(),1!=playing&&0!=recFileProtocol&&(playing=!0,QV("metadatadiv",!1),QE("PlayButton",!1),QE("PauseButton",!0),QE("RestartButton",!1),1==recFileProtocol&&null==agentTerminal&&(QV("DeskParent",!1),QV("TermParent",!0),agentTerminal=CreateAmtRemoteTerminal("Term",{}),agentTerminal.State=3),readNextBlock(processBlock))}function pause(){Q("PauseButton").blur(),0!=playing&&(playing=!1,QE("PlayButton",recFilePtr!=recFile.size),QE("PauseButton",!1),QE("RestartButton",0!=recFilePtr),null!=waitTimer&&(clearTimeout(waitTimer),waitTimer=null,processBlockEx(waitTimerArgs[0],waitTimerArgs[1],waitTimerArgs[2],waitTimerArgs[3]),waitTimerArgs=null))}function restart(){Q("RestartButton").blur(),1!=playing&&(currentDeltaTimeTotalSec=readState=recFilePtr=0,QV("metadatadiv",!0),QE("PlayButton",!0),QE("PauseButton",!1),QE("RestartButton",!1),QS("progressbar").width="0px",QH("timespan","00:00:00"),QV("DeskParent",!0),QV("TermParent",!1),agentDesktop?agentDesktop.Canvas.clearRect(0,0,agentDesktop.CanvasId.width,agentDesktop.CanvasId.height):amtDesktop?(amtDesktop.canvas.clearRect(0,0,amtDesktop.CanvasId.width,amtDesktop.CanvasId.height),(amtDesktop=CreateAmtRemoteDesktop("Desk")).onScreenSizeChange=deskAdjust,amtDesktop.State=3,amtDesktop.Start()):agentTerminal=agentTerminal&&null)}function clearConsoleMsg(){QH("p11DeskConsoleMsg","")}function toggleAspectRatio(e){1===e&&(deskAspectRatio=(deskAspectRatio+1)%3),deskAdjust()}function deskAdjust(){var e=Q("DeskParent").clientHeight,t=Q("DeskParent").clientWidth,a=Q("Desk").height,r=Q("Desk").width;if(2==deskAspectRatio)QS("Desk")["margin-top"]=null,QS("Desk").height="100%",QS("Desk").width="100%",QS("DeskParent").overflow="hidden";else if(1==deskAspectRatio)QS("Desk")["margin-top"]="0px",QS("Desk").height=a+"px",QS("Desk").width=r+"px",QS("DeskParent").overflow="scroll";else{if(a/r<e/t){var i=a*t/r+"px";QS("Desk").height=i,QS("Desk").width="100%"}else{var l=r*e/a+"px";QS("Desk").height="100%",QS("Desk").width=l}QS("Desk")["margin-top"]=null,QS("DeskParent").overflow="hidden"}}var xxcurrentView=-1;function setDialogMode(e,t,a,r,i,l){xxdialogMode=e,xxdialogFunc=r,xxdialogButtons=a,xxdialogTag=l,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&a),QV("idx_dlgCancelButton",2&a),QV("id_dialogclose",2&a||8&a),QV("idx_dlgDeleteButton",4&a),QV("idx_dlgButtonBar",7&a),t&&QH("id_dialogtitle",t);for(var o=1;o<3;o++)QV("dialog"+o,o==e);QV("dialog",e),i&&(2==e?QH("id_dialogOptions",i):QH("id_dialogMessage",i))}function dialogclose(e){var t=xxdialogFunc,a=xxdialogButtons,r=xxdialogTag;setDialogMode(),(8&a||e)&&t&&t(e,r)}function messagebox(e,t){setSessionActivity(),QH("id_dialogMessage",t),setDialogMode(1,e,1)}function statusbox(e,t){setSessionActivity(),QH("id_dialogMessage",t),setDialogMode(1,e)}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function pad2(e){var t="00"+e;return t.substr(t.length-2)}function format(e){var a=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,t){return void 0!==a[t]?a[t]:e})}start()</script>
\ No newline at end of file
public/translations/player_pt.htm new
+537
@@ -0,0 +1,537 @@
1 +<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
8 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
9 + <script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
10 + <script type="text/javascript" src="scripts/amt-desktop-0.0.2.js"></script>
11 + <script type="text/javascript" src="scripts/amt-terminal-0.0.2.js"></script>
12 + <script type="text/javascript" src="scripts/zlib.js"></script>
13 + <script type="text/javascript" src="scripts/zlib-inflate.js"></script>
14 + <script type="text/javascript" src="scripts/zlib-adler32.js"></script>
15 + <script type="text/javascript" src="scripts/zlib-crc32.js"></script>
16 +</head>
17 +<body style="overflow:hidden;background-color:black">
18 + <div id="p11" class="noselect" style="overflow:hidden">
19 + <div id="deskarea0">
20 + <div id="deskarea1" class="areaHead">
21 + <div class="toright2">
22 + <div class="deskareaicon" title="Alternar modo de exibição" onclick="toggleAspectRatio(1)">⇲</div>
23 + </div>
24 + <div>
25 + <input id="OpenFileButton" type="button" value="Abrir arquivo..." onclick="openfile()">
26 + <span id="deskstatus"></span>
27 + </div>
28 + </div>
29 + <div id="deskarea2" style="">
30 + <div class="areaProgress"><div id="progressbar" style=""></div></div>
31 + </div>
32 + <div id="deskarea3x" style="max-height:calc(100vh - 54px);height:calc(100vh - 54px);" onclick="togglePause()">
33 + <div id="bigok" style="display:none;left:calc((100vh / 2))"><b>✓</b></div>
34 + <div id="bigfail" style="display:none;left:calc((100vh / 2))"><b>✗</b></div>
35 + <div id="metadatadiv" style="padding:20px;color:lightgrey;text-align:left;display:none"></div>
36 + <div id="DeskParent">
37 + <canvas id="Desk" width="640" height="480"></canvas>
38 + </div>
39 + <div id="TermParent" style="display:none">
40 + <pre id="Term"></pre>
41 + </div>
42 + <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>
43 + </div>
44 + <div id="deskarea4" class="areaFoot">
45 + <div class="toright2">
46 + <div id="timespan" style="padding-top:4px;padding-right:4px">00:00:00</div>
47 + </div>
48 + <div>
49 + &nbsp;
50 + <input id="PlayButton" type="button" value="Play" disabled="disabled" onclick="play()">
51 + <input id="PauseButton" type="button" value="Pausa" disabled="disabled" onclick="pause()">
52 + <input id="RestartButton" type="button" value="Reiniciar" disabled="disabled" onclick="restart()">
53 + <select id="PlaySpeed" onchange="this.blur();">
54 + <option value="4">1/4 de velocidade</option>
55 + <option value="2">1/2 velocidade</option>
56 + <option value="1" selected="">Velocidade normal</option>
57 + <option value="0.5">2x velocidade</option>
58 + <option value="0.25">4x velocidade</option>
59 + <option value="0.1">10x Velocidade</option>
60 + </select>
61 + </div>
62 + </div>
63 + </div>
64 + <div id="dialog" class="noselect" style="display:none">
65 + <div id="dialogHeader">
66 + <div tabindex="0" id="id_dialogclose" onclick="setDialogMode()" onkeypress="if (event.key == 'Enter') setDialogMode()">✖</div>
67 + <div id="id_dialogtitle"></div>
68 + </div>
69 + <div id="dialogBody">
70 + <div id="dialog1">
71 + <div id="id_dialogMessage" style=""></div>
72 + </div>
73 + <div id="dialog2" style="">
74 + <div id="id_dialogOptions"></div>
75 + </div>
76 + </div>
77 + <div id="idx_dlgButtonBar">
78 + <input id="idx_dlgCancelButton" type="button" value="Cancelar" style="" onclick="dialogclose(0)">
79 + <input id="idx_dlgOkButton" type="button" value="Ok" style="" onclick="dialogclose(1)">
80 + <div><input id="idx_dlgDeleteButton" type="button" value="Deletar" style="display:none" onclick="dialogclose(2)"></div>
81 + </div>
82 + </div>
83 + </div>
84 + <script>
85 + var recFile = null;
86 + var recFilePtr = 0;
87 + var recFileStartTime = 0;
88 + var recFileLastTime = 0;
89 + var recFileEndTime = 0;
90 + var recFileMetadata = null;
91 + var recFileProtocol = 0;
92 + var agentDesktop = null;
93 + var amtDesktop = null;
94 + var playing = false;
95 + var readState = 0;
96 + var waitTimer = null;
97 + var waitTimerArgs = null;
98 + var deskAspectRatio = 0;
99 + var currentDeltaTimeTotalSec = 0;
100 +
101 + function start() {
102 + window.onresize = deskAdjust;
103 + document.ondrop = ondrop;
104 + document.ondragover = ondragover;
105 + document.ondragleave = ondragleave;
106 + document.onkeypress = onkeypress;
107 + Q('PlaySpeed').value = 1;
108 + cleanup();
109 + }
110 +
111 + function readNextBlock(func) {
112 + if ((recFilePtr + 16) > recFile.size) { QS('progressbar').width = '100%'; func(-1); } else {
113 + var fr = new FileReader();
114 + fr.onload = function () {
115 + var type = ReadShort(this.result, 0);
116 + var flags = ReadShort(this.result, 2);
117 + var size = ReadInt(this.result, 4);
118 + var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
119 + if ((recFilePtr + 16 + size) > recFile.size) { QS('progressbar').width = '100%'; func(-1); } else {
120 + var fr2 = new FileReader();
121 + fr2.onload = function () {
122 + recFilePtr += (16 + size);
123 + if (recFileEndTime == 0) {
124 + // File pointer progress bar
125 + QS('progressbar').width = Math.floor(100 * (recFilePtr / recFile.size)) + '%';
126 + } else {
127 + // Time progress bar
128 + QS('progressbar').width = Math.floor(((recFileLastTime - recFileStartTime) / (recFileEndTime - recFileStartTime)) * 100) + '%';
129 + }
130 + func(type, flags, time, this.result);
131 + };
132 + fr2.readAsBinaryString(recFile.slice(recFilePtr + 16, recFilePtr + 16 + size));
133 + }
134 + };
135 + fr.readAsBinaryString(recFile.slice(recFilePtr, recFilePtr + 16));
136 + }
137 + }
138 +
139 + function readLastBlock(func) {
140 + if (recFile.size < 32) { func(-1); } else {
141 + var fr = new FileReader();
142 + fr.onload = function () {
143 + var type = ReadShort(this.result, 0);
144 + var flags = ReadShort(this.result, 2);
145 + var size = ReadInt(this.result, 4);
146 + var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
147 + if ((type == 3) && (size == 16) && (this.result.substring(16, 32) == 'MeshCentralMCREC')) { func(type, flags, time); } else { func(-1); }
148 + };
149 + fr.readAsBinaryString(recFile.slice(recFile.size - 32, recFile.size));
150 + }
151 + }
152 +
153 + function addInfo(name, value) { if (value == null) return ''; return addInfoNoEsc(name, EscapeHtml(value)); }
154 +
155 + function addInfoNoEsc(name, value) {
156 + if (value == null) return '';
157 + return '<span style=color:gray>' + EscapeHtml(name) + '</span>:&nbsp;<span style=font-size:20px>' + value + '</span><br/>';
158 + }
159 +
160 + function processFirstBlock(type, flags, time, data) {
161 + recFileProtocol = 0;
162 + if ((type != 1) || (flags != 0)) { cleanup(); return; }
163 + try { recFileMetadata = JSON.parse(data) } catch (ex) { cleanup(); return; }
164 + if ((recFileMetadata == null) || (recFileMetadata.magic != 'MeshCentralRelaySession') || (recFileMetadata.ver != 1)) { cleanup(); return; }
165 + var x = '';
166 + x += addInfo("Tempo", recFileMetadata.time);
167 + if (recFileEndTime != 0) { var secs = Math.floor((recFileEndTime - time) / 1000); x += addInfo("Duração", format("{0} segundo{1}", secs, (secs > 1) ? 's' : '')); }
168 + x += addInfo("Nome de usuário", recFileMetadata.username);
169 + x += addInfo("ID do usuário", recFileMetadata.userid);
170 + x += addInfo("ID da sessão", recFileMetadata.sessionid);
171 + if (recFileMetadata.ipaddr1 && recFileMetadata.ipaddr2) { x += addInfo("Endereços", format("{0} para {1}", recFileMetadata.ipaddr1, recFileMetadata.ipaddr2)); }
172 + if (recFileMetadata.devicename) { x += addInfo("Nome do Dispositivo", recFileMetadata.devicename); }
173 + x += addInfo("NodeID", recFileMetadata.nodeid);
174 + if (recFileMetadata.protocol) {
175 + var p = recFileMetadata.protocol;
176 + if (p == 1) { p = "MeshCentral Terminal"; }
177 + else if (p == 2) { p = "MeshCentral Desktop"; }
178 + else if (p == 100) { p = "Intel&reg; AMT WSMAN"; }
179 + else if (p == 101) { p = "Intel&reg; Redirecionamento AMT"; }
180 + x += addInfoNoEsc("Protocolo", p);
181 + }
182 + QV('DeskParent', true);
183 + QV('TermParent', false);
184 + if (recFileMetadata.protocol == 1) {
185 + // MeshCentral remote terminal
186 + recFileProtocol = 1;
187 + x += '<br /><br /><span style=color:gray>' + "Pressione [espaço] para reproduzir / pausar." + '</span>';
188 + QE('PlayButton', true);
189 + QE('PauseButton', false);
190 + QE('RestartButton', false);
191 + recFileStartTime = recFileLastTime = time;
192 + }
193 + else if (recFileMetadata.protocol == 2) {
194 + // MeshCentral remote desktop
195 + recFileProtocol = 2;
196 + x += '<br /><br /><span style=color:gray>' + "Pressione [espaço] para reproduzir / pausar." + '</span>';
197 + QE('PlayButton', true);
198 + QE('PauseButton', false);
199 + QE('RestartButton', false);
200 + recFileStartTime = recFileLastTime = time;
201 + agentDesktop = CreateAgentRemoteDesktop('Desk');
202 + agentDesktop.onScreenSizeChange = deskAdjust;
203 + agentDesktop.State = 3;
204 + deskAdjust();
205 + }
206 + else if (recFileMetadata.protocol == 101) {
207 + // Intel AMT Redirection
208 + recFileProtocol = 101;
209 + x += '<br /><br /><span style=color:gray>Press [space] to play/pause.</span>';
210 + QE('PlayButton', true);
211 + QE('PauseButton', false);
212 + QE('RestartButton', false);
213 + recFileStartTime = recFileLastTime = time;
214 + amtDesktop = CreateAmtRemoteDesktop('Desk');
215 + amtDesktop.onScreenSizeChange = deskAdjust;
216 + amtDesktop.State = 3;
217 + amtDesktop.Start();
218 + deskAdjust();
219 + }
220 + QV('metadatadiv', true);
221 + QH('metadatadiv', x);
222 + QH('deskstatus', recFile.name);
223 + }
224 +
225 + function processBlock(type, flags, time, data) {
226 + if (type < 0) { pause(); return; }
227 + var waitTime = Math.round((time - recFileLastTime) * parseFloat(Q('PlaySpeed').value));
228 + if (waitTime < 5) {
229 + processBlockEx(type, flags, time, data);
230 + } else {
231 + waitTimerArgs = [type, flags, time, data]
232 + waitTimer = setTimeout(function () { waitTimer = null; processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]); }, waitTime);
233 + }
234 + }
235 +
236 + function processBlockEx(type, flags, time, data) {
237 + if (playing == false) return;
238 + var flagBinary = (flags & 1) != 0, flagUser = (flags & 2) != 0;
239 +
240 + // Update the clock
241 + var deltaTimeTotalSec = Math.floor((time - recFileStartTime) / 1000);
242 + if (currentDeltaTimeTotalSec != deltaTimeTotalSec) {
243 + currentDeltaTimeTotalSec = deltaTimeTotalSec;
244 + var deltaTimeHours = Math.floor(deltaTimeTotalSec / 3600);
245 + deltaTimeTotalSec -= (deltaTimeHours * 3600)
246 + var deltaTimeMinutes = Math.floor(deltaTimeTotalSec / 60);
247 + deltaTimeTotalSec -= (deltaTimeHours * 60)
248 + var deltaTimeSeconds = Math.floor(deltaTimeTotalSec);
249 + QH('timespan', pad2(deltaTimeHours) + ':' + pad2(deltaTimeMinutes) + ':' + pad2(deltaTimeSeconds))
250 + }
251 +
252 + if ((type == 2) && flagBinary && !flagUser) {
253 + // Device --> User data
254 + if (recFileProtocol == 1) {
255 + // MeshCentral Terminal
256 + agentTerminal.ProcessData(data);
257 + } else if (recFileProtocol == 2) {
258 + // MeshCentral Remote Desktop
259 + agentDesktop.ProcessData(data);
260 + } else if (recFileProtocol == 101) {
261 + // Intel AMT KVM
262 + if ((readState == 0) && (rstr2hex(data) == '4100000000000000')) {
263 + // We are not authenticated, KVM data starts here.
264 + readState = 1;
265 + if (data.length > 8) { amtDesktop.ProcessData(data.substring(8)); }
266 + } else if (readState == 1) {
267 + amtDesktop.ProcessData(data);
268 + }
269 + }
270 + } else if ((type == 2) && flagBinary && flagUser) {
271 + // User --> Device data
272 + if (recFileProtocol == 101) {
273 + // Intel AMT KVM
274 + if (rstr2hex(data) == '0000000008080001000700070003050200000000') { amtDesktop.bpp = 1; } // Switch to 1 byte per pixel.
275 + }
276 + }
277 +
278 + recFileLastTime = time;
279 + if (playing) { readNextBlock(processBlock); }
280 + }
281 +
282 + function cleanup() {
283 + recFile = null;
284 + recFilePtr = 0;
285 + recFileMetadata = null;
286 + playing = false;
287 + if (agentDesktop != null) { agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height); agentDesktop = null; }
288 + if (amtDesktop != null) { amtDesktop.canvas.clearRect(0, 0, amtDesktop.CanvasId.width, amtDesktop.CanvasId.height); amtDesktop = null; }
289 + readState = 0;
290 + waitTimerArgs = null;
291 + currentDeltaTimeTotalSec = 0;
292 + recFileEndTime = 0;
293 + agentTerminal = null;
294 + if (waitTimer != null) { clearTimeout(waitTimer); waitTimer = null; }
295 + QH('deskstatus', '');
296 + QE('PlayButton', false);
297 + QE('PauseButton', false);
298 + QE('RestartButton', false);
299 + QS('progressbar').width = '0px';
300 + QH('timespan', '00:00:00');
301 + QV('metadatadiv', true);
302 + 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>');
303 + QV('DeskParent', true);
304 + QV('TermParent', false);
305 + }
306 +
307 + function ondrop(e) {
308 + haltEvent(e);
309 + QV('bigfail', false);
310 + QV('bigok', false);
311 +
312 + // Check if these are files we can upload, remove all folders.
313 + if (e.dataTransfer == null) return;
314 + var files = [];
315 + for (var i in e.dataTransfer.files) {
316 + 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'))) {
317 + files.push(e.dataTransfer.files[i]);
318 + }
319 + }
320 + if (files.length == 0) return;
321 + cleanup();
322 + recFile = files[0];
323 + recFilePtr = 0;
324 + readNextBlock(processFirstBlock);
325 + readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
326 + }
327 +
328 + var dragtimer = null;
329 + function ondragover(e) {
330 + haltEvent(e);
331 + if (dragtimer != null) { clearTimeout(dragtimer); dragtimer = null; }
332 + var ac = true;
333 + QV('bigok', ac);
334 + QV('bigfail', !ac);
335 + }
336 +
337 + function ondragleave(e) {
338 + haltEvent(e);
339 + dragtimer = setTimeout(function () { QV('bigfail', false); QV('bigok', false); dragtimer = null; }, 10);
340 + }
341 +
342 + function onkeypress(e) {
343 + if (xxdialogMode) return;
344 + if (e.key == ' ') { togglePause(); haltEvent(e); }
345 + if (e.key == '1') { Q('PlaySpeed').value = 4; haltEvent(e); }
346 + if (e.key == '2') { Q('PlaySpeed').value = 2; haltEvent(e); }
347 + if (e.key == '3') { Q('PlaySpeed').value = 1; haltEvent(e); }
348 + if (e.key == '4') { Q('PlaySpeed').value = 0.5; haltEvent(e); }
349 + if (e.key == '5') { Q('PlaySpeed').value = 0.25; haltEvent(e); }
350 + if (e.key == '6') { Q('PlaySpeed').value = 0.1; haltEvent(e); }
351 + if (e.key == '0') { pause(); restart(); haltEvent(e); }
352 + }
353 +
354 + function openfile() {
355 + var x = '<input type=file name=files id=p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />';
356 + setDialogMode(2, "Abrir arquivo...", 3, openfileEx, x);
357 + QE('idx_dlgOkButton', false);
358 + }
359 +
360 + function openfileEx() {
361 + var xfiles = Q('p2fileinput').files;
362 + 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]); } } }
363 + if (files.length == 0) return;
364 + cleanup();
365 + recFile = files[0];
366 + recFilePtr = 0;
367 + readNextBlock(processFirstBlock);
368 + readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
369 + Q('OpenFileButton').blur();
370 + }
371 +
372 + function openfileChanged() {
373 + var xfiles = Q('p2fileinput').files;
374 + 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]); } } }
375 + QE('idx_dlgOkButton', files.length == 1);
376 + }
377 +
378 + function togglePause() {
379 + if (recFile != null) { if (playing == true) { pause(); } else { if (recFilePtr != recFile.size) { play(); } } } return false;
380 + }
381 +
382 + function play() {
383 + Q('PlayButton').blur();
384 + if ((playing == true) || (recFileProtocol == 0)) return;
385 + playing = true;
386 + QV('metadatadiv', false);
387 + QE('PlayButton', false);
388 + QE('PauseButton', true);
389 + QE('RestartButton', false);
390 + if ((recFileProtocol == 1) && (agentTerminal == null)) {
391 + QV('DeskParent', false);
392 + QV('TermParent', true);
393 + agentTerminal = CreateAmtRemoteTerminal('Term', {});
394 + agentTerminal.State = 3;
395 + }
396 + readNextBlock(processBlock);
397 + }
398 +
399 + function pause() {
400 + Q('PauseButton').blur();
401 + if (playing == false) return;
402 + playing = false;
403 + QE('PlayButton', recFilePtr != recFile.size);
404 + QE('PauseButton', false);
405 + QE('RestartButton', recFilePtr != 0);
406 + if (waitTimer != null) {
407 + clearTimeout(waitTimer);
408 + waitTimer = null;
409 + processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]);
410 + waitTimerArgs = null;
411 + }
412 + }
413 +
414 + function restart() {
415 + Q('RestartButton').blur();
416 + if (playing == true) return;
417 + recFilePtr = 0;
418 + readState = 0;
419 + currentDeltaTimeTotalSec = 0;
420 + QV('metadatadiv', true);
421 + QE('PlayButton', true);
422 + QE('PauseButton', false);
423 + QE('RestartButton', false);
424 + QS('progressbar').width = '0px';
425 + QH('timespan', '00:00:00');
426 + QV('DeskParent', true);
427 + QV('TermParent', false);
428 + if (agentDesktop) {
429 + agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height);
430 + } else if (amtDesktop) {
431 + amtDesktop.canvas.clearRect(0, 0, amtDesktop.CanvasId.width, amtDesktop.CanvasId.height);
432 + amtDesktop = CreateAmtRemoteDesktop('Desk');
433 + amtDesktop.onScreenSizeChange = deskAdjust;
434 + amtDesktop.State = 3;
435 + amtDesktop.Start();
436 + } else if (agentTerminal) {
437 + agentTerminal = null;
438 + }
439 + }
440 +
441 + function clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); }
442 +
443 + // Toggle the web page to full screen
444 + function toggleAspectRatio(toggle) {
445 + if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); }
446 + deskAdjust();
447 + }
448 +
449 + function deskAdjust() {
450 + var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
451 + var deskH = Q('Desk').height, deskW = Q('Desk').width;
452 +
453 + if (deskAspectRatio == 2) {
454 + // Scale mode
455 + QS('Desk')['margin-top'] = null;
456 + QS('Desk').height = '100%';
457 + QS('Desk').width = '100%';
458 + QS('DeskParent').overflow = 'hidden';
459 + } else if (deskAspectRatio == 1) {
460 + // Zoomed mode
461 + QS('Desk')['margin-top'] = '0px';
462 + //QS('Desk')['margin-left'] = '0px';
463 + QS('Desk').height = deskH + 'px';
464 + QS('Desk').width = deskW + 'px';
465 + QS('DeskParent').overflow = 'scroll';
466 + } else {
467 + // Fixed aspect ratio
468 + if ((parentH / parentW) > (deskH / deskW)) {
469 + var hNew = ((deskH * parentW) / deskW) + 'px';
470 + //if (webPageFullScreen || fullscreen) {
471 + //QS('deskarea3x').height = null;
472 + //} else {
473 + // QS('deskarea3x').height = hNew;
474 + //QS('deskarea3x').height = null;
475 + //}
476 + QS('Desk').height = hNew;
477 + QS('Desk').width = '100%';
478 + } else {
479 + var wNew = ((deskW * parentH) / deskH) + 'px';
480 + //if (webPageFullScreen || fullscreen) {
481 + //QS('Desk').height = null;
482 + //} else {
483 + QS('Desk').height = '100%';
484 + //}
485 + QS('Desk').width = wNew;
486 + }
487 + QS('Desk')['margin-top'] = null;
488 + QS('DeskParent').overflow = 'hidden';
489 + }
490 + }
491 +
492 + //
493 + // POPUP DIALOG
494 + //
495 +
496 + // null = Hidden, 1 = Generic Message
497 + var xxdialogMode;
498 + var xxdialogFunc;
499 + var xxdialogButtons;
500 + var xxdialogTag;
501 + var xxcurrentView = -1;
502 +
503 + // Display a dialog box
504 + // 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)
505 + function setDialogMode(x, y, b, f, c, tag) {
506 + xxdialogMode = x;
507 + xxdialogFunc = f;
508 + xxdialogButtons = b;
509 + xxdialogTag = tag;
510 + QE('idx_dlgOkButton', true);
511 + QV('idx_dlgOkButton', b & 1);
512 + QV('idx_dlgCancelButton', b & 2);
513 + QV('id_dialogclose', (b & 2) || (b & 8));
514 + QV('idx_dlgDeleteButton', b & 4);
515 + QV('idx_dlgButtonBar', b & 7);
516 + if (y) QH('id_dialogtitle', y);
517 + for (var i = 1; i < 3; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
518 + QV('dialog', x);
519 + if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
520 + }
521 +
522 + function dialogclose(x) {
523 + var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag;
524 + setDialogMode();
525 + if (((b & 8) || x) && f) f(x, t);
526 + }
527 +
528 + function messagebox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
529 + function statusbox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t); }
530 + function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
531 + function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }
532 + 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; }); };
533 +
534 + start();
535 + </script>
536 +
537 +</body></html>
\ No newline at end of file
translate/translate.js
+49 -1
@@ -53,7 +53,7 @@ function start() {
53
54 var command = null;
55 if (process.argv.length > 2) { command = process.argv[2].toLowerCase(); }
56 - if (['check', 'extract', 'extractall', 'translate', 'translateall', 'minifyall'].indexOf(command) == -1) { command = null; }
56 + if (['check', 'extract', 'extractall', 'translate', 'translateall', 'minifyall', 'merge'].indexOf(command) == -1) { command = null; }
57
58 console.log('MeshCentral web site translator');
59 if (command == null) {
@@ -77,6 +77,9 @@ function start() {
77 console.log('');
78 console.log(' MINIFYALL');
79 console.log(' Minify the main MeshCentral english web pages.');
80 + console.log('');
81 + console.log(' MERGE [sourcefile] [tartgetfile] [language code]');
82 + console.log(' Merge a language from a translation file into another translation file.');
83 process.exit();
84 return;
85 }
@@ -105,6 +108,18 @@ function start() {
108 extract(process.argv[3], sources);
109 }
110
111 + // Merge one language from a language file into another language file.
112 + if (command == 'merge') {
113 + if ((process.argv.length == 6)) {
114 + if (fs.existsSync(process.argv[3]) == false) { console.log('Unable to find: ' + process.argv[3]); return; }
115 + if (fs.existsSync(process.argv[4]) == false) { console.log('Unable to find: ' + process.argv[4]); return; }
116 + merge(process.argv[3], process.argv[4], process.argv[5]);
117 + } else {
118 + console.log('Usage: MERGE [sourcefile] [tartgetfile] [language code]');
119 + }
120 + return;
121 + }
122 +
123 // Extract or translate all MeshCentral strings
124 if (command == 'extractall') { extract("translate.json", meshCentralSourceFiles); }
125 if (command == 'translateall') {
@@ -180,6 +195,39 @@ function start() {
195 }
196 }
197
198 +function merge(source, target, lang) {
199 + // Load the source language file
200 + var sourceLangFileData = null;
201 + try { sourceLangFileData = JSON.parse(fs.readFileSync(source)); } catch (ex) { }
202 + if ((sourceLangFileData == null) || (sourceLangFileData.strings == null)) { console.log("Invalid source language file."); process.exit(); return; }
203 +
204 + // Load the target language file
205 + var targetLangFileData = null;
206 + try { targetLangFileData = JSON.parse(fs.readFileSync(target)); } catch (ex) { }
207 + if ((targetLangFileData == null) || (targetLangFileData.strings == null)) { console.log("Invalid target language file."); process.exit(); return; }
208 +
209 + console.log('Merging ' + lang + '...');
210 +
211 + // Index the target file
212 + var index = {};
213 + for (var i in targetLangFileData.strings) { if (targetLangFileData.strings[i].en != null) { index[targetLangFileData.strings[i].en] = targetLangFileData.strings[i]; } }
214 +
215 + // Merge the translation
216 + for (var i in sourceLangFileData.strings) {
217 + if ((sourceLangFileData.strings[i].en != null) && (sourceLangFileData.strings[i][lang] != null) && (index[sourceLangFileData.strings[i].en] != null)) {
218 + index[sourceLangFileData.strings[i].en][lang] = sourceLangFileData.strings[i][lang];
219 + }
220 + }
221 +
222 + // Deindex the new target file
223 + var targetData = { strings: [] };
224 + for (var i in index) { targetData.strings.push(index[i]); }
225 +
226 + // Save the target back
227 + fs.writeFileSync(target, JSON.stringify(targetData, null, ' '), { flag: 'w+' });
228 + console.log('Done.');
229 +}
230 +
231 function translate(lang, langFile, sources, createSubDir) {
232 // Load the language file
233 var langFileData = null;
translate/translate.json
+2684 -1342
@@ -5,20 +5,23 @@
5 "xloc": [
6 "default.handlebars->container->masthead->5->notificationCount",
7 "default-mobile.handlebars->9->229"
8 - ]
8 + ],
9 + "pt": "0"
10 },
11 {
12 "en": "3",
13 "xloc": [
14 "default-mobile.handlebars->9->266"
14 - ]
15 + ],
16 + "pt": "3"
17 },
18 {
19 "en": "404",
20 "xloc": [
21 "error404.handlebars->container->column_l->1->0",
22 "error404-mobile.handlebars->container->page_content->column_l->1->0"
21 - ]
23 + ],
24 + "pt": "404"
25 },
26 {
27 "en": " + CIRA",
@@ -26,7 +29,8 @@
29 "xloc": [
30 "default.handlebars->23->965",
31 "default.handlebars->23->967"
29 - ]
32 + ],
33 + "pt": "+ CIRA"
34 },
35 {
36 "en": " - Reset in {0} day{1}.",
@@ -35,7 +39,8 @@
39 "xloc": [
40 "default.handlebars->23->24",
41 "default-mobile.handlebars->9->13"
38 - ]
42 + ],
43 + "pt": "- Redefinir em {0} dia {1}."
44 },
45 {
46 "en": " - Reset in {0} hour{1}.",
@@ -44,7 +49,8 @@
49 "xloc": [
50 "default.handlebars->23->23",
51 "default-mobile.handlebars->9->12"
47 - ]
52 + ],
53 + "pt": "- Redefinir em {0} hora {1}."
54 },
55 {
56 "en": " - Reset in {0} minute{1}.",
@@ -53,7 +59,8 @@
59 "xloc": [
60 "default.handlebars->23->22",
61 "default-mobile.handlebars->9->11"
56 - ]
62 + ],
63 + "pt": "- Redefinir em {0} minuto {1}."
64 },
65 {
66 "en": " - Reset on next login.",
@@ -64,13 +71,15 @@
71 "default.handlebars->23->21",
72 "default-mobile.handlebars->9->9",
73 "default-mobile.handlebars->9->10"
67 - ]
74 + ],
75 + "pt": "- Redefinir no próximo login."
76 },
77 {
78 "en": " / ",
79 "xloc": [
80 "default-mobile.handlebars->9->91"
73 - ]
81 + ],
82 + "pt": " / "
83 },
84 {
85 "en": " Add User",
@@ -78,7 +87,8 @@
87 "fr": "Ajouter un utilisateur",
88 "xloc": [
89 "default-mobile.handlebars->9->277"
81 - ]
90 + ],
91 + "pt": "Adicionar usuário"
92 },
93 {
94 "en": " and authenticate to the server using this username and any password.",
@@ -86,7 +96,8 @@
96 "fr": "et vous authentifier sur le serveur en utilisant ce nom d'utilisateur et n'importe quel mot de passe.",
97 "xloc": [
98 "default.handlebars->23->231"
89 - ]
99 + ],
100 + "pt": "e autenticar no servidor usando esse nome de usuário e qualquer senha."
101 },
102 {
103 "en": " and authenticate to the server using this username and password.",
@@ -94,7 +105,8 @@
105 "fr": "et authentifiez-vous sur le serveur en utilisant ce nom d'utilisateur et mot de passe.",
106 "xloc": [
107 "default.handlebars->23->230"
97 - ]
108 + ],
109 + "pt": "e autenticar no servidor usando esse nome de usuário e senha."
110 },
111 {
112 "en": " node",
@@ -102,7 +114,8 @@
114 "fr": "nœud",
115 "xloc": [
116 "default-mobile.handlebars->9->124"
105 - ]
117 + ],
118 + "pt": "nó"
119 },
120 {
121 "en": " nodes",
@@ -110,7 +123,8 @@
123 "fr": "noeuds",
124 "xloc": [
125 "default-mobile.handlebars->9->125"
113 - ]
126 + ],
127 + "pt": "nós"
128 },
129 {
130 "en": " Password hint can be used but is not recommanded.",
@@ -118,7 +132,8 @@
132 "fr": "Un indice de mot de passe peut être utilisé mais n'est pas recommandé.",
133 "xloc": [
134 "default.handlebars->23->897"
121 - ]
135 + ],
136 + "pt": "Dica de senha pode ser usada, mas não é recomendada."
137 },
138 {
139 "en": " Users need to login to this server once before they can be added to a device group.",
@@ -126,7 +141,8 @@
141 "fr": "Les utilisateurs doivent se connecter une fois sur ce serveur avant de pouvoir être ajoutés à un groupe de périphériques..",
142 "xloc": [
143 "default.handlebars->23->1037"
129 - ]
144 + ],
145 + "pt": "Os usuários precisam fazer login neste servidor uma vez antes de poderem ser adicionados a um grupo de dispositivos."
146 },
147 {
148 "en": " with TLS.",
@@ -134,7 +150,8 @@
150 "fr": "avec TLS.",
151 "xloc": [
152 "default.handlebars->23->128"
137 - ]
153 + ],
154 + "pt": "com TLS."
155 },
156 {
157 "en": " without TLS.",
@@ -142,56 +159,64 @@
159 "fr": "sans TLS.",
160 "xloc": [
161 "default.handlebars->23->129"
145 - ]
162 + ],
163 + "pt": "sem TLS."
164 },
165 {
166 "en": "(",
167 "xloc": [
168 "default.handlebars->container->column_l->p2->p2createMeshLink1",
169 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3createMeshLink1"
152 - ]
170 + ],
171 + "pt": "("
172 },
173 {
174 "en": "(optional)",
175 "cs": "(volitelné)",
176 "xloc": [
177 "default.handlebars->23->267"
159 - ]
178 + ],
179 + "pt": "(opcional)"
180 },
181 {
182 "en": ")",
183 "xloc": [
184 "default.handlebars->container->column_l->p2->p2createMeshLink1",
185 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3createMeshLink1"
166 - ]
186 + ],
187 + "pt": ")"
188 },
189 {
190 "en": "* For BSD, run \\\"pkg install wget sudo bash\\\" first.",
191 "cs": "* Pro BSD, spusť \\\"pkg install wget sudo bash\\\" nejprve.",
192 "xloc": [
193 "default.handlebars->23->298"
173 - ]
194 + ],
195 + "pt": "* Para o BSD, execute \\\"pkg install wget sudo bash\\\"."
196 },
197 {
198 "en": "* Leave blank to assign a random password to each device.",
199 "cs": "* Ponechat prázdné pro vygenerování náhodného hesla každému zařízení.",
200 "xloc": [
201 "default.handlebars->23->1014"
180 - ]
202 + ],
203 + "pt": "* Deixe em branco para atribuir uma senha aleatória a cada dispositivo."
204 },
205 {
206 "en": ",",
207 "xloc": [
208 "default.handlebars->container->column_l->p0->p0message",
209 "default-mobile.handlebars->container->page_content->column_l->p0->1->p0message"
187 - ]
210 + ],
211 + "pt": ","
212 },
213 {
214 "en": ", ",
215 "xloc": [
216 "default.handlebars->23->1080",
217 "default-mobile.handlebars->9->327"
194 - ]
218 + ],
219 + "pt": ","
220 },
221 {
222 "en": ", click here to enable it.",
@@ -199,7 +224,8 @@
224 "xloc": [
225 "default.handlebars->container->column_l->p11->p11warning->3->p11warninga",
226 "default.handlebars->container->column_l->p12->p12warning->3->p12warninga"
202 - ]
227 + ],
228 + "pt": ", clique aqui para habilitá-lo."
229 },
230 {
231 "en": ", Intel&reg; AMT only",
@@ -207,21 +233,24 @@
233 "xloc": [
234 "default.handlebars->23->145",
235 "default-mobile.handlebars->9->89"
210 - ]
236 + ],
237 + "pt": "Intelreg; "
238 },
239 {
240 "en": ", MQTT is online",
241 "cs": ", MQTT je online",
242 "xloc": [
243 "default.handlebars->23->651"
217 - ]
244 + ],
245 + "pt": ", O MQTT está online"
246 },
247 {
248 "en": ", right click on it or press \"control\" and click on the file. Then select \"Open\" and follow the instructions.",
249 "cs": ", poté spusťe instalaci. Postupujte dle instrukcí.",
250 "xloc": [
251 "agentinvite.handlebars->container->column_l->5->macostab->3"
224 - ]
252 + ],
253 + "pt": ", clique com o botão direito do mouse ou pressione \"control\".Em seguida, selecione \"Open\"."
254 },
255 {
256 "en": ", run it and press \"Install\" or \"Connect\".",
@@ -229,13 +258,15 @@
258 "xloc": [
259 "agentinvite.handlebars->container->column_l->5->wintab64->3",
260 "agentinvite.handlebars->container->column_l->5->wintab32->3"
232 - ]
261 + ],
262 + "pt": ", execute-o e pressione \"Install\" or \"Connect\"."
263 },
264 {
265 "en": ", Soft-KVM",
266 "xloc": [
267 "default.handlebars->23->569"
238 - ]
268 + ],
269 + "pt": ", Soft-KVM"
270 },
271 {
272 "en": ", WebRTC",
@@ -245,13 +276,15 @@
276 "default.handlebars->23->613",
277 "default-mobile.handlebars->9->225",
278 "default-mobile.handlebars->9->235"
248 - ]
279 + ],
280 + "pt": ", WebRTC"
281 },
282 {
283 "en": "-",
284 "xloc": [
285 "default-mobile.handlebars->9->228"
254 - ]
286 + ],
287 + "pt": "-"
288 },
289 {
290 "en": ".",
@@ -265,7 +298,8 @@
298 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->newAccountDiv",
299 "terms.handlebars->container->column_l->75->1",
300 "terms-mobile.handlebars->container->page_content->column_l->75->1"
268 - ]
301 + ],
302 + "pt": "."
303 },
304 {
305 "en": "...",
@@ -275,13 +309,15 @@
309 "default.handlebars->23->1244",
310 "default-mobile.handlebars->9->64",
311 "default-mobile.handlebars->9->240"
278 - ]
312 + ],
313 + "pt": "..."
314 },
315 {
316 "en": "00:00:00",
317 "xloc": [
318 "player.htm->p11->deskarea0->deskarea4->1->timespan"
284 - ]
319 + ],
320 + "pt": "00:00:00"
321 },
322 {
323 "en": "1 active session",
@@ -289,7 +325,8 @@
325 "fr": "1 session active",
326 "xloc": [
327 "default.handlebars->23->1230"
292 - ]
328 + ],
329 + "pt": "1 sessão ativa"
330 },
331 {
332 "en": "1 byte",
@@ -299,7 +336,8 @@
336 "default.handlebars->23->1103",
337 "default-mobile.handlebars->9->74",
338 "default-mobile.handlebars->9->331"
302 - ]
339 + ],
340 + "pt": "1 byte"
341 },
342 {
343 "en": "1 day",
@@ -309,7 +347,8 @@
347 "default.handlebars->23->132",
348 "default.handlebars->23->258",
349 "default.handlebars->23->272"
312 - ]
350 + ],
351 + "pt": "1 dia"
352 },
353 {
354 "en": "1 group",
@@ -317,7 +356,8 @@
356 "fr": "1 groupe",
357 "xloc": [
358 "default.handlebars->23->1216"
320 - ]
359 + ],
360 + "pt": "1 grupo"
361 },
362 {
363 "en": "1 hour",
@@ -326,7 +366,8 @@
366 "xloc": [
367 "default.handlebars->23->256",
368 "default.handlebars->23->270"
329 - ]
369 + ],
370 + "pt": "1 hora"
371 },
372 {
373 "en": "1 month",
@@ -336,14 +377,16 @@
377 "default.handlebars->23->134",
378 "default.handlebars->23->260",
379 "default.handlebars->23->274"
339 - ]
380 + ],
381 + "pt": "1 mês"
382 },
383 {
384 "en": "1 more user not shown, use search box to look for users...",
385 "cs": "1 další uživatel není zobrazen, pomocí vyhledávacího pole vyhledejte uživatele ...",
386 "xloc": [
387 "default.handlebars->23->1136"
346 - ]
388 + ],
389 + "pt": "Mais 1 usuário não mostrado, use a caixa de pesquisa para procurar usuários..."
390 },
391 {
392 "en": "1 node",
@@ -351,7 +394,8 @@
394 "fr": "1 appareil",
395 "xloc": [
396 "default.handlebars->23->311"
354 - ]
397 + ],
398 + "pt": "1 nó"
399 },
400 {
401 "en": "1 session",
@@ -359,7 +403,8 @@
403 "fr": "1 session",
404 "xloc": [
405 "default.handlebars->23->1140"
362 - ]
406 + ],
407 + "pt": "1 sessão"
408 },
409 {
410 "en": "1 week",
@@ -369,7 +414,8 @@
414 "default.handlebars->23->133",
415 "default.handlebars->23->259",
416 "default.handlebars->23->273"
372 - ]
417 + ],
418 + "pt": "1 semana"
419 },
420 {
421 "en": "1.AJAX Control Toolkit - New BSD License",
@@ -377,7 +423,8 @@
423 "xloc": [
424 "terms.handlebars->container->column_l->9->1->0",
425 "terms-mobile.handlebars->container->page_content->column_l->9->1->0"
380 - ]
426 + ],
427 + "pt": "1.AJAX Control Toolkit - Nova licença BSD"
428 },
429 {
430 "en": "1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.",
@@ -387,7 +434,8 @@
434 "terms.handlebars->container->column_l->31->1",
435 "terms-mobile.handlebars->container->page_content->column_l->15->1",
436 "terms-mobile.handlebars->container->page_content->column_l->31->1"
390 - ]
437 + ],
438 + "pt": "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."
439 },
440 {
441 "en": "1/2 Speed",
@@ -395,7 +443,8 @@
443 "fr": "1/2 vitesse",
444 "xloc": [
445 "player.htm->p11->deskarea0->deskarea4->3->PlaySpeed->3"
398 - ]
446 + ],
447 + "pt": "1/2 velocidade"
448 },
449 {
450 "en": "1/4 Speed",
@@ -403,20 +452,23 @@
452 "fr": "1/4 vitesse",
453 "xloc": [
454 "player.htm->p11->deskarea0->deskarea4->3->PlaySpeed->1"
406 - ]
455 + ],
456 + "pt": "1/4 de velocidade"
457 },
458 {
459 "en": "100%",
460 "xloc": [
461 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1",
462 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->1"
413 - ]
463 + ],
464 + "pt": "100%"
465 },
466 {
467 "en": "100x30",
468 "xloc": [
469 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->1"
419 - ]
470 + ],
471 + "pt": "100x30"
472 },
473 {
474 "en": "10x Speed",
@@ -424,28 +476,32 @@
476 "fr": "10x vitesse",
477 "xloc": [
478 "player.htm->p11->deskarea0->deskarea4->3->PlaySpeed->11"
427 - ]
479 + ],
480 + "pt": "10x Velocidade"
481 },
482 {
483 "en": "12.5%",
484 "xloc": [
485 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15",
486 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->15"
434 - ]
487 + ],
488 + "pt": "12.5%"
489 },
490 {
491 "en": "2-step login activation failed.",
492 "cs": "aktivace 2-faktorového přihlašování selhalo.",
493 "xloc": [
494 "default.handlebars->23->89"
441 - ]
495 + ],
496 + "pt": "Falha na ativação do login em duas etapas."
497 },
498 {
499 "en": "2-step login activation removal failed.",
500 "cs": "odstranění 2-faktorového přihlašování selhalo.",
501 "xloc": [
502 "default.handlebars->23->94"
448 - ]
503 + ],
504 + "pt": "A remoção da ativação do login em duas etapas falhou."
505 },
506 {
507 "en": "2.OpenSSL – OpenSSL and SSLeay License",
@@ -453,7 +509,8 @@
509 "xloc": [
510 "terms.handlebars->container->column_l->23->1->0",
511 "terms-mobile.handlebars->container->page_content->column_l->23->1->0"
456 - ]
512 + ],
513 + "pt": "2.OpenSSL - Licença OpenSSL e SSLeay"
514 },
515 {
516 "en": "2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.",
@@ -463,14 +520,16 @@
520 "terms.handlebars->container->column_l->33->1",
521 "terms-mobile.handlebars->container->page_content->column_l->17->1",
522 "terms-mobile.handlebars->container->page_content->column_l->33->1"
466 - ]
523 + ],
524 + "pt": "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."
525 },
526 {
527 "en": "25%",
528 "xloc": [
529 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13",
530 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->13"
473 - ]
531 + ],
532 + "pt": "25%"
533 },
534 {
535 "en": "2x Speed",
@@ -478,7 +537,8 @@
537 "fr": "2x vitesse",
538 "xloc": [
539 "player.htm->p11->deskarea0->deskarea4->3->PlaySpeed->7"
481 - ]
540 + ],
541 + "pt": "2x velocidade"
542 },
543 {
544 "en": "3.All advertising materials mentioning features or use of this software must display the following acknowledgment: \"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"",
@@ -486,7 +546,8 @@
546 "xloc": [
547 "terms.handlebars->container->column_l->35->1",
548 "terms-mobile.handlebars->container->page_content->column_l->35->1"
489 - ]
549 + ],
550 + "pt": "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/)\""
551 },
552 {
553 "en": "3.jQuery Foundation - MIT License",
@@ -494,7 +555,8 @@
555 "xloc": [
556 "terms.handlebars->container->column_l->45->1->0",
557 "terms-mobile.handlebars->container->page_content->column_l->45->1->0"
497 - ]
558 + ],
559 + "pt": "3.jQuery Foundation - Licença MIT"
560 },
561 {
562 "en": "3.Neither the name of CodePlex Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.",
@@ -502,7 +564,8 @@
564 "xloc": [
565 "terms.handlebars->container->column_l->19->1",
566 "terms-mobile.handlebars->container->page_content->column_l->19->1"
505 - ]
567 + ],
568 + "pt": "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."
569 },
570 {
571 "en": "32bit version of the MeshAgent",
@@ -510,14 +573,16 @@
573 "xloc": [
574 "default.handlebars->23->290",
575 "default.handlebars->23->304"
513 - ]
576 + ],
577 + "pt": "Versão de 32 bits do MeshAgent"
578 },
579 {
580 "en": "37.5%",
581 "xloc": [
582 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11",
583 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->11"
520 - ]
584 + ],
585 + "pt": "37..5%"
586 },
587 {
588 "en": "4.jQuery User Interface - MIT License",
@@ -525,7 +590,8 @@
590 "xloc": [
591 "terms.handlebars->container->column_l->51->1->0",
592 "terms-mobile.handlebars->container->page_content->column_l->51->1->0"
528 - ]
593 + ],
594 + "pt": "4.Interface do Usuário jQuery - Licença MIT"
595 },
596 {
597 "en": "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.",
@@ -541,7 +607,8 @@
607 "fr": "4x vitesse",
608 "xloc": [
609 "player.htm->p11->deskarea0->deskarea4->3->PlaySpeed->9"
544 - ]
610 + ],
611 + "pt": "4x velocidade"
612 },
613 {
614 "en": "5.noVNC - Mozilla Public License 2.0",
@@ -549,7 +616,8 @@
616 "xloc": [
617 "terms.handlebars->container->column_l->59->1->0",
618 "terms-mobile.handlebars->container->page_content->column_l->59->1->0"
552 - ]
619 + ],
620 + "pt": "5.noVNC - Licença Pública Mozilla 2.0 0"
621 },
622 {
623 "en": "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.",
@@ -564,7 +632,8 @@
632 "xloc": [
633 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9",
634 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->9"
567 - ]
635 + ],
636 + "pt": "50%"
637 },
638 {
639 "en": "6.Redistributions of any form whatsoever must retain the following acknowledgment: \"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)\".",
@@ -572,14 +641,16 @@
641 "xloc": [
642 "terms.handlebars->container->column_l->41->1",
643 "terms-mobile.handlebars->container->page_content->column_l->41->1"
575 - ]
644 + ],
645 + "pt": "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/)\"."
646 },
647 {
648 "en": "62.5%",
649 "xloc": [
650 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7",
651 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->7"
582 - ]
652 + ],
653 + "pt": "62.5%"
654 },
655 {
656 "en": "64bit version of the MeshAgent",
@@ -587,14 +658,16 @@
658 "xloc": [
659 "default.handlebars->23->293",
660 "default.handlebars->23->307"
590 - ]
661 + ],
662 + "pt": "Versão de 64 bits do MeshAgent"
663 },
664 {
665 "en": "7 Day Power State",
666 "cs": "7 denní statistika provozu",
667 "xloc": [
668 "default.handlebars->23->523"
597 - ]
669 + ],
670 + "pt": "Estado de energia de 7 dias"
671 },
672 {
673 "en": "7.Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UK License",
@@ -602,14 +675,16 @@
675 "xloc": [
676 "terms.handlebars->container->column_l->73->1->0",
677 "terms-mobile.handlebars->container->page_content->column_l->73->1->0"
605 - ]
678 + ],
679 + "pt": "7.Webtoolkit Javascript Base 64 - Licença Creative Commons Attribution 2.0 UK"
680 },
681 {
682 "en": "75%",
683 "xloc": [
684 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5",
685 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->5"
612 - ]
686 + ],
687 + "pt": "75%"
688 },
689 {
690 "en": "8 hours",
@@ -618,61 +693,70 @@
693 "xloc": [
694 "default.handlebars->23->257",
695 "default.handlebars->23->271"
621 - ]
696 + ],
697 + "pt": "8 horas"
698 },
699 {
700 "en": "80x25",
701 "xloc": [
702 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->0"
627 - ]
703 + ],
704 + "pt": "80x25"
705 },
706 {
707 "en": "87.5%",
708 "xloc": [
709 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3",
710 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->3"
634 - ]
711 + ],
712 + "pt": "87.5%"
713 },
714 {
715 "en": ":",
716 "xloc": [
717 "agentinvite.handlebars->3->1"
640 - ]
718 + ],
719 + "pt": ":"
720 },
721 {
722 "en": "<a href=\\\"https://www.yubico.com/\\\" rel=\\\"noreferrer noopener\\\" target=\\\"_blank\\\">Hardware keys</a> are used as secondary login authentication.",
723 "cs": "<a href=\\\"https://www.yubico.com/\\\" rel=\\\"noreferrer noopener\\\" target=\\\"_blank\\\">Hardwarové klíče</a> jsou použity jako druhá možnost autentizace.",
724 "xloc": [
725 "default.handlebars->23->103"
647 - ]
726 + ],
727 + "pt": "<a href=\\\"https://www.yubico.com/\\\" rel=\\\"noreferrer noopener\\\" target=\\\"_blank\\\">Chaves Hardware</a> são usados como autenticação de login secundária."
728 },
729 {
730 "en": "<b style=color:green>2-step login activation removed</b>. You can reactivate this feature at any time.",
731 "cs": "<b style=color:green>2-faktorové přihlášení odstraněno</b>. Lze znovu kdykoliv zapnout.",
732 "xloc": [
733 "default-mobile.handlebars->9->19"
654 - ]
734 + ],
735 + "pt": "<b style=color:green>Ativação de login em duas etapas removida</b>. Você pode reativar esse recurso a qualquer momento."
736 },
737 {
738 "en": "<b style=color:green>2-step login activation successful</b>. You will now need a valid token to login again.",
739 "cs": "<b style=color:green>2-faktorová autentizace zapnuta</b>. Je třeba platný token k přihlášení.",
740 "xloc": [
741 "default-mobile.handlebars->9->16"
661 - ]
742 + ],
743 + "pt": "<b style=color:green> ativação de login em duas etapas </b>. Agora você precisará de um token válido para fazer login novamente."
744 },
745 {
746 "en": "<b style=color:red>2-step login activation failed</b>. Clear the secret from the application and try again. You only have a few minutes to enter the proper code.",
747 "cs": "<b style=color:red>2-faktorové přihlášení selhalo</b>. Je třeba smazat tajemství z aplikace a zkusit znovu. Na toto máte již jen pár minut.",
748 "xloc": [
749 "default-mobile.handlebars->9->17"
668 - ]
750 + ],
751 + "pt": "<b style=color:red> falha na ativação do login em duas etapas </b>. Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto."
752 },
753 {
754 "en": "<b style=color:red>2-step login activation removal failed</b>. Try again.",
755 "cs": "<b style=color:red>Odstranění 2-faktorového přihlášení selhalo</b>. Zkuste znovu.",
756 "xloc": [
757 "default-mobile.handlebars->9->20"
675 - ]
758 + ],
759 + "pt": "<b style=color:red> falha na remoção da ativação do login em duas etapas </b>. Tente novamente."
760 },
761 {
762 "en": "\\\\",
@@ -688,7 +772,8 @@
772 "fr": "Accès refusé",
773 "xloc": [
774 "default.handlebars->23->652"
691 - ]
775 + ],
776 + "pt": "Acesso Negado"
777 },
778 {
779 "en": "Access denied.",
@@ -703,21 +788,24 @@
788 "cs": "Přístup k souborům na serveru",
789 "xloc": [
790 "default.handlebars->23->1197"
706 - ]
791 + ],
792 + "pt": "Acesso aos arquivos do servidor"
793 },
794 {
795 "en": "Account actions",
796 "cs": "Akce účtu",
797 "xloc": [
798 "default.handlebars->container->column_l->p2->p2AccountActions->1->0"
713 - ]
799 + ],
800 + "pt": "Ações da conta"
801 },
802 {
803 "en": "Account Actions",
804 "cs": "Akce účtu",
805 "xloc": [
806 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->0"
720 - ]
807 + ],
808 + "pt": "Ações da Conta"
809 },
810 {
811 "en": "Account Creation",
@@ -725,7 +813,8 @@
813 "xloc": [
814 "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->5->1",
815 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->5->1"
728 - ]
816 + ],
817 + "pt": "Criação de conta"
818 },
819 {
820 "en": "Account limit reached.",
@@ -757,14 +846,16 @@
846 "xloc": [
847 "login.handlebars->container->column_l->centralTable->1->0->logincell->resetpanel->1->5->1",
848 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpanel->1->5->1"
760 - ]
849 + ],
850 + "pt": "Redefinição de conta"
851 },
852 {
853 "en": "Account security",
854 "cs": "Nastavení bezpečnosti",
855 "xloc": [
856 "default.handlebars->container->column_l->p2->p2AccountSecurity->1->0"
767 - ]
857 + ],
858 + "pt": "Segurança da conta"
859 },
860 {
861 "en": "Account Security",
@@ -779,14 +870,16 @@
870 "default-mobile.handlebars->9->51",
871 "default-mobile.handlebars->9->126",
872 "default-mobile.handlebars->9->128"
782 - ]
873 + ],
874 + "pt": "Segurança da Conta"
875 },
876 {
877 "en": "ACM",
878 "xloc": [
879 "default.handlebars->23->441",
880 "default-mobile.handlebars->9->179"
789 - ]
881 + ],
882 + "pt": "ACM"
883 },
884 {
885 "en": "Action",
@@ -794,7 +887,8 @@
887 "xloc": [
888 "default.handlebars->container->column_l->p42->p42tbl->1->0->8",
889 "default.handlebars->23->657"
797 - ]
890 + ],
891 + "pt": "Ação"
892 },
893 {
894 "en": "Actions",
@@ -806,7 +900,8 @@
900 "default.handlebars->23->473",
901 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3",
902 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->1"
809 - ]
903 + ],
904 + "pt": "Ações"
905 },
906 {
907 "en": "Activate camera & microphone",
@@ -814,7 +909,8 @@
909 "fr": "Activer caméra et microphone",
910 "xloc": [
911 "messenger.handlebars->xtop->1"
817 - ]
912 + ],
913 + "pt": "Ativar câmera e microfone"
914 },
915 {
916 "en": "Activate microphone",
@@ -822,7 +918,8 @@
918 "fr": "Activer le microphone",
919 "xloc": [
920 "messenger.handlebars->xtop->1"
825 - ]
921 + ],
922 + "pt": "Ativar microfone"
923 },
924 {
925 "en": "Activated",
@@ -833,7 +930,8 @@
930 "default.handlebars->23->436",
931 "default-mobile.handlebars->9->174",
932 "default-mobile.handlebars->9->176"
836 - ]
933 + ],
934 + "pt": "ativado"
935 },
936 {
937 "en": "Activation",
@@ -843,14 +941,16 @@
941 "default.handlebars->23->196",
942 "default.handlebars->23->977",
943 "default.handlebars->23->979"
846 - ]
944 + ],
945 + "pt": "Ativação"
946 },
947 {
948 "en": "Active User{0}",
949 "cs": "Aktivní uživatel{0}",
950 "xloc": [
951 "default.handlebars->23->460"
853 - ]
952 + ],
953 + "pt": "Usuário ativo {0}"
954 },
955 {
956 "en": "Add a new computer to this mesh by installing the mesh agent.",
@@ -858,14 +958,16 @@
958 "xloc": [
959 "default.handlebars->23->197",
960 "default.handlebars->23->980"
861 - ]
961 + ],
962 + "pt": "Adicione um novo computador a essa malha instalando o agente de malha."
963 },
964 {
965 "en": "Add a new Intel&reg; AMT computer by scanning the local network.",
966 "cs": "Přidat nový Intel&reg; AMT počítač pomocí skenu lokální sítě.",
967 "xloc": [
968 "default.handlebars->23->191"
868 - ]
969 + ],
970 + "pt": "Adicione um novo Intelreg; Computador AMT digitalizando a rede local."
971 },
972 {
973 "en": "Add a new Intel&reg; AMT computer that is located on the internet.",
@@ -873,7 +975,8 @@
975 "xloc": [
976 "default.handlebars->23->187",
977 "default.handlebars->23->972"
876 - ]
978 + ],
979 + "pt": "Adicione um novo Intel&reg; Computador AMT localizado na Internet."
980 },
981 {
982 "en": "Add a new Intel&reg; AMT computer that is located on the local network.",
@@ -881,14 +984,16 @@
984 "xloc": [
985 "default.handlebars->23->189",
986 "default.handlebars->23->974"
884 - ]
987 + ],
988 + "pt": "Adicione um novo Intel&reg; AMT computer that is located on the local network."
989 },
990 {
991 "en": "Add a new Intel&reg; AMT device to device group \\\"{0}\\\".",
992 "cs": "Přidat nové Intel&reg; AMT zařízení do skupiny \\\"{0}\\\".",
993 "xloc": [
994 "default.handlebars->23->201"
891 - ]
995 + ],
996 + "pt": "Adicione um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \\\"{0}\\\"."
997 },
998 {
999 "en": "Add Agent",
@@ -896,7 +1001,8 @@
1001 "fr": "Ajouter un agent",
1002 "xloc": [
1003 "default.handlebars->23->198"
899 - ]
1004 + ],
1005 + "pt": "Adicionar agente"
1006 },
1007 {
1008 "en": "Add CIRA",
@@ -904,7 +1010,8 @@
1010 "fr": "Ajouter CIRA",
1011 "xloc": [
1012 "default.handlebars->23->188"
907 - ]
1013 + ],
1014 + "pt": "Adicionar CIRA"
1015 },
1016 {
1017 "en": "Add Device Event",
@@ -912,7 +1019,8 @@
1019 "fr": "Ajouter un événement",
1020 "xloc": [
1021 "default.handlebars->23->506"
915 - ]
1022 + ],
1023 + "pt": "Adicionar evento do dispositivo"
1024 },
1025 {
1026 "en": "Add Device Group",
@@ -920,42 +1028,48 @@
1028 "fr": "Ajouter un groupe",
1029 "xloc": [
1030 "default.handlebars->23->169"
923 - ]
1031 + ],
1032 + "pt": "Adicionar grupo de dispositivos"
1033 },
1034 {
1035 "en": "Add Intel&reg; AMT CIRA device",
1036 "cs": "Přidat Intel&reg; AMT CIRA zařízení",
1037 "xloc": [
1038 "default.handlebars->23->243"
930 - ]
1039 + ],
1040 + "pt": "Adicione Intelreg; "
1041 },
1042 {
1043 "en": "Add Intel&reg; AMT device",
1044 "cs": "Přidat Intel&reg; AMT zařízení",
1045 "xloc": [
1046 "default.handlebars->23->211"
937 - ]
1047 + ],
1048 + "pt": "Adicione Intelreg; dispositivo AMT"
1049 },
1050 {
1051 "en": "Add Key",
1052 "cs": "Přidat klíč",
1053 "xloc": [
1054 "default.handlebars->23->107"
944 - ]
1055 + ],
1056 + "pt": "Adicionar chave"
1057 },
1058 {
1059 "en": "Add Local",
1060 "cs": "Přidat lokálně",
1061 "xloc": [
1062 "default.handlebars->23->190"
951 - ]
1063 + ],
1064 + "pt": "Adicionar local"
1065 },
1066 {
1067 "en": "Add Mesh Agent",
1068 "cs": "Přidat agenta",
1069 "xloc": [
1070 "default.handlebars->23->310"
958 - ]
1071 + ],
1072 + "pt": "Adicionar agente de malha"
1073 },
1074 {
1075 "en": "add one",
@@ -964,7 +1078,8 @@
1078 "xloc": [
1079 "default.handlebars->23->165",
1080 "default.handlebars->23->167"
967 - ]
1081 + ],
1082 + "pt": "Adicione um"
1083 },
1084 {
1085 "en": "Add Security Key",
@@ -977,7 +1092,8 @@
1092 "default.handlebars->23->116",
1093 "default.handlebars->23->676",
1094 "default.handlebars->23->677"
980 - ]
1095 + ],
1096 + "pt": "Adicionar chave de segurança"
1097 },
1098 {
1099 "en": "Add User to Mesh",
@@ -985,7 +1101,8 @@
1101 "fr": "Ajouter un utilisateur au groupe",
1102 "xloc": [
1103 "default-mobile.handlebars->9->306"
988 - ]
1104 + ],
1105 + "pt": "Adicionar usuário à malha"
1106 },
1107 {
1108 "en": "Add Users",
@@ -993,21 +1110,24 @@
1110 "fr": "Ajouter des utilisateurs",
1111 "xloc": [
1112 "default.handlebars->23->971"
996 - ]
1113 + ],
1114 + "pt": "Adicionar usuários"
1115 },
1116 {
1117 "en": "Add Users to Device Group",
1118 "cs": "Přidat uživatele do skupiny zařizení",
1119 "xloc": [
1120 "default.handlebars->23->1057"
1003 - ]
1121 + ],
1122 + "pt": "Adicionar usuários ao grupo de dispositivos"
1123 },
1124 {
1125 "en": "Add YubiKey&reg; OTP",
1126 "cs": "Přidat YubiKey&reg; OTP",
1127 "xloc": [
1128 "default.handlebars->23->108"
1010 - ]
1129 + ],
1130 + "pt": "Adicione YubiKeyreg; OTP"
1131 },
1132 {
1133 "en": "Address",
@@ -1015,46 +1135,53 @@
1135 "xloc": [
1136 "default.handlebars->23->143",
1137 "default.handlebars->23->160"
1018 - ]
1138 + ],
1139 + "pt": "Endereço"
1140 },
1141 {
1142 "en": "Addresses",
1143 "cs": "Adresy",
1144 "xloc": [
1145 "player.htm->3->7"
1025 - ]
1146 + ],
1147 + "pt": "Endereços"
1148 },
1149 {
1150 "en": "admin",
1151 "xloc": [
1152 "default.handlebars->23->206"
1031 - ]
1153 + ],
1154 + "pt": "admin"
1155 },
1156 {
1157 "en": "Admin Realms",
1158 "cs": "Administrátorské realmy",
1159 "xloc": [
1160 "default.handlebars->23->1220"
1038 - ]
1161 + ],
1162 + "pt": "Admin Realms"
1163 },
1164 {
1165 "en": "Administrative Realms",
1166 "cs": "Administrátorské realmy",
1167 "xloc": [
1168 "default.handlebars->23->1184"
1045 - ]
1169 + ],
1170 + "pt": "Domínios Administrativos"
1171 },
1172 {
1173 "en": "Administrator",
1174 "xloc": [
1175 "default.handlebars->23->1147"
1051 - ]
1176 + ],
1177 + "pt": "Administrador"
1178 },
1179 {
1180 "en": "Afrikaans",
1181 "xloc": [
1182 "default.handlebars->23->679"
1057 - ]
1183 + ],
1184 + "pt": "afrikaans"
1185 },
1186 {
1187 "en": "Agent",
@@ -1067,14 +1194,16 @@
1194 "default-mobile.handlebars->9->118",
1195 "default-mobile.handlebars->9->171",
1196 "default-mobile.handlebars->9->187"
1070 - ]
1197 + ],
1198 + "pt": "Agente"
1199 },
1200 {
1201 "en": "Agent Action",
1202 "cs": "Akce agenta",
1203 "xloc": [
1204 "default.handlebars->container->column_l->p15->consoleTable->1->0->1->1"
1077 - ]
1205 + ],
1206 + "pt": "Ação do agente"
1207 },
1208 {
1209 "en": "Agent connected",
@@ -1083,7 +1212,8 @@
1212 "default.handlebars->23->118",
1213 "default.handlebars->23->497",
1214 "default.handlebars->23->498"
1086 - ]
1215 + ],
1216 + "pt": "Agente conectado"
1217 },
1218 {
1219 "en": "Agent Console",
@@ -1091,61 +1221,70 @@
1221 "xloc": [
1222 "default.handlebars->23->1064",
1223 "default-mobile.handlebars->9->312"
1094 - ]
1224 + ],
1225 + "pt": "Console do agente"
1226 },
1227 {
1228 "en": "Agent disconnected",
1229 "cs": "Agent odpojen",
1230 "xloc": [
1231 "default.handlebars->23->122"
1101 - ]
1232 + ],
1233 + "pt": "Agente desconectado"
1234 },
1235 {
1236 "en": "Agent is offline",
1237 "cs": "Agent je offline",
1238 "xloc": [
1239 "default.handlebars->23->650"
1108 - ]
1240 + ],
1241 + "pt": "O agente está offline"
1242 },
1243 {
1244 "en": "Agent is online",
1245 "cs": "Agent je online",
1246 "xloc": [
1247 "default.handlebars->23->649"
1115 - ]
1248 + ],
1249 + "pt": "Agente está online"
1250 },
1251 {
1252 "en": "Agent Relay",
1253 "xloc": [
1254 "default-mobile.handlebars->9->190"
1121 - ]
1255 + ],
1256 + "pt": "Retransmissão do agente"
1257 },
1258 {
1259 "en": "Agent Remote Desktop",
1260 "xloc": [
1261 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->1",
1262 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->1"
1128 - ]
1263 + ],
1264 + "pt": "Área de trabalho remota do agente"
1265 },
1266 {
1267 "en": "Agent Tag",
1268 "xloc": [
1269 "default.handlebars->23->453",
1270 "default-mobile.handlebars->9->186"
1135 - ]
1271 + ],
1272 + "pt": "Etiqueta do agente"
1273 },
1274 {
1275 "en": "Agents",
1276 "cs": "Agenti",
1277 "xloc": [
1278 "default.handlebars->23->1258"
1142 - ]
1279 + ],
1280 + "pt": "Agentes"
1281 },
1282 {
1283 "en": "Albanian",
1284 "xloc": [
1285 "default.handlebars->23->680"
1148 - ]
1286 + ],
1287 + "pt": "albanês"
1288 },
1289 {
1290 "en": "All",
@@ -1155,14 +1294,16 @@
1294 "default-mobile.handlebars->9->73",
1295 "default-mobile.handlebars->9->241",
1296 "default-mobile.handlebars->9->243"
1158 - ]
1297 + ],
1298 + "pt": "Todos"
1299 },
1300 {
1301 "en": "All Displays",
1302 "cs": "Všechny displeje",
1303 "xloc": [
1304 "default-mobile.handlebars->9->230"
1165 - ]
1305 + ],
1306 + "pt": "Todas as telas"
1307 },
1308 {
1309 "en": "All Focus",
@@ -1170,221 +1311,256 @@
1311 "default.handlebars->23->571",
1312 "default.handlebars->23->573",
1313 "default.handlebars->23->574"
1173 - ]
1314 + ],
1315 + "pt": "All Focus"
1316 },
1317 {
1318 "en": "Allow users to manage this device group and devices in this group.",
1319 "fr": "Autoriser les utilisateurs à gérer ce groupe et les périphériques de ce groupe.",
1320 "xloc": [
1321 "default.handlebars->23->1036"
1180 - ]
1322 + ],
1323 + "pt": "Permitir que os usuários gerenciem esse grupo de dispositivos e dispositivos neste grupo."
1324 },
1325 {
1326 "en": "Alt-F4",
1327 "xloc": [
1328 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->17",
1329 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->19"
1187 - ]
1330 + ],
1331 + "pt": "Alt-F4"
1332 },
1333 {
1334 "en": "Alt-Tab",
1335 "xloc": [
1336 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->21",
1337 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->23"
1194 - ]
1338 + ],
1339 + "pt": "Alt-Tab"
1340 },
1341 {
1342 "en": "Alternate (F10 = ESC+0)",
1343 "xloc": [
1344 "default.handlebars->23->606"
1200 - ]
1345 + ],
1346 + "pt": "Alternativo (F10 = ESC + 0)"
1347 },
1348 {
1349 "en": "Always Notify",
1350 "fr": "Toujours aviser",
1351 "xloc": [
1352 "default.handlebars->23->954"
1207 - ]
1353 + ],
1354 + "pt": "Notificar sempre"
1355 },
1356 {
1357 "en": "Always Prompt",
1358 "xloc": [
1359 "default.handlebars->23->955"
1213 - ]
1360 + ],
1361 + "pt": "Sempre alerta"
1362 },
1363 {
1364 "en": "AMT",
1365 "xloc": [
1366 "default.handlebars->23->153",
1367 "default.handlebars->23->339"
1220 - ]
1368 + ],
1369 + "pt": "AMT"
1370 },
1371 {
1372 "en": "and its source can be downloaded from",
1373 "xloc": [
1374 "terms.handlebars->container->column_l->75->1",
1375 "terms-mobile.handlebars->container->page_content->column_l->75->1"
1227 - ]
1376 + ],
1377 + "pt": "e sua fonte pode ser baixada de"
1378 },
1379 {
1380 "en": "Android APK",
1381 "xloc": [
1382 "default.handlebars->23->414",
1383 "default-mobile.handlebars->9->154"
1234 - ]
1384 + ],
1385 + "pt": "Android APK"
1386 },
1387 {
1388 "en": "Android ARM",
1389 "xloc": [
1390 "default.handlebars->23->409",
1391 "default-mobile.handlebars->9->149"
1241 - ]
1392 + ],
1393 + "pt": "Android ARM"
1394 },
1395 {
1396 "en": "Android x86",
1397 "xloc": [
1398 "default.handlebars->23->412",
1399 "default-mobile.handlebars->9->152"
1248 - ]
1400 + ],
1401 + "pt": "Android x86"
1402 },
1403 {
1404 "en": "Antivirus",
1405 "fr": "Antivirus",
1406 "xloc": [
1407 "default.handlebars->23->459"
1255 - ]
1408 + ],
1409 + "pt": "Antivírus"
1410 },
1411 {
1412 "en": "Any supported",
1413 "xloc": [
1414 "default.handlebars->23->251"
1261 - ]
1415 + ],
1416 + "pt": "Qualquer suportado"
1417 },
1418 {
1419 "en": "Apple MacOS",
1420 "xloc": [
1421 "default.handlebars->23->281"
1267 - ]
1422 + ],
1423 + "pt": "Apple MacOS"
1424 },
1425 {
1426 "en": "Apple MacOS only",
1427 "xloc": [
1428 "default.handlebars->23->253"
1273 - ]
1429 + ],
1430 + "pt": "Apenas Apple MacOS "
1431 },
1432 {
1433 "en": "Apple™ MacOS",
1434 "xloc": [
1435 "agentinvite.handlebars->container->column_l->5->macostab->1"
1279 - ]
1436 + ],
1437 + "pt": "Apple™ MacOS"
1438 },
1439 {
1440 "en": "Arabic (Algeria)",
1441 "xloc": [
1442 "default.handlebars->23->682"
1285 - ]
1443 + ],
1444 + "pt": "Árabe (Argélia)"
1445 },
1446 {
1447 "en": "Arabic (Bahrain)",
1448 "xloc": [
1449 "default.handlebars->23->683"
1291 - ]
1450 + ],
1451 + "pt": "Árabe (Bahrain)"
1452 },
1453 {
1454 "en": "Arabic (Egypt)",
1455 "xloc": [
1456 "default.handlebars->23->684"
1297 - ]
1457 + ],
1458 + "pt": "Árabe (Egito)"
1459 },
1460 {
1461 "en": "Arabic (Iraq)",
1462 "xloc": [
1463 "default.handlebars->23->685"
1303 - ]
1464 + ],
1465 + "pt": "Árabe (Iraque)"
1466 },
1467 {
1468 "en": "Arabic (Jordan)",
1469 "xloc": [
1470 "default.handlebars->23->686"
1309 - ]
1471 + ],
1472 + "pt": "Árabe (Jordânia)"
1473 },
1474 {
1475 "en": "Arabic (Kuwait)",
1476 "xloc": [
1477 "default.handlebars->23->687"
1315 - ]
1478 + ],
1479 + "pt": "Árabe (Kuwait)"
1480 },
1481 {
1482 "en": "Arabic (Lebanon)",
1483 "xloc": [
1484 "default.handlebars->23->688"
1321 - ]
1485 + ],
1486 + "pt": "Árabe (Líbano)"
1487 },
1488 {
1489 "en": "Arabic (Libya)",
1490 "xloc": [
1491 "default.handlebars->23->689"
1327 - ]
1492 + ],
1493 + "pt": "Árabe (Líbia)"
1494 },
1495 {
1496 "en": "Arabic (Morocco)",
1497 "xloc": [
1498 "default.handlebars->23->690"
1333 - ]
1499 + ],
1500 + "pt": "Árabe (Marrocos)"
1501 },
1502 {
1503 "en": "Arabic (Oman)",
1504 "xloc": [
1505 "default.handlebars->23->691"
1339 - ]
1506 + ],
1507 + "pt": "Árabe (Omã)"
1508 },
1509 {
1510 "en": "Arabic (Qatar)",
1511 "xloc": [
1512 "default.handlebars->23->692"
1345 - ]
1513 + ],
1514 + "pt": "Árabe (Catar)"
1515 },
1516 {
1517 "en": "Arabic (Saudi Arabia)",
1518 "xloc": [
1519 "default.handlebars->23->693"
1351 - ]
1520 + ],
1521 + "pt": "Árabe (Arábia Saudita)"
1522 },
1523 {
1524 "en": "Arabic (Standard)",
1525 "xloc": [
1526 "default.handlebars->23->681"
1357 - ]
1527 + ],
1528 + "pt": "Árabe (padrão)"
1529 },
1530 {
1531 "en": "Arabic (Syria)",
1532 "xloc": [
1533 "default.handlebars->23->694"
1363 - ]
1534 + ],
1535 + "pt": "Árabe (Síria)"
1536 },
1537 {
1538 "en": "Arabic (Tunisia)",
1539 "xloc": [
1540 "default.handlebars->23->695"
1369 - ]
1541 + ],
1542 + "pt": "Árabe (Tunísia)"
1543 },
1544 {
1545 "en": "Arabic (U.A.E.)",
1546 "xloc": [
1547 "default.handlebars->23->696"
1375 - ]
1548 + ],
1549 + "pt": "Árabe (U.A.E)"
1550 },
1551 {
1552 "en": "Arabic (Yemen)",
1553 "xloc": [
1554 "default.handlebars->23->697"
1381 - ]
1555 + ],
1556 + "pt": "Árabe (Iêmen)"
1557 },
1558 {
1559 "en": "Aragonese",
1560 "xloc": [
1561 "default.handlebars->23->698"
1387 - ]
1562 + ],
1563 + "pt": "Aragonês"
1564 },
1565 {
1566 "en": "Architecture",
@@ -1392,7 +1568,8 @@
1568 "fr": "Architecture",
1569 "xloc": [
1570 "default.handlebars->23->46"
1395 - ]
1571 + ],
1572 + "pt": "Arquitetura"
1573 },
1574 {
1575 "en": "Are you sure you want to connect to {0} devices?",
@@ -1406,14 +1583,16 @@
1583 "xloc": [
1584 "default.handlebars->23->1018",
1585 "default-mobile.handlebars->9->283"
1409 - ]
1586 + ],
1587 + "pt": "Tem certeza de que deseja excluir o grupo {0}? A exclusão do grupo de dispositivos também excluirá todas as informações sobre os dispositivos desse grupo."
1588 },
1589 {
1590 "en": "Are you sure you want to delete node {0}?",
1591 "fr": "Êtes-vous sûr de vouloir supprimer le noeud {0}?",
1592 "xloc": [
1593 "default.handlebars->23->545"
1416 - ]
1594 + ],
1595 + "pt": "Tem certeza de que deseja excluir o nó {0}?"
1596 },
1597 {
1598 "en": "Are you sure you want to uninstall selected agent?",
@@ -1438,52 +1617,60 @@
1617 "xloc": [
1618 "default.handlebars->23->424",
1619 "default-mobile.handlebars->9->164"
1441 - ]
1620 + ],
1621 + "pt": "ARM-Linaro"
1622 },
1623 {
1624 "en": "Armenian",
1625 "xloc": [
1626 "default.handlebars->23->699"
1447 - ]
1627 + ],
1628 + "pt": "Armênio"
1629 },
1630 {
1631 "en": "ARMv6l / ARMv7l",
1632 "xloc": [
1633 "default.handlebars->23->425",
1634 "default-mobile.handlebars->9->165"
1454 - ]
1635 + ],
1636 + "pt": "ARMv6l / ARMv7l"
1637 },
1638 {
1639 "en": "ARMv6l / ARMv7l / NoKVM",
1640 "xloc": [
1641 "default.handlebars->23->427",
1642 "default-mobile.handlebars->9->167"
1461 - ]
1643 + ],
1644 + "pt": "ARMv6l / ARMv7l / NoKVM"
1645 },
1646 {
1647 "en": "ARMv8 64bit",
1648 "xloc": [
1649 "default.handlebars->23->426",
1650 "default-mobile.handlebars->9->166"
1468 - ]
1651 + ],
1652 + "pt": "ARMv8 64bit"
1653 },
1654 {
1655 "en": "Assamese",
1656 "xloc": [
1657 "default.handlebars->23->700"
1474 - ]
1658 + ],
1659 + "pt": "Assamese"
1660 },
1661 {
1662 "en": "Asturian",
1663 "xloc": [
1664 "default.handlebars->23->701"
1480 - ]
1665 + ],
1666 + "pt": "Asturiano"
1667 },
1668 {
1669 "en": "Authentication App",
1670 "xloc": [
1671 "default.handlebars->23->1221"
1486 - ]
1672 + ],
1673 + "pt": "Aplicativo de autenticação"
1674 },
1675 {
1676 "en": "Authenticator App",
@@ -1496,19 +1683,22 @@
1683 "default-mobile.handlebars->9->18",
1684 "default-mobile.handlebars->9->27",
1685 "default-mobile.handlebars->9->29"
1499 - ]
1686 + ],
1687 + "pt": "Autenticador de aplicativo"
1688 },
1689 {
1690 "en": "Authenticator app activation successful.",
1691 "xloc": [
1692 "default.handlebars->23->87"
1505 - ]
1693 + ],
1694 + "pt": "Ativação do aplicativo autenticador bem-sucedida."
1695 },
1696 {
1697 "en": "Authenticator application removed.",
1698 "xloc": [
1699 "default.handlebars->23->92"
1511 - ]
1700 + ],
1701 + "pt": "Aplicativo autenticador removido."
1702 },
1703 {
1704 "en": "Auto",
@@ -1516,13 +1706,15 @@
1706 "xloc": [
1707 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar->5",
1708 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->2"
1519 - ]
1709 + ],
1710 + "pt": "Auto"
1711 },
1712 {
1713 "en": "Auto-Remove",
1714 "xloc": [
1715 "default.handlebars->23->942"
1525 - ]
1716 + ],
1717 + "pt": "Remover automaticamente"
1718 },
1719 {
1720 "en": "AutoConnect",
@@ -1531,20 +1723,23 @@
1723 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3",
1724 "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3",
1725 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3"
1534 - ]
1726 + ],
1727 + "pt": "Conexão automática"
1728 },
1729 {
1730 "en": "Automatic connect",
1731 "fr": "Connexion automatique",
1732 "xloc": [
1733 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar->5"
1541 - ]
1734 + ],
1735 + "pt": "Conexão automática"
1736 },
1737 {
1738 "en": "Azerbaijani",
1739 "xloc": [
1740 "default.handlebars->23->702"
1547 - ]
1741 + ],
1742 + "pt": "Azerbaijão"
1743 },
1744 {
1745 "en": "Back",
@@ -1567,7 +1762,8 @@
1762 "error404-mobile.handlebars->container->footer->1->1->0->3->1",
1763 "terms.handlebars->container->footer->1->1->0->3->0",
1764 "terms-mobile.handlebars->container->footer->1->1->0->3->1"
1570 - ]
1765 + ],
1766 + "pt": "Voltar"
1767 },
1768 {
1769 "en": "Back to login",
@@ -1582,120 +1778,139 @@
1778 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->10",
1779 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resettokenpanel->1->8",
1780 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpasswordpanel->1->10"
1585 - ]
1781 + ],
1782 + "pt": "Volte ao login"
1783 },
1784 {
1785 "en": "Background & interactive",
1786 "xloc": [
1787 "default.handlebars->23->285"
1591 - ]
1788 + ],
1789 + "pt": "Segundo plano e interativo"
1790 },
1791 {
1792 "en": "Background and interactive",
1793 "xloc": [
1794 "default.handlebars->23->263"
1597 - ]
1795 + ],
1796 + "pt": "Segundo plano e interativo"
1797 },
1798 {
1799 "en": "Background only",
1800 "xloc": [
1801 "default.handlebars->23->264",
1802 "default.handlebars->23->286"
1604 - ]
1803 + ],
1804 + "pt": "Apenas em segundo plano"
1805 },
1806 {
1807 "en": "Backspace",
1808 "fr": "Retour arrière",
1809 "xloc": [
1810 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3"
1611 - ]
1811 + ],
1812 + "pt": "Excluir"
1813 },
1814 {
1815 "en": "Backup Codes",
1816 "xloc": [
1817 "default.handlebars->23->1223"
1617 - ]
1818 + ],
1819 + "pt": "Códigos de backup"
1820 },
1821 {
1822 "en": "Basque",
1823 "xloc": [
1824 "default.handlebars->23->703"
1623 - ]
1825 + ],
1826 + "pt": "Basco"
1827 },
1828 {
1829 "en": "Batch create many user accounts",
1830 "xloc": [
1831 "default.handlebars->container->column_l->p4->3->1->0->3->1->5"
1629 - ]
1832 + ],
1833 + "pt": "Lote criar muitas contas de usuário"
1834 },
1835 {
1836 "en": "Belarusian",
1837 "xloc": [
1838 "default.handlebars->23->705"
1635 - ]
1839 + ],
1840 + "pt": "Bielorrusso"
1841 },
1842 {
1843 "en": "Bengali",
1844 "xloc": [
1845 "default.handlebars->23->706"
1641 - ]
1846 + ],
1847 + "pt": "Bengali"
1848 },
1849 {
1850 "en": "BIOS",
1851 "xloc": [
1852 "default.handlebars->23->30"
1647 - ]
1853 + ],
1854 + "pt": "BIOS"
1855 },
1856 {
1857 "en": "Bosnian",
1858 "xloc": [
1859 "default.handlebars->23->707"
1653 - ]
1860 + ],
1861 + "pt": "Bósnia"
1862 },
1863 {
1864 "en": "Breton",
1865 "xloc": [
1866 "default.handlebars->23->708"
1659 - ]
1867 + ],
1868 + "pt": "Breton"
1869 },
1870 {
1871 "en": "Broadcast",
1872 "fr": "Diffuser",
1873 "xloc": [
1874 "default.handlebars->container->column_l->p4->3->1->0->3->1"
1666 - ]
1875 + ],
1876 + "pt": "Broadcast"
1877 },
1878 {
1879 "en": "Broadcast a message to all connected users.",
1880 "xloc": [
1881 "default.handlebars->23->1169"
1672 - ]
1882 + ],
1883 + "pt": "Transmita uma mensagem para todos os usuários conectados."
1884 },
1885 {
1886 "en": "Broadcast Message",
1887 "fr": "Diffusion d'un Message",
1888 "xloc": [
1889 "default.handlebars->23->1170"
1679 - ]
1890 + ],
1891 + "pt": "Mensagem de transmissão"
1892 },
1893 {
1894 "en": "Bulgarian",
1895 "xloc": [
1896 "default.handlebars->23->704"
1685 - ]
1897 + ],
1898 + "pt": "Búlgaria"
1899 },
1900 {
1901 "en": "Burmese",
1902 "xloc": [
1903 "default.handlebars->23->709"
1691 - ]
1904 + ],
1905 + "pt": "Birmanês"
1906 },
1907 {
1908 "en": "Call Error",
1909 "fr": "Erreur d'appel",
1910 "xloc": [
1911 "default.handlebars->23->1290"
1698 - ]
1912 + ],
1913 + "pt": "Erro de chamada"
1914 },
1915 {
1916 "en": "Cancel",
@@ -1709,39 +1924,45 @@
1924 "login.handlebars->dialog->idx_dlgButtonBar",
1925 "login-mobile.handlebars->dialog->idx_dlgButtonBar",
1926 "player.htm->p11->dialog->idx_dlgButtonBar"
1712 - ]
1927 + ],
1928 + "pt": "Cancelar"
1929 },
1930 {
1931 "en": "Capacity / Speed",
1932 "xloc": [
1933 "default.handlebars->23->40"
1718 - ]
1934 + ],
1935 + "pt": "Capacidade / velocidade"
1936 },
1937 {
1938 "en": "Catalan",
1939 "xloc": [
1940 "default.handlebars->23->710"
1724 - ]
1941 + ],
1942 + "pt": "Catalão"
1943 },
1944 {
1945 "en": "CCM",
1946 "xloc": [
1947 "default.handlebars->23->439",
1948 "default-mobile.handlebars->9->178"
1731 - ]
1949 + ],
1950 + "pt": "CCM"
1951 },
1952 {
1953 "en": "Center map here",
1954 "fr": "Centré la carte ici",
1955 "xloc": [
1956 "default.handlebars->23->373"
1738 - ]
1957 + ],
1958 + "pt": "Centralize o mapa aqui"
1959 },
1960 {
1961 "en": "Chamorro",
1962 "xloc": [
1963 "default.handlebars->23->711"
1744 - ]
1964 + ],
1965 + "pt": "Chamorro"
1966 },
1967 {
1968 "en": "Change email address",
@@ -1749,14 +1970,16 @@
1970 "xloc": [
1971 "default.handlebars->container->column_l->p2->p2AccountActions->3->accountChangeEmailAddressSpan->0",
1972 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->3->changeEmailId->0"
1752 - ]
1973 + ],
1974 + "pt": "Mude o endereço de email"
1975 },
1976 {
1977 "en": "Change Email for {0}",
1978 "cs": "Změnit email pro {0}",
1979 "xloc": [
1980 "default.handlebars->23->1234"
1759 - ]
1981 + ],
1982 + "pt": "Alterar email para {0}"
1983 },
1984 {
1985 "en": "Change Group",
@@ -1765,7 +1988,8 @@
1988 "default.handlebars->23->480",
1989 "default.handlebars->23->542",
1990 "default.handlebars->23->543"
1768 - ]
1991 + ],
1992 + "pt": "Alterar grupo"
1993 },
1994 {
1995 "en": "Change Password",
@@ -1773,7 +1997,8 @@
1997 "xloc": [
1998 "default.handlebars->23->903",
1999 "default-mobile.handlebars->9->46"
1776 - ]
2000 + ],
2001 + "pt": "Mudar senha"
2002 },
2003 {
2004 "en": "Change password",
@@ -1781,50 +2006,58 @@
2006 "xloc": [
2007 "default.handlebars->container->column_l->p2->p2AccountActions->3->13",
2008 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->5->0"
1784 - ]
2009 + ],
2010 + "pt": "Mudar senha"
2011 },
2012 {
2013 "en": "Change Password for {0}",
2014 "xloc": [
2015 "default.handlebars->23->1241"
1790 - ]
2016 + ],
2017 + "pt": "Alterar senha para {0}"
2018 },
2019 {
2020 "en": "Change the agent Java Script code module",
2021 "xloc": [
2022 "default.handlebars->container->column_l->p15->consoleTable->1->0->1->1"
1796 - ]
2023 + ],
2024 + "pt": "Alterar o módulo de código Java Script do agente"
2025 },
2026 {
2027 "en": "Change the power state of the remote machine",
2028 "xloc": [
2029 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1"
1802 - ]
2030 + ],
2031 + "pt": "Alterar o estado de energia da máquina remota"
2032 },
2033 {
2034 "en": "Change your account email address here.",
2035 "xloc": [
2036 "default.handlebars->23->890"
1808 - ]
2037 + ],
2038 + "pt": "Mude o endereço de e-mail da sua conta aqui."
2039 },
2040 {
2041 "en": "Change your account password by entering the old password and new password twice in the boxes below.",
2042 "cs": "Změnit heslo zadáním starého a dvakrát nového hesla níže.",
2043 "xloc": [
2044 "default.handlebars->23->896"
1815 - ]
2045 + ],
2046 + "pt": "Altere a senha da sua conta digitando a senha antiga e a nova senha duas vezes nas caixas abaixo."
2047 },
2048 {
2049 "en": "Changing the language will require a refresh of the page.",
2050 "xloc": [
2051 "default.handlebars->23->876"
1821 - ]
2052 + ],
2053 + "pt": "Alterar o idioma exigirá uma atualização da página."
2054 },
2055 {
2056 "en": "Chat",
2057 "xloc": [
2058 "default.handlebars->23->1139"
1827 - ]
2059 + ],
2060 + "pt": "Chat"
2061 },
2062 {
2063 "en": "Chat & Notify",
@@ -1833,32 +2066,37 @@
2066 "default.handlebars->23->1074",
2067 "default-mobile.handlebars->9->304",
2068 "default-mobile.handlebars->9->322"
1836 - ]
2069 + ],
2070 + "pt": "Chat & Notificação"
2071 },
2072 {
2073 "en": "Chechen",
2074 "xloc": [
2075 "default.handlebars->23->712"
1842 - ]
2076 + ],
2077 + "pt": "Checheno"
2078 },
2079 {
2080 "en": "Check and click OK to clear error log.",
2081 "xloc": [
2082 "default.handlebars->23->83"
1848 - ]
2083 + ],
2084 + "pt": "Verifique e clique em OK para limpar o log de erros."
2085 },
2086 {
2087 "en": "Check and click OK to start server self-update.",
2088 "xloc": [
2089 "default.handlebars->23->78"
1854 - ]
2090 + ],
2091 + "pt": "Marque e clique em OK para iniciar a atualização automática do servidor."
2092 },
2093 {
2094 "en": "Check server version",
2095 "cs": "Zkontrolovat verzi serveru",
2096 "xloc": [
2097 "default.handlebars->container->column_l->p6->p2ServerActions->3->p2ServerActionsVersion->0"
1861 - ]
2098 + ],
2099 + "pt": "Verifique a versão do servidor"
2100 },
2101 {
2102 "en": "Checking...",
@@ -1866,50 +2104,58 @@
2104 "xloc": [
2105 "default.handlebars->23->678",
2106 "default.handlebars->23->1286"
1869 - ]
2107 + ],
2108 + "pt": "Verificando ..."
2109 },
2110 {
2111 "en": "Chinese",
2112 "xloc": [
2113 "default.handlebars->23->713"
1875 - ]
2114 + ],
2115 + "pt": "Chinês"
2116 },
2117 {
2118 "en": "Chinese (Hong Kong)",
2119 "xloc": [
2120 "default.handlebars->23->714"
1881 - ]
2121 + ],
2122 + "pt": "Chinês (Hong Kong)"
2123 },
2124 {
2125 "en": "Chinese (PRC)",
2126 "xloc": [
2127 "default.handlebars->23->715"
1887 - ]
2128 + ],
2129 + "pt": "Chinês (PRC)"
2130 },
2131 {
2132 "en": "Chinese (Singapore)",
2133 "xloc": [
2134 "default.handlebars->23->716"
1893 - ]
2135 + ],
2136 + "pt": "Chinês (Singapura)"
2137 },
2138 {
2139 "en": "Chinese (Taiwan)",
2140 "xloc": [
2141 "default.handlebars->23->717"
1899 - ]
2142 + ],
2143 + "pt": "Chinês (Taiwan)"
2144 },
2145 {
2146 "en": "ChromeOS",
2147 "xloc": [
2148 "default.handlebars->23->417",
2149 "default-mobile.handlebars->9->157"
1906 - ]
2150 + ],
2151 + "pt": "ChromeOS"
2152 },
2153 {
2154 "en": "Chuvash",
2155 "xloc": [
2156 "default.handlebars->23->718"
1912 - ]
2157 + ],
2158 + "pt": "Chuvash"
2159 },
2160 {
2161 "en": "CIRA",
@@ -1919,25 +2165,29 @@
2165 "default.handlebars->23->1006",
2166 "default.handlebars->23->1011",
2167 "default-mobile.handlebars->9->119"
1922 - ]
2168 + ],
2169 + "pt": "CIRA"
2170 },
2171 {
2172 "en": "CIRA Server",
2173 "xloc": [
2174 "default.handlebars->23->1280"
1928 - ]
2175 + ],
2176 + "pt": "Servidor CIRA"
2177 },
2178 {
2179 "en": "CIRA Server Commands",
2180 "xloc": [
2181 "default.handlebars->23->1281"
1934 - ]
2182 + ],
2183 + "pt": "Comandos do servidor CIRA"
2184 },
2185 {
2186 "en": "Cleanup CIRA",
2187 "xloc": [
2188 "default.handlebars->23->228"
1940 - ]
2189 + ],
2190 + "pt": "Limpeza CIRA"
2191 },
2192 {
2193 "en": "Clear",
@@ -1956,44 +2206,51 @@
2206 "default-mobile.handlebars->9->263",
2207 "default-mobile.handlebars->9->265",
2208 "messenger.handlebars->xbottom"
1959 - ]
2209 + ],
2210 + "pt": "Limpo"
2211 },
2212 {
2213 "en": "Clear the core",
2214 "xloc": [
2215 "default.handlebars->23->659"
1965 - ]
2216 + ],
2217 + "pt": "Limpe o núcleo"
2218 },
2219 {
2220 "en": "Clear the secret from the application and try again. You only have a few minutes to enter the proper code.",
2221 "xloc": [
2222 "default.handlebars->23->90"
1971 - ]
2223 + ],
2224 + "pt": "Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto."
2225 },
2226 {
2227 "en": "Clear Tokens",
2228 "xloc": [
2229 "default.handlebars->23->100"
1977 - ]
2230 + ],
2231 + "pt": "Limpar Tokens"
2232 },
2233 {
2234 "en": "click here to create a device group",
2235 "xloc": [
2236 "default.handlebars->container->column_l->p1->NoMeshesPanel->1->1->0->3->getStarted1->1->0"
1983 - ]
2237 + ],
2238 + "pt": "clique aqui para criar um grupo de dispositivos"
2239 },
2240 {
2241 "en": "Click here to edit the server-side device name",
2242 "xloc": [
2243 "default.handlebars->23->388"
1989 - ]
2244 + ],
2245 + "pt": "clique aqui para criar um grupo de dispositivos"
2246 },
2247 {
2248 "en": "Click ok to send a verification mail to:",
2249 "xloc": [
2250 "default.handlebars->23->887",
2251 "default-mobile.handlebars->9->31"
1996 - ]
2252 + ],
2253 + "pt": "Clique em ok para enviar um email de verificação para:"
2254 },
2255 {
2256 "en": "click to reconnect",
@@ -2001,26 +2258,30 @@
2258 "xloc": [
2259 "default.handlebars->container->column_l->p0->p0message->2->0",
2260 "default-mobile.handlebars->container->page_content->column_l->p0->1->p0message->2->0"
2004 - ]
2261 + ],
2262 + "pt": "clique para reconectar"
2263 },
2264 {
2265 "en": "Click to view current notifications",
2266 "xloc": [
2267 "default.handlebars->container->masthead->5"
2010 - ]
2268 + ],
2269 + "pt": "Clique para visualizar as notificações atuais"
2270 },
2271 {
2272 "en": "Client Initiated Remote Access",
2273 "xloc": [
2274 "default.handlebars->23->1005",
2275 "default.handlebars->23->1010"
2017 - ]
2276 + ],
2277 + "pt": "Acesso remoto iniciado pelo cliente"
2278 },
2279 {
2280 "en": "Clipboard",
2281 "xloc": [
2282 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3"
2023 - ]
2283 + ],
2284 + "pt": "Área de transferência"
2285 },
2286 {
2287 "en": "Close",
@@ -2029,7 +2290,8 @@
2290 "default.handlebars->23->106",
2291 "default.handlebars->23->591",
2292 "default-mobile.handlebars->9->23"
2032 - ]
2293 + ],
2294 + "pt": "Fechar"
2295 },
2296 {
2297 "en": "Columns",
@@ -2037,14 +2299,16 @@
2299 "xloc": [
2300 "default.handlebars->container->column_l->p1->devListToolbarViewIcons",
2301 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarView->viewselect->1"
2040 - ]
2302 + ],
2303 + "pt": "Colunas"
2304 },
2305 {
2306 "en": "Confim {0} of {1} entrie{2} to this location?",
2307 "xloc": [
2308 "default.handlebars->23->1113",
2309 "default-mobile.handlebars->9->83"
2047 - ]
2310 + ],
2311 + "pt": "Confirme {0} da {1} entrada {2} para este local?"
2312 },
2313 {
2314 "en": "Confirm",
@@ -2055,42 +2319,48 @@
2319 "default.handlebars->23->1019",
2320 "default-mobile.handlebars->9->217",
2321 "default-mobile.handlebars->9->284"
2058 - ]
2322 + ],
2323 + "pt": "Confirme"
2324 },
2325 {
2326 "en": "Confirm copy of 1 entrie to this location?",
2327 "xloc": [
2328 "default.handlebars->23->629",
2329 "default-mobile.handlebars->9->254"
2065 - ]
2330 + ],
2331 + "pt": "Confirmar cópia de 1 entrada para este local?"
2332 },
2333 {
2334 "en": "Confirm copy of {0} entries's to this location?",
2335 "xloc": [
2336 "default.handlebars->23->628",
2337 "default-mobile.handlebars->9->253"
2072 - ]
2338 + ],
2339 + "pt": "Confirmar cópia de {0} entradas para este local?"
2340 },
2341 {
2342 "en": "Confirm delete selected devices(s)?",
2343 "cs": "Potvrdit smázání vybraných zařízení?",
2344 "xloc": [
2345 "default.handlebars->23->359"
2079 - ]
2346 + ],
2347 + "pt": "Confirmar a exclusão dos dispositivos selecionados?"
2348 },
2349 {
2350 "en": "Confirm move of 1 entrie to this location?",
2351 "xloc": [
2352 "default.handlebars->23->631",
2353 "default-mobile.handlebars->9->256"
2086 - ]
2354 + ],
2355 + "pt": "Confirmar a movimentação de 1 entrada para este local?"
2356 },
2357 {
2358 "en": "Confirm move of {0} entries's to this location?",
2359 "xloc": [
2360 "default.handlebars->23->630",
2361 "default-mobile.handlebars->9->255"
2093 - ]
2362 + ],
2363 + "pt": "Confirmar a movimentação de {0} entradas para este local?"
2364 },
2365 {
2366 "en": "Confirm overwrite?",
@@ -2103,14 +2373,16 @@
2373 "xloc": [
2374 "default.handlebars->23->668",
2375 "default-mobile.handlebars->9->30"
2106 - ]
2376 + ],
2377 + "pt": "Confirmar remoção do login do aplicativo autenticador em duas etapas?"
2378 },
2379 {
2380 "en": "Confirm removal of user {0}?",
2381 "xloc": [
2382 "default.handlebars->23->1083",
2383 "default-mobile.handlebars->9->330"
2113 - ]
2384 + ],
2385 + "pt": "Confirmar remoção do usuário {0}?"
2386 },
2387 {
2388 "en": "Connect",
@@ -2124,14 +2396,16 @@
2396 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3",
2397 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3",
2398 "default-mobile.handlebars->9->233"
2127 - ]
2399 + ],
2400 + "pt": "Conectar"
2401 },
2402 {
2403 "en": "Connect All",
2404 "xloc": [
2405 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar",
2406 "default.handlebars->23->181"
2134 - ]
2407 + ],
2408 + "pt": "Conectar todos"
2409 },
2410 {
2411 "en": "Connect to server",
@@ -2139,7 +2413,8 @@
2413 "xloc": [
2414 "default.handlebars->23->1009",
2415 "default.handlebars->23->1013"
2142 - ]
2416 + ],
2417 + "pt": "Conecte-se ao servidor"
2418 },
2419 {
2420 "en": "Connect using Intel AMT hardware KVM",
@@ -2153,14 +2428,16 @@
2428 "xloc": [
2429 "default.handlebars->23->11",
2430 "default-mobile.handlebars->9->4"
2156 - ]
2431 + ],
2432 + "pt": "Conectado"
2433 },
2434 {
2435 "en": "Connected.",
2436 "cs": "Připojeno.",
2437 "xloc": [
2438 "messenger.handlebars->13->7"
2163 - ]
2439 + ],
2440 + "pt": "Conectado."
2441 },
2442 {
2443 "en": "Connecting...",
@@ -2173,31 +2450,36 @@
2450 "default-mobile.handlebars->9->2",
2451 "default-mobile.handlebars->9->6",
2452 "default-mobile.handlebars->9->269"
2176 - ]
2453 + ],
2454 + "pt": "Conectando..."
2455 },
2456 {
2457 "en": "Connection closed.",
2458 "xloc": [
2459 "messenger.handlebars->13->3"
2182 - ]
2460 + ],
2461 + "pt": "Conexão fechada."
2462 },
2463 {
2464 "en": "Connection Count",
2465 "xloc": [
2466 "default.handlebars->23->1257"
2188 - ]
2467 + ],
2468 + "pt": "Contagem de conexões"
2469 },
2470 {
2471 "en": "Connection Relay",
2472 "xloc": [
2473 "default.handlebars->23->1279"
2194 - ]
2474 + ],
2475 + "pt": "Encaminhador de conexão"
2476 },
2477 {
2478 "en": "Connections",
2479 "xloc": [
2480 "default.handlebars->container->column_l->p40->3->1->p40type->1"
2200 - ]
2481 + ],
2482 + "pt": "Conexões"
2483 },
2484 {
2485 "en": "Connectivity",
@@ -2206,7 +2488,8 @@
2488 "default.handlebars->23->161",
2489 "default.handlebars->23->471",
2490 "default-mobile.handlebars->9->192"
2209 - ]
2491 + ],
2492 + "pt": "Conectividade"
2493 },
2494 {
2495 "en": "Console",
@@ -2215,26 +2498,30 @@
2498 "default.handlebars->contextMenu->cxconsole",
2499 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevConsole",
2500 "default.handlebars->container->topbar->1->1->ServerSubMenuSpan->ServerSubMenu->1->0->ServerConsole"
2218 - ]
2501 + ],
2502 + "pt": "Console"
2503 },
2504 {
2505 "en": "Console - ",
2506 "cs": "Konzole - ",
2507 "xloc": [
2508 "default.handlebars->23->389"
2225 - ]
2509 + ],
2510 + "pt": "Console - "
2511 },
2512 {
2513 "en": "console.txt",
2514 "xloc": [
2515 "default.handlebars->23->655"
2231 - ]
2516 + ],
2517 + "pt": "console.txt"
2518 },
2519 {
2520 "en": "Cookie encoder",
2521 "xloc": [
2522 "default.handlebars->23->1267"
2237 - ]
2523 + ],
2524 + "pt": "Codificador de cookies"
2525 },
2526 {
2527 "en": "Copy",
@@ -2244,14 +2531,16 @@
2531 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
2532 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3",
2533 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3"
2247 - ]
2534 + ],
2535 + "pt": "Copiar"
2536 },
2537 {
2538 "en": "copy",
2539 "xloc": [
2540 "default.handlebars->23->1116",
2541 "default-mobile.handlebars->9->86"
2254 - ]
2542 + ],
2543 + "pt": "Copiar"
2544 },
2545 {
2546 "en": "Copy address to clipboard",
@@ -2261,13 +2550,15 @@
2550 "default.handlebars->23->65",
2551 "default.handlebars->23->67",
2552 "default.handlebars->23->69"
2264 - ]
2553 + ],
2554 + "pt": "Copiar endereço para a área de transferência"
2555 },
2556 {
2557 "en": "Copy link to clipboard",
2558 "xloc": [
2559 "default.handlebars->23->276"
2270 - ]
2560 + ],
2561 + "pt": "Copiar link para a área de transferência"
2562 },
2563 {
2564 "en": "Copy MAC address to clipboard",
@@ -2275,21 +2566,24 @@
2566 "xloc": [
2567 "default.handlebars->23->63",
2568 "default.handlebars->23->71"
2278 - ]
2569 + ],
2570 + "pt": "Copiar endereço MAC para a área de transferência"
2571 },
2572 {
2573 "en": "Copy MacOS agent URL to clipboard",
2574 "cs": "Kopírovat odkaz pro MacOS agenta do schránky",
2575 "xloc": [
2576 "default.handlebars->23->301"
2285 - ]
2577 + ],
2578 + "pt": "Copiar o URL do agente MacOS para a área de transferência"
2579 },
2580 {
2581 "en": "Copy name to clipboard",
2582 "cs": "Zkopírovat jméno do schránky",
2583 "xloc": [
2584 "default.handlebars->23->61"
2292 - ]
2585 + ],
2586 + "pt": "Copiar nome para a área de transferência"
2587 },
2588 {
2589 "en": "Copy to clipboard",
@@ -2297,86 +2591,99 @@
2591 "xloc": [
2592 "agentinvite.handlebars->container->column_l->5->linuxtab",
2593 "agentinvite.handlebars->container->column_l->5->linuxtab"
2300 - ]
2594 + ],
2595 + "pt": "Copiar para área de transferência"
2596 },
2597 {
2598 "en": "Copy valid codes to clipboard",
2599 "xloc": [
2600 "default.handlebars->23->101"
2306 - ]
2601 + ],
2602 + "pt": "Copiar códigos válidos para a área de transferência"
2603 },
2604 {
2605 "en": "Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.",
2606 "xloc": [
2607 "terms.handlebars->container->column_l->27->1",
2608 "terms-mobile.handlebars->container->page_content->column_l->27->1"
2313 - ]
2609 + ],
2610 + "pt": "Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados."
2611 },
2612 {
2613 "en": "Copyright (c) 2009, CodePlex Foundation. All rights reserved.",
2614 "xloc": [
2615 "terms.handlebars->container->column_l->11->1",
2616 "terms-mobile.handlebars->container->page_content->column_l->11->1"
2320 - ]
2617 + ],
2618 + "pt": "Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados."
2619 },
2620 {
2621 "en": "Copyright (c) 2010 Wojciech 'RRH' Ryrych",
2622 "xloc": [
2623 "terms.handlebars->container->column_l->69->1",
2624 "terms-mobile.handlebars->container->page_content->column_l->69->1"
2327 - ]
2625 + ],
2626 + "pt": "Copyright (c) 2010 Wojciech 'RRH' Ryrych"
2627 },
2628 {
2629 "en": "Copyright (C) 2011 Joel Martin This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.",
2630 "xloc": [
2631 "terms.handlebars->container->column_l->63->1",
2632 "terms-mobile.handlebars->container->page_content->column_l->63->1"
2334 - ]
2633 + ],
2634 + "pt": "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 /."
2635 },
2636 {
2637 "en": "Copyright 2013 jQuery Foundation and other contributors",
2638 "xloc": [
2639 "terms.handlebars->container->column_l->47->1",
2640 "terms-mobile.handlebars->container->page_content->column_l->47->1"
2341 - ]
2641 + ],
2642 + "pt": "Copyright 2013 jQuery Foundation e outros colaboradores"
2643 },
2644 {
2645 "en": "Copyright 2013 jQuery Foundation and other contributors,",
2646 "xloc": [
2647 "terms.handlebars->container->column_l->53->1",
2648 "terms-mobile.handlebars->container->page_content->column_l->53->1"
2348 - ]
2649 + ],
2650 + "pt": "Copyright 2013 jQuery Foundation e outros colaboradores,"
2651 },
2652 {
2653 "en": "Core Server",
2654 "xloc": [
2655 "default.handlebars->23->1266"
2354 - ]
2656 + ],
2657 + "pt": "Servidor Core"
2658 },
2659 {
2660 "en": "Corsican",
2661 "xloc": [
2662 "default.handlebars->23->719"
2360 - ]
2663 + ],
2664 + "pt": "Corso"
2665 },
2666 {
2667 "en": "CPU load in the last 15 minutes",
2668 "xloc": [
2669 "default.handlebars->23->1253"
2366 - ]
2670 + ],
2671 + "pt": "Carga da CPU nos últimos 15 minutos"
2672 },
2673 {
2674 "en": "CPU load in the last 5 minutes",
2675 "xloc": [
2676 "default.handlebars->23->1252"
2372 - ]
2677 + ],
2678 + "pt": "Carga da CPU nos últimos 5 minutos"
2679 },
2680 {
2681 "en": "CPU load in the last minute",
2682 "cs": "CPU zatížení v poslední minutě",
2683 "xloc": [
2684 "default.handlebars->23->1251"
2379 - ]
2685 + ],
2686 + "pt": "Carga da CPU no último minuto"
2687 },
2688 {
2689 "en": "CR+LF",
@@ -2384,21 +2691,24 @@
2691 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
2692 "default.handlebars->23->599",
2693 "default.handlebars->23->608"
2387 - ]
2694 + ],
2695 + "pt": "CR + LF"
2696 },
2697 {
2698 "en": "Create a new device group using the options below.",
2699 "cs": "Vytvořit novou skupinu zařízení podle nastavení níže.",
2700 "xloc": [
2701 "default.handlebars->23->910"
2394 - ]
2702 + ],
2703 + "pt": "Crie um novo grupo de dispositivos usando as opções abaixo."
2704 },
2705 {
2706 "en": "Create a new group of devices.",
2707 "cs": "Vytvořit novou skupinu zařízení.",
2708 "xloc": [
2709 "default.handlebars->23->168"
2401 - ]
2710 + ],
2711 + "pt": "Crie um novo grupo de dispositivos."
2712 },
2713 {
2714 "en": "Create Account",
@@ -2406,20 +2716,23 @@
2716 "default.handlebars->23->1180",
2717 "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->12->1->1",
2718 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->12->1->1"
2409 - ]
2719 + ],
2720 + "pt": "Criar conta"
2721 },
2722 {
2723 "en": "Create Device Group",
2724 "cs": "Vytvořit skupinu zařízení",
2725 "xloc": [
2726 "default-mobile.handlebars->9->58"
2416 - ]
2727 + ],
2728 + "pt": "Criar grupo de dispositivo"
2729 },
2730 {
2731 "en": "Create many accounts at once by importing a JSON file with the following format:",
2732 "xloc": [
2733 "default.handlebars->23->1152"
2422 - ]
2734 + ],
2735 + "pt": "Crie várias contas ao mesmo tempo importando um arquivo JSON com o seguinte formato:"
2736 },
2737 {
2738 "en": "Create one",
@@ -2427,77 +2740,89 @@
2740 "xloc": [
2741 "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->newAccountDiv->1",
2742 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->newAccountDiv->1"
2430 - ]
2743 + ],
2744 + "pt": "Crie um"
2745 },
2746 {
2747 "en": "Creation",
2748 "xloc": [
2749 "default.handlebars->23->1209"
2436 - ]
2750 + ],
2751 + "pt": "Criação"
2752 },
2753 {
2754 "en": "Creation Token:",
2755 "xloc": [
2756 "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->newAccountPass->nuToken",
2757 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->newAccountPass->1"
2443 - ]
2758 + ],
2759 + "pt": "Token de criação"
2760 },
2761 {
2762 "en": "Cree",
2763 "xloc": [
2764 "default.handlebars->23->720"
2449 - ]
2765 + ],
2766 + "pt": "Cree"
2767 },
2768 {
2769 "en": "Croatian",
2770 "xloc": [
2771 "default.handlebars->23->721"
2455 - ]
2772 + ],
2773 + "pt": "Croata"
2774 },
2775 {
2776 "en": "CSV Format",
2777 "xloc": [
2778 "default.handlebars->23->1123",
2779 "default.handlebars->23->1161"
2462 - ]
2780 + ],
2781 + "pt": "Formato CSV"
2782 },
2783 {
2784 "en": "Ctl-C",
2785 "xloc": [
2786 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3"
2468 - ]
2787 + ],
2788 + "pt": "CTRL-C"
2789 },
2790 {
2791 "en": "Ctl-X",
2792 "xloc": [
2793 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3"
2474 - ]
2794 + ],
2795 + "pt": "CTRL-X"
2796 },
2797 {
2798 "en": "Ctrl",
2799 "xloc": [
2800 "default.handlebars->23->15"
2480 - ]
2801 + ],
2802 + "pt": "CTRL"
2803 },
2804 {
2805 "en": "Ctrl+Alt+Del",
2806 "xloc": [
2807 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->1",
2808 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->1"
2487 - ]
2809 + ],
2810 + "pt": "CTRL+ALT+DEL"
2811 },
2812 {
2813 "en": "Ctrl-W",
2814 "xloc": [
2815 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->19",
2816 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->21"
2494 - ]
2817 + ],
2818 + "pt": "CTRL-W"
2819 },
2820 {
2821 "en": "Current Version",
2822 "xloc": [
2823 "default.handlebars->23->74"
2500 - ]
2824 + ],
2825 + "pt": "Versão Atual"
2826 },
2827 {
2828 "en": "Cut",
@@ -2507,52 +2832,60 @@
2832 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
2833 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3",
2834 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3"
2510 - ]
2835 + ],
2836 + "pt": "Cortar"
2837 },
2838 {
2839 "en": "Czech",
2840 "xloc": [
2841 "default.handlebars->23->722"
2516 - ]
2842 + ],
2843 + "pt": "Tcheco"
2844 },
2845 {
2846 "en": "Danish",
2847 "xloc": [
2848 "default.handlebars->23->723"
2522 - ]
2849 + ],
2850 + "pt": "Dinamarquês"
2851 },
2852 {
2853 "en": "DataChannel",
2854 "xloc": [
2855 "default.handlebars->23->568"
2528 - ]
2856 + ],
2857 + "pt": "DataChannel"
2858 },
2859 {
2860 "en": "Dates & Time",
2861 "cs": "Datum & čas",
2862 "xloc": [
2863 "default.handlebars->23->879"
2535 - ]
2864 + ],
2865 + "pt": "Datas e Horário"
2866 },
2867 {
2868 "en": "Day",
2869 "cs": "Den",
2870 "xloc": [
2871 "default.handlebars->23->521"
2542 - ]
2872 + ],
2873 + "pt": "Dia"
2874 },
2875 {
2876 "en": "Deactivate Client Control Mode (CCM)",
2877 "xloc": [
2878 "default.handlebars->23->997"
2548 - ]
2879 + ],
2880 + "pt": "Desativar o modo de controle do cliente (CCM)"
2881 },
2882 {
2883 "en": "Deep Sleep",
2884 "xloc": [
2885 "default.handlebars->23->320",
2886 "default-mobile.handlebars->9->107"
2555 - ]
2887 + ],
2888 + "pt": "Deep Sleep"
2889 },
2890 {
2891 "en": "Delete",
@@ -2568,7 +2901,8 @@
2901 "default-mobile.handlebars->9->78",
2902 "default-mobile.handlebars->9->246",
2903 "player.htm->p11->dialog->idx_dlgButtonBar->5"
2571 - ]
2904 + ],
2905 + "pt": "Deletar"
2906 },
2907 {
2908 "en": "Delete Account",
@@ -2576,7 +2910,8 @@
2910 "xloc": [
2911 "default.handlebars->23->895",
2912 "default-mobile.handlebars->9->40"
2579 - ]
2913 + ],
2914 + "pt": "Deletar Conta"
2915 },
2916 {
2917 "en": "Delete account",
@@ -2584,7 +2919,8 @@
2919 "xloc": [
2920 "default.handlebars->container->column_l->p2->p2AccountActions->3->17",
2921 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->7->0"
2587 - ]
2922 + ],
2923 + "pt": "Deletar conta"
2924 },
2925 {
2926 "en": "Delete Device",
@@ -2592,13 +2928,15 @@
2928 "xloc": [
2929 "default.handlebars->23->482",
2930 "default-mobile.handlebars->9->196"
2595 - ]
2931 + ],
2932 + "pt": "Excluir dispositivo"
2933 },
2934 {
2935 "en": "Delete devices",
2936 "xloc": [
2937 "default.handlebars->23->356"
2601 - ]
2938 + ],
2939 + "pt": "Excluir Dispositivos"
2940 },
2941 {
2942 "en": "Delete Group",
@@ -2608,7 +2946,8 @@
2946 "default.handlebars->23->1020",
2947 "default-mobile.handlebars->9->282",
2948 "default-mobile.handlebars->9->285"
2611 - ]
2949 + ],
2950 + "pt": "Excluir grupo"
2951 },
2952 {
2953 "en": "Delete Node",
@@ -2616,14 +2955,16 @@
2955 "xloc": [
2956 "default.handlebars->23->547",
2957 "default-mobile.handlebars->9->215"
2619 - ]
2958 + ],
2959 + "pt": "Excluir nó"
2960 },
2961 {
2962 "en": "Delete Nodes",
2963 "cs": "Smazat nody",
2964 "xloc": [
2965 "default.handlebars->23->361"
2626 - ]
2966 + ],
2967 + "pt": "Excluir nós"
2968 },
2969 {
2970 "en": "Delete selected item?",
@@ -2633,14 +2974,16 @@
2974 "default.handlebars->23->1109",
2975 "default-mobile.handlebars->9->80",
2976 "default-mobile.handlebars->9->248"
2636 - ]
2977 + ],
2978 + "pt": "Excluir item selecionado?"
2979 },
2980 {
2981 "en": "Delete User {0}",
2982 "cs": "Smazat uživatele {0}",
2983 "xloc": [
2984 "default.handlebars->23->1242"
2643 - ]
2985 + ],
2986 + "pt": "Excluir usuário {0}"
2987 },
2988 {
2989 "en": "Delete {0} selected items?",
@@ -2650,14 +2993,16 @@
2993 "default.handlebars->23->1108",
2994 "default-mobile.handlebars->9->79",
2995 "default-mobile.handlebars->9->247"
2653 - ]
2996 + ],
2997 + "pt": "Excluir {0} itens selecionados?"
2998 },
2999 {
3000 "en": "Delete {0}?",
3001 "cs": "Smazat {0}?",
3002 "xloc": [
3003 "default-mobile.handlebars->9->216"
2660 - ]
3004 + ],
3005 + "pt": "Excluir {0}?"
3006 },
3007 {
3008 "en": "Descend by date",
@@ -2666,7 +3011,8 @@
3011 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->11",
3012 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->11",
3013 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->11"
2669 - ]
3014 + ],
3015 + "pt": "Descrescente por data"
3016 },
3017 {
3018 "en": "Descend by name",
@@ -2675,7 +3021,8 @@
3021 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->7",
3022 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->7",
3023 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->7"
2678 - ]
3024 + ],
3025 + "pt": "Decrescente por nome"
3026 },
3027 {
3028 "en": "Descend by size",
@@ -2684,7 +3031,8 @@
3031 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->9",
3032 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->9",
3033 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->9"
2687 - ]
3034 + ],
3035 + "pt": "Decrescente por tamanho"
3036 },
3037 {
3038 "en": "Description",
@@ -2704,13 +3052,15 @@
3052 "default-mobile.handlebars->9->221",
3053 "default-mobile.handlebars->9->274",
3054 "default-mobile.handlebars->9->287"
2707 - ]
3055 + ],
3056 + "pt": "Descrição"
3057 },
3058 {
3059 "en": "DeskControl",
3060 "xloc": [
3061 "default.handlebars->23->596"
2713 - ]
3062 + ],
3063 + "pt": "DeskControl"
3064 },
3065 {
3066 "en": "Desktop",
@@ -2720,37 +3070,43 @@
3070 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevDesktop",
3071 "default.handlebars->23->366",
3072 "default.handlebars->23->1024"
2723 - ]
3073 + ],
3074 + "pt": "Área de Trabalho"
3075 },
3076 {
3077 "en": "Desktop -",
3078 "xloc": [
3079 "default.handlebars->container->column_l->p11->p11title->p11deviceNameHeader->5"
2729 - ]
3080 + ],
3081 + "pt": "Área de Trabalho - "
3082 },
3083 {
3084 "en": "Desktop Notify",
3085 "xloc": [
3086 "default.handlebars->23->949"
2735 - ]
3087 + ],
3088 + "pt": "Notificação na área de trabalho"
3089 },
3090 {
3091 "en": "Desktop Prompt",
3092 "xloc": [
3093 "default.handlebars->23->948"
2741 - ]
3094 + ],
3095 + "pt": "Prompt da área de trabalho"
3096 },
3097 {
3098 "en": "Desktop Prompt+Toolbar",
3099 "xloc": [
3100 "default.handlebars->23->946"
2747 - ]
3101 + ],
3102 + "pt": "Prompt da área de trabalho + barra de ferramentas"
3103 },
3104 {
3105 "en": "Desktop Toolbar",
3106 "xloc": [
3107 "default.handlebars->23->947"
2753 - ]
3108 + ],
3109 + "pt": "Barra de ferramentas da área de trabalho"
3110 },
3111 {
3112 "en": "Desktops",
@@ -2758,28 +3114,32 @@
3114 "xloc": [
3115 "default.handlebars->container->column_l->p1->devListToolbarViewIcons",
3116 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarView->viewselect->5"
2761 - ]
3117 + ],
3118 + "pt": "Áreas de trabalho"
3119 },
3120 {
3121 "en": "Details",
3122 "cs": "Detaily",
3123 "xloc": [
3124 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevInfo"
2768 - ]
3125 + ],
3126 + "pt": "Detalhes"
3127 },
3128 {
3129 "en": "Details -",
3130 "cs": "Detaily -",
3131 "xloc": [
3132 "default.handlebars->container->column_l->p17->p17title->3"
2775 - ]
3133 + ],
3134 + "pt": "Detalhes - "
3135 },
3136 {
3137 "en": "Device",
3138 "cs": "Zařízení",
3139 "xloc": [
3140 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->5"
2782 - ]
3141 + ],
3142 + "pt": "Dispositivo"
3143 },
3144 {
3145 "en": "Device Action",
@@ -2787,25 +3147,29 @@
3147 "xloc": [
3148 "default.handlebars->23->520",
3149 "default-mobile.handlebars->9->208"
2790 - ]
3150 + ],
3151 + "pt": "Ação do dispositivo"
3152 },
3153 {
3154 "en": "Device connections.",
3155 "xloc": [
3156 "default.handlebars->23->883"
2796 - ]
3157 + ],
3158 + "pt": "Conexões de dispositivos."
3159 },
3160 {
3161 "en": "Device disconnections.",
3162 "xloc": [
3163 "default.handlebars->23->884"
2802 - ]
3164 + ],
3165 + "pt": "Desconexões de dispositivos."
3166 },
3167 {
3168 "en": "Device group notes can be viewed and changed by other device group administrators.",
3169 "xloc": [
3170 "default.handlebars->23->509"
2808 - ]
3171 + ],
3172 + "pt": "As notas do grupo de dispositivos podem ser visualizadas e alteradas por outros administradores do grupo de dispositivos."
3173 },
3174 {
3175 "en": "Device Group User",
@@ -2813,7 +3177,8 @@
3177 "xloc": [
3178 "default.handlebars->23->1081",
3179 "default-mobile.handlebars->9->328"
2816 - ]
3180 + ],
3181 + "pt": "Usuário do grupo de dispositivos"
3182 },
3183 {
3184 "en": "Device Groups",
@@ -2822,21 +3187,24 @@
3187 "default.handlebars->container->column_l->p2->9",
3188 "default.handlebars->23->1218",
3189 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->3"
2825 - ]
3190 + ],
3191 + "pt": "Grupos de dispositivos"
3192 },
3193 {
3194 "en": "Device is detected but power state could not be obtained.",
3195 "cs": "Zařízení je detekováno, ale nelze zjistit stav.",
3196 "xloc": [
3197 "default.handlebars->23->325"
2832 - ]
3198 + ],
3199 + "pt": "O dispositivo foi detectado, mas não foi possível obter o estado de energia."
3200 },
3201 {
3202 "en": "Device is hibernating (S4)",
3203 "xloc": [
3204 "default.handlebars->23->331",
3205 "default-mobile.handlebars->9->115"
2839 - ]
3206 + ],
3207 + "pt": "O dispositivo está hibernando (S4)"
3208 },
3209 {
3210 "en": "Device is in deep sleep state (S3)",
@@ -2844,27 +3212,31 @@
3212 "xloc": [
3213 "default.handlebars->23->330",
3214 "default-mobile.handlebars->9->114"
2847 - ]
3215 + ],
3216 + "pt": "O dispositivo está no estado de sono profundo (S3)"
3217 },
3218 {
3219 "en": "Device is in deep sleep state (S3).",
3220 "cs": "Zařízení je v hlubokém spánku (S3).",
3221 "xloc": [
3222 "default.handlebars->23->319"
2854 - ]
3223 + ],
3224 + "pt": "O dispositivo está no estado de suspensão profunda (S3)."
3225 },
3226 {
3227 "en": "Device is in hibernating state (S4).",
3228 "xloc": [
3229 "default.handlebars->23->321"
2860 - ]
3230 + ],
3231 + "pt": "O dispositivo está no estado de hibernação (S4)."
3232 },
3233 {
3234 "en": "Device is in powered off state (S5).",
3235 "cs": "Zařízení je vypnuto (S5).",
3236 "xloc": [
3237 "default.handlebars->23->323"
2867 - ]
3238 + ],
3239 + "pt": "O dispositivo está no estado desligado (S5)."
3240 },
3241 {
3242 "en": "Device is in sleep state (S1)",
@@ -2872,33 +3244,38 @@
3244 "xloc": [
3245 "default.handlebars->23->328",
3246 "default-mobile.handlebars->9->112"
2875 - ]
3247 + ],
3248 + "pt": "O dispositivo está no estado de suspensão (S1)"
3249 },
3250 {
3251 "en": "Device is in sleep state (S1).",
3252 "xloc": [
3253 "default.handlebars->23->315"
2881 - ]
3254 + ],
3255 + "pt": "O dispositivo está no estado de suspensão (S1)."
3256 },
3257 {
3258 "en": "Device is in sleep state (S2)",
3259 "xloc": [
3260 "default.handlebars->23->329",
3261 "default-mobile.handlebars->9->113"
2888 - ]
3262 + ],
3263 + "pt": "O dispositivo está no estado de suspensão (S2)"
3264 },
3265 {
3266 "en": "Device is in sleep state (S2).",
3267 "xloc": [
3268 "default.handlebars->23->317"
2894 - ]
3269 + ],
3270 + "pt": "O dispositivo está no estado de suspensão (S2)."
3271 },
3272 {
3273 "en": "Device is in soft-off state (S5)",
3274 "xloc": [
3275 "default.handlebars->23->332",
3276 "default-mobile.handlebars->9->116"
2901 - ]
3277 + ],
3278 + "pt": "O dispositivo está no estado soft-off (S5)"
3279 },
3280 {
3281 "en": "Device is powered",
@@ -2906,33 +3283,38 @@
3283 "xloc": [
3284 "default.handlebars->23->327",
3285 "default-mobile.handlebars->9->111"
2909 - ]
3286 + ],
3287 + "pt": "O dispositivo está ligado"
3288 },
3289 {
3290 "en": "Device is powered on.",
3291 "xloc": [
3292 "default.handlebars->23->313"
2915 - ]
3293 + ],
3294 + "pt": "O dispositivo está ligado."
3295 },
3296 {
3297 "en": "Device is present, but power state cannot be determined",
3298 "xloc": [
3299 "default.handlebars->23->333",
3300 "default-mobile.handlebars->9->117"
2922 - ]
3301 + ],
3302 + "pt": "O dispositivo está presente, mas o estado de energia não pode ser determinado"
3303 },
3304 {
3305 "en": "Device Location",
3306 "xloc": [
3307 "default.handlebars->23->548"
2928 - ]
3308 + ],
3309 + "pt": "Localização do dispositivo"
3310 },
3311 {
3312 "en": "Device name",
3313 "cs": "Název zařízení",
3314 "xloc": [
3315 "default.handlebars->23->379"
2935 - ]
3316 + ],
3317 + "pt": "Nome do dispositivo"
3318 },
3319 {
3320 "en": "Device Name",
@@ -2941,31 +3323,36 @@
3323 "default.handlebars->23->562",
3324 "default-mobile.handlebars->9->219",
3325 "player.htm->3->9"
2944 - ]
3326 + ],
3327 + "pt": "Nome do Dispositivo"
3328 },
3329 {
3330 "en": "Device Notification",
3331 "xloc": [
3332 "default.handlebars->23->511"
2950 - ]
3333 + ],
3334 + "pt": "Notificação de dispositivo"
3335 },
3336 {
3337 "en": "Device Toast",
3338 "xloc": [
3339 "default-mobile.handlebars->9->201"
2956 - ]
3340 + ],
3341 + "pt": "Brinde do dispositivo"
3342 },
3343 {
3344 "en": "DeviceCheckbox",
3345 "xloc": [
3346 "default.handlebars->23->358"
2962 - ]
3347 + ],
3348 + "pt": "Caixa de seleção do dispositivo"
3349 },
3350 {
3351 "en": "Disabled",
3352 "xloc": [
3353 "default.handlebars->23->456"
2968 - ]
3354 + ],
3355 + "pt": "Desativado"
3356 },
3357 {
3358 "en": "Disconnect",
@@ -2976,13 +3363,15 @@
3363 "default.handlebars->23->959",
3364 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3",
3365 "default-mobile.handlebars->9->234"
2979 - ]
3366 + ],
3367 + "pt": "Desconectar"
3368 },
3369 {
3370 "en": "Disconnect All",
3371 "xloc": [
3372 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar"
2985 - ]
3373 + ],
3374 + "pt": "Desconectar todos"
3375 },
3376 {
3377 "en": "Disconnected",
@@ -3000,32 +3389,37 @@
3389 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3->deskstatus",
3390 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3->p13Status",
3391 "default-mobile.handlebars->9->1"
3003 - ]
3392 + ],
3393 + "pt": "Desconectado"
3394 },
3395 {
3396 "en": "Display a notification on the remote computer",
3397 "xloc": [
3398 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1"
3009 - ]
3399 + ],
3400 + "pt": "Exibir uma notificação no computador remoto"
3401 },
3402 {
3403 "en": "Display name",
3404 "xloc": [
3405 "default.handlebars->23->582"
3015 - ]
3406 + ],
3407 + "pt": "Mostrar nome"
3408 },
3409 {
3410 "en": "DNS suffix",
3411 "xloc": [
3412 "default.handlebars->23->60"
3021 - ]
3413 + ],
3414 + "pt": "Sufixo DNS"
3415 },
3416 {
3417 "en": "Do nothing",
3418 "cs": "Nic",
3419 "xloc": [
3420 "default.handlebars->23->1003"
3028 - ]
3421 + ],
3422 + "pt": "Fazer nada"
3423 },
3424 {
3425 "en": "Don't have an account?",
@@ -3033,20 +3427,23 @@
3427 "xloc": [
3428 "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->newAccountDiv",
3429 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->newAccountDiv"
3036 - ]
3430 + ],
3431 + "pt": "Não possui uma conta?"
3432 },
3433 {
3434 "en": "Don\\'t configure",
3435 "xloc": [
3436 "default.handlebars->23->1007",
3437 "default.handlebars->23->1012"
3043 - ]
3438 + ],
3439 + "pt": "Não configure"
3440 },
3441 {
3442 "en": "Don\\'t connect to server",
3443 "xloc": [
3444 "default.handlebars->23->1008"
3049 - ]
3445 + ],
3446 + "pt": "Não conecte ao servidor"
3447 },
3448 {
3449 "en": "Download",
@@ -3054,25 +3451,29 @@
3451 "fr": "Télécharger",
3452 "xloc": [
3453 "download.handlebars->container->page_content->column_l->1"
3057 - ]
3454 + ],
3455 + "pt": "Baixar"
3456 },
3457 {
3458 "en": "Download console text",
3459 "xloc": [
3460 "default.handlebars->container->column_l->p15->consoleTable->1->0->1->1"
3063 - ]
3461 + ],
3462 + "pt": "Baixar do texto do console"
3463 },
3464 {
3465 "en": "Download data points (.csv)",
3466 "xloc": [
3467 "default.handlebars->container->column_l->p40->3->1"
3069 - ]
3468 + ],
3469 + "pt": "Baixar pontos de dados (.csv)"
3470 },
3471 {
3472 "en": "Download error log",
3473 "xloc": [
3474 "default.handlebars->23->82"
3075 - ]
3475 + ],
3476 + "pt": "Baixar log de erro"
3477 },
3478 {
3479 "en": "Download Events",
@@ -3080,7 +3481,8 @@
3481 "default.handlebars->container->column_l->p3->3->1->0->3->3",
3482 "default.handlebars->container->column_l->p16->3->1->0->5->3",
3483 "default.handlebars->container->column_l->p31->5->1->0->5->3"
3083 - ]
3484 + ],
3485 + "pt": "Download de Eventos"
3486 },
3487 {
3488 "en": "Download File",
@@ -3088,25 +3490,29 @@
3490 "xloc": [
3491 "default.handlebars->23->641",
3492 "default-mobile.handlebars->9->267"
3091 - ]
3493 + ],
3494 + "pt": "⇬ Fazer download do arquivo"
3495 },
3496 {
3497 "en": "Download MeshCentral Router, a TCP port mapping tool.",
3498 "xloc": [
3499 "default.handlebars->23->172"
3097 - ]
3500 + ],
3501 + "pt": "Faça o download do MeshCentral Router, uma ferramenta de mapeamento de portas TCP."
3502 },
3503 {
3504 "en": "Download MeshCmd",
3505 "xloc": [
3506 "default.handlebars->23->559"
3103 - ]
3507 + ],
3508 + "pt": "Baixar MeshCmd"
3509 },
3510 {
3511 "en": "Download MeshCmd, a command line tool that performs many functions.",
3512 "xloc": [
3513 "default.handlebars->23->170"
3109 - ]
3514 + ],
3515 + "pt": "Faça o download do MeshCmd, uma ferramenta de linha de comando que executa muitas funções."
3516 },
3517 {
3518 "en": "Download Plugin",
@@ -3118,94 +3524,109 @@
3524 "en": "Download power events",
3525 "xloc": [
3526 "default.handlebars->23->522"
3121 - ]
3527 + ],
3528 + "pt": "Download de eventos de energia"
3529 },
3530 {
3531 "en": "Download server backup",
3532 "xloc": [
3533 "default.handlebars->container->column_l->p6->p2ServerActions->3->p2ServerActionsBackup->0"
3127 - ]
3534 + ],
3535 + "pt": "Fazer o download do backup do servidor"
3536 },
3537 {
3538 "en": "Download the installer here",
3539 "cs": "Stáhnout instalaci zde",
3540 "xloc": [
3541 "agentinvite.handlebars->container->column_l->5->macostab->3->macosurl"
3134 - ]
3542 + ],
3543 + "pt": "Faça o download do instalador aqui"
3544 },
3545 {
3546 "en": "Download the list of events with one of the file formats below.",
3547 "xloc": [
3548 "default.handlebars->23->1122"
3140 - ]
3549 + ],
3550 + "pt": "Faça o download da lista de eventos com um dos formatos de arquivo abaixo."
3551 },
3552 {
3553 "en": "Download the list of users with one of the file formats below.",
3554 "xloc": [
3555 "default.handlebars->23->1160"
3146 - ]
3556 + ],
3557 + "pt": "Baixe a lista de usuários com um dos formatos de arquivo abaixo."
3558 },
3559 {
3560 "en": "Download the software here",
3561 "xloc": [
3562 "agentinvite.handlebars->container->column_l->5->wintab64->3->win64url",
3563 "agentinvite.handlebars->container->column_l->5->wintab32->3->win32url"
3153 - ]
3564 + ],
3565 + "pt": "Faça o download do software aqui"
3566 },
3567 {
3568 "en": "Download trace (.csv)",
3569 "xloc": [
3570 "default.handlebars->container->column_l->p41->3->1"
3159 - ]
3571 + ],
3572 + "pt": "Rastreio de download (.csv)"
3573 },
3574 {
3575 "en": "Download user information",
3576 "xloc": [
3577 "default.handlebars->container->column_l->p4->3->1->0->3->1->3"
3165 - ]
3578 + ],
3579 + "pt": "Baixar informações do usuário"
3580 },
3581 {
3582 "en": "Drag & drop a .mcrec file or click \\\"Open File...\\\"",
3583 "xloc": [
3584 "player.htm->3->18"
3171 - ]
3585 + ],
3586 + "pt": "Arraste e solte um arquivo .mcrec ou clique em \\\"Abrir arquivo...\\\""
3587 },
3588 {
3589 "en": "Duration",
3590 "xloc": [
3591 "player.htm->3->2"
3177 - ]
3592 + ],
3593 + "pt": "Duração"
3594 },
3595 {
3596 "en": "During activation, the agent will have access to admin password infomation.",
3597 "xloc": [
3598 "default.handlebars->23->1017"
3183 - ]
3599 + ],
3600 + "pt": "Durante a ativação, o agente terá acesso às informações da senha do administrador."
3601 },
3602 {
3603 "en": "Dutch (Belgian)",
3604 "xloc": [
3605 "default.handlebars->23->725"
3189 - ]
3606 + ],
3607 + "pt": "Holandês (belga)"
3608 },
3609 {
3610 "en": "Dutch (Standard)",
3611 "xloc": [
3612 "default.handlebars->23->724"
3195 - ]
3613 + ],
3614 + "pt": "Holandês (padrão)"
3615 },
3616 {
3617 "en": "Edit",
3618 "xloc": [
3619 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3"
3201 - ]
3620 + ],
3621 + "pt": "Editar"
3622 },
3623 {
3624 "en": "Edit Device",
3625 "xloc": [
3626 "default.handlebars->23->567",
3627 "default-mobile.handlebars->9->224"
3208 - ]
3628 + ],
3629 + "pt": "Editar dispositivo"
3630 },
3631 {
3632 "en": "Edit Device Group",
@@ -3217,19 +3638,22 @@
3638 "default-mobile.handlebars->9->288",
3639 "default-mobile.handlebars->9->290",
3640 "default-mobile.handlebars->9->308"
3220 - ]
3641 + ],
3642 + "pt": "Editar grupo de dispositivos"
3643 },
3644 {
3645 "en": "Edit Device Group Features",
3646 "xloc": [
3647 "default.handlebars->23->1035"
3226 - ]
3648 + ],
3649 + "pt": "Editar recursos do grupo de dispositivos"
3650 },
3651 {
3652 "en": "Edit Device Group User Consent",
3653 "xloc": [
3654 "default.handlebars->23->1034"
3232 - ]
3655 + ],
3656 + "pt": "Editar consentimento do usuário do grupo de dispositivos"
3657 },
3658 {
3659 "en": "Edit Device Notes",
@@ -3237,7 +3661,8 @@
3661 "xloc": [
3662 "default.handlebars->23->1053",
3663 "default-mobile.handlebars->9->302"
3240 - ]
3664 + ],
3665 + "pt": "Editar notas do dispositivo"
3666 },
3667 {
3668 "en": "Edit Intel&reg; AMT credentials",
@@ -3246,7 +3671,8 @@
3671 "default.handlebars->23->447",
3672 "default.handlebars->23->529",
3673 "default-mobile.handlebars->9->214"
3249 - ]
3674 + ],
3675 + "pt": "Editar Intel & reg; Credenciais AMT"
3676 },
3677 {
3678 "en": "Edit Notes",
@@ -3254,19 +3680,22 @@
3680 "xloc": [
3681 "default.handlebars->23->1067",
3682 "default-mobile.handlebars->9->315"
3257 - ]
3683 + ],
3684 + "pt": "Editar notas"
3685 },
3686 {
3687 "en": "Edit remote desktop settings",
3688 "xloc": [
3689 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1"
3263 - ]
3690 + ],
3691 + "pt": "Editar configurações da área de trabalho remota"
3692 },
3693 {
3694 "en": "Edit User Device Group Permissions",
3695 "xloc": [
3696 "default.handlebars->23->1058"
3269 - ]
3697 + ],
3698 + "pt": "Editar permissões do grupo de dispositivos do usuário"
3699 },
3700 {
3701 "en": "Email",
@@ -3277,7 +3706,8 @@
3706 "default.handlebars->23->1206",
3707 "default.handlebars->23->1232",
3708 "default-mobile.handlebars->9->34"
3280 - ]
3709 + ],
3710 + "pt": "Email"
3711 },
3712 {
3713 "en": "Email Address Change",
@@ -3285,35 +3715,40 @@
3715 "xloc": [
3716 "default.handlebars->23->891",
3717 "default-mobile.handlebars->9->35"
3288 - ]
3718 + ],
3719 + "pt": "Alteração de endereço de email"
3720 },
3721 {
3722 "en": "Email is verified",
3723 "cs": "Email ověřen",
3724 "xloc": [
3725 "default.handlebars->23->1202"
3295 - ]
3726 + ],
3727 + "pt": "O email foi verificado"
3728 },
3729 {
3730 "en": "Email is verified.",
3731 "cs": "Email je ověřen.",
3732 "xloc": [
3733 "default.handlebars->23->1177"
3302 - ]
3734 + ],
3735 + "pt": "O email foi verificado."
3736 },
3737 {
3738 "en": "Email not verified",
3739 "cs": "Email není ověřen",
3740 "xloc": [
3741 "default.handlebars->23->1203"
3309 - ]
3742 + ],
3743 + "pt": "Email não verificado"
3744 },
3745 {
3746 "en": "Email Verification",
3747 "xloc": [
3748 "default.handlebars->23->889",
3749 "default-mobile.handlebars->9->33"
3316 - ]
3750 + ],
3751 + "pt": "verificação de e-mail"
3752 },
3753 {
3754 "en": "Email:",
@@ -3324,202 +3759,234 @@
3759 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->2->1",
3760 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpanel->1->7->1->0->1",
3761 "login-mobile.handlebars->5->17"
3327 - ]
3762 + ],
3763 + "pt": "Email:"
3764 },
3765 {
3766 "en": "Enable browser notification",
3767 "cs": "Zapnout notifikace v prohlížeči",
3768 "xloc": [
3769 "messenger.handlebars->xtop->1"
3334 - ]
3770 + ],
3771 + "pt": "Ativar notificação do navegador"
3772 },
3773 {
3774 "en": "Enable web notifications",
3775 "cs": "Zapnout notifikace prohlížeče",
3776 "xloc": [
3777 "default.handlebars->container->column_l->p2->p2AccountActions->3->accountEnableNotificationsSpan->0"
3341 - ]
3778 + ],
3779 + "pt": "Ativar notificações da web"
3780 },
3781 {
3782 "en": "Encoding",
3783 "xloc": [
3784 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->3"
3347 - ]
3785 + ],
3786 + "pt": "Codificação"
3787 },
3788 {
3789 "en": "English",
3790 "xloc": [
3791 "default.handlebars->23->726"
3353 - ]
3792 + ],
3793 + "pt": "Inglês"
3794 },
3795 {
3796 "en": "English (Australia)",
3797 "xloc": [
3798 "default.handlebars->23->727"
3359 - ]
3799 + ],
3800 + "pt": "Inglês (Austrália)"
3801 },
3802 {
3803 "en": "English (Belize)",
3804 "xloc": [
3805 "default.handlebars->23->728"
3365 - ]
3806 + ],
3807 + "pt": "Inglês (Belize)"
3808 },
3809 {
3810 "en": "English (Canada)",
3811 "xloc": [
3812 "default.handlebars->23->729"
3371 - ]
3813 + ],
3814 + "pt": "Inglês (Canadá)"
3815 },
3816 {
3817 "en": "English (Ireland)",
3818 "xloc": [
3819 "default.handlebars->23->730"
3377 - ]
3820 + ],
3821 + "pt": "Inglês (Irlanda)"
3822 },
3823 {
3824 "en": "English (Jamaica)",
3825 "xloc": [
3826 "default.handlebars->23->731"
3383 - ]
3827 + ],
3828 + "pt": "Inglês (Jamaica)"
3829 },
3830 {
3831 "en": "English (New Zealand)",
3832 "xloc": [
3833 "default.handlebars->23->732"
3389 - ]
3834 + ],
3835 + "pt": "Inglês (Nova Zelândia)"
3836 },
3837 {
3838 "en": "English (Philippines)",
3839 "xloc": [
3840 "default.handlebars->23->733"
3395 - ]
3841 + ],
3842 + "pt": "Inglês (Filipinas)"
3843 },
3844 {
3845 "en": "English (South Africa)",
3846 "xloc": [
3847 "default.handlebars->23->734"
3401 - ]
3848 + ],
3849 + "pt": "Inglês (África do Sul)"
3850 },
3851 {
3852 "en": "English (Trinidad & Tobago)",
3853 "xloc": [
3854 "default.handlebars->23->735"
3407 - ]
3855 + ],
3856 + "pt": "Inglês (Trinidad Tobago)"
3857 },
3858 {
3859 "en": "English (United Kingdom)",
3860 "fr": "Anglais (Royaume Uni)",
3861 "xloc": [
3862 "default.handlebars->23->736"
3414 - ]
3863 + ],
3864 + "pt": "Inglês (Reino Unido)"
3865 },
3866 {
3867 "en": "English (United States)",
3868 "fr": "Anglais (États Unis)",
3869 "xloc": [
3870 "default.handlebars->23->737"
3421 - ]
3871 + ],
3872 + "pt": "Inglês (Estados Unidos)"
3873 },
3874 {
3875 "en": "English (Zimbabwe)",
3876 "fr": "Anglais (Zimbabwe)",
3877 "xloc": [
3878 "default.handlebars->23->738"
3428 - ]
3879 + ],
3880 + "pt": "Inglês (Zimbábue)"
3881 },
3882 {
3883 "en": "Enter",
3884 "xloc": [
3885 "default.handlebars->23->917",
3886 "default.handlebars->23->918"
3435 - ]
3887 + ],
3888 + "pt": "Entrar"
3889 },
3890 {
3891 "en": "Enter a comma seperate list of administrative realms names.",
3892 "xloc": [
3893 "default.handlebars->23->1181"
3441 - ]
3894 + ],
3895 + "pt": "Insira uma lista separada por vírgulas de nomes de regiões administrativas."
3896 },
3897 {
3898 "en": "Enter a range of IP addresses to scan for Intel AMT devices.",
3899 "xloc": [
3900 "default.handlebars->23->217"
3447 - ]
3901 + ],
3902 + "pt": "Digite um intervalo de endereços IP para procurar dispositivos Intel AMT."
3903 },
3904 {
3905 "en": "Enter text and click OK to remotely type it using a US english keyboard. Make sure to place the remote cursor at the correct position before proceeding.",
3906 "xloc": [
3907 "default.handlebars->23->577"
3453 - ]
3908 + ],
3909 + "pt": "Digite o texto e clique em OK para digitá-lo remotamente usando um teclado em inglês dos EUA.Certifique-se de colocar o cursor remoto na posição correta antes de continuar."
3910 },
3911 {
3912 "en": "Enter the account creation token",
3913 "xloc": [
3914 "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1",
3915 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1"
3460 - ]
3916 + ],
3917 + "pt": "Insira o token de criação da conta"
3918 },
3919 {
3920 "en": "Enter the token here for 2-step login:",
3921 "xloc": [
3922 "default.handlebars->23->85"
3466 - ]
3923 + ],
3924 + "pt": "Digite o token aqui para o login em duas etapas:"
3925 },
3926 {
3927 "en": "Error, Unable to add key.",
3928 "xloc": [
3929 "default.handlebars->23->111"
3472 - ]
3930 + ],
3931 + "pt": "Erro, não foi possível adicionar a chave."
3932 },
3933 {
3934 "en": "ERROR: ",
3935 "fr": "ERREUR:",
3936 "xloc": [
3937 "default.handlebars->23->117"
3479 - ]
3938 + ],
3939 + "pt": "ERRO:"
3940 },
3941 {
3942 "en": "Error: No connection key specified.",
3943 "xloc": [
3944 "messenger.handlebars->13->8"
3485 - ]
3945 + ],
3946 + "pt": "Erro: Nenhuma chave de conexão especificada."
3947 },
3948 {
3949 "en": "ERROR: Unable to add key.",
3950 "fr": "ERREUR: Impossible d'ajouter la clé.",
3951 "xloc": [
3952 "default.handlebars->23->113"
3492 - ]
3953 + ],
3954 + "pt": "ERRO: Não foi possível adicionar a chave."
3955 },
3956 {
3957 "en": "ESC",
3958 "xloc": [
3959 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3"
3498 - ]
3960 + ],
3961 + "pt": "ESC"
3962 },
3963 {
3964 "en": "Esperanto",
3965 "xloc": [
3966 "default.handlebars->23->739"
3504 - ]
3967 + ],
3968 + "pt": "Esperanto"
3969 },
3970 {
3971 "en": "Estonian",
3972 "xloc": [
3973 "default.handlebars->23->740"
3510 - ]
3974 + ],
3975 + "pt": "Estoniano"
3976 },
3977 {
3978 "en": "Event Details",
3979 "xloc": [
3980 "default.handlebars->23->647"
3516 - ]
3981 + ],
3982 + "pt": "Detalhes do evento"
3983 },
3984 {
3985 "en": "Event List Export",
3986 "xloc": [
3987 "default.handlebars->23->1127"
3522 - ]
3988 + ],
3989 + "pt": "Exportação da lista de eventos"
3990 },
3991 {
3992 "en": "Events",
@@ -3529,7 +3996,8 @@
3996 "default.handlebars->contextMenu->cxevents",
3997 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevEvents",
3998 "default.handlebars->container->topbar->1->1->UserSubMenuSpan->UserSubMenu->1->0->UserEvents"
3532 - ]
3999 + ],
4000 + "pt": "Eventos"
4001 },
4002 {
4003 "en": "Events -",
@@ -3537,27 +4005,31 @@
4005 "xloc": [
4006 "default.handlebars->container->column_l->p16->p16title->3",
4007 "default.handlebars->container->column_l->p31->3"
3540 - ]
4008 + ],
4009 + "pt": "Eventos -"
4010 },
4011 {
4012 "en": "eventslist.csv",
4013 "xloc": [
4014 "default.handlebars->23->1124",
4015 "default.handlebars->23->1129"
3547 - ]
4016 + ],
4017 + "pt": "eventslist.csv"
4018 },
4019 {
4020 "en": "eventslist.json",
4021 "xloc": [
4022 "default.handlebars->23->1126",
4023 "default.handlebars->23->1130"
3554 - ]
4024 + ],
4025 + "pt": "eventslist.json"
4026 },
4027 {
4028 "en": "example@email.com",
4029 "xloc": [
4030 "default.handlebars->23->248"
3560 - ]
4031 + ],
4032 + "pt": "example@email.com"
4033 },
4034 {
4035 "en": "Existing account with this email address.",
@@ -3570,19 +4042,22 @@
4042 "en": "Extended Ascii",
4043 "xloc": [
4044 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons"
3573 - ]
4045 + ],
4046 + "pt": "Ascii estendido"
4047 },
4048 {
4049 "en": "Extended ASCII",
4050 "xloc": [
4051 "default.handlebars->23->603"
3579 - ]
4052 + ],
4053 + "pt": "ASCII estendido"
4054 },
4055 {
4056 "en": "Faeroese",
4057 "xloc": [
4058 "default.handlebars->23->741"
3585 - ]
4059 + ],
4060 + "pt": "O servidor remoto retornou um erro: (429) Too Many Requests."
4061 },
4062 {
4063 "en": "Failed",
@@ -3590,14 +4065,16 @@
4065 "fr": "Échoué",
4066 "xloc": [
4067 "default.handlebars->23->49"
3593 - ]
4068 + ],
4069 + "pt": "Falhou"
4070 },
4071 {
4072 "en": "Farsi (Persian)",
4073 "fr": "Farsi (Persan)",
4074 "xloc": [
4075 "default.handlebars->23->742"
3600 - ]
4076 + ],
4077 + "pt": "Persa (persa)"
4078 },
4079 {
4080 "en": "Fast",
@@ -3606,20 +4083,23 @@
4083 "xloc": [
4084 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1",
4085 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->1"
3609 - ]
4086 + ],
4087 + "pt": "Rápido"
4088 },
4089 {
4090 "en": "Features",
4091 "cs": "Funkce",
4092 "xloc": [
4093 "default.handlebars->23->945"
3616 - ]
4094 + ],
4095 + "pt": "Recursos"
4096 },
4097 {
4098 "en": "Fijian",
4099 "xloc": [
4100 "default.handlebars->23->743"
3622 - ]
4101 + ],
4102 + "pt": "Fijiano"
4103 },
4104 {
4105 "en": "File Editor",
@@ -3627,14 +4107,16 @@
4107 "xloc": [
4108 "default.handlebars->23->626",
4109 "default-mobile.handlebars->9->251"
3630 - ]
4110 + ],
4111 + "pt": "Editor de Arquivos"
4112 },
4113 {
4114 "en": "File Selection",
4115 "fr": "Sélection de fichier",
4116 "xloc": [
4117 "default.handlebars->container->dialog->dialogBody->dialog3->d3upload->1"
3637 - ]
4118 + ],
4119 + "pt": "Seleção de arquivo"
4120 },
4121 {
4122 "en": "Files",
@@ -3644,7 +4126,8 @@
4126 "default.handlebars->contextMenu->cxfiles",
4127 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevFiles",
4128 "default.handlebars->23->1031"
3647 - ]
4129 + ],
4130 + "pt": "Arquivos"
4131 },
4132 {
4133 "en": "Files -",
@@ -3652,25 +4135,29 @@
4135 "fr": "Dossiers -",
4136 "xloc": [
4137 "default.handlebars->container->column_l->p13->p13title->3"
3655 - ]
4138 + ],
4139 + "pt": "Arquivos - "
4140 },
4141 {
4142 "en": "Files Notify",
4143 "xloc": [
4144 "default.handlebars->23->953"
3661 - ]
4145 + ],
4146 + "pt": "Notificação arquivos"
4147 },
4148 {
4149 "en": "Files Prompt",
4150 "xloc": [
4151 "default.handlebars->23->952"
3667 - ]
4152 + ],
4153 + "pt": "Arquivos do prompt"
4154 },
4155 {
4156 "en": "FileSystemDriver",
4157 "xloc": [
4158 "default.handlebars->23->585"
3673 - ]
4159 + ],
4160 + "pt": "Driver do sistema de arquivos"
4161 },
4162 {
4163 "en": "Filter",
@@ -3679,14 +4166,16 @@
4166 "xloc": [
4167 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar",
4168 "default.handlebars->container->column_l->p4->3->1->0->3->3"
3682 - ]
4169 + ],
4170 + "pt": "Filtro"
4171 },
4172 {
4173 "en": "Finnish",
4174 "fr": "Finlandais",
4175 "xloc": [
4176 "default.handlebars->23->744"
3689 - ]
4177 + ],
4178 + "pt": "Finlandês"
4179 },
4180 {
4181 "en": "Fixed width interface",
@@ -3697,13 +4186,15 @@
4186 "error404.handlebars->container->topbar->uiMenuButton->uiMenu",
4187 "login.handlebars->container->topbar->uiMenuButton->uiMenu",
4188 "terms.handlebars->container->topbar->uiMenuButton->uiMenu"
3700 - ]
4189 + ],
4190 + "pt": "Interface de largura fixa"
4191 },
4192 {
4193 "en": "Focus All",
4194 "xloc": [
4195 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1"
3706 - ]
4196 + ],
4197 + "pt": "Focus All"
4198 },
4199 {
4200 "en": "Folder",
@@ -3712,14 +4203,16 @@
4203 "xloc": [
4204 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->1",
4205 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->1"
3715 - ]
4206 + ],
4207 + "pt": "Pasta"
4208 },
4209 {
4210 "en": "Force password reset on next login.",
4211 "xloc": [
4212 "default.handlebars->23->1176",
4213 "default.handlebars->23->1239"
3722 - ]
4214 + ],
4215 + "pt": "Forçar redefinição de senha no próximo login."
4216 },
4217 {
4218 "en": "Forgot password?",
@@ -3728,28 +4221,32 @@
4221 "xloc": [
4222 "login.handlebars->5->18",
4223 "login-mobile.handlebars->5->18"
3731 - ]
4224 + ],
4225 + "pt": "Esqueceu a senha?"
4226 },
4227 {
4228 "en": "Forgot user/password?",
4229 "cs": "Zapomenuté jméno/heslo?",
4230 "xloc": [
4231 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->resetAccountDiv->resetAccountSpan"
3738 - ]
4232 + ],
4233 + "pt": "Esqueceu usuário / senha?"
4234 },
4235 {
4236 "en": "Forgot username/password?",
4237 "cs": "Zapomenuté jméno/heslo?",
4238 "xloc": [
4239 "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->resetAccountDiv->resetAccountSpan"
3745 - ]
4240 + ],
4241 + "pt": "Esqueceu seu nome de usuário / senha?"
4242 },
4243 {
4244 "en": "Frame rate",
4245 "cs": "Obnovování",
4246 "xloc": [
4247 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->1"
3752 - ]
4248 + ],
4249 + "pt": "Taxa de quadros"
4250 },
4251 {
4252 "en": "Free",
@@ -3757,84 +4254,96 @@
4254 "xloc": [
4255 "default.handlebars->23->1248",
4256 "default.handlebars->23->1250"
3760 - ]
4257 + ],
4258 + "pt": "Livre"
4259 },
4260 {
4261 "en": "free",
4262 "fr": "libre",
4263 "xloc": [
4264 "default.handlebars->23->1255"
3767 - ]
4265 + ],
4266 + "pt": "Livre"
4267 },
4268 {
4269 "en": "FreeBSD x86-64",
4270 "xloc": [
4271 "default.handlebars->23->430",
4272 "default-mobile.handlebars->9->170"
3774 - ]
4273 + ],
4274 + "pt": "FreeBSD x86-64"
4275 },
4276 {
4277 "en": "French (Belgium)",
4278 "fr": "Français (Belgique)",
4279 "xloc": [
4280 "default.handlebars->23->746"
3781 - ]
4281 + ],
4282 + "pt": "Francês (Bélgica)"
4283 },
4284 {
4285 "en": "French (Canada)",
4286 "fr": "Français (Canada)",
4287 "xloc": [
4288 "default.handlebars->23->747"
3788 - ]
4289 + ],
4290 + "pt": "Francês (Canadá)"
4291 },
4292 {
4293 "en": "French (France)",
4294 "fr": "Français (France)",
4295 "xloc": [
4296 "default.handlebars->23->748"
3795 - ]
4297 + ],
4298 + "pt": "Francês (França)"
4299 },
4300 {
4301 "en": "French (Luxembourg)",
4302 "fr": "Français (Luxembourg)",
4303 "xloc": [
4304 "default.handlebars->23->749"
3802 - ]
4305 + ],
4306 + "pt": "Francês (Luxemburgo)"
4307 },
4308 {
4309 "en": "French (Monaco)",
4310 "fr": "Français (Monaco)",
4311 "xloc": [
4312 "default.handlebars->23->750"
3809 - ]
4313 + ],
4314 + "pt": "Francês (Mônaco)"
4315 },
4316 {
4317 "en": "French (Standard)",
4318 "fr": "Français (standard)",
4319 "xloc": [
4320 "default.handlebars->23->745"
3816 - ]
4321 + ],
4322 + "pt": "Francês (Padrão)"
4323 },
4324 {
4325 "en": "French (Switzerland)",
4326 "fr": "Français (Suisse)",
4327 "xloc": [
4328 "default.handlebars->23->751"
3823 - ]
4329 + ],
4330 + "pt": "Francês (Suíça)"
4331 },
4332 {
4333 "en": "Frisian",
4334 "fr": "Frison",
4335 "xloc": [
4336 "default.handlebars->23->752"
3830 - ]
4337 + ],
4338 + "pt": "Frísio"
4339 },
4340 {
4341 "en": "Friulian",
4342 "fr": "Frioulan",
4343 "xloc": [
4344 "default.handlebars->23->753"
3837 - ]
4345 + ],
4346 + "pt": "Friuliano"
4347 },
4348 {
4349 "en": "Full Administrator",
@@ -3849,7 +4358,8 @@
4358 "default-mobile.handlebars->9->280",
4359 "default-mobile.handlebars->9->289",
4360 "default-mobile.handlebars->9->307"
3852 - ]
4361 + ],
4362 + "pt": "Administrador completo"
4363 },
4364 {
4365 "en": "Full administrator",
@@ -3857,7 +4367,8 @@
4367 "fr": "Administrateur complet",
4368 "xloc": [
4369 "default.handlebars->23->1198"
3860 - ]
4370 + ],
4371 + "pt": "Administrador completo"
4372 },
4373 {
4374 "en": "Full Administrator (all rights)",
@@ -3865,7 +4376,8 @@
4376 "fr": "Administrateur Complet (tous droits)",
4377 "xloc": [
4378 "default.handlebars->23->1059"
3868 - ]
4379 + ],
4380 + "pt": "Administrador Pleno (todos os direitos)"
4381 },
4382 {
4383 "en": "Full Screen. Hold shift to browser full screen.",
@@ -3873,35 +4385,40 @@
4385 "xloc": [
4386 "default.handlebars->container->column_l->p11->p11title->p11deviceNameHeader->devListToolbarViewIcons",
4387 "default.handlebars->container->column_l->p14->p14title->devListToolbarViewIcons"
3876 - ]
4388 + ],
4389 + "pt": "Tela cheia. Mantenha a tecla Shift pressionada no navegador em tela cheia."
4390 },
4391 {
4392 "en": "FYRO Macedonian",
4393 "fr": "ARY Macédonien",
4394 "xloc": [
4395 "default.handlebars->23->790"
3883 - ]
4396 + ],
4397 + "pt": "FYRO Macedonian"
4398 },
4399 {
4400 "en": "Gaelic (Irish)",
4401 "fr": "Gaélique (irlandais)",
4402 "xloc": [
4403 "default.handlebars->23->755"
3890 - ]
4404 + ],
4405 + "pt": "Gaélico (irlandês)"
4406 },
4407 {
4408 "en": "Gaelic (Scots)",
4409 "fr": "Gaélique (écossais)",
4410 "xloc": [
4411 "default.handlebars->23->754"
3897 - ]
4412 + ],
4413 + "pt": "Gaélico (escocês)"
4414 },
4415 {
4416 "en": "Galacian",
4417 "fr": "Galicien",
4418 "xloc": [
4419 "default.handlebars->23->756"
3904 - ]
4420 + ],
4421 + "pt": "Galego"
4422 },
4423 {
4424 "en": "Gateway MAC",
@@ -3909,7 +4426,8 @@
4426 "fr": "Passerelle MAC",
4427 "xloc": [
4428 "default.handlebars->23->70"
3912 - ]
4429 + ],
4430 + "pt": "Gateway MAC"
4431 },
4432 {
4433 "en": "General",
@@ -3920,7 +4438,8 @@
4438 "default.handlebars->container->topbar->1->1->MeshSubMenuSpan->MeshSubMenu->1->0->MeshGeneral",
4439 "default.handlebars->container->topbar->1->1->UserSubMenuSpan->UserSubMenu->1->0->UserGeneral",
4440 "default.handlebars->container->topbar->1->1->ServerSubMenuSpan->ServerSubMenu->1->0->ServerGeneral"
3923 - ]
4441 + ],
4442 + "pt": "Geral"
4443 },
4444 {
4445 "en": "General -",
@@ -3930,7 +4449,8 @@
4449 "default.handlebars->container->column_l->p10->1->1->0->1->p10title->3",
4450 "default.handlebars->container->column_l->p20->5",
4451 "default.handlebars->container->column_l->p30->1->1->0->1->p30title->3"
3933 - ]
4452 + ],
4453 + "pt": "Geral - "
4454 },
4455 {
4456 "en": "General information",
@@ -3938,7 +4458,8 @@
4458 "fr": "Informations générales",
4459 "xloc": [
4460 "default.handlebars->23->365"
3941 - ]
4461 + ],
4462 + "pt": "Informações gerais"
4463 },
4464 {
4465 "en": "Generate New Tokens",
@@ -3946,56 +4467,65 @@
4467 "fr": "Générer de nouveaux jetons",
4468 "xloc": [
4469 "default.handlebars->23->99"
3949 - ]
4470 + ],
4471 + "pt": "Gere novos tokens"
4472 },
4473 {
4474 "en": "Georgian",
4475 "fr": "Géorgien",
4476 "xloc": [
4477 "default.handlebars->23->757"
3956 - ]
4478 + ],
4479 + "pt": "Georgiano"
4480 },
4481 {
4482 "en": "German (Austria)",
4483 "xloc": [
4484 "default.handlebars->23->759"
3962 - ]
4485 + ],
4486 + "pt": "Alemão (Áustria)"
4487 },
4488 {
4489 "en": "German (Germany)",
4490 "xloc": [
4491 "default.handlebars->23->760"
3968 - ]
4492 + ],
4493 + "pt": "Alemão (Alemanha)"
4494 },
4495 {
4496 "en": "German (Liechtenstein)",
4497 "xloc": [
4498 "default.handlebars->23->761"
3974 - ]
4499 + ],
4500 + "pt": "Alemão (Liechtenstein)"
4501 },
4502 {
4503 "en": "German (Luxembourg)",
4504 "xloc": [
4505 "default.handlebars->23->762"
3980 - ]
4506 + ],
4507 + "pt": "Alemão (Luxemburgo)"
4508 },
4509 {
4510 "en": "German (Standard)",
4511 "xloc": [
4512 "default.handlebars->23->758"
3986 - ]
4513 + ],
4514 + "pt": "Alemão (Padrão)"
4515 },
4516 {
4517 "en": "German (Switzerland)",
4518 "xloc": [
4519 "default.handlebars->23->763"
3992 - ]
4520 + ],
4521 + "pt": "Alemão (Suíça)"
4522 },
4523 {
4524 "en": "Get MQTT login credentials for this device.",
4525 "xloc": [
4526 "default.handlebars->23->495"
3998 - ]
4527 + ],
4528 + "pt": "Obtenha credenciais de login do MQTT para este dispositivo."
4529 },
4530 {
4531 "en": "Get started here!",
@@ -4003,7 +4533,8 @@
4533 "xloc": [
4534 "default.handlebars->container->column_l->p2->p2noMeshFound->p2createMeshLink2->1->0",
4535 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3noMeshFound->p3createMeshLink2->1->0"
4006 - ]
4536 + ],
4537 + "pt": "Comece aqui!"
4538 },
4539 {
4540 "en": "Go to main site",
@@ -4011,14 +4542,16 @@
4542 "xloc": [
4543 "error404.handlebars->container->column_l->5->0->0",
4544 "error404-mobile.handlebars->container->page_content->column_l->5->0->0"
4014 - ]
4545 + ],
4546 + "pt": "Ir para o site principal"
4547 },
4548 {
4549 "en": "Good",
4550 "fr": "Bien",
4551 "xloc": [
4552 "default.handlebars->23->920"
4021 - ]
4553 + ],
4554 + "pt": "Bom"
4555 },
4556 {
4557 "en": "Good Password",
@@ -4029,14 +4562,16 @@
4562 "login.handlebars->5->25",
4563 "login-mobile.handlebars->5->21",
4564 "login-mobile.handlebars->5->25"
4032 - ]
4565 + ],
4566 + "pt": "Boa senha"
4567 },
4568 {
4569 "en": "Greek",
4570 "fr": "Grec",
4571 "xloc": [
4572 "default.handlebars->23->764"
4039 - ]
4573 + ],
4574 + "pt": "Grego"
4575 },
4576 {
4577 "en": "Group",
@@ -4046,7 +4581,8 @@
4581 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->1",
4582 "default.handlebars->23->391",
4583 "default-mobile.handlebars->9->131"
4049 - ]
4584 + ],
4585 + "pt": "Grupo"
4586 },
4587 {
4588 "en": "Group Action",
@@ -4055,14 +4591,16 @@
4591 "xloc": [
4592 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar",
4593 "default.handlebars->23->357"
4058 - ]
4594 + ],
4595 + "pt": "Ações do grupo"
4596 },
4597 {
4598 "en": "Group permissions for user {0}.",
4599 "fr": "Autorisations de groupe pour l'utilisateur {0}.",
4600 "xloc": [
4601 "default.handlebars->23->1039"
4065 - ]
4602 + ],
4603 + "pt": "Permissões de grupo para o usuário {0}."
4604 },
4605 {
4606 "en": "Group1, Group2, Group3",
@@ -4070,41 +4608,47 @@
4608 "fr": "Groupe1, Groupe2, Groupe3",
4609 "xloc": [
4610 "default-mobile.handlebars->9->223"
4073 - ]
4611 + ],
4612 + "pt": "Grupo1, Grupo2, Grupo3"
4613 },
4614 {
4615 "en": "Gujurati",
4616 "fr": "Gujarati",
4617 "xloc": [
4618 "default.handlebars->23->765"
4080 - ]
4619 + ],
4620 + "pt": "Gujarati"
4621 },
4622 {
4623 "en": "Haitian",
4624 "fr": "Haïtien",
4625 "xloc": [
4626 "default.handlebars->23->766"
4087 - ]
4627 + ],
4628 + "pt": "Haitiano"
4629 },
4630 {
4631 "en": "Hang up",
4632 "fr": "Raccrocher",
4633 "xloc": [
4634 "messenger.handlebars->xtop->1"
4094 - ]
4635 + ],
4636 + "pt": "Desligar"
4637 },
4638 {
4639 "en": "Hard disconnect agent",
4640 "fr": "Déconnexion forcée de l'agent",
4641 "xloc": [
4642 "default.handlebars->23->663"
4101 - ]
4643 + ],
4644 + "pt": "Forçar desconexão do agente"
4645 },
4646 {
4647 "en": "Hebrew",
4648 "xloc": [
4649 "default.handlebars->23->767"
4107 - ]
4650 + ],
4651 + "pt": "Hebraico"
4652 },
4653 {
4654 "en": "Hibernating",
@@ -4114,13 +4658,15 @@
4658 "default.handlebars->23->322",
4659 "default-mobile.handlebars->9->101",
4660 "default-mobile.handlebars->9->108"
4117 - ]
4661 + ],
4662 + "pt": "Hibernando"
4663 },
4664 {
4665 "en": "Hindi",
4666 "xloc": [
4667 "default.handlebars->23->768"
4123 - ]
4668 + ],
4669 + "pt": "Hindi"
4670 },
4671 {
4672 "en": "Hold on, reset mail sent.",
@@ -4135,35 +4681,40 @@
4681 "xloc": [
4682 "default.handlebars->23->635",
4683 "default-mobile.handlebars->9->260"
4138 - ]
4684 + ],
4685 + "pt": "Mantendo 1 entrada para cópia"
4686 },
4687 {
4688 "en": "Holding 1 entrie for move",
4689 "xloc": [
4690 "default.handlebars->23->639",
4691 "default-mobile.handlebars->9->264"
4145 - ]
4692 + ],
4693 + "pt": "Segurando 1 entrada para mover"
4694 },
4695 {
4696 "en": "Holding {0} entries for copy",
4697 "xloc": [
4698 "default.handlebars->23->633",
4699 "default-mobile.handlebars->9->258"
4152 - ]
4700 + ],
4701 + "pt": "Mantendo {0} entradas para cópia"
4702 },
4703 {
4704 "en": "Holding {0} entries for move",
4705 "xloc": [
4706 "default.handlebars->23->637",
4707 "default-mobile.handlebars->9->262"
4159 - ]
4708 + ],
4709 + "pt": "Manter {0} entradas para mover"
4710 },
4711 {
4712 "en": "Holding {0} entrie{1} for {2}",
4713 "xloc": [
4714 "default.handlebars->23->1115",
4715 "default-mobile.handlebars->9->85"
4166 - ]
4716 + ],
4717 + "pt": "Mantendo {0} entrada {1} para {2}"
4718 },
4719 {
4720 "en": "Hostname",
@@ -4177,41 +4728,47 @@
4728 "default-mobile.handlebars->9->134",
4729 "default-mobile.handlebars->9->136",
4730 "default-mobile.handlebars->9->220"
4180 - ]
4731 + ],
4732 + "pt": "Hostname"
4733 },
4734 {
4735 "en": "Hostname Sync",
4736 "xloc": [
4737 "default.handlebars->23->943"
4186 - ]
4738 + ],
4739 + "pt": "Sincronização de nome de host"
4740 },
4741 {
4742 "en": "http://creativecommons.org/licenses/by/2.0/uk/legalcode",
4743 "xloc": [
4744 "terms.handlebars->container->column_l->75->1->3",
4745 "terms-mobile.handlebars->container->page_content->column_l->75->1->3"
4193 - ]
4746 + ],
4747 + "pt": "http://creativecommons.org/licenses/by/2.0/uk/legalcode"
4748 },
4749 {
4750 "en": "http://jquery.com/",
4751 "xloc": [
4752 "terms.handlebars->container->column_l->47->1->1",
4753 "terms-mobile.handlebars->container->page_content->column_l->47->1->1"
4200 - ]
4754 + ],
4755 + "pt": "http://jquery.com/"
4756 },
4757 {
4758 "en": "http://jqueryui.com/",
4759 "xloc": [
4760 "terms.handlebars->container->column_l->53->1->1",
4761 "terms-mobile.handlebars->container->page_content->column_l->53->1->1"
4207 - ]
4762 + ],
4763 + "pt": "http://jqueryui.com/"
4764 },
4765 {
4766 "en": "http://www.openssl.org/source/license.html",
4767 "xloc": [
4768 "terms.handlebars->container->column_l->25->1->0",
4769 "terms-mobile.handlebars->container->page_content->column_l->25->1->0"
4214 - ]
4770 + ],
4771 + "pt": "http://www.openssl.org/source/license.html"
4772 },
4773 {
4774 "en": "http://www.webtoolkit.info/javascript-base64.html",
@@ -4220,27 +4777,31 @@
4777 "terms.handlebars->container->column_l->75->1->5",

This file is too large to show in full.

views/translations/agentinvite-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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 - Agent Installation</title><style>.tab{overflow:hidden;border:1px solid #ccc;background-color:#f1f1f1}.tab button{background-color:inherit;float:left;border:none;outline:0;cursor:pointer;padding:14px 16px;transition:.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><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><p id=logoutControl style="color:#fff;font-size:11px;margin:10px 10px 0">{{{logoutControl}}}</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.<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:#fff;color:#000><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".<div style=text-align:center><img class=winagent-img src=images/winagent.png></div></div><div id=wintab32 class=tabcontent style=background-color:#fff;color:#000><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".<div style=text-align:center><img class=winagent-img src=images/winagent.png></div></div><div id=linuxtab class=tabcontent style=background-color:#fff;color:#000><h3>Linux</h3><p>Para instalar, recorte e cole o seguinte comando em um terminal raiz.<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.<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:#fff;color:#000><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".<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%><tr><td style=text-align:left><td style=text-align:right></table></div></div><script>"use strict";var linuxInstall,linuxUnInstall,uiMode=parseInt(getstore("uiMode",1)),webPageStackMenu=!1,webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),domain="{{{domain}}}",domainUrl="{{{domainurl}}}",meshid="{{{meshid}}}",serverPort="{{{serverport}}}",serverHttps="{{{serverhttps}}}",serverNoProxy="{{{servernoproxy}}}",installFlags="{{{installflags}}}",groupName=decodeURIComponent("{{{meshname}}}");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 n=localStorage.getItem(e);return null==n||null==n?t:n}catch(e){return t}}function openTab(e,t){var n,s,l;for(s=document.getElementsByClassName("tabcontent"),n=0;n<s.length;n++)s[n].style.display="none";for(l=document.getElementsByClassName("tablinks"),n=0;n<l.length;n++)l[n].className=l[n].className.replace(" active","");document.getElementById(t).style.display="block",null!=e?e.currentTarget.className+=" active":document.getElementById("t"+t).className+=" active"}function setup(){var e=window.location.hostname,t=domainUrl.substring(0,domainUrl.length-1),n="meshagents?id=4&meshid="+meshid;if(0!=installFlags&&(n+="&installflags="+installFlags),Q("win64url").href=n,n="meshagents?id=3&meshid="+meshid,0!=installFlags&&(n+="&installflags="+installFlags),Q("win32url").href=n,n="meshosxagent?id=16&meshid="+meshid,Q("macosurl").href=n,1==serverHttps){var s=443==serverPort?"":":"+serverPort;linuxUnInstall=0==serverNoProxy?(linuxInstall="(wget https://"+e+s+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://'+e+s+t+" '"+meshid+"'\r\n","(wget https://"+e+s+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'):(linuxInstall="wget https://"+e+s+domainUrl+"meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://"+e+s+t+" '"+meshid+"'\r\n","wget https://"+e+s+domainUrl+"meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n")}else{s=80==serverPort?"":":"+serverPort;linuxUnInstall=0==serverNoProxy?(linuxInstall="(wget http://"+e+s+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://'+e+s+t+" '"+meshid+"'\r\n","(wget http://"+e+s+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'):(linuxInstall="wget http://"+e+s+domainUrl+"meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://"+e+s+t+" '"+meshid+"'\r\n","wget http://"+e+s+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),0<=navigator.userAgent.indexOf("Win64")?openTab(null,"wintab64"):0<=navigator.userAgent.indexOf("Windows")?openTab(null,"wintab32"):0<=navigator.userAgent.indexOf("Linux")?openTab(null,"linuxtab"):0<=navigator.userAgent.indexOf("Macintosh")?openTab(null,"macostab"):openTab(null,"wintab64")}function copyToClipLinuxInstall(){copyTextToClip(linuxInstall)}function copyToClipLinuxUnInstall(){copyTextToClip(linuxUnInstall)}function copyTextToClip(e){var t=document.createElement("DIV");t.textContent=e,document.body.appendChild(t),function(e){if(document.selection)(t=document.body.createTextRange()).moveToElementText(e),t.select();else if(window.getSelection){var t;(t=document.createRange()).selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(t)}}(t),document.execCommand("copy"),t.remove()}""!=groupName&&QH("groupname"," for "+groupName),userInterfaceSelectMenu(),setup()</script>
\ No newline at end of file
views/translations/agentinvite_pt.handlebars new
+294
@@ -0,0 +1,294 @@
1 +<!DOCTYPE html><html><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
8 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
9 + <title>MeshCentral - Agent Installation</title>
10 + <style>
11 + .tab {
12 + overflow: hidden;
13 + border: 1px solid #ccc;
14 + background-color: #f1f1f1;
15 + }
16 +
17 + .tab button {
18 + background-color: inherit;
19 + float: left;
20 + border: none;
21 + outline: none;
22 + cursor: pointer;
23 + padding: 14px 16px;
24 + transition: 0.3s;
25 + }
26 +
27 + .tab button:hover {
28 + background-color: #ddd;
29 + }
30 +
31 + .tab button.active {
32 + background-color: #8f8;
33 + }
34 +
35 + .tabcontent {
36 + display: none;
37 + padding: 6px 12px;
38 + border: 1px solid #ccc;
39 + border-top: none;
40 + }
41 +
42 + </style>
43 +</head>
44 +<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
45 + <div id="container">
46 + <!-- Begin Masthead -->
47 + <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;">
48 + <div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
49 + <strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
50 + </div>
51 + <div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
52 + <strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
53 + </div>
54 + <p id="logoutControl" style="color:white;font-size:11px;margin: 10px 10px 0;">{{{logoutControl}}}</p>
55 + </div>
56 + <div id="page_leftbar">
57 + <div style="height:16px"></div>
58 + </div>
59 + <div id="topbar" class="noselect style3" style="height:24px;position:relative">
60 + <div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
61 + ♦
62 + <div id="uiMenu" style="display:none">
63 + <div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
64 + <div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
65 + <div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
66 + <div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
67 + </div>
68 + </div>
69 + </div>
70 + <div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
71 + <h1>Instalação remota do agente<span id="groupname"></span></h1>
72 + <p>
73 + 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.
74 + Siga apenas as instruções abaixo se esse convite for esperado e você sabe quem acessará seu computador.
75 + Selecionando seu sistema operacional e siga as instruções abaixo.
76 + </p>
77 + <div>
78 + <div class="tab">
79 + <button id="twintab64" class="tablinks" onclick="openTab(event, 'wintab64')">Windows 64 Bits</button>
80 + <button id="twintab32" class="tablinks" onclick="openTab(event, 'wintab32')">Windows 32 Bits</button>
81 + <button id="tlinuxtab" class="tablinks" onclick="openTab(event, 'linuxtab')">Linux</button>
82 + <button id="tmacostab" class="tablinks" onclick="openTab(event, 'macostab')">MacOS</button>
83 + </div>
84 +
85 + <div id="wintab64" class="tabcontent" style="background-color:white;color:black">
86 + <h3>Microsoft™ Windows 64 bits</h3>
87 + <p><a id="win64url">Faça o download do software aqui</a>, execute-o e pressione "Install" or "Connect".</p>
88 + <div style="text-align:center">
89 + <img class="winagent-img" src="images/winagent.png">
90 + </div>
91 + </div>
92 +
93 + <div id="wintab32" class="tabcontent" style="background-color:white;color:black">
94 + <h3>Microsoft™ Windows 32 bits</h3>
95 + <p><a id="win32url">Faça o download do software aqui</a>, execute-o e pressione "Install" or "Connect".</p>
96 + <div style="text-align:center">
97 + <img class="winagent-img" src="images/winagent.png">
98 + </div>
99 + </div>
100 +
101 + <div id="linuxtab" class="tabcontent" style="background-color:white;color:black">
102 + <h3>Linux</h3>
103 + <p>Para instalar, recorte e cole o seguinte comando em um terminal raiz.</p>
104 + <div id="linuxinstall" style="font-family:courier,'courier new',monospace;margin-left:30px"></div>
105 + <input type="button" value="Copiar para área de transferência" style="margin-left:30px;margin-top:4px" onclick="copyToClipLinuxInstall()">
106 + <p>Para desinstalar, recorte e cole o seguinte comando como raiz.</p>
107 + <div id="unlinuxinstall" style="font-family:courier,'courier new',monospace;margin-left:30px"></div>
108 + <input type="button" value="Copiar para área de transferência" style="margin-left:30px;margin-top:4px" onclick="copyToClipLinuxUnInstall()">
109 + <br><br>
110 + </div>
111 +
112 + <div id="macostab" class="tabcontent" style="background-color:white;color:black">
113 + <h3>Apple™ MacOS</h3>
114 + <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>
115 + <div style="text-align:center">
116 + <img src="images/macosagent.png">
117 + </div>
118 + </div>
119 + </div>
120 + </div>
121 + <div id="footer">
122 + <table cellpadding="0" cellspacing="10" style="width: 100%">
123 + <tbody><tr>
124 + <td style="text-align:left"></td>
125 + <td style="text-align:right"></td>
126 + </tr>
127 + </tbody></table>
128 + </div>
129 + </div>
130 + <script>
131 + 'use strict';
132 + var uiMode = parseInt(getstore('uiMode', 1));
133 + var webPageStackMenu = false;
134 + var webPageFullScreen = true;
135 + var nightMode = (getstore('_nightMode', '0') == '1');
136 + var domain = '{{{domain}}}';
137 + var domainUrl = '{{{domainurl}}}';
138 + var meshid = '{{{meshid}}}';
139 + var serverPort = '{{{serverport}}}';
140 + var serverHttps = '{{{serverhttps}}}';
141 + var serverNoProxy = '{{{servernoproxy}}}';
142 + var installFlags = '{{{installflags}}}';
143 + var groupName = decodeURIComponent('{{{meshname}}}');
144 + if (groupName != '') { QH('groupname', ' for ' + groupName); }
145 + userInterfaceSelectMenu();
146 + setup();
147 +
148 + // Toggle user interface menu
149 + function showUserInterfaceSelectMenu() {
150 + Q('uiViewButton1').classList.remove('uiSelectorSel');
151 + Q('uiViewButton2').classList.remove('uiSelectorSel');
152 + Q('uiViewButton3').classList.remove('uiSelectorSel');
153 + Q('uiViewButton4').classList.remove('uiSelectorSel');
154 + try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
155 + QV('uiMenu', (QS('uiMenu').display == 'none'));
156 + if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
157 + }
158 +
159 + function userInterfaceSelectMenu(s) {
160 + if (s) { uiMode = s; putstore('uiMode', uiMode); }
161 + webPageFullScreen = (uiMode < 3);
162 + webPageStackMenu = true;//(uiMode > 1);
163 + toggleFullScreen(0);
164 + toggleStackMenu(0);
165 + QC('column_l').add('room4submenu');
166 + }
167 +
168 + function toggleNightMode() {
169 + nightMode = !nightMode;
170 + if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
171 + putstore('_nightMode', nightMode ? '1' : '0');
172 + }
173 +
174 + // Toggle the web page to full screen
175 + function toggleFullScreen(toggle) {
176 + if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
177 + var hide = 0;
178 + //if (args.hide) { hide = parseInt(args.hide); }
179 + if (webPageFullScreen == false) {
180 + QC('body').remove('menu_stack');
181 + QC('body').remove('fullscreen');
182 + QC('body').remove('arg_hide');
183 + //if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
184 + //QV('UserDummyMenuSpan', false);
185 + //QV('page_leftbar', false);
186 + } else {
187 + QC('body').add('fullscreen');
188 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
189 + //QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
190 + //QV('page_leftbar', true);
191 + }
192 + QV('body', true);
193 + }
194 +
195 + // If FullScreen, toggle menu to be horisontal or vertical
196 + function toggleStackMenu(toggle) {
197 + if (webPageFullScreen == true) {
198 + if (toggle === 1) {
199 + webPageStackMenu = !webPageStackMenu;
200 + putstore('webPageStackMenu', webPageStackMenu);
201 + }
202 + if (webPageStackMenu == false) {
203 + QC('body').remove('menu_stack');
204 + } else {
205 + QC('body').add('menu_stack');
206 + //if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
207 + }
208 + }
209 + }
210 +
211 + function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
212 + 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; } }
213 +
214 + function openTab(evt, tabname) {
215 + // Declare all variables
216 + var i, tabcontent, tablinks;
217 +
218 + // Get all elements with class="tabcontent" and hide them
219 + tabcontent = document.getElementsByClassName('tabcontent');
220 + for (i = 0; i < tabcontent.length; i++) {
221 + tabcontent[i].style.display = 'none';
222 + }
223 +
224 + // Get all elements with class="tablinks" and remove the class "active"
225 + tablinks = document.getElementsByClassName('tablinks');
226 + for (i = 0; i < tablinks.length; i++) {
227 + tablinks[i].className = tablinks[i].className.replace(' active', '');
228 + }
229 +
230 + // Show the current tab, and add an "active" class to the button that opened the tab
231 + document.getElementById(tabname).style.display = 'block';
232 + if (evt != null) { evt.currentTarget.className += ' active'; } else { document.getElementById('t' + tabname).className += ' active'; }
233 + }
234 +
235 + var linuxInstall, linuxUnInstall;
236 + function setup() {
237 + var servername = window.location.hostname;
238 + var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
239 +
240 + // Windows 64bit Setup
241 + var url = 'meshagents?id=4&meshid=' + meshid;
242 + if (installFlags != 0) { url += ('&installflags=' + installFlags); }
243 + Q('win64url').href = url;
244 +
245 + // Windows 32bit Setup
246 + url = 'meshagents?id=3&meshid=' + meshid;
247 + if (installFlags != 0) { url += ('&installflags=' + installFlags); }
248 + Q('win32url').href = url;
249 +
250 + // MacOS Setup
251 + url = 'meshosxagent?id=16&meshid=' + meshid;
252 + Q('macosurl').href = url;
253 +
254 + // Linux Setup
255 + if (serverHttps == 1) {
256 + var portStr = (serverPort == 443) ? '' : (":" + serverPort);
257 + if (serverNoProxy == 0) {
258 + 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';
259 + 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';
260 + } else {
261 + // Server asked that agent be installed to preferably not use a HTTP proxy.
262 + 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';
263 + 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';
264 + }
265 + } else {
266 + var portStr = (serverPort == 80) ? '' : (':' + serverPort);
267 + if (serverNoProxy == 0) {
268 + 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';
269 + 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';
270 + } else {
271 + // Server asked that agent be installed to preferably not use a HTTP proxy.
272 + 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';
273 + linuxUnInstall = 'wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
274 + }
275 + }
276 + QH('linuxinstall', linuxInstall);
277 + QH('unlinuxinstall', linuxUnInstall);
278 +
279 + // Attempt to detect the most likely operating system for this browser
280 + if (navigator.userAgent.indexOf('Win64') >= 0) { openTab(null, 'wintab64'); }
281 + else if (navigator.userAgent.indexOf('Windows') >= 0) { openTab(null, 'wintab32'); }
282 + else if (navigator.userAgent.indexOf('Linux') >= 0) { openTab(null, 'linuxtab'); }
283 + else if (navigator.userAgent.indexOf('Macintosh') >= 0) { openTab(null, 'macostab'); }
284 + else { openTab(null, 'wintab64'); }
285 + }
286 +
287 + function copyToClipLinuxInstall() { copyTextToClip(linuxInstall); }
288 + function copyToClipLinuxUnInstall() { copyTextToClip(linuxUnInstall); }
289 + 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(); }
290 +
291 + </script>
292 +
293 +
294 +</body></html>
\ No newline at end of file
views/translations/default-min_pt.handlebars new
+8706
@@ -0,0 +1,8706 @@
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 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><link type=text/css href=styles/ol.css media=screen rel=stylesheet title=CSS><link type=text/css href=styles/ol3-contextmenu.min.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><script src=scripts/meshcentral.js></script><script src=scripts/amt-0.2.0.js></script><script src=scripts/amt-wsman-0.2.0.js></script><script src=scripts/amt-desktop-0.0.2.js></script><script src=scripts/amt-terminal-0.0.2.js></script><script src=scripts/zlib.js></script><script src=scripts/zlib-inflate.js></script><script src=scripts/zlib-adler32.js></script><script src=scripts/zlib-crc32.js></script><script src=scripts/amt-redir-ws-0.1.0.js></script><script src=scripts/amt-wsman-ws-0.2.0.js></script><script src=scripts/agent-redir-ws-0.1.1.js></script><script src=scripts/agent-redir-rtc-0.1.0.js></script><script src=scripts/agent-desktop-0.0.2.js></script><script src=scripts/qrcode.min.js></script><script keeplink=1 src=scripts/u2f-api.js></script><script keeplink=1 src=scripts/charts.js></script><script keeplink=1 src=scripts/filesaver.js></script><body id=body onload='"undefined"!=typeof startup&&startup()'oncontextmenu=handleContextMenu(event) style=display:none;min-width:495px>{{{StartGeoLocation}}}<script keeplink=1 src=scripts/ol.js></script><script keeplink=1 src=scripts/ol3-contextmenu.js></script>{{{EndGeoLocation}}}<title>{{{title}}}</title><div id=contextMenu class="contextMenu noselect"style=display:none><div id=cxinfo class=cmtext onclick=cmaction(1,event)><b>Informação</b></div><div id=cxdesktop class=cmtext onclick=cmaction(3,event)>Área de Trabalho</div><div id=cxterminal class=cmtext onclick=cmaction(2,event)>Terminal</div><div id=cxfiles class=cmtext onclick=cmaction(4,event)>Arquivos</div><div id=cxevents class=cmtext onclick=cmaction(5,event)>Eventos</div><div id=cxconsole class=cmtext onclick=cmaction(6,event)>Console</div><hr id=cxmgroupsplit><div id=cxmdesktop class=cmtext onclick=cmaction(7,event) style=display:none>Multi-Desktop</div></div><div id=meshContextMenu class="contextMenu noselect"style=display:none;min-width:0><div id=cxselectall class=cmtext onclick=cmmeshaction(1,event)>Selecionar tudo</div><div id=cxselectnone class=cmtext onclick=cmmeshaction(2,event)>Selecione nenhum</div></div><div id=termShellContextMenu class="contextMenu noselect"style=display:none;min-width:0><div id=cxtermnorm class=cmtext onclick=cmtermaction(1,event)><b>Admin Shell</b></div><div id=cxtermps class=cmtext onclick=cmtermaction(6,event)>Admin PowerShell</div><div id=cxtermunorm class=cmtext style=display:none onclick=cmtermaction(8,event)>User Shell</div><div id=cxtermups class=cmtext style=display:none onclick=cmtermaction(9,event)>User PowerShell</div></div><div id=termShellContextMenuLinux class="contextMenu noselect"style=display:none;min-width:0><div id=cxtermnorm class=cmtext onclick=cmtermaction(1,event)><b>Root Shell</b></div><div id=cxtermps class=cmtext onclick=cmtermaction(8,event)>User Shell</div></div><div id=container><div id=notifiyBox class=notifiyBox style=display:none></div><div id=masthead class=noselect><div class=title>{{{title}}}</div><div class=title2>{{{title2}}}</div><div style=float:right><div id=notificationCount onclick=clickNotificationIcon() class=unselectable style=display:none title="Clique para visualizar as notificações atuais">0</div></div><p id=logoutControl><span id=logoutControlSpan style=color:#fff></span><span id=idleTimeoutNotify style=color:#ff0></span></div><div id=page_leftbar><div style=height:16px></div><div id=LeftMenuMyDevices tabindex=0 class="lbbutton lbbuttonsel"title="Meus dispositivos"onclick=go(1,event) onkeypress='"Enter"==event.key&&go(1)'><div class=lb2></div></div><div id=LeftMenuMyAccount tabindex=0 class=lbbutton title="Minha conta"onclick=go(2,event) onkeypress='"Enter"==event.key&&go(2)'><div class=lb1></div></div><div id=LeftMenuMyEvents tabindex=0 class=lbbutton title="Meus Eventos"onclick=go(3,event) onkeypress='"Enter"==event.key&&go(3)'><div class=lb3></div></div><div id=LeftMenuMyFiles tabindex=0 class=lbbutton style=display:none title="Meus arquivos"onclick=go(5,event) onkeypress='"Enter"==event.key&&go(5)'><div class=lb4></div></div><div id=LeftMenuMyUsers tabindex=0 class=lbbutton style=display:none title="Meus usuários"onclick=go(4,event) onkeypress='"Enter"==event.key&&go(4)'><div class=lb5></div></div><div id=LeftMenuMyServer tabindex=0 class=lbbutton style=display:none title="Meu servidor"onclick=go(6,event) onkeypress='"Enter"==event.key&&go(6)'><div class=lb6></div></div></div><div id=topbar class=noselect><div><div style=position:relative><div tabindex=0 id=uiMenuButton title="Seleção da interface do usuário"onclick=showUserInterfaceSelectMenu() onkeypress='"Enter"==event.key&&showUserInterfaceSelectMenu()'>♦<div id=uiMenu style=display:none><div tabindex=0 id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Interface da barra esquerda"onkeypress='"Enter"==event.key&&userInterfaceSelectMenu(1)'><div class=uiSelector1></div></div><div tabindex=0 id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Interface da barra superior"onkeypress='"Enter"==event.key&&userInterfaceSelectMenu(2)'><div class=uiSelector2></div></div><div tabindex=0 id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Interface de largura fixa"onkeypress='"Enter"==event.key&&userInterfaceSelectMenu(3)'><div class=uiSelector3></div></div><div tabindex=0 id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Alternar modo noturno"onkeypress='"Enter"==event.key&&toggleNightMode()'><div class=uiSelector4></div></div></div></div><table id=MainMenuSpan cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=MainMenuMyDevices class="topbar_td style3x"onclick=go(1,event) onkeypress='"Enter"==event.key&&go(1)'>Meus dispositivos<td tabindex=0 id=MainMenuMyAccount class="topbar_td style3x"onclick=go(2,event) onkeypress='"Enter"==event.key&&go(2)'>Minha conta<td tabindex=0 id=MainMenuMyEvents class="topbar_td style3x"onclick=go(3,event) onkeypress='"Enter"==event.key&&go(3)'>Meus Eventos<td tabindex=0 id=MainMenuMyFiles class="topbar_td style3x"onclick=go(5,event) onkeypress='"Enter"==event.key&&go(5)'>Meus arquivos<td tabindex=0 id=MainMenuMyUsers class="topbar_td style3x"onclick=go(4,event) onkeypress='"Enter"==event.key&&go(4)'>Meus usuários<td tabindex=0 id=MainMenuMyServer class="topbar_td style3x"onclick=go(6,event) onkeypress='"Enter"==event.key&&go(6)'>Meu servidor<td class="topbar_td_end style3">&nbsp;</table><div id=MainSubMenuSpan style=display:none><table id=MainSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=MainDev class="topbar_td style3x"onclick=go(10,event) onkeypress='"Enter"==event.key&&go(10)'>Geral<td tabindex=0 id=MainDevDesktop class="topbar_td style3x"onclick=go(11,event) onkeypress='"Enter"==event.key&&go(11)'>Área de Trabalho<td tabindex=0 id=MainDevTerminal class="topbar_td style3x"onclick=go(12,event) onkeypress='"Enter"==event.key&&go(12)'>Terminal<td tabindex=0 id=MainDevFiles class="topbar_td style3x"onclick=go(13,event) onkeypress='"Enter"==event.key&&go(13)'>Arquivos<td tabindex=0 id=MainDevEvents class="topbar_td style3x"onclick=go(16,event) onkeypress='"Enter"==event.key&&go(16)'>Eventos<td tabindex=0 id=MainDevInfo class="topbar_td style3x"onclick=go(17,event) onkeypress='"Enter"==event.key&&go(17)'>Detalhes<td tabindex=0 id=MainDevAmt class="topbar_td style3x"onclick=go(14,event) onkeypress='"Enter"==event.key&&go(14)'>Intel® AMT<td tabindex=0 id=MainDevConsole class="topbar_td style3x"onclick=go(15,event) onkeypress='"Enter"==event.key&&go(15)'>Console<td tabindex=0 id=MainDevPlugins class="topbar_td style3x"onclick=go(19,event) onkeypress='"Enter"==event.key&&go(19)'>Plugins<td class="topbar_td_end style3">&nbsp;</table></div><div id=MeshSubMenuSpan style=display:none><table id=MeshSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=MeshGeneral class="topbar_td style3x"onclick=go(20,event) onkeypress='"Enter"==event.key&&go(20)'>Geral<td class="topbar_td_end style3">&nbsp;</table></div><div id=UserSubMenuSpan style=display:none><table id=UserSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=UserGeneral class="topbar_td style3x"onclick=go(30,event) onkeypress='"Enter"==event.key&&go(30)'>Geral<td tabindex=0 id=UserEvents class="topbar_td style3x"onclick=go(31,event) onkeypress='"Enter"==event.key&&go(31)'>Eventos<td class="topbar_td_end style3">&nbsp;</table></div><div id=ServerSubMenuSpan style=display:none><table id=ServerSubMenu cellpadding=0 cellspacing=0 class=style1><tr><td tabindex=0 id=ServerGeneral class="topbar_td style3x"onclick=go(6,event) onkeypress='"Enter"==event.key&&go(6)'>Geral<td tabindex=0 id=ServerStats class="topbar_td style3x"onclick=go(40,event) onkeypress='"Enter"==event.key&&go(40)'>Estatísticas<td tabindex=0 id=ServerConsole class="topbar_td style3x"onclick=go(115,event) onkeypress='"Enter"==event.key&&go(115)'>Console<td tabindex=0 id=ServerTrace class="topbar_td style3x"onclick=go(41,event) onkeypress='"Enter"==event.key&&go(41)'>Vestígio<td tabindex=0 id=ServerPlugins class="topbar_td style3x"onclick=go(42,event) onkeypress='"Enter"==event.key&&go(42)'>Plugins<td class="topbar_td_end style3">&nbsp;</table></div><div id=UserDummyMenuSpan><table id=UserDummyMenu cellpadding=0 cellspacing=0 class=style1><tr><td class=style3>&nbsp;</table></div></div></div></div><div id=column_l><div id=p0 style=display:none><div id=p0message><span id=p0span>Servidor desconectado</span>,<href onclick=reload() style=cursor:pointer><u>clique para reconectar</u></href>.</div></div><div id=p1 style=display:none><div style=display:none id=devListToolbarViewIcons><div tabindex=0 id=devViewButton1 class=viewSelector onclick=onDeviceViewChange(1) onkeypress='"Enter"==event.key&&onDeviceViewChange(1)'title=Colunas><div class=viewSelector2></div></div><div tabindex=0 id=devViewButton2 class=viewSelector onclick=onDeviceViewChange(2) onkeypress='"Enter"==event.key&&onDeviceViewChange(2)'title=Lista><div class=viewSelector1></div></div><div tabindex=0 id=devViewButton3 class=viewSelector onclick=onDeviceViewChange(3) onkeypress='"Enter"==event.key&&onDeviceViewChange(3)'title="Áreas de trabalho"><div class=viewSelector3></div></div><div tabindex=0 id=devViewButton4 class=viewSelector onclick=onDeviceViewChange(4) onkeypress='"Enter"==event.key&&onDeviceViewChange(4)'title=Mapa style=display:none><div class=viewSelector4></div></div></div><div><h1>Meus dispositivos</h1></div><table id=devListToolbarSpan class=noselect><tr><td class=h1><td id=devListToolbar class=style14 style=display:none>&nbsp;&nbsp;<input type=button id=SelectAllButton onclick=selectallButtonFunction() value="Selecionar tudo">&nbsp; <input type=button id=GroupActionButton disabled value="Ações do grupo"onclick=groupActionFunction()>&nbsp; <input id=SearchInput placeholder=Filtro onchange=masterUpdate(5) onkeyup=masterUpdate(5) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0)>&nbsp; <label><input type=checkbox id=RealNameCheckBox onclick=onRealNameCheckBox()><span title="Mostrar o nome do sistema operacional dos dispositivos">Nome do SO</span></label><td id=kvmListToolbar class=style14 style=display:none>&nbsp;&nbsp;<input type=button onclick=connectAllKvmFunction() value="Conectar todos">&nbsp; <input type=button onclick=disconnectAllKvmFunction() value="Desconectar todos">&nbsp; <label><input type=checkbox id=autoConnectDesktopCheckbox onclick=autoConnectDesktops(event) title="Conexão automática">Auto&nbsp;</label> <input type=button onclick=showMultiDesktopSettings() value=Configurações>&nbsp;<td id=devMapToolbar class=style14 style=display:none>&nbsp;&nbsp;<input id=mapSearchLocation placeholder="Pesquisar Localização"onfocus=onMapSearchFocus(1) onblur=onMapSearchFocus(0)> <input type=button value=Procurar title="Pesquisar localização"onclick=getSearchLocation()> <input type=button id=refreshmap title="Redefinir visualização de mapa"value=Redefinir onclick=refreshMap(!1,!0)><td class=auto-style1 style=height:100%><div style=display:none id=devListToolbarView>Visualizar <select id=viewselect onchange=onDeviceViewChange()><option value=1>Colunas<option value=2>Lista<option value=3>Áreas de trabalho<option id=viewselectmapoption value=4 style=display:none>Mapa</select></div><div style=display:none id=devListToolbarSort>Classificar <select id=sortselect onchange=masterUpdate(6)><option>Grupo<option>Ligar<option>Dispositivo<option>Tags</select> &nbsp;</div><div style=display:none id=devListToolbarSize>Tamanho <select id=sizeselect onchange=onDeviceViewChange()><option value=0>Pequeno<option value=1>Médio<option value=2>ampla</select> &nbsp;</div><td class=h2></table><div id=NoMeshesPanel style=display:none><table><tr><td valign=top style=width:50px><img src=images/info.png><td><div id=getStarted1>Para começar, <a href=# onclick="return account_createMesh()"><strong>clique aqui para criar um grupo de dispositivos</strong></a>.</div><div id=getStarted2>Nenhum grupo de dispositivos.</div></table></div><div id=xdevices class=noselect style=display:none></div><div id=xdevicesmap style=display:none><div id=xmapSearchResultsDlg style=display:none><div id=xmapSearchResultsBck><div id=xmapSearchClose onclick=mapCloseSearchWindow()><b>X</b></div><div style=padding:5px>Resultados da Localização</div><div style=width:100%;margin:6px></div></div><div id=xmapSearchResults style=margin:6px></div></div></div><div id=xmap-info-window></div></div><div id=p2 style=display:none><h1>Minha conta</h1><img id=p2AccountImage alt=""src=images/clipboard-128.png><div id=p2AccountSecurity style=display:none><p><strong>Segurança da conta</strong><div style=margin-left:25px><div id=manageAuthApp><div class=p2AccountActions><span id=authAppSetupCheck><strong>✓</strong></span></div><span><a href=# onclick="return account_manageAuthApp()">Gerenciar aplicativo autenticador</a><br></span></div><div id=manageHardwareOtp><div class=p2AccountActions><span id=authKeySetupCheck><strong>✓</strong></span></div><span><a href=# onclick="return account_manageHardwareOtp(0)">Gerenciar chaves de segurança</a><br></span></div><div id=manageOtp><div class=p2AccountActions><span id=authCodesSetupCheck><strong>✓</strong></span></div><span><a href=# onclick="return account_manageOtp(0)">Gerenciar códigos de backup</a><br></span></div></div></div><div id=p2AccountActions><p><strong>Ações da conta</strong><p class=mL><span id=verifyEmailId style=display:none><a href=# onclick="return account_showVerifyEmail()">Verificar email</a><br></span><span id=accountEnableNotificationsSpan style=display:none><a href=# onclick="return account_enableNotifications()">Ativar notificações da web</a><br></span><a href=# onclick="return account_showLocalizationSettings()">Configurações de localização</a><br><a href=# onclick="return account_showAccountNotifySettings()">Configurações de notificação</a><br><span id=accountChangeEmailAddressSpan style=display:none><a href=# onclick="return account_showChangeEmail()">Mude o endereço de email</a><br></span><a href=# onclick="return account_showChangePassword()">Mudar senha</a><span id=p2nextPasswordUpdateTime></span><br><a href=# onclick="return account_showDeleteAccount()">Deletar conta</a><br></p><br style=clear:both></div><strong>Grupos de dispositivos</strong> <span id=p2createMeshLink1>( <a href=# onclick="return account_createMesh()"class=newMeshBtn>Novo</a> )</span><br><br><div id=p2meshes></div><div id=p2noMeshFound style=display:none>Nenhum grupo de dispositivos.<span id=p2createMeshLink2> <a href=# onclick="return account_createMesh()"><strong>Comece aqui!</strong></a></span></div><br style=clear:both></div><div id=p3 style=display:none><h1>Meus Eventos</h1><table class=pTable><tr><td class=h1><td class=auto-style1>Mostrar <select id=p3limitdropdown onchange=refreshEvents()><option value=60>Últimos 60<option value=120>Últimos 120<option value=250>Últimos 250<option value=500>Últimos 500<option value=1000>Últimos 1000</select>&nbsp; <a href=# onclick=p3showDownloadEventsDialog(2)><img src=images/link4.png height=10 width=10 title="Download de Eventos"style=cursor:pointer></a>&nbsp;<td class=h2></table><div id=p3events></div></div><div id=p4 style=display:none><h1>Meus usuários</h1><table class=pTable><tr><td class=h1><td class=style14><div style=float:right><input type=button onclick=showUserBroadcastDialog() style=margin-right:6px value=Broadcast> <a href=# onclick=p4downloadUserInfo()><img style=cursor:pointer title="Baixar informações do usuário"src=images/link4.png></a><a href=# onclick=p4batchAccountCreate()><img id=p4UserBatchCreate style=cursor:pointer;display:none title="Lote criar muitas contas de usuário"src=images/link6.png></a></div><div><input id=UserNewAccountButton type=button style=margin-left:6px onclick=showCreateNewAccountDialog() value="Nova conta..."> <input id=UserSearchInput style=width:120px;margin-left:6px placeholder=Filtro onchange=onUserSearchInputChanged() onkeyup=onUserSearchInputChanged() autocomplete=off onfocus=onUserSearchFocus(1) onblur=onUserSearchFocus(0)></div><td class=h2></table><div id=p3users></div></div><div id=p5 style=display:none><h1>Meus arquivos</h1><table id=p5toolbar cellpadding=0 cellspacing=0><tr><td id=p5filehead valign=bottom><div id=p5rightOfButtons></div><div><input type=button id=p5FolderUp disabled onclick="return p5folderup()"value=Acima>&nbsp; <input type=button id=p5SelectAllButton disabled onclick=p5selectallfile() value="Selecionar tudo">&nbsp; <input type=button id=p5RenameFileButton disabled value=Renomear onclick=p5renamefile()>&nbsp; <input type=button id=p5DeleteFileButton disabled value=Deletar onclick=p5deletefile()>&nbsp; <input type=button id=p5NewFolderButton disabled value="Nova pasta"onclick=p5createfolder()>&nbsp; <input type=button id=p5UploadButton disabled value=Envio onclick=p5uploadFile()>&nbsp; <input type=button id=p5CutButton disabled value=Cortar onclick=p5copyFile(1)>&nbsp; <input type=button id=p5CopyButton disabled value=Copiar onclick=p5copyFile(0)>&nbsp; <input type=button id=p5PasteButton disabled value=Colar onclick=p5pasteFile()>&nbsp;</div><tr><td id=p5filesubhead><div style=float:right><select id=p5sortdropdown onchange=updateFiles()><option value=1 selected>Classificar por nome<option value=2>Classificar por tamanho<option value=3>Classificar por data<option value=4>Decrescente por nome<option value=5>Decrescente por tamanho<option value=6>Descrescente por data</select></div><div>&nbsp;&nbsp;<span id=p5currentpath></span></div></table><div id=p5filetable><div id=p5PublicShare><div>Esses arquivos são compartilhados publicamente, clique em "link" para obter o URL público.</div></div><div id=bigok style=display:none><b>✓</b></div><div id=bigfail style=display:none><b>✗</b></div><span id=p5files></span></div><table id=p5toolbarBottom style=width:100% cellpadding=0 cellspacing=0><tr><td class=style6>&nbsp;<span id=p5bottomstatus></span></table></div><div id=p6 style=display:none><img id=MainMeshImage src=serverpic.ashx><h1>Meu servidor</h1><div id=p2ServerActions><p><strong>Ações do servidor</strong><div class=mL><div id=p2ServerActionsBackup><a href={{{domainurl}}}backup.zip rel="noreferrer noopener"target=_blank>Fazer o download do backup do servidor</a></div><div id=p2ServerActionsRestore><a href=# onclick="return server_showRestoreDlg()">Restaurar servidor com backup</a></div><div id=p2ServerActionsVersion><a href=# onclick="return server_showVersionDlg()">Verifique a versão do servidor</a></div><div id=p2ServerActionsErrors><a href=# onclick="return server_showErrorsDlg()">Mostrar log de erros do servidor</a></div></div></div><br><strong>Estatísticas do servidor</strong><br><br><div id=serverStats><div id=serverCpuChartView style=display:none><div class=chartViewCanvas><canvas id=serverCpuChart></canvas></div><div class=chartViewText id=serverCpuChartText></div></div><div id=serverMemoryChartView style=display:none><div class=chartViewCanvas><canvas id=serverMemoryChart></canvas></div><div class=chartViewText id=serverMemoryChartText></div></div><br><br><div id=serverStatsTable></div></div><div id=serverWarningsDiv style=display:none><br><strong>Server Warnings</strong><br><br><div id=serverWarnings></div></div></div><div id=p10 style=display:none><table style=width:100% cellpadding=0 cellspacing=0><tr><td style=width:auto valign=top><div id=p10title><div id=p10BackButton><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Geral - <span id=p10deviceName></span></h1></div><div id=p10html></div><td style=width:20px><td style=width:200px><a href=# onclick=p10showiconselector()><img id=MainComputerImage></a><div id=MainComputerState></div></table><br><div id=p10html2></div><div id=p10html3></div></div><div id=p11 class=noselect style=display:none><div id=p11title><div id=p11deviceNameHeader><div id=p11BackButton><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><div id=devListToolbarViewIcons><div class=viewSelector onclick=deskToggleFull(event) title="Tela cheia. Mantenha a tecla Shift pressionada no navegador em tela cheia."><div class=viewSelector5></div></div></div><h1>Área de Trabalho - <span id=p11deviceName></span></h1></div></div><div id=p11warning onclick=showFeaturesDlg()><div class=icon2></div><div class=warningbox>Intel® Porta de redirecionamento AMT ou recurso KVM desativado<span id=p11warninga>, clique aqui para habilitá-lo.</span></div></div><div id=p11warning2 onclick=showPowerActionDlg()><div class=icon2></div><div class=warningbox>O computador remoto não está ligado, clique aqui para emitir um comando de energia.</div></div><div id=deskarea0 cellpadding=0 cellspacing=0><div id=deskarea1 class=areaHead><div class=toright2><span id=p11power></span>&nbsp;<div class=deskareaicon title="Alternar modo de exibição"onclick=toggleAspectRatio(1)>⇲</div><div class=deskareaicon title="Vire à esquerda"onclick=drotate(-1)>↺</div><div class=deskareaicon title="Vire à direita"onclick=drotate(1)>↻</div><div id=deskRecordIcon class=deskareaicon title="O servidor está gravando esta sessão"style=display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px></div><input id=deskFocusBtn type=button title="Alternar modo de foco, quando ativo, apenas a região ao redor do mouse é atualizada"onkeypress=return!1 onkeydown=return!1 value="Focus All"onclick=deskToggleFocus() style=margin-right:3px;display:none> <input id=deskSaveBtn type=button title="Salvar uma captura de tela da área de trabalho remota"onkeypress=return!1 onkeydown=return!1 value=Salvar... onclick=deskSaveImage() class=mR> <input id=deskActionsBtn type=button title="Execute ações de energia no dispositivo"onkeypress=return!1 onkeydown=return!1 value=Ações onclick=deviceActionFunction() class=mR> <input id=deskActionsSettings type=button value=Configurações... title="Editar configurações da área de trabalho remota"onkeypress=return!1 onkeydown=return!1 onclick=showDesktopSettings() class=mR> <input type=button title="Alterar o estado de energia da máquina remota"onkeypress=return!1 onkeydown=return!1 value="Ações de energia (Ligar/Desligar)"onclick=showPowerActionDlg() style=display:none></div><div><div id=idx_deskFullBtn2 onclick=deskToggleFull(event)>&nbsp;✖</div><input type=button id=autoconnectbutton1 value="Conexão automática"onclick=autoConnectDesktop(event) onkeypress=return!1 onkeydown=return!1 style=display:none> <span id=connectbutton1span><input type=button id=connectbutton1 value=Conectar onclick=connectDesktop(event,1) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=connectbutton1hspan>&nbsp;<input type=button id=connectbutton1h value="Conectar HW"title="Connect using Intel AMT hardware KVM"onclick=connectDesktop(event,2) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=disconnectbutton1span>&nbsp;<input type=button id=disconnectbutton1 value=Desconectar onclick=connectDesktop(event,0) onkeypress=return!1 onkeydown=return!1></span>&nbsp;<span id=deskstatus>Desconectado</span></div></div><div id=deskarea2><div class=areaProgress><div id=progressbar></div></div></div><div id=deskarea3x><div id=DeskFocus oncontextmenu=return!1 onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></div><div id=DeskParent><canvas id=Desk width=640 height=480 oncontextmenu=return!1 onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event) onmousewheel=dmousewheel(event)></canvas></div><div id=DeskTools><div id=deskToolsAreaTop><a id=DeskToolsRefreshButton style=right:2px onclick=refreshDeskTools()>Atualizar</a><div id=deskToolsTopTabProcess class=deskToolsTopTab onclick=changeDeskToolTab(0) style=left:0;bottom:0>Processos</div><div id=deskToolsTopTabService class=deskToolsTopTab onclick=changeDeskToolTab(1) style=display:none;left:90px;color:gray>Serviços</div></div><div id=deskToolsArea><div id=DeskToolsProcessTab><div id=deskToolsHeader><a class=colmn1 title="Classificar por ID do processo"onclick=sortProcess(0)>PID</a> <a class=colmn2 title="Classificar por nome"onclick=sortProcess(1)>Nome</a></div><div id=DeskToolsProcesses></div></div><div id=DeskToolsServiceTab style=display:none><div id=deskToolsServiceHeader><a class=colmn1 style=width:70px title="Classificar por estado"onclick=sortService(0)>Estado</a> <a class=colmn2 title="Classificar por nome"onclick=sortService(1)>Nome</a></div><div id=DeskToolsServices></div></div></div></div><div id=p11DeskConsoleMsg style=display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:#ff0;background-color:rgba(0,0,0,.6);padding:10px;border-radius:5px onclick=p11clearConsoleMsg()></div></div><div id=deskarea4 class=areaFoot><div class=toright2><span id=DeskTimer title="Tempo de sessão"></span>&nbsp; <select id=termdisplays style=display:none onchange=deskSetDisplay(event) onkeypress=return!1 onkeydown=return!1></select>&nbsp; <input id=DeskToolsButton type=button value=Ferramentas title="Alternar visualização de ferramentas"onkeypress=return!1 onkeydown=return!1 onclick=toggleDeskTools()>&nbsp; <span id=DeskChatButton class=deskarea title="Abra a janela de bate-papo neste computador"><img src=images/icon-chat.png onclick=deviceChat(event) height=16 width=16 style=padding-top:2px></span><span id=DeskNotifyButton title="Exibir uma notificação no computador remoto"><img src=images/icon-notify.png onclick=deviceToastFunction() height=16 width=16 style=padding-top:2px></span><span id=DeskOpenWebButton title="Open a web address on the remote computer"><img src=images/icon-url2.png onclick=deviceUrlFunction() height=16 width=16 style=padding-top:2px></span><span id=DeskBackgroundButton title="Toggle remote desktop background"><img src=images/icon-background.png onclick=deviceToggleBackground(event) height=16 width=16 style=padding-top:2px></span></div><div><select id=deskkeys><option value=10>CTRL+ALT+DEL<option value=5>Win<option value=0>Win+Down<option value=1>Win+Up<option value=2>Win+L<option value=3>Win+M<option value=4>Shift+Win+M<option value=6>Win+R<option value=7>Alt-F4<option value=8>CTRL-W<option value=9>Alt-Tab<option value=11>Win+Left<option value=12>Win+Right</select> <input id=DeskWD type=button value=Enviar onkeypress=return!1 onkeydown=return!1 onclick=deskSendKeys()> <input id=DeskClip type=button value="Área de transferência"onkeypress=return!1 onkeydown=return!1 onclick=showDeskClip()> <input id=DeskType type=button value=Tipo onkeypress=return!1 onkeydown=return!1 onclick=showDeskType()> <label><span id=DeskControlSpan title="Alternar entrada de mouse e teclado"><input id=DeskControl type=checkbox onkeypress=return!1 onkeydown=return!1 onclick=toggleKvmControl()>Entrada</span></label>&nbsp;</div></div></div></div><div id=p12 style=display:none><div id=p12title><div id=p12BackButton><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Terminal - <span id=p12deviceName></span></h1></div><div id=p12warning onclick=showFeaturesDlg()><div class=icon2></div><div class=warningbox>Intel® Porta de redirecionamento AMT ou recurso KVM desativado<span id=p12warninga>, clique aqui para habilitá-lo.</span></div></div><div id=p12warning2 onclick=showPowerActionDlg()><div class=icon2></div><div class=warningbox>O computador remoto não está ligado, clique aqui para emitir um comando de energia.</div></div><div id=termTable style=position:relative><table style=width:100% cellpadding=0 cellspacing=0><tr><td class=areaHead><div class=toright2><div id=termRecordIcon class=deskareaicon title="O servidor está gravando esta sessão"style=display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px></div><input id=termActionsBtn type=button title="Execute ações de energia no dispositivo"onkeypress=return!1 onkeydown=return!1 value=Ações onclick=deviceActionFunction()></div><div><input type=button id=autoconnectbutton2 value="Conexão automática"onclick=autoConnectTerminal(event) onkeypress=return!1 onkeydown=return!1 style=display:none> <span id=connectbutton2span><input type=button id=connectbutton2 value=Conectar onclick=connectTerminal(event,1) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=connectbutton2hspan>&nbsp;<input type=button id=connectbutton2h value="Conectar HW"title="Connect using Intel AMT hardware KVM"onclick=connectTerminal(event,2) onkeypress=return!1 onkeydown=return!1 disabled></span><span id=disconnectbutton2span>&nbsp;<input type=button id=disconnectbutton2 value=Desconectar onclick=connectTerminal(event,0) onkeypress=return!1 onkeydown=return!1></span>&nbsp;<span id=termstatus>Desconectado</span><span id=termtitle></span></div><tr><td><div class=areaProgress><div id=termprogressbar></div></div><tr><td id=termarea3x><pre id=Term></pre><tr><td class=areaFoot><div class=toright2><span id=TermTimer title="Tempo de sessão"></span>&nbsp; <span id=terminalSettingsButtons style=display:none><input id=id_tcrbutton type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton value="CR + LF"title="Alterne o que a chave de retorno enviará"onclick=termToggleCr()> <input id=id_tfxkeysbutton type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton value="Intel (F10 = ESC+[OM)"title="Alterna o tipo de emulação de teclas F1 a F10"onclick=termToggleFx()> <input id=id_ttypebutton type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton value="Ascii estendido"title="Alternar tipo de emulação de terminal"onclick=termToggleType()> </span><span id=terminalSizeDropDown><select id=termSizeList onkeypress=return!1><option value=1>80x25<option value=2>100x30<option value=3 selected>Auto</select> </span><select id=specialkeylist onkeypress=return!1></select> <input id=specialkeylistinput type=button onkeypress=return!1 class=bottombutton value=Enviar title="Enviar a chave especial selecionada"onclick=sendSpecialKey()></div><div>&nbsp; <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=ctrlcbutton value=CTRL-C onclick='termSendKey(3,"ctrlcbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=ctrlxbutton value=CTRL-X onclick='termSendKey(24,"ctrlxbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=escbutton value=ESC onclick='termSendKey(27,"escbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=bsbutton value=Excluir onclick='termSendKey(8,"bsbutton")'> <input type=button onkeypress=return!1 onkeydown=return!1 class=bottombutton id=pastebutton value=Colar title="Cole o texto no terminal"onclick=showTermPasteDialog()></div></table><div id=p12TermConsoleMsg style=display:none;cursor:pointer;position:absolute;left:30px;top:45px;color:#ff0;background-color:rgba(0,0,0,.6);padding:10px;border-radius:5px onclick=p12clearConsoleMsg()></div></div></div><div id=p13 style=display:none><div id=p13title><div id=p13BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Arquivos - <span id=p13deviceName></span></h1></div><table id=p13toolbar cellpadding=0 cellspacing=0><tr><td class=areaHead><div class=toright2><input id=filesActionsBtn type=button title="Execute ações de energia no dispositivo"value=Ações onclick=deviceActionFunction()><div id=filesRecordIcon class=deskareaicon title="O servidor está gravando esta sessão"style=display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px></div></div><div><input id=p13AutoConnect value="Conexão automática"onclick=autoConnectFiles(event) type=button style=display:none> <input id=p13Connect value=Conectar onclick=connectFiles(event) type=button> <span id=p13Status>Desconectado</span></div><tr><td class=areaHead2 valign=bottom><div id=p13rightOfButtons class=toright2></div><div><input type=button id=p13FolderUp disabled onclick=p13folderup() value=Acima>&nbsp; <input type=button id=p13SelectAllButton disabled onclick=p13selectallfile() value="Selecionar tudo">&nbsp; <input type=button id=p13RenameFileButton disabled value=Renomear onclick=p13renamefile()>&nbsp; <input type=button id=p13DeleteFileButton disabled value=Deletar onclick=p13deletefile()>&nbsp; <input type=button id=p13ViewFileButton disabled value=Editar onclick=p13viewfile()>&nbsp; <input type=button id=p13NewFolderButton disabled value="Nova pasta"onclick=p13createfolder()>&nbsp; <input type=button id=p13UploadButton disabled value=Envio onclick=p13uploadFile()>&nbsp; <input type=button id=p13CutButton disabled value=Cortar onclick=p13copyFile(1)>&nbsp; <input type=button id=p13CopyButton disabled value=Copiar onclick=p13copyFile(0)>&nbsp; <input type=button id=p13PasteButton disabled value=Colar onclick=p13pasteFile()>&nbsp; <input type=button id=p13RefreshButton disabled value=Atualizar onclick=p13folderup(9999)>&nbsp;</div><tr><td class=areaHead3><div class=toright2><select id=p13sortdropdown onchange=p13updateFiles()><option value=1 selected>Classificar por nome<option value=2>Classificar por tamanho<option value=3>Classificar por data<option value=4>Decrescente por nome<option value=5>Decrescente por tamanho<option value=6>Descrescente por data</select></div><div>&nbsp;&nbsp;<span id=p13currentpath></span></div></table><div id=p13FilesConsoleMsg style=display:none;cursor:pointer;position:absolute;left:30px;top:165px;color:#ff0;background-color:rgba(0,0,0,.6);padding:10px;border-radius:5px onclick=p13clearConsoleMsg()></div><div id=p13filetable><div id=p13bigok style=display:none><b>✓</b></div><div id=p13bigfail style=display:none><b>✗</b></div><span id=p13files></span></div><table id=p13toolbarBottom cellpadding=0 cellspacing=0><tr><td class=style6>&nbsp;<span id=p13bottomstatus></span></table></div><div id=p14 style=display:none><div id=p14title><div id=p14BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><div id=devListToolbarViewIcons><div class=viewSelector onclick=deskToggleFull(event) title="Tela cheia. Mantenha a tecla Shift pressionada no navegador em tela cheia."><div class=viewSelector5></div></div></div><h1>Intel® AMT - <span id=p14deviceName></span></h1></div><iframe id=p14iframe src={{{domainurl}}}commander.htm></iframe></div><div id=p15 style=display:none><div id=p15title><div id=p15BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1><span id=p15deviceName></span></h1></div><table id=consoleTable cellpadding=0 cellspacing=0><tr><td class=areaHead><div class=toright2><div id=p15coreName title="Informações sobre o núcleo atual em execução neste agente"></div><input type=button id=p15uploadCore value="Ação do agente"onclick=p15uploadCore(event) title="Alterar o módulo de código Java Script do agente"> <img onclick=p15downloadConsoleText() style=cursor:pointer;margin-top:6px title="Baixar do texto do console"src=images/link4.png></div><div id=p15statetext></div><tr><td><div class=areaProgress><div id=consoleprogressbar></div></div><tr><td id=p15agentConsole><pre id=p15agentConsoleText></pre><tr><td class=areaFoot><table style=width:100%><tr><td style=width:99%><input id=p15consoleText style=width:100% onkeyup=p15consoleSend(event) onfocus=onConsoleFocus(1) onblur=onConsoleFocus(0)><td>&nbsp;<td id=p15outputselecttd><select id=p15outputselect><option value=1>Agente<option value=2>MQTT</select><td style=width:1%><input id=id_p15consoleClear type=button class=bottombutton value=Limpo onclick=p15consoleClear()></table></table></div><div id=p16 style=display:none><div id=p16title><div id=p16BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Eventos - <span id=p16deviceName></span></h1></div><table class=pTable><tr><td class=h1><td class=auto-style1>Mostrar <select id=p16limitdropdown onchange=refreshDeviceEvents()><option value=60>Últimos 60<option value=120>Últimos 120<option value=250>Últimos 250<option value=500>Últimos 500<option value=1000>Últimos 1000</select> <a href=# onclick=p3showDownloadEventsDialog(1)><img src=images/link4.png height=10 width=10 title="Download de Eventos"style=cursor:pointer></a>&nbsp;<td class=h2></table><div id=p16events></div></div><div id=p17 style=display:none><div id=p17title><div id=p17BackButton style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Detalhes - <span id=p17deviceName></span></h1></div><div id=p17info></div></div><div id=p20 style=display:none><picture id=MainMeshImage style=border-width:0;height:200px;width:200px;float:right><source type=image/webp width=200 height=200 srcset=images/webp/mesh-256.webp><img alt=""width=200 height=200 src=images/mesh-256.png></picture><div style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Geral - <span id=p20meshName></span></h1><p id=p20info></div><div id=p30 style=display:none><table style=width:100% cellpadding=0 cellspacing=0><tr><td style=width:auto valign=top><div id=p30title><div style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Geral - <span id=p30userName></span></h1></div><div id=p30html></div><td style=width:20px><td style=width:200px><picture id=MainUserImage style=border-width:0;height:200px;width:200px;float:right><source type=image/webp width=200 height=200 srcset=images/webp/user-256.webp><img alt=""width=200 height=200 src=images/user-256.png></picture><div style=width:100%;text-align:center><strong><span id=MainUserState></span></strong></div></table><br><div id=p30html2></div><div id=p30html3></div></div><div id=p31 style=display:none><div style=float:left><div class=backButton tabindex=0 onclick=goBack() title=Voltar onkeypress='"Enter"==event.key&&goBack()'><div class=backButtonEx></div></div></div><h1>Eventos - <span id=p31userName></span></h1><table class=pTable><tr><td class=h1><td class=auto-style1>Mostrar <select id=p31limitdropdown onchange=refreshUsersEvents()><option value=60>Últimos 60<option value=120>Últimos 120<option value=250>Últimos 250<option value=500>Últimos 500<option value=1000>Últimos 1000</select> <a href=# onclick=p3showDownloadEventsDialog(3)><img src=images/link4.png height=10 width=10 title="Download de Eventos"style=cursor:pointer></a>&nbsp;<td class=h2></table><div id=p31events></div></div><div id=p40 style=display:none><h1>Estatísticas do meu servidor</h1><div class=areaHead><div class=toright2><select id=p40type onchange=updateServerTimelineStats()><option value=0>Conexões<option value=1>Memória</select>&nbsp; <select id=p40time onchange=updateServerTimelineHours()><option value=3>Últimas 3 horas<option value=8>Últimas 8 horas<option value=24>Último dia<option value=168>Semana passada<option value=720>Últimos 30 dias</select>&nbsp; <img src=images/link4.png height=10 width=10 title="Baixar pontos de dados (.csv)"style=cursor:pointer onclick=p40downloadEvents()>&nbsp;</div><div><input value=Atualizar type=button onclick=refreshServerTimelineStats()> &nbsp;<label><input id=p40log type=checkbox onclick=updateServerTimelineHours()>Log-X</label></div></div><canvas id=serverMainStats></canvas></div><div id=p41 style=display:none><h1>Rastreio do meu servidor</h1><div class=areaHead><div class=toright2>Mostrar <select id=p41limitdropdown onchange=displayServerTrace()><option value=100>Últimos 100<option value=250>Últimos 250<option value=500>Últimos 500<option value=1000>Últimos 1000</select> <input value=Limpo type=button onclick=clearServerTracing()> <img src=images/link4.png height=10 width=10 title="Rastreio de download (.csv)"style=cursor:pointer onclick=p41downloadServerTrace()>&nbsp;</div><div><input value=Rastreamento type=button onclick=setServerTracing()> <span id=p41traceStatus>Nenhum</span></div></div><div id=p41events></div></div><div id=p42 style=display:none><h1>My Server Plugins</h1><div class=areaHead><div class=toright2></div><div><input value="Download Plugin"type=button onclick="return pluginHandler.addPluginDlg()"></div></div><div id=pluginRestartNotice class=areaHead style=background-color:gold;display:none><div class=toright2><input value="Refresh Agent Cores"type=button onclick="return distributeCore(),!1"></div><div style=padding:2px><div style=padding:2px><b>Notice:</b> Plugins have been altered, this may require agent core update.</div></div></div><table id=p42tbl><tr class=DevSt><th style=width:26px><th style=width:10px><th class=chName>Nome<th class=chDescription>Descrição<th class=chSite style=text-align:center>Ligação<th class=chVersion style=text-align:center>Versão<th class=chUpgradeAvail style=text-align:center>Latest<th class=chStatus style=text-align:center>Status<th class=chAction style=text-align:center>Ação<th style=width:10px></table><div id=pluginNoneNotice style=width:100%;text-align:center;padding-top:10px;display:none><i>No plugins on server.</i></div></div><div id=p43 style=display:none><div id=p43BackButton><div class=backButton tabindex=0 onclick=go(42) title=Voltar onkeypress='"Enter"==event.key&&go(42)'><div class=backButtonEx></div></div></div><h1>My Server Plugins - <span id=p43title></span></h1><iframe id=p43iframe frameborder=0 style="width:100%;height:calc(100vh - 245px);max-height:calc(100vh - 245px)"></iframe></div><div id=p19 style=display:none><h1>Plugins - <span id=p19deviceName></span></h1><div id=p19headers></div><div id=p19pages></div></div><br id=column_l_bottomgap></div><div id=footer><div class=footer1>{{{footer}}}</div><div class=footer2><a id=verifyEmailId2 style=display:none href=# onclick=account_showVerifyEmail()>Verificar Email</a> &nbsp;<a href=terms>Termos &amp; Privacidade</a></div></div><div id=dialog class=noselect style=display:none><div id=dialogHeader><div tabindex=0 id=id_dialogclose onclick=setDialogMode() onkeypress='"Enter"==event.key&&setDialogMode()'>✖</div><div id=id_dialogtitle></div></div><div id=dialogBody><div id=dialog1><div id=id_dialogMessage></div></div><div id=dialog2><div id=id_dialogOptions></div></div><div id=dialog3><div id=d3upload><div>Seleção de arquivo</div><select id=d3uploadMode onchange=d3modechange()><option value=1>Upload de arquivo local<option value=2>Seleção de arquivo do servidor</select></div><div id=d3localmode style=display:none><div>Subir arquivo</div><form id=d3localmodeform method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame><input id=d3auth name=auth style=display:none> <input id=d3attrib name=attrib style=display:none> <input type=file id=d3localFile name=files onchange=d3setActions()> <input type=submit id=d3submit style=display:none></form></div><div id=d3servermode><div id=d3serveraction valign=bottom><input type=button id=p3FolderUp disabled onclick=d3folderup() value=Acima>&nbsp;</div><div id=d3serverfiles></div></div></div><div id=dialog7><div id=d7meshkvm><h4>Área de trabalho remota do agente</h4><div><div>Qualidade</div><select id=d7bitmapquality dir=rtl></select></div><div><div>Dimensionamento</div><select id=d7bitmapscaling dir=rtl><option selected value=1024>100%<option value=896>87.5%<option value=768>75%<option value=640>62.5%<option value=512>50%<option value=384>37..5%<option value=256>25%<option value=128>12.5%</select></div><div><div>Taxa de quadros</div><select id=d7framelimiter dir=rtl><option selected value=50>Rápido<option value=100>Médio<option value=400>Lento<option value=1000>Muito devagar</select></div></div><div id=d7amtkvm><h4>Intel® AMT Hardware KVM</h4><div><div>Codificação de Imagem</div><select id=d7desktopmode><option value=1>RLE8, mais rápido<option value=2>RLE16, Recomendado<option value=3>RAW8, lento<option value=4>RAW16, muito lento</select></div><div><div>Outros ajustes</div><div id=d7otherset style=display:block><label style=display:block><input type=checkbox id=d7showfocus>Mostrar ferramenta de foco</label> <label style=display:block><input type=checkbox id=d7showcursor>Mostrar Cursor do Mouse Local</label> <label style=display:block><input type=checkbox id=d7localKeyMap>Mapa do teclado local</label></div></div></div></div></div><div id=idx_dlgButtonBar><input id=idx_dlgCancelButton type=button value=Cancelar onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=Ok onclick=dialogclose(1)><div><input id=idx_dlgDeleteButton type=button value=Deletar style=display:none onclick=dialogclose(2)></div></div></div><iframe name=fileUploadFrame style=display:none></iframe><form style=display:none method=post action=uploadfile.ashx enctype=multipart/form-data target=fileUploadFrame><input id=p5fileDragName name=name><input id=p5fileDragAuthCookie name=auth><input id=p5fileDragSize name=size><input id=p5fileDragType name=type><input id=p5fileDragData name=data><input id=p5fileDragLink name=link><input type=submit id=p5loginSubmit2 style=display:none></form><form style=display:none method=post action=uploadnodefile.ashx enctype=multipart/form-data target=fileUploadFrame><input id=p13fileDragName name=name><input id=p13fileDragSize name=size><input id=p13fileDragType name=type><input id=p13fileDragData name=data><input id=p13fileDragLink name=link><input type=submit id=p13loginSubmit2 style=display:none></form><audio id=chimes><source src=sounds/chimes.mp3 type=audio/mp3></audio></div><script>'use strict';
2 +
3 + // Process server-side web state
4 + var webState = '{{{webstate}}}';
5 + if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
6 + for (var i in webState) { localStorage.setItem(i, webState[i]); }
7 + if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
8 +
9 + var args;
10 + var autoReconnect = true;
11 + var powerStatetable = ['', "Ligado", "Hibernar", "Hibernar", "Hibernar", "Hibernando", "Desligar", "Presente"];
12 + var StatusStrs = ["Desconectado", "Conectando...", "Configurando...", "Conectado", "Intel&reg; AMT conectado"];
13 + var sort = 0;
14 + var searchFocus = 0;
15 + var mapSearchFocus = 0;
16 + var userSearchFocus = 0;
17 + var consoleFocus = 0;
18 + var showRealNames = false;
19 + var meshserver = null;
20 + var meshes = {};
21 + var meshcount = 0;
22 + var nodes = null;
23 + var filetree = {};
24 + var userinfo = null;
25 + var serverinfo = null;
26 + var events = [];
27 + var users = null;
28 + var wssessions = null;
29 + var nodeShortIdent = 0;
30 + var desktop;
31 + var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50, localkeymap: false };
32 + var multidesktopsettings = { quality: 20, scaling: 128, framerate: 1000 };
33 + var terminal;
34 + var files;
35 + var debugLevel = parseInt('{{{debuglevel}}}');
36 + var features = parseInt('{{{features}}}');
37 + var sessionTime = parseInt('{{{sessiontime}}}');
38 + var domain = '{{{domain}}}';
39 + var domainUrl = '{{{domainurl}}}';
40 + var authCookie = '{{{authCookie}}}';
41 + var authRelayCookie = '{{{authRelayCookie}}}';
42 + var logoutControls = {{{logoutControls}}};
43 + var authCookieRenewTimer = null;
44 + var multiDesktop = {};
45 + var multiDesktopFilter = null;
46 + var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
47 + var amtScanResults = null;
48 + var debugmode = 0;
49 + var clickOnce = (((features & 256) != 0) && detectClickOnce());
50 + var attemptWebRTC = ((features & 128) != 0);
51 + var passRequirements = '{{{passRequirements}}}';
52 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
53 + var deskAspectRatio = 0;
54 + try { deskAspectRatio = parseInt(getstore('deskAspectRatio', '0')); } catch (ex) { }
55 + var uiMode = parseInt(getstore('uiMode', 1));
56 + var webPageStackMenu = false;
57 + var webPageFullScreen = true;
58 + var nightMode = (getstore('_nightMode', '0') == '1');
59 + var sessionActivity = Date.now();
60 + var updateSessionTimer = null;
61 + var pluginHandlerBuilder = {{{pluginHandler}}};
62 + var pluginHandler = null;
63 + if (pluginHandlerBuilder != null) { pluginHandler = new pluginHandlerBuilder(); }
64 + var installedPluginList = null;
65 +
66 + // Console Message Display Timers
67 + var p11DeskConsoleMsgTimer = null;
68 + var p12TermConsoleMsgTimer = null;
69 + var p13FilesConsoleMsgTimer = null;
70 +
71 + function startup() {
72 + if ((features & 32) == 0) {
73 + // Guard against other site's top frames (web bugs).
74 + var loc = null;
75 + try { loc = top.location.toString().toLowerCase(); } catch (e) { }
76 + if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
77 + }
78 +
79 + // Setup logout control
80 + var logoutControl = '';
81 + if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); }
82 + if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Sair" + '</a>'); }
83 + QH('logoutControlSpan', logoutControl);
84 +
85 + // Check if we are in debug mode
86 + args = parseUriArgs();
87 + if (!args.locale) { var x = getstore('loctag', 0); if ((x != null) && (x != '*')) { args.locale = x; } }
88 + debugmode = args.debug;
89 + if (args.webrtc != null) { attemptWebRTC = (args.webrtc == 1); }
90 + QV('p13AutoConnect', debugmode); // Files
91 + QV('autoconnectbutton2', debugmode); // Terminal
92 + QV('autoconnectbutton1', debugmode); // Desktop
93 + //QV('DeskClip', debugmode); // Clipboard feature, not completed so show in in debug mode only.
94 +
95 + if (nightMode) { QC('body').add('night'); }
96 + toggleFullScreen();
97 +
98 + // Debug
99 + QV('cxtermunorm', debugmode == 1);
100 + QV('cxtermups', debugmode == 1);
101 +
102 + // Setup page visuals
103 + if (args.hide) {
104 + var hide = parseInt(args.hide);
105 + QV('masthead', !(hide & 1));
106 + QV('topbar', !(hide & 2));
107 + QV('footer', !(hide & 4));
108 + QV('p10title', !(hide & 8));
109 + QV('p11title', !(hide & 8));
110 + QV('p12title', !(hide & 8));
111 + QV('p13title', !(hide & 8));
112 + QV('p14title', !(hide & 8));
113 + QV('p15title', !(hide & 8));
114 + QV('p16title', !(hide & 8));
115 + //if (hide & 16) {
116 + // QV('page_leftbar', false);
117 + // QS('page_content').left = '0px';
118 + //}
119 +
120 + // Fix the main grid to zero-height elements we want to hide.
121 + QS('container')['grid-template-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
122 + QS('container')['-ms-grid-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
123 +
124 + // Adjust height of remote desktop, files and Intel AMT
125 + var xh = (((hide & 1) ? 0 : 66) + ((hide & 2) ? 0 : 24) + ((hide & 4) ? 0 : 45) + ((hide & 8) ? 0 : 60)); // 0 to 195
126 + QS('p3users')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
127 + QS('p3events')['height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
128 + QS('deskarea3x')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
129 + QS('deskarea3x')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
130 + QS('p5filetable')['height'] = 'calc(100vh - ' + (160 + xh) + 'px)';
131 + QS('p13filetable')['height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
132 + QS('serverMainStats')['height'] = 'calc(100vh - ' + (110 + xh) + 'px)';
133 + QS('serverMainStats')['max-height'] = 'calc(100vh - ' + (110 + xh) + 'px)';
134 + QS('xdevices')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
135 + QS('xdevicesmap')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
136 + QS('p15agentConsole')['height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
137 + QS('p15agentConsole')['max-height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
138 + QS('p15agentConsoleText')['height'] = 'calc(100vh - ' + (81 + xh) + 'px)';
139 + QS('p15agentConsoleText')['max-height'] = 'calc(100vh - ' + (81 + xh) + 'px)';
140 + QS('p43iframe')['height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
141 + QS('p43iframe')['max-height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
142 + }
143 +
144 + // We are looking at a single device, remove all the back buttons
145 + if ('{{currentNode}}' != '') {
146 + QV('p10BackButton', false);
147 + QV('p11BackButton', false);
148 + QV('p12BackButton', false);
149 + QV('p13BackButton', false);
150 + QV('p14BackButton', false);
151 + QV('p15BackButton', false);
152 + QV('p16BackButton', false);
153 + }
154 + p1updateInfo();
155 +
156 + // Setup the context menu
157 + document.onclick = function (e) { hideContextMenu(); }
158 + document.onkeypress = ondockeypress;
159 + document.onkeydown = ondockeydown;
160 + document.onkeyup = ondockeyup;
161 + //window.addEventListener('focus', ondocfocus, false);
162 + window.addEventListener('blur', ondocblur, false);
163 + window.onresize = function () { masterUpdate(512); }
164 + setTimeout(function() { masterUpdate(512); }, 200);
165 +
166 + // Connect to the mesh server
167 + meshserver = MeshServerCreateControl(domainUrl, authCookie);
168 + meshserver.onStateChanged = onStateChanged;
169 + meshserver.onMessage = onMessage;
170 + meshserver.trace = (args.trace == 1);
171 + meshserver.Start();
172 +
173 + // Setup page controls
174 + Q('sortselect').selectedIndex = sort = getstore('sort', 0);
175 + Q('sizeselect').selectedIndex = getstore('_viewsize', 1);
176 + Q('SearchInput').value = getstore('_search', '');
177 + showRealNames = (getstore('showRealNames', 0) == 1);
178 + Q('RealNameCheckBox').checked = showRealNames;
179 + Q('viewselect').value = getstore('_deviceView', 1);
180 + Q('DeskControl').checked = (getstore('DeskControl', 1) == 1);
181 + QV('accountChangeEmailAddressSpan', (features & 0x200000) == 0);
182 +
183 + // Display the page devices
184 + masterUpdate(3)
185 + for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
186 + Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
187 +
188 + // Setup upload drag & drop
189 + Q('p5filetable').addEventListener('drop', p5fileDragDrop, false);
190 + Q('p5filetable').addEventListener('dragover', p5fileDragOver, false);
191 + Q('p5filetable').addEventListener('dragleave', p5fileDragLeave, false);
192 + //Q('p5fileCatchAllInput').addEventListener('drop', p5fileDragDrop, false);
193 + //Q('p5fileCatchAllInput').addEventListener('dragover', p5fileDragOver, false);
194 + //Q('p5fileCatchAllInput').addEventListener('dragleave', p5fileDragLeave, false);
195 +
196 + // Setup upload drag & drop
197 + Q('p13filetable').addEventListener('drop', p13fileDragDrop, false);
198 + Q('p13filetable').addEventListener('dragover', p13fileDragOver, false);
199 + Q('p13filetable').addEventListener('dragleave', p13fileDragLeave, false);
200 +
201 + // Timeline update interval
202 + setInterval(updateDeviceTimeline, 120000); // Check every 2 minutes
203 +
204 + // Load desktop settings
205 + var t = localStorage.getItem('desktopsettings');
206 + if (t != null) { desktopsettings = JSON.parse(t); }
207 + t = localStorage.getItem('multidesktopsettings');
208 + if (t != null) { multidesktopsettings = JSON.parse(t); }
209 + applyDesktopSettings();
210 +
211 + // Terminal special keys
212 + var x = '';
213 + for (var c = 1; c < 27; c++) x += '<option value=\'' + c + '\'>' + "CTRL" + '-' + String.fromCharCode(64 + c) + ' (' + c + ')</option>';
214 + QH('specialkeylist', x);
215 +
216 + // Setup server stats panels
217 + setupGeneralServerStats();
218 + setupServerTimelineStats();
219 +
220 + // Setup the user interface in the right mode
221 + userInterfaceSelectMenu();
222 +
223 + // If SSPI or LDAP authentication not used, allow batch account creation.
224 + QV('p4UserBatchCreate', (features & 0x00080000) == 0);
225 + }
226 +
227 + // Toggle the web page to full screen
228 + function toggleAspectRatio(toggle) {
229 + if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); putstore('deskAspectRatio', deskAspectRatio); }
230 + deskAdjust();
231 + }
232 +
233 + // If FullScreen, toggle menu to be horisontal or vertical
234 + function toggleStackMenu(toggle) {
235 + if (webPageFullScreen == true) {
236 + if (toggle === 1) {
237 + webPageStackMenu = !webPageStackMenu;
238 + putstore('webPageStackMenu', webPageStackMenu);
239 + }
240 + if (webPageStackMenu == false) {
241 + QC('body').remove('menu_stack');
242 + } else {
243 + QC('body').add('menu_stack');
244 + if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
245 + }
246 + deskAdjust();
247 + }
248 + }
249 +
250 + // Toggle user interface menu
251 + function showUserInterfaceSelectMenu() {
252 + Q('uiViewButton1').classList.remove('uiSelectorSel');
253 + Q('uiViewButton2').classList.remove('uiSelectorSel');
254 + Q('uiViewButton3').classList.remove('uiSelectorSel');
255 + Q('uiViewButton4').classList.remove('uiSelectorSel');
256 + try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
257 + QV('uiMenu', (QS('uiMenu').display == 'none'));
258 + //Q('uiViewButton1').focus();
259 + if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
260 + }
261 +
262 + function userInterfaceSelectMenu(s) {
263 + if (s) { uiMode = s; putstore('uiMode', uiMode); }
264 + webPageFullScreen = (uiMode < 3);
265 + webPageStackMenu = (uiMode > 1);
266 + toggleFullScreen(0);
267 + toggleStackMenu(0);
268 + if (webPageStackMenu && (xxcurrentView >= 10)) { QC('column_l').add('room4submenu'); } else { QC('column_l').remove('room4submenu'); }
269 + }
270 +
271 + function toggleNightMode() {
272 + nightMode = !nightMode;
273 + if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
274 + putstore('_nightMode', nightMode?'1':'0');
275 + }
276 +
277 + // Toggle the web page to full screen
278 + function toggleFullScreen(toggle) {
279 + if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
280 + var hide = 0;
281 + if (args.hide) { hide = parseInt(args.hide); }
282 + if (webPageFullScreen == false) {
283 + QC('body').remove('menu_stack');
284 + QC('body').remove('fullscreen');
285 + QC('body').remove('arg_hide');
286 + if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
287 + QV('UserDummyMenuSpan', false);
288 + //QV('page_leftbar', false);
289 + } else {
290 + QC('body').add('fullscreen');
291 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
292 + QV('page_leftbar', !(hide & 16));
293 + QV('MainMenuSpan', !(hide & 16));
294 + if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
295 + QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
296 + }
297 + masterUpdate(512);
298 + QV('body', true);
299 + }
300 +
301 + function getNodeFromId(id) { if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } } return null; }
302 + function reload() {
303 + var x = window.location.href;
304 + if (x.endsWith('/#')) { x = x.substring(0, x.length - 2); }
305 + window.location.href = x;
306 + }
307 +
308 + function onStateChanged(server, state, prevState, errorCode) {
309 + if (state == 0) {
310 + // Control web socket disconnected
311 + setDialogMode(0); // Close any dialog boxes if present
312 + go(0); // Go to disconnection panel
313 +
314 + // Clean up
315 + powerTimeline = null;
316 + powerTimelineReq = null;
317 + powerTimelineNode = null;
318 + powerTimelineUpdate = null;
319 + deleteAllNotifications(); // Close and clear notifications if present
320 + hideContextMenu(); // Hide the context menu if present
321 + QV('verifyEmailId2', false);
322 + QV('logoutControl', false);
323 + if (errorCode == 'noauth') { QH('p0span', "Não foi possível executar a autenticação"); return; }
324 + if (prevState == 2) { if (autoReconnect) { setTimeout(serverPoll, 5000); } } else { QH('p0span', "Não foi possível conectar o soquete da web"); }
325 + if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
326 + } else if (state == 2) {
327 + // Fetch list of meshes, nodes, files
328 + meshserver.send({ action: 'meshes' });
329 + meshserver.send({ action: 'nodes', id: '{{currentNode}}' });
330 + if (pluginHandler != null) { meshserver.send({ action: 'plugins' }); }
331 + if ('{{currentNode}}' == '') { meshserver.send({ action: 'files' }); }
332 + if ('{{viewmode}}' == '') { go(1); }
333 + authCookieRenewTimer = setInterval(function () { meshserver.send({ action: 'authcookie' }); }, 1800000); // Request a cookie refresh every 30 minutes.
334 + }
335 + }
336 +
337 + // Poll the server, if it responds, refresh the page.
338 + function serverPoll() {
339 + var xdr = null;
340 + try { xdr = new XDomainRequest(); } catch (e) { }
341 + if (!xdr) xdr = new XMLHttpRequest();
342 + xdr.open('HEAD', window.location.href);
343 + xdr.timeout = 15000;
344 + xdr.onload = function () { reload(); };
345 + xdr.onerror = xdr.ontimeout = function () { setTimeout(serverPoll, 10000); };
346 + xdr.send();
347 + }
348 +
349 + // Return true if this browser supports clickonce
350 + function detectClickOnce() {
351 + for (var i in window.navigator.mimeTypes) { if (window.navigator.mimeTypes[i].type == 'application/x-ms-application') { return true; } }
352 + var userAgent = window.navigator.userAgent.toUpperCase();
353 + return (userAgent.indexOf('.NET CLR 3.5') >= 0) || (userAgent.indexOf('(WINDOWS NT ') >= 0);
354 + }
355 +
356 + function updateSiteAdmin() {
357 + var noServerBackup = '{{{noServerBackup}}}';
358 + var siteRights = userinfo.siteadmin;
359 + if (noServerBackup == 1) { siteRights &= 0xFFFFFFFA; } // If not server backups allowed, remove server backup and restore permissions
360 +
361 + // Update account actions
362 + QV('p2AccountSecurity', ((features & 4) == 0) && (serverinfo.domainauth == false) && ((features & 4096) != 0)); // Hide Account Security if in single user mode, domain authentication to 2 factor auth not supported.
363 + QV('p2AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
364 + QV('p2AccountImage', ((features & 4) == 0) && (serverinfo.domainauth == false)); // If account actions are not visible, also remove the image on that panel
365 + QV('p2ServerActions', siteRights & 21);
366 + QV('LeftMenuMyServer', siteRights & 21); // 16 + 4 + 1
367 + QV('MainMenuMyServer', siteRights & 21);
368 + QV('p2ServerActionsBackup', siteRights & 1);
369 + QV('p2ServerActionsRestore', siteRights & 4);
370 + QV('p2ServerActionsVersion', siteRights & 16);
371 + QV('MainMenuMyFiles', siteRights & 8);
372 + QV('LeftMenuMyFiles', siteRights & 8);
373 + if (((siteRights & 8) == 0) && (xxcurrentView == 5)) { setDialogMode(0); go(1); }
374 + if (currentNode != null) { gotoDevice(currentNode._id, xxcurrentView, true); }
375 +
376 + // Update user management state
377 + if ((userinfo.siteadmin & 2) != 0)
378 + {
379 + // We are user administrator
380 + if (users == null) { meshserver.send({ action: 'users' }); }
381 + if (wssessions == null) { meshserver.send({ action: 'wssessioncount' }); }
382 + } else {
383 + // We are not user administrator
384 + users = null;
385 + wssessions = null;
386 + updateUsers();
387 + if (xxcurrentView == 4 || ((xxcurrentView >= 30) && (xxcurrentView < 40))) { setDialogMode(0); go(1); currentUser = null; }
388 + }
389 + meshserver.send({ action: 'events', limit: parseInt(p3limitdropdown.value) });
390 + QV('ServerConsole', userinfo.siteadmin === 0xFFFFFFFF);
391 + QV('ServerTrace', userinfo.siteadmin === 0xFFFFFFFF);
392 + if ((xxcurrentView == 115) && (userinfo.siteadmin != 0xFFFFFFFF)) { go(6); }
393 + if ((xxcurrentView == 6) && ((userinfo.siteadmin & 21) == 0)) { go(1); }
394 +
395 + // If we are site administrator, register to get server statistics
396 + if ((siteRights & 21) != 0) { meshserver.send({ action: 'serverstats', interval: 10000 }); }
397 + }
398 +
399 + // To boost the speed of the web page when even floods occur, this method perform a delayed update on the web page.
400 + var updateNaggleTimer = null;
401 + var updateNaggleFlags = 0;
402 + function masterUpdate(flags) {
403 + updateNaggleFlags |= flags;
404 + if (updateNaggleTimer == null) {
405 + updateNaggleTimer = setTimeout(function () {
406 + if (updateNaggleFlags & 512) { center(); }
407 + if (updateNaggleFlags & 1) { onSearchInputChanged(); }
408 + if (updateNaggleFlags & 2) { onSortSelectChange(false); }
409 + if (updateNaggleFlags & 128) { updateMeshes(); }
410 + if (updateNaggleFlags & 4) { updateDevices(); }
411 + if (updateNaggleFlags & 8) { drawNotifications(); }
412 + {{{StartGeoLocationJS}}}if (updateNaggleFlags & 16) { updateMapMarkers(); }{{{EndGeoLocationJS}}}
413 + if (updateNaggleFlags & 32) { eventsUpdate(); }
414 + {{{StartGeoLocationJS}}}if (updateNaggleFlags & 64) { refreshMap(false, true); }{{{EndGeoLocationJS}}}
415 + if (updateNaggleFlags & 256) { drawDeviceTimeline(); }
416 + if (updateNaggleFlags & 1024) { deviceEventsUpdate(); }
417 + if (updateNaggleFlags & 2048) { userEventsUpdate(); }
418 + if (updateNaggleFlags & 4096) { p20updateMesh(); }
419 + updateNaggleTimer = null;
420 + updateNaggleFlags = 0;
421 + }, 150);
422 + }
423 + }
424 +
425 + var backupCodesWarningDone = false;
426 + function updateSelf() {
427 + QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
428 + QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
429 + QV('manageOtp', (userinfo.otpsecret == 1) || (userinfo.otphkeys > 0));
430 + QV('authAppSetupCheck', userinfo.otpsecret == 1);
431 + QV('authKeySetupCheck', userinfo.otphkeys > 0);
432 + QV('authCodesSetupCheck', userinfo.otpkeys > 0);
433 + masterUpdate(4 + 128 + 4096);
434 +
435 + // Check if backup codes should really be enabled
436 + if ((backupCodesWarningDone == false) && !(userinfo.otpkeys > 0) && (((userinfo.otpsecret == 1) && !(userinfo.otphkeys > 0)) || ((userinfo.otpsecret != 1) && (userinfo.otphkeys == 1)))) {
437 + var n = { text: "Adicione códigos de backup de dois fatores. Se o fator atual for perdido, não há como recuperar esta conta.", title: "Autenticação de dois fatores" };
438 + addNotification(n);
439 + backupCodesWarningDone = true;
440 + }
441 +
442 + // If we can't create new groups, hide all links that can do that.
443 + var newGroupsAllowed = ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0));
444 + QV('p2createMeshLink1', newGroupsAllowed);
445 + QV('p2createMeshLink2', newGroupsAllowed);
446 + QV('getStarted1', newGroupsAllowed);
447 + QV('getStarted2', !newGroupsAllowed);
448 +
449 + if (typeof userinfo.passchange == 'number') {
450 + if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', "- Redefinir no próximo login."); }
451 + else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
452 + var seconds = (userinfo.passchange) + (passRequirements.reset * 86400) - Math.floor(Date.now() / 1000);
453 + if (seconds < 0) { QH('p2nextPasswordUpdateTime', "- Redefinir no próximo login."); }
454 + else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} minuto {1}.", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
455 + else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} hora {1}.", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
456 + else { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} dia {1}."), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
457 + }
458 + }
459 + }
460 +
461 + function addLetterS(x) { return (x > 1) ? 's' : ''; }
462 + function setSessionActivity() { sessionActivity = Date.now(); QH('idleTimeoutNotify', ''); }
463 + function checkIdleSessionTimeout() {
464 + var delta = (Date.now() - sessionActivity);
465 + if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else {
466 + var ds = Math.round((serverinfo.timeout - delta) / 1000);
467 + if (ds <= 60) {
468 + QH('idleTimeoutNotify', '<br />' + format("{0} segundo{1} até desconectar", ds, addLetterS(ds)));
469 + } else {
470 + ds = Math.round(ds / 60);
471 + if (ds <= 5) { QH('idleTimeoutNotify', '<br />' + format("{0} minutos{1} até desconectar", ds, addLetterS(ds))); }
472 + }
473 + }
474 + }
475 +
476 + function onMessage(server, message) {
477 + switch (message.action) {
478 + case 'trace': {
479 + serverTrace.unshift(message);
480 + displayServerTrace();
481 + break;
482 + }
483 + case 'traceinfo': {
484 + if (typeof message.traceSources == 'object') {
485 + if ((message.traceSources != null) && (message.traceSources.length > 0)) {
486 + serverTraceSources = message.traceSources;
487 + QH('p41traceStatus', EscapeHtml(message.traceSources.join(', ')));
488 + } else {
489 + serverTraceSources = [];
490 + QH('p41traceStatus', "Nenhum");
491 + }
492 + }
493 + break;
494 + }
495 + case 'serverstats': {
496 + updateGeneralServerStats(message);
497 + break;
498 + }
499 + case 'serverwarnings': {
500 + if ((message.warnings != null) && (message.warnings.length > 0)) {
501 + var x = '';
502 + for (var i in message.warnings) { x += '<div style=color:red;padding-bottom:6px><b>' + "WARNING: " + message.warnings[i] + '</b></div>'; }
503 + QH('serverWarnings', x);
504 + QV('serverWarningsDiv', true);
505 + }
506 + break;
507 + }
508 + case 'servertimelinestats': {
509 + setServerTimelineStats(message.events);
510 + break;
511 + }
512 + case 'authcookie': {
513 + // Got an authentication cookie refresh
514 + authCookie = message.cookie;
515 + authRelayCookie = message.rcookie;
516 + break;
517 + }
518 + case 'serverinfo': {
519 + serverinfo = message.serverinfo;
520 + if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
521 + if (debugmode == 1) { console.log('Server time: ', printDateTime(new Date(serverinfo.serverTime))); }
522 + break;
523 + }
524 + case 'userinfo': {
525 + userinfo = message.userinfo;
526 + updateSiteAdmin();
527 + updateSelf();
528 + break;
529 + }
530 + case 'users': {
531 + users = {};
532 + for (var m in message.users) { users[message.users[m]._id] = message.users[m]; }
533 + updateUsers();
534 + break;
535 + }
536 + case 'wssessioncount': {
537 + wssessions = message.wssessions;
538 + updateUsers();
539 + break;
540 + }
541 + case 'meshes': {
542 + meshes = {};
543 + for (var m in message.meshes) { meshes[message.meshes[m]._id] = message.meshes[m]; }
544 + masterUpdate(4 + 128);
545 + break;
546 + }
547 + case 'files': {
548 + filetree = setupBackPointers(message.filetree);
549 + updateFiles();
550 + d3updatefiles();
551 + break;
552 + }
553 + case 'nodes': {
554 + nodes = [];
555 + for (var m in message.nodes) {
556 + if (!meshes[m]) { console.log('Invalid mesh (1): ' + m); continue; }
557 + for (var n in message.nodes[m]) {
558 + if (message.nodes[m][n]._id == null) { console.log('Invalid node (' + n + '): ' + JSON.stringify(message.nodes)); continue; }
559 + message.nodes[m][n].namel = message.nodes[m][n].name.toLowerCase();
560 + if (message.nodes[m][n].rname) { message.nodes[m][n].rnamel = message.nodes[m][n].rname.toLowerCase(); } else { message.nodes[m][n].rnamel = message.nodes[m][n].namel; }
561 + message.nodes[m][n].meshnamel = meshes[m].name.toLowerCase();
562 + message.nodes[m][n].meshid = m;
563 + message.nodes[m][n].state = (message.nodes[m][n].state)?(message.nodes[m][n].state):0;
564 + message.nodes[m][n].desc = message.nodes[m][n].desc;
565 + message.nodes[m][n].ip = message.nodes[m][n].ip;
566 + if (!message.nodes[m][n].icon) message.nodes[m][n].icon = 1;
567 + message.nodes[m][n].ident = ++nodeShortIdent;
568 + nodes.push(message.nodes[m][n]);
569 + }
570 + }
571 + masterUpdate(1 | 2 | 4 | 64);
572 +
573 + if (xxcurrentView == -1) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(1); } }
574 + if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}',parseInt('{{viewmode}}'));}
575 + break;
576 + }
577 + case 'powertimeline': {
578 + if (message.nodeid != powerTimelineReq) break;
579 + powerTimelineNode = message.nodeid;
580 + powerTimeline = message.timeline;
581 + powerTimelineUpdate = Date.now() + 300000; // Update every 5 minutes
582 + for (var i in powerTimeline) { if (i % 2 == 1) { powerTimeline[i] = powerTimeline[i] * 1000; } } // Decompress time
583 + if (currentNode._id == message.nodeid) { masterUpdate(256); }
584 + break;
585 + }
586 + case 'getsysinfo': {
587 + if (message.nodeid != powerTimelineReq) break;
588 + //console.log('getsysinfo', message); // ***********************
589 + if (message.noinfo === true) {
590 + QH('p17info', "Nenhuma informação para este dispositivo.");
591 + } else {
592 + var x = '', s = {};
593 + if (message.hardware) {
594 + if (message.hardware.identifiers) {
595 + var ident = message.hardware.identifiers;
596 + // BIOS
597 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "BIOS" + '</b></div>';
598 + if (ident.bios_vendor) { x += addDetailItem("Fornecedor", ident.bios_vendor, s); }
599 + if (ident.bios_version) { x += addDetailItem("Versão", ident.bios_version, s); }
600 + x += '<br />';
601 +
602 + // Motherboard
603 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Placa-mãe" + '</b></div>';
604 + if (ident.board_vendor) { x += addDetailItem("Fornecedor", ident.board_vendor, s); }
605 + if (ident.board_name) { x += addDetailItem("Nome", ident.board_name, s); }
606 + if (ident.board_serial && (ident.board_serial != '')) { x += addDetailItem("Serial", ident.board_serial, s); }
607 + if (ident.board_version) { x += addDetailItem("Versão", ident.board_version, s); }
608 + if (ident.product_uuid) { x += addDetailItem("Identificador", ident.product_uuid, s); }
609 + x += '<br />';
610 + }
611 +
612 + if (message.hardware.windows) {
613 + if (message.hardware.windows.memory) {
614 + // Memory
615 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Memória" + '</b></div>';
616 +
617 + // Sort Memory
618 + function memorySort(a, b) { if (a.BankLabel > b.BankLabel) return 1; if (a.BankLabel < b.BankLabel) return -1; return 0; }
619 + message.hardware.windows.memory.sort(memorySort);
620 +
621 + x += '<table style=width:100%>';
622 + for (var i in message.hardware.windows.memory) {
623 + var m = message.hardware.windows.memory[i];
624 + x += '<tr><td VALIGN=Top style=width:38px><img src="images/ram2.png" />'
625 + x += '<td><div style=background-color:lightgray;border-radius:5px;padding:8px>';
626 + x += '<div><b>' + m.BankLabel + '</b></div>';
627 + if (m.Capacity) { x += addDetailItem("Capacidade / velocidade", format("{0} Mb, {1} Mhz", (m.Capacity / 1024 / 1024), m.Speed), s); }
628 + if (m.PartNumber) { x += addDetailItem("Número Parcial", ((m.Manufacturer && m.Manufacturer != 'Undefined')?(m.Manufacturer + ', '):'') + m.PartNumber, s); }
629 + x += '</div>';
630 + }
631 + x += '</table><br />';
632 + }
633 +
634 + if (message.hardware.windows.osinfo) {
635 + // Operating System
636 + var m = message.hardware.windows.osinfo;
637 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Sistema operacional" + '</b></div>';
638 + if (m.Caption) { x += addDetailItem("Nome", m.Caption, s); }
639 + if (m.Version) { x += addDetailItem("Versão", m.Version, s); }
640 + if (m.OSArchitecture) { x += addDetailItem("Arquitetura", m.OSArchitecture, s); }
641 + x += '<br />';
642 + }
643 +
644 + // Disks
645 + //x += '<div class=DevSt style=margin-bottom:3px><b>Disks</b></div>';
646 + //x += '<br />';
647 + }
648 + }
649 +
650 + QH('p17info', x);
651 + }
652 + break;
653 + }
654 + case 'lastconnect': {
655 + var node = getNodeFromId(message.nodeid);
656 + if (node != null) {
657 + node.lastconnect = message.time;
658 + node.lastaddr = message.addr;
659 + if ((currentNode._id == node._id) && (Q('MainComputerState').innerHTML == '')) {
660 + QH('MainComputerState', '<span>' + "Visto pela última vez:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>');
661 + }
662 + }
663 + break;
664 + }
665 + case 'msg': {
666 + // Check if this is a message from a node
667 + if (message.nodeid != null) {
668 + var index = -1;
669 + if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } } }
670 + if (index != -1) {
671 + // Node was found, dispatch the message
672 + if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
673 + else if (message.type == 'notify') { // This is a notification message.
674 + var n = getstore('notifications', 0);
675 + if (((n & 8) == 0) && (message.amtMessage != null)) { break; } // Intel AMT desktop & terminal messages should be ignored.
676 + var n = { text: message.value, title: message.title, icon: message.icon };
677 + if (message.nodeid != null) { n.nodeid = message.nodeid; }
678 + if (message.tag != null) { n.tag = message.tag; }
679 + if (message.username != null) { n.username = message.username; }
680 + addNotification(n);
681 + } else if (message.type == 'ps') {
682 + showDeskToolsProcesses(message);
683 + } else if (message.type == 'services') {
684 + showDeskToolsServices(message);
685 + } else if ((message.type == 'getclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
686 + Q('d2clipText').value = message.data;
687 + } else if ((message.type == 'setclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
688 + // Display success/fail on the clipboard dialog box.
689 + QH('dlgClipStatus', message.success ? '<span style=color:green>' + "Sucesso" + '</span>' : '<span style=color:red>' + "Falhou" + '</span>')
690 + setTimeout(function () { try { QH('dlgClipStatus', ''); } catch (ex) { } }, 2000);
691 + }
692 + }
693 + } else {
694 + if (message.type == 'notify') { // This is a notification message.
695 + var n = { text: message.value, title: message.title, icon: message.icon };
696 + if (message.tag != null) { n.tag = message.tag; }
697 + if (message.username != null) { n.username = message.username; }
698 + addNotification(n);
699 + }
700 + }
701 + break;
702 + }
703 + case 'getnetworkinfo': {
704 + if ((currentNode._id == message.nodeid) && (xxdialogMode == 2) && (xxdialogTag == 'if' + message.nodeid)) {
705 + if (message.netif == null) {
706 + QH('d2netinfo', "Nenhuma informação de interface de rede disponível para este dispositivo.");
707 + } else {
708 + var x = '<div class=dialogText>';
709 +
710 + if (currentNode.lastconnect) { x += addHtmlValue2("Última conexão do agente", printDateTime(new Date(currentNode.lastconnect))); }
711 + if (currentNode.lastaddr) {
712 + var splitip = currentNode.lastaddr.split(':');
713 + if (splitip.length > 2) {
714 + // IPv6
715 + x += addHtmlValue2("Último endereço do agente", currentNode.lastaddr + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(currentNode.lastaddr) + '\") width=10 height=10>');
716 + } else {
717 + // IPv4
718 + if (isPrivateIP(currentNode.lastaddr)) {
719 + x += addHtmlValue2("Último endereço do agente", splitip[0] + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
720 + } else {
721 + x += addHtmlValue2("Último endereço do agente", '<a href="https://iplocation.com/?ip=' + splitip[0] + '" rel="noreferrer noopener" target="MeshIPLoopup">' + splitip[0] + '</a> <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
722 + }
723 + }
724 + }
725 +
726 + x += addHtmlValue2("Última atualização de interfaces", printDateTime(new Date(message.updateTime)));
727 + for (var i in message.netif) {
728 + var net = message.netif[i];
729 + x += '<hr />'
730 + if (net.name) { x += addHtmlValue2("Nome", '<b>' + EscapeHtml(net.name) + '</b>'); }
731 + if (net.desc) { x += addHtmlValue2("Descrição", EscapeHtml(net.desc).replace('(R)', '&reg;').replace('(r)', '&reg;')); }
732 + if (net.dnssuffix) { x += addHtmlValue2("Sufixo DNS", EscapeHtml(net.dnssuffix) + ' <img src="images/link4.png" title="' + "Copiar nome para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.dnssuffix) + '\") width=10 height=10>'); }
733 + if (net.mac) { x += addHtmlValue2("Endereço MAC", '<a href="https://dnslytics.com/mac-address-lookup/' + net.mac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.mac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copiar endereço MAC para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.mac.toLowerCase()) + '\") width=10 height=10>'); }
734 + if (net.v4addr) { x += addHtmlValue2("Endereço IPv4", EscapeHtml(net.v4addr) + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4addr) + '\") width=10 height=10>'); }
735 + if (net.v4mask) { x += addHtmlValue2("Máscara IPv4", EscapeHtml(net.v4mask) + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4mask) + '\") width=10 height=10>'); }
736 + if (net.v4gateway) { x += addHtmlValue2("Gateway IPv4", EscapeHtml(net.v4gateway) + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4gateway) + '\") width=10 height=10>'); }
737 + if (net.gatewaymac) { x += addHtmlValue2("Gateway MAC", '<a href="https://dnslytics.com/mac-address-lookup/' + net.gatewaymac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.gatewaymac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copiar endereço MAC para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.gatewaymac.toLowerCase()) + '\") width=10 height=10>'); }
738 + }
739 + x += '</div>';
740 + QH('d2netinfo', x);
741 + }
742 + }
743 + break;
744 + }
745 + case 'serverversion': {
746 + if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerUpdate')) {
747 + var x = '<div class=dialogText>';
748 + if (!message.current) { message.current = "Desconhecido"; }
749 + if (!message.latest) { message.latest = "Desconhecido"; }
750 + x += addHtmlValue2("Versão Atual", '<b>' + EscapeHtml(message.current) + '</b>');
751 + x += addHtmlValue2("Última versão", '<b>' + EscapeHtml(message.latest) + '</b>');
752 + x += '</div>';
753 + if ((message.latest.indexOf('.') == -1) || (message.current == message.latest) || ((features & 2048) == 0)) {
754 + setDialogMode(2, "Versão MeshCentral", 1, null, x);
755 + } else {
756 + setDialogMode(2, "Versão MeshCentral", 3, server_showVersionDlgEx, x + '<br /><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Marque e clique em OK para iniciar a atualização automática do servidor." + '</label>');
757 + server_showVersionDlgUpdate();
758 + }
759 + }
760 + break;
761 + }
762 + case 'servererrors': {
763 + if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerErrors')) {
764 + if (message.data == null) {
765 + setDialogMode(2, "Erros do servidor MeshCentral", 1, null, "O servidor não possui log de erros.");
766 + } else {
767 + var x = '<div class="dialogText dialogTextLog"><pre id=d2ServerErrorsLogPre>' + message.data + '<pre></div>';
768 + setDialogMode(2, "Erros do servidor MeshCentral", 3, server_showErrorsDlgEx, x + '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="' + "Baixar log de erro" + '" style=cursor:pointer onclick=d2CopyServerErrorsToClip()></div><div><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Verifique e clique em OK para limpar o log de erros." + '</label></div>');
769 + server_showVersionDlgUpdate();
770 + }
771 + }
772 + break;
773 + }
774 + case 'serverconsole': {
775 + p15consoleReceive('serverconsole', message.value);
776 + break;
777 + }
778 + case 'events': {
779 + if ((message.nodeid != null) && (message.nodeid == currentNode._id)) {
780 + currentDeviceEvents = message.events;
781 + masterUpdate(1024);
782 + } else if ((message.user != null) && (message.user == currentUser.name)) {
783 + currentUserEvents = message.events;
784 + masterUpdate(2048);
785 + } else {
786 + events = message.events;
787 + masterUpdate(32);
788 + }
789 + break;
790 + }
791 + case 'getcookie': {
792 + if (message.tag == 'clickonce') {
793 + var basicPort = '{{{serverRedirPort}}}' == '' ? '{{{serverPublicPort}}}' : '{{{serverRedirPort}}}';
794 + var rdpurl = 'http://' + window.location.hostname + ':' + basicPort + '/clickonce/minirouter/MeshMiniRouter.application?WS=wss%3A%2F%2F' + window.location.hostname + '%2Fmeshrelay.ashx%3Fauth=' + message.cookie + '&CH={{{webcerthash}}}&AP=' + message.protocol + ((debugmode == 1) ? '' : '&HOL=1');
795 + var newWindow = window.open(rdpurl, '_blank');
796 + newWindow.opener = null;
797 + }
798 + break;
799 + }
800 + case 'getNotes': {
801 + var n = Q('d2devNotes');
802 + if (n && (message.id == decodeURIComponent(n.attributes['noteid'].value))) {
803 + if (message.notes) { QH('d2devNotes', decodeURIComponent(message.notes)); } else { QH('d2devNotes', ''); }
804 + var ro = (n.attributes['ro'].value == 'true');
805 + if (ro == false) { // If we have permissions, set read/write on this note.
806 + n.removeAttribute('readonly');
807 + QE('idx_dlgOkButton', true);
808 + QV('idx_dlgOkButton', true);
809 + focusTextBox('d2devNotes');
810 + }
811 + }
812 + break;
813 + }
814 + case 'otpauth-request': {
815 + if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-request')) {
816 + var secret = message.secret;
817 + if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
818 + else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
819 + QH('d2optinfo', '<table style=width:380px><tr><td style=vertical-align:top>' + "Install <a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank>Google Authenticator</a> or a compatible application and scan the barcode, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login." + '<br /><br />Secret<br /><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:12px>' + secret + '</tt><br /><br /></td><td style=width:1px;vertical-align:top><a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank><div id="qrcode"></div></a></td><tr><td colspan=2 style="text-align:center;border-top:1px solid black"><br />' + "Digite o token aqui para o login em duas etapas:" + ' <input type=text onkeypress=\"return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></td></table>');
820 + new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H });
821 + QV('idx_dlgOkButton', true);
822 + QE('idx_dlgOkButton', false);
823 + Q('d2otpauthinput').focus();
824 + }
825 + break;
826 + }
827 + case 'otpauth-setup': {
828 + if (xxdialogMode) return;
829 + setDialogMode(2, "Autenticador de aplicativo", 1, null, message.success ? ('<b style=color:green>' + "Ativação do aplicativo autenticador bem-sucedida." + '</b> ' + "Agora você precisará de um token válido para fazer login novamente.") : ('<b style=color:red>' + "Falha na ativação do login em duas etapas." + '</b> ' + "Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto."));
830 + break;
831 + }
832 + case 'otpauth-clear': {
833 + if (xxdialogMode) return;
834 + setDialogMode(2, "Autenticador de aplicativo", 1, null, message.success ? ('<b>' + "Aplicativo autenticador removido." + '</b> ' + "Você pode reativar esse recurso a qualquer momento.") : ('<b style=color:red>' + "A remoção da ativação do login em duas etapas falhou." + '</b> ' + "Tente novamente."));
835 + break;
836 + }
837 + case 'otpauth-getpasswords': {
838 + if (xxdialogMode) return;
839 + var x = "Os tokens únicos podem ser usados como autenticação secundária. Gere um conjunto, imprima-os e mantenha-os em um local seguro.";
840 + x += '<div style="border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px"><div style="padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold"><table class=selecttext style=width:100%;text-align:center>';
841 + if (message.passwords) {
842 + var j = 0, clipb = '';
843 + for (var i in message.passwords) {
844 + if (++j % 2) { x += '<tr>'; }
845 + var p = '' + message.passwords[i].p;
846 + while (p.length < 8) { p = '0' + p; }
847 + if (message.passwords[i].u === true) {
848 + x += '<td>' + p.substring(0, 4) + '&nbsp;' + p.substring(4);
849 + if (clipb != '') { clipb += ' '; }
850 + clipb += p;
851 + } else {
852 + x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + '&nbsp;' + p.substring(4); + '</strike>';
853 + }
854 + }
855 + } else {
856 + x += '<tr><td>' + "Nenhum token ativo";
857 + }
858 + x += '</table></div></div><br />';
859 + x += '<div><input type=button value=' + "Fechar" + ' onclick=setDialogMode(0) style=float:right></input>';
860 + x += '<input type=button value="' + "Gere novos tokens" + '" onclick="account_manageOtp(1);"></input>';
861 + if (message.passwords != null) {
862 + x += '<input type=button value="' + "Limpar Tokens" + '" onclick="account_manageOtp(2);"></input>';
863 + x += '&nbsp;<img src=images/link4.png height=10 width=10 title="' + "Copiar códigos válidos para a área de transferência" + '" style=cursor:pointer onclick=copyTextToClip2("' + encodeURIComponent(clipb) + '")>';
864 + }
865 + x += '</div><br />';
866 + setDialogMode(2, "Gerenciar códigos de backup", 8, null, x, 'otpauth-manage');
867 + break;
868 + }
869 + case 'otp-hkey-get': {
870 + if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
871 + var start = '<div style="border-radius:6px;border:2px solid #CCC;background-color:#BBB;width:100%;box-sizing:border-box;margin-bottom:6px"><div style="margin:3px;font-family:Arial, Helvetica, sans-serif;font-size:16px;font-weight:bold"><table style=width:100%;text-align:left>';
872 + var end = '</table></div></div>';
873 + var x = "<a href=\"https://www.yubico.com/\" rel=\"noreferrer noopener\" target=\"_blank\">Chaves Hardware</a> são usados como autenticação de login secundária.";
874 + x += '<div style="max-height:150px;overflow-y:auto;overflow-x:hidden;margin-top:6px;margin-bottom:6px">';
875 + if (message.keys && message.keys.length > 0) {
876 + for (var i in message.keys) {
877 + var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
878 + x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remover" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
879 + }
880 + } else {
881 + x += start + '<tr style=text-align:center><td>' + "Nenhuma chave configurada" + end;
882 + }
883 + x += '</div>';
884 + x += '<div><input type=button value="' + "Fechar" + '" onclick=setDialogMode(0) style=float:right></input>';
885 + if ((features & 0x00020000) != 0) { x += '<input id=d2addkey3 type=button value="' + "Adicionar chave" + '" onclick="account_addhkey(3);"></input>'; }
886 + if ((features & 0x00004000) != 0) { x += '<input id=d2addkey2 type=button value="' + "Adicione YubiKeyreg; OTP" + '" onclick="account_addhkey(2);"></input>'; }
887 + x += '</div><br />';
888 + setDialogMode(2, "Gerenciar chaves de segurança", 8, null, x, 'otpauth-hardware-manage');
889 + if (u2fSupported() == false) { QE('d2addkey1', false); }
890 + break;
891 + }
892 + case 'otp-hkey-yubikey-add': {
893 + if (message.result) {
894 + meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
895 + } else {
896 + setDialogMode(2, "Adicionar chave de segurança", 1, null, '<br />' + "Erro, não foi possível adicionar a chave." + '<br /><br />');
897 + }
898 + break;
899 + }
900 + case 'otp-hkey-setup-response': {
901 + if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
902 + if (message.result == true) {
903 + meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
904 + } else {
905 + setDialogMode(2, "Adicionar chave de segurança", 1, null, '<br />' + "ERRO: Não foi possível adicionar a chave." + '<br /><br />', 'otpauth-hardware-manage');
906 + }
907 + break;
908 + }
909 + case 'webauthn-startregister': {
910 + if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
911 + var x = "Pressione o botão da tecla agora." + '<br /><br /><div style=width:100%;text-align:center><img width=120 height=117 src="images/hardware-keypress-120.png" /></div><input id=dp1keyname style=display:none value=' + message.name + ' />';
912 + setDialogMode(2, "Adicionar chave de segurança", 2, null, x);
913 +
914 + var publicKey = message.request;
915 + message.request.challenge = Uint8Array.from(atob(message.request.challenge), function (c) { return c.charCodeAt(0) })
916 + message.request.user.id = Uint8Array.from(atob(message.request.user.id), function (c) { return c.charCodeAt(0) })
917 + navigator.credentials.create({ publicKey: publicKey })
918 + .then(function(newCredentialInfo) {
919 + // Public key credential
920 + var r = { rawId: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.rawId))), response: { attestationObject: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.attestationObject))), clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.clientDataJSON))) }, type: newCredentialInfo.type };
921 + meshserver.send({ action: 'webauthn-endregister', response: r });
922 + setDialogMode(0);
923 + }, function(error) {
924 + // Error
925 + setDialogMode(2, "Adicionar chave de segurança", 1, null, "ERRO:" + error);
926 + });
927 + break;
928 + }
929 + case 'event': {
930 + if (!message.event.nolog) {
931 + if (currentNode && (message.event.nodeid == currentNode._id)) {
932 + // If this event has a nodeid and we are looking at this node, update the log in real time.
933 + currentDeviceEvents.unshift(message.event);
934 + var eventLimit = parseInt(p16limitdropdown.value);
935 + while (currentDeviceEvents.length > eventLimit) { currentDeviceEvents.pop(); } // Remove element(s) at the end
936 + masterUpdate(1024);
937 + }
938 +
939 + if (currentUser && (message.event.userid == currentUser._id)) {
940 + // If this event has a userid and we are looking at this user, update the log in real time.
941 + currentUserEvents.unshift(message.event);
942 + var eventLimit = parseInt(p31limitdropdown.value);
943 + while (currentUserEvents.length > eventLimit) { currentUserEvents.pop(); } // Remove element(s) at the end
944 + masterUpdate(2048);
945 + }
946 +
947 + // Add this event to the master events log.
948 + events.unshift(message.event);
949 + var eventLimit = parseInt(p3limitdropdown.value);
950 + while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
951 + masterUpdate(32);
952 + }
953 + if (message.event.noact) break; // Take no action on this event
954 + switch (message.event.action) {
955 + case 'userWebState': {
956 + // New user web state, update the web page as needed
957 + if (localStorage != null) {
958 + var oldShowRealNames = localStorage.getItem('showRealNames');
959 + var oldUiMode = localStorage.getItem('uiMode');
960 + var oldSort = localStorage.getItem('sort');
961 + var oldLoctag = localStorage.getItem('loctag');
962 +
963 + var webstate = JSON.parse(message.event.state);
964 + for (var i in webstate) { localStorage.setItem(i, webstate[i]); }
965 +
966 + // Update the web page
967 + if ((webstate.deskAspectRatio != null) && (webstate.deskAspectRatio != deskAspectRatio)) { deskAspectRatio = webstate.deskAspectRatio; deskAdjust(); }
968 + if ((webstate.showRealNames != null) && (webstate.showRealNames != oldShowRealNames)) { showRealNames = Q('RealNameCheckBox').checked = (webstate.showRealNames == '1'); masterUpdate(6); }
969 + if ((webstate.uiMode != null) && (webstate.uiMode != oldUiMode)) { userInterfaceSelectMenu(parseInt(webstate.uiMode)); }
970 + if ((webstate.sort != null) && (webstate.sort != oldSort)) { document.getElementById('sortselect').selectedIndex = sort = parseInt(webstate.sort); masterUpdate(6); }
971 + if ((webstate.loctag != null) && (webstate.loctag != oldLoctag)) { if (webstate.loctag != null) { args.locale = webstate.loctag; } else { delete args.locale; } masterUpdate(0xFFFFFFFF); }
972 + }
973 + break;
974 + }
975 + case 'servertimelinestats': { addServerTimelineStats(message.event.data); break; }
976 + case 'accountcreate':
977 + case 'accountchange': {
978 + // An account was created or changed
979 + if (userinfo.name == message.event.account.name) {
980 + var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
981 + var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
982 + if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
983 + var oldgroups = userinfo.groups;
984 + userinfo = message.event.account;
985 + if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
986 + updateSelf();
987 +
988 + if ((userinfo.siteadmin & 2) != 0) {
989 + // Compare our groups
990 + var og = oldgroups ? oldgroups : [];
991 + var ng = userinfo.groups ? userinfo.groups : [];
992 + if (og.join(',') != ng.join(',')) {
993 + // Our groups have changed, re-ask for a list of users.
994 + users = wssessions = null;
995 + meshserver.send({ action: 'users' });
996 + meshserver.send({ action: 'wssessioncount' });
997 + }
998 + }
999 + }
1000 + if (users == null) break;
1001 +
1002 + // Check if the account is part of our user group
1003 + if ((userinfo.groups == null) || (userinfo.groups.length == 0) || (findOne(message.event.account.groups, userinfo.groups) == true)) {
1004 + users[message.event.account._id] = message.event.account; // Part of our groups, update this user.
1005 + } else {
1006 + delete users[message.event.account._id]; // No longer part of our groups, remove this user.
1007 + }
1008 +
1009 + updateUsers();
1010 + break;
1011 + }
1012 + case 'accountremove': {
1013 + // An account was removed
1014 + if (users == null) break;
1015 + delete users['user/' + domain + '/' + message.event.username.toLowerCase()];
1016 + updateUsers();
1017 + break;
1018 + }
1019 + case 'createmesh': {
1020 + // A new mesh was created
1021 + if ((meshes[message.event.meshid] == null) && (message.event.links[userinfo._id] != null)) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some.
1022 + meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
1023 + masterUpdate(4 + 128);
1024 + meshserver.send({ action: 'files' });
1025 + }
1026 + break;
1027 + }
1028 + case 'meshchange': {
1029 + // Update mesh information
1030 + if (meshes[message.event.meshid] == null) {
1031 + // This is a new mesh for us
1032 + meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
1033 + meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
1034 + } else {
1035 + // This is an existing mesh
1036 + if (message.event.name != null) {
1037 + meshes[message.event.meshid].name = message.event.name;
1038 + for (var i in nodes) { if (nodes[i].meshid == message.event.meshid) { nodes[i].meshnamel = message.event.name.toLowerCase(); } }
1039 + }
1040 + if (message.event.desc != null) { meshes[message.event.meshid].desc = message.event.desc; }
1041 + if (message.event.flags != null) { meshes[message.event.meshid].flags = message.event.flags; }
1042 + if (message.event.consent != null) { meshes[message.event.meshid].consent = message.event.consent; }
1043 + if (message.event.links) { meshes[message.event.meshid].links = message.event.links; }
1044 + if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; }
1045 +
1046 + // Check if we lost rights to this mesh in this change.
1047 + if (meshes[message.event.meshid].links[userinfo._id] == null) {
1048 + if ((xxcurrentView == 20) && (currentMesh == meshes[message.event.meshid])) go(2);
1049 + delete meshes[message.event.meshid];
1050 +
1051 + // Delete all nodes in that mesh
1052 + var newnodes = [];
1053 + for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } }
1054 + nodes = newnodes;
1055 +
1056 + // If we are looking at a node in the deleted mesh, move back to "My Devices"
1057 + if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
1058 + }
1059 + }
1060 + masterUpdate(4 + 128);
1061 + if (currentNode && (currentNode.meshid == message.event.meshid)) { currentNode = null; if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } }
1062 + //meshserver.send({ action: 'files' }); // TODO: Why do we need to do this??
1063 +
1064 + // If we are looking at a mesh that is now deleted, move back to "My Account"
1065 + if (xxcurrentView == 20 && currentMesh._id == message.event.meshid) { masterUpdate(4096); }
1066 + break;
1067 + }
1068 + case 'deletemesh': {
1069 + // Delete the mesh
1070 + if (meshes[message.event.meshid]) {
1071 + delete meshes[message.event.meshid];
1072 + masterUpdate(128);
1073 + meshserver.send({ action: 'files' });
1074 + }
1075 +
1076 + // Delete all nodes in that mesh
1077 + var newnodes = [];
1078 + if (nodes != null) { for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } } }
1079 + nodes = newnodes;
1080 + masterUpdate(4);
1081 +
1082 + // If we are looking at a mesh that is now deleted, move back to "My Account"
1083 + if (xxcurrentView >= 20 && xxcurrentView < 30 && currentMesh._id == message.event.meshid) { setDialogMode(0); go(2); }
1084 + // If we are looking at a node in the deleted mesh, move back to "My Devices"
1085 + if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
1086 +
1087 + break;
1088 + }
1089 + case 'addnode': {
1090 + var node = message.event.node;
1091 + if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
1092 + if (getNodeFromId(node._id) != null) break; // This node is already known.
1093 + node.namel = node.name.toLowerCase();
1094 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1095 + node.meshnamel = meshes[node.meshid].name.toLowerCase();
1096 + node.state = 0;
1097 + if (!node.icon) node.icon = 1;
1098 + node.ident = ++nodeShortIdent;
1099 + if (nodes == null) { }
1100 + nodes.push(node);
1101 +
1102 + // Web page update
1103 + masterUpdate(1 | 2 | 4 | 16);
1104 +
1105 + break;
1106 + }
1107 + case 'removenode': {
1108 + var index = -1;
1109 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1110 + if (index != -1) {
1111 + var node = nodes[index];
1112 + if (currentNode == node) {
1113 + if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); }
1114 + currentNode = null;
1115 + // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
1116 + }
1117 + nodes.splice(index, 1);
1118 +
1119 + // Web page update
1120 + masterUpdate(4 | 16);
1121 + }
1122 + break;
1123 + }
1124 + case 'changenode': {
1125 + var index = -1;
1126 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1127 + if (index != -1) {
1128 + var node = nodes[index];
1129 +
1130 + // Change the node
1131 + node.name = message.event.node.name;
1132 + node.rname = message.event.node.rname;
1133 + node.users = message.event.node.users;
1134 + node.host = message.event.node.host;
1135 + node.desc = message.event.node.desc;
1136 + node.ip = message.event.node.ip;
1137 + node.osdesc = message.event.node.osdesc;
1138 + node.publicip = message.event.node.publicip;
1139 + node.iploc = message.event.node.iploc;
1140 + node.wifiloc = message.event.node.wifiloc;
1141 + node.gpsloc = message.event.node.gpsloc;
1142 + node.tags = message.event.node.tags;
1143 + node.userloc = message.event.node.userloc;
1144 + if (message.event.node.agent != null) {
1145 + if (node.agent == null) node.agent = {};
1146 + if (message.event.node.agent.ver != null) { node.agent.ver = message.event.node.agent.ver; }
1147 + if (message.event.node.agent.id != null) { node.agent.id = message.event.node.agent.id; }
1148 + if (message.event.node.agent.caps != null) { node.agent.caps = message.event.node.agent.caps; }
1149 + if (message.event.node.agent.core != null) { node.agent.core = message.event.node.agent.core; } else { if (node.agent.core) { delete node.agent.core; } }
1150 + node.agent.tag = message.event.node.agent.tag;
1151 + }
1152 + if (message.event.node.intelamt != null) {
1153 + if (node.intelamt == null) node.intelamt = {};
1154 + if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; }
1155 + if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; }
1156 + if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; }
1157 + if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; }
1158 + if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; }
1159 + if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; }
1160 + if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; }
1161 + if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; }
1162 + }
1163 + if (message.event.node.av != null) { node.av = message.event.node.av; }
1164 + node.namel = node.name.toLowerCase();
1165 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1166 + if (message.event.node.icon) { node.icon = message.event.node.icon; }
1167 +
1168 + // Web page update
1169 + masterUpdate(2 | 4 | 8 | 16);
1170 + refreshDevice(node._id);
1171 +
1172 + if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
1173 + }
1174 + break;
1175 + }
1176 + case 'nodemeshchange': {
1177 + var index = -1;
1178 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1179 + if (index != -1) {
1180 + var node = nodes[index];
1181 + if (meshes[message.event.newMeshId] == null) {
1182 + // We don't see the new mesh, remove this device
1183 +
1184 + // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
1185 + if (currentNode == node) { if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); } currentNode = null; }
1186 + nodes.splice(index, 1);
1187 + masterUpdate(4 | 16);
1188 + } else {
1189 + // We see the new mesh, move this device
1190 + node.meshid = message.event.newMeshId;
1191 + node.meshnamel = meshes[message.event.newMeshId].name.toLowerCase();
1192 + masterUpdate(1 | 2 | 4);
1193 + }
1194 + refreshDevice(message.event.nodeid);
1195 + } else {
1196 + // This is a new device, add it.
1197 + var node = message.event.node;
1198 + if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
1199 + node.namel = node.name.toLowerCase();
1200 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1201 + node.meshnamel = meshes[node.meshid].name.toLowerCase();
1202 + node.state = 0;
1203 + if (!node.icon) node.icon = 1;
1204 + node.ident = ++nodeShortIdent;
1205 + if (nodes == null) { }
1206 + nodes.push(node);
1207 +
1208 + // Web page update
1209 + masterUpdate(1 | 2 | 4 | 16);
1210 + }
1211 + break;
1212 + }
1213 + case 'nodeconnect': {
1214 + // Indicated a node has changed connectivity state
1215 + var index = -1;
1216 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1217 + if (index != -1) {
1218 + var node = nodes[index];
1219 +
1220 + // Event the connection change if needed
1221 + var n = getstore('notifications', 0); // Account notification settings
1222 +
1223 + // Per-group notification settings
1224 + if (message.event.meshid && userinfo.links && userinfo.links[message.event.meshid] && userinfo.links[message.event.meshid].notify) {
1225 + n &= userinfo.links[message.event.meshid].notify;
1226 + } else {
1227 + n = 0;
1228 + }
1229 +
1230 + // Show the notification
1231 + if (n & 2) {
1232 + if (((node.conn & 1) == 0) && ((message.event.conn & 1) != 0)) { addNotification({ text: "Agente conectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1233 + if (((node.conn & 2) == 0) && ((message.event.conn & 2) != 0)) { addNotification({ text: "Intel AMT detectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1234 + if (((node.conn & 4) == 0) && ((message.event.conn & 4) != 0)) { addNotification({ text: "Intel AMT CIRA conectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1235 + if (((node.conn & 16) == 0) && ((message.event.conn & 16) != 0)) { addNotification({ text: "MQTT conectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1236 + }
1237 + if (n & 4) {
1238 + if (((node.conn & 1) != 0) && ((message.event.conn & 1) == 0)) { addNotification({ text: "Agente desconectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1239 + if (((node.conn & 2) != 0) && ((message.event.conn & 2) == 0)) { addNotification({ text: "Intel AMT não detectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1240 + if (((node.conn & 4) != 0) && ((message.event.conn & 4) == 0)) { addNotification({ text: "Intel AMT CIRA desconectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1241 + if (((node.conn & 16) != 0) && ((message.event.conn & 16) == 0)) { addNotification({ text: "MQTT desconectado", title: node.name, icon: node.icon, nodeid: node._id }); }
1242 + }
1243 +
1244 + // Change the node connection state
1245 + node.conn = message.event.conn;
1246 + node.pwr = message.event.pwr;
1247 +
1248 + // Web page update
1249 + masterUpdate(4 | 16);
1250 + refreshDevice(node._id);
1251 + }
1252 + break;
1253 + }
1254 + case 'wssessioncount': {
1255 + // Update the active web socket session count for a user
1256 + if (wssessions != null) {
1257 + if (message.event.count == 0 && wssessions['user/' + domain + '/' + message.event.username.toLowerCase()]) {
1258 + delete wssessions['user/' + domain + '/' + message.event.username.toLowerCase()];
1259 + } else {
1260 + wssessions['user/' + domain + '/' + message.event.username.toLowerCase()] = message.event.count;
1261 + }
1262 + updateUsers();
1263 + }
1264 + break;
1265 + }
1266 + case 'login': {
1267 + // Update the last login time
1268 + if (users != null && users['user/' + domain + '/' + message.event.username.toLowerCase()]) {
1269 + users['user/' + domain + '/' + message.event.username.toLowerCase()].login = Math.floor(new Date(message.event.time).getTime() / 1000);
1270 + }
1271 + break;
1272 + }
1273 + case 'scanamtdevice': {
1274 + // Populate the Intel AMT scan dialog box with the result of the RMCP scan
1275 + if ((xxdialogMode == null) || (!Q('dp1range')) || (Q('dp1range').value != message.event.range)) return;
1276 + var x = '';
1277 + if (message.event.results == null) {
1278 + // The scan could not occur because of an error. Likely the user range was invalid.
1279 + x = '<div style=width:100%;text-align:center;margin-top:12px>' + "Não foi possível verificar este intervalo de endereços." + '</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Valores de intervalo de IP de amostra<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100" + '</div>';
1280 + } else {
1281 + // Go thru all the results and populate the dialog box
1282 + amtScanResults = message.event.results;
1283 + for (var i in message.event.results) {
1284 + var r = message.event.results[i], shortname = r.hostname;
1285 + if (shortname.length > 20) { shortname = shortname.substring(0, 20) + '...'; }
1286 + var str = '<b title="' + EscapeHtml(r.hostname) + '">' + EscapeHtml(shortname) + '</b> - v' + r.ver;
1287 + if (r.state == 2) { if (r.tls == 1) { str += "com TLS."; } else { str += "sem TLS."; } } else { str += ' not activated.'; }
1288 + x += '<div style=width:100%;margin-bottom:2px;background-color:lightgray><div style=padding:4px><div style=display:inline-block;margin-right:5px><input class=DevScanCheckbox name=dp1checkbox tag="' + EscapeHtml(i) + '" type=checkbox onclick=addAmtScanToMeshCheckbox() /></div><div class=j1 style=display:inline-block></div><div style=display:inline-block;margin-left:5px;overflow-x:auto;white-space:nowrap>' + str + '</div></div></div>';
1289 + }
1290 + // If no results where found, display a nice message
1291 + if (x == '') { x = '<div style=width:100%;text-align:center;margin-top:12px>Scan returned no results.</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100</div>'; }
1292 + }
1293 + // Set the html in the dialog box and re-enable the scan button
1294 + QH('dp1results', x);
1295 + QE('dp1range', true);
1296 + QE('dp1rangebutton', true);
1297 + break;
1298 + }
1299 + case 'notify': {
1300 + var n = { text: message.event.value, title: message.event.title, icon: message.event.icon };
1301 + if (message.event.tag != null) { n.tag = message.event.tag; }
1302 + addNotification(n);
1303 + break;
1304 + }
1305 + case 'traceinfo': {
1306 + if (typeof message.event.traceSources == 'object') {
1307 + if ((message.event.traceSources != null) && (message.event.traceSources.length > 0)) {
1308 + serverTraceSources = message.event.traceSources;
1309 + QH('p41traceStatus', EscapeHtml(message.event.traceSources.join(', ')));
1310 + } else {
1311 + serverTraceSources = [];
1312 + QH('p41traceStatus', "Nenhum");
1313 + }
1314 + }
1315 + break;
1316 + }
1317 + case 'sysinfohash': {
1318 + // If the sysinfo document has changed and we are looking at it, request an update.
1319 + if ((currentNode != null) && (message.event.nodeid == powerTimelineReq)) {
1320 + meshserver.send({ action: 'getsysinfo', nodeid: message.event.nodeid });
1321 + }
1322 + break;
1323 + }
1324 + case 'stopped': { // Server is stopping.
1325 + // Disconnect
1326 + //console.log(message.msg);
1327 + break;
1328 + }
1329 + case 'updatePluginList': {
1330 + installedPluginList = message.event.list;
1331 + updatePluginList();
1332 + break;
1333 + }
1334 + case 'pluginStateChange': {
1335 + if (pluginHandler == null) break;
1336 + pluginHandler.refreshPluginHandler();
1337 + break;
1338 + }
1339 + default:
1340 + //console.log('Unknown message.event.action', message.event.action);
1341 + break;
1342 + }
1343 + break;
1344 + }
1345 + case 'createInviteLink': { // Agent installation invitation link
1346 + if (xxdialogTag != message.meshid) break;
1347 + var servername = serverinfo.name;
1348 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
1349 + var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
1350 + var url;
1351 + if (serverinfo.https == true) {
1352 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
1353 + url = 'https://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
1354 + } else {
1355 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
1356 + url = 'http://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
1357 + }
1358 + Q('agentInvitationLink').href = url;
1359 + var t = format("{0} horas{1}", message.expire, addLetterS(message.expire));
1360 + if (message.expire == 24) { t = "1 dia"; }
1361 + if (message.expire == 168) { t = "1 semana"; }
1362 + if (message.expire == 5040) { t = "1 mês"; }
1363 + if (message.expire == 0) { t = "Ilimitado"; }
1364 + QH('agentInvitationLink', format("Link de convite ({0})", t));
1365 + QV('agentInvitationLinkDiv', true);
1366 + break;
1367 + }
1368 + case 'getmqttlogin': {
1369 + if ((currentNode == null) || (currentNode._id != message.nodeid) || (xxdialogMode != null)) return;
1370 + var x = "Essas configurações podem ser usadas para conectar o MQTT a este dispositivo." + '<br /><br />';
1371 + delete message.action;
1372 + delete message.nodeid;
1373 + x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>' + JSON.stringify(message) + '</textarea>';
1374 + /*
1375 + x += addHtmlValue('Username', '<input style=width:230px readonly value="' + message.user + '" />');
1376 + x += addHtmlValue('Password', '<input style=width:230px readonly value="' + message.pass + '" />');
1377 + x += addHtmlValue('WS URL', '<input style=width:230px readonly value="' + message.wsUrl + '" />');
1378 + if (message.mpsUrl && message.mpsCertHash) {
1379 + x += addHtmlValue('MPS URL', '<input style=width:230px readonly value="' + message.mpsUrl + '" />');
1380 + x += addHtmlValue('MPS Cert Hash', '<input style=width:230px readonly value="' + message.mpsCertHash + '" />');
1381 + }
1382 + */
1383 + setDialogMode(2, "Credenciais MQTT", 1, null, x);
1384 + break;
1385 + }
1386 + case 'stopped': { // Server is stopping.
1387 + // Disconnect
1388 + autoReconnect = false;
1389 + QH('p0span', message.msg);
1390 + break;
1391 + }
1392 + case 'updatePluginList': {
1393 + installedPluginList = message.list;
1394 + updatePluginList();
1395 + break;
1396 + }
1397 + case 'pluginVersionsAvailable': {
1398 + if (pluginHandler == null) break;
1399 + updatePluginList(message.list);
1400 + break;
1401 + }
1402 + case 'downgradePluginVersions': {
1403 + var vSelect = '<select id="lastPluginVersion">';
1404 + message.info.versionList.forEach(function(v) { vSelect += '<option value="' + v.zipball_url + '">' + v.name + '</option>'; });
1405 + vSelect += '</select>';
1406 + setDialogMode(2, "Plugin Action", 3, pluginActionEx, format('Select the version to downgrade the plugin: {0}', message.info.name) + '<hr />' + vSelect + '<hr />' + "Please be aware that downgrading is not recommended. Please only do so in the event that a recent upgrade has broken something." + + '<input id="lastPluginAct" type="hidden" value="downgrade" /><input id="lastPluginId" type="hidden" value="' + message.info.id + '" />');
1407 + break;
1408 + }
1409 + case 'pluginError': {
1410 + setDialogMode(2, "Plugin Error", 1, null, message.msg);
1411 + break;
1412 + }
1413 + case 'plugin': {
1414 + if ((pluginHandler == null) || (typeof message.plugin != 'string')) break;
1415 + try { pluginHandler[message.plugin][message.method](server, message); } catch (e) { console.log('Error loading plugin handler ('+ e + ')'); }
1416 + break;
1417 + }
1418 + default:
1419 + //console.log('Unknown message.action', message.action);
1420 + break;
1421 + }
1422 + }
1423 +
1424 + //
1425 + // MY DEVICES
1426 + //
1427 +
1428 + function onRealNameCheckBox() {
1429 + showRealNames = Q('RealNameCheckBox').checked;
1430 + putstore('showRealNames', showRealNames ? 1 : 0);
1431 + masterUpdate(6);
1432 + return;
1433 + }
1434 +
1435 + function onDeviceViewChange(i) {
1436 + if (i != null) { Q('viewselect').value = i; }
1437 + for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
1438 + Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
1439 + putstore('_deviceView', Q('viewselect').value);
1440 + putstore('_viewsize', Q('sizeselect').value);
1441 + masterUpdate(4);
1442 + setTimeout(function () { masterUpdate(512); }, 200);
1443 + }
1444 +
1445 + function ondockeypress(e) {
1446 + setSessionActivity();
1447 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
1448 + // Check what keys we are allows to send
1449 + if (currentNode != null) {
1450 + var mesh = meshes[currentNode.meshid];
1451 + var meshrights = mesh.links[userinfo._id].rights;
1452 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1453 + if (inputAllowed == false) return false;
1454 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1455 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1456 + }
1457 + return desktop.m.handleKeys(e);
1458 + }
1459 + if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeys(e); }
1460 + if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) return agentConsoleHandleKeys(e);
1461 + if (!xxdialogMode && xxcurrentView == 4) {
1462 + if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1463 + var processed = 0;
1464 + if (e.key) {
1465 + if (e.key.length === 1 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + e.key)); processed = 1; }
1466 + if (e.keyCode == 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = x.substring(0, x.length - 1); processed = 1; }
1467 + if (e.keyCode == 27) { Q('UserSearchInput').value = ''; processed = 1; }
1468 + } else {
1469 + if (e.charCode != 0 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
1470 + }
1471 + if (processed > 0) { if (processed == 1) { onUserSearchInputChanged(); } return haltEvent(e); }
1472 + }
1473 + if (xxdialogMode || xxcurrentView != 1) return;
1474 + if (e.ctrlKey == true && e.charCode == 96) {
1475 + showRealNames = !showRealNames;
1476 + Q('RealNameCheckBox').value = showRealNames;
1477 + putstore('showRealNames', showRealNames ? 1 : 0);
1478 + masterUpdate(6)
1479 + return;
1480 + }
1481 + if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1482 + if (Q('viewselect').value < 3) {
1483 + var processed = 0;
1484 + if (e.key) {
1485 + if (e.key.length === 1 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + e.key)); processed = 1; }
1486 + if (e.keyCode == 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = x.substring(0, x.length - 1); processed = 1; }
1487 + if (e.keyCode == 27) { Q('SearchInput').value = ''; processed = 1; }
1488 + } else {
1489 + if (e.charCode != 0 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
1490 + }
1491 + if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
1492 + }
1493 + if (Q('viewselect').value == 3) {
1494 + if (e.key) {
1495 + if (e.key.length === 1 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + e.key)); processed = 1; }
1496 + //if (e.keyCode == 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = x.substring(0, x.length - 1); processed = 1; }
1497 + if (e.keyCode == 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
1498 + if (e.keyCode == 13) { getSearchLocation(); }
1499 + } else {
1500 + if (e.charCode != 0 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + String.fromCharCode(e.charCode))); processed = 1; }
1501 + }
1502 + }
1503 + }
1504 +
1505 + function ondockeydown(e) {
1506 + setSessionActivity();
1507 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
1508 + // Check what keys we are allows to send
1509 + if (currentNode != null) {
1510 + var mesh = meshes[currentNode.meshid];
1511 + var meshrights = mesh.links[userinfo._id].rights;
1512 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1513 + if (inputAllowed == false) return false;
1514 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1515 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1516 + }
1517 + return desktop.m.handleKeyDown(e);
1518 + }
1519 + if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { terminal.m.TermHandleKeyDown(e); if ((e.keyCode >= 37) && (e.keyCode <= 40)) { haltEvent(e); } }
1520 + if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { haltEvent(e); return false; } // F5 Refresh on files
1521 + if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) { return agentConsoleHandleKeys(e); }
1522 + if (!xxdialogMode && xxcurrentView == 4) {
1523 + if (e.keyCode === 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
1524 + if (e.keyCode === 27) { Q('UserSearchInput').value = ''; processed = 1; }
1525 + if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
1526 + }
1527 + if (xxdialogMode || xxcurrentView != 1 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1528 + var processed = 0;
1529 + if (Q('viewselect').value < 3) {
1530 + if (e.keyCode === 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
1531 + if (e.keyCode === 27) { Q('SearchInput').value = ''; processed = 1; }
1532 + if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
1533 + }
1534 + if (Q('viewselect').value == 3) {
1535 + if (e.keyCode === 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = (x.substring(0, x.length - 1)); processed = 1; }
1536 + if (e.keyCode === 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
1537 + }
1538 + }
1539 +
1540 + function ondockeyup(e) {
1541 + setSessionActivity();
1542 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
1543 + // Check what keys we are allows to send
1544 + if (currentNode != null) {
1545 + var mesh = meshes[currentNode.meshid];
1546 + var meshrights = mesh.links[userinfo._id].rights;
1547 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1548 + if (inputAllowed == false) return false;
1549 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1550 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1551 + }
1552 + return desktop.m.handleKeyUp(e);
1553 + }
1554 + if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeyUp(e); }
1555 + if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { p13folderup(9999); haltEvent(e); return false; } // F5 Refresh on files
1556 + if (!xxdialogMode && xxcurrentView == 4) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
1557 + if (xxdialogMode && e.keyCode == 27) { dialogclose(0); }
1558 + if (xxdialogMode || xxcurrentView != 0 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
1559 + if (Q('viewselect').value < 3) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
1560 + if (Q('viewselect').value == 3) { if ((e.keyCode === 8 && mapSearchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
1561 + }
1562 +
1563 + //function ondocfocus() { }
1564 + // TODO: Add handleReleaseKeys() for Intel AMT.
1565 + function ondocblur() { if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked && desktop.m.handleReleaseKeys) { return desktop.m.handleReleaseKeys(); } }
1566 +
1567 + // Highlights the device being hovered
1568 + function devMouseHover(element, over) {
1569 + setSessionActivity();
1570 + var view = Q('viewselect').value;
1571 + if (view == 1) {
1572 + var e = element.children[1].children[1];
1573 + e.children[0].classList.remove('g1s');
1574 + e.children[1].classList.remove('e2s');
1575 + e.children[2].classList.remove('g2s');
1576 + if (over == 1) {
1577 + e.children[0].classList.add('g1s');
1578 + e.children[1].classList.add('e2s');
1579 + e.children[2].classList.add('g2s');
1580 + }
1581 + } else if (view == 2) {
1582 + var e = element;
1583 + e.children[2].classList.remove('g1s');
1584 + e.children[4].classList.remove('e2s');
1585 + e.children[3].classList.remove('g2s');
1586 + if (over == 1) {
1587 + e.children[2].classList.add('g1s');
1588 + e.children[4].classList.add('e2s');
1589 + e.children[3].classList.add('g2s');
1590 + }
1591 + }
1592 + }
1593 +
1594 + var deviceHeaderId = 0;
1595 + var deviceHeaderTotal = 0;
1596 + var deviceHeadersTitles = {};
1597 + var deviceHeaderCount;
1598 + var deviceHeaders = {};
1599 + var oldviewmode = 0;
1600 + function updateDevices() {
1601 + if (nodes == null) { return; }
1602 + var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
1603 + QV('xdevices', view < 4);
1604 + QV('xdevicesmap', view == 4);
1605 + QV('devListToolbar', view < 3);
1606 + QV('kvmListToolbar', view == 3);
1607 + QV('devMapToolbar', view == 4);
1608 + QV('devListToolbarSize', view == 3);
1609 + QV('NoMeshesPanel', meshcount == 0);
1610 + //QV('devListToolbarView', (meshcount != 0) && (nodes.length > 0));
1611 + QV('devListToolbarViewIcons', (meshcount != 0) && (nodes.length > 0));
1612 + QV('devListToolbarSort', (meshcount != 0) && (nodes.length > 0) && (view < 4));
1613 + if ((meshcount == 0) || (nodes.length == 0)) { view = 1; sort = 0; }
1614 + if (view == 4) {
1615 + setTimeout( function() { if (xxmap.map != null) { xxmap.map.updateSize(); } }, 200);
1616 + // TODO
1617 + } else {
1618 + // 3 wide, list view or desktop view
1619 + deviceHeaderId = 0;
1620 + deviceHeaderCount = {};
1621 + deviceHeaderTotal = 0;
1622 + deviceHeaders = {};
1623 + deviceHeadersTitles = {};
1624 + var kvmDivs = [];
1625 +
1626 + // Perform node sort
1627 + if (sort == 0) { nodes.sort(meshSort); }
1628 + else if (sort == 1) { nodes.sort(powerSort); }
1629 + else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
1630 +
1631 + // Save the list of currently checked nodeid's
1632 + var checkedNodeids = [], elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
1633 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
1634 + if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
1635 + else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
1636 +
1637 + // Compute the width of the device view.
1638 + var totalDeviceViewWidth = Q('column_l').clientWidth - 60;
1639 + var deviceBoxWidth = Math.floor(totalDeviceViewWidth / 301);
1640 + deviceBoxWidth = 301 + Math.floor((totalDeviceViewWidth - (deviceBoxWidth * 301)) / deviceBoxWidth);
1641 +
1642 + if ((view == 2) && (sort != 3)) {
1643 + r += '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>' + "Do utilizador" + '<th style=color:gray;width:120px>' + "Endereço" + '<th style=color:gray;width:100px>' + "Conectividade"; //<th style=color:gray;width:100px>State';
1644 + }
1645 +
1646 + // Go thru the list of nodes and display them
1647 + for (var i in nodes) {
1648 + var node = nodes[i];
1649 + if (node.v == false) continue;
1650 + var mesh2 = meshes[node.meshid], meshlinks = mesh2.links[userinfo._id];
1651 + if (meshlinks == null) continue;
1652 + var meshrights = meshlinks.rights;
1653 + if ((view == 3) && (mesh2.mtype == 1)) continue;
1654 + if (sort == 0) {
1655 + // Mesh header
1656 + if (node.meshid != current) {
1657 + deviceHeaderSet();
1658 + var extra = '';
1659 + if (view == 2) { r += '<tr><td colspan=5>'; }
1660 + if (meshes[node.meshid].mtype == 1) { extra = '<span class=devHeaderx>' + "Intelreg; " + '</span>'; }
1661 + if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1662 + if (view == 2) { r += '<div>'; }
1663 + r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
1664 + r += '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span>' + extra;
1665 + r += '</span><span id=MxMESH tabindex=0 style=cursor:pointer onclick=gotoMesh("' + node.meshid + '") onkeypress="if (event.key==\'Enter\') gotoMesh(\'' + node.meshid + '\')">' + EscapeHtml(meshes[node.meshid].name) + '</span>' + getMeshActions(mesh2, meshrights) + '</div>';
1666 + if (view == 2) { r += '</div>'; }
1667 + current = node.meshid;
1668 + displayedMeshes[current] = 1;
1669 + c = 0;
1670 + }
1671 + } else if (sort == 1) {
1672 + // Power header
1673 + var pwr = node.pwr?node.pwr:0;
1674 + if (pwr !== current) {
1675 + deviceHeaderSet();
1676 + if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1677 +
1678 + if (view == 2) { r += '<tr><td>'; }
1679 + r += '<div class=DevSt style=width:100%;padding-top:4px><span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx style=float:right></span><span>' + PowerStateStr2(node.pwr) + '</span></div>';
1680 +
1681 + current = pwr;
1682 + c = 0;
1683 + }
1684 + } else if (sort == 2) {
1685 + // Device header
1686 + if (current == null) { current = '1'; }
1687 + }
1688 +
1689 + count++;
1690 + var title = EscapeHtml(node.name);
1691 + if (title.length == 0) { title = '<i>' + "Nenhum" + '</i>'; }
1692 + if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
1693 + var name = EscapeHtml(node.name);
1694 + if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
1695 + if (name.length == 0) { name = '<i>' + "Nenhum" + '</i>'; }
1696 +
1697 + // Node
1698 + var icon = node.icon;
1699 + if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
1700 + if (view == 1) {
1701 + r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer tabindex=0 onclick=gotoDevice(\'' + node._id + '\',null,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)"><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div></div>';
1702 + } else if (view == 2) {
1703 + var states = [];
1704 + if (node.conn) {
1705 + if ((node.conn & 1) != 0) { states.push('<span title=\"' + "O agente de malha está conectado e pronto para uso." + '\">' + "Agente" + '</span>'); }
1706 + if ((node.conn & 2) != 0) { states.push('<span title=\"' + "Intel&reg; O AMT CIRA está conectado e pronto para uso." + '\">' + "CIRA" + '</span>'); }
1707 + else if ((node.conn & 4) != 0) { states.push('<span title=\"' + "Intel&reg; AMT é roteável." + '\">' + "AMT" + '</span>'); }
1708 + if ((node.conn & 8) != 0) { states.push('<span title=\"' + "O agente de malha é alcançável usando outro agente como retransmissão." + '\">' + "Retransmissão" + '</span>'); }
1709 + if ((node.conn & 16) != 0) { states.push('<span title=\"' + "A conexão MQTT com o dispositivo está ativa." + '\">' + "MQTT" + '</span>'); }
1710 + }
1711 + r += '<tr><td><div id=devs class=bar18 tabindex=0 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)">';
1712 + r += '<div class=deviceBarCheckbox><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div>';
1713 + r += '<div class=deviceBarIcon onclick=gotoDevice(\'' + node._id + '\',null,null,event)><div class=\"j' + icon + '\" style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
1714 + r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
1715 + r += '<div style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + node._id + '\',null,null,event)><span style=width:300px>' + name + '</span></div></div></td>';
1716 + r += '<td style=text-align:center>' + getUserShortStr(node);
1717 + r += '<td style=text-align:center>' + (node.ip != null ? node.ip : '');
1718 + r += '<td style=text-align:center>' + states.join('&nbsp;+&nbsp;');
1719 + //r += '<td style=text-align:center>' + (node.pwr != null ? powerStateStrings[node.pwr] : '');
1720 + r += '</tr>';
1721 + } else if ((view == 3) && (node.conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((node.agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
1722 + if ((multiDesktopFilter) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + node._id) >= 0))) {
1723 + r += '<div id=devs style=display:inline-block;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div tabindex=0 style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + node._id + '\',11,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',11,null,event)">';
1724 + //r += '<input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox style=float:left>';
1725 + r += '<div class="j' + icon + '" style=width:16px;float:left></div>&nbsp;' + name + '</div>';
1726 + r += '<span onclick=gotoDevice(\'' + node._id + '\',null,null,event)></span><div id=xkvmid_' + node._id.split('/')[2] + '><div id=skvmid_' + node._id.split('/')[2] + ' tabindex=0 style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + node._id + '\') onkeypress="if (event.key==\'Enter\') toggleKvmDevice(\'' + node._id + '\')">' + "Desconectado" + '</div></div>';
1727 + r += '</div>';
1728 + kvmDivs.push(node._id);
1729 + }
1730 + }
1731 +
1732 + // If we are displaying devices by group, put the device in the right group.
1733 + if ((sort == 3) && (r != '')) {
1734 + if (node.tags) {
1735 + for (var j in node.tags) {
1736 + var tag = node.tags[j];
1737 + if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
1738 + if (view == 3) break;
1739 + }
1740 + }
1741 + r = '';
1742 + }
1743 +
1744 + deviceHeaderTotal++;
1745 + if (typeof deviceHeaderCount[node.state] == 'undefined') { deviceHeaderCount[node.state] = 1; } else { deviceHeaderCount[node.state]++; }
1746 + }
1747 +
1748 + // Above 32 devices, gray out the auto connect feature.
1749 + if (kvmDivs.length >= 32) { Q('autoConnectDesktopCheckbox').checked = false; }
1750 + QE('autoConnectDesktopCheckbox', kvmDivs.length < 32);
1751 +
1752 + // If displaying devices by groups, sort the group names and display the devices.
1753 + if (sort == 3) {
1754 + if (view == 2) { r = '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>' + "Do utilizador" + '<th style=color:gray;width:120px>' + "Endereço" + '<th style=color:gray;width:100px>' + "Conectividade"; }
1755 +
1756 + var groupNames = [];
1757 + for (var i in groups) { groupNames.push(i); }
1758 + groupNames.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
1759 + for (var j in groupNames) {
1760 + var i = groupNames[j];
1761 + if (view == 2) {
1762 + r += '<tr><td colspan=4><div class=DevSt style=width:100%;padding-top:4px><span class=devHeaderx style=float:right>' + groupCount[i] + ' node' + ((groupCount[i] > 1) ? 's' : '') + '</span><span>' + i + '</span></div>' + groups[i];
1763 + } else {
1764 + r += '<div class=DevSt style=width:100%;padding-top:4px><span class=devHeaderx style=float:right>' + groupCount[i] + ' node' + ((groupCount[i] > 1) ? 's' : '') + '</span><span>' + i + '</span></div>' + groups[i];
1765 + }
1766 + }
1767 + }
1768 +
1769 + // If there is nothing to display, explain the problem
1770 + if ((r == '') && (meshcount > 0) && (Q('SearchInput').value != '')) {
1771 + if (sort == 3) {
1772 + r = '<div style="margin:30px">' + "Nenhum dispositivo está incluído em nenhum grupo, clique no \"Grupo\" de um dispositivo para adicionar a um grupo" + '</div>';
1773 + } else {
1774 + r = '<div style="margin:30px">' + "Nenhum dispositivo correspondente a esta pesquisa." + '</div>';
1775 + }
1776 + }
1777 +
1778 + if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
1779 +
1780 + // Display all empty device groups, we need to do this because users can add devices to these at any time.
1781 + if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) {
1782 + for (var i in meshes) {
1783 + var mesh = meshes[i], meshlink = mesh.links[userinfo._id];
1784 + if (meshlink != null) {
1785 + var meshrights = meshlink.rights;
1786 + if (displayedMeshes[mesh._id] == null) {
1787 + if ((current != '') && (r != '')) { r += '</tr></table>'; }
1788 + r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span><span>';
1789 + r += getMeshActions(mesh, meshrights);
1790 + r += '</span></td></tr><tr>';
1791 + if (mesh.mtype == 1) {
1792 + r += '<td><div style=padding:10px><i>' + "Nenhum Intel&reg; dispositivos AMT nessa malha";
1793 + if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "Adicione um" + '</a>'; }
1794 + }
1795 + if (mesh.mtype == 2) {
1796 + r += '<td><div style=padding:10px><i>' + "Nenhum dispositivo neste grupo";
1797 + if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "Adicione um" + '</a>'; }
1798 + }
1799 + r += '.</i></div></td>';
1800 + current = mesh._id;
1801 + count++;
1802 + }
1803 + }
1804 + }
1805 + }
1806 + r += '</tr></table><div style=height:1px></div>'; // This height of 1 div fixes a problem in Linux firefox browsers
1807 +
1808 + // Add a "Add Device Group" option
1809 + r += '<div style=border-top-style:solid;border-top-width:1px;border-top-color:#DDDDDD;cursor:pointer;font-size:10px>';
1810 + if ((view < 3) && (sort == 0) && (meshcount > 0) && ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0))) {
1811 + r += '<a href=# onclick="return account_createMesh()" title=\"' + "Crie um novo grupo de dispositivos." + '\" style=cursor:pointer>' + "Adicionar grupo de dispositivos" + '</a>&nbsp';
1812 + }
1813 + if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 128) == 0)) {
1814 + r += '<a href=# onclick=\'return p10showMeshCmdDialog(0)\' style=cursor:pointer title=\"' + "Faça o download do MeshCmd, uma ferramenta de linha de comando que executa muitas funções." + '\">' + "MeshCmd" + '</a>&nbsp';
1815 + if (navigator.platform.toLowerCase() == 'win32') { r += '<a href=# onclick=\'return p10showMeshRouterDialog()\' style=cursor:pointer title=\"' + "Faça o download do MeshCentral Router, uma ferramenta de mapeamento de portas TCP." + '\">' + "Roteador" + '</a>&nbsp'; }
1816 + }
1817 + r += '</div><br/>';
1818 +
1819 + QH('xdevices', r);
1820 + deviceHeaderSet();
1821 +
1822 + // Re-check nodeid's
1823 + var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
1824 + if (checkedNodeids) { for (var i=0;i<elements.length;i++) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); } }
1825 +
1826 + for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
1827 + for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
1828 + p1updateInfo();
1829 +
1830 + // Take care of KVM surfaces in desktop view mode
1831 + if (view == 3) {
1832 + // Figure out and adjust the size to fill the width of the div
1833 + var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
1834 + //var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
1835 + var realw = vsize.x + 2, tw = totalDeviceViewWidth - 5, xw = Math.floor(tw / realw);
1836 + xw = realw + Math.floor((tw - (xw * realw)) / xw);
1837 + vsize.y = vsize.y * (xw / vsize.x);
1838 + vsize.x = xw;
1839 +
1840 + for (var i in multiDesktop) { multiDesktop[i].xxdelete = true; }
1841 + for (var i in kvmDivs) {
1842 + var id = kvmDivs[i], shortid = id.split('/')[2], desk = multiDesktop[id];
1843 + if (desk != null) {
1844 + // This device already has a canvas, use it.
1845 + desk.m.CanvasId.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
1846 + Q('xkvmid_' + shortid).appendChild(desk.m.CanvasId);
1847 + delete desk.xxdelete;
1848 + QH('skvmid_' + shortid, ["Desconectado", "Conectando...", "Configurando...", '', ''][((desk.m.State == null)?desk.m.state:desk.m.State)]);
1849 + } else {
1850 + var node = getNodeFromId(id);
1851 + if ((desktopNode == node) && (desktop != null)) { // Check if the main desktop is this device, if it is, use that.
1852 + // This device already has a canvas, use it.
1853 + var c = desktop.m.CanvasId;
1854 + c.setAttribute('id', 'kvmid_' + shortid);
1855 + c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
1856 + c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
1857 + c.removeAttribute('onmousedown');
1858 + c.removeAttribute('onmouseup');
1859 + c.removeAttribute('onmousemove');
1860 + Q('xkvmid_' + shortid).appendChild(c);
1861 + QH('skvmid_' + shortid, ["Desconectado", "Conectando...", "Configurando...", '', ''][((desktop.m.State == null)?desktop.m.state:desktop.m.State)]);
1862 + if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
1863 + desktop.shortid = shortid;
1864 + desktop.onStateChanged = onMultiDesktopStateChange;
1865 + multiDesktop[id] = desktop;
1866 + desktop = desktopNode = currentNode = null;
1867 + // Setup a replacement desktop
1868 + QH('DeskParent', '<canvas id="Desk" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
1869 + } else {
1870 + // This is a new device, create a canvas for it.
1871 + var c = document.createElement('canvas');
1872 + c.setAttribute('id', 'kvmid_' + shortid);
1873 + c.setAttribute('width', 640);
1874 + c.setAttribute('height', 480);
1875 + c.setAttribute('oncontextmenu', 'return false');
1876 + c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
1877 + c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
1878 + try { Q('xkvmid_' + shortid).appendChild(c); } catch (ex) {}
1879 + // Check if we need to auto-connect
1880 + if (Q('autoConnectDesktopCheckbox').checked == true) { setTimeout(function() { connectMultiDesktop(node, 1); }, 100); }
1881 + }
1882 + }
1883 + }
1884 + for (var i in multiDesktop) {
1885 + // If a device is no longer viewed, disconnect it.
1886 + if (multiDesktop[i].xxdelete == true) { multiDesktop[i].Stop(); delete multiDesktop[i]; }
1887 + else if (debugmode && multiDesktop[i].m && multiDesktop[i].m.onScreenSizeChange) {
1888 + mdeskAdjust(multiDesktop[i].m, multiDesktop[i].m.ScreenWidth, multiDesktop[i].m.ScreenHeight, multiDesktop[i].m.CanvasId); // Adjust screen size change
1889 + }
1890 + }
1891 + deskAdjust();
1892 + } else {
1893 + disconnectAllKvmFunction();
1894 + Q('autoConnectDesktopCheckbox').checked = false;
1895 + }
1896 + }
1897 + oldviewmode = view;
1898 + }
1899 +
1900 + function toggleKvmDevice(node) {
1901 + if (typeof node == 'string') { node = getNodeFromId(node); } // Convert nodeid to node if needed
1902 + var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
1903 + if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
1904 + //var conn = 0;
1905 + //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
1906 + if (node.conn & 1) { connectMultiDesktop(node, 1); }
1907 + }
1908 + }
1909 +
1910 + function getUserShortStr(node) {
1911 + if (node == null || node.users == null || node.users.length == 0) return '';
1912 + if (node.users.length > 1) { return '<span title="' + EscapeHtml(node.users.join(', ')) + '">' + nobreak(format("{0} usuários", node.users.length)) + '</span>'; }
1913 + var u = node.users[0], su = u, i = u.indexOf('\\');
1914 + if (i > 0) { su = u.substring(i + 1); }
1915 + su = EscapeHtml(su);
1916 + if (su.length > 15) { su = su.substring(0, 14) + '&#8230;'; }
1917 + return '<span title="' + EscapeHtml(u) + '">' + su + '</span>';
1918 + }
1919 +
1920 + function autoConnectDesktops() { if (Q('autoConnectDesktopCheckbox').checked == true) { connectAllKvmFunction(); } }
1921 + function connectAllKvmFunction(force) {
1922 + if (xxdialogMode) return false;
1923 + if (force !== true) { // We need to count how many devices will need to be connected, if it's a lot, prompt first.
1924 + var count = 0;
1925 + for (var i in nodes) {
1926 + var node = nodes[i], nodeid = nodes[i]._id;
1927 + if (multiDesktop[nodeid] == null) {
1928 + var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
1929 + if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
1930 + //var conn = 0;
1931 + //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
1932 + if (node.conn & 1) { count++; }
1933 + }
1934 + }
1935 + }
1936 + if (count > 8) { setDialogMode(2, "Conectar todos", 3, function() { connectAllKvmFunction(true); }, format("Are you sure you want to connect to {0} devices?", count)); return; }
1937 + }
1938 +
1939 + // Perform connect all
1940 + for (var i in nodes) { if (multiDesktop[nodes[i]._id] == null) { toggleKvmDevice(nodes[i]._id); } }
1941 + }
1942 + function disconnectAllKvmFunction() { if (xxdialogMode) return false; for (var nodeid in multiDesktop) { multiDesktop[nodeid].Stop(); } multiDesktop = {}; }
1943 + function onMultiDesktopStateChange(desk, state) { try { QH('skvmid_' + desk.shortid, ["Desconectado", "Conectando...", "Configurando...", '', ''][state]); } catch (ex) {} }
1944 +
1945 + function showMultiDesktopSettings() {
1946 + QV('d7amtkvm', false);
1947 + QV('d7meshkvm', true);
1948 + d7bitmapquality.value = multidesktopsettings.quality;
1949 + d7bitmapscaling.value = multidesktopsettings.scaling;
1950 + if (multidesktopsettings.framerate) { d7framelimiter.value = multidesktopsettings.framerate; } else { d7framelimiter.value = 1000; }
1951 + setDialogMode(7, "Configurações da área de trabalho remota", 3, showMultiDesktopSettingsChanged);
1952 + }
1953 +
1954 + function showMultiDesktopSettingsChanged() {
1955 + multidesktopsettings.quality = d7bitmapquality.value;
1956 + multidesktopsettings.scaling = d7bitmapscaling.value;
1957 + multidesktopsettings.framerate = d7framelimiter.value;
1958 + localStorage.setItem('multidesktopsettings', JSON.stringify(multidesktopsettings));
1959 + // Make changes to all current connections
1960 + for (var i in multiDesktop) { multiDesktop[i].m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
1961 + }
1962 +
1963 + function connectMultiDesktop(node, contype) {
1964 + var nodeid = node._id, shortid = nodeid.split('/')[2];
1965 + var desk = multiDesktop[nodeid];
1966 + if (desk == null) {
1967 + if (Q('kvmid_' + shortid) == null) return; // Check if this device is being displayed, if not, exit now.
1968 + if (contype == 2) {
1969 + // Setup the Intel AMT remote desktop
1970 + if ((node.intelamt.user == null) || (node.intelamt.user == '')) { return; }
1971 + desk = CreateAmtRedirect(CreateAmtRemoteDesktop('kvmid_' + shortid), authCookie);
1972 + desk.shortid = shortid;
1973 + //desk.debugmode = debugmode;
1974 + desk.onStateChanged = onMultiDesktopStateChange;
1975 + desk.m.bpp = 1;
1976 + desk.m.useZRLE = true;
1977 + desk.m.showmouse = true;
1978 + desk.m.onKvmData = function (data) { console.log('KVM Data received in multi-desktop mode, this is not supported.'); }; // KVM Data Channel not supported in multi-desktop right now.
1979 + //desk.m.onScreenSizeChange = deskAdjust;
1980 + if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
1981 + desk.Start(nodeid, 16994, '*', '*', 0);
1982 + desk.contype = 2;
1983 + multiDesktop[nodeid] = desk;
1984 + } else if (contype == 1) {
1985 + // Setup the Mesh Agent remote desktop
1986 + desk = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('kvmid_' + shortid), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
1987 + desk.shortid = shortid;
1988 + desk.attemptWebRTC = attemptWebRTC;
1989 + desk.onStateChanged = onMultiDesktopStateChange;
1990 + //desk.onConsoleMessageChange = function () { console.log('CONSOLEMSG:', desk.consoleMessage); }
1991 + desk.m.CompressionLevel = multidesktopsettings.quality;
1992 + desk.m.ScalingLevel = multidesktopsettings.scaling;
1993 + desk.m.FrameRateTimer = multidesktopsettings.framerate;
1994 + //desk.m.onDisplayinfo = deskDisplayInfo;
1995 + //desk.m.onScreenSizeChange = deskAdjust;
1996 + if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
1997 + desk.Start(nodeid);
1998 + desk.contype = 1;
1999 + multiDesktop[nodeid] = desk;
2000 + }
2001 + } else {
2002 + // Disconnect and clean up the remote desktop
2003 + desk.Stop();
2004 + delete multiDesktop[nodeid];
2005 + }
2006 + }
2007 +
2008 + function getMeshActions(mesh, meshrights) {
2009 + if ((meshrights & 4) == 0) return '';
2010 + var r = '';
2011 + if ((features & 1024) == 0) { // If CIRA is allowed
2012 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo Intel&reg; Computador AMT localizado na Internet." + '\" onclick=\'return addCiraDeviceToMesh(\"' + mesh._id + '\")\'>' + "Adicionar CIRA" + '</a>';
2013 + }
2014 + if (mesh.mtype == 1) {
2015 + if ((features & 1) == 0) { // If not WAN-Only
2016 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo Intel&reg; AMT computer that is located on the local network." + '\" onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "Adicionar local" + '</a>';
2017 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo Intelreg; Computador AMT digitalizando a rede local." + '\" onclick=\'return addAmtScanToMesh(\"' + mesh._id + '\")\'>' + "Escaneamento via rede" + '</a>';
2018 + }
2019 + if (mesh.amt && (mesh.amt.type == 2)) { // CCM activation
2020 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Execute a ativação do modo de controle do cliente Intel AMT (CCM)." + '\" onclick=\'return showCcmActivation(\"' + mesh._id + '\")\'>' + "Ativação" + '</a>';
2021 + } else if (mesh.amt && (mesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation
2022 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Execute a ativação do modo de controle de administração Intel AMT (ACM)." + '\" onclick=\'return showAcmActivation(\"' + mesh._id + '\")\'>' + "Ativação" + '</a>';
2023 + }
2024 + }
2025 + if (mesh.mtype == 2) {
2026 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo computador a essa malha instalando o agente de malha." + '\" onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "Adicionar agente" + '</a>';
2027 + if ((features & 2) == 0) { r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Convide alguém para instalar o agente de malha nessa malha." + '\" onclick=\'return inviteAgentToMesh(\"' + mesh._id + '\")\'>' + "Convite" + '</a>'; }
2028 + }
2029 + return r;
2030 + }
2031 +
2032 + function addDeviceToMesh(meshid) {
2033 + if (xxdialogMode) return false;
2034 + var mesh = meshes[meshid];
2035 + var x = format("Adicione um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
2036 + x += addHtmlValue("Nome do Dispositivo", '<input id=dp1devicename style=width:230px maxlength=32 autocomplete=off onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2037 + x += addHtmlValue("Hostname", '<input id=dp1hostname style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "Igual ao nome do dispositivo" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2038 + x += addHtmlValue("Nome de usuário", '<input id=dp1username style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "admin" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2039 + x += addHtmlValue("Senha", '<input id=dp1password type=password style=width:230px autocomplete=off maxlength=32 onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
2040 + x += addHtmlValue("Segurança", '<select id=dp1tls style=width:236px><option value=0>' + "Sem segurança TLS" + '</option><option value=1>' + "Segurança TLS necessária" + '</option></select>');
2041 + setDialogMode(2, "Adicione Intelreg; dispositivo AMT", 3, addDeviceToMeshEx, x, meshid);
2042 + validateDeviceToMesh();
2043 + Q('dp1devicename').focus();
2044 + return false;
2045 + }
2046 +
2047 + // Intel AMT CCM Activation
2048 + function showCcmActivation(meshid) {
2049 + if (xxdialogMode) return false;
2050 + var servername = serverinfo.name, mesh = meshes[meshid];
2051 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2052 + var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2053 + if (serverinfo.https == true) {
2054 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2055 + url = 'wss://' + servername + portStr + domainUrl;
2056 + } else {
2057 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2058 + url = 'ws://' + servername + portStr + domainUrl;
2059 + }
2060 + var x = format("Execute a ativação do modo de controle de cliente Intel AMT (CCM) para agrupar \"{0}\" baixando a ferramenta MeshCMD e executando-a assim:", EscapeHtml(mesh.name)) + '<br /><br />';
2061 + x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>meshcmd amtccm --url ' + url + 'amtactivate?id=' + meshid.split('/')[2] + ' --serverhttpshash ' + serverinfo.tlshash + '</textarea>';
2062 + setDialogMode(2, "Intel&reg; Ativação AMT", 9, null, x);
2063 + Q('idx_dlgOkButton').focus();
2064 + return false;
2065 + }
2066 +
2067 + // Intel AMT ACM Activation
2068 + function showAcmActivation(meshid) {
2069 + if (xxdialogMode) return false;
2070 + var servername = serverinfo.name, mesh = meshes[meshid];
2071 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2072 + var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2073 + if (serverinfo.https == true) {
2074 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2075 + url = 'wss://' + servername + portStr + domainUrl;
2076 + } else {
2077 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2078 + url = 'ws://' + servername + portStr + domainUrl;
2079 + }
2080 + var x = format("Execute a ativação do modo de controle de administração Intel AMT (ACM) para agrupar \"{0}\" baixando a ferramenta MeshCMD e executando-a assim:", EscapeHtml(mesh.name)) + '<br /><br />';
2081 + x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>meshcmd amtacm --url ' + url + 'amtactivate?id=' + meshid.split('/')[2] + ' --serverhttpshash ' + serverinfo.tlshash + '</textarea>';
2082 + if (serverinfo.amtAcmFqdn != null) {
2083 + x += ('<div style=margin-top:8px>' + "A Intel AMT precisará ser configurada com um FQDN confiável na MEBx ou ter uma LAN com fio na rede:" + ' <b>' + serverinfo.amtAcmFqdn.join(', ') + '</b></div>');
2084 + }
2085 + setDialogMode(2, "Intel&reg; Ativação AMT", 9, null, x);
2086 + Q('idx_dlgOkButton').focus();
2087 + return false;
2088 + }
2089 +
2090 + // Display the Intel AMT scanning dialog box
2091 + function addAmtScanToMesh(meshid) {
2092 + if (xxdialogMode) return false;
2093 + var x = "Digite um intervalo de endereços IP para procurar dispositivos Intel AMT." + '<br /><br />';
2094 + x += addHtmlValue("IP Range", '<input id=dp1range style=width:184px value="192.168.1.0/24" onkeyup=addAmtScanToMeshKeyUp(event) /><input id=dp1rangebutton type=button value=\"' + "Scan" + '\" onclick=addAmtScanToMeshButton()></input>');
2095 + x += '<div id=dp1results style="width:100%;height:200px;background-color:white;border:1px gray solid;overflow-y:scroll"></div>';
2096 + setDialogMode(2, "Digitalizar para Intel&reg; dispositivos AMT", 3, addAmtScanToMeshEx, x, meshid);
2097 + QE('idx_dlgOkButton', false);
2098 + QH('dp1results', '<div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100</div>');
2099 + focusTextBox('dp1range');
2100 + return false;
2101 + }
2102 +
2103 + function addAmtScanToMeshKeyUp(e) {
2104 + if (e.keyCode == 13) { haltEvent(e); addAmtScanToMeshButton(); }
2105 + }
2106 +
2107 + // Called when OK is pressed on the Intel AMT scanning box
2108 + function addAmtScanToMeshEx(button, meshid) {
2109 + var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
2110 + for (var i=0;i<elements.length;i++) {
2111 + if (elements[i].checked) {
2112 + var ipaddr = elements[i].getAttribute('tag');
2113 + var amtinfo = amtScanResults[ipaddr];
2114 + meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: ipaddr, hostname: amtinfo.hostname, amtusername: '', amtpassword: '', amttls: amtinfo.tls });
2115 + }
2116 + }
2117 + }
2118 +
2119 + // If the user presses the "Scan" button on the Intel AMT scanning dialog box, start a scan.
2120 + function addAmtScanToMeshButton() {
2121 + QE('dp1range', false);
2122 + QE('dp1rangebutton', false);
2123 + QH('dp1results', '<div style=width:100%;text-align:center;margin-top:12px>' + "Escaneando..." + '</div>');
2124 + meshserver.send({ action: 'scanamtdevice', range: Q('dp1range').value });
2125 + }
2126 +
2127 + // Called when a scanned computer is checked or unchecked.
2128 + function addAmtScanToMeshCheckbox() {
2129 + var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
2130 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) checkcount++; }
2131 + QE('idx_dlgOkButton', checkcount > 0);
2132 + }
2133 +
2134 + function addCiraDeviceToMesh(meshid) {
2135 + if (xxdialogMode) return false;
2136 + var mesh = meshes[meshid];
2137 +
2138 + // Replace non alphabetic characters (@ and $) with 'X' because MPS username cannot accept it.
2139 + var meshidx = meshid.split('/')[2].replace(/\@/g, 'X').replace(/\$/g, 'X');
2140 +
2141 + var y = '<select id=dlgAddCiraSel onclick=dlgAddCiraSelClick() style=width:230px><option value=0>' + "MeshCommander Script" + '</option><option value=1>' + "Nome de usuário / senha manual" + '</option>';
2142 + if ((features & 16) == 0) { y += ('<option value=2>' + "Certificado manual" + '</option></select>'); } // Only display this option if Intel AMT CIRA with Mutual-Auth is allowed.
2143 +
2144 + var x = '';
2145 + x += addHtmlValue("Método de instalação", y);
2146 + x += '<hr>';
2147 +
2148 + // Setup CIRA using a MeshCommander script (Pretty Simple)
2149 + x += '<div id=dlgAddCira0>' + format("Para adicionar um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\" com CIRA, baixe os seguintes arquivos de script e use <a href='http://meshcommander.com' rel='noreferrer noopener' target='_blank'>MeshCommander</a> para executar o script para configurar computadores.", EscapeHtml(mesh.name)) + '<br /><br />';
2150 + //x += addHtmlValue('Setup CIRA', '<a href="mescript.ashx?type=1&meshid=' + meshidx.substring(0, 16) + '" download>cira_setup.mescript</a>');
2151 + x += addHtmlValue("Configuração CIRA", '<a href="mescript.ashx?type=1&meshid=' + meshid + '" download>cira_setup.mescript</a>');
2152 + x += addHtmlValue("Limpeza CIRA", '<a href="mescript.ashx?type=2" download>cira_clean.mescript</a>');
2153 + x += '</div>';
2154 +
2155 + // Setup CIRA with user/pass authentication (Somewhat difficult)
2156 + x += '<div id=dlgAddCira1 style=display:none>' + format("Para adicionar um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\" com CIRA, carregue o seguinte certificado como raiz confiável no Intel AMT", EscapeHtml(mesh.name));
2157 + if (serverinfo.mpspass) { x += ("e autenticar no servidor usando esse nome de usuário e senha." + '<br /><br />'); } else { x += ("e autenticar no servidor usando esse nome de usuário e qualquer senha." + '<br /><br />'); }
2158 + x += addHtmlValue("Certificado raiz", '<a href=\"' + "MeshServerRootCert.cer" + '\" download>' + "Arquivo de certificado raiz" + '</a>');
2159 + x += addHtmlValue("Nome de usuário", '<input style=width:230px readonly value="' + meshidx.substring(0, 16) + '" />');
2160 + if (serverinfo.mpspass) { x += addHtmlValue("Senha", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpspass) + '" />'); }
2161 + if (serverinfo != null) { x += addHtmlValue("Servidor MPS", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
2162 + x += '</div>';
2163 +
2164 + // Setup CIRA with certificate authentication (Really difficult, only if TLS offload is not used)
2165 + if ((features & 16) == 0) {
2166 + x += '<div id=dlgAddCira2 style=display:none>' + format("Para adicionar um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\" com CIRA, carregue o seguinte certificado como raiz confiável no Intel AMT, autentique usando um certificado de cliente com o seguinte nome comum e conecte-se ao servidor a seguir.", EscapeHtml(mesh.name)) + '<br /><br />';
2167 + x += addHtmlValue("Certificado raiz", '<a href="MeshServerRootCert.cer" download>' + "Arquivo de certificado raiz" + '</a>');
2168 + x += addHtmlValue("Organização", '<input style=width:230px readonly value="' + meshidx + '" />');
2169 + if (serverinfo != null) { x += addHtmlValue("Servidor MPS", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
2170 + x += '</div>';
2171 + }
2172 +
2173 + setDialogMode(2, "Adicione Intelreg; ", 2, null, x, 'fileDownload');
2174 + Q('dlgAddCiraSel').focus();
2175 + return false;
2176 + }
2177 +
2178 + function dlgAddCiraSelClick() {
2179 + var val = Q('dlgAddCiraSel').value;
2180 + QV('dlgAddCira0', val == 0);
2181 + QV('dlgAddCira1', val == 1);
2182 + QV('dlgAddCira2', val == 2);
2183 + }
2184 +
2185 + // Return true is the input string looks like an email address
2186 + function checkEmail(str) {
2187 + var x = str.split('@');
2188 + var ok = ((x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2));
2189 + if (ok == true) { var y = x[1].split('.'); for (var i in y) { if (y[i].length == 0) { ok = false; } } }
2190 + return ok;
2191 + }
2192 +
2193 + function inviteAgentToMesh(meshid) {
2194 + if (xxdialogMode) return false;
2195 + var x = '', mesh = meshes[meshid];
2196 + if (features & 64) {
2197 + x += addHtmlValue("Tipo de convite", '<select id=d2InviteType onchange=d2ChangedInviteType() style=width:236px><option value=0>Link invitation</option><option value=1>Email invitation</option></select>') + '<hr />';
2198 + x += '<div id=emailInviteDiv style=display:none>' + format("Convide alguém para instalar o agente de malha.Um email será enviado com o link para a instalação do agente de malha para o grupo de dispositivos \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
2199 + x += addHtmlValue("Nome (Opcional)", '<input id=agentInviteName value="" style=width:230px maxlength=64 />');
2200 + x += addHtmlValue("Email", '<input id=agentInviteEmail style=width:230px placeholder=\"' + "example@email.com" + '\" onkeyup=validateAgentInvite()></input>');
2201 + x += addHtmlValue("Sistema operacional", '<select id=agentInviteNameOs onchange=d2ChangedInviteType() style=width:236px><option value=4>' + "Enviar link de instalação" + '</option><option value=0 selected>' + "Qualquer suportado" + '</option><option value=1>' + "Apenas Windows" + '</option><option value=3>' + "Apenas Apple MacOS " + '</option><option value=2>' + "Apenas Linux" + '</option></select>');
2202 + x += '<div id=d2agentexpirediv>';
2203 + x += addHtmlValue("Expiração do link", '<select id=agentInviteExpire style=width:236px><option value=1>' + "1 hora" + '</option><option value=8>' + "8 horas" + '</option><option value=24>' + "1 dia" + '</option><option value=168>' + "1 semana" + '</option><option value=5040>' + "1 mês" + '</option><option value=0>' + "Ilimitado" + '</option></select>');
2204 + x += '</div>';
2205 + x += addHtmlValue("Tipo de instalação ", '<select id=agentInviteType style=width:236px><option value=0>' + "Segundo plano e interativo" + '</option><option value=2>' + "Apenas em segundo plano" + '</option><option value=1>' + "Apenas interativo" + '</option></select>');
2206 + x += addHtmlValue("Mensagem" + '<br />' + "(opcional)", '<textarea id=agentInviteMessage value="" style=width:230px;height:100px;resize:none maxlength=1024 /></textarea>');
2207 + x += '</div>';
2208 + }
2209 + x += '<div id=urlInviteDiv>' + format("Convide alguém para instalar o agente de malha compartilhando um link de convite.Este link indica ao usuário instruções de instalação para o grupo de dispositivos \"{0}\". O link é público e nenhuma conta para este servidor é necessária.", EscapeHtml(mesh.name)) + '<br /><br />';
2210 + x += addHtmlValue("Expiração do link", '<select id=d2inviteExpire style=width:236px onchange=d2RequestInvitationLink()><option value=1>' + "1 hora" + '</option><option value=8>' + "8 horas" + '</option><option value=24>' + "1 dia" + '</option><option value=168>' + "1 semana" + '</option><option value=5040>' + "1 mês" + '</option><option value=0>' + "Ilimitado" + '</option></select>');
2211 + x += '<div id=agentInvitationLinkDiv style="text-align:center;font-size:large;margin:16px;display:none"><a href=# id=agentInvitationLink target="_blank" style=cursor:pointer></a> <img src=images/link4.png height=10 width=10 title=\"' + "Copiar link para a área de transferência" + '\" style=cursor:pointer onclick=d2CopyInviteToClip()></div></div>';
2212 + setDialogMode(2, "Convite", 3, performAgentInvite, x, meshid);
2213 + if (features & 64) { Q('d2InviteType').focus(); d2ChangedInviteType(); } else { Q('d2inviteExpire').focus(); validateAgentInvite(); }
2214 + d2RequestInvitationLink();
2215 + return false;
2216 + }
2217 +
2218 + function d2RequestInvitationLink() {
2219 + meshserver.send({ action: 'createInviteLink', meshid: xxdialogTag, expire: parseInt(Q('d2inviteExpire').value), flags: 0 });
2220 + }
2221 +
2222 + function d2ChangedInviteType() {
2223 + QV('urlInviteDiv', Q('d2InviteType').value == 0);
2224 + QV('d2agentexpirediv', Q('agentInviteNameOs').value == 4);
2225 + QV('emailInviteDiv', Q('d2InviteType').value == 1);
2226 + validateAgentInvite();
2227 + }
2228 +
2229 + function d2CopyInviteToClip() { copyTextToClip(Q('agentInvitationLink').href); }
2230 +
2231 + function validateAgentInvite() {
2232 + if ((features & 64) && (Q('d2InviteType').value == 1)) {
2233 + QE('idx_dlgOkButton', checkEmail(Q('agentInviteEmail').value));
2234 + QV('idx_dlgCancelButton', true);
2235 + } else {
2236 + QE('idx_dlgOkButton', true);
2237 + QV('idx_dlgCancelButton', false);
2238 + }
2239 + }
2240 +
2241 + function performAgentInvite(button, meshid) {
2242 + if ((features & 64) && (Q('d2InviteType').value == 1)) {
2243 + meshserver.send({ action: 'inviteAgent', meshid: meshid, email: Q('agentInviteEmail').value, name: Q('agentInviteName').value, os: Q('agentInviteNameOs').value, flags: Q('agentInviteType').value, msg: Q('agentInviteMessage').value, expire: parseInt(Q('agentInviteExpire').value) });
2244 + }
2245 + }
2246 +
2247 + function addAgentToMesh(meshid) {
2248 + if (xxdialogMode) return false;
2249 + var mesh = meshes[meshid], x = '', installType = 0;
2250 + x += addHtmlValue("Sistema operacional", '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Windows" + '</option><option value=1>' + "Linux / BSD" + '</option><option value=2>' + "Apple MacOS" + '</option><option value=3>' + "Windows (Desinstalador)" + '</option><option value=4>' + "Linux / BSD (desinstalação)" + '</option></select>');
2251 + x += '<div id=aginsTypeDiv>';
2252 + x += addHtmlValue("Tipo de instalação ", '<select id=aginsType onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Segundo plano e interativo" + '</option><option value=2>' + "Apenas em segundo plano" + '</option><option value=1>' + "Apenas interativo" + '</option></select>');
2253 + x += '</div><hr>';
2254 +
2255 + // \/:*?"<>|
2256 + var meshfilename = mesh.name
2257 + meshfilename = meshfilename.split('\\').join('').split('/').join('').split(':').join('').split('*').join('').split('?').join('').split('"').join('').split('<').join('').split('>').join('').split('|').join('').split(' ').join('').split('\'').join('');
2258 +
2259 + // Windows agent install
2260 + //x += "<div id=agins_windows>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and configuration file and install the agent on the computer to manage.<br /><br />";
2261 + x += '<div id=agins_windows>' + format("Para adicionar um novo computador ao grupo de dispositivos \"{0}\", faça o download do agente de malha e instale-o no computador para gerenciar. Este agente possui informações de servidor e grupo de dispositivos incorporadas.", EscapeHtml(mesh.name)) + '<br /><br />';
2262 + x += addHtmlValue("Mesh Agent", '<a id=aginsw32lnk href="meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "Versão de 32 bits do MeshAgent" + '\">' + "Windows (.exe)" + '</a> <img src=images/link4.png height=10 width=10 title="Copy Windows 32bit agent URL to clipboard" style=cursor:pointer onclick=copyAgentUrl("meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=",1)>');
2263 + x += addHtmlValue("Mesh Agent", '<a id=aginsw64lnk href="meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "Versão de 64 bits do MeshAgent" + '\">' + "Windows x64 (.exe)" + '</a> <img src=images/link4.png height=10 width=10 title="Copy Windows 64bit agent URL to clipboard" style=cursor:pointer onclick=copyAgentUrl("meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=",1)>');
2264 + if (debugmode > 0) { x += addHtmlValue("Arquivo de configurações", '<a id=aginswmshlnk href="meshsettings?id=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank">' + format("{0} configurações (.msh)", EscapeHtml(mesh.name)) + '</a>'); }
2265 + x += '</div>';
2266 +
2267 + // Linux agent install
2268 + x += '<div id=agins_linux style=display:none>' + format("Para adicionar um computador a {0}, execute o seguinte comando.Serão necessárias credenciais raiz.", EscapeHtml(mesh.name)) + '<br />';
2269 + x += '<textarea id=agins_linux_area rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
2270 + x += '<div style=\'font-size:x-small\'>' + "* Para o BSD, execute \"pkg install wget sudo bash\"." + '</div></div>';
2271 +
2272 + // MacOS agent install
2273 + x += '<div id=agins_osx style=display:none>' + format("Para adicionar um novo computador ao grupo de dispositivos \"{0}\", faça o download do agente de malha e instale-o no computador para gerenciar. Este instalador do agente possui informações de servidor e grupo de dispositivos incorporadas.", EscapeHtml(mesh.name)) + '<br /><br />';
2274 + x += addHtmlValue("Mesh Agent", '<a href="meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '" rel="noreferrer noopener" target="_blank" title="64bit version of MacOS Mesh Agent">MacOS Agent (64bit)</a> <img src=images/link4.png height=10 width=10 title="' + "Copiar o URL do agente MacOS para a área de transferência" + '" style=cursor:pointer onclick=copyAgentUrl("meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '",0)>');
2275 + x += '</div>';
2276 +
2277 + // Windows agent uninstall
2278 + x += '<div id=agins_windows_un style=display:none>' + "Para remover um agente de malha, faça o download do arquivo abaixo, execute-o e clique em \"uninstall\"." + '<br /><br />';
2279 + x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=3" download onclick="setDialogMode(0)" title="' + "Versão de 32 bits do MeshAgent" + '">' + "Windows (.exe)" + '</a>');
2280 + x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=4" download onclick="setDialogMode(0)" title="' + "Versão de 64 bits do MeshAgent" + '">' + "Windows x64 (.exe)" + '</a>');
2281 + x += '</div>';
2282 +
2283 + // Linux agent uninstall
2284 + x += '<div id=agins_linux_un style=display:none>' + "Para remover um agente de malha, execute o seguinte comando. Serão necessárias credenciais raiz." + '<br />';
2285 + x += '<textarea id=agins_linux_area_un rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
2286 + x += '</div>';
2287 +
2288 + setDialogMode(2, "Adicionar agente de malha", 2, null, x, 'fileDownload');
2289 + var servername = serverinfo.name;
2290 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2291 + var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2292 +
2293 + if (serverinfo.https == true)
2294 + {
2295 + var portStr = (serverinfo.port == 443)?'':(':' + serverinfo.port);
2296 + if ((features & 0x2000) == 0)
2297 + {
2298 + Q('agins_linux_area').value = '(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 -E ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\' || ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
2299 + Q('agins_linux_area_un').value = '(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';
2300 + }
2301 + else
2302 + {
2303 + // Server asked that agent be installed to preferably not use a HTTP proxy.
2304 + Q('agins_linux_area').value = '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.split('/')[2] + '\' || ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
2305 + Q('agins_linux_area_un').value = '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';
2306 + }
2307 + }
2308 + else
2309 + {
2310 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2311 + if ((features & 0x2000) == 0)
2312 + {
2313 + Q('agins_linux_area').value = '(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 -E ./meshinstall.sh http://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
2314 + Q('agins_linux_area_un').value = '(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';
2315 + }
2316 + else
2317 + {
2318 + // Server asked that agent be installed to preferably not use a HTTP proxy.
2319 + Q('agins_linux_area').value = '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.split('/')[2] + '\'\r\n';
2320 + Q('agins_linux_area_un').value = 'wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
2321 + }
2322 + }
2323 + Q('aginsSelect').focus();
2324 + addAgentToMeshClick();
2325 + return false;
2326 + }
2327 +
2328 + function copyAgentUrl(url,addflag) {
2329 + var servername = serverinfo.name;
2330 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2331 + var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2332 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2333 + var c = 'https://' + servername + portStr + domainUrl + url;
2334 + if (addflag == 1) c += Q('aginsType').value;
2335 + copyTextToClip(c);
2336 + }
2337 +
2338 + function addAgentToMeshClick() {
2339 + var v = Q('aginsSelect').value;
2340 + QV('agins_windows', v == 0);
2341 + QV('agins_linux', v == 1);
2342 + QV('agins_osx', v == 2);
2343 + QV('agins_windows_un', v == 3);
2344 + QV('agins_linux_un', v == 4);
2345 + QV('aginsTypeDiv', v == 0);
2346 +
2347 + // Fix the links if needed
2348 + Q('aginsw32lnk').href = (Q('aginsw32lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
2349 + Q('aginsw64lnk').href = (Q('aginsw64lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
2350 + if (debugmode > 0) { Q('aginswmshlnk').href = (Q('aginswmshlnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value; }
2351 + }
2352 +
2353 + function validateDeviceToMesh() {
2354 + QE('idx_dlgOkButton', (Q('dp1devicename').value.length > 0) && (passwordcheck(Q('dp1password').value)));
2355 + }
2356 +
2357 + function addDeviceToMeshEx(button, meshid) {
2358 + var amtuser = Q('dp1username').value;
2359 + if (amtuser == '') amtuser = 'admin';
2360 + var host = Q('dp1hostname').value;
2361 + if (host == '') host = Q('dp1devicename').value;
2362 + meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: Q('dp1devicename').value, hostname: host, amtusername: amtuser, amtpassword: Q('dp1password').value, amttls: Q('dp1tls').value });
2363 + }
2364 +
2365 + function deviceHeaderSet() {
2366 + if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
2367 + deviceHeaders['DevxHeader' + deviceHeaderId] = ((deviceHeaderTotal == 1) ? "1 nó" : format("{0} nós", deviceHeaderTotal));
2368 + //var title = '';
2369 + //for (x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
2370 + //deviceHeadersTitles["DevxHeader" + deviceHeaderId] = title;
2371 + deviceHeaderId++;
2372 + deviceHeaderCount = {};
2373 + deviceHeaderTotal = 0;
2374 + }
2375 +
2376 + var powerStateStrings = ['', '<span title=\"' + "O dispositivo está ligado." + '\">' + "Ligado" + '</span>', '<span title=\"' + "O dispositivo está no estado de suspensão (S1)." + '\">' + "Hibernando" + '</span>', '<span title=\"' + "O dispositivo está no estado de suspensão (S2)." + '\">' + "Hibernando" + '</span>', '<span title=\"' + "O dispositivo está no estado de suspensão profunda (S3)." + '\">' + "Deep Sleep" + '</span>', '<span title=\"' + "O dispositivo está no estado de hibernação (S4)." + '\">' + "Hibernando" + '</span>', '<span title=\"' + "O dispositivo está no estado desligado (S5)." + '\">' + "Soft-Off" + '</span>', '<span title=\"' + "O dispositivo foi detectado, mas não foi possível obter o estado de energia." + '\">' + "Presente" + '</span>'];
2377 + var powerStateStrings2 = ['', "O dispositivo está ligado", "O dispositivo está no estado de suspensão (S1)", "O dispositivo está no estado de suspensão (S2)", "O dispositivo está no estado de sono profundo (S3)", "O dispositivo está hibernando (S4)", "O dispositivo está no estado soft-off (S5)", "O dispositivo está presente, mas o estado de energia não pode ser determinado"];
2378 + var powerColorTable = ['pwsTransparent', 'pwsBlack', 'pwsBlue', 'pwsBlue2', 'pwsLightblue', 'pwsBlueviolet', 'pwsDarkgreen', 'pwsLightseagreen', 'pwsLightseagreen2'];
2379 + function NodeStateStr(node) {
2380 + var states = [];
2381 + if (node.state > 0 && node.state < powerStatetable.length) state.push(powerStatetable[node.state]);
2382 + if (node.conn) {
2383 + if ((node.conn & 1) != 0) { states.push('<span title=\"' + "O agente de malha está conectado e pronto para uso." + '\">' + "Agente" + '</span>'); }
2384 + if ((node.conn & 2) != 0) { states.push('<span title=\"' + "Intel&reg; O AMT CIRA está conectado e pronto para uso." + '\">' + "CIRA" + '</span>'); }
2385 + else if ((node.conn & 4) != 0) { states.push('<span title=\"' + "Intel&reg; AMT é roteável." + '\">' + "AMT" + '</span>'); }
2386 + if ((node.conn & 8) != 0) { states.push('<span title=\"' + "O agente de malha é alcançável usando outro agente como retransmissão." + '\">' + "Retransmissão" + '</span>'); }
2387 + if ((node.conn & 16) != 0) { states.push('<span title=\"' + "A conexão MQTT com o dispositivo está ativa." + '\">' + "MQTT" + '</span>'); }
2388 + }
2389 + if ((node.pwr != null) && (node.pwr != 0)) { states.push(powerStateStrings[node.pwr]); }
2390 + return states.join(', ');
2391 + }
2392 +
2393 + function PowerStateStr(x) {
2394 + if (x < powerStatetable.length) return powerStatetable[x];
2395 + return '';
2396 + }
2397 +
2398 + function PowerStateStr2(x) {
2399 + if ((x != 0) && (x < powerStatetable.length)) return powerStatetable[x];
2400 + return "Desconhecido";
2401 + }
2402 +
2403 + function selectallButtonFunction() {
2404 + var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
2405 + for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) checkcount++; }
2406 + for (var i=0;i<elements.length;i++) { elements[i].checked = (checkcount == 0); }
2407 + p1updateInfo();
2408 + }
2409 +
2410 + function p1updateInfo() {
2411 + var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
2412 + for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) { checkcount++; } }
2413 + if (checkcount > 0) {
2414 + QE('GroupActionButton', true);
2415 + Q('SelectAllButton').value = "Selecione nenhum";
2416 + QV('cxmgroupsplit', true);
2417 + QV('cxmdesktop', true);
2418 + } else {
2419 + QE('GroupActionButton', false);
2420 + Q('SelectAllButton').value = "Selecionar tudo";
2421 + QV('cxmgroupsplit', false);
2422 + QV('cxmdesktop', false);
2423 + }
2424 + }
2425 +
2426 + function groupActionFunction() {
2427 + var addedOptions = '', nodeids = getCheckedDevices();
2428 +
2429 + // Check if any of the selected devices have a MQTT connection active
2430 + if (features & 0x00400000) {
2431 + for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { addedOptions += '<option value=103>' + "Enviar Mensagem MQTT" + '</option>'; break; } }
2432 + }
2433 +
2434 + // Display the "Uninstall Agent" option if allowed and we selected connected devices.
2435 + for (var i in nodeids) {
2436 + var node = getNodeFromId(nodeids[i]);
2437 + var mesh = meshes[node.meshid];
2438 + var meshrights = mesh.links[userinfo._id].rights;
2439 + if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
2440 + }
2441 +
2442 + var x = "Selecione uma operação para executar em todos os dispositivos selecionados. As ações serão executadas apenas com os direitos adequados." + '<br /><br />';
2443 + x += addHtmlValue("Operação", '<select id=d2groupop><option value=100>' + "Acordar dispositivo" + '</option><option value=4>' + "Hibernar dispositivo" + '</option><option value=3>' + "Redefinir dispositivos" + '</option><option value=2>' + "Desligar dispositivos" + '</option><option value=102>' + "Mover para o grupo de dispositivos" + '</option>' + addedOptions + '<option value=101>' + "Excluir Dispositivos" + '</option></select>');
2444 + setDialogMode(2, "Ações do grupo", 3, groupActionFunctionEx, x);
2445 + }
2446 +
2447 + // Get the list of checked devices, removes any duplicates.
2448 + function getCheckedDevices() {
2449 + var nodeids = [], elements = document.getElementsByClassName("Caixa de seleção do dispositivo"), checkcount = 0;
2450 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
2451 + return nodeids;
2452 + }
2453 +
2454 + function groupActionFunctionEx() {
2455 + var op = Q('d2groupop').value;
2456 + if (op == 100) {
2457 + // Group wake
2458 + meshserver.send({ action: 'wakedevices', nodeids: getCheckedDevices() });
2459 + } else if (op == 101) {
2460 + // Group delete, ask for confirmation
2461 + var x = "Confirmar a exclusão dos dispositivos selecionados?" + '<br /><br />';
2462 + x += '<label><input id=d2check type=checkbox onchange=d2groupActionFunctionDelEx() />' + "Confirme" + '</label>';
2463 + setDialogMode(2, "Excluir nós", 3, groupActionFunctionDelEx, x);
2464 + QE('idx_dlgOkButton', false);
2465 + } else if (op == 102) {
2466 + // Move computers to a different group
2467 + p10showChangeGroupDialog(getCheckedDevices());
2468 + } else if (op == 103) {
2469 + // Send MQTT Message
2470 + p10showSendMqttMsgDialog(getCheckedDevices());
2471 + } else if (op == 104) {
2472 + // Uninstall agent
2473 + p10showSendUninstallAgentDialog(getCheckedDevices());
2474 + } else {
2475 + // Power operation
2476 + meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: parseInt(op) });
2477 + }
2478 + }
2479 +
2480 + function d2groupActionFunctionDelEx() { QE('idx_dlgOkButton', Q('d2check').checked); }
2481 + function groupActionFunctionDelEx() { meshserver.send({ action: 'removedevices', nodeids: getCheckedDevices() }); }
2482 +
2483 + function onSortSelectChange(skipsave) {
2484 + sort = document.getElementById('sortselect').selectedIndex;
2485 + if (!skipsave) { putstore('sort', sort); }
2486 + }
2487 +
2488 + function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
2489 + function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap > bp) return -1; if (ap < bp) return 1; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
2490 + function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
2491 + function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
2492 + function onSearchFocus(x) { searchFocus = x; }
2493 + function onMapSearchFocus(x) { mapSearchFocus = x; }
2494 + function onUserSearchFocus(x) { userSearchFocus = x; }
2495 + function onConsoleFocus(x) { consoleFocus = x; }
2496 +
2497 + function onSearchInputChanged() {
2498 + var x = Q('SearchInput').value.toLowerCase().trim(); putstore('_search', x);
2499 + var userSearch = null, ipSearch = null, groupSearch = null;
2500 + if (x.startsWith('user:')) { userSearch = x.substring(5); }
2501 + else if (x.startsWith('u:')) { userSearch = x.substring(2); }
2502 + else if (x.startsWith('ip:')) { ipSearch = x.substring(3); }
2503 + else if (x.startsWith('group:')) { groupSearch = x.substring(6); }
2504 + else if (x.startsWith('g:')) { groupSearch = x.substring(2); }
2505 +
2506 + if (x == '') {
2507 + // No search
2508 + for (var d in nodes) { nodes[d].v = true; }
2509 + } else if (ipSearch != null) {
2510 + // IP address search
2511 + for (var d in nodes) { nodes[d].v = ((nodes[d].ip != null) && (nodes[d].ip.indexOf(ipSearch) >= 0)); }
2512 + } else if (groupSearch != null) {
2513 + // Group filter
2514 + for (var d in nodes) { nodes[d].v = (meshes[nodes[d].meshid].name.toLowerCase().indexOf(groupSearch) >= 0); }
2515 + } else if (userSearch != null) {
2516 + // User search
2517 + for (var d in nodes) {
2518 + nodes[d].v = false;
2519 + if (nodes[d].users && nodes[d].users.length > 0) { for (var i in nodes[d].users) { if (nodes[d].users[i].toLowerCase().indexOf(userSearch) >= 0) { nodes[d].v = true; } } }
2520 + }
2521 + } else {
2522 + // Device name search
2523 + try {
2524 + var rs = x.split(/\s+/).join('|'), rx = new RegExp(rs); // In some cases (like +), this can throw an exception.
2525 + for (var d in nodes) {
2526 + nodes[d].v = (rx.test(nodes[d].name.toLowerCase())) || (nodes[d].rnamel != null && rx.test(nodes[d].rnamel.toLowerCase()));
2527 + if ((nodes[d].v == false) && nodes[d].tags) {
2528 + for (var s in nodes[d].tags) {
2529 + if (rx.test(nodes[d].tags[s].toLowerCase())) {
2530 + nodes[d].v = true;
2531 + break;
2532 + } else {
2533 + nodes[d].v = false;
2534 + }
2535 + }
2536 + }
2537 + }
2538 + } catch (ex) { for (var d in nodes) { nodes[d].v = true; } }
2539 + }
2540 + }
2541 +
2542 + var contextelement = null;
2543 + function handleContextMenu(event) {
2544 + hideContextMenu();
2545 + var scrollLeft = (window.pageXOffset !== null) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
2546 + var scrollTop = (window.pageYOffset !== null) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
2547 + var elem = document.elementFromPoint(event.pageX - scrollLeft, event.pageY - scrollTop);
2548 + if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 0) && (currentNode.agent.id < 5)) {
2549 + contextelement = elem;
2550 + var contextmenudiv = document.getElementById('termShellContextMenu');
2551 + contextmenudiv.style.left = event.pageX + 'px';
2552 + contextmenudiv.style.top = event.pageY + 'px';
2553 + contextmenudiv.style.display = 'block';
2554 + } else if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 4)) {
2555 + contextelement = elem;
2556 + var contextmenudiv = document.getElementById('termShellContextMenuLinux');
2557 + contextmenudiv.style.left = event.pageX + 'px';
2558 + contextmenudiv.style.top = event.pageY + 'px';
2559 + contextmenudiv.style.display = 'block';
2560 + } else if (elem && elem != null && elem.id == 'MxMESH') {
2561 + contextelement = elem;
2562 + var contextmenudiv = document.getElementById('meshContextMenu');
2563 + contextmenudiv.style.left = event.pageX + 'px';
2564 + contextmenudiv.style.top = event.pageY + 'px';
2565 + contextmenudiv.style.display = 'block';
2566 + /*} else if (elem && elem != null && elem.classList.contains('pluginTab')) {
2567 + contextelement = elem;
2568 + var contextmenudiv = document.getElementById('pluginTabContextMenu');
2569 + contextmenudiv.style.left = event.pageX + 'px';
2570 + contextmenudiv.style.top = event.pageY + 'px';
2571 + contextmenudiv.style.display = 'block';*/
2572 + } else {
2573 + while (elem && elem != null && elem.id != 'devs') { elem = elem.parentElement; }
2574 + if (!elem || elem == null) return true;
2575 + contextelement = elem;
2576 + var contextmenudiv = document.getElementById('contextMenu');
2577 + contextmenudiv.style.left = event.pageX + 'px';
2578 + contextmenudiv.style.top = event.pageY + 'px';
2579 + contextmenudiv.style.display = 'block';
2580 +
2581 + // Get the node and set the menu options
2582 + var nodeid = contextelement.children[1].attributes.onclick.value;
2583 + var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
2584 + var mesh = meshes[node.meshid];
2585 + var meshlinks = mesh.links[userinfo._id];
2586 + var meshrights = meshlinks.rights;
2587 + var consoleRights = ((meshrights & 16) != 0);
2588 +
2589 + // Check if we have terminal and file access
2590 + var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
2591 + var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
2592 +
2593 + QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((meshrights & 8) || (meshrights & 256)));
2594 + QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
2595 + QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
2596 + QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
2597 + QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
2598 + }
2599 +
2600 + return haltEvent(event);
2601 + }
2602 +
2603 + function cmaction(action,event) {
2604 + var nodeid = contextelement.children[1].attributes.onclick.value;
2605 + nodeid = nodeid.substring(12, nodeid.length - 18);
2606 + if (action == 7) { Q('viewselect').value = 3; Q('viewselect').onchange(); Q('autoConnectDesktopCheckbox').checked = true; Q('autoConnectDesktopCheckbox').onclick(); } // Multi-Desktop
2607 + if ((action > 0) && (action < 7)) {
2608 + var panel = [0, 10, 12, 11, 13, 16, 15][action]; // (invalid), General, Desktop, Terminal, Files, Events, Console
2609 + if (event && (event.shiftKey == true)) {
2610 + // Open the device in a different tab
2611 + window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=' + panel + '&hide=16', 'meshcentral:' + nodeid);
2612 + } else {
2613 + // Go to the right panel
2614 + gotoDevice(nodeid, panel);
2615 +
2616 + // If possible, connect...
2617 + var mesh = meshes[currentNode.meshid];
2618 + if ((currentNode.conn & 1) && (mesh.mtype == 2)) {
2619 + if ((panel == 11) && (desktop == null) && (currentNode.agent.caps & 1)) { connectDesktop(null, 1); } // Desktop
2620 + if ((panel == 12) && (terminal == null) && (currentNode.agent.caps & 2)) { connectTerminal(null, 1); } // Terminal
2621 + if ((panel == 13) && (files == null)) { connectFiles(null); } // files
2622 + }
2623 + }
2624 + }
2625 + }
2626 +
2627 + function cmmeshaction(action) {
2628 + var meshid = contextelement.attributes.onclick.value.substring(10, contextelement.attributes.onclick.value.length - 2);
2629 + var elements = document.getElementsByClassName('DeviceCheckbox');
2630 + if ((action == 1) || (action == 2)) {
2631 + for (var i = 0; i < elements.length; i++) {
2632 + if ((elements[i].attributes) && (elements[i].attributes['class']['value'].split(' ')[0] == meshid)) { elements[i].checked = (action == 1); }
2633 + }
2634 + }
2635 + //if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
2636 + p1updateInfo();
2637 + }
2638 +
2639 + function cmtermaction(action) {
2640 + connectTerminal(null, 1, { protocol: action });
2641 + }
2642 +
2643 + /*
2644 + function pluginTabClose() {
2645 + var pluginTab = contextelement;
2646 + var pname = pluginTab.getAttribute('x-data-plugin-sname');
2647 + var pdiv = Q('plugin-'+pname);
2648 + pdiv.parentNode.removeChild(pdiv);
2649 + pluginTab.parentNode.removeChild(pluginTab);
2650 + QV('p42', true);
2651 + goPlugin(-1);
2652 + }
2653 + */
2654 +
2655 + function hideContextMenu() {
2656 + QV('contextMenu', false);
2657 + QV('meshContextMenu', false);
2658 + QV('termShellContextMenu', false);
2659 + QV('termShellContextMenuLinux', false);
2660 + //QV('pluginTabContextMenu', false);
2661 + contextelement = null;
2662 + }
2663 +
2664 + //
2665 + // DEVICES MAP
2666 + //
2667 +
2668 + // Maps code starts from here. Initialize all the variables
2669 + var xxmap = {
2670 + map: null,
2671 + contextmenu: null,
2672 + activeInteractions: [], // Save Modified features in this list
2673 + showindex: 0,
2674 + markersSource: null, // Initialize a Source Vector
2675 + markersLayer: null,
2676 + mapLayer: null, // Create a tile and use OSM source
2677 + mapView: null, // Sets the initial view
2678 + }
2679 +
2680 + {{{StartGeoLocationJS}}}
2681 +
2682 + // Add a feature for every Node and change style if connection status changes
2683 + function updateMapMarkers(selectedMesh) {
2684 + if ((xxmap != null) && (xxmap.map == null)) { try { loadmap(); } catch (ex) { console.error('loadmap() exception', ex); } }
2685 + if (xxmap == null) return;
2686 + var boundingBox = null;
2687 + for (var i in nodes) {
2688 + try {
2689 + var loc = map_parseNodeLoc(nodes[i]), feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
2690 + if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
2691 + var lat = loc[0], lon = loc[1], type = loc[2];
2692 + if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
2693 + if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature
2694 + } else {
2695 + if (feature) { xxmap.markersSource.removeFeature(feature); }
2696 + }
2697 + } catch (ex) { console.error('updateMapMarkers() exception', ex, JSON.stringify(nodes[i])); }
2698 + }
2699 + return boundingBox;
2700 + }
2701 +
2702 + // Show node details on hovering over a feature
2703 + var map_cm_popup = new ol.Overlay({ element: Q('xmap-info-window'), positioning: 'bottom-center', stopEvent: false });
2704 +
2705 + // Edit Marker item
2706 + var map_cm_editMarker = { text: "Modificar localização do nó", callback: function (obj) { modifyMarkerloc(obj.data); } };
2707 +
2708 + // Clear Marker item
2709 + var map_cm_clearMarker = { text: "Remover localização do nó", callback: function (obj) {
2710 + meshserver.send({ action: 'changedevice', nodeid: obj.data.a, userloc: [] }); // Clear the user position marker
2711 + }};
2712 +
2713 + // Save Marker item
2714 + var map_cm_saveMarker = { text: "Salvar localização do nó", callback: function (obj) { saveMarkerloc(obj.data); } };
2715 +
2716 + // Build a context menu for a feature
2717 + var map_cm_nodemenu_items = [
2718 + { text: "Informações gerais", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 10); } } },
2719 + { text: "Área de Trabalho", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 11); } } },
2720 + { text: "Terminal", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 12); } } },
2721 + { text: "Intel&reg; AMT", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 14); } } },
2722 + '-',
2723 + { text: "Aumentar o zoom até o limite", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 19); } },
2724 + { text: "Diminuir o zoom até o limite", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 2); } }
2725 + ];
2726 +
2727 + // Context menu for clicks other than on feature
2728 + var contextmenu_items = [
2729 + { text: "Atualizar", callback: function () { refreshMap(true, true); } },
2730 + { text: "Zoom para ajustar a extensão", callback: function () { zoomToFitExtent(); } },
2731 + { text: "Centralize o mapa aqui", callback: function(obj) { xxmap.mapView.animate({ center: obj.coordinate } ); } },
2732 + { text: "Coloque o nó aqui", callback: function(obj) { placeNode(obj.coordinate); } }
2733 + ];
2734 +
2735 + function stringToIntHash(str) {
2736 + var hash = 0, i;
2737 + for (i = 0; i < str.length; i++) { hash = ((hash << 5) - hash) + str.charCodeAt(i); hash |= 0; }
2738 + return hash;
2739 + };
2740 +
2741 + // Get the lat/lon from a node
2742 + function map_parseNodeLoc(node) {
2743 + var loc = null, t = 0;
2744 + if (node.iploc) { loc = node.iploc; t = 1; }
2745 + if (node.wifiloc) { loc = node.wifiloc; t = 2; }
2746 + if (node.gpsloc) { loc = node.gpsloc; t = 3; }
2747 + if (node.userloc) { loc = node.userloc; t = 4; }
2748 + if ((loc == null) || (typeof loc != 'string')) return null;
2749 + loc = loc.split(',');
2750 + if (t == 1) {
2751 + // If this is IP location, randomize the position a little.
2752 + return [ parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000), t ];
2753 + } else {
2754 + // Return the real position
2755 + return [ parseFloat(loc[0]), parseFloat(loc[1]), t ];
2756 + }
2757 + }
2758 +
2759 + // Load the entire map
2760 + function loadmap() {
2761 + if (xxmap == null) return;
2762 + if ((features & 0x8000) == 0) { xxmap = null; return; } // Geolocation not supported
2763 + QV('viewselectmapoption', true);
2764 + QV('devViewButton4', true);
2765 + try {
2766 + // Initialize a Source Vector
2767 + xxmap.markersSource = new ol.source.Vector();
2768 +
2769 + xxmap.markersLayer = new ol.layer.Vector({
2770 + source: xxmap.markersSource
2771 + });
2772 +
2773 + // Create a tile and use OSM source
2774 + xxmap.mapLayer = new ol.layer.Tile({ source: new ol.source.OSM() });
2775 +
2776 + xxmap.mapView = new ol.View({ // Set the initial view
2777 + center: ol.proj.transform([0, 0], 'EPSG:4326', 'EPSG:3857'),
2778 + zoom: 2,
2779 + minZoom: 2,
2780 + maxZoom: 20,
2781 + extent: ol.proj.transformExtent([-100000, -69.55, 100000, 69.55], 'EPSG:4326', 'EPSG:3857')
2782 + });
2783 +
2784 + xxmap.map = new ol.Map({
2785 + target: 'xdevicesmap',
2786 + layers: [xxmap.mapLayer, xxmap.markersLayer],
2787 + view: xxmap.mapView
2788 + });
2789 +
2790 + xxmap.map.addOverlay(map_cm_popup);
2791 +
2792 + // Goto information tab if a user clicks on a feature
2793 + xxmap.map.on('click', function(evt) {
2794 + var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
2795 + if (feature) {
2796 + var nodeid = feature.getId();
2797 + if (nodeid != null) { gotoDevice(nodeid, 10); } // Goto general info tab
2798 + else { // For pointer
2799 + var nodeFeatgoto = getCorrespondingFeature(feature); gotoDevice(nodeFeatgoto.getId(), 10);
2800 + }
2801 + }
2802 + });
2803 +
2804 + // On hover feature show the name of the node. Also add pointer style
2805 + xxmap.map.on('pointermove', function(evt) {
2806 + var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
2807 + if (feature) {
2808 + xxmap.map.getTargetElement().style.cursor = 'pointer';
2809 + var coord = feature.getGeometry().getCoordinates();
2810 + // map_cm_popup.setPosition(evt.coordinate);
2811 + map_cm_popup.setPosition(coord);
2812 + var featid = feature.getId();
2813 + if (featid) {
2814 + QH('xmap-info-window', feature.get('name'));
2815 + } else {
2816 + var nodeFeat = getCorrespondingFeature(feature); // Return the node feature associated to pointer.
2817 + QH('xmap-info-window', nodeFeat.get('name'));
2818 + }
2819 + } else {
2820 + xxmap.map.getTargetElement().style.cursor = '';
2821 + QH('xmap-info-window', '');
2822 + }
2823 + });
2824 +
2825 + // Initialize context menu for openlayers
2826 + var contextmenu = new ContextMenu({
2827 + width: 160,
2828 + defaultItems: false, // defaultItems are Zoom In/Zoom Out
2829 + items: contextmenu_items
2830 + });
2831 +
2832 + // On right click open the context menu
2833 + contextmenu.on("abrir", function (evt) {
2834 + var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(ft, l){ return ft; });
2835 + xxmap.contextmenu.clear(); //Clear the context menu
2836 + if (feature) {
2837 + var featId = feature.getId();
2838 + if (featId) { addContextMenuItems(feature); } // Node feature will have an id
2839 + else { // If the feature is a pointer, Get its corresponding Node feature
2840 + var nodeFeature = getCorrespondingFeature(feature); //return the node feature associated to pointer.
2841 + if (nodeFeature) { addContextMenuItems(nodeFeature); }
2842 + else{ xxmap.contextmenu.extend(contextmenu_items); }
2843 + }
2844 + }
2845 + else { xxmap.contextmenu.extend(contextmenu_items); }
2846 + });
2847 + if (xxmap.contextmenu == null) { xxmap.contextmenu = contextmenu; }
2848 + xxmap.map.addControl(xxmap.contextmenu);
2849 + //addMeshOptions(); // Adds Mesh names to mesh dropdown
2850 + } catch (ex) {
2851 + console.log(ex);
2852 + QV('viewselectmapoption', false);
2853 + QV('devViewButton4', false);
2854 + xxmap = null;
2855 + }
2856 + }
2857 +
2858 + // Add feature on to Map for a Node
2859 + function addFeature(node, lat, lon) {
2860 + var existingfeature = getModifiedFeature(node._id); // Check if Corresponding feature was Modified ( Modifed feature are in active interactions list)
2861 + if (existingfeature) { xxmap.markersSource.addFeature(existingfeature); } // Add that existing feature
2862 + else { // Add new feature for this node
2863 + if (!lat && !lon) { var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1]; }
2864 +
2865 + // Fix the longiture and send an event to patch the db to correct coordinate format. It will cause second unnecessary updateFeature on this node to the map.
2866 + if (lon > 180) { lon = 180 - lon; meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: [ lat, lon ] }); }
2867 +
2868 + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
2869 + var feature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326','EPSG:3857')), name: node.name, status: node.conn, lat: lat, lon: lon });
2870 + feature.setId(node._id); // Set id for the device as nodeid
2871 + feature.setStyle(markerStyle(node));
2872 + xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source
2873 + }
2874 + }
2875 + }
2876 +
2877 + // Removing any feature from map
2878 + function removeFeature(node) {
2879 + var feature = xxmap.markersSource.getFeatureById(node._id);
2880 + if (feature) { xxmap.markersSource.removeFeature(feature); }
2881 + }
2882 +
2883 + // Update feature
2884 + function updateFeature(node, feature) {
2885 + if (node.conn != feature.get('status') ) { // Update status if changed
2886 + feature.set('status',node.conn)
2887 + feature.setStyle(markerStyle(node));
2888 + }
2889 +
2890 + // Since this is IP address location, add some fixed randomness to the location. Avoid pin pile-up.
2891 + var loc = map_parseNodeLoc(node);
2892 + if (loc != null) {
2893 + var lat = loc[0], lon = loc[1];
2894 + if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
2895 + feature.set('lat', lat); feature.set('lon', lon);
2896 + var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326', 'EPSG:3857');
2897 + feature.getGeometry().setCoordinates(modifiedCoordinates);
2898 + }
2899 + }
2900 +
2901 + if (node.name != feature.get('name') ) { feature.set('name', node.name); } // Update name
2902 + }
2903 +
2904 + // Enable dragging of a marker after edit option is clicked in context menu
2905 + function modifyMarkerloc(ft){
2906 + var featid = ft.getId();
2907 + if (featid) {
2908 + ft.setStyle(markerStyle(getNodeFromId(ft.a), 4)); // Switch to a user marker
2909 + if ( !getActiveInteractions(ft)) {
2910 + var dragInteration = new ol.interaction.Modify({
2911 + features: new ol.Collection([ft]),
2912 + pixelTolerance: 10
2913 + });
2914 + xxmap.activeInteractions.push({ featureid: featid, feature:ft, interaction: dragInteration }); // Also keep track of Interactions
2915 + xxmap.map.addInteraction(dragInteration);
2916 + }
2917 + }
2918 + }
2919 +
2920 + // This will be called when save location option is clicked in context menu
2921 + function saveMarkerloc(ft){
2922 + var featid = ft.getId()
2923 + if (featid) {
2924 + var actInteraction = getActiveInteractions(ft);
2925 + if (actInteraction) { // Check if the interaction exists
2926 + xxmap.map.removeInteraction(actInteraction); //Clear Interaction for that node
2927 + removeInteraction(featid);
2928 + var coord = ft.getGeometry().getCoordinates();
2929 + var v = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
2930 + if (v[0] > 180) { v[0] = 180 - v[0]; }
2931 + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
2932 + meshserver.send({ action: 'changedevice', nodeid: featid, userloc: vx }); // Send them to server to save changes
2933 + }
2934 + }
2935 + }
2936 +
2937 + // Style the Markers
2938 + function markerStyle(node, type) {
2939 + if (type == null) {
2940 + type = 0;
2941 + if (node.iploc) { type = 1; }
2942 + if (node.wifiloc) { type = 2; }
2943 + if (node.gpsloc) { type = 3; }
2944 + if (node.userloc) { type = 4; }
2945 + }
2946 + var types = ['', '-ip','-wifi','-gps','-user'];
2947 + var color = connStateColor(node);
2948 + var style = new ol.style.Style({
2949 + image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker' + types[type] + '.png' })
2950 + //stroke: new ol.style.Stroke({ color: '#000', width: 20 })
2951 + //text: new ol.style.Text({ text: 'bob!', textAlign: 'right', offsetX: -10, fill: new ol.style.Fill({ color: '#000' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) })
2952 + });
2953 +
2954 + //deviceMark.setStyle(new ol.style.Style({
2955 + // text: new ol.style.Text({
2956 + // //font: '12px helvetica,sans-serif',
2957 + // text: currentNode.name,
2958 + // textAlign: 'right',
2959 + // offsetX: -10,
2960 + // fill: new ol.style.Fill({ color: '#000' }),
2961 + // stroke: new ol.style.Stroke({ color: '#fff', width: 2 })
2962 + // }),
2963 + // image: new ol.style.Icon(({ color: [113, 140, 0], src: 'images/dot.png' })) }));
2964 +
2965 + return [ style ];
2966 + }
2967 +
2968 + // TODO: Add more connection status types. Currently we only change color if connection status changes
2969 + function connStateColor(nodeConn){
2970 + if (nodeConn.conn == 1 || nodeConn.conn == 3 || nodeConn.conn == 5) { return '#00ffdd'; } // Green for connected devices
2971 + return '#C70039'; // Red if the Agent is not connected
2972 + }
2973 +
2974 + // Add save/edit option to context menu
2975 + function addContextMenuItems(feature) {
2976 + if (getActiveInteractions(feature)) { // If this feature is modified then display save option in contextmenu
2977 + map_cm_saveMarker.data = feature;
2978 + xxmap.contextmenu.push(map_cm_saveMarker);
2979 + } else {
2980 + map_cm_editMarker.data = feature;
2981 + xxmap.contextmenu.push(map_cm_editMarker);
2982 + var node = getNodeFromId(feature.a);
2983 + if (node.userloc) {
2984 + map_cm_clearMarker.data = feature;
2985 + xxmap.contextmenu.push(map_cm_clearMarker);
2986 + }
2987 + }
2988 + map_cm_nodemenu_items.forEach(function (item){
2989 + if (item.text == "Aumentar o zoom até o limite" || item.text == "Diminuir o zoom até o limite") { item.data = feature; }
2990 + else { if (item != '-') { item.data = feature.getId(); } }
2991 + });
2992 + xxmap.contextmenu.extend(map_cm_nodemenu_items);
2993 + }
2994 +
2995 + // Return a active Interaction if it exists in activeInteractions list
2996 + function getActiveInteractions(feature) {
2997 + var featid = feature.getId();
2998 + for (var i = 0; i < xxmap.activeInteractions.length; i++) {
2999 + if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].interaction; }
3000 + }
3001 + return false;
3002 + }
3003 +
3004 + // Return Modified feature based on Id
3005 + function getModifiedFeature(featid) {
3006 + if (featid) {
3007 + for (var i = 0; i < xxmap.activeInteractions.length; i++) {
3008 + if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].feature; }
3009 + }
3010 + }
3011 + return null;
3012 + }
3013 +
3014 + // Remove Interaction
3015 + function removeInteraction(ftid) {
3016 + var index = -1;
3017 + for (var i = 0; i < xxmap.activeInteractions.length; i++) {
3018 + if (xxmap.activeInteractions[i].featureid === ftid) { index = i; break; }
3019 + }
3020 + if (index >= 0) { xxmap.activeInteractions.splice(index, 1); }
3021 + }
3022 +
3023 + // Check if pointer coordinates are equal to features and return node feature
3024 + function getCorrespondingFeature(pointerFeat) {
3025 + var pointerCoord = pointerFeat.getGeometry().getCoordinates();
3026 + for (var i = 0; i < xxmap.activeInteractions.length ; i++) {
3027 + var modifiedFeatures = xxmap.activeInteractions[i].feature;
3028 + var fearCoord = modifiedFeatures.getGeometry().getCoordinates();
3029 + if (fearCoord[0].toFixed(5) == pointerCoord[0].toFixed(5) && fearCoord[1].toFixed(5) == pointerCoord[1].toFixed(5) ) { return modifiedFeatures; }
3030 + }
3031 + return null;
3032 + }
3033 +
3034 + // Refresh the map and clear list
3035 + function refreshMap(reset, rebound){
3036 + if (reset) {
3037 + xxmap.map.setTarget(null);
3038 + xxmap.map = null;
3039 + xxmap.markersSource = null;
3040 + xxmap.mapView = null;
3041 + xxmap.mapLayer = null;
3042 + xxmap.activeInteractions = []; // Clear Active Interaction list
3043 + }
3044 + //clearMeshOptions();
3045 + //onSelectMeshChange();
3046 + var box = updateMapMarkers();
3047 + if ((box != null) && (rebound || (box[4] == 1))) {
3048 + var clat = (box[0] + box[2]) / 2;
3049 + var clon = (box[1] + box[3]) / 2;
3050 + var cscale = Math.max(Math.abs(box[0] - box[2]), Math.abs(box[1] - box[3]));
3051 + var view = xxmap.map.getView();
3052 + view.setCenter(ol.proj.transform([clon, clat], 'EPSG:4326', 'EPSG:3857'));
3053 + var i = 360, j = -2;
3054 + while (i > cscale) { j++; i = i / 2; }
3055 + view.setZoom(j);
3056 + }
3057 + }
3058 +
3059 + // Called When Place a node option is clicked from context menu
3060 + function placeNode(coords) {
3061 + if (xxdialogMode) return;
3062 + var x = '<div style=margin-bottom:6px><label for=selectnode-search>' + "Procurar" + '</label>&nbsp&nbsp<input type=text placeholder="' + "Nome do dispositivo" + '" id="selectnode-search" onchange=onPlaceNodeInputChange() onkeyup=onPlaceNodeInputChange() autocomplete=off style=width:120px></div><div id=placenode style="height:254px;overflow-y:auto;width:100%;margin:12px 1px 4px 1px;"><div id=noNodesMapPlace style=text-align:center;width:100%;display:none>' + "Nenhum dispositivo encontrado." + '</div>';
3063 + for (var i in nodes) {
3064 + x += '<div class=noselect id=' + nodes[i]._id + '-rowid onclick=selectNodeToPlace(event,\''+ nodes[i]._id +'\') style=background-color:lightgray;margin-bottom:4px;border-radius:2px><input name=PlaceMapDeviceCheckbox id=' + nodes[i]._id + '-checkid type=checkbox style=width:16px;display:inline />';
3065 + x += '<div class=j' + nodes[i].icon + ' style=width:16px;height:16px;margin-top:2px;margin-right:4px;display:inline-block></div><div style=width:16px;display:inline>' + nodes[i].name + '</div></div>';
3066 + }
3067 + setDialogMode(2, "Selecione um nó para colocar", 3, placeNodeEx, x + '</div>', coords);
3068 + onPlaceNodeInputChange();
3069 + }
3070 +
3071 + function placeNodeEx(button, coords) {
3072 + var elements = document.getElementsByName('PlaceMapDeviceCheckbox');
3073 + for (var i in elements) {
3074 + if (elements[i].checked) {
3075 + var node = getNodeFromId(elements[i].id.substring(0, elements[i].id.length - 8));
3076 + if (node) {
3077 + var feature = xxmap.markersSource.getFeatureById(i);
3078 + var v = ol.proj.transform(coords, 'EPSG:3857', 'EPSG:4326');
3079 + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
3080 + if (feature) {
3081 + feature.getGeometry().setCoordinates(coords);
3082 + var activeInteraction = getActiveInteractions(feature);
3083 + if (activeInteraction) {
3084 + saveMarkerloc(feature);
3085 + } else { // If this feature is not saved after its location is changed, then send updated coords to server.
3086 + meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // Send them to server to save changes
3087 + }
3088 + } else {
3089 + meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // This Node is not yet added to maps.
3090 + }
3091 + }
3092 + }
3093 + }
3094 + }
3095 +
3096 + // Called when the user changes the search box
3097 + function onPlaceNodeInputChange() {
3098 + updatePlaceNodeTable(Q('selectnode-search').value.trim().toLowerCase());
3099 + }
3100 +
3101 + // Update the list of devices in the "place on map" table
3102 + function updatePlaceNodeTable(inputSearch) {
3103 + var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), count = 0;
3104 + for (var i in nodes) {
3105 + var visible = ((nodes[i].namel.indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.indexOf(inputSearch) >= 0));
3106 + if (visible) { count++; }
3107 + QV(nodes[i]._id + '-rowid', visible);
3108 + }
3109 + QV('noNodesMapPlace', count == 0);
3110 + //console.log(selected);
3111 + //for (var i in nodes) {
3112 + // if ((nodes[i].name.toLowerCase().indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.toLowerCase().indexOf(inputSearch) >= 0)) {
3113 + // console.log(selected.indexOf(nodes[i]._id));
3114 + // x += '<div class=noselect id=' + nodes[i]._id + '-rowid onclick=selectNodeToPlace(event,\''+ nodes[i]._id +'\') style=background-color:lightgray;margin-bottom:4px;border-radius:2px><input name=PlaceMapDeviceCheckbox id=' + nodes[i]._id + '-checkid type=checkbox style=width:16px;display:inline ' + ((selected.indexOf(nodes[i]._id) >= 0)?'checked':'') + ' />';
3115 + // x += '<div class=j' + nodes[i].icon + ' style=width:16px;height:16px;margin-top:2px;margin-right:4px;display:inline-block></div><div style=width:16px;display:inline>' + nodes[i].name + '</div></div>';
3116 + // }
3117 + //}
3118 + //if (x == '') { x = '<div style=text-align:center;width:100%>No devices found.</div>'; }
3119 + //QH('placenode', '');
3120 + }
3121 +
3122 + // Called when a user clicks on a device to toggle selection for placement on map.
3123 + function selectNodeToPlace(e, id) {
3124 + // Toggle checkbox if needed
3125 + if (e.target.name != 'PlaceMapDeviceCheckbox') { var inputElement = Q(id + '-checkid'); inputElement.checked = !inputElement.checked; }
3126 +
3127 + // Check button state
3128 + var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), checkcount = 0;
3129 + for (var i in elements) { if (elements[i].checked) checkcount++; }
3130 + QE('idx_dlgOkButton', checkcount > 0);
3131 + }
3132 +
3133 + // Add option for available meshes in mesh Dropdown
3134 + function addMeshOptions(addMeshid, meshName) {
3135 + //var meshOptions = Q('select-mesh');
3136 + //if (addMeshid && meshName) {
3137 + // var option = document.createElement('option');
3138 + // option.value =addMeshid;
3139 + // option.text = meshName;
3140 + // meshOptions.add(option); // Add specific option
3141 + //}
3142 + //else {
3143 + // for (var i in meshes) { // Add all options
3144 + // var option = document.createElement('option');
3145 + // option.value = i;
3146 + // option.text = meshes[i].name;
3147 + // meshOptions.add(option);
3148 + // }
3149 + //}
3150 + }
3151 +
3152 + // Remove/Modify options in Mesh dropdown (if modMeshname is defined then Modify else Remove)
3153 + function meshOptionRmvMod(delMeshid, modMeshname){
3154 + //var meshOptions = Q('select-mesh');
3155 + //if (delMeshid) {
3156 + // var index=-1;
3157 + // for (var i = 1; i < meshOptions.options.length; i++) {
3158 + // if (meshOptions[i].value === delMeshid) { index=i; }
3159 + // }
3160 + // if (index > 0) {
3161 + // if (modMeshname) {
3162 + // meshOptions[index].innerHTML=modMeshname; // If Mesh name is Modified
3163 + // }
3164 + // else { meshOptions.remove(index); }
3165 + // }
3166 + //}
3167 + }
3168 +
3169 + //Check if there is any mesh created
3170 + function meshExists() {
3171 + for (var i in meshes) { if (meshes[i]) { return true; } }
3172 + return false;
3173 + }
3174 +
3175 + // Reset Mesh dropdown option to 'All' when a current view mesh is deleted.
3176 + function setMeshView(emeshid) {
3177 + var selectMeshElement=Q('select-mesh');
3178 + var selectedIndex = selectMeshElement.selectedIndex;
3179 + if (selectMeshElement[selectedIndex].value == emeshid) { selectMeshElement[0].selected = true; onSelectMeshChange(); }
3180 + }
3181 +
3182 + // Clear all mesh options except 'All'
3183 + function clearMeshOptions() {
3184 + //var meshOptions=Q('select-mesh');
3185 + //for(var i = meshOptions.options.length - 1 ; i > 0 ; i--) { meshOptions.remove(i); }
3186 + }
3187 +
3188 + // Make a http get call- Replace this with AJAX get if jquery is used
3189 + function getSearchLocation() {
3190 + try {
3191 + var searchdata = Q('mapSearchLocation').value.trim();
3192 + if (searchdata.length > 0) {
3193 + var xmlhttp = new XMLHttpRequest(); // Compatible with Chrome, Opera, Safari, IE7+, Firefox.
3194 + xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { formatSearchData(xmlhttp.responseText); } }
3195 + xmlhttp.open('GET', 'https://nominatim.openstreetmap.org/search?q=' + searchdata + '&format=json', true); // Get request
3196 + xmlhttp.send();
3197 + }
3198 + } catch (e) {}
3199 + }
3200 +
3201 + // Format data recieved from nominatim API and display it on content window
3202 + function formatSearchData(data) {
3203 + try {
3204 + QH('xmapSearchResults','');
3205 + var dataInfo = JSON.parse(data), count = 0, x = '<div class="xmapItem">';
3206 + for (var i = 0; i < dataInfo.length; i++) {
3207 + if (dataInfo[i].display_name && dataInfo[i].boundingbox[0] && dataInfo[i].boundingbox[1] && dataInfo[i].boundingbox[2] && dataInfo[i].boundingbox[3]) {
3208 + count++;
3209 + var itemclass = (i % 2 == 0)?'xmapItemSel1':'xmapItemSel1';
3210 + x += '<div class="' + itemclass + '" onclick=mapGotoSelectedLocation(this)><div>' + dataInfo[i].display_name + '</div><div style=display:none>' + dataInfo[i].boundingbox[0] + '!#!' + dataInfo[i].boundingbox[1] + '!#!' + dataInfo[i].boundingbox[2] + '!#!' + dataInfo[i].boundingbox[3] + '</div></div>';
3211 + }
3212 + }
3213 + x += '</div>';
3214 + if (count == 1) {
3215 + // If only one result is returned then zoom to that location
3216 + var extent = [ parseFloat(dataInfo[0].boundingbox[2]), parseFloat(dataInfo[0].boundingbox[0]), parseFloat(dataInfo[0].boundingbox[3]), parseFloat(dataInfo[0].boundingbox[1]) ];
3217 + zoomToExtent(extent);
3218 + } else {
3219 + if (count == 0) { x = '<div style=width:200px>' + "Nenhum local encontrado." + '<div>'; }
3220 + QV('xmapSearchResultsDlg', true);
3221 + }
3222 + QH('xmapSearchResults', x);
3223 + }
3224 + catch (e) {}
3225 + }
3226 +
3227 + // Zoom into the bounding box
3228 + function mapGotoSelectedLocation(obj) {
3229 + var objchildren = obj.children;
3230 + var boundingBox = objchildren[1].innerHTML.split('!#!');
3231 + var extent = [parseFloat(boundingBox[2]), parseFloat(boundingBox[0]), parseFloat(boundingBox[3]), parseFloat(boundingBox[1])];
3232 + //Q('search-location').value = objchildren[0].innerHTML;
3233 + zoomToExtent(extent);
3234 + mapCloseSearchWindow();
3235 + }
3236 +
3237 + // Close the search window
3238 + function mapCloseSearchWindow() {
3239 + QH('xmapSearchResults', '');
3240 + QV('xmapSearchResultsDlg', false);
3241 + }
3242 +
3243 + // Zoom to specific cordinates
3244 + function zoomToLocation(coordinates, zoomVal) {
3245 + var view = xxmap.map.getView();
3246 + view.setCenter(coordinates);
3247 + view.setZoom(zoomVal);
3248 + }
3249 +
3250 + function zoomToFitExtent() {
3251 + var features = xxmap.markersSource.getFeatures();
3252 + if (features.length > 0) {
3253 + var extent = xxmap.markersSource.getExtent();
3254 + xxmap.map.getView().fit(extent, xxmap.map.getSize());
3255 + }
3256 + }
3257 +
3258 + function zoomToExtent(extent){
3259 + var boundingExtent = ol.proj.transformExtent(extent, ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
3260 + xxmap.map.getView().fit(boundingExtent, xxmap.map.getSize());
3261 + }
3262 +
3263 + {{{EndGeoLocationJS}}}
3264 +
3265 + //
3266 + // MY DEVICE
3267 + //
3268 + function refreshDevice(nodeid) {
3269 + if (!currentNode || currentNode._id != nodeid) return;
3270 + gotoDevice(nodeid, xxcurrentView, true);
3271 + }
3272 +
3273 + function getNodeRights(nodeid) {
3274 + var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
3275 + return mesh.links[userinfo._id].rights;
3276 + }
3277 +
3278 + var currentNode;
3279 + var powerTimelineNode = null;
3280 + var powerTimelineReq = null;
3281 + var powerTimelineUpdate = null;
3282 + var powerTimeline = null;
3283 + function getCurrentNode() { return currentNode; };
3284 + function gotoDevice(nodeid, panel, refresh, event) {
3285 + // Remind the user to verify the email address
3286 + if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para a guia \"Minha conta\" para alterar e verificar um endereço de email."); return; }
3287 +
3288 + // Remind the user to add two factor authentication
3289 + if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para a guia \"Minha conta\" e consulte a seção \"Segurança da conta\"."); return; }
3290 +
3291 + if (event && (event.shiftKey == true)) {
3292 + // Open the device in a different tab
3293 + window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid);
3294 + return;
3295 + }
3296 +
3297 + //disconnectAllKvmFunction();
3298 + var node = getNodeFromId(nodeid);
3299 + var mesh = meshes[node.meshid];
3300 + var meshrights = mesh.links[userinfo._id].rights;
3301 + if (!currentNode || currentNode._id != node._id || refresh == true) {
3302 + currentNode = node;
3303 +
3304 + // Add node name
3305 + var nname = EscapeHtml(node.name);
3306 + if (nname.length == 0) { nname = '<i>' + "Nenhum" + '</i>'; }
3307 + if (((meshrights & 4) != 0) && ((!mesh.flags) || ((mesh.flags & 2) == 0))) { nname = '<span tabindex=0 title=\"' + "clique aqui para criar um grupo de dispositivos" + '\" onclick=showEditNodeValueDialog(0) onkeyup="if (event.key == \'Enter\') showEditNodeValueDialog(0)" style=cursor:pointer>' + nname + ' <img class=hoverButton src="images/link5.png" /></span>'; }
3308 + nname += '<span style=color:#AAA;font-size:small> - ' + EscapeHtml(mesh.name) + '</span>';
3309 + QH('p10deviceName', nname);
3310 + QH('p11deviceName', nname);
3311 + QH('p12deviceName', nname);
3312 + QH('p13deviceName', nname);
3313 + QH('p14deviceName', nname);
3314 + QH('p15deviceName', "Console - " + nname);
3315 + QH('p16deviceName', nname);
3316 + QH('p17deviceName', nname);
3317 + QH('p19deviceName', nname);
3318 +
3319 + // Node attributes
3320 + var x = '<table style=width:100%>';
3321 +
3322 + // Attribute: Mesh
3323 + x += addDeviceAttribute('<span title=\"' + "O nome do grupo de dispositivos ao qual este computador pertence." + '\">' + "Grupo" + '</span>', '<a href=# title=\"' + "O nome do grupo de dispositivos ao qual este computador pertence" + '\" onclick=gotoMesh("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
3324 +
3325 + // Attribute: Name
3326 + if ((node.rname != null) && (node.name != node.rname)) { x += addDeviceAttribute('<span title="The name of this computer as set in the operating system">Name</span>', '<span title="The name of this computer as set in the operating system">' + EscapeHtml(node.rname) + '</span>'); }
3327 +
3328 + // Attribute: Host
3329 + if ((features & 1) == 0) { // If not WAN-only, local hostname is in use
3330 + if ((meshrights & 4) != 0) {
3331 + if (node.host) {
3332 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
3333 + } else {
3334 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>' + "Nenhum" + '</i></span>');
3335 + }
3336 + } else {
3337 + x += addDeviceAttribute("Hostname", EscapeHtml(node.host));
3338 + }
3339 + }
3340 +
3341 + // Attribute: Description
3342 + var description = node.desc?EscapeHtml(node.desc):('<i>' + "Nenhum" + '</i>');
3343 + if ((meshrights & 4) != 0) {
3344 + x += addDeviceAttribute("Descrição", '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + ' <img class=hoverButton src="images/link5.png" /></span>');
3345 + } else {
3346 + x += addDeviceAttribute("Descrição", description);
3347 + }
3348 +
3349 + // Attribute: Mesh Agent
3350 + var agentsStr = ["Desconhecido", "Windows 32 Bits console", "Windows 64 Bits console", "Serviço Windows 32 Bits", "Serviço Windows 64 Bits", "Linux 32 bits", "Linux 64 bits", "MIPS", "XENx86", "Android ARM", "Linux ARM", "MacOS 32 bits", "Android x86", "PogoPlug ARM", "Android APK", "Linux Poky x86-32 bits", "MacOS 64 bits", "ChromeOS", "Linux Poky x86-64 bits", "Linux NoKVM x86-32 bits", "Linux NoKVM x86-64 bits", "Windows MinCore console", "Windows MinCore service", "NodeJS", "ARM-Linaro", "ARMv6l / ARMv7l", "ARMv8 64bit", "ARMv6l / ARMv7l / NoKVM", "Desconhecido", "Desconhecido", "FreeBSD x86-64"];
3351 + if ((node.agent != null) && (node.agent.id != null) && (node.agent.ver != null)) {
3352 + var str = '';
3353 + if (node.agent.id <= agentsStr.length) { str = agentsStr[node.agent.id]; } else { str = agentsStr[0]; }
3354 + if (node.agent.ver != 0) { str += ' v' + node.agent.ver; }
3355 + x += addDeviceAttribute("Mesh Agent", str);
3356 + }
3357 +
3358 + // Attribute: Intel AMT
3359 + if (node.intelamt != null) {
3360 + var str = '';
3361 + var provisioningStates = { 0: nobreak("Não ativado (pré)"), 1: nobreak("Não ativado (entrada)"), 2: nobreak("ativado") };
3362 + if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + "Estado desconhecido" + '</i>, v' + node.intelamt.ver; } else
3363 +
3364 + if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "ativado" + '</i>'; }
3365 + else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Estado da versão desconhecida" + '</i>'; }
3366 + else {
3367 + str += provisioningStates[node.intelamt.state];
3368 + if ((node.intelamt.state == 2) && node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' <span title=\"' + "O Intel AMT é ativado no modo de controle do cliente" + '\">' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str += ' <span title=\"' + "O Intel AMT é ativado no modo de controle de administrador" + '\">' + "ACM" + '</span>'; } }
3369 + str += (', v' + node.intelamt.ver);
3370 + }
3371 +
3372 + if (node.intelamt.tls == 1) { str += ', <span title=\"' + "O Intel AMT está configurado com segurança de rede TLS" + '\">' + "TLS" + '</span>'; }
3373 + if (node.intelamt.state == 2) {
3374 + if (node.intelamt.user == null || node.intelamt.user == '') {
3375 + if ((meshrights & 4) != 0) {
3376 + str += ', <i style=color:#FF0000;cursor:pointer title=\"' + "Editar Intel & reg; Credenciais AMT" + '\" onclick=editDeviceAmtSettings("' + node._id + '")>' + "Sem credenciais" + '</i>';
3377 + } else {
3378 + str += ', <i style=color:#FF0000>' + "Sem credenciais" + '</i>';
3379 + }
3380 + }
3381 + str += ' ';
3382 + if ((meshrights & 4) != 0) {
3383 + str += '<img src=images/link4.png height=10 width=10 title=\"' + "Editar Intel & reg; Credenciais AMT" + '\" style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
3384 + }
3385 + }
3386 +
3387 + var meName = '<span title=\"Intel&reg; Manageability Engine\">' + "Intel&reg; ME" + '<span>';
3388 + if (typeof node.intelamt.sku == 'number') {
3389 + if ((node.intelamt.sku & 8) != 0) { meName = '<span title=\"' + "Intel&reg; Tecnologia de gerenciamento ativo" + '\">' + "Intel&reg; AMT" + '<span>'; }
3390 + else if ((node.intelamt.sku & 16) != 0) { meName = '<span title=\"' + "Intel&reg; Gerenciamento padrão" + '\">' + "Intel&reg; SM" + '<span>'; }
3391 + }
3392 + x += addDeviceAttribute(meName, str);
3393 + }
3394 +
3395 + if (mesh.mtype == 2) {
3396 + // Attribute: Mesh Agent Tag
3397 + if ((node.agent != null) && (node.agent.tag != null)) {
3398 + var tag = EscapeHtml(node.agent.tag);
3399 + if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
3400 + x += addDeviceAttribute("Etiqueta do agente", tag);
3401 + }
3402 + } else {
3403 + // Attribute: Intel AMT Tag
3404 + if ((node.intelamt != null) && (node.intelamt.tag != null)) {
3405 + var tag = EscapeHtml(node.intelamt.tag);
3406 + if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
3407 + x += addDeviceAttribute("Intel&reg; Tag AMT ", tag);
3408 + }
3409 + }
3410 +
3411 + // Attribute: Intel AMT
3412 + //if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel&reg; AMT', node.intelamt.user); }
3413 +
3414 + // Operating system description
3415 + if (node.osdesc) { x += addDeviceAttribute("Sistema operacional", node.osdesc); }
3416 +
3417 + // Antivirus
3418 + if (node.av && node.av.length > 0) {
3419 + var y = [];
3420 + for (var i in node.av) {
3421 + if (node.av[i].product) {
3422 + var avx = EscapeHtml(node.av[i].product);
3423 + if (node.av[i].enabled !== true) { avx += ' - <span style=color:red>' + "Desativado" + '</span>'; }
3424 + if (node.av[i].updated !== true) { avx += ' - <span style=color:red>' + "Desatualizado" + '</span>'; }
3425 + if ((node.av[i].enabled == true) && (node.av[i].updated == true)) { avx += ' - <span style=color:green>' + "Ok" + '</span>'; }
3426 + y.push(avx);
3427 + }
3428 + }
3429 + x += addDeviceAttribute("Antivírus", y.join('<br />'));
3430 + }
3431 +
3432 + // Active Users
3433 + if (node.users && node.conn && (node.users.length > 0) && (node.conn & 1)) { x += addDeviceAttribute(format("Usuário ativo {0}", ((node.users.length > 1)?'s':'')), node.users.join(', ')); }
3434 +
3435 + // Attribute: Connectivity (Only show this if more than just the agent is connected).
3436 + var connectivity = node.conn;
3437 + if (connectivity && connectivity > 1) {
3438 + var cstate = [];
3439 + if ((node.conn & 1) != 0) cstate.push('<span title=\"' + "O agente de malha está conectado e pronto para uso." + '\">' + "Mesh Agent" + '</span>');
3440 + if ((node.conn & 2) != 0) cstate.push('<span title=\"' + "Intel&reg; O AMT CIRA está conectado e pronto para uso." + '\">' + "Intel&reg; AMT CIRA" + '</span>');
3441 + else if ((node.conn & 4) != 0) cstate.push('<span title=\"' + "Intel&reg; O AMT é roteável e pronto para uso." + '\">' + "Intel&reg; AMT" + '</span>');
3442 + if ((node.conn & 8) != 0) cstate.push('<span title=\"' + "O agente de malha é alcançável usando outro agente como retransmissão." + '\">' + "Mesh Relay" + '</span>');
3443 + if ((node.conn & 16) != 0) { cstate.push('<span title=\"' + "A conexão MQTT com o dispositivo está ativa." + '\">' + "MQTT" + '</span>'); }
3444 + x += addDeviceAttribute("Conectividade", cstate.join(', '));
3445 + }
3446 +
3447 + // Node grouping tags
3448 + var groupingTags = '<i>' + "Nenhum" + '</i>';
3449 + if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span class="tagSpan">' + node.tags[i] + '</span>'; } }
3450 + if ((meshrights & 4) != 0) {
3451 + x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + ' <img class=hoverButton src="images/link5.png" /></span>');
3452 + } else {
3453 + x += addDeviceAttribute('Tags', groupingTags);
3454 + }
3455 +
3456 + x += '</table><br />';
3457 + // Show action button, only show if we have permissions 4, 8, 64
3458 + if ((meshrights & 76) != 0) { x += '<input type=button value=\"' + "Ações" + '\" title=\"' + "Execute ações de energia no dispositivo" + '\" onclick=deviceActionFunction() />'; }
3459 + x += '<input type=button value=\"' + "Notas" + '\" title=\"' + "Ver notas sobre este dispositivo" + '\" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
3460 + x += '<input type=button value=\"' + "Log de Evento" + '\" title=\"' + "Escreva um evento para este dispositivo" + '\" onclick=writeDeviceEvent("' + encodeURIComponent(node._id) + '") />';
3461 + //if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="Display a text message of the remote device" onclick=deviceToastFunction() />'; }
3462 + QH('p10html', x);
3463 +
3464 + // Show node last 7 days timeline
3465 + masterUpdate(256);
3466 +
3467 + // Show bottom buttons
3468 + x = '<div class="p10html3right">';
3469 + if ((meshrights & 4) != 0) {
3470 + // TODO: Show change group only if there is another mesh of the same type.
3471 + x += '&nbsp;<a href=# onclick=p10showChangeGroupDialog(["' + node._id + '"]) title=\"' + "Mova este dispositivo para um grupo de dispositivos diferente" + '\">' + "Alterar grupo" + '</a>';
3472 + x += '&nbsp;<a href=# onclick=p10showDeleteNodeDialog("' + node._id + '") title=\"' + "Remova este dispositivo" + '\">' + "Excluir dispositivo" + '</a>';
3473 + }
3474 + x += '</div><div class="p10html3left">';
3475 + if (mesh.mtype == 2) x += '<a href=# onclick=p10showNodeNetInfoDialog("' + node._id + '") title=\"' + "Mostrar informações da interface de rede do dispositivo" + '\">' + "Interfaces" + '</a>&nbsp;';
3476 + if (xxmap != null) x += '<a href=# onclick=p10showNodeLocationDialog("' + node._id + '") title=\"' + "Mostrar informações de localizações do dispositivo" + '\">' + "Localização" + '</a>&nbsp;';
3477 + if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a href=# onclick=p10showMeshCmdDialog(1,"' + node._id + '") title=\"' + "Roteador de tráfego usado para conectar-se a um dispositivo através deste servidor" + '.\">' + "Roteador" + '</a>&nbsp;';
3478 +
3479 + // RDP link, show this link only of the remote machine is Windows.
3480 + if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
3481 + if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a href=# onclick=p10clickOnce("' + node._id + '","RDP2",3389) title=\"' + "Requer o suporte Microsoft ClickOnce no seu navegador" + '.\">' + "RDP" + '</a>&nbsp;'; }
3482 + if (node.agent.id > 4) {
3483 + x += '<a href=# onclick=p10clickOnce("' + node._id + '","PSSH",22) title=\"' + "Requer o suporte Microsoft ClickOnce no seu navegador." + '\">' + "Putty" + '</a>&nbsp;';
3484 + x += '<a href=# onclick=p10clickOnce("' + node._id + '","WSCP",22) title=\"' + "Requer o suporte Microsoft ClickOnce no seu navegador." + '\">' + "WinSCP" + '</a>&nbsp;';
3485 + }
3486 + }
3487 +
3488 + // MQTT options
3489 + if ((meshrights == 0xFFFFFFFF) && (features & 0x00400000)) { x += '<a href=# onclick=p10showMqttLoginDialog("' + node._id + '") title=\"' + "Obtenha credenciais de login do MQTT para este dispositivo." + '\">' + "Login do MQTT" + '</a>&nbsp;'; }
3490 + x += '</div><br>'
3491 +
3492 + QH('p10html3', x);
3493 +
3494 + // Set the node power state
3495 + var powerstate = PowerStateStr(node.state);
3496 + //if (node.state == 0) { powerstate = 'Unknown State'; }
3497 + if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Agente conectado" + '\">' + "Agente conectado" + '</span>'; }
3498 + if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel&reg; AMT conectado" + '\">' + "Intel&reg; AMT conectado" + '</span>'; }
3499 + else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel&reg; AMT detectado" + '\">' + "Intel&reg; AMT detectado" + '</span>'; }
3500 + if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "MQTT conectado" + '\">' + "Canal MQTT conectado" + '</span>'; }
3501 + if ((powerstate == '') && node.lastconnect) { powerstate = '<span style=font-size:12px>' + "Visto pela última vez:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>'; }
3502 + QH('MainComputerState', powerstate);
3503 +
3504 + // Set the node icon
3505 + Q('MainComputerImage').setAttribute('src', 'images/icons256-' + node.icon + '-1.png');
3506 + Q('MainComputerImage').className = ((!node.conn) || (node.conn == 0)?'gray':'');
3507 +
3508 + // Check if we have terminal and file access
3509 + var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
3510 + var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
3511 + var amtAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 2048) == 0));
3512 +
3513 + // Setup/Refresh the desktop tab
3514 + if (terminalAccess) { setupTerminal(); }
3515 + if (fileAccess) { setupFiles(); }
3516 + var consoleRights = ((meshrights & 16) != 0);
3517 + if (consoleRights) { setupConsole(); } else { if (panel == 15) { panel = 10; } }
3518 +
3519 + // Show or hide the tabs
3520 + // mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent
3521 + // node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console
3522 + QV('MainDevDesktop', (((mesh.mtype == 1) && ((typeof node.intelamt.sku !== 'number') || ((node.intelamt.sku & 8) != 0)))
3523 + || ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2)))))
3524 + && ((meshrights & 8) || (meshrights & 256))
3525 + );
3526 + QV('MainDevTerminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
3527 + QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
3528 + QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8) && amtAccess);
3529 + QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
3530 + QV('MainDevPlugins', false);
3531 + QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0));
3532 + QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
3533 +
3534 + // Setup/Refresh Intel AMT tab
3535 + var amtFrameNode = Q('p14iframe').contentWindow.getCurrentMeshNode();
3536 + if ((amtFrameNode != null) && (amtFrameNode._id != currentNode._id)) { Q('p14iframe').contentWindow.disconnect(); }
3537 + var online = ((node.conn & 6) != 0)?true:false; // If CIRA (2) or AMT (4) connected, enable Commander
3538 + Q('p14iframe').contentWindow.setConnectionState(online);
3539 + Q('p14iframe').contentWindow.setFrameHeight('650px');
3540 + Q('p14iframe').contentWindow.setAuthCallback(updateAmtCredentials);
3541 +
3542 + // Display "action" button on desktop/terminal/files
3543 + QV('deskActionsBtn', (meshrights & 72) != 0); // 72 = Wake-up + Remote Control permissions
3544 + QV('termActionsBtn', (meshrights & 72) != 0);
3545 + QV('filesActionsBtn', (meshrights & 72) != 0);
3546 +
3547 + // Request the power timeline
3548 + if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) {
3549 + QH('p10html2', '');
3550 + powerTimelineReq = currentNode._id;
3551 + meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
3552 + meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
3553 + meshserver.send({ action: 'getsysinfo', nodeid: currentNode._id });
3554 + QH('p17info', '');
3555 + }
3556 +
3557 + // Reset the desktop tools
3558 + QV('DeskTools', false);
3559 + showDeskToolsProcesses();
3560 +
3561 + // Ask for device events
3562 + refreshDeviceEvents();
3563 +
3564 + // Update the web page title
3565 + if ((currentNode) && (xxcurrentView >= 10) && (xxcurrentView < 20)) {
3566 + document.title = decodeURIComponent('{{{extitle}}}') + ' - ' + currentNode.name + ' - ' + mesh.name;
3567 + } else {
3568 + document.title = decodeURIComponent('{{{extitle}}}');
3569 + }
3570 +
3571 + // Clear user consent status if present
3572 + p11clearConsoleMsg();
3573 + p12clearConsoleMsg();
3574 + p13clearConsoleMsg();
3575 +
3576 + // Device refresh plugin handler
3577 + if (pluginHandler != null) { pluginHandler.callHook('onDeviceRefreshEnd', nodeid, panel, refresh, event); }
3578 + }
3579 + setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
3580 + if (!panel) panel = 10;
3581 + go(panel);
3582 + }
3583 +
3584 + function writeDeviceEvent(nodeid) {
3585 + if (xxdialogMode) return;
3586 + setDialogMode(2, "Adicionar evento do dispositivo", 3, writeDeviceEventEx, '<textarea id=d2devEvent style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>' + "Isso adicionará uma entrada ao log de eventos deste dispositivo." + '<span>', nodeid);
3587 + }
3588 +
3589 + function writeDeviceEventEx(buttons, tag) { meshserver.send({ action: 'setDeviceEvent', nodeid: decodeURIComponent(tag), msg: encodeURIComponent(Q('d2devEvent').value) }); }
3590 +
3591 + function showNotes(readonly, noteid) {
3592 + if (xxdialogMode) return;
3593 + setDialogMode(2, "Notas", 2, showNotesEx, '<textarea id=d2devNotes ro=' + readonly + ' noteid=' + noteid + ' readonly style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>' + "As notas do grupo de dispositivos podem ser visualizadas e alteradas por outros administradores do grupo de dispositivos." + '<span>', noteid);
3594 + meshserver.send({ action: 'getNotes', id: decodeURIComponent(noteid) });
3595 + }
3596 +
3597 + function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
3598 +
3599 + function deviceChat(e) {
3600 + if (xxdialogMode) return;
3601 + var url = '/messenger?id=meshmessenger/' + encodeURIComponent(currentNode._id) + '/' + encodeURIComponent(userinfo._id) + '&title=' + currentNode.name;
3602 + if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; }
3603 + if (e && (e.shiftKey == true)) {
3604 + window.open(url, 'meshmessenger:' + currentNode._id);
3605 + } else {
3606 + window.open(url, 'meshmessenger:' + currentNode._id, 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=400,height=560');
3607 + }
3608 + meshserver.send({ action: 'meshmessenger', nodeid: decodeURIComponent(currentNode._id) });
3609 + }
3610 +
3611 + function deviceToggleBackground() {
3612 + if (xxdialogMode) return;
3613 + meshserver.send({ action: 'msg', type: 'deskBackground', nodeid: currentNode._id, op: 1 }); // Toggle desktop background image
3614 + }
3615 +
3616 + function deviceUrlFunction() {
3617 + if (xxdialogMode) return;
3618 + setDialogMode(2, "Abrir página no dispositivo", 3, deviceUrlFunctionEx, '<input id=d2devurl placeholder="http://server.com" style=width:100%;overflow-y:scroll></input>');
3619 + Q('d2devurl').focus();
3620 + }
3621 +
3622 + function deviceUrlFunctionEx() {
3623 + meshserver.send({ action: 'msg', type: 'openUrl', nodeid: currentNode._id, url: Q('d2devurl').value });
3624 + }
3625 +
3626 + function deviceToastFunction() {
3627 + if (xxdialogMode) return;
3628 + setDialogMode(2, "Notificação de dispositivo", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
3629 + Q('d2devToast').focus();
3630 + }
3631 +
3632 + function deviceToastFunctionEx() {
3633 + meshserver.send({ action: 'toast', nodeids: [ currentNode._id ], title: 'MeshCentral', msg: Q('d2devToast').value });
3634 + }
3635 +
3636 + function deviceActionFunction() {
3637 + if (xxdialogMode) return;
3638 + var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
3639 + var x = "Selecione uma operação para executar neste dispositivo." + '<br /><br />';
3640 + var y = '<select id=d2deviceop style=float:right;width:250px>';
3641 + if ((meshrights & 64) != 0) { y += '<option value=100>' + "Ligar" + '</option>'; } // Wake-up permission
3642 + if ((meshrights & 8) != 0) { y += '<option value=4>' + "Hibernar" + '</option><option value=3>' + "Redefinir" + '</option><option value=2>' + "Desligar" + '</option>'; } // Remote control permission
3643 + if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Enviar Mensagem MQTT" + '</option>'; }
3644 + if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
3645 + y += '</select>';
3646 + x += addHtmlValue("Operação", y);
3647 + setDialogMode(2, "Ação do dispositivo", 3, deviceActionFunctionEx, x);
3648 + }
3649 +
3650 + function deviceActionFunctionEx() {
3651 + var op = Q('d2deviceop').value;
3652 + if (op == 100) {
3653 + // Device wake
3654 + meshserver.send({ action: 'wakedevices', nodeids: [currentNode._id] });
3655 + } else if (op == 103) {
3656 + // Send MQTT Message
3657 + p10showSendMqttMsgDialog([currentNode._id]);
3658 + } else if (op == 104) {
3659 + // Uninstall agent
3660 + p10showSendUninstallAgentDialog([currentNode._id]);
3661 + } else {
3662 + // Power operation
3663 + meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: parseInt(op) });
3664 + }
3665 + }
3666 +
3667 + // Called when MeshCommander needs new credentials or updated credentials.
3668 + function updateAmtCredentials(forceDialog) {
3669 + var node = getNodeFromId(currentNode._id);
3670 + if ((forceDialog == true) || (node.intelamt.user == null) || (node.intelamt.user == '')) {
3671 + editDeviceAmtSettings(currentNode._id, updateAmtCredentialsEx);
3672 + } else {
3673 + Q('p14iframe').contentWindow.connectButtonfunctionEx();
3674 + }
3675 + }
3676 +
3677 + function updateAmtCredentialsEx(button, tag) {
3678 + Q('p14iframe').contentWindow.connectButtonfunctionEx();
3679 + }
3680 +
3681 + // Look to see if we need to update the device timeline
3682 + function updateDeviceTimeline() {
3683 + if ((meshserver.State != 2) || (powerTimelineNode == null) || (powerTimelineUpdate == null) || (currentNode == null)) return;
3684 + if ((powerTimelineNode == powerTimelineReq) && (currentNode._id == powerTimelineNode) && (powerTimelineUpdate < Date.now())) {
3685 + powerTimelineUpdate = null;
3686 + meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
3687 + meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
3688 + }
3689 + }
3690 +
3691 + // Draw device power bars. The bars are 766px wide.
3692 + function drawDeviceTimeline() {
3693 + if ((currentNode == null) || (xxcurrentView < 10) || (xxcurrentView > 19)) return;
3694 + var timeline = null, now = Date.now();
3695 + if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
3696 +
3697 + // Calculate when the timeline starts
3698 + var d = new Date();
3699 + d.setHours(0, 0, 0, 0);
3700 + d = new Date(d.getTime() - (1000 * 60 * 60 * 24 * 6));
3701 + var timelineStart = d.getTime();
3702 +
3703 + // De-compact the timeline
3704 + var timeline2 = [];
3705 + if (timeline != null && timeline.length > 1) {
3706 + timeline2.push([ 0, timeline[1], timeline[0] ]); // Start, End, Power
3707 + var ct = timeline[1];
3708 + for (var i = 2; i < timeline.length; i += 2) {
3709 + var power = timeline[i], dt = now;
3710 + if (timeline.length > (i + 1)) { dt = timeline[i + 1]; }
3711 + timeline2.push([ ct, ct + dt, power ]); // Start, End, Power
3712 + ct = ct + dt;
3713 + }
3714 + }
3715 +
3716 + // Draw the timeline
3717 + var x = '', count = 1, date = new Date();
3718 + var totalWidth = Q('masthead').offsetWidth - (160 + 9 + 9 + 14); // Compute the total width of the power bar
3719 + date.setHours(0, 0, 0, 0);
3720 + for (var i = 0; i < 7; i++) {
3721 + var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
3722 + for (var j in timeline2) {
3723 + var block = timeline2[j];
3724 + if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
3725 + var ts = Math.max(start, block[0]);
3726 + var te = Math.min(Math.min(end, block[1]), now);
3727 + var width = Math.round(((te - ts) * totalWidth) / 86400000);
3728 + if (width > 0) {
3729 + var title = format('{0} from {1} to {2}.', powerStateStrings2[block[2]], printTime(new Date(ts)), printTime(new Date(te)));
3730 + datavalue += '<div class="pwState ' + powerColor(block[2]) + '" title="' + title + '" style="width:' + width + 'px;"></div>';
3731 + }
3732 + }
3733 + }
3734 + x += '<tr class=' + (((count % 2) == 0)?'altBack':'') + '><td><div>&nbsp;' + printDate(date) + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
3735 + ++count;
3736 + date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
3737 + }
3738 + QH('p10html2', '<table cellpadding=2 cellspacing=0><thead><tr style=><th scope=col style=text-align:center;width:150px>' + "Dia" + '</th><th scope=col style=text-align:center><a download href="devicepowerevents.ashx?id=' + currentNode._id + '" onclick="setDialogMode(0)"><img title=\"' + "Download de eventos de energia" + '\" src="images/link4.png" /></a>' + "Estado de energia de 7 dias" + '</th></tr></thead><tbody>' + x + '</tbody></table>');
3739 + }
3740 +
3741 + // Return a color for the given power state
3742 + function powerColor(x) { if (x < powerColorTable.length) { return powerColorTable[x]; } return 'pwsYellow'; }
3743 +
3744 + // Return true if the time block is visible within the start/end period
3745 + function isTimeBlockInside(start, end, blockStart, blockEnd) {
3746 + if ((blockStart < start) && (blockEnd > end)) return true; // Block is wider than timespan
3747 + if ((blockStart > start) && (blockStart < end)) return true;
3748 + if ((blockEnd > start) && (blockEnd < end)) return true;
3749 + return false;
3750 + }
3751 +
3752 + function addDeviceAttribute(name, value) { return '<tr><td class=style7>' + name + '</td><td class=style9>' + value + '</td></tr>'; }
3753 +
3754 + function editDeviceAmtSettings(nodeid, func, arg) {
3755 + if (xxdialogMode) return;
3756 + var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
3757 + if ((meshrights & 4) == 0) return;
3758 + x += addHtmlValue("Nome de usuário", '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
3759 + x += addHtmlValue("Senha", '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
3760 + x += addHtmlValue("Segurança", '<select id=dp10tls style=width:236px><option value=0>' + "Sem segurança TLS" + '</option><option value=1>' + "Segurança TLS necessária" + '</option></select>');
3761 + if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
3762 + setDialogMode(2, "Editar Intel & reg; Credenciais AMT", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg });
3763 + if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
3764 + Q('dp10tls').value = node.intelamt.tls;
3765 + validateDeviceAmtSettings();
3766 + }
3767 +
3768 + function validateDeviceAmtSettings() {
3769 + QE('idx_dlgOkButton', passwordcheck(Q('dp10password').value));
3770 + }
3771 +
3772 + function editDeviceAmtSettingsEx(button, tag) {
3773 + if (button == 2) {
3774 + // Delete button pressed, remove credentials
3775 + meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: '', pass: '' } });
3776 + } else {
3777 + // Change Intel AMT credentials
3778 + var amtuser = Q('dp10username').value;
3779 + if (amtuser == '') amtuser = 'admin';
3780 + var amtpass = Q('dp10password').value;
3781 + if (amtpass == '') amtuser = '';
3782 + meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
3783 + tag.node.intelamt.user = amtuser;
3784 + tag.node.intelamt.tls = Q('dp10tls').value;
3785 + if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); }
3786 + }
3787 + }
3788 +
3789 + function p10showSendMqttMsgDialog(nodeids) {
3790 + if (xxdialogMode) return false;
3791 + var x = addHtmlValue("Tema", '<input id=dp2topic style=width:230px maxlength=64 onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1) />');
3792 + x += addHtmlValue("Mensagem", '<div style=width:230px;margin:0;padding:0><textarea id=dp2msg maxlength=4096 style=width:100%;height:150px;resize:none onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1)></textarea></div>');
3793 + setDialogMode(2, "Enviar mensagem MQTT", 3, p10showSendMqttMsgDialogEx, x, nodeids);
3794 + p10validateSendMqttMsgDialog();
3795 + Q('dp2topic').focus();
3796 + return false;
3797 + }
3798 +
3799 + function p10validateSendMqttMsgDialog() {
3800 + QE('idx_dlgOkButton', (Q('dp2topic').value.length > 0) && (Q('dp2msg').value.length > 0));
3801 + }
3802 +
3803 + function p10showSendMqttMsgDialogEx(b, nodeids) {
3804 + meshserver.send({ action: 'sendmqttmsg', nodeids: nodeids, topic: Q('dp2topic').value, msg: Q('dp2msg').value });
3805 + }
3806 +
3807 + function p10showSendUninstallAgentDialog(nodeids) {
3808 + if (xxdialogMode) return false;
3809 + var x = '';
3810 + if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
3811 + x += '<br /><br />';
3812 + if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
3813 + x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirme" + '</label>';
3814 + setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
3815 + p10validateSendUninstallAgentDialog();
3816 + return false;
3817 + }
3818 +
3819 + function p10validateSendUninstallAgentDialog() { QE('idx_dlgOkButton', Q('p10check').checked); }
3820 + function p10showSendUninstallAgentDialogEx(b, nodeids) { meshserver.send({ action: 'uninstallagent', nodeids: nodeids }); }
3821 +
3822 + function p10showChangeGroupDialog(nodeids) {
3823 + if (xxdialogMode) return false;
3824 + var targetMeshId = null;
3825 + if (nodeids.length == 1) { try { targetMeshId = meshes[getNodeFromId(nodeids[0])]._id; } catch (ex) { } }
3826 +
3827 + // List all available alternative groups
3828 + var y = '<select id=p10newGroup style=width:236px>', count = 0;
3829 + for (var i in meshes) {
3830 + var meshrights = meshes[i].links[userinfo._id].rights;
3831 + if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += '<option value=\'' + meshes[i]._id + '\'>' + meshes[i].name + '</option>'; }
3832 + }
3833 + y += '</select>';
3834 +
3835 + if (count > 0) {
3836 + var x = (nodeids.length == 1) ? ("Selecione um novo grupo para este dispositivo" + '<br /><br />') : ("Selecione um novo grupo para dispositivos selecionados" + '<br /><br />');
3837 + x += addHtmlValue("Novo grupo de dispositivos", y);
3838 + setDialogMode(2, "Alterar grupo", 3, p10showChangeGroupDialogEx, x, nodeids);
3839 + } else {
3840 + setDialogMode(2, "Alterar grupo", 1, null, "Não existe outro grupo de dispositivos do mesmo tipo.");
3841 + }
3842 + return false;
3843 + }
3844 +
3845 + function p10showChangeGroupDialogEx(b, nodeids) {
3846 + meshserver.send({ action: 'changeDeviceMesh', nodeids: nodeids, meshid: Q('p10newGroup').value });
3847 + }
3848 +
3849 + function p10showDeleteNodeDialog(nodeid) {
3850 + if (xxdialogMode) return false;
3851 + var x = format("Tem certeza de que deseja excluir o nó {0}?", EscapeHtml(currentNode.name)) + '<br /><br /><label><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirme" + '</label>';
3852 + setDialogMode(2, "Excluir nó", 3, p10showDeleteNodeDialogEx, x, nodeid);
3853 + p10validateDeleteNodeDialog();
3854 + return false;
3855 + }
3856 +
3857 + function p10validateDeleteNodeDialog() {
3858 + QE('idx_dlgOkButton', Q('p10check').checked);
3859 + }
3860 +
3861 + function p10showDeleteNodeDialogEx(buttons, nodeid) {
3862 + meshserver.send({ action: 'removedevices', nodeids: [ nodeid ] });
3863 + }
3864 +
3865 + function p10clickOnce(nodeid, protocol, port) {
3866 + meshserver.send({ action: 'getcookie', nodeid: nodeid, tcpport: port, tag: 'clickonce', protocol: protocol });
3867 + return false;
3868 + }
3869 +
3870 + // Show current location
3871 + var d2map = null;
3872 + function p10showNodeLocationDialog() {
3873 + if ((xxdialogMode != null) && (xxdialogTag == '@xxmap')) { setDialogMode(0); } else { if (xxdialogMode) return false; }
3874 + var markers = [], types = ['iploc', 'wifiloc', 'gpsloc', 'userloc'], boundingBox = null;
3875 +
3876 + for (var loctype in types) {
3877 + if (currentNode[types[loctype]] != null) {
3878 + var loc = currentNode[types[loctype]].split(','), lat = parseFloat(loc[0]), lon = parseFloat(loc[1]);
3879 + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
3880 + var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lon, lat])) });
3881 + deviceMark.setStyle(markerStyle(currentNode, parseInt(loctype) + 1));
3882 + markers.push(deviceMark);
3883 +
3884 + if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
3885 + }
3886 + }
3887 + }
3888 +
3889 + // Setup the device mark layer
3890 + var vectorSource = new ol.source.Vector({ features: markers });
3891 + var vectorLayer = new ol.layer.Vector({ source: vectorSource });
3892 +
3893 + //var x = '<div><a href="https://www.google.com/maps/preview/@' + lat + ',' + lng + ',12z" rel="noreferrer noopener" target=_blank>Open in Google maps</a></div>';
3894 + var x = '<div id=d2map style=width:100%;height:300px></div>';
3895 + setDialogMode(2, "Localização do dispositivo", 1, null, x, '@xxmap');
3896 +
3897 + var clng = 0, clat = 0, zoom = 8;
3898 + if (boundingBox != null) {
3899 + var clat = (boundingBox[0] + boundingBox[2]) / 2;
3900 + var clng = (boundingBox[1] + boundingBox[3]) / 2;
3901 + var cscale = Math.max(Math.abs(boundingBox[0] - boundingBox[2]), Math.abs(boundingBox[1] - boundingBox[3]));
3902 + var i = 360, zoom = -2;
3903 + while (i > cscale) { zoom++; i = i / 2; }
3904 + }
3905 +
3906 + if (markers.length == 1) { zoom = 8; }
3907 +
3908 + // Setup the map
3909 + d2map = new ol.Map({
3910 + target: 'd2map',
3911 + interactions: ol.interaction.defaults({dragPan:false, mouseWheelZoom:false}),
3912 + layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ],
3913 + view: new ol.View({ center: ol.proj.fromLonLat([clng, clat]), zoom: zoom })
3914 + });
3915 + return false;
3916 + }
3917 +
3918 + // Show network interfaces
3919 + function p10showNodeNetInfoDialog() {
3920 + if (xxdialogMode) return false;
3921 + setDialogMode(2, "Interfaces de rede", 1, null, '<div id=d2netinfo>' + "Carregando..." + '</div>', 'if' + currentNode._id );
3922 + meshserver.send({ action: 'getnetworkinfo', nodeid: currentNode._id });
3923 + return false;
3924 + }
3925 +
3926 + // Show MeshCentral Router dialog
3927 + function p10showMeshRouterDialog() {
3928 + if (xxdialogMode) return;
3929 + var x = '<div>' + "O MeshCentral Router é uma ferramenta do Windows para mapeamento de portas TCP. Você pode, por exemplo, RDP em um dispositivo remoto através deste servidor." + '</div><br />';
3930 + x += addHtmlValue('Win32 Executable', '<a style=cursor:pointer download href="meshagents?meshaction=winrouter" onclick="setDialogMode(0)">MeshCentralRouter.exe</a>');
3931 + setDialogMode(2, "MeshCentral Router", 1, null, x, 'fileDownload');
3932 + }
3933 +
3934 + // Request MQTT login credentials
3935 + function p10showMqttLoginDialog(nodeid) { meshserver.send({ action: 'getmqttlogin', nodeid: nodeid }); }
3936 +
3937 + // Show MeshCmd dialog
3938 + function p10showMeshCmdDialog(mode, nodeid) {
3939 + if (xxdialogMode) return;
3940 + var y = '<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>';
3941 + y += '<option value=3>' + "Windows (32 Bits)" + '</option>';
3942 + y += '<option value=4>' + "Windows (64 Bits)" + '</option>';
3943 + y += '<option value=5>' + "Linux x86 (32 bits)" + '</option>';
3944 + y += '<option value=6>' + "Linux x86 (64 bits)" + '</option>';
3945 + y += '<option value=16>' + "MacOS (64 bits)" + '</option>';
3946 + y += '<option value=25>' + "Linux ARM, Raspberry Pi (32 bits)" + '</option>';
3947 + y += '</select>';
3948 +
3949 + var x = '';
3950 + if (mode == 0) { x += '<div>MeshCmd is a command line tool that performs lots of different operations. The action file can optionally be downloaded and edited to provide server information and credentials.<br /><br />'; }
3951 + if (mode == 1) { x += '<div>Download "meshcmd" with an action file to route traffic thru this server to this device. Make sure to edit meshaction.txt and add your account password or make any changes needed.<br /><br />'; }
3952 + x += addHtmlValue('Operating System', y);
3953 + x += addHtmlValue('MeshCmd', '<a id=meshcmddownloadid href="meshagents?meshcmd=3" download></a>');
3954 + if (mode == 0) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=generic" download>MeshAction (.txt)</a>'); }
3955 + if (mode == 1) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=route&nodeid=' + nodeid + '" download>MeshAction (.txt)</a>'); }
3956 + x += '</div>';
3957 + setDialogMode(2, [ "Baixar MeshCmd", "Roteador de rede" ][mode], 9, null, x, 'fileDownload');
3958 + meshCmdOsClick();
3959 + }
3960 +
3961 + function meshCmdOsClick() {
3962 + var os = Q('aginsSelect').value, osn = '', osurl = '';
3963 + //Q('meshcmddownloadid').href = 'meshagents?meshcmd=' + os;
3964 + if (os == 3) { osn = 'MeshCmd (Win32 executable)'; }
3965 + if (os == 4) { osn = 'MeshCmd (Win64 executable)'; }
3966 + if (os == 5) { osn = 'MeshCmd (Linux x86, 32bit)'; }
3967 + if (os == 6) { osn = 'MeshCmd (Linux x86, 64bit)'; }
3968 + if (os == 16) { osn = 'MeshCmd (MacOS, 64bit)'; }
3969 + if (os == 25) { osn = 'MeshCmd (Linux ARM, 32bit)'; }
3970 + QH('meshcmddownloadid', osn);
3971 + Q('meshcmddownloadid').setAttribute('href', 'meshagents?meshcmd=' + os);
3972 + }
3973 +
3974 + function p10showiconselector() {
3975 + if (xxdialogMode) return;
3976 + var mesh = meshes[currentNode.meshid];
3977 + var meshrights = mesh.links[userinfo._id].rights;
3978 + if ((meshrights & 4) == 0) return;
3979 +
3980 + var x = '<br><div style=display:inline-block;width:40px></div>';
3981 + x += '<div tabindex=0 style=display:inline-block class=i1 onclick=p10setIcon(1) onkeypress="if (event.key==\'Enter\') p10setIcon(1)"></div>';
3982 + x += '<div tabindex=0 style=display:inline-block class=i2 onclick=p10setIcon(2) onkeypress="if (event.key==\'Enter\') p10setIcon(2)"></div>';
3983 + x += '<div tabindex=0 style=display:inline-block class=i3 onclick=p10setIcon(3) onkeypress="if (event.key==\'Enter\') p10setIcon(3)"></div>';
3984 + x += '<div tabindex=0 style=display:inline-block class=i4 onclick=p10setIcon(4) onkeypress="if (event.key==\'Enter\') p10setIcon(4)"></div>';
3985 + x += '<div tabindex=0 style=display:inline-block class=i5 onclick=p10setIcon(5) onkeypress="if (event.key==\'Enter\') p10setIcon(5)"></div>';
3986 + x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div><br><br>';
3987 + setDialogMode(2, "Seleção de ícone", 0, null, x);
3988 + QV('id_dialogclose', true);
3989 + }
3990 +
3991 + function p10setIcon(icon) {
3992 + setDialogMode(0);
3993 + meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
3994 + }
3995 +
3996 + var showEditNodeValueDialog_modes = ["Nome do Dispositivo", "Hostname", "Descrição", "Tags"];
3997 + var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
3998 + var showEditNodeValueDialog_modes3 = ['', '', '', "Tag1, Tag2, Tag3"];
3999 + function showEditNodeValueDialog(mode) {
4000 + if (xxdialogMode) return;
4001 + var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
4002 + setDialogMode(2, "Editar dispositivo", 3, showEditNodeValueDialogEx, x, mode);
4003 + var v = currentNode[showEditNodeValueDialog_modes2[mode]];
4004 + if (v == null) v = '';
4005 + if (Array.isArray(v)) { v = v.join(', '); }
4006 + Q('dp10devicevalue').value = v;
4007 + p10editdevicevalueValidate();
4008 + Q('dp10devicevalue').focus();
4009 + }
4010 +
4011 + function showEditNodeValueDialogEx(button, mode) {
4012 + var x = { action: 'changedevice', nodeid: currentNode._id };
4013 + x[showEditNodeValueDialog_modes2[mode]] = Q('dp10devicevalue').value;
4014 + meshserver.send(x);
4015 + }
4016 +
4017 + function p10editdevicevalueValidate(mode, e) {
4018 + var x = ((mode > 1) || (Q('dp10devicevalue').value.length > 0));
4019 + QE('idx_dlgOkButton', x);
4020 + if ((e != null) && (x == true) && (e.keyCode == 13)) { dialogclose(1); }
4021 + }
4022 +
4023 + //
4024 + // DESKTOP
4025 + //
4026 +
4027 + var desktopNode;
4028 + function setupDesktop() {
4029 + // Setup the remote desktop
4030 + if ((desktopNode != currentNode) && (desktop != null)) { desktop.Stop(); desktopNode = null; desktop = null; }
4031 +
4032 + // If the device desktop is already connected in multi-desktop, use that.
4033 + if ((desktopNode != currentNode) || (desktop == null)) {
4034 + var xdesk = multiDesktop[currentNode._id];
4035 + if (xdesk != null) {
4036 + // This device already has a canvas, use it.
4037 + QH('DeskParent', '');
4038 + var c = xdesk.m.CanvasId;
4039 + c.setAttribute('id', 'Desk');
4040 + c.setAttribute('onmousedown', 'dmousedown(event)');
4041 + c.setAttribute('onmouseup', 'dmouseup(event)');
4042 + c.setAttribute('onmousemove', 'dmousemove(event)');
4043 + c.removeAttribute('onclick');
4044 + Q('DeskParent').appendChild(c);
4045 + desktop = xdesk;
4046 + if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate); }
4047 + desktop.onStateChanged = onDesktopStateChange;
4048 + desktopNode = currentNode;
4049 + onDesktopStateChange(desktop, desktop.State);
4050 + delete multiDesktop[currentNode._id];
4051 + } else {
4052 + // Device is not already connected, just setup a blank canvas
4053 + QH('DeskParent', '<canvas id=Desk oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
4054 + desktopNode = currentNode;
4055 + }
4056 + // Setup the mouse wheel
4057 + Q('Desk').addEventListener('DOMMouseScroll', function (e) { return dmousewheel(e); });
4058 + Q('Desk').addEventListener('mousewheel', function (e) { return dmousewheel(e); });
4059 + }
4060 + desktopNode = currentNode;
4061 + updateDesktopButtons();
4062 + deskAdjust();
4063 +
4064 + // On some browsers like IE, we can't save screen shots. Hide the scheenshot/capture buttons.
4065 + if (!Q('Desk')['toBlob']) { QV('deskSaveBtn', false); }
4066 + }
4067 +
4068 + // Show and enable the right buttons
4069 + function updateDesktopButtons() {
4070 + var mesh = meshes[currentNode.meshid];
4071 + var deskState = 0;
4072 + if (desktop != null) { deskState = desktop.State; }
4073 + var meshrights = mesh.links[userinfo._id].rights;
4074 +
4075 + // Show the right buttons
4076 + QV('disconnectbutton1span', (deskState != 0));
4077 + QV('connectbutton1span', (deskState == 0) && ((meshrights & 8) || (meshrights & 256)) && (mesh.mtype == 2) && (currentNode.agent.caps & 1));
4078 + QV('connectbutton1hspan',
4079 + (deskState == 0) &&
4080 + (meshrights & 8) &&
4081 + ((mesh.mtype == 1) ||
4082 + ((currentNode.intelamt != null) &&
4083 + (currentNode.intelamt.state == 2) &&
4084 + (currentNode.intelamt.ver != null) &&
4085 + (typeof currentNode.intelamt.sku == 'number') &&
4086 + ((currentNode.intelamt.sku & 8) != 0))
4087 + )
4088 + );
4089 +
4090 + // Show the right settings
4091 + QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == 0) || (desktop.contype == 2)));
4092 + QV('d7meshkvm', (webRtcDesktop) || ((mesh.mtype == 2) && (currentNode.agent.caps & 1) && ((deskState == false) || (desktop.contype == 1))));
4093 +
4094 + // Enable buttons
4095 + var inputAllowed = (meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) == 0));
4096 + var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
4097 + QE('connectbutton1', online);
4098 + var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
4099 + QE('connectbutton1h', hwonline);
4100 + QE('deskSaveBtn', deskState == 3);
4101 + QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
4102 + QV('DeskClip', (currentNode.agent) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && ((desktop == null) || (desktop.contype != 2))); // Clipboard not supported on MacOS
4103 + QE('DeskClip', deskState == 3);
4104 + QE('DeskType', deskState == 3);
4105 + QV('DeskWD', inputAllowed);
4106 + QE('DeskWD', deskState == 3);
4107 + QV('deskkeys', inputAllowed);
4108 + QE('deskkeys', deskState == 3);
4109 +
4110 + // Display this only if we have Chat & Notify permissions
4111 + QV('DeskChatButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
4112 + QV('DeskNotifyButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (mesh.mtype == 2) && online);
4113 +
4114 + QV('DeskToolsButton', (inputAllowed) && (mesh.mtype == 2) && online);
4115 + QV('DeskOpenWebButton', (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
4116 + QV('DeskBackgroundButton', (deskState == 3) && (desktop.contype == 1) && (mesh.mtype == 2) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && online);
4117 + QV('DeskControlSpan', inputAllowed)
4118 + QV('deskActionsBtn', (browserfullscreen == false));
4119 + QV('deskActionsSettings', (browserfullscreen == false));
4120 + if (meshrights & 8) { Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); } else { Q('DeskControl').checked = false; }
4121 + if (online == false) QV('DeskTools', false);
4122 + }
4123 +
4124 + // Debug
4125 + var autoConnectDesktopTimer = null;
4126 + function autoConnectDesktop(e) { if (autoConnectDesktopTimer == null) { autoConnectDesktopTimer = setInterval(connectDesktop, 100); } else { clearInterval(autoConnectDesktopTimer); autoConnectDesktopTimer = null; } }
4127 +
4128 + function connectDesktop(e, contype) {
4129 + p11clearConsoleMsg();
4130 + if (desktop == null) {
4131 + desktopNode = currentNode;
4132 + if (contype == 2) {
4133 + // Setup the Intel AMT remote desktop
4134 + if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; }
4135 + desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
4136 + desktop.debugmode = debugmode;
4137 + desktop.onStateChanged = onDesktopStateChange;
4138 + desktop.m.bpp = (desktopsettings.encoding == 1 || desktopsettings.encoding == 3) ? 1 : 2;
4139 + desktop.m.useZRLE = (desktopsettings.encoding < 3);
4140 + desktop.m.localKeyMap = desktopsettings.localkeymap;
4141 + desktop.m.showmouse = desktopsettings.showmouse;
4142 + desktop.m.onScreenSizeChange = deskAdjust;
4143 + desktop.m.onKvmData = function (x) {
4144 + //console.log('onKvmData (' + x.length + '): ' + x);
4145 + // Send the presense probe only once if needed.
4146 + if (x.length == 0) { if (!desktop.m._sentPresence) { desktop.m._sentPresence = true; desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 })); } return; }
4147 + var data = null;
4148 + try { data = JSON.parse(x); } catch (e) { }
4149 + if ((data != null) && (data.action != null)) {
4150 + if (data.action == 'restart') {
4151 + // Clear WebRTC channel
4152 + webRtcDesktopReset();
4153 + desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 }));
4154 + } else if ((data.action == 'present') && (webRtcDesktop == null)) {
4155 + // Setup WebRTC channel
4156 + webRtcDesktop = { platform: data.platform };
4157 + var configuration = null; //{ "iceServers": [ { 'urls': 'stun:stun.services.mozilla.com' }, { 'urls': 'stun:stun.l.google.com:19302' } ] };
4158 + if (typeof RTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new RTCPeerConnection(configuration); }
4159 + else if (typeof webkitRTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new webkitRTCPeerConnection(configuration); }
4160 +
4161 + webRtcDesktop.webchannel = webRtcDesktop.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
4162 + webRtcDesktop.webchannel.onopen = function () {
4163 + // Switch to software KVM
4164 + //if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
4165 + console.log('WebRTC Data Channel Open');
4166 + Q('deskstatus').textContent = StatusStrs[desktop.State] + ", Soft-KVM";
4167 + desktop.m.hold(true);
4168 + webRtcDesktop.webRtcActive = true;
4169 + webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
4170 + webRtcDesktop.softdesktop.m.setRotation(desktop.m.rotation);
4171 + webRtcDesktop.softdesktop.m.onScreenSizeChange = deskAdjust;
4172 + if (desktopsettings.quality) { webRtcDesktop.softdesktop.m.CompressionLevel = desktopsettings.quality; } // Number from 1 to 100. 50 or less is best.
4173 + if (desktopsettings.scaling) { webRtcDesktop.softdesktop.m.ScalingLevel = desktopsettings.scaling; }
4174 + webRtcDesktop.softdesktop.Start();
4175 +
4176 + // Check if we can get remote file access
4177 + // ###BEGIN###{DesktopInbandFiles}
4178 + /*
4179 + QV('go24', true); // Files
4180 + downloadFile = null;
4181 + p24files = webRtcDesktop.softdesktop;
4182 + p24targetpath = '';
4183 + webRtcDesktop.softdesktop.onControlMsg = onFilesControlData;
4184 + webRtcDesktop.softdesktop.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: '' })); // Ask for the root folder
4185 + */
4186 + // ###END###{DesktopInbandFiles}
4187 + }
4188 + webRtcDesktop.webchannel.onclose = function (event) {
4189 + //if (urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Closed'); }
4190 + console.log('WebRTC Data Channel Closed');
4191 + webRtcDesktopReset();
4192 + }
4193 + webRtcDesktop.webrtc.onicecandidate = function (e) {
4194 + if (e.candidate == null) {
4195 + desktop.m.sendKvmData(JSON.stringify({ action: 'offer', ver: 1, sdp: webRtcDesktop.webrtcoffer.sdp }));
4196 + } else {
4197 + webRtcDesktop.webrtcoffer.sdp += ('a=' + e.candidate.candidate + '\r\n'); // New candidate, add it to the SDP
4198 + }
4199 + }
4200 + webRtcDesktop.webrtc.oniceconnectionstatechange = function () {
4201 + if ((webRtcDesktop != null) && (webRtcDesktop.webrtc != null) && ((webRtcDesktop.webrtc.iceConnectionState == 'disconnected') || (webRtcDesktop.webrtc.iceConnectionState == 'failed'))) { /*console.log('WebRTC ICE Failed');*/ webRtcDesktopReset(); }
4202 + }
4203 + webRtcDesktop.webrtc.createOffer(function (offer) {
4204 + // Got the offer
4205 + webRtcDesktop.webrtcoffer = offer;
4206 + webRtcDesktop.webrtc.setLocalDescription(offer, function () { }, webRtcDesktopReset);
4207 + }, webRtcDesktopReset, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
4208 + } else if ((data.action == 'answer') && (webRtcDesktop != null)) {
4209 + // Complete the WebRTC channel
4210 + webRtcDesktop.webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }), function () { }, webRtcDesktopReset);
4211 + }
4212 + }
4213 + };
4214 + desktop.Start(desktopNode._id, 16994, '*', '*', 0);
4215 + desktop.contype = 2;
4216 + } else {
4217 + // Setup the Mesh Agent remote desktop
4218 + desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
4219 + desktop.debugmode = debugmode;
4220 + desktop.m.debugmode = debugmode;
4221 + desktop.attemptWebRTC = attemptWebRTC;
4222 + desktop.onStateChanged = onDesktopStateChange;
4223 + desktop.onConsoleMessageChange = function () {
4224 + p11clearConsoleMsg();
4225 + if (desktop.consoleMessage) {
4226 + QH('p11DeskConsoleMsg', EscapeHtml(desktop.consoleMessage).split('\n').join('<br />'));
4227 + QV('p11DeskConsoleMsg', true);
4228 + p11DeskConsoleMsgTimer = setTimeout(p11clearConsoleMsg, 8000);
4229 + }
4230 + }
4231 + desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
4232 + desktop.m.ScalingLevel = desktopsettings.scaling;
4233 + desktop.m.FrameRateTimer = desktopsettings.framerate;
4234 + desktop.m.onDisplayinfo = deskDisplayInfo;
4235 + desktop.m.onScreenSizeChange = deskAdjust;
4236 + desktop.Start(desktopNode._id);
4237 + desktop.contype = 1;
4238 + }
4239 + } else {
4240 + // Disconnect and clean up the remote desktop
4241 + desktop.Stop();
4242 + webRtcDesktopReset();
4243 + desktopNode = desktop = null;
4244 + if (pluginHandler != null) { pluginHandler.callHook('onDesktopDisconnect'); }
4245 + }
4246 + }
4247 +
4248 + function p11clearConsoleMsg() { QV('p11DeskConsoleMsg', false); if (p11DeskConsoleMsgTimer) { clearTimeout(p11DeskConsoleMsgTimer); p11DeskConsoleMsgTimer = null; } }
4249 + function p12clearConsoleMsg() { QV('p12TermConsoleMsg', false); if (p12TermConsoleMsgTimer) { clearTimeout(p12TermConsoleMsgTimer); p12TermConsoleMsgTimer = null; } }
4250 + function p13clearConsoleMsg() { QV('p13FilesConsoleMsg', false); if (p13FilesConsoleMsgTimer) { clearTimeout(p13FilesConsoleMsgTimer); p13FilesConsoleMsgTimer = null; } }
4251 +
4252 + var webRtcDesktop = null;
4253 + function webRtcDesktopReset() {
4254 + if (webRtcDesktop == null) return;
4255 + if (webRtcDesktop.softdesktop != null) { webRtcDesktop.softdesktop.Stop(); webRtcDesktop.softdesktop = null; }
4256 + if (webRtcDesktop.webchannel != null) { try { webRtcDesktop.webchannel.close(); } catch (e) { } webRtcDesktop.webchannel = null; }
4257 + if (webRtcDesktop.webrtc != null) { try { webRtcDesktop.webrtc.close(); } catch (e) { } webRtcDesktop.webrtc = null; }
4258 + webRtcDesktop = null;
4259 + // Switch back to hardware KVM
4260 + if (desktop && desktop.m) {
4261 + desktop.m.hold(false);
4262 + Q('deskstatus').textContent = StatusStrs[desktop.State];
4263 + }
4264 + // ###BEGIN###{DesktopInbandFiles}
4265 + /*
4266 + p24files = null;
4267 + p24downloadFileCancel() // If any downloads are in process, cancel them.
4268 + p24uploadFileCancel(); // If any uploads are in process, cancel them.
4269 + QV('go24', false); // Files
4270 + if (currentView == 24) { go(14); }
4271 + */
4272 + // ###END###{DesktopInbandFiles}
4273 + }
4274 +
4275 + function onDesktopStateChange(xdesktop, state) {
4276 + var xstate = state;
4277 + if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
4278 + var str = StatusStrs[xstate];
4279 + if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
4280 + //if (desktop.m.stopInput == true) { str += ', Loopback'; }
4281 + QH('deskstatus', str);
4282 + switch (state) {
4283 + case 0:
4284 + // Disconnect and clean up the remote desktop
4285 + desktop.Stop();
4286 + desktopNode = desktop = null;
4287 + QV('DeskFocus', false);
4288 + QV('termdisplays', false);
4289 + QV('deskRecordIcon', false);
4290 + deskFocusBtn.value = "All Focus";
4291 + if (fullscreen == true) { deskToggleFull(); }
4292 + webRtcDesktopReset();
4293 + deskPreferedStickyDisplay = 0;
4294 + break;
4295 + case 2:
4296 + break;
4297 + case 3:
4298 + if (desktop && (desktop.serverIsRecording == true)) { QV('deskRecordIcon', true); }
4299 + desktop.startTime = new Date();
4300 + if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
4301 + break;
4302 + default:
4303 + //console.log('Unknown onDesktopStateChange state', state);
4304 + break;
4305 + }
4306 + updateDesktopButtons();
4307 + deskAdjust();
4308 + setTimeout(deskAdjust, 50);
4309 + }
4310 +
4311 + function updateSessionTime() {
4312 + // Desktop
4313 + var seconds = 0;
4314 + if (desktop && desktop.startTime) {
4315 + seconds = Math.floor((new Date() - desktop.startTime) / 1000);
4316 + QH('DeskTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
4317 + } else {
4318 + QH('DeskTimer', '');
4319 + }
4320 +
4321 + // Terminal
4322 + seconds = 0;
4323 + if (terminal && terminal.startTime) {
4324 + seconds = Math.floor((new Date() - terminal.startTime) / 1000);
4325 + QH('TermTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
4326 + } else {
4327 + QH('TermTimer', '');
4328 + }
4329 +
4330 + if ((desktop == null) && (terminal == null)) { clearInterval(updateSessionTimer); updateSessionTimer = null; }
4331 + }
4332 +
4333 + function showDesktopSettings() {
4334 + if (xxdialogMode) return;
4335 + applyDesktopSettings();
4336 + updateDesktopButtons();
4337 + setDialogMode(7, "Configurações da área de trabalho remota", 3, showDesktopSettingsChanged);
4338 + }
4339 +
4340 + function showDesktopSettingsChanged() {
4341 + desktopsettings.encoding = d7desktopmode.value;
4342 + desktopsettings.showfocus = d7showfocus.checked;
4343 + desktopsettings.showmouse = d7showcursor.checked;
4344 + desktopsettings.quality = d7bitmapquality.value;
4345 + desktopsettings.scaling = d7bitmapscaling.value;
4346 + desktopsettings.framerate = d7framelimiter.value;
4347 + desktopsettings.localkeymap = d7localKeyMap.checked;
4348 + localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
4349 + applyDesktopSettings();
4350 + if (desktop) {
4351 + if (desktop.contype == 1) {
4352 + if (desktop.State != 0) {
4353 + desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate);
4354 + }
4355 + }
4356 + if (desktop.contype == 2) {
4357 + if (desktopsettings.showfocus == false) { desktop.m.focusmode = 0; deskFocusBtn.value = "All Focus"; }
4358 + if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
4359 + }
4360 + }
4361 + }
4362 +
4363 + function applyDesktopSettings() {
4364 + var r = '', ops = (features & 512)?[90,80,70,60,50,40,30,20,10,5,1]:[60,50,40,30,20,10,5,1];
4365 + for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
4366 + QH('d7bitmapquality', r);
4367 + d7desktopmode.value = desktopsettings.encoding;
4368 + d7showfocus.checked = desktopsettings.showfocus;
4369 + d7showcursor.checked = desktopsettings.showmouse;
4370 + d7bitmapquality.value = 40; // Default value
4371 + if (ops.indexOf(parseInt(desktopsettings.quality)) >= 0) { d7bitmapquality.value = desktopsettings.quality; }
4372 + d7bitmapscaling.value = desktopsettings.scaling;
4373 + if (desktopsettings.framerate) { d7framelimiter.value = desktopsettings.framerate; }
4374 + if (desktopsettings.localkeymap) { d7localKeyMap.checked = desktopsettings.localkeymap; }
4375 + QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (desktop.state != 0) && (desktopsettings.showfocus));
4376 + }
4377 +
4378 + // Enter browser fullscreen
4379 + function enterBrowserFullscreen(elem) {
4380 + if (elem.requestFullscreen) { elem.requestFullscreen(); }
4381 + else if (elem.msRequestFullscreen) { elem.msRequestFullscreen(); }
4382 + else if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); }
4383 + else if (elem.webkitRequestFullscreen) { elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); }
4384 + }
4385 +
4386 + // Exit browser fullscreen
4387 + function exitBrowserFullscreen() {
4388 + if (document.exitFullscreen) { document.exitFullscreen(); }
4389 + else if (document.msExitFullscreen) { document.msExitFullscreen(); }
4390 + else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); }
4391 + else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); }
4392 + }
4393 +
4394 + // Return true if the browser is fullscreen. This is a delayed method that will return true/false late. Not very useful.
4395 + function isBrowserFullscreen() {
4396 + if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { return false; } else { return true; }
4397 + }
4398 +
4399 + var fullscreen = false;
4400 + var browserfullscreen = false;
4401 + function deskToggleFull(e) {
4402 + fullscreen = !fullscreen;
4403 + if (fullscreen) {
4404 + QC('body').add('fulldesk');
4405 + QS('deskarea3x')['height'] = '100%';
4406 + QS('deskarea3x')['max-height'] = '100%';
4407 + // If shift is pressed, enter browser full screen.
4408 + if (e.shiftKey == true) { enterBrowserFullscreen(Q('deskarea0')); browserfullscreen = true; }
4409 + } else {
4410 + QC('body').remove('fulldesk');
4411 + QS('deskarea3x')['height'] = null;
4412 + QS('deskarea3x')['max-height'] = null;
4413 + if (browserfullscreen == true) { exitBrowserFullscreen(); browserfullscreen = false; }
4414 + }
4415 + deskAdjust();
4416 + updateDesktopButtons();
4417 + }
4418 +
4419 + function deskToggleFocus() {
4420 + desktop.m.focusmode = (desktop.m.focusmode + 64) % 192;
4421 + Q('deskFocusBtn').value = ["All Focus", "Foco pequeno", "Foco grande"][desktop.m.focusmode / 64];
4422 + }
4423 +
4424 + function deskAdjust() {
4425 + var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
4426 + var deskH = Q('Desk').height, deskW = Q('Desk').width;
4427 +
4428 + if (deskAspectRatio == 2) {
4429 + // Scale mode
4430 + QS('Desk')['margin-top'] = null;
4431 + QS('Desk').height = '100%';
4432 + QS('Desk').width = '100%';
4433 + //QS('deskarea3x').height = null;
4434 + QS('DeskParent').overflow = 'hidden';
4435 + } else if (deskAspectRatio == 1) {
4436 + // Zoomed mode
4437 + QS('Desk')['margin-top'] = '0px';
4438 + QS('Desk').height = deskH + 'px';
4439 + QS('Desk').width = deskW + 'px';
4440 + QS('DeskParent').overflow = 'scroll';
4441 + } else {
4442 + // Fixed aspect ratio
4443 + if ((parentH / parentW) > (deskH / deskW)) {
4444 + var hNew = ((deskH * parentW) / deskW) + 'px';
4445 + //if (webPageFullScreen || fullscreen) {
4446 + //QS('deskarea3x').height = null;
4447 + //} else {
4448 + // QS('deskarea3x').height = hNew;
4449 + //QS('deskarea3x').height = null;
4450 + //}
4451 + QS('Desk').height = hNew;
4452 + QS('Desk').width = '100%';
4453 + } else {
4454 + var wNew = ((deskW * parentH) / deskH) + 'px';
4455 + if (webPageFullScreen || fullscreen) {
4456 + QS('Desk').height = null;
4457 + } else {
4458 + QS('Desk').height = '100%';
4459 + }
4460 + QS('Desk').width = wNew;
4461 + }
4462 + QS('Desk')['margin-top'] = null;
4463 + QS('DeskParent').overflow = 'hidden';
4464 + }
4465 + }
4466 +
4467 + function mdeskAdjust(mod, sw, sh, cv) {
4468 + if (!mod || !sw || !sh || !cv) return;
4469 +
4470 + // Check if we are in single desktop mode
4471 + if (cv.id == 'Desk') { deskAdjust(); return; }
4472 +
4473 + // Figure out and adjust the size to fill the width of the div
4474 + var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
4475 + var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
4476 + xw = realw + Math.floor((tw - (xw * realw)) / xw);
4477 + vsize.y = vsize.y * (xw / vsize.x);
4478 + vsize.x = xw;
4479 + var mh = vsize.y, mw = vsize.x;
4480 + if (mod.State != 0) { mh = vsize.y; mw = (sw / sh) * vsize.y; }
4481 + QS(cv.id)['max-height'] = mh + 'px';
4482 + QS(cv.id)['max-width'] = mw + 'px';
4483 + QS(cv.id)['margin-top'] = '0';
4484 + QS(cv.id)['margin-bottom'] = '0';
4485 + }
4486 +
4487 + // Remote desktop special key combos for Windows
4488 + function deskSendKeys() {
4489 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
4490 + var ks = Q('deskkeys').value;
4491 + if (ks == 0) { // WIN+Down arrow
4492 + if (desktop.contype == 2) {
4493 + desktop.m.sendkey([[0xffe7,1],[0xff54,1],[0xff54,0],[0xffe7,0]]); // Intel AMT: Meta-left down, Down arrow press, Down arrow release, Meta-left release
4494 + } else {
4495 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,40],[desktop.m.KeyAction.UP,40],[desktop.m.KeyAction.EXUP,0x5B]]); // Agent: L-Winkey press, Down arrow press, Down arrow release, L-Winkey release
4496 + }
4497 + } else if (ks == 1) { // WIN+Up arrow
4498 + if (desktop.contype == 2) {
4499 + desktop.m.sendkey([[0xffe7,1],[0xff52,1],[0xff52,0],[0xffe7,0]]); // Intel AMT: Meta-left down, Up arrow press, Up arrow release, Meta-left release
4500 + } else {
4501 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,38],[desktop.m.KeyAction.UP,38],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, Up arrow press, Up arrow release, L-Winkey release
4502 + }
4503 + } else if (ks == 2) { // WIN+L arrow
4504 + if (desktop.contype == 2) {
4505 + desktop.m.sendkey([[0xffe7,1],[0x6c,1],[0x6c,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
4506 + } else {
4507 + desktop.sendCtrlMsg('{"action":"lock"}');
4508 + //desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,76],[desktop.m.KeyAction.UP,76],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'L' press, 'L' release, L-Winkey release
4509 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXDOWN, 0x5B);
4510 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.DOWN, 76);
4511 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.UP, 76);
4512 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXUP, 0x5B);
4513 + }
4514 + } else if (ks == 3) { // WIN+M arrow
4515 + if (desktop.contype == 2) {
4516 + desktop.m.sendkey([[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
4517 + } else {
4518 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'M' press, 'M' release, L-Winkey release
4519 + }
4520 + } else if (ks == 4) { // Shift+WIN+M arrow
4521 + if (desktop.contype == 2) {
4522 + desktop.m.sendkey([[0xffe1,1],[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0],[0xffe1,0]]); // Intel AMT: Shift-left down, Meta-left down, 'm' press, 'm' release, Meta-left release, Shift-left release
4523 + } else {
4524 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN,16],[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,0x5B],[desktop.m.KeyAction.UP, 16]]); // MeshAgent: L-shift press, L-Winkey press, 'M' press, 'M' release, L-Winkey release, L-shift release
4525 + }
4526 + } else if (ks == 5) { // WIN
4527 + if (desktop.contype == 2) {
4528 + desktop.m.sendkey([[0xffe7,1],[0xffe7,0]]); // Intel AMT: Meta-left down, Meta-left release
4529 + } else {
4530 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B], [desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, L-Winkey release
4531 + }
4532 + } else if (ks == 6) { // WIN+R
4533 + if (desktop.contype == 2) {
4534 + desktop.m.sendkey([[0xffe7,1],[0x72,1],[0x72,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'r' press, 'r' release, Meta-left release
4535 + } else {
4536 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 82], [desktop.m.KeyAction.UP, 82], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'R' press, 'R' release, L-Winkey release
4537 + }
4538 + } else if (ks == 7) { // ALT-F4
4539 + if (desktop.contype == 2) {
4540 + desktop.m.sendkey([[0xffe9,1],[0xffc1,1],[0xffc1,0],[0xffe9,0]]); // Intel AMT: Alt down, 'F4' press, 'F4' release, Alt release
4541 + } else {
4542 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 115], [desktop.m.KeyAction.UP, 115], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'F4' press, 'F4' release, Alt release
4543 + }
4544 + } else if (ks == 8) { // CTRL-W
4545 + if (desktop.contype == 2) {
4546 + desktop.m.sendkey([[0xffe3,1],[0x77,1],[0x77,0],[0xffe3,0]]); // Intel AMT: Ctrl down, 'w' press, 'w' release, Ctrl release
4547 + } else {
4548 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 17], [desktop.m.KeyAction.DOWN, 87], [desktop.m.KeyAction.UP, 87], [desktop.m.KeyAction.EXUP, 17]]); // MeshAgent: Ctrl press, 'W' press, 'W' release, Ctrl release
4549 + }
4550 + } else if (ks == 9) { // ALT-TAB
4551 + if (desktop.contype == 2) {
4552 + desktop.m.sendkey([[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'TAB' press, 'TAB' release, Alt release
4553 + } else {
4554 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 9], [desktop.m.KeyAction.UP, 9], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'TAB' press, 'TAB' release, Alt release
4555 + }
4556 + } else if (ks == 10) { // CTRL-ALT-DEL
4557 + desktop.m.sendcad();
4558 + } else if (ks == 11) { // WIN-LEFT
4559 + if (desktop.contype == 2) {
4560 + desktop.m.sendkey([[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Left arrow press, Left arrow release, Meta-left release
4561 + } else {
4562 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 37], [desktop.m.KeyAction.UP, 37], [desktop.m.KeyAction.EXUP, 0x5B]]);
4563 + }
4564 + } else if (ks == 12) { // WIN-RIGHT
4565 + if (desktop.contype == 2) {
4566 + desktop.m.sendkey([[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Right arrow press, Right arrow release, Meta-left release
4567 + } else {
4568 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 39], [desktop.m.KeyAction.UP, 39], [desktop.m.KeyAction.EXUP, 0x5B]]);
4569 + }
4570 + }
4571 + }
4572 +
4573 + // Remote desktop typing
4574 + function showDeskType() {
4575 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
4576 + Q('DeskType').blur();
4577 + var x = '<div>' + "Digite o texto e clique em OK para digitá-lo remotamente usando um teclado em inglês dos EUA.Certifique-se de colocar o cursor remoto na posição correta antes de continuar." + '<div>';
4578 + x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
4579 + setDialogMode(2, "Entrada remota do teclado", 3, showDeskTypeEx, x);
4580 + Q('d2typeText').focus();
4581 + }
4582 +
4583 + var AmtDeskTypeTimer = null;
4584 + var AmtDeskTypeContent = null;
4585 + var DeskTypeTranslate = { 39: 222, 42: 106, 43: 107, 44: 188, 45: 189, 46: 190, 47: 191, 59: 186, 61: 187, 91: 219, 92: 220, 93: 221, 96: 192, 191: 111 };
4586 + var DeskTypeShiftTranslate = { 33: 49, 34: 222, 35: 51, 36: 52, 37: 53, 38: 55, 40: 57, 41: 48, 58: 186, 60: 188, 62: 190, 63: 191, 64: 50, 94: 54, 95: 189, 106: 56, 107: 187, 123: 219, 124: 220, 125: 221, 126: 192 };
4587 + function showDeskTypeEx() {
4588 + var txt = Q('d2typeText').value, ltxt = Q('d2typeText').value.toUpperCase(), x = [], shift = false;
4589 + if (desktop.contype == 2) {
4590 + // Intel AMT
4591 + for (var i in txt) { var a = txt.charCodeAt(i); x.push([a, 1], [a, 0]); }
4592 + AmtDeskTypeContent = x;
4593 + AmtDeskTypeTimer = setInterval(function () {
4594 + var key = AmtDeskTypeContent.shift();
4595 + if (desktop) { desktop.m.sendkey(key[0], key[1]); }
4596 + if ((desktop == null) || (AmtDeskTypeContent.length == 0)) { clearInterval(AmtDeskTypeTimer); AmtDeskTypeContent = null; }
4597 + }, 10);
4598 + } else {
4599 + // MeshAgent
4600 + for (var i in txt) {
4601 + var a = txt.charCodeAt(i), b = ltxt.charCodeAt(i);
4602 + if (((a >= 65) && (a <= 90)) || ((a >= 97) && (a <= 122))) {
4603 + if ((a == b) && (shift == false)) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
4604 + if ((a != b) && (shift == true)) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // LShift up
4605 + } else if ((a >= 48) && (a <= 57)) {
4606 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
4607 + } else if (DeskTypeTranslate[a]) {
4608 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
4609 + b = DeskTypeTranslate[a];
4610 + } else if (DeskTypeShiftTranslate[a]) {
4611 + if (shift == false) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
4612 + b = DeskTypeShiftTranslate[a];
4613 + }
4614 + x.push([desktop.m.KeyAction.DOWN, b], [desktop.m.KeyAction.UP, b]);
4615 + }
4616 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
4617 + desktop.m.SendKeyMsgKC(x);
4618 + }
4619 + }
4620 +
4621 + // Show clipboard dialog
4622 + function showDeskClip() {
4623 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
4624 + Q('DeskClip').blur();
4625 + var x = '';
4626 + x += '<input id=dlgClipGet type=button value="Get Clipboard" style=width:120px onclick=showDeskClipGet()>';
4627 + x += '<input id=dlgClipSet type=button value="Set Clipboard" style=width:120px onclick=showDeskClipSet()>';
4628 + x += '<div id=dlgClipStatus style="display:inline-block;margin-left:8px" ></div>';
4629 + x += '<textarea id=d2clipText style="width:100%;height:184px;resize:none" maxlength=65535></textarea>';
4630 + x += '<input type=button value="Close" style=width:80px;float:right onclick=dialogclose(0)><div style=height:26px;margin-top:3px><span id=linuxClipWarn style=display:none>' + "A área de transferência remota é válida por 60 segundos." + '</span>&nbsp;</div><div></div>';
4631 + setDialogMode(2, "Área de transferência remota", 8, null, x, 'clipboard');
4632 + Q('d2clipText').focus();
4633 + }
4634 +
4635 + function showDeskClipGet() {
4636 + if (desktop == null || desktop.State != 3) return;
4637 + meshserver.send({ action: 'msg', type: 'getclip', nodeid: currentNode._id });
4638 + }
4639 +
4640 + function showDeskClipSet() {
4641 + if (desktop == null || desktop.State != 3) return;
4642 + meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: Q('d2clipText').value });
4643 + QV('linuxClipWarn', currentNode && currentNode.agent && (currentNode.agent.id > 4) && (currentNode.agent.id != 21) && (currentNode.agent.id != 22));
4644 + }
4645 +
4646 + // Send CTRL-ALT-DEL
4647 + function sendCAD() {
4648 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
4649 + desktop.m.sendcad();
4650 + }
4651 +
4652 + // Show process dialogs
4653 + function toggleDeskTools() {
4654 + if (xxdialogMode) return;
4655 + if (QS('DeskTools').display == 'none') {
4656 + QV('DeskTools', true);
4657 + Q('DeskTools').nodeid = currentNode._id;
4658 + QH('DeskToolsProcesses', '');
4659 + QH('DeskToolsServices', '');
4660 + QV('deskToolsTopTabService', false);
4661 + changeDeskToolTab(0)
4662 + refreshDeskTools(0);
4663 + refreshDeskTools(1);
4664 + } else {
4665 + QV('DeskTools', false);
4666 + }
4667 + }
4668 +
4669 + var deskToolTabSelection = 0;
4670 + function changeDeskToolTab(tabnum) {
4671 + deskToolTabSelection = tabnum;
4672 + QV('DeskToolsProcessTab', tabnum == 0);
4673 + QV('DeskToolsServiceTab', tabnum == 1);
4674 + QS('deskToolsTopTabProcess')['bottom'] = (tabnum == 0) ? '0px' : '3px';
4675 + QS('deskToolsTopTabService')['bottom'] = (tabnum == 1) ? '0px' : '3px';
4676 + QS('deskToolsTopTabProcess')['color'] = (tabnum == 0) ? 'black' : 'gray';
4677 + QS('deskToolsTopTabService')['color'] = (tabnum == 1) ? 'black' : 'gray';
4678 + }
4679 +
4680 + // Refresh all of the desktop tool panels
4681 + function refreshDeskTools(x) {
4682 + var sel = (x == null) ? deskToolTabSelection : x;
4683 + QV('DeskToolsRefreshButton', false);
4684 + setTimeout(refreshDeskToolsEx, 500);
4685 + if (sel == 0) meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id });
4686 + if (sel == 1) meshserver.send({ action: 'msg', type: 'services', nodeid: currentNode._id });
4687 + }
4688 + function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
4689 + var deskTools = { sort: 1, ssort: 1, msg: null, smsg: null };
4690 + function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
4691 + function sortService(sort) { deskTools.ssort = sort; showDeskToolsServices(deskTools.smsg); }
4692 + function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return sortProcessName(a, b); }
4693 + function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
4694 + function showDeskToolsProcesses(message) {
4695 + deskTools.msg = message;
4696 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
4697 + if (Q('DeskTools').nodeid != message.nodeid) return;
4698 + var p = [], processes = null;
4699 + try { processes = JSON.parse(message.value); } catch (e) { }
4700 + if (processes != null) {
4701 + for (var pid in processes) { p.push( { p:parseInt(pid), c:processes[pid].cmd, d:processes[pid].cmd.toLowerCase(), u: processes[pid].user } ); }
4702 + if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
4703 + var x = '';
4704 + for (var i in p) {
4705 + if (p[i].p != 0) {
4706 + var c = p[i].c;
4707 + if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0,30) + '...</span>' }
4708 + x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a href=# style=float:right;padding-right:5px;cursor:pointer title="Stop process" onclick=\'return stopProcess(' + p[i].p + ',"' + p[i].c + '")\'><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? p[i].u : '') + '</div><div>' + c + '</div></div>';
4709 + }
4710 + }
4711 + QH('DeskToolsProcesses', x);
4712 + }
4713 + }
4714 + function showDeskToolsServices(message) {
4715 + deskTools.smsg = message;
4716 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
4717 + if (Q('DeskTools').nodeid != message.nodeid) return;
4718 + QV('deskToolsTopTabService', true);
4719 + var s = [], services = null;
4720 + try { services = JSON.parse(message.value); } catch (e) { }
4721 + deskTools.services = services;
4722 + if (services != null) {
4723 + for (var i in services) {
4724 + if (services[i].status) {
4725 + // Windows
4726 + s.push({ p: capitalizeFirstLetter(services[i].status.state.toLowerCase()), d: services[i].displayName, i: i });
4727 + } else if (services[i].serviceType) {
4728 + // Linux (TODO: This the service status is not displayed, not sure start/stop/restart will work).
4729 + s.push({ p: services[i].serviceType, d: services[i].name, i: i });
4730 + }
4731 + }
4732 + if (deskTools.ssort == 0) { s.sort(sortProcessPid); } else if (deskTools.ssort == 1) { s.sort(sortProcessName); }
4733 + var x = '';
4734 + for (var i in s) {
4735 + if (s[i].p != 0) {
4736 + var c = s[i].d;
4737 + if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0, 30) + '...</span>' }
4738 + x += '<div onclick=showServiceDetailsDialog(' + s[i].i + ') class=deskToolsBar><div style=width:70px;float:left;padding-right:5px>' + s[i].p + '</div><div>' + c + '</div></div>';
4739 + }
4740 + }
4741 + QH('DeskToolsServices', x);
4742 + }
4743 + }
4744 +
4745 + function showServiceDetailsDialog(index) {
4746 + if (xxdialogMode) return;
4747 + var service = deskTools.services[index];
4748 + if (service != null) {
4749 + var x = '';
4750 + if (service.name) { x += addHtmlValue("Nome", service.name); }
4751 + if (service.displayName) { x += addHtmlValue("Mostrar nome", service.displayName); }
4752 + if (service.status) {
4753 + if (service.status.state) { x += addHtmlValue("Estado", capitalizeFirstLetter(service.status.state.toLowerCase())); }
4754 + if (service.status.pid) { x += addHtmlValue("PID", service.status.pid); }
4755 + var serviceTypes = [];
4756 + if (service.status.isFileSystemDriver === true) { serviceTypes.push("Driver do sistema de arquivos"); }
4757 + if (service.status.isInteractive === true) { serviceTypes.push("Interativo"); }
4758 + if (service.status.isKernelDriver === true) { serviceTypes.push("KernelDriver"); }
4759 + if (service.status.isOwnProcess === true) { serviceTypes.push("Processo próprio"); }
4760 + if (service.status.isSharedProcess === true) { serviceTypes.push("Processo compartilhado"); }
4761 + if (serviceTypes.length > 0) { x += addHtmlValue("Tipo", serviceTypes.join(', ')); }
4762 + }
4763 + x += '<br/><div style=float:right;margin-bottom:12px><input type=button value=\"' + "Fechar" + '\" onclick=showServiceDetailsDialogEx(0,' + index + ')></div><div style=margin-bottom:12px><input type=button value=\"' + "Start" + '\" onclick=showServiceDetailsDialogEx(1,' + index + ')><input type=button value=\"' + "Pare" + '\" onclick=showServiceDetailsDialogEx(2,' + index + ')><input type=button value=\"' + "Reiniciar" + '\" onclick=showServiceDetailsDialogEx(3,' + index + ')></div>';
4764 + setDialogMode(2, "Detalhes do serviço", 8, null, x, name);
4765 + }
4766 + }
4767 +
4768 + function showServiceDetailsDialogEx(action, index) {
4769 + setDialogMode(0);
4770 + if (action == 0) return;
4771 + var service = deskTools.services[index];
4772 + if (service != null) {
4773 + if (action == 1) { meshserver.send({ action: 'msg', type: 'serviceStart', nodeid: currentNode._id, serviceName: service.name }); }
4774 + if (action == 2) { meshserver.send({ action: 'msg', type: 'serviceStop', nodeid: currentNode._id, serviceName: service.name }); }
4775 + if (action == 3) { meshserver.send({ action: 'msg', type: 'serviceRestart', nodeid: currentNode._id, serviceName: service.name }); }
4776 + setTimeout(function () { refreshDeskTools(1) }, 1000);
4777 + }
4778 + }
4779 +
4780 + // Toggle mouse and keyboard input
4781 + function toggleKvmControl() { putstore('DeskControl', (Q("DeskControl").checked?1:0)); }
4782 +
4783 + // Save the desktop image to file
4784 + function deskSaveImage() {
4785 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
4786 + var d = new Date(), n = 'Desktop-' + currentNode.name + '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
4787 + Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.jpg'); });
4788 + }
4789 +
4790 + function deskDisplayInfo(sender, displays, selDisplay) {
4791 + var displayCount = 0, displaySelector = '';
4792 + for (var i in displays) {
4793 + displayCount++;
4794 + displaySelector += '<option' + ((selDisplay == i) ? ' selected' : '') + ' value=' + i + '>' + displays[i] + '</option>';
4795 + if ((deskPreferedStickyDisplay == i) && (selDisplay != deskPreferedStickyDisplay)) { desktop.m.SetDisplay(i); }
4796 + }
4797 + QH('termdisplays', displaySelector);
4798 + QV('termdisplays', displayCount > 1);
4799 + }
4800 +
4801 + function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
4802 + var deskPreferedStickyDisplay = 0;
4803 + function deskSetDisplay(e) { desktop.m.SetDisplay(deskPreferedStickyDisplay = parseInt(Q('termdisplays').value)); Q('termdisplays').blur(); }
4804 +
4805 + // Double click detection. This is important for MacOS.
4806 + var dblClickDetectArgs = { t:0, x:0, y:0 };
4807 + function dblClickDetect(e) {
4808 + if (e.buttons != 1) return;
4809 + var t = Date.now();
4810 + if (((t - dblClickDetectArgs.t) < 250) && (Math.abs(e.clientX - dblClickDetectArgs.x) < 2) && (Math.abs(e.clientY - dblClickDetectArgs.y) < 2)) {
4811 + if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedblclick(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedblclick(e); } }
4812 + }
4813 + dblClickDetectArgs.t = t;
4814 + dblClickDetectArgs.x = e.clientX;
4815 + dblClickDetectArgs.y = e.clientY;
4816 + }
4817 +
4818 + function dmousedown(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } dblClickDetect(e); }
4819 + function dmouseup(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } }
4820 + function dmousemove(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } }
4821 + function dmousewheel(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { if (desktop.m.mousewheel) { desktop.m.mousewheel(e); } } haltEvent(e); return true; } return false; }
4822 + function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
4823 + function stopProcess(id, name) { setDialogMode(2, "Controle do processo", 3, stopProcessEx, format("Parar processo #{0} \"{1}\"?", id, name), id); return false; }
4824 + function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
4825 +
4826 + //
4827 + // TERMINAL
4828 + //
4829 +
4830 + var terminalNode;
4831 + function setupTerminal() {
4832 + // Setup the terminal
4833 + if ((terminalNode != currentNode) && (terminal != null)) { terminal.Stop(); terminal = null; }
4834 + terminalNode = currentNode;
4835 + updateTerminalButtons();
4836 + }
4837 +
4838 + // Show and enable the right buttons
4839 + function updateTerminalButtons() {
4840 + var mesh = meshes[terminalNode.meshid];
4841 + var termState = ((terminal != null) && (terminal.state != 0));
4842 +
4843 + // Show the right buttons
4844 + QV('disconnectbutton2span', (termState == true));
4845 + QV('connectbutton2span', (termState == false) && (mesh.mtype == 2) && (currentNode.agent.caps & 2));
4846 + QV('connectbutton2hspan', (termState == false) && ((terminalNode.intelamt != null) && (mesh.mtype == 1 || terminalNode.intelamt.state == 2) && ((terminalNode.intelamt.ver != null) || (mesh.mtype == 1))));
4847 +
4848 + // Enable buttons
4849 + var online = ((terminalNode.conn & 1) != 0); // If Agent (1) connected, enable Terminal
4850 + QE('connectbutton2', online);
4851 + var hwonline = ((terminalNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
4852 + QE('connectbutton2h', hwonline);
4853 +
4854 + // Key buttons
4855 + QE('ctrlcbutton', termState);
4856 + QE('ctrlxbutton', termState);
4857 + QE('escbutton', termState);
4858 + QE('bsbutton', termState);
4859 + QE('pastebutton', termState);
4860 + QE('specialkeylist', termState);
4861 + QE('specialkeylistinput', termState);
4862 +
4863 + // Terminal settings
4864 + QV('terminalSettingsButtons', (terminal) && (terminal.contype == 2));
4865 + if (terminal) {
4866 + Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
4867 + Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
4868 + Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n')?"CR + LF":"LF";
4869 + }
4870 + }
4871 +
4872 + // Called when the terminal state changes
4873 + function onTerminalStateChange(xterminal, state) {
4874 + var xstate = state;
4875 + if ((xstate == 3) && (xterminal.contype == 2)) { xstate++; }
4876 + var str = StatusStrs[xstate];
4877 + if (terminal.webRtcActive == true) { str += ", WebRTC"; }
4878 + QH('termstatus', str);
4879 + switch (state) {
4880 + case 0:
4881 + // Disconnected, clear the terminal
4882 + QE('termSizeList', true);
4883 + QH('termtitle', '');
4884 + QV('termRecordIcon', false);
4885 + xterminal.m.TermResetScreen();
4886 + xterminal.m.TermDraw();
4887 + if (terminal != null) { terminal.Stop(); terminal = null; }
4888 + break;
4889 + case 3:
4890 + QE('termSizeList', false);
4891 + if (xterminal && (xterminal.serverIsRecording == true)) { QV('termRecordIcon', true); }
4892 + terminal.startTime = new Date();
4893 + if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
4894 + break;
4895 + default:
4896 + QE('termSizeList', false);
4897 + //console.log('Unhandled onTerminalStateChange state', state);
4898 + break;
4899 + }
4900 + updateTerminalButtons();
4901 + }
4902 +
4903 + // DEBUG
4904 + var autoConnectTerminalTimer = null;
4905 + function autoConnectTerminal(e) { if (autoConnectTerminalTimer == null) { autoConnectTerminalTimer = setInterval(connectTerminal, 100); } else { clearInterval(autoConnectTerminalTimer); autoConnectTerminalTimer = null; } }
4906 +
4907 + function connectTerminal(e, contype, options) {
4908 + p12clearConsoleMsg();
4909 + if (!terminal) {
4910 + if (contype == 2) {
4911 + // Setup the Intel AMT terminal
4912 + if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal, 2); return; }
4913 + var termoptions = {};
4914 + if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; }
4915 + terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term', termoptions), authCookie);
4916 + terminal.debugmode = debugmode;
4917 + terminal.m.debugmode = debugmode;
4918 + terminal.m.onTitleChange = function (sender, title) { QH('termtitle', ' - ' + EscapeHtml(title)); }
4919 + terminal.onStateChanged = onTerminalStateChange;
4920 + terminal.Start(terminalNode._id, 16994, '*', '*', 0);
4921 + terminal.contype = 2;
4922 + Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
4923 + } else {
4924 + // Setup a mesh agent terminal
4925 + var termoptions = { protocol: ((options != null) && (typeof options.protocol == 'number'))?options.protocol:1 };
4926 + if ([1, 2, 3, 4, 21, 22].indexOf(currentNode.agent.id) == -1) {
4927 + if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; termoptions.xterm = true; }
4928 + if (Q('termSizeList').value == 3) {
4929 + // TODO: Try to improve terminal auto-size.
4930 + termoptions.width = Math.floor((Q('column_l').clientWidth - 60) / 10);
4931 + termoptions.height = Math.floor((Q('column_l').clientHeight - 120) / 20);
4932 + termoptions.xterm = true;
4933 + }
4934 + }
4935 +
4936 + // If shift is pressed
4937 + if ((e && (e.shiftKey == true))) {
4938 + if (currentNode.agent.id > 4) {
4939 + if (termoptions.protocol == 1) { termoptions.protocol = 7; } // Switch to user shell
4940 + } else {
4941 + if (termoptions.protocol == 1) { termoptions.protocol = 6; } // Switch to Powershell
4942 + }
4943 + }
4944 +
4945 + terminal = CreateAgentRedirect(meshserver, CreateAmtRemoteTerminal('Term', termoptions), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
4946 + terminal.debugmode = debugmode;
4947 + terminal.m.debugmode = debugmode;
4948 + terminal.m.onTitleChange = function (sender, title) { QH('termtitle', ' - ' + EscapeHtml(title)); }
4949 + terminal.m.lineFeed = ([1, 2, 3, 4, 21, 22].indexOf(currentNode.agent.id) >= 0) ? '\r\n' : '\r'; // On windows, send \r\n, on Linux only \r
4950 + terminal.attemptWebRTC = attemptWebRTC;
4951 + terminal.onStateChanged = onTerminalStateChange;
4952 + terminal.onConsoleMessageChange = function () {
4953 + p12clearConsoleMsg();
4954 + if (terminal.consoleMessage) {
4955 + QH('p12TermConsoleMsg', EscapeHtml(terminal.consoleMessage).split('\n').join('<br />'));
4956 + QV('p12TermConsoleMsg', true);
4957 + p12TermConsoleMsgTimer = setTimeout(p12clearConsoleMsg, 8000);
4958 + }
4959 + }
4960 + terminal.Start(terminalNode._id);
4961 + terminal.contype = 1;
4962 + terminal.m.terminalEmulation = 0;
4963 + terminal.m.fxEmulation = 0;
4964 + Q('id_ttypebutton').value = terminalEmulations[0];
4965 + }
4966 + } else {
4967 + //QH('Term', '');
4968 + terminal.Stop();
4969 + terminal = null;
4970 + }
4971 + Q('connectbutton2').blur(); // Deselect the connect button so the button does not get key presses.
4972 + }
4973 +
4974 + var terminalEmulations = ["Terminal UTF8", "ASCII estendido", "Intel ASCII"];
4975 + function termToggleType() {
4976 + if (!terminal || xxdialogMode) return;
4977 + terminal.m.terminalEmulation = (terminal.m.terminalEmulation + 1) % 3;
4978 + Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
4979 + Q('id_ttypebutton').blur(); // Deselect the connect button so the button does not get key presses.
4980 + }
4981 +
4982 + var fxEmulations = ["Intel (F10 = ESC+[OM)", "Alternativo (F10 = ESC + 0)", "VT100+ (F10 = ESC+[OY)"];
4983 + function termToggleFx() {
4984 + if (!terminal || xxdialogMode) return;
4985 + terminal.m.fxEmulation = (terminal.m.fxEmulation + 1) % 3;
4986 + Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
4987 + Q('id_tfxkeysbutton').blur(); // Deselect the connect button so the button does not get key presses.
4988 + }
4989 +
4990 + function termToggleCr() {
4991 + if (!terminal || xxdialogMode) return;
4992 + if (terminal.m.lineFeed == '\n') { terminal.m.lineFeed = '\r\n'; } else { terminal.m.lineFeed = '\n'; }
4993 + Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n') ? "CR + LF" : "LF";
4994 + }
4995 +
4996 + function termSendKey(key, id) {
4997 + if (!terminal || xxdialogMode) return;
4998 + terminal.m.TermSendKey(key);
4999 + Q(id).blur(); // Deselect the connect button so the button does not get key presses.

This file is too large to show in full.

views/translations/default-mobile-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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 rel="shortcut icon"type=image/x-icon href={{{domainurl}}}favicon.ico><script src=scripts/common-0.0.1.js></script><script src=scripts/meshcentral.js></script><script src=scripts/agent-redir-ws-0.1.1.js></script><script src=scripts/agent-desktop-0.0.2.js></script><script src=scripts/amt-0.2.0.js></script><script src=scripts/amt-redir-ws-0.1.0.js></script><script src=scripts/amt-desktop-0.0.2.js></script><script src=scripts/zlib.js></script><script src=scripts/zlib-inflate.js></script><script src=scripts/zlib-adler32.js></script><script src=scripts/zlib-crc32.js></script><script keeplink=1 src=scripts/filesaver.js></script><title>{{{title}}}</title><style>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}.i1{background:url(../images/icons50.png) 0 0;height:50px;width:50px;border:none}.i2{background:url(../images/icons50.png) -50px 0;height:50px;width:50px;border:none}.i3{background:url(../images/icons50.png) -100px 0;height:50px;width:50px;border:none}.i4{background:url(../images/icons50.png) -150px 0;height:50px;width:50px;border:none}.i5{background:url(../images/icons50.png) -200px 0;height:50px;width:50px;border:none}.i6{background:url(../images/icons50.png) -250px 0;height:50px;width:50px;border:none}.m0{background:url(../images/images16.png) -32px 0;height:16px;width:16px;border:none;float:left}.m1{background:url(../images/images16.png) -16px 0;height:16px;width:16px;border:none;float:left}.m2{background:url(../images/images16.png) -96px 0;height:16px;width:16px;border:none;float:left}.m3{background:url(../images/images16.png) -112px 0;height:16px;width:16px;border:none;float:left}.gray{filter:gray;-webkit-filter:grayscale(100%) opacity(60%)}.DevSt{padding-left:5px;border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:#ddd}.noselect{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fileIcon1{background:url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb49Y2Sj9LT2f///yH5BAEAAAMALAAAAAAQABAAAAImnI+py+1vhJwyUYAzHTL4D3qdlJWaIFJqmKod607sDKIiDUP63hQAOw==);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.fileIcon2{background:url(data:image/gif;base64,R0lGODlhEAAQAJEDAM2xV/Xur+XPgP///yH5BAEAAAMALAAAAAAQABAAAAJD3ISZIGHWUGihznesYDYATFVM+D2hJ4lgN1olxALAtAlmPCJvuMmJd6PJckDYwicrHhTD5o7plJmg0Uc0asNMkphHAQA7);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.fileIcon3{background:url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb19IGBgbq6uv///yH5BAEAAAMALAAAAAAQABAAAAIy3ISpxgcPH2ouQgFEw1YmxnUXKEaaEZZnVWZk66JwzKpvuwZzwOgwb/C1gIOA8Yg8DgoAOw==);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.fileIcon4{background:url(../images/meshicon16.png);height:16px;width:16px;cursor:pointer;border:none;float:left;margin-top:1px}.filelist{-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;cursor:default;-khtml-user-drag:element;background-color:#fff;clear:both}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;margin:0;padding:0;border:0;color:#000;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) 0 0;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"><div style="width:calc(100% - 50px);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><img id=topMenuIcon class=noselect style=position:absolute;right:0;top:10px;bottom:50px;color:#c8c8c8;font-size:44px;margin-right:8px;cursor:pointer;display:none onclick=topMenu() src=/images/3bars-30.png width=30 height=30></div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%><div id=column_l style=width:100%;padding:0;position:absolute;bottom:0;top:0><div id=p0 style=display:none;width:100%;height:100%><div style=display:flex;align-items:center;width:100%;height:100%><div id=p0message style=text-align:center;width:100%><span id=p0span>Servidor desconectado</span>,<href onclick=reload() style=cursor:pointer><u>clique para reconectar</u></href>.</div></div></div><div id=p1 style=display:none;width:100%;height:100%><div style=display:flex;align-items:center;width:100%;height:100%><div id=p1message style=text-align:center;width:100%></div></div></div><div id=p2 style=display:none><div id=xdevices></div></div><div id=p3 style=display:none;position:absolute;bottom:0;top:0;width:100%><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div><td><img src=/images/user-50.png width=50 height=50><td><div style=margin-left:5px><strong style=font-size:large><span id=p3userName></span></strong><br></div></table><div id=p3info style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%><div style=margin-left:8px><div id=p3AccountActions><p><strong>Segurança da Conta</strong><div style=margin-left:9px;margin-bottom:8px><div id=manageAuthApp style=margin-top:5px;display:none><a onclick=account_manageAuthApp() style=cursor:pointer>Gerenciar aplicativo autenticador</a></div><div id=manageOtp style=margin-top:5px;display:none><a onclick=account_manageOtp(0) style=cursor:pointer>Gerenciar códigos de backup</a></div></div><p><strong>Ações da Conta</strong><div style=margin-left:9px;margin-bottom:8px><div style=margin-top:5px><span id=verifyEmailId style=display:none><a onclick=account_showVerifyEmail() style=cursor:pointer>Verificar email</a></span></div><div style=margin-top:5px><span id=changeEmailId style=display:none><a onclick=account_showChangeEmail() style=cursor:pointer>Mude o endereço de email</a></span></div><div style=margin-top:5px><a onclick=account_showChangePassword() style=cursor:pointer>Mudar senha</a><span id=p2nextPasswordUpdateTime></span></div><div style=margin-top:5px><a onclick=account_showDeleteAccount() style=cursor:pointer>Deletar conta</a></div></div><br style=clear:both></div><strong>Grupos de dispositivos</strong> <span id=p3createMeshLink1>( <a onclick=account_createMesh() style=cursor:pointer><img src=images/icon-addnew.png width=12 height=12 border=0> Novo</a> )</span><br><br><div id=p3meshes></div><div id=p3noMeshFound style=margin-left:9px;display:none>Nenhum grupo de dispositivos.<span id=p3createMeshLink2> <a onclick=account_createMesh() style=cursor:pointer><strong>Comece aqui!</strong></a></span></div><br style=clear:both></div></div></div><div id=p5 style=display:none><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div><td><img src=/images/user-50.png width=50 height=50><td><div style=margin-left:5px><strong style=font-size:large>Meus arquivos</strong><br></div></table><div id=p5myfiles style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%><table id=p5toolbar style=width:100%;height:78px cellpadding=0 cellspacing=0><tr><td style=width:100%;background-color:#d3d9d6;text-align:left;padding:4px valign=bottom><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p5FolderUp disabled onclick=p5folderup() value=Acima> <input type=button style="width:calc(100%/5 - 5px)"id=p5SelectAllButton disabled onclick=p5selectallfile() value="Selecionar tudo"onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5RenameFileButton disabled value=Renomear onclick=p5renamefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5DeleteFileButton disabled value=Deletar onclick=p5deletefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5NewFolderButton disabled value=Pasta onclick=p5createfolder() onkeypress=return!1 onkeydown=return!1></div><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p5UploadButton disabled value=Envio onclick=p5uploadFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5CutButton disabled value=Cortar onclick=p5copyFile(1) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5CopyButton disabled value=Copiar onclick=p5copyFile(0) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5PasteButton disabled value=Colar onclick=p5pasteFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p5RefreshButton value=Atualizar onclick=p5refreshFiles() onkeypress=return!1 onkeydown=return!1></div><tr><td style=background-color:#e4e9e7;height:28px><table style=width:100%><tr><td id=p5currentpath style=overflow:hidden;padding-left:4px;padding-top:2px><td style=text-align:right;padding-right:4px><select id=p5sortdropdown onchange=updateFiles()><option value=1 selected>Classificar por nome<option value=2>Classificar por tamanho<option value=3>Classificar por data<option value=4>Decrescente por nome<option value=5>Decrescente por tamanho<option value=6>Descrescente por data</select></table></table><div id=p5filetable style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none"><span id=p5files></span></div><table id=p5toolbarBottom style=width:100%;height:22px;position:absolute;bottom:0;background-color:#d3d9d6 cellpadding=0 cellspacing=0><tr><td style=text-align:left;padding:3px>&nbsp;<span id=p5bottomstatus></span><td id=p5rightOfButtons style=text-align:right;padding:3px></table></div></div><div id=p10 style=display:none;position:absolute;bottom:0;top:0;width:100%;overflow:hidden><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0;position:absolute;top:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div><td><a id=MainComputerImage style=cursor:pointer onclick=p10showiconselector()></a><td><div style=margin-left:5px><strong><span id=p10deviceName></span></strong><br><span id=MainComputerState></span></div></table><div id=p10general style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%><div id=p10html style=margin-left:8px;margin-right:8px></div><div id=p10html2></div><div id=p10html3></div></div><div id=p10desktop style=overflow:hidden;position:absolute;top:55px;bottom:0;width:100%;display:none><div id=deskarea1 style=position:absolute;top:0;width:100%;height:25px><div style=padding-top:2px;padding-bottom:2px;background:silver><div style=float:right;text-align:right><span id=p14power></span>&nbsp; <input id=DeskSoftInput style=width:25px;display:none;opacity:.2 onblur=toggleSoftKeys(0) onkeypress="return ondeskkeypress(event)"onkeydown="return ondeskkeydown(event)"onkeyup="return ondeskkeyup(event)"></div><div style=margin-left:3px><input type=button id=connectbutton1 value=Conectar onclick=connectDesktop(event,1) onkeypress=return!1 onkeydown=return!1 disabled> <input type=button id=connectbutton1h value="Conectar HW"onclick=connectDesktop(event,2) onkeypress=return!1 onkeydown=return!1 disabled> <input type=button id=disconnectbutton1 value=Desconectar onclick=connectDesktop(event,0) onkeypress=return!1 onkeydown=return!1> <span id=deskstatus>Desconectado</span></div></div></div><div id=deskarea3 style="position:absolute;top:25px;width:100%;height:calc(100% - 50px)"><div id=deskarea3x style=background:#000;text-align:center;height:100%;position:relative><div id=DeskParent style=height:100%><canvas id=Desk width=640 height=200 style=width:100%;-ms-touch-action:none;margin-left:0 oncontextmenu=return!1 onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event) onmousewheel=dmousewheel(event)></canvas></div><div id=DeskTools style="position:absolute;width:400px;height:100%;background-color:gray;top:0;right:0;border-left:2px solid #d3d3d3;display:none"><a id=DeskToolsRefreshButton style=float:right;padding:3px;cursor:pointer onclick=refreshDeskTools()>Atualizar</a><div id=DeskToolsBar style="position:absolute;padding:3px;border-radius:3px 3px 0 0;top:5px;left:4px;bottom:26px;background-color:#d3d3d3;cursor:pointer">Processos</div><div style=position:absolute;top:26px;left:4px;right:4px;bottom:4px;background-color:#d3d3d3;text-align:left><div style="border-bottom:1px solid #a9a9a9;padding:3px"><a style=width:50px;padding-right:5px;float:left;cursor:pointer onclick=sortProcess(0)>PID</a><a style=cursor:pointer onclick=sortProcess(1)>Nome</a></div><div id=DeskToolsProcesses style=overflow-y:scroll;position:absolute;top:24px;bottom:0;width:100%></div></div></div></div></div><div id=deskarea4 style=position:absolute;bottom:0;width:100%;height:25px><div style=padding-top:2px;padding-bottom:2px;background:silver><div style=float:right;text-align:right><select id=termdisplays style=display:none onchange=deskSetDisplay(event) onclick=deskGetDisplayNumbers(event)></select>&nbsp; <span id=DeskToastButton><img src=images/icon-notify.png onclick=deviceToastFunction() height=16 width=16 style=padding-top:2px></span>&nbsp;</div><div><input id=deskActionsBtn type=button style=margin-left:3px onkeypress=return!1 onkeydown=return!1 value=Ações onclick=deviceActionFunction()> <input type=button value=Configurações onkeypress=return!1 onkeydown=return!1 onclick=showDesktopSettings()> <input type=button onkeypress=return!1 onkeydown=return!1 value="Ações de energia (Ligar/Desligar)"onclick=showPowerActionDlg() style=display:none> <input id=DeskSpecialKeys type=button value="Chaves especiais"onkeypress=return!1 onkeydown=return!1 onclick=sendSpecialKeys()> <input id=DeskSoftKeys type=button value=Teclado onkeypress=return!1 onkeydown=return!1 onclick=toggleSoftKeys(1)> <label><span id=DeskControlSpan style=display:none><input id=DeskControl type=checkbox onkeypress=return!1 onkeydown=return!1>Entrada</span></label></div></div></div></div><div id=p10files style=overflow-y:scroll;position:absolute;top:55px;bottom:0;width:100%;display:none><table id=p13toolbar style=width:100%;height:111px cellpadding=0 cellspacing=0><tr><td style="background-color:silver;border-bottom:2px solid #000;padding:2px"><div style=float:right;text-align:right><input id=filesActionsBtn type=button onkeypress=return!1 onkeydown=return!1 value=Ações onclick=deviceActionFunction() style=margin-right:2px></div><div style=margin-left:2px><input id=p13AutoConnect value="Conexão automática"onclick=autoConnectFiles(event) onkeypress=return!1 onkeydown=return!1 type=button style=display:none> <input id=p13Connect value=Conectar onclick=connectFiles(event) onkeypress=return!1 onkeydown=return!1 type=button> <span id=p13Status>Desconectado</span></div><tr><td style=width:100%;background-color:#d3d9d6;text-align:left;padding:4px valign=bottom><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p13FolderUp disabled onclick=p13folderup() value=Acima> <input type=button style="width:calc(100%/5 - 5px)"id=p13SelectAllButton disabled onclick=p13selectallfile() value="Selecionar tudo"onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13RenameFileButton disabled value=Renomear onclick=p13renamefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13DeleteFileButton disabled value=Deletar onclick=p13deletefile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13NewFolderButton disabled value=Pasta onclick=p13createfolder() onkeypress=return!1 onkeydown=return!1></div><div style=width:100%;text-align:center><input type=button style="width:calc(100%/5 - 5px)"id=p13UploadButton disabled value=Envio onclick=p13uploadFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13CutButton disabled value=Cortar onclick=p13copyFile(1) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13CopyButton disabled value=Copiar onclick=p13copyFile(0) onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13PasteButton disabled value=Colar onclick=p13pasteFile() onkeypress=return!1 onkeydown=return!1> <input type=button style="width:calc(100%/5 - 5px)"id=p13RefreshButton disabled value=Atualizar onclick=p13folderup(9999) onkeypress=return!1 onkeydown=return!1></div><tr><td style=background-color:#e4e9e7;height:28px><table style=width:100%><tr><td id=p13currentpath style=overflow:hidden;padding-left:4px;padding-top:2px><td style=text-align:right;padding-right:4px><select id=p13sortdropdown onchange=p13updateFiles()><option value=1 selected>Classificar por nome<option value=2>Classificar por tamanho<option value=3>Classificar por data<option value=4>Decrescente por nome<option value=5>Decrescente por tamanho<option value=6>Descrescente por data</select></table></table><div id=p13filetable style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none"><span id=p13files></span></div><table id=p13toolbarBottom style=width:100%;height:22px;position:absolute;bottom:0 cellpadding=0 cellspacing=0><tr><td style=text-align:left;padding:3px;text-align:center;background-color:#d3d9d6>&nbsp;<span id=p13bottomstatus></span></table></div></div><div id=p20 style=display:none;position:absolute;bottom:0;top:0;width:100%><table cellspacing=0 style=margin:0;padding:0;border-spacing:0;border:0><tr style=padding:0><td style=padding:0;color:#c8c8c8;text-align:center;cursor:pointer width=60px valign=top onclick=goBack()><div style=padding:0;background-color:#036;width:10px;height:10px;float:right;border:0><div style="background-color:#fff;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid #fff;border-bottom:1px solid #fff"></div></div><div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div><td onclick=p20editmesh(1)><img src=/images/meshicon50.png width=50 height=50><td onclick=p20editmesh(1)><div style=margin-left:5px><strong style=font-size:large><span id=p20meshName></span></strong><br></div></table><div id=p20info style=margin-left:8px;margin-right:8px></div></div></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table id=footerMenu cellpadding=0 cellspacing=0 style=height:32px;width:100%;color:#fff;cursor:pointer;table-layout:fixed></table></div></div><div id=dialog style="z-index:1000;background-color:#eee;box-shadow:0 0 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:90px;width:300px;display:none"><div style="width:100%;background-color:#036;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 id=dialog3 style=margin:auto;margin:3px><select id=deskkeys style=width:100%><option value=10>CTRL+ALT+DEL<option value=11>Tab<option value=5>Win<option value=0>Win+Down<option value=1>Win+Up<option value=2>Win+L<option value=3>Win+M<option value=4>Shift+Win+M<option value=6>Win+R<option value=7>Alt-F4<option value=8>CTRL-W<option value=9>Alt-Tab</select></div><div id=dialog7 style=margin:auto;margin:3px><div id=d7meshkvm><h4 style="width:100%;border-bottom:1px solid gray">Área de trabalho remota do agente</h4><div style="margin:3px 0 3px 0"><select id=d7bitmapquality style=float:right;width:200px;height:20px dir=rtl></select><div style=height:20px>Qualidade</div></div><div style="margin:3px 0 3px 0"><select id=d7bitmapscaling style=float:right;width:200px;height:20px dir=rtl><option selected value=1024>100%<option value=896>87.5%<option value=768>75%<option value=640>62.5%<option value=512>50%<option value=384>37..5%<option value=256>25%<option value=128>12.5%</select><div style=height:20px>Dimensionamento</div></div><div style="margin:3px 0 3px 0"><select id=d7framelimiter style=float:right;width:200px;height:20px dir=rtl><option selected value=50>Rápido<option value=100>Médio<option value=400>Lento<option value=1000>Muito devagar</select><div style=height:20px>Taxa</div></div></div><div id=d7amtkvm><h4 style="width:100%;border-bottom:1px solid gray">Intel® AMT Hardware KVM</h4><div style=height:26px><select id=d7desktopmode style=float:right;width:200px><option value=1>RLE8, mais rápido<option value=2>RLE16, Recomendado<option value=3>RAW8, lento<option value=4>RAW16, muito lento</select><div>Codificação</div></div><div style=height:60px><div style="float:right;border:1px solid #666;width:200px;height:60px;overflow-y:scroll;background-color:#fff"><label><input type=checkbox id=d7showfocus>Mostrar ferramenta de foco</label><br><label><input type=checkbox id=d7showcursor>Mostrar Cursor do Mouse Local</label><br></div><div>Outro</div></div></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><div id=topMenu style="z-index:1000;background-color:#eee;box-shadow:0 0 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:0 0 5px 5px;position:fixed;top:50px;right:5px;width:170px;display:none"><div style="padding:12px;border-top:1px solid gray;color:#000;cursor:pointer"onclick=topMenu(2)>Meus arquivos</div><div style="padding:12px;border-top:1px solid gray;color:#000;cursor:pointer"onclick=topMenu(1)>Minha conta</div><div id=logoutMenuOption><a href=/logout><div style="padding:12px;border-top:1px solid gray;color:#000;cursor:pointer">Sair</div></a></div></div><iframe name=fileUploadFrame style=display:none></iframe><script>"use strict";var webState="{{{webstate}}}";for(var i in""!=webState&&(webState=JSON.parse(decodeURIComponent(webState))),webState)localStorage.setItem(i,webState[i]);webState.loctag||localStorage.removeItem("loctag");var files,args=parseUriArgs(),debugLevel=parseInt("{{{debuglevel}}}"),features=parseInt("{{{features}}}"),sessionTime=parseInt("{{{sessiontime}}}"),domain="{{{domain}}}",domainUrl="{{{domainurl}}}",authCookie="{{{authCookie}}}",authRelayCookie="{{{authRelayCookie}}}",authCookieRenewTimer=null,meshserver=null,xdr=null,serverinfo=null,nodes=[],meshes={},filetree={},userinfo=null,users=(serverinfo=null,null),nodeShortIdent=0,serverPublicNamePort="{{{serverDnsName}}}:{{{serverPublicPort}}}",debugmode=!1,attemptWebRTC=0!=(128&features),StatusStrs=["Desconectado","Conectando...","Configurando...","Conectado","Intel&reg; AMT conectado"],passRequirements="{{{passRequirements}}}";""!=passRequirements&&(passRequirements=JSON.parse(decodeURIComponent(passRequirements)));var sessionActivity=Date.now();function startup(){if(0==(32&features)){var e=null;try{e=top.location.toString().toLowerCase()}catch(e){}if(top!=self&&(null==e||0==top.active))return void(top.location=self.location)}if(!args.locale){var t=getstore("loctag",0);null!=t&&"*"!=t&&(args.locale=t)}(window.onresize=center)(),QV("changeEmailId",0==(2097152&features)),QH("p1message","Conectando..."),go(1),(meshserver=MeshServerCreateControl(domainUrl,authCookie)).onStateChanged=onStateChanged,meshserver.onMessage=onMessage,meshserver.Start();var o=localStorage.getItem("desktopsettings");null!=o&&(desktopsettings=JSON.parse(o)),applyDesktopSettings()}function onStateChanged(e,t,o,n){if(0==t){if(setDialogMode(0),go(0),"noauth"==n)return void QH("p0span","Não foi possível executar a autenticação");2==o?setTimeout(serverPoll,5e3):QH("p0span","Não foi possível conectar o soquete da web"),null!=authCookieRenewTimer&&(clearInterval(authCookieRenewTimer),authCookieRenewTimer=null)}else 2==t&&(meshserver.send({action:"meshes"}),meshserver.send({action:"nodes"}),meshserver.send({action:"files"}),xxcurrentView<2&&go(2),authCookieRenewTimer=setInterval(function(){meshserver.send({action:"authcookie"})},18e5));QV("topMenuIcon",2==t)}function serverPoll(){xdr=null;try{xdr=new XDomainRequest}catch(e){}(xdr=xdr||new XMLHttpRequest).open("HEAD",window.location.href),xdr.timeout=15e3,xdr.onload=function(){reload()},xdr.onerror=xdr.ontimeout=function(){setTimeout(serverPoll,1e4)},xdr.send()}function updateSelf(){if(QV("verifyEmailId",!0!==userinfo.emailVerified&&null!=userinfo.email&&1==serverinfo.emailcheck),QV("manageAuthApp",4096&features),QV("manageOtp",0!=(4096&features)&&(1==userinfo.otpsecret||0<userinfo.otphkeys)),QV("p3createMeshLink1",!1),QV("p3createMeshLink2",!1),"number"==typeof userinfo.passchange)if(-1==userinfo.passchange)QH("p2nextPasswordUpdateTime","- Redefinir no próximo login.");else if(null!=passRequirements&&"number"==typeof passRequirements.reset){var e=userinfo.passchange+86400*passRequirements.reset-Math.floor(Date.now()/1e3);e<0?QH("p2nextPasswordUpdateTime","- Redefinir no próximo login."):e<3600?QH("p2nextPasswordUpdateTime",format("- Redefinir em {0} minuto {1}.",Math.floor(e/60),addLetterS(Math.floor(e/60)))):e<86400?QH("p2nextPasswordUpdateTime",format("- Redefinir em {0} hora {1}.",Math.floor(e/3600),addLetterS(Math.floor(e/3600)))):QH("p2nextPasswordUpdateTime",format("- Redefinir em {0} dia {1}."),Math.floor(e/86400),addLetterS(Math.floor(e/86400)))}}function addLetterS(e){return 1<e?"s":""}function setSessionActivity(){sessionActivity=Date.now()}function checkIdleSessionTimeout(){Date.now()-sessionActivity>serverinfo.timeout&&(window.location.href="logout")}function onMessage(e,t){switch(t.action){case"serverinfo":(serverinfo=t.serverinfo).timeout&&(setInterval(checkIdleSessionTimeout,1e4),checkIdleSessionTimeout()),QV("p3AccountActions",0==(4&features)&&0==serverinfo.domainauth),QV("logoutMenuOption",0==(4&features)&&0==serverinfo.domainauth);break;case"authcookie":authCookie=t.cookie,authRelayCookie=t.rcookie;break;case"userinfo":userinfo=t.userinfo,QH("p3userName",userinfo.name),updateSelf();break;case"users":for(var o in users={},t.users)users[t.users[o]._id]=t.users[o];updateUsers();break;case"wssessioncount":wssessions=t.wssessions,updateUsers();break;case"meshes":for(var o in meshes={},t.meshes)meshes[t.meshes[o]._id]=t.meshes[o];updateMeshes(),updateDevices();break;case"files":filetree=setupBackPointers(t.filetree),updateFiles();break;case"nodes":for(var o in nodes=[],t.nodes)for(var n in t.nodes[o])meshes[o]?(t.nodes[o][n].namel=t.nodes[o][n].name.toLowerCase(),t.nodes[o][n].rname?t.nodes[o][n].rnamel=t.nodes[o][n].rname.toLowerCase():t.nodes[o][n].rnamel=t.nodes[o][n].namel,t.nodes[o][n].meshnamel=meshes[o].name.toLowerCase(),t.nodes[o][n].meshid=o,t.nodes[o][n].state=t.nodes[o][n].state?t.nodes[o][n].state:0,t.nodes[o][n].desc=t.nodes[o][n].desc,t.nodes[o][n].icon||(t.nodes[o][n].icon=1),t.nodes[o][n].ident=++nodeShortIdent,nodes.push(t.nodes[o][n])):console.log("Invalid mesh (1): "+o);updateDevices(),0==xxcurrentView&&go(parseInt("{{viewmode}}")),gotoDevice("{{currentNode}}",parseInt("{{viewmode}}"));break;case"powertimeline":if(t.nodeid!=powerTimelineReq)break;powerTimelineNode=t.nodeid,powerTimeline=t.timeline,powerTimelineUpdate=Date.now()+3e5,currentNode._id==t.nodeid&&drawDeviceTimeline();break;case"otpauth-request":if(2==xxdialogMode&&"otpauth-request"==xxdialogTag){var i=t.secret;52==i.length?i=i.split(/(.............)/).filter(Boolean).join(" "):32==i.length&&(i=(i=i.split(/(....)/).filter(Boolean).join(" ")).substring(0,20)+"<br/>"+i.substring(20)),QH("d2optinfo",'Install <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" rel="noreferrer noopener" target=_blank>Google Authenticator</a> or a compatible application, use <a href="\' + message.url + \'" rel="noreferrer noopener" target=_blank> this link</a> or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login.<br /><br /><div style=width:100%;text-align:center><tt id=d2optsecret secret="'+t.secret+'" style=font-size:15px>'+i+'</tt><br /><br />Token: <input type=text onkeypress="return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></div>'),QV("idx_dlgOkButton",!0),QE("idx_dlgOkButton",!1),Q("d2otpauthinput").focus()}break;case"otpauth-setup":if(xxdialogMode)return;setDialogMode(2,"Autenticador de aplicativo",1,null,t.success?"<b style=color:green> ativação de login em duas etapas </b>. Agora você precisará de um token válido para fazer login novamente.":"<b style=color:red> falha na ativação do login em duas etapas </b>. Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto.");break;case"otpauth-clear":if(xxdialogMode)return;setDialogMode(2,"Autenticador de aplicativo",1,null,t.success?"<b style=color:green>Ativação de login em duas etapas removida</b>. Você pode reativar esse recurso a qualquer momento.":"<b style=color:red> falha na remoção da ativação do login em duas etapas </b>. Tente novamente.");break;case"otpauth-getpasswords":if(xxdialogMode)return;var a="Os tokens únicos podem ser usados como autenticação secundária. Gere um conjunto, imprima-os e mantenha-os em um local seguro.";if(a+="<div style='border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px'><div style='padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold'><table style=width:100%;text-align:center>",t.passwords){var s=0;for(var l in t.passwords){++s%2&&(a+="<tr>");for(var r=""+t.passwords[l].p;r.length<8;)r="0"+r;!0===t.passwords[l].u?a+="<td>"+r.substring(0,4)+"&nbsp;"+r.substring(4):a+="<td><strike style=color:#BBB>"+r.substring(0,4)+"&nbsp;"+r.substring(4)}}else a+="<tr><td>Nenhum token ativo";a+="</table></div></div><br />",a+="<div><input type=button value='Fechar' onclick=setDialogMode(0) style=float:right></input>",a+="<input type=button value='Novos tokens' onclick='account_manageOtp(1);'></input>",null!=t.passwords&&(a+="<input type=button value='Limpo' onclick='account_manageOtp(2);'></input>"),setDialogMode(2,"Gerenciar códigos de backup",8,null,a+="</div><br />","otpauth-manage");break;case"event":if(t.event.noact)break;switch(t.event.action){case"userWebState":if(null!=localStorage){var d=JSON.parse(t.event.state);for(var l in d)localStorage.setItem(l,d[l]);null!=d.loctag&&d.loctag!=oldLoctag&&(null!=d.loctag?args.locale=d.loctag:delete args.locale,updateDevices(),updateMeshes())}break;case"accountchange":if(userinfo.name==t.event.account.name){var p=t.event.account.siteadmin?t.event.account.siteadmin:0,c=userinfo.siteadmin?userinfo.siteadmin:0;(t.event.account.quota!=userinfo.quota||0==(8&userinfo.siteadmin)&&0!=(8&t.event.account.siteadmin))&&meshserver.send({action:"files"}),userinfo=t.event.account,c!=p&&updateSiteAdmin(),updateSelf()}break;case"createmesh":null!=t.event.links[userinfo._id]&&(meshes[t.event.meshid]={_id:t.event.meshid,name:t.event.name,mtype:t.event.mtype,desc:t.event.desc,links:t.event.links},updateMeshes(),updateDevices(),meshserver.send({action:"files"}));break;case"meshchange":if(null==meshes[t.event.meshid])meshes[t.event.meshid]={_id:t.event.meshid,name:t.event.name,mtype:t.event.mtype,desc:t.event.desc,links:t.event.links},meshserver.send({action:"nodes"});else{if(meshes[t.event.meshid].name!=t.event.name)for(var l in meshes[t.event.meshid].name=t.event.name,nodes)nodes[l].meshid==t.event.meshid&&(nodes[l].meshnamel=t.event.name.toLowerCase());if(meshes[t.event.meshid].desc=t.event.desc,meshes[t.event.meshid].links=t.event.links,null==meshes[t.event.meshid].links[userinfo._id]){20==xxcurrentView&&currentMesh==meshes[t.event.meshid]&&go(2),delete meshes[t.event.meshid];var u=[];for(var l in nodes)nodes[l].meshid!=t.event.meshid&&u.push(nodes[l]);nodes=u,10<=xxcurrentView&&xxcurrentView<20&&currentNode&&currentNode.meshid==t.event.meshid&&(setDialogMode(0),go(2))}}updateMeshes(),updateDevices(),meshserver.send({action:"files"}),20==xxcurrentView&&currentMesh._id==t.event.meshid&&p20updateMesh();break;case"deletemesh":meshes[t.event.meshid]&&(delete meshes[t.event.meshid],updateMeshes(),meshserver.send({action:"files"}));u=[];for(var l in nodes)nodes[l].meshid!=t.event.meshid&&u.push(nodes[l]);nodes=u,updateDevices(),20<=xxcurrentView&&xxcurrentView<30&&currentMesh._id==t.event.meshid&&(setDialogMode(0),go(2)),10<=xxcurrentView&&xxcurrentView<20&&currentNode&&currentNode.meshid==t.event.meshid&&(setDialogMode(0),go(2));break;case"addnode":var m=t.event.node;if(!meshes[m.meshid])break;if(null!=getNodeFromId(m._id))break;m.namel=m.name.toLowerCase(),m.rname?m.rnamel=m.rname.toLowerCase():m.rnamel=m.namel,m.meshnamel=meshes[m.meshid].name.toLowerCase(),m.state=0,m.icon||(m.icon=1),m.ident=++nodeShortIdent,nodes.push(m),updateDevices();break;case"removenode":var h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h){m=nodes[h];currentNode==m&&(10<=xxcurrentView&&xxcurrentView<20&&(setDialogMode(0),go(2)),currentNode=null),nodes.splice(h,1),updateDevices()}break;case"changenode":h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h)(m=nodes[h]).name=t.event.node.name,m.rname=t.event.node.rname,m.host=t.event.node.host,m.desc=t.event.node.desc,m.publicip=t.event.node.publicip,m.iploc=t.event.node.iploc,m.wifiloc=t.event.node.wifiloc,m.gpsloc=t.event.node.gpsloc,m.tags=t.event.node.tags,m.userloc=t.event.node.userloc,null!=t.event.node.agent&&(null==m.agent&&(m.agent={}),null!=t.event.node.agent.ver&&(m.agent.ver=t.event.node.agent.ver),null!=t.event.node.agent.id&&(m.agent.id=t.event.node.agent.id),null!=t.event.node.agent.caps&&(m.agent.caps=t.event.node.agent.caps),null!=t.event.node.agent.core?m.agent.core=t.event.node.agent.core:m.agent.core&&delete m.agent.core,m.agent.tag=t.event.node.agent.tag),null!=t.event.node.intelamt&&(null==m.intelamt&&(m.intelamt={}),null!=t.event.node.intelamt.state&&(m.intelamt.state=t.event.node.intelamt.state),null!=t.event.node.intelamt.host&&(m.intelamt.user=t.event.node.intelamt.host),null!=t.event.node.intelamt.user&&(m.intelamt.user=t.event.node.intelamt.user),null!=t.event.node.intelamt.tls&&(m.intelamt.tls=t.event.node.intelamt.tls),null!=t.event.node.intelamt.ver&&(m.intelamt.ver=t.event.node.intelamt.ver),null!=t.event.node.intelamt.tag&&(m.intelamt.tag=t.event.node.intelamt.tag),null!=t.event.node.intelamt.uuid&&(m.intelamt.uuid=t.event.node.intelamt.uuid),null!=t.event.node.intelamt.realm&&(m.intelamt.realm=t.event.node.intelamt.realm)),m.namel=m.name.toLowerCase(),m.rname?m.rnamel=m.rname.toLowerCase():m.rnamel=m.namel,t.event.node.icon&&(m.icon=t.event.node.icon),refreshDevice(m._id),updateDevices();break;case"nodemeshchange":h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h){m=nodes[h];null==meshes[t.event.newMeshId]?(currentNode==m&&(10<=xxcurrentView&&xxcurrentView<20&&(setDialogMode(0),go(2)),currentNode=null),nodes.splice(h,1)):(m.meshid=t.event.newMeshId,m.meshnamel=meshes[t.event.newMeshId].name.toLowerCase()),updateDevices(),refreshDevice(t.event.nodeid)}else{m=t.event.node;if(!meshes[m.meshid])break;m.namel=m.name.toLowerCase(),m.rname?m.rnamel=m.rname.toLowerCase():m.rnamel=m.namel,m.meshnamel=meshes[m.meshid].name.toLowerCase(),m.state=0,m.icon||(m.icon=1),m.ident=++nodeShortIdent,nodes.push(m),updateDevices()}break;case"nodeconnect":h=-1;for(var l in nodes)if(nodes[l]._id==t.event.nodeid){h=l;break}if(-1!=h)(m=nodes[h]).conn=t.event.conn,m.pwr=t.event.pwr,updateDevices();break;case"login":null!=users&&users["user/"+domain+"/"+t.event.username.toLowerCase()]&&(users["user/"+domain+"/"+t.event.username.toLowerCase()].login=t.event.time)}}}function topMenu(e){null!=xxdialogMode&&0!=xxdialogMode&&999!=xxdialogMode||(void 0===e?1==("none"==QS("topMenu").display)?0!=xxdialogMode&&null!=xxdialogMode||(QV("topMenu",!0),xxdialogMode=999):(QV("topMenu",!1),xxdialogMode=0):(QV("topMenu",!1),xxdialogMode=0,1==e&&3!=xxcurrentView&&goForward("account"),2==e&&5!=xxcurrentView&&goForward("files")))}var filetreelinkpath,backStack=[];function goBack(){xxdialogMode||(0<backStack.length&&backStack.pop(),goStack())}function goForward(e){xxdialogMode||(backStack.push(e),goStack())}function goStack(){if(0!=backStack.length){var e=backStack[backStack.length-1],t=e.split("/")[0];"node"==t&&(setupDeviceMenu(0),gotoDevice(e)),"mesh"==t&&gotoMesh(e),"account"==t&&go(3),"devices"==t&&go(2),"files"==t&&go(5)}else go(2)}function updateFooterMenu(e){for(;null!=e&&e.length<3;)e.push({n:""});var t="",o="";if(null!=e)for(var n in e)t+='<td style="cursor:pointer'+(""==o?"":";border-left:solid 1px white")+'" onclick="'+e[n].f+'">'+e[n].n,o=e[n].n;QH("footerMenu","<tr>"+t)}function account_manageAuthApp(){xxdialogMode||0==(4096&features)||(1==userinfo.otpsecret?account_removeOtp():account_addOtp())}function account_addOtp(){xxdialogMode||1==userinfo.otpsecret||0==(4096&features)||(setDialogMode(2,"Autenticador de aplicativo",2,function(){meshserver.send({action:"otpauth-setup",secret:Q("d2optsecret").attributes.secret.value,token:Q("d2otpauthinput").value})},"<div id=d2optinfo>Carregando...</div>","otpauth-request"),meshserver.send({action:"otpauth-request"}))}function account_addOtpCheck(e){var t=6==Q("d2otpauthinput").value.length;QE("idx_dlgOkButton",t),e&&13==e.keyCode&&t&&dialogclose(1)}function account_removeOtp(){xxdialogMode||1!=userinfo.otpsecret||0==(4096&features)||setDialogMode(2,"Autenticador de aplicativo",3,function(){meshserver.send({action:"otpauth-clear"})},"Confirmar remoção do login do aplicativo autenticador em duas etapas?")}function account_manageOtp(e){2==xxdialogMode&&"otpauth-manage"==xxdialogTag&&dialogclose(0),xxdialogMode||1!=userinfo.otpsecret||0==(4096&features)||meshserver.send({action:"otpauth-getpasswords",subaction:e})}function account_showVerifyEmail(){xxdialogMode||1==userinfo.emailVerified||1!=serverinfo.emailcheck||setDialogMode(2,"verificação de e-mail",3,account_showVerifyEmailEx,"Clique em ok para enviar um email de verificação para:<br /><div style=padding:8px><b>"+EscapeHtml(userinfo.email)+"</b></div>Aguarde alguns minutos para receber a verificação.")}function account_showVerifyEmailEx(){meshserver.send({action:"verifyemail",email:userinfo.email})}function account_showChangeEmail(){xxdialogMode||(setDialogMode(2,"Alteração de endereço de email",3,account_changeEmail,addHtmlValue("Email","<input id=dp3email style=width:170px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />")),null!=userinfo.email&&(Q("dp3email").value=userinfo.email),account_validateEmail(),Q("dp3email").focus())}function account_validateEmail(e,t){QE("idx_dlgOkButton",validateEmail(Q("dp3email").value)&&Q("dp3email").value!=userinfo.email),null!=e&&13==e.keyCode&&dialogclose(1)}function account_changeEmail(){meshserver.send({action:"changeemail",email:Q("dp3email").value})}function account_showDeleteAccount(){if(!xxdialogMode){var e="<form method=post><table style=margin-left:10px><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value="+authCookie+" /><tr>";e+="<td align=right>Senha:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>",e+="</tr><tr><td align=right>Senha:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>",e+="</tr></table><div style=padding:10px;margin-bottom:4px>",e+='<input id=account_dlgCancelButton type=button value="Cancelar" style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>',e+='<input id=account_dlgOkButton type=submit value="Ok" style="float:right;width:80px" onclick=dialogclose(1)>',setDialogMode(2,"Deletar Conta",0,null,e+="</div><br /></form>"),account_validateDeleteAccount(),Q("apassword1").focus()}}function account_showChangePassword(){if(xxdialogMode)return!1;var e="<table style=margin-left:10px>";if(e+="<tr><td align=right>"+nobreak("Senha Antiga:")+"</td><td><input id=apassword0 type=password name=apassword0 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b></b></td></tr>",e+="<tr><td align=right>"+nobreak("Nova senha:")+"</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b><span id=dxPassWarn></span></b></td></tr>",e+="<tr><td align=right>"+nobreak("Nova senha:")+"</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>",65536&features&&(e+="<tr><td align=right>Dica de senha</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>"),e+="</table>",passRequirements){var t=[],o=0;for(var n in passRequirements)"reset"!=n&&"hint"!=n&&(t.push(n+":"+passRequirements[n]),o++);0<o&&(e+="<br /><span style=font-size:x-small>"+format("Requisitos: {0}.",t.join(", "))+"</span>")}return setDialogMode(2,"Mudar senha",3,account_showChangePasswordEx,e+="<br />"),Q("apassword0").focus(),account_validateNewPassword(),!1}function account_showChangePasswordEx(){if(Q("apassword1").value==Q("apassword2").value){var e={action:"changepassword",oldpass:Q("apassword0").value,newpass:Q("apassword1").value};65536&features&&(e.hint=Q("apasswordhint").value),meshserver.send(e)}}function account_createMesh(){if(!xxdialogMode)if(4294967295==userinfo.siteadmin||0==(64&userinfo.siteadmin))if(!0===userinfo.emailVerified||1!=serverinfo.emailcheck||4294967295==userinfo.siteadmin)if(!(262144&features)||1==userinfo.otpsecret||0<userinfo.otphkeys||0<userinfo.otpkeys){var e=addHtmlValue("Nome","<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />");e+=addHtmlValue("Tipo","<div style=width:170px;margin:0;padding:0><select id=dp3meshtype style=width:100% onchange=account_validateMeshCreate() ><option value=2>Grupo de agentes de software</option><option value=1>Intel&reg; Apenas AMT</option></select></div>"),setDialogMode(2,"Criar grupo de dispositivo",3,account_createMeshEx,e+=addHtmlValue("Descrição","<div style=width:170px;margin:0;padding:0><textarea id=dp3meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>")),account_validateMeshCreate(),Q("dp3meshname").focus()}else setDialogMode(2,"Segurança da Conta",1,null,'Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para "Minha conta" e veja a seção "Segurança da conta".');else setDialogMode(2,"Segurança da Conta",1,null,'Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para "Minha conta" para alterar e verificar um endereço de email.');else setDialogMode(2,"Novo grupo de dispositivos",1,null,"Esta conta não tem direitos para criar um novo grupo de dispositivos.")}function account_validateMeshCreate(){QE("idx_dlgOkButton",0<Q("dp3meshname").value.length)}function account_createMeshEx(e,t){meshserver.send({action:"createmesh",meshname:Q("dp3meshname").value,meshtype:Q("dp3meshtype").value,desc:Q("dp3meshdesc").value})}function account_validateDeleteAccount(){QE("account_dlgOkButton",0<Q("apassword1").value.length&&Q("apassword1").value==Q("apassword2").value)}function account_validateNewPassword(){var e="",t=0<Q("apassword0").value.length&&0<Q("apassword1").value.length&&Q("apassword1").value==Q("apassword2").value&&Q("apassword0").value!=Q("apassword1").value;if(65536&features&&Q("apasswordhint").value==Q("apassword1").value&&(t=!1),""!=Q("apassword1").value)if(null==passRequirements||""==passRequirements){var o=checkPasswordStrength(Q("apassword1").value);e=80<=o?"<span style=color:green>Strong<span>":60<=o?"<span style=color:blue>&#9679;<span>":"<span style=color:red>&#9679;<span>"}else{0==checkPasswordRequirements(Q("apassword1").value,passRequirements)&&(t=!1,e="<span style=color:red>Política<span>")}QH("dxPassWarn",e),QE("idx_dlgOkButton",t)}function checkPasswordStrength(e){var t=0,o={},n=0,i={digits:/\d/.test(e),lower:/[a-z]/.test(e),upper:/[A-Z]/.test(e),nonWords:/\W/.test(e)};if(!e)return 0;for(var a=0;a<e.length;a++)o[e[a]]=(o[e[a]]||0)+1,t+=5/o[e[a]];for(var s in i)n+=1==i[s]?1:0;return parseInt(t+10*(n-1))}function checkPasswordRequirements(e,t){if(null==t||""==t||"object"!=typeof t)return!0;if(t.min&&e.length<t.min)return!1;if(t.max&&e.length>t.max)return!1;for(var o=0,n=0,i=0,a=0,s=0;s<e.length;s++)/\d/.test(e[s])&&o++,/[a-z]/.test(e[s])&&n++,/[A-Z]/.test(e[s])&&i++,/\W/.test(e[s])&&a++;return!(t.num&&o<t.num)&&(!(t.lower&&n<t.lower)&&(!(t.upper&&i<t.upper)&&!(t.nonalpha&&a<t.nonalpha)))}function updateMeshes(){var e="",t=0;for(i in meshes){t++;var o=meshes[i].links[userinfo._id].rights,n="Direitos parciais";4294967295==o?n="Administrador completo":0==o&&(n="Sem direitos"),e+="<div style=cursor:pointer onclick=goForward('"+i+"')>",e+='<div style="float:left;margin-left:4px"><img src="/images/meshicon50.png" width=50 height=50 /></div>',e+='<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">',e+="<div><div style=padding-left:12px;padding-top:2px><b>"+EscapeHtml(meshes[i].name)+"</b></div><div style=padding-left:12px;padding-top:3px;color:gray>"+n+"</div></div>",e+="</div></div>"}QH("p3meshes",e),QV("p3noMeshFound",0==t)}function gotoMesh(e){null==(currentMesh=meshes[e])&&goBack(),p20updateMesh(),go(20)}var sortorder,filetreelocation=[];function p5refreshFiles(){meshserver.send({action:"files"})}function updateFiles(){if(QV("MainMenuMyFiles",0==(8&features)),0==(8&features)){for(var e,t="",o="",n="<a style=cursor:pointer onclick=p5folderup(0)>Raiz</a>",i="Root",a=filetree,s=1,l=[],r=filetreelinkpath,d=[],p=document.getElementsByName("fc"),c=0;c<p.length;c++)p[c].checked&&d.push(p[c].value);for(var c in filetreelinkpath="",filetreelocation){if(null==a.f||null==a.f[filetreelocation[c]])break;if(l.push(filetreelocation[c]),i+=" / "+filetreelocation[c],1==s){var u=filetreelocation[c].split("/");e=window.location+u[0]+"files/"+u[2],filetreelinkpath+=filetreelocation[c]}else""!=filetreelinkpath&&(filetreelinkpath+="/"+filetreelocation[c],2<s&&(e+="/"+filetreelocation[c]));n+=" / <a style=cursor:pointer onclick=p5folderup("+s+")>"+(null!=(a=a.f[filetreelocation[c]]).n?a.n:filetreelocation[c])+"</a>",s++}filetreelocation=l;var m=i.toLowerCase().startsWith("root / "+userinfo._id+" / public"),h=p5sort_files(a.f);for(var c in h){var g,v=h[c],f=v.n;g=40<(g=f).length?EscapeHtml(f.substring(0,40))+"...":EscapeHtml(f),f=EscapeHtml(f);var k="";null!=v.s&&(k=getFileSizeStr(v.s));var x="";if(v.t<3||4==v.t){x="<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='"+f+"'>&nbsp;<span style=float:right;padding-right:4px>"+(1==v.t||4==v.t?p5getQuotabar(v):"")+"</span><span><div class=fileIcon"+v.t+'></div><a style=cursor:pointer onclick=p5folderset("'+encodeURIComponent(v.nx)+'")>'+g+"</a></span></div>"}else{var y=g,b="";m&&(b=" (<a style=cursor:pointer onclick='p5showPublicLink(\""+e+"/"+v.nx+"\")'>Ligação</a>)"),0<v.s&&(y='<a rel="noreferrer noopener" target="_blank" href="downloadfile.ashx?link='+encodeURIComponent(filetreelinkpath+"/"+v.nx)+'">'+g+"</a>"+b),x="<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='"+v.nx+"'>&nbsp;<span style=float:right;padding-right:4px>"+k+"</span><span><div class=fileIcon"+v.t+"></div>"+y+"</span></div>"}v.t<3?t+=x:o+=x}if(QH("p5rightOfButtons",p5getQuotabar(a)),QH("p5files",t+o),QH("p5currentpath",n),QE("p5FolderUp",0!=filetreelocation.length),QV("p5PublicShare",m),r==filetreelinkpath){p=document.getElementsByName("fc");for(c=0;c<p.length;c++)p[c].checked=0<=d.indexOf(p[c].value)}p5setActions()}}function getNiceSize(e){return e<=0?"Armazenamento excedido":e<2048?format("{0}b restante",e):e<2097152?format("{0}k restante",Math.round(e/1024)):e<2147483648?format("{0}m restante",Math.round(e/1024/1024)):format("{0}g restante",Math.round(e/1024/1024/1024))}function p5getQuotabar(e){for(;1<e.t&&4!=e.t;)e=e.parent;return 1!=e.t&&4!=e.t||null==e.maxbytes?"":getNiceSize(e.maxbytes-e.s)+" <progress style=height:10px;width:100px value="+e.s+" max="+e.maxbytes+" />"}function p5showPublicLink(e){setDialogMode(2,"Link Público",1,null,'<input type=text style=width:100% value="'+e+'" readonly />')}function p5sort_filename(e,t){return e.ln>t.ln?1*sortorder:e.ln<t.ln?-1*sortorder:0}function p5sort_timestamp(e,t){return e.d>t.d?1*sortorder:e.d<t.d?-1*sortorder:0}function p5sort_bysize(e,t){return e.s==t.s?p5sort_filename(e,t):(e.s-t.s)*sortorder}function p5sort_files(e){var t=[],o=Q("p5sortdropdown").value;for(var n in e)e[n].nx=n,null==e[n].n&&(e[n].n=n),e[n].ln=e[n].n.toLowerCase(),t.push(e[n]);return sortorder=1,3<o&&(sortorder=-1,o-=3),1==o?t.sort(p5sort_filename):2==o?t.sort(p5sort_bysize):3==o&&t.sort(p5sort_timestamp),t}function p5setActions(){var e=getFileSelCount(),t=getFileCount(),o=getFileSelCount(!1);QE("p5DeleteFileButton",0<e&&0<filetreelocation.length),QE("p5NewFolderButton",0<filetreelocation.length),QE("p5UploadButton",0<filetreelocation.length),QE("p5RenameFileButton",1==e&&0<filetreelocation.length),QE("p5SelectAllButton",0<t),Q("p5SelectAllButton").value=0<e?"Nenhum":"Todos",QE("p5CutButton",0<o&&e==o),QE("p5CopyButton",0<o&&e==o),QE("p5PasteButton",null!=p5clipboard&&0<p5clipboard.length&&0<filetreelocation.length)}function getFileSelCount(e){for(var t=0,o=document.getElementsByName("fc"),n=0;n<o.length;n++)!o[n].checked||0==e&&"3"!=o[n].attributes.file.value||t++;return t}function getFileSelDirCount(){for(var e=0,t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked&&"999"==t[o].attributes.file.value&&e++;return e}function getFileCount(){return document.getElementsByName("fc").length}function p5selectallfile(){for(var e=0==getFileSelCount(),t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked=e;p5setActions()}function setupBackPointers(e){if(null!=e.f){var t=0,o=0;for(var n in e.f)setupBackPointers(e.f[n]),(e.f[n].parent=e).f[n].s&&(t+=e.f[n].s),e.f[n].c&&(o+=e.f[n].c),3==e.f[n].t&&o++;e.s=t,e.c=o}return e}function getFileSizeStr(e){return 1==e?"1 byte":format("{0} bytes",e)}function p5folderup(e){if(null==e)filetreelocation.pop();else for(;filetreelocation.length>e;)filetreelocation.pop();return updateFiles(),!1}function p5folderset(e){return filetreelocation.push(decodeURIComponent(e)),updateFiles(),!1}function p5createfolder(){setDialogMode(2,"Nova pasta",3,p5createfolderEx,"<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% />"),focusTextBox("p5renameinput"),p5fileNameCheck()}function p5createfolderEx(){meshserver.send({action:"fileoperation",fileop:"createfolder",path:filetreelocation,newfolder:Q("p5renameinput").value})}function p5deletefile(){var e=getFileSelCount(),t=0<getFileSelDirCount()?"<br /><br /><label><input type=checkbox id=p5recdeleteinput>Exclusão recursiva</label><br>":"<input type=checkbox id=p5recdeleteinput style='display:none'>";setDialogMode(2,"Deletar",3,p5deletefileEx,1<e?format("Excluir {0} itens selecionados?",e)+t:"Excluir item selecionado?"+t)}function p5deletefileEx(){for(var e=[],t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked&&e.push(t[o].value);meshserver.send({action:"fileoperation",fileop:"delete",path:filetreelocation,delfiles:e,rec:Q("p5recdeleteinput").checked})}function p5renamefile(){for(var e,t=document.getElementsByName("fc"),o=0;o<t.length;o++)t[o].checked&&(e=t[o].value);setDialogMode(2,"Renomear",3,p5renamefileEx,'<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% value="'+e+'" />',{action:"fileoperation",fileop:"rename",path:filetreelocation,oldname:e}),focusTextBox("p5renameinput"),p5fileNameCheck()}function p5renamefileEx(e,t){t.newname=Q("p5renameinput").value,meshserver.send(t)}function p5fileNameCheck(e){var t=isFilenameValid(Q("p5renameinput").value);QE("idx_dlgOkButton",t),1==t&&e&&13==e.keyCode&&dialogclose(1)}var isFilenameValid=function(){var t=/^[^\\/:\*\?"<>\|]+$/,o=/^\./,n=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i;return function(e){return t.test(e)&&!o.test(e)&&!n.test(e)&&"."!=e[0]}}();function p5uploadFile(){setDialogMode(2,"Subir arquivo",3,p5uploadFileEx,'<form method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame><input type=text name=link style=display:none id=p5uploadpath value="'+encodeURIComponent(filetreelinkpath)+'" /><input type=file name=files id=p5uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p5uploadinput\')" /><input type=hidden name=authCookie value='+authCookie+" /><input type=submit id=p5loginSubmit style=display:none /></form>"),updateUploadDialogOk("p5uploadinput")}function p5uploadFileEx(){Q("p5loginSubmit").click()}function updateUploadDialogOk(e){QE("idx_dlgOkButton",""!=Q(e).value)}var p5clipboard=null,p5clipboardFolder=null,p5clipboardCut=0;function p5copyFile(e){var t=document.getElementsByName("fc");p5clipboard=[],p5clipboardCut=e,p5clipboardFolder=Clone(filetreelocation);for(var o=0;o<t.length;o++)t[o].checked&&"3"==t[o].attributes.file.value&&p5clipboard.push(t[o].value);p5updateClipview()}function p5pasteFile(){var e="";null!=p5clipboard&&0<p5clipboard.length&&(e=format("Confirme {0} da {1} entrada {2} para este local?",0==p5clipboardCut?"copy":"move",p5clipboard.length,1<p5clipboard.length?"s":"")),setDialogMode(2,"Colar",3,p5pasteFileEx,e)}function p5pasteFileEx(){meshserver.send({action:"fileoperation",fileop:0==p5clipboardCut?"copy":"move",scpath:p5clipboardFolder,path:filetreelocation,names:p5clipboard}),p5folderup(999),1==p5clipboardCut&&(p5clipboardFolder=p5clipboard=null,p5clipboardCut=0,p5updateClipview())}function p5updateClipview(){var e="";null!=p5clipboard&&0<p5clipboard.length&&(e=format("Mantendo {0} entrada {1} para {2}",p5clipboard.length,1<p5clipboard.length?"s":"",0==p5clipboardCut?"Copiar":"Mover")+', <a href=# onclick="return p5clearClip()" style=cursor:pointer>Limpo</a>.'),QH("p5bottomstatus",e),p5setActions()}function p5clearClip(){return p5clipboardFolder=p5clipboard=null,p5clipboardCut=0,p5updateClipview(),!1}function p5fileDragDrop(e){if(haltEvent(e),QV("bigfail",!1),QV("bigok",!1),null!=e.dataTransfer&&0!=e.dataTransfer.files.length&&0!=filetreelocation.length)for(var t=[],o=[],n=[],i=[],a=e.dataTransfer.files.length,s=0;s<e.dataTransfer.files.length;s++){var l=new FileReader,r=e.dataTransfer.files[s];t.push(r.name),o.push(r.size),n.push(r.type),l.onload=function(e){i.push(e.target.result),0==--a&&(Q("p5fileDragName").value=t.join("*"),Q("p5fileDragSize").value=o.join("*"),Q("p5fileDragType").value=n.join("*"),Q("p5fileDragData").value=i.join("*"),Q("p5fileDragLink").value=encodeURIComponent(filetreelinkpath),Q("p5loginSubmit2").click())},l.readAsDataURL(r)}}var p5dragtimer=null;function p5fileDragOver(e){haltEvent(e),null!=p5dragtimer&&(clearTimeout(p5dragtimer),p5dragtimer=null);var t=!0;0==filetreelocation.length&&(t=!1),QV("bigok",t),QV("bigfail",!t)}function p5fileDragLeave(e){haltEvent(e),"p5filetable"!=e.target.id?(QV("bigfail",!1),QV("bigok",!1)):p5dragtimer=setTimeout("QV('bigfail',false);QV('bigok',false);p5dragtimer=null;",200)}function ondeskkeypress(e){if(toggleSoftKeys(0),Q("DeskSoftInput").value="",setSessionActivity(),desktop&&!xxdialogMode&&10==xxcurrentView){if(null!=currentNode){var t=meshes[currentNode.meshid].links[userinfo._id].rights;if(0==(4294967295==t||0!=(8&t)&&0==(256&t)))return!1;if(1==(4294967295!=t&&0!=(8&t)&&0==(256&t)&&0!=(4096&t))&&(1==e.altKey||1==e.ctrlKey||e.keyCode<32&&8!=e.keyCode&&13!=e.keyCode||90<e.keyCode))return!1}return desktop.m.handleKeys(e)}}function ondeskkeydown(e){if(toggleSoftKeys(0),Q("DeskSoftInput").value="",setSessionActivity(),desktop&&!xxdialogMode&&10==xxcurrentView){if(null!=currentNode){var t=meshes[currentNode.meshid].links[userinfo._id].rights;if(0==(4294967295==t||0!=(8&t)&&0==(256&t)))return!1;if(1==(4294967295!=t&&0!=(8&t)&&0==(256&t)&&0!=(4096&t))&&(1==e.altKey||1==e.ctrlKey||e.keyCode<32&&8!=e.keyCode&&13!=e.keyCode||90<e.keyCode))return!1}return desktop.m.handleKeyDown(e)}}function ondeskkeyup(e){if(toggleSoftKeys(0),Q("DeskSoftInput").value="",setSessionActivity(),desktop&&!xxdialogMode&&10==xxcurrentView){if(null!=currentNode){var t=meshes[currentNode.meshid].links[userinfo._id].rights;if(0==(4294967295==t||0!=(8&t)&&0==(256&t)))return!1;if(1==(4294967295!=t&&0!=(8&t)&&0==(256&t)&&0!=(4096&t))&&(1==e.altKey||1==e.ctrlKey||e.keyCode<32&&8!=e.keyCode&&13!=e.keyCode||90<e.keyCode))return!1}return desktop.m.handleKeyUp(e)}}var updateDevicesTimer=null;function updateDevices(){null==updateDevicesTimer&&(updateDevicesTimer=setTimeout(updateDevicesEx,200))}var deviceHeaderCount,sort=0,deviceHeaderId=0,deviceHeaders={},showRealNames=!1,deviceHeaderTotal=0,deviceHeadersTitles=(deviceHeaders={},{});function updateDevicesEx(){null!=updateDevicesTimer&&(clearTimeout(updateDevicesTimer),updateDevicesTimer=null);var e="",t=0,o=null,n=0,i={};for(var a in deviceHeaderCount={},deviceHeaders={},deviceHeadersTitles={},(deviceHeaderTotal=deviceHeaderId=0)==sort?nodes.sort(meshSort):1==sort?nodes.sort(powerSort):2==sort&&(1==showRealNames?nodes.sort(deviceHostSort):nodes.sort(deviceSort)),nodes)if(0!=nodes[a].v){var s=meshes[nodes[a].meshid].links[userinfo._id];if(null!=s){s.rights;if(0==sort){if(nodes.sort(meshSort),nodes[a].meshid!=o){deviceHeaderSet();var l="";1==meshes[nodes[a].meshid].mtype&&(l="<span style=color:lightgray>Intelreg; </span>"),null!=o&&(2==t&&(e+="<td><div style=width:301px></div></td>"),""!=e&&(e+="</tr></table>")),e+="<div class=DevSt style=padding-top:4px><span style=float:right>",e+='</span><span id=MxMESH style=cursor:pointer onclick=goForward("'+nodes[a].meshid+'")>'+EscapeHtml(meshes[nodes[a].meshid].name)+"</span>"+l+"<span id=DevxHeader"+deviceHeaderId+" style=color:lightgray></span></div>",i[o=nodes[a].meshid]=1,t=0}}else 1==sort?nodes[a].pwr!==o&&(deviceHeaderSet(),null!==o&&(2==t&&(e+="<td><div style=width:301px></div></td>"),""!=e&&(e+="</tr></table>")),e+="<div class=DevSt style=width:100%;padding-top:4px><span>"+PowerStateStr2(nodes[a].pwr)+"</span><span id=DevxHeader"+deviceHeaderId+" style=color:lightgray></span></div>",o=nodes[a].pwr,t=0):2==sort&&null==o&&(o="1");n++;var r=EscapeHtml(nodes[a].name);0==r.length&&(r="<i>Nenhum</i>"),null!=nodes[a].rname&&0<nodes[a].rname.length&&(r+=" / "+EscapeHtml(nodes[a].rname));var d=EscapeHtml(nodes[a].name);1==showRealNames&&null!=nodes[a].rname&&(d=EscapeHtml(nodes[a].rname)),0==d.length&&(d="<i>Nenhum</i>");var p=nodes[a].icon,c=NodeStateStr(nodes[a]);nodes[a].conn&&0!=nodes[a].conn||(p+=" gray"),e+="<div style=cursor:pointer onclick=goForward('"+nodes[a]._id+"')>",e+='<div class="i'+p+'" style="float:left;margin-left:4px"></div>',e+='<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">',e+="<div><div style=padding-left:12px;padding-top:2px><b>"+d+"</b></div><div style=padding-left:12px;padding-top:3px;color:gray>"+c+"</div></div>",e+="</div></div>",deviceHeaderTotal++,void 0===deviceHeaderCount[nodes[a].state]?deviceHeaderCount[nodes[a].state]=1:deviceHeaderCount[nodes[a].state]++}}if(0==sort)for(var a in meshes){var u=meshes[a],m=u.links[userinfo._id];if(null!=m){m.rights;null==i[u._id]&&(""!=o&&""!=e&&(e+="</tr></table>"),e+="<div><div colspan=3 class=DevSt><span style=float:right>",e+='</span><span id=MxMESH style=cursor:pointer onclick=goForward("'+u._id+'")>'+EscapeHtml(u.name)+"</span></div>",1==u.mtype&&(e+="<div style=padding:10px><i>Nenhum Intel&reg; AMT devices in this group"),2==u.mtype&&(e+="<div style=padding:10px><i>Nenhum dispositivo neste grupo"),e+=".</i></div></div>",o=u._id,n++)}}for(var a in 0==n?QH("xdevices",'<div style="margin-top:50px;text-align:center"><span style="font-size:30px">Nenhum dispositivo</span><br /><br />Use a versão desktop deste site para adicionar dispositivos.</div>'):QH("xdevices",e),deviceHeaderSet(),deviceHeaders)QH(a,deviceHeaders[a]);for(var a in deviceHeadersTitles)Q(a).title=deviceHeadersTitles[a]}var powerStatetable=["","Ligado","Hibernar","Hibernar","Hibernar","Hibernando","Desligar","Presente"],powerStateStrings=["","Ligado","Hibernando","Hibernando","Deep Sleep","Hibernando","Soft-Off","Presente"],powerStateStrings2=["","O dispositivo está ligado","O dispositivo está no estado de suspensão (S1)","O dispositivo está no estado de suspensão (S2)","O dispositivo está no estado de sono profundo (S3)","O dispositivo está hibernando (S4)","O dispositivo está no estado soft-off (S5)","O dispositivo está presente, mas o estado de energia não pode ser determinado"],powerColorTable=["#00000000","black","blue","blue","lightblue","blueviolet","darkgreen","lightseagreen","lightseagreen"];function NodeStateStr(e){var t=[];return 0<e.state&&e.state<powerStatetable.length&&state.push(powerStatetable[e.state]),e.conn&&(0!=(1&e.conn)&&t.push("<span>Agente</span>"),0!=(2&e.conn)?t.push("<span>CIRA</span>"):0!=(4&e.conn)&&t.push("<span>Intel&reg; AMT</span>"),0!=(8&e.conn)&&t.push("<span>Retransmissão</span>"),0!=(16&e.conn)&&t.push("<span>MQTT</span>")),null!=e.pwr&&0!=e.pwr&&t.push(powerStateStrings[e.pwr]),t.join(", ")}function PowerStateStr(e){return e<powerStatetable.length?powerStatetable[e]:""}function PowerStateStr2(e){return 0!=e&&e<powerStatetable.length?powerStatetable[e]:"Desconhecido"}function onSortSelectChange(e){sort=document.getElementById("sortselect").selectedIndex,e||putstore("sort",sort),updateDevicesEx()}function deviceHeaderSet(){if(0!=deviceHeaderId){deviceHeaders["DevxHeader"+deviceHeaderId]=", "+deviceHeaderTotal+(1==deviceHeaderTotal?"nó":"nós");var e="";for(var t in deviceHeaderCount)0<e.length&&(e+=", "),e+=deviceHeaderCount[t]+" "+PowerStateStr2(t);deviceHeadersTitles["DevxHeader"+deviceHeaderId]=e,deviceHeaderId++,deviceHeaderCount={},deviceHeaderTotal=0}else deviceHeaderId=1}function meshSort(e,t){return e.meshnamel>t.meshnamel?1:e.meshnamel<t.meshnamel?-1:e.meshid==t.meshid?1==showRealNames?e.rnamel>t.rnamel?1:e.rnamel<t.rnamel?-1:0:e.namel>t.namel?1:e.namel<t.namel?-1:0:0}function powerSort(e,t){var o=e.pwr?e.pwr:0,n=t.pwr?t.pwr:0;return o==n?1==showRealNames?e.rnamel>t.rnamel?1:e.rnamel<t.rnamel?-1:0:e.namel>t.namel?1:e.namel<t.namel?-1:0:n<o?1:o<n?-1:0}function deviceSort(e,t){return e.namel>t.namel?1:e.namel<t.namel?-1:0}function deviceHostSort(e,t){return e.rnamel>t.rnamel?1:e.rnamel<t.rnamel?-1:0}function refreshDevice(e){currentNode&&currentNode._id==e&&gotoDevice(e,xxcurrentView,!0)}function getNodeRights(e){var t=getNodeFromId(e);return meshes[t.meshid].links[userinfo._id].rights}var currentNode,currentDevicePanel=0,powerTimelineNode=null,powerTimelineReq=null,powerTimelineUpdate=null,powerTimeline=null;function getCurrentNode(){return currentNode}function gotoDevice(e,t,o){if(!0===userinfo.emailVerified||1!=serverinfo.emailcheck||4294967295==userinfo.siteadmin)if(!(262144&features)||1==userinfo.otpsecret||0<userinfo.otphkeys||0<userinfo.otpkeys){var n=getNodeFromId(e);if(null!=n){var i=meshes[n.meshid];if(null!=i){var a=i.links[userinfo._id].rights;if(!currentNode||currentNode._id!=n._id||1==o){currentNode=n;var s=EscapeHtml(n.name);0==s.length&&(s="<i>Nenhum</i>"),0!=(4&a)&&(s="<span onclick=showEditNodeValueDialog(0) style=cursor:pointer>"+s+"</span>"),QH("p10deviceName",s);var l="<table style=width:100%>";l+=addDeviceAttribute("<span>Grupo</span>",'<a onclick=goForward("'+n.meshid+'") style=cursor:pointer>'+EscapeHtml(meshes[n.meshid].name)+"</a>"),null!=n.rname&&(l+=addDeviceAttribute("<span>Nome</span>","<span>"+EscapeHtml(n.rname)+"</span>")),1!=i.mtype&&n.name==n.host||(0!=(4&a)?n.host?l+=addDeviceAttribute("Hostname","<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>"+EscapeHtml(n.host)+"</span>"):l+=addDeviceAttribute("Hostname","<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>Nenhum</i></span>"):l+=addDeviceAttribute("Hostname",EscapeHtml(n.host)));var r=n.desc?EscapeHtml(n.desc):"<i>Nenhum</i>";l+=addDeviceAttribute("Descrição",0!=(4&a)?"<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>"+r+"</span>":r);var d=["Desconhecido","Windows 32 Bits console","Windows 64 Bits console","Serviço Windows 32 Bits","Serviço Windows 64 Bits","Linux 32 bits","Linux 64 bits","MIPS","XENx86","Android ARM","Linux ARM","MacOS 32 bits","Android x86","PogoPlug ARM","Android APK","Linux Poky x86-32 bits","MacOS 64 bits","ChromeOS","Linux Poky x86-64 bits","Linux NoKVM x86-32 bits","Linux NoKVM x86-64 bits","Windows MinCore console","Windows MinCore service","NodeJS","ARM-Linaro","ARMv6l / ARMv7l","ARMv8 64bit","ARMv6l / ARMv7l / NoKVM","Desconhecido","Desconhecido","FreeBSD x86-64"];if(null!=n.agent&&null!=n.agent.id&&null!=n.agent.ver){var p="";p=n.agent.id<=d.length?d[n.agent.id]:d[0],0!=n.agent.ver&&(p+=" v"+n.agent.ver),l+=addDeviceAttribute("Agente",p)}if(null!=n.intelamt){p="";var c={0:nobreak("Não ativado (pré)"),1:nobreak("Não ativado (entrada)"),2:nobreak("ativado")};null!=n.intelamt.ver&&null==n.intelamt.state?p+="<i>"+nobreak("Estado desconhecido")+"</i>, v"+n.intelamt.ver:null==n.intelamt.ver&&2==n.intelamt.state?p+="<i>ativado</i>":null==n.intelamt.ver||null==n.intelamt.state?p+="<i>Estado da versão desconhecida</i>":(p+=c[n.intelamt.state],n.intelamt.flags&&(2&n.intelamt.flags?p=" <span>CCM</span>":4&n.intelamt.flags&&(p=" <span>ACM</span>")),p+=", v"+n.intelamt.ver),1==n.intelamt.tls&&(p+=", <span>TLS</span>"),2==n.intelamt.state&&(null!=n.intelamt.user&&""!=n.intelamt.user||(p+=0!=(4&a)?', <i style=color:#FF0000;cursor:pointer onclick=editDeviceAmtSettings("'+n._id+'")>'+nobreak("Sem credenciais")+"</i>":", <i style=color:#FF0000>Sem credenciais</i>"),p+=" ",0!=(4&a)&&(p+='<img src=images/link4.png height=10 width=10 style=cursor:pointer onclick=editDeviceAmtSettings("'+n._id+'")>'));var u="Intel&reg; ME";"number"==typeof n.intelamt.sku&&(0!=(8&n.intelamt.sku)?u="Intel&reg; AMT":0!=(16&n.intelamt.sku)&&(u="Intel&reg; SM")),l+=addDeviceAttribute(u,p)}if(null!=n.agent&&null!=n.agent.tag&&"mailto:"!=n.agent.tag){var m=EscapeHtml(n.agent.tag);m.startsWith("mailto:")&&(m='<a href="'+m+'">'+m.substring(7)+"</a>"),l+=addDeviceAttribute("Etiqueta do agente",m)}var h=n.conn;if(h&&1<h){var g=[];0!=(1&n.conn)&&g.push("<span>Agente</span>"),0!=(2&n.conn)?g.push("<span>Intel&reg; AMT CIRA</span>"):0!=(4&n.conn)&&g.push("<span>Intel&reg; AMT</span>"),0!=(8&n.conn)&&g.push("<span>Retransmissão do agente</span>"),0!=(16&n.conn)&&g.push("<span>MQTT</span>"),l+=addDeviceAttribute("Conectividade",g.join(", "))}var v="<i>Nenhum</i>";if(null!=n.tags)for(var f in v="",n.tags)v+='<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">'+n.tags[f]+"</span>";l+=addDeviceAttribute("Tags",0!=(4&a)?"<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>"+v+"</span>":v),l+="</table><br />",0!=(76&a)&&(l+="<input type=button value=Actions onclick=deviceActionFunction() />"),QH("p10html",l),setupFiles(),l="<div style=float:right;font-size:x-small;margin-right:10px>",0!=(4&a)&&(l+='<a style=cursor:pointer onclick=p10showDeleteNodeDialog("'+n._id+'")>Excluir dispositivo</a>'),l+="</div><div style=font-size:x-small>",l+="</div><br>",QH("p10html3",l);var k=PowerStateStr(n.state);0!=(1&h)&&(0<k.length&&(k+=", "),k+="<span style=font-size:10px>Mesh Agent</span>"),0!=(2&h)?(0<k.length&&(k+=", "),k+="<span style=font-size:10px>Intel&reg; AMT conectado</span>"):0!=(4&h)&&(0<k.length&&(k+=", "),k+="<span style=font-size:10px>Intel&reg; AMT detectado</span>"),0!=(16&h)&&(0<k.length&&(k+="<br/>"),k+="<span style=font-size:12px>Canal MQTT conectado</span>"),QH("MainComputerState",k),QH("MainComputerImage",'<div class="i'+n.icon+'"></div>'),powerTimelineNode!=currentNode._id&&powerTimelineReq!=currentNode._id&&(QH("p10html2",""),powerTimelineReq=currentNode._id,meshserver.send({action:"powertimeline",nodeid:currentNode._id}))}setupDesktop(),go(t=t||10),setupDeviceMenu()}else goBack()}else goBack()}else setDialogMode(2,"Segurança da Conta",1,null,'Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para "Minha conta" e veja a seção "Segurança da conta".');else setDialogMode(2,"Segurança da Conta",1,null,'Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para "Minha conta" para alterar e verificar um endereço de email.')}function deviceToastFunction(){xxdialogMode||setDialogMode(2,"Brinde do dispositivo",3,deviceToastFunctionEx,"<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>")}function deviceToastFunctionEx(){meshserver.send({action:"toast",nodeids:[currentNode._id],title:"MeshCentral",msg:Q("d2devToast").value})}function setupDeviceMenu(e,t){var o=0;currentNode&&(o=meshes[currentNode.meshid].links[userinfo._id].rights),null!=e&&(currentDevicePanel=e),QV("p10general",0==currentDevicePanel),QV("p10desktop",1==currentDevicePanel),QV("p10files",2==currentDevicePanel);var n=[];0!=currentDevicePanel&&n.push({n:"General",f:"setupDeviceMenu(0)"}),1!=currentDevicePanel&&null!=currentNode&&(8&o||256&o)&&(1==meshes[currentNode.meshid].mtype&&("number"!=typeof currentNode.intelamt.sku||0!=(8&currentNode.intelamt.sku))||currentNode.agent&&1&currentNode.agent.caps)&&n.push({n:"Desktop",f:"setupDeviceMenu(1)"}),2!=currentDevicePanel&&null!=currentNode&&8&o&&(4294967295==o||0==(1024&o))&&2==currentNode.mtype&&4&currentNode.agent.caps&&n.push({n:"Files",f:"setupDeviceMenu(2)"}),updateFooterMenu(n)}function deviceActionFunction(){if(!xxdialogMode){var e=meshes[currentNode.meshid].links[userinfo._id].rights,t="Selecione uma operação para executar neste dispositivo.<br /><br />",o="<select id=d2deviceop style=float:right;width:170px>";0!=(64&e)&&(o+="<option value=100>Ligar</option>"),0!=(8&e)&&(o+="<option value=4>Hibernar</option><option value=3>Redefinir</option><option value=2>Desligar</option>"),setDialogMode(2,"Ação do dispositivo",3,deviceActionFunctionEx,t+=addHtmlValue("Operação",o+="</select>"))}}function deviceActionFunctionEx(){var e=Q("d2deviceop").value;100==e?meshserver.send({action:"wakedevices",nodeids:[currentNode._id]}):meshserver.send({action:"poweraction",nodeids:[currentNode._id],actiontype:e})}function updateDeviceTimeline(){2==meshserver.State&&null!=powerTimelineNode&&null!=powerTimelineUpdate&&null!=currentNode&&powerTimelineNode==powerTimelineReq&&currentNode._id==powerTimelineNode&&powerTimelineUpdate<Date.now()&&(powerTimelineUpdate=null,meshserver.send({action:"powertimeline",nodeid:currentNode._id}))}function drawDeviceTimeline(){var e=null,t=Date.now();currentNode._id==powerTimelineNode&&(e=powerTimeline);var o=new Date;o.setHours(0,0,0,0);(o=new Date(o.getTime()-5184e5)).getTime();var n=[];if(null!=e&&1<e.length){n.push([0,e[1],e[0]]);for(var i=e[1],a=2;a<e.length;a+=2){var s=e[a],l=t;e.length>a+1&&(l=e[a+1]),n.push([i,i+l,s]),i+=l}}var r="",d=1,p=new Date,c=Q("masthead").offsetWidth-122;p.setHours(0,0,0,0);for(a=0;a<7;a++){var u="",m=p.getTime(),h=m+864e5;for(var g in n){var v=n[g];if(1==isTimeBlockInside(m,h,v[0],v[1])){var f=Math.max(m,v[0]),k=Math.min(Math.min(h,v[1]),t),x=Math.round((k-f)*c/864e5);0<x&&(u+="<div style=display:table-cell;width:"+x+"px;background-color:"+powerColor(v[2])+";height:16px></div>")}}r+="<tr style="+(d%2==0?"background-color:#DDD":"")+"><td><div>&nbsp;"+printDate(p)+"<div></div></div></td><td><div>"+u+"</div></td></tr>",++d,p=new Date(p.getTime()-864e5)}QH("p10html2",'<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse;width:calc(100% - 18px);margin:9px" border=0 cellpadding=2 cellspacing=0><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:center;width:90px>Day</th><th scope=col style=text-align:center>Power State</th></tr>'+r+"</tbody></table>")}function powerColor(e){return e<powerColorTable.length?powerColorTable[e]:"yellow"}function isTimeBlockInside(e,t,o,n){return o<e&&t<n||(e<o&&o<t||e<n&&n<t)}function addDeviceAttribute(e,t){return"<tr><td style=width:100px;color:gray>"+e+"</td><td style=overflow:hidden>"+t+"</td></tr>"}function editDeviceAmtSettings(e,t){if(!xxdialogMode){var o="",n=getNodeFromId(e),i=3;0!=(4&getNodeRights(e))&&(o+=addHtmlValue("Nome de usuário",'<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />'),o+=addHtmlValue("Senha","<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />"),o+=addHtmlValue("Segurança","<select id=dp10tls style=width:176px><option value=0>Sem segurança TLS</option><option value=1>Segurança TLS necessária</option></select>"),null!=n.intelamt.user&&""!=n.intelamt.user&&(i=7),setDialogMode(2,"Editar Intel & reg; Credenciais AMT",i,editDeviceAmtSettingsEx,o,{node:n,func:t}),null!=n.intelamt.user&&""!=n.intelamt.user?Q("dp10username").value=n.intelamt.user:Q("dp10username").value="admin",Q("dp10tls").value=n.intelamt.tls,validateDeviceAmtSettings())}}function validateDeviceAmtSettings(){QE("idx_dlgOkButton",passwordcheck(Q("dp10password").value))}function editDeviceAmtSettingsEx(e,t){if(2==e)meshserver.send({action:"changedevice",nodeid:t.node._id,intelamt:{user:"",pass:""}});else{var o=Q("dp10username").value;""==o&&(o="admin");var n=Q("dp10password").value;""==n&&(o=""),meshserver.send({action:"changedevice",nodeid:t.node._id,intelamt:{user:o,pass:n,tls:Q("dp10tls").value}}),t.node.intelamt.user=o,t.node.intelamt.tls=Q("dp10tls").value,t.func&&setTimeout(t.func,300)}}function p10showDeleteNodeDialog(e){xxdialogMode||(setDialogMode(2,"Excluir nó",3,p10showDeleteNodeDialogEx,format("Excluir {0}?",EscapeHtml(currentNode.name))+"<br /><br /><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />Confirme",e),p10validateDeleteNodeDialog())}function p10validateDeleteNodeDialog(){QE("idx_dlgOkButton",Q("p10check").checked)}function p10showDeleteNodeDialogEx(e,t){meshserver.send({action:"removedevices",nodeids:[t]})}function p10showiconselector(){if(!xxdialogMode&&0!=(4&meshes[currentNode.meshid].links[userinfo._id].rights)){"<div style=display:inline-block class=i1 onclick=p10setIcon(1)></div>","<div style=display:inline-block class=i2 onclick=p10setIcon(2)></div>","<div style=display:inline-block class=i3 onclick=p10setIcon(3)></div><br>","<div style=display:inline-block class=i4 onclick=p10setIcon(4)></div>","<div style=display:inline-block class=i5 onclick=p10setIcon(5)></div>","<div style=display:inline-block class=i6 onclick=p10setIcon(6)></div></table>",setDialogMode(2,"Seleção de ícone",0,null,"<table align=center><td><div style=display:inline-block class=i1 onclick=p10setIcon(1)></div><div style=display:inline-block class=i2 onclick=p10setIcon(2)></div><div style=display:inline-block class=i3 onclick=p10setIcon(3)></div><br><div style=display:inline-block class=i4 onclick=p10setIcon(4)></div><div style=display:inline-block class=i5 onclick=p10setIcon(5)></div><div style=display:inline-block class=i6 onclick=p10setIcon(6)></div></table>"),QV("id_dialogclose",!0)}}function p10setIcon(e){setDialogMode(0),meshserver.send({action:"changedevice",nodeid:currentNode._id,icon:e})}var desktop,desktopNode,showEditNodeValueDialog_modes=["Nome do Dispositivo","Hostname","Descrição","Tags"],showEditNodeValueDialog_modes2=["name","host","desc","tags"],showEditNodeValueDialog_modes3=["","","","Grupo1, Grupo2, Grupo3"];function showEditNodeValueDialog(e){if(!xxdialogMode){setDialogMode(2,"Editar dispositivo",3,showEditNodeValueDialogEx,addHtmlValue(showEditNodeValueDialog_modes[e],'<input id=dp10devicevalue style=width:170px maxlength=64 placeholder="'+showEditNodeValueDialog_modes3[e]+'" onchange=p10editdevicevalueValidate('+e+",event) onkeyup=p10editdevicevalueValidate("+e+",event) />"),e);var t=currentNode[showEditNodeValueDialog_modes2[e]];null==t&&(t=""),Array.isArray(t)&&(t=t.join(", ")),Q("dp10devicevalue").value=t,p10editdevicevalueValidate(),Q("dp10devicevalue").focus()}}function showEditNodeValueDialogEx(e,t){var o={action:"changedevice",nodeid:currentNode._id};o[showEditNodeValueDialog_modes2[t]]=Q("dp10devicevalue").value,meshserver.send(o)}function p10editdevicevalueValidate(e,t){var o=1<e||0<Q("dp10devicevalue").value.length;QE("idx_dlgOkButton",o),null!=t&&1==o&&13==t.keyCode&&dialogclose(1)}var desktopsettings={encoding:2,showfocus:!1,showmouse:!0,showcad:!0,quality:40,scaling:1024,framerate:50};function setupDesktop(){desktopNode!=currentNode&&null!=desktop&&(desktop.Stop(),desktop=desktopNode=null),desktopNode==currentNode&&null!=desktop||(QH("DeskParent",'<canvas id=Desk width=640 height=200 style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>'),desktopNode=currentNode,Q("Desk").addEventListener("DOMMouseScroll",function(e){return dmousewheel(e)}),Q("Desk").addEventListener("mousewheel",function(e){return dmousewheel(e)})),desktopNode=currentNode,updateDesktopButtons(),Q("Desk").toBlob||QV("deskSaveBtn",!1)}function updateDesktopButtons(){var e=meshes[currentNode.meshid],t=0;null!=desktop&&(t=desktop.State);var o=e.links[userinfo._id].rights;QV("disconnectbutton1",0!=t),QV("connectbutton1",0==t&&2==e.mtype&&(8&o||256&o)),QV("connectbutton1h",0==t&&8&o&&(1==e.mtype||null!=currentNode.intelamt&&2==currentNode.intelamt.state&&null!=currentNode.intelamt.ver&&"number"==typeof currentNode.intelamt.sku&&0!=(8&currentNode.intelamt.sku))),QV("d7amtkvm",!(null==currentNode.intelamt||null==currentNode.intelamt.ver&&1!=e.mtype||0!=t&&2!=desktop.contype)),QV("d7meshkvm",2==e.mtype&&(0==t||1==desktop.contype));var n=0!=(1&currentNode.conn);QE("connectbutton1",n);var i=0!=(6&currentNode.conn);QE("connectbutton1h",i),QV("DeskToastButton",0!=(16384&o)&&currentNode.agent&&currentNode.agent.id<5&&8&o),QV("deskActionsBtn",8&o),Q("DeskControl").checked=0!=(8&o),0==n&&QV("DeskTools",!1)}function connectDesktop(e,t){if(setSessionActivity(),null==desktop)if(desktopNode=currentNode,2==t){if(null==desktopNode.intelamt.user||""==desktopNode.intelamt.user)return void editDeviceAmtSettings(desktopNode._id,connectDesktop);(desktop=CreateAmtRedirect(CreateAmtRemoteDesktop("Desk"),authCookie)).debugmode=debugmode,desktop.onStateChanged=onDesktopStateChange,desktop.m.bpp=1==desktopsettings.encoding||3==desktopsettings.encoding?1:2,desktop.m.useZRLE=desktopsettings.encoding<3,desktop.m.showmouse=desktopsettings.showmouse,desktop.m.onScreenSizeChange=deskAdjust,desktop.Start(desktopNode._id,16994,"*","*",0),desktop.contype=2}else(desktop=CreateAgentRedirect(meshserver,CreateAgentRemoteDesktop("Desk"),serverPublicNamePort,authCookie,authRelayCookie,domainUrl)).debugmode=debugmode,desktop.m.debugmode=debugmode,desktop.attemptWebRTC=attemptWebRTC,desktop.onStateChanged=onDesktopStateChange,desktop.m.CompressionLevel=desktopsettings.quality,desktop.m.ScalingLevel=desktopsettings.scaling,desktop.m.FrameRateTimer=desktopsettings.framerate,desktop.m.onDisplayinfo=deskDisplayInfo,desktop.m.onScreenSizeChange=deskAdjust,desktop.Start(desktopNode._id),desktop.contype=1;else desktop.Stop(),desktopNode=desktop=null}function onDesktopStateChange(e,t){var o=t;3==o&&2==e.contype&&o++;var n=StatusStrs[o];switch(null!=desktop&&1==desktop.webRtcActive&&(n+=", WebRTC"),QH("deskstatus",n),t){case 0:desktop.Stop(),desktopNode=desktop=null,QV("termdisplays",!1),1==fullscreen&&deskToggleFull()}updateDesktopButtons(),deskAdjust(),setTimeout(deskAdjust,50)}function showDesktopSettings(){xxdialogMode||(applyDesktopSettings(),updateDesktopButtons(),setDialogMode(7,"Configurações da área de trabalho remota",3,showDesktopSettingsChanged))}function showDesktopSettingsChanged(){desktopsettings.encoding=d7desktopmode.value,desktopsettings.showfocus=d7showfocus.checked,desktopsettings.showmouse=d7showcursor.checked,desktopsettings.quality=d7bitmapquality.value,desktopsettings.scaling=d7bitmapscaling.value,desktopsettings.framerate=d7framelimiter.value,localStorage.setItem("desktopsettings",JSON.stringify(desktopsettings)),applyDesktopSettings(),desktop&&(1==desktop.contype&&0!=desktop.State&&desktop.m.SendCompressionLevel(1,desktopsettings.quality,desktopsettings.scaling,desktopsettings.framerate),2==desktop.contype&&0!=desktop.State&&(desktop.Stop(),setTimeout(function(){connectDesktop(null,2)},50)))}function applyDesktopSettings(){var e="",t=512&features?[90,70,50,40,30,20,10,5,1]:[50,40,30,20,10,5,1];for(var o in t)e+="<option value="+t[o]+">"+t[o]+"%</option>";QH("d7bitmapquality",e),d7desktopmode.value=desktopsettings.encoding,d7showfocus.checked=desktopsettings.showfocus,d7showcursor.checked=desktopsettings.showmouse,d7bitmapquality.value=40,0<=t.indexOf(parseInt(desktopsettings.quality))&&(d7bitmapquality.value=desktopsettings.quality),d7bitmapscaling.value=desktopsettings.scaling,desktopsettings.framerate&&(d7framelimiter.value=desktopsettings.framerate)}var fullscreen=!1;function deskAdjust(){var e=(Q("DeskParent").clientHeight-Q("Desk").clientHeight)/2;if(e<0){var t=Q("DeskParent").clientHeight,o=9999;desktop&&(o=desktop.m.width/desktop.m.height*t),QS("Desk")["max-height"]=t+"px",QS("Desk")["max-width"]=o+"px",e=0}else QS("Desk")["max-height"]=null,QS("Desk")["max-width"]=null;QS("Desk")["margin-top"]=e+"px",QS("Desk")["margin-bottom"]=e+"px"}function deskSendKeys(){if(!xxdialogMode&&null!=desktop&&3==desktop.State){var e=Q("deskkeys").value;0==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[65364,1],[65364,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,40],[desktop.m.KeyAction.UP,40],[desktop.m.KeyAction.EXUP,91]]):1==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[65362,1],[65362,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,38],[desktop.m.KeyAction.UP,38],[desktop.m.KeyAction.EXUP,91]]):2==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[108,1],[108,0],[65511,0]]):desktop.sendCtrlMsg('{"action":"lock"}'):3==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[109,1],[109,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,91]]):4==e?2==desktop.contype?desktop.m.sendkey([[65505,1],[65511,1],[109,1],[109,0],[65511,0],[65505,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN,16],[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,91],[desktop.m.KeyAction.UP,16]]):5==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.EXUP,91]]):6==e?2==desktop.contype?desktop.m.sendkey([[65511,1],[114,1],[114,0],[65511,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,91],[desktop.m.KeyAction.DOWN,82],[desktop.m.KeyAction.UP,82],[desktop.m.KeyAction.EXUP,91]]):7==e?2==desktop.contype?desktop.m.sendkey([[65513,1],[65473,1],[65473,0],[65513,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,18],[desktop.m.KeyAction.DOWN,115],[desktop.m.KeyAction.UP,115],[desktop.m.KeyAction.EXUP,18]]):8==e?2==desktop.contype?desktop.m.sendkey([[65507,1],[119,1],[119,0],[65507,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,17],[desktop.m.KeyAction.DOWN,87],[desktop.m.KeyAction.UP,87],[desktop.m.KeyAction.EXUP,17]]):9==e?2==desktop.contype?desktop.m.sendkey([[65513,1],[65289,1],[65289,0],[65513,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,18],[desktop.m.KeyAction.DOWN,9],[desktop.m.KeyAction.UP,9],[desktop.m.KeyAction.EXUP,18]]):10==e?desktop.m.sendcad():11==e&&(2==desktop.contype?desktop.m.sendkey([[65289,1],[65289,0]]):desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN,9],[desktop.m.KeyAction.UP,9]]))}}function sendSpecialKeys(){xxdialogMode||null==desktop||3!=desktop.State||setDialogMode(3,"Chaves especiais",3,deskSendKeys)}function toggleSoftKeys(e){QV("DeskSoftInput",1==e),1==e&&Q("DeskSoftInput").focus()}function toggleDeskTools(){setSessionActivity(),xxdialogMode||("none"==QS("DeskTools").display?(QV("DeskTools",!0),Q("DeskTools").nodeid=currentNode._id,refreshDeskTools()):QV("DeskTools",!1))}function refreshDeskTools(){setSessionActivity(),QV("DeskToolsRefreshButton",!1),setTimeout(refreshDeskToolsEx,500),meshserver.send({action:"msg",type:"ps",nodeid:currentNode._id})}function refreshDeskToolsEx(){QV("DeskToolsRefreshButton",!0)}var filesNode,deskTools={sort:1,msg:null};function sortProcess(e){deskTools.sort=e,showDeskToolsProcesses(deskTools.msg)}function sortProcessPid(e,t){return e.p>t.p?1:e.p<t.p?-1:0}function sortProcessName(e,t){return e.d>t.d?1:e.d<t.d?-1:0}function showDeskToolsProcesses(e){if(null!=(deskTools.msg=e)){if(Q("DeskTools").nodeid==e.nodeid){var t=[],o=null;try{o=JSON.parse(e.value)}catch(e){}if(console.log(o),null!=o){for(var n in o)t.push({p:parseInt(n),c:o[n].cmd,d:o[n].cmd.toLowerCase(),u:o[n].user});0==deskTools.sort?t.sort(sortProcessPid):1==deskTools.sort&&t.sort(sortProcessName);var i="";for(var a in t)0!=t[a].p&&(i+="<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>"+t[a].p+"</div><a style=float:right;padding-right:5px;cursor:pointer onclick=stopProcess("+t[a].p+',"'+t[a].c+'")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>'+(t[a].u?t[a].u:"")+"</div><div>"+t[a].c+"</div></div>");QH("DeskToolsProcesses",i)}}}else QH("DeskToolsProcesses","")}function deskSaveImage(){if(setSessionActivity(),!xxdialogMode&&null!=desktop&&3==desktop.State){var e=new Date,t="Desktop-"+currentNode.name+"-"+e.getFullYear()+"-"+("0"+(e.getMonth()+1)).slice(-2)+"-"+("0"+e.getDate()).slice(-2)+"-"+("0"+e.getHours()).slice(-2)+"-"+("0"+e.getMinutes()).slice(-2);Q("Desk").toBlob(function(e){saveAs(e,t+".jpg")})}}function deskDisplayInfo(e,t,o,n){var i=Q("termdisplays").value;if(0<t.length){var a="";for(var s in t)a+="<option"+(i==t[s]?" selected":"")+">"+t[s]+"</option>";QH("termdisplays",a)}QV("termdisplays",0<t.length)}function deskGetDisplayNumbers(e){desktop.m.GetDisplayNumbers()}function deskSetDisplay(e){setSessionActivity();var t=0,o=Q("termdisplays").value;t="Todas as telas"==o?65535:parseInt(o.substring(8)),desktop.m.SetDisplay(t)}function dmousedown(e){setSessionActivity(),xxdialogMode||null==desktop||desktop.m.mousedown(e)}function dmouseup(e){setSessionActivity(),xxdialogMode||null==desktop||desktop.m.mouseup(e)}function dmousemove(e){setSessionActivity(),xxdialogMode||null==desktop||desktop.m.mousemove(e)}function dmousewheel(e){return setSessionActivity(),!(xxdialogMode||null==desktop||!desktop.m.mousewheel)&&(desktop.m.mousewheel(e),haltEvent(e),!0)}function drotate(e){xxdialogMode||null==desktop||(desktop.m.setRotation(desktop.m.rotation+e),deskAdjust(),deskAdjust())}function stopProcess(e,t){return setDialogMode(2,"Controle do processo",3,stopProcessEx,format('Parar processo #{0} "{1}"?',e,t),e),!1}function stopProcessEx(e,t){meshserver.send({action:"msg",type:"pskill",nodeid:currentNode._id,value:t}),setTimeout(refreshDeskTools,300)}function setupFiles(){var e=filesNode==currentNode,t=0!=(1&(filesNode=currentNode).conn);QE("p13Connect",t),0!=e&&0!=t||!files||(files.Stop(),files=null)}function onFilesStateChange(e,t){setSessionActivity(),p13Connect.value=0==t?"Conectar":"Desconectar";var o=StatusStrs[t];switch(1==files.webRtcActive&&(o+=", WebRTC"),Q("p13Status").textContent=o,t){case 0:QH("p13files",""),p13filetree=null,p13filetreelocation=[],QH("p13currentpath",""),QE("p13FolderUp",!1),p13setActions(),null!=files&&(files.Stop(),files=null);break;case 3:p13targetpath="",files.sendText({action:"ls",reqid:1,path:""})}}function CreateRemoteFiles(e){var t={protocol:5};return t.onFileUpdate=e,t.xxStateChange=function(e){},t.ProcessData=function(e){t.onFileUpdate(e)},t}var autoConnectFilesTimer=null;function autoConnectFiles(e){autoConnectFilesTimer=null==autoConnectFilesTimer?setInterval(connectFiles,100):(clearInterval(autoConnectFilesTimer),null)}function connectFiles(e){files?(files.Stop(),files=null):((files=CreateAgentRedirect(meshserver,CreateRemoteFiles(p13gotFiles),serverPublicNamePort,authCookie,authRelayCookie,domainUrl)).attemptWebRTC=attemptWebRTC,files.onStateChanged=onFilesStateChange,files.Start(filesNode._id)),p13clipboard=p13clipboardFolder=null,p13clipboardCut=0,p13updateClipview()}var p13sortorder,p13filetree=null,p13targetpath=null,p13filetreelocation=[];function p13gotFiles(e){if(setSessionActivity(),0<e.length&&123!=e.charCodeAt(0))p13gotDownloadBinaryData(e);else if("download"!=(e=JSON.parse(decode_utf8(e))).action)if(e.path=e.path.replace(/\//g,"\\"),null!=p13filetree&&e.path==p13filetree.path){var t=p13getCheckedNames();p13filetree=e,p13updateFiles(t)}else{for(var o=e.path.replace(/\//g,"\\"),n=p13targetpath.replace(/\//g,"\\");0<o.length&&"\\"==o[0];)o=o.substring(1);for(;0<n.length&&"\\"==n[0];)n=n.substring(1);(o==n||"\\"==e.path&&""==p13targetpath)&&(p13filetree=e,p13updateFiles())}else p13gotDownloadCommand(e)}function p13getCheckedNames(){for(var e=[],t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&e.push(p13filetree.dir[t[o].value].n);return e}function p13updateFiles(e){var t="",o="",n="<a style=cursor:pointer onclick=p13folderup(0)>Raiz</a>",i=p13filetree.path.split("\\");for(var a in p13filetreelocation=[],i)""!=i[a]&&p13filetreelocation.push(i[a]);for(var a in p13filetreelocation)n+=" / <a style=cursor:pointer onclick=p13folderup("+(parseInt(a)+1)+")>"+p13filetreelocation[a]+"</a>";var s=p13filetreelocation.join("/"),l=p13sort_files(p13filetree.dir);for(var a in l){var r,d=l[a],p=d.n;r=70<(r=p).length?EscapeHtml(p.substring(0,70))+"...":EscapeHtml(p),p=EscapeHtml(p);var c="";null!=d.s&&(c=getFileSizeStr(d.s));var u="";if(d.t<3){u="<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='"+d.nx+"'>&nbsp;<span style=float:right></span><span><div class=fileIcon"+d.t+'></div><a style=cursor:pointer onclick=p13folderset("'+encodeURIComponent(d.nx)+'")>'+r+"</a></span></div>"}else{var m=r;0<d.s&&(m='<a rel="noreferrer noopener" target="_blank" style=cursor:pointer onclick="p13downloadfile(\''+encodeURIComponent(s+"/"+p)+"','"+encodeURIComponent(p)+"',"+d.s+')">'+r+"</a>"),u="<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='"+d.nx+"'>&nbsp;<span style=float:right;padding-right:4px>"+c+"</span><span><div class=fileIcon"+d.t+"></div>"+m+"</span></div>"}d.t<3?t+=u:o+=u}if(QH("p13files",t+o),QH("p13currentpath",n),QE("p13FolderUp",0!=p13filetreelocation.length),null!=e){var h=document.getElementsByName("fd");for(a=0;a<h.length;a++)0<=e.indexOf(p13filetree.dir[h[a].value].n)&&(h[a].checked=!0)}p13setActions()}function p13folderset(e){p13targetpath=joinPaths(p13filetree.path,p13filetree.dir[e].n).split("\\").join("/"),files.sendText({action:"ls",reqid:1,path:p13targetpath})}function p13folderup(e){if(null==e)p13filetreelocation.pop();else for(;p13filetreelocation.length>e;)p13filetreelocation.pop();p13targetpath=p13filetreelocation.join("/"),files.sendText({action:"ls",reqid:1,path:p13targetpath})}function p13sort_filename(e,t){return e.ln>t.ln?1*p13sortorder:e.ln<t.ln?-1*p13sortorder:0}function p13sort_timestamp(e,t){return e.d>t.d?1*p13sortorder:e.d<t.d?-1*p13sortorder:0}function p13sort_bysize(e,t){return e.s==t.s?p13sort_filename(e,t):(e.s-t.s)*p13sortorder}function p13sort_files(e){var t=[],o=Q("p13sortdropdown").value;for(var n in e)e[n].nx=n,null==e[n].s&&(e[n].s=0),null==e[n].n&&(e[n].n=n),e[n].ln=e[n].n.toLowerCase(),t.push(e[n]);return p13sortorder=1,3<o&&(p13sortorder=-1,o-=3),1==o?t.sort(p13sort_filename):2==o?t.sort(p13sort_bysize):3==o&&t.sort(p13sort_timestamp),t}function p13setActions(){if(null==p13filetree)QE("p13DeleteFileButton",!1),QE("p13NewFolderButton",!1),QE("p13UploadButton",!1),QE("p13RenameFileButton",!1),QE("p13SelectAllButton",!1),Q("p13SelectAllButton").value="Todos",QE("p13RefreshButton",!1),QE("p13CutButton",!1),QE("p13CopyButton",!1),QE("p13PasteButton",!1);else{var e=p13getFileSelCount(),t=p13getFileCount(),o=p13getFileSelCount(!1),n=0<currentNode.agent.id&&currentNode.agent.id<5;QE("p13DeleteFileButton",0<e&&(0<p13filetreelocation.length||0==n)),QE("p13NewFolderButton",0<p13filetreelocation.length||0==n),QE("p13UploadButton",0<p13filetreelocation.length||0==n),QE("p13RenameFileButton",1==e&&(0<p13filetreelocation.length||0==n)),QE("p13SelectAllButton",0<t),Q("p13SelectAllButton").value=0<e?"Nenhum":"Todos",QE("p13RefreshButton",!0),QE("p13CutButton",0<e&&e==o&&(0<p13filetreelocation.length||0==n)),QE("p13CopyButton",0<e&&e==o&&(0<p13filetreelocation.length||0==n)),QE("p13PasteButton",(0<p13filetreelocation.length||0==n)&&null!=p13clipboard&&0<p13clipboard.length)}}function p13getFileSelCount(e){for(var t=0,o=document.getElementsByName("fd"),n=0;n<o.length;n++)!o[n].checked||0==e&&"3"!=o[n].attributes.file.value||t++;return t}function p13getFileSelDirCount(){for(var e=0,t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&"999"==t[o].attributes.file.value&&e++;return e}function p13getFileCount(){return document.getElementsByName("fd").length}function p13selectallfile(){for(var e=0==p13getFileSelCount(),t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked=e;p13setActions()}function p13createfolder(){setDialogMode(2,"Nova pasta",3,p13createfolderEx,"<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />"),focusTextBox("p13renameinput"),p13fileNameCheck()}function p13createfolderEx(){files.sendText({action:"mkdir",reqid:1,path:p13filetreelocation.join("/")+"/"+Q("p13renameinput").value}),p13folderup(999)}function p13deletefile(){var e=p13getFileSelCount(),t=0<p13getFileSelDirCount()?"<br /><br /><label><input type=checkbox id=p13recdeleteinput>Exclusão recursiva</label><br>":"<input type=checkbox id=p13recdeleteinput style='display:none'>";setDialogMode(2,"Deletar",3,p13deletefileEx,1<e?format("Excluir {0} itens selecionados?",e)+t:"Excluir item selecionado?"+t)}function p13deletefileEx(){for(var e=[],t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&e.push(p13filetree.dir[t[o].value].n);files.sendText({action:"rm",reqid:1,path:p13filetreelocation.join("/"),delfiles:e,rec:Q("p13recdeleteinput").checked}),p13folderup(999)}function p13renamefile(){for(var e,t=document.getElementsByName("fd"),o=0;o<t.length;o++)t[o].checked&&(e=p13filetree.dir[t[o].value].n);setDialogMode(2,"Renomear",3,p13renamefileEx,'<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% value="'+e+'" />',{action:"rename",path:p13filetreelocation.join("/"),oldname:e}),focusTextBox("p13renameinput"),p13fileNameCheck()}function p13renamefileEx(e,t){t.newname=Q("p13renameinput").value,files.sendText(t),p13folderup(999)}function p13fileNameCheck(e){var t=isFilenameValid(Q("p13renameinput").value);QE("idx_dlgOkButton",t),1==t&&null!=e&&13==e.keyCode&&dialogclose(1)}function p13uploadFile(){setDialogMode(2,"Subir arquivo",3,p13uploadFileEx,"<input type=file name=files id=p13uploadinput style=width:100% multiple=multiple onchange=\"updateUploadDialogOk('p13uploadinput')\" />"),updateUploadDialogOk("p13uploadinput")}function p13uploadFileEx(){p13doUploadFiles(Q("p13uploadinput").files)}function p13viewfile(){for(var e=document.getElementsByName("fd"),t=0;t<e.length;t++)if(e[t].checked){p13filetree.dir[e[t].value].s<=204800?p13downloadfile(encodeURIComponent(p13filetreelocation.join("/")+"/"+p13filetree.dir[e[t].value].n),encodeURIComponent(p13filetree.dir[e[t].value].n),p13filetree.dir[e[t].value].s,"viewer"):messagebox("Editor de Arquivos","Somente arquivos com menos de 200k podem ser editados.");break}}var downloadFile,uploadFile,currentMesh,p13clipboard=null,p13clipboardFolder=null,p13clipboardCut=0;function p13copyFile(e){var t=document.getElementsByName("fd");p13clipboard=[],p13clipboardCut=e,p13clipboardFolder=p13targetpath;for(var o=0;o<t.length;o++)t[o].checked&&"3"==t[o].attributes.file.value&&p13clipboard.push(p13filetree.dir[t[o].value].n);p13updateClipview()}function p13pasteFile(){var e="";null!=p13clipboard&&0<p13clipboard.length&&(e=0==p13clipboardCut?1<p13clipboard.length?format("Confirmar cópia de {0} entradas para este local?",p13clipboard.length):format("Confirmar cópia de 1 entrada para este local?"):1<p13clipboard.length?format("Confirmar a movimentação de {0} entradas para este local?",p13clipboard.length):format("Confirmar a movimentação de 1 entrada para este local?")),setDialogMode(2,"Colar",3,p13pasteFileEx,e)}function p13pasteFileEx(){files.sendText({action:0==p13clipboardCut?"copy":"move",reqid:1,scpath:p13clipboardFolder,dspath:p13targetpath,names:p13clipboard}),p13folderup(999),1==p13clipboardCut&&(p13clipboardFolder=p13clipboard=null,p13clipboardCut=0,p13updateClipview())}function p13updateClipview(){var e="";null!=p13clipboard&&0<p13clipboard.length&&(e=0==p13clipboardCut?1<p13clipboard.length?format('Mantendo {0} entradas para cópia, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Limpo</a>.',p13clipboard.length):format('Mantendo 1 entrada para cópia, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Limpo</a>.'):1<p13clipboard.length?format('Manter {0} entradas para mover, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Limpo</a>.',p13clipboard.length):format('Segurando 1 entrada para mover, <a href=# onclick="return p13clearClip()" style=cursor:pointer>Limpo</a>.')),QH("p13bottomstatus",e),p13setActions()}function p13clearClip(){return p13clipboardFolder=p13clipboard=null,p13clipboardCut=0,p13updateClipview(),!1}function updateUploadDialogOk(e){QE("idx_dlgOkButton",""!=Q(e).value)}function getFileSelCount(e){for(var t=0,o=document.getElementsByName("fc"),n=0;n<o.length;n++)!o[n].checked||0==e&&"3"!=o[n].attributes.file.value||t++;return t}function getFileCount(){return document.getElementsByName("fc").length}function p13downloadfile(e,t,o){xxdialogMode||downloadFile||!files||(downloadFile={path:decodeURIComponent(e),file:decodeURIComponent(t),size:o,tsize:0,data:"",state:0,id:Math.random()},files.sendText({action:"download",sub:"start",id:downloadFile.id,path:downloadFile.path}),setDialogMode(2,"⇬ Fazer download do arquivo",10,p13downloadFileCancel,"<div>"+downloadFile.file+"</div><br /><progress id=d2progressBar style=width:100% value=0 max="+o+" />"))}function p13downloadFileCancel(){setDialogMode(0),files.sendText({action:"download",sub:"cancel",id:downloadFile.id}),downloadFile=null}function p13gotDownloadCommand(e){null!=downloadFile&&e.id==downloadFile.id&&("start"==e.sub?(downloadFile.state=1,files.sendText({action:"download",sub:"startack",id:downloadFile.id})):"cancel"==e.sub&&(downloadFile=null,setDialogMode(0)))}function p13gotDownloadBinaryData(e){downloadFile&&0!=downloadFile.state&&(4<e.length&&(downloadFile.tsize+=e.length-4,downloadFile.data+=e.substring(4),Q("d2progressBar").value=downloadFile.tsize),0!=(1&ReadInt(e,0))?(saveAs(data2blob(downloadFile.data),downloadFile.file),downloadFile=null,setDialogMode(0)):files.sendText({action:"download",sub:"ack",id:downloadFile.id}))}function p13doUploadFiles(e){xxdialogMode||((uploadFile={}).xpath=p13filetreelocation.join("/"),uploadFile.xfiles=e,uploadFile.xfilePtr=-1,setDialogMode(2,"Subir arquivo",10,p13uploadFileCancel,"<div id=p13dfileName>Conectando...</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />"),p13uploadReconnect())}function onFileUploadStateChange(e,t){switch(t){case 0:p13folderup(9999);break;case 3:p13uploadNextFile();break;default:console.log("Unknown onFileUploadStateChange state",t)}}function p13uploadReconnect(){uploadFile.ws=CreateAgentRedirect(meshserver,CreateRemoteFiles(p13gotUploadData),serverPublicNamePort,authCookie,authRelayCookie,domainUrl),uploadFile.ws.attemptWebRTC=!1,uploadFile.ws.ctrlMsgAllowed=!1,uploadFile.ws.onStateChanged=onFileUploadStateChange,uploadFile.ws.Start(filesNode._id)}function p13uploadNextFile(){if(uploadFile.xfilePtr++,uploadFile.xfiles.length>uploadFile.xfilePtr){uploadFile.xptr=0;var e=uploadFile.xfiles[uploadFile.xfilePtr];QH("p13dfileName",e.name),Q("d2progressBar").max=e.size,Q("d2progressBar").value=0,uploadFile.xreader=new FileReader,uploadFile.xreader.onload=function(){uploadFile.xdata=uploadFile.xreader.result,uploadFile.ws.sendText({action:"upload",reqid:uploadFile.xfilePtr,path:uploadFile.xpath,name:e.name,size:uploadFile.xdata.byteLength})},uploadFile.xreader.readAsArrayBuffer(e)}else p13uploadFileCancel()}function p13uploadFileCancel(e,t){null!=uploadFile&&(null!=uploadFile.ws&&(uploadFile.ws.Stop(),uploadFile.ws=null),uploadFile=null),setDialogMode(0)}function p13gotUploadData(e){var t=JSON.parse(e);if(null!=uploadFile&&parseInt(uploadFile.xfilePtr)==parseInt(t.reqid))if("uploadstart"==t.action){p13uploadNextPart(!1);for(var o=0;o<8;o++)p13uploadNextPart(!0)}else"uploadack"==t.action?p13uploadNextPart(!1):"uploaderror"==t.action&&p13uploadFileCancel()}function p13uploadNextPart(e){var t=uploadFile.xdata,o=uploadFile.xptr,n=uploadFile.xptr+4096;if(n>t.byteLength){if(1==e)return;n=t.byteLength}if(o==t.byteLength)null!=uploadFile.ws&&(uploadFile.ws.Stop(),uploadFile.ws=null),uploadFile.xfiles.length>uploadFile.xfilePtr+1?p13uploadReconnect():p13uploadFileCancel();else{var i=t.slice(o,n);uploadFile.ws.send(i),uploadFile.xptr=n,Q("d2progressBar").value=n}}function p20updateMesh(){if(null!=currentMesh){QH("p20meshName",EscapeHtml(currentMesh.name));var e=format("Desconhecido # {0}",currentMesh.mtype),t=currentMesh.links[userinfo._id].rights;1==currentMesh.mtype&&(e="Intel&reg; Apenas AMT, nenhum agente"),2==currentMesh.mtype&&(e="Gerenciado usando um agente de software");var o="";o+=addHtmlValue("Nome",addLinkConditional(EscapeHtml(currentMesh.name),"p20editmesh(1)",0!=(1&t))),o+=addHtmlValue("Descrição",addLinkConditional(currentMesh.desc&&""!=currentMesh.desc?EscapeHtml(currentMesh.desc):"<i>Nenhum</i>","p20editmesh(2)",0!=(1&t))),o+=addHtmlValue("Tipo",e),o+="<br style=clear:both><br>";var n=currentMesh.links[userinfo._id];n&&0!=(2&n.rights)&&(o+="<div style=margin-bottom:6px><a onclick=p20showAddMeshUserDialog() style=cursor:pointer><img src=images/icon-addnew.png border=0 height=12 width=12>Adicionar usuário</a></div>"),o+='<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>Autorizações de usuário</th></tr>';var i=1,a=[];for(var s in currentMesh.links)a.push({id:s,name:s.split("/")[2],rights:currentMesh.links[s].rights});for(var s in a.sort(function(e,t){return e.name>t.name?1:e.name<t.name?-1:0}),a){var l="",r="Direitos parciais",d=a[s].rights;4294967295==d?r="Administrador completo":0==d&&(r="Sem direitos"),s==userinfo._id||4294967295!=t&&0==(2&t)||(l='<a onclick=p20deleteUser(event,"'+encodeURIComponent(a[s].id)+'") style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'),o+='<tr onclick=p20viewuser("'+encodeURIComponent(a[s].id)+'") style=height:32px;cursor:pointer'+(i%2==0?";background-color:#DDD":"")+"><td>",o+="<div style=float:right>"+l+"</div><div style=float:right;padding-right:4px>"+r+"</div><div class=m2></div><div>&nbsp;"+EscapeHtml(decodeURIComponent(a[s].name))+"<div></div></div>",o+="</td></tr>",++i}o+="</tbody></table>",4294967295==t&&(o+="<div style=font-size:small;text-align:right;margin-top:6px><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>Excluir grupo</a></span></div>"),QH("p20info",o)}}function p20showDeleteMeshDialog(){if(xxdialogMode)return!1;var e=format("Tem certeza de que deseja excluir o grupo {0}? A exclusão do grupo de dispositivos também excluirá todas as informações sobre os dispositivos desse grupo.",EscapeHtml(currentMesh.name))+"<br /><br />";return setDialogMode(2,"Excluir grupo",3,p20showDeleteMeshDialogEx,e+="<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />Confirme</label>"),p20validateDeleteMeshDialog(),!1}function p20validateDeleteMeshDialog(){QE("idx_dlgOkButton",Q("p20check").checked)}function p20showDeleteMeshDialogEx(e,t){meshserver.send({action:"deletemesh",meshid:currentMesh._id,meshname:currentMesh.name})}function p20editmesh(e){if(!xxdialogMode){var t=addHtmlValue("Nome","<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />");setDialogMode(2,"Editar grupo de dispositivos",3,p20editmeshEx,t+=addHtmlValue("Descrição","<input id=dp20meshdesc style=width:170px maxlength=1024 onkeyup=p20editmeshValidate() />")),Q("dp20meshname").value=currentMesh.name,currentMesh.desc&&(Q("dp20meshdesc").value=currentMesh.desc),p20editmeshValidate(),2==e?Q("dp20meshdesc").focus():Q("dp20meshname").focus()}}function p20editmeshEx(){meshserver.send({action:"editmesh",meshid:currentMesh._id,meshname:Q("dp20meshname").value,desc:Q("dp20meshdesc").value})}function p20editmeshValidate(){QE("idx_dlgOkButton",0<Q("dp20meshname").value.length)}function p20showAddMeshUserDialog(){if(!xxdialogMode){var e=addHtmlValue("User","<input id=dp20username style=width:170px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />");e+='<div style="border:2px groove gray;background-color:white;max-height:120px;overflow-y:scroll">',e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Administrador completo</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>Editar grupo de dispositivos</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>Gerenciar usuários do grupo de dispositivos</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>Gerenciar computadores do grupo de dispositivos</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>Controle remoto</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>Somente visualização remota</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>Somente entrada limitada</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>Sem acesso ao terminal</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>Sem acesso a arquivos</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>Nenhum Intel&reg; AMT</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>Mesh Agent Console</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>Arquivos do servidor</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Reativar dispositivo</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Editar notas do dispositivo</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>Mostrar apenas eventos próprios</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>Chat & Notificação</label><br>",e+="<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20uninstall>Uninstall Agent</label><br>",setDialogMode(2,"Adicionar usuário à malha",3,p20showAddMeshUserDialogEx,e+="</div>"),p20validateAddMeshUserDialog(),Q("dp20username").focus()}}function p20validateAddMeshUserDialog(){var e=currentMesh.links[userinfo._id].rights,t=!Q("p20fulladmin").checked;QE("p20fulladmin",4294967295==e),QE("p20editmesh",t&&4294967295==e),QE("p20manageusers",t),QE("p20managecomputers",t),QE("p20remotecontrol",t),QE("p20meshagentconsole",t),QE("p20meshserverfiles",t),QE("p20wakedevices",t),QE("p20editnotes",t),QE("p20limitevents",t),QE("p20remoteview",t&&Q("p20remotecontrol").checked),QE("p20remotelimitedinput",t&&Q("p20remotecontrol").checked&&!Q("p20remoteview").checked),QE("p20noterminal",t&&Q("p20remotecontrol").checked),QE("p20nofiles",t&&Q("p20remotecontrol").checked),QE("p20noamt",t&&Q("p20remotecontrol").checked),QE("p20chatnotify",t),QE("p20uninstall",t)}function p20showAddMeshUserDialogEx(){var e=0;1==Q("p20fulladmin").checked?e=4294967295:(1==Q("p20editmesh").checked&&(e+=1),1==Q("p20manageusers").checked&&(e+=2),1==Q("p20managecomputers").checked&&(e+=4),1==Q("p20remotecontrol").checked&&(e+=8),1==Q("p20meshagentconsole").checked&&(e+=16),1==Q("p20meshserverfiles").checked&&(e+=32),1==Q("p20wakedevices").checked&&(e+=64),1==Q("p20editnotes").checked&&(e+=128),1==Q("p20remoteview").checked&&(e+=256),1==Q("p20noterminal").checked&&(e+=512),1==Q("p20nofiles").checked&&(e+=1024),1==Q("p20noamt").checked&&(e+=2048),1==Q("p20remotelimitedinput").checked&&(e+=4096),1==Q("p20limitevents").checked&&(e+=8192),1==Q("p20chatnotify").checked&&(e+=16384),1==Q("p20uninstall").checked&&(e+=32768));var t=Q("dp20username").value.split(","),o=[];for(var n in t)o.push(t[n].trim());meshserver.send({action:"addmeshuser",meshid:currentMesh._id,meshname:currentMesh.name,usernames:o,meshadmin:e})}function p20viewuser(e){if(!xxdialogMode){e=decodeURIComponent(e);var t=[],o=currentMesh.links[userinfo._id].rights,n=currentMesh.links[e].rights;4294967295==n?t.push("Administrador completo"):(0!=(1&n)&&t.push("Editar grupo de dispositivos"),0!=(2&n)&&t.push("Gerenciar usuários do grupo de dispositivos"),0!=(4&n)&&t.push("Gerenciar computadores do grupo de dispositivos"),0!=(8&n)&&t.push("Controle remoto"),0!=(16&n)&&t.push("Console do agente"),0!=(32&n)&&t.push("Arquivos do servidor"),0!=(64&n)&&t.push("Reativar dispositivo"),0!=(128&n)&&t.push("Editar notas"),0!=(256&n)&&t.push("Somente visualização remota"),0!=(512&n)&&t.push("Sem terminal"),0!=(1024&n)&&t.push("Sem arquivos"),0!=(2048&n)&&t.push("Nenhum Intel&reg; AMT"),0!=(8&n)&&0!=(4096&n)&&0==(256&n)&&t.push("Entrada limitada"),0!=(8192&n)&&t.push("Somente Eventos Próprios"),0!=(16384&n)&&t.push("Chat & Notificação"),0!=(32768&n)&&t.push("Uninstall")),0==t.length&&t.push("Sem direitos");var i=1,a=addHtmlValue("Do utilizador",EscapeHtml(decodeURIComponent(e.split("/")[2])));a+=addHtmlValue("Permissões",t.join(",")),userinfo._id!=e&&(4294967295==o||0!=(2&o)&&4294967295!=n)&&(i+=4),setDialogMode(2,"Usuário do grupo de dispositivos",i,p20viewuserEx,a,e)}}function p20viewuserEx(e,t){2==e&&setDialogMode(2,"Usuário de malha remota",3,p20viewuserEx2,format("Confirmar remoção do usuário {0}?",t.split("/")[2]),t)}function p20deleteUser(e,t){haltEvent(e),p20viewuserEx(2,decodeURIComponent(t))}function p20viewuserEx2(e,t){meshserver.send({action:"removemeshuser",meshid:currentMesh._id,meshname:currentMesh.name,userid:t})}var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,xxcurrentView=-1;function go(e){if(setSessionActivity(),!xxdialogMode&&xxcurrentView!=e){updateFooterMenu(),setDialogMode(0);for(var t=0;t<32;t++)QV("p"+t,t==e);xxcurrentView=e}}function setDialogMode(e,t,o,n,i,a){setSessionActivity(),xxdialogMode=e,xxdialogFunc=n,xxdialogButtons=o,xxdialogTag=a,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&o),QV("idx_dlgCancelButton",2&o),QV("id_dialogclose",2&o||8&o),QV("idx_dlgButtonBar",7&o),t&&QH("id_dialogtitle",t);for(var s=1;s<24;s++)QV("dialog"+s,s==e);QV("dialog",e),i&&(2==e?QH("id_dialogOptions",i):QH("id_dialogMessage",i))}function dialogclose(e){setSessionActivity();var t=xxdialogFunc,o=xxdialogButtons,n=xxdialogTag;setDialogMode(),(8&o||e)&&t&&t(e,n)}function putstore(e,t){try{if("undefined"==typeof localStorage||localStorage.getItem(e)==t)return;null==t?localStorage.removeItem(e):localStorage.setItem(e,t)}catch(e){}if("_"!=e[0]){for(var o={},n=0,i=localStorage.length;n<i;++n){var a=localStorage.key(n);"_"!=a[0]&&(o[a]=localStorage.getItem(a))}meshserver.send({action:"userWebState",state:JSON.stringify(o)})}}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}}function center(){QS("dialog").left=(getDocWidth()-300)/2+"px",deskAdjust(),deskAdjust()}function messagebox(e,t){QH("id_dialogMessage",t),setDialogMode(1,e,1)}function statusbox(e,t){QH("id_dialogMessage",t),setDialogMode(1,e)}function getDocWidth(){return window.innerWidth?window.innerWidth:document.documentElement&&document.documentElement.clientWidth&&0!=document.documentElement.clientWidth?document.documentElement.clientWidth:document.getElementsByTagName("body")[0].clientWidth}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function haltReturn(e){13==e.keyCode&&haltEvent(e)}function validateEmail(e){return/^(([^<>()\[\]\\.,;:\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,}))$/.test(e)}function reload(){window.location.href=window.location.href}function getNodeFromId(e){for(var t in nodes)if(nodes[t]._id==e)return nodes[t];return null}function addHtmlValue(e,t){return"<table><td style=width:120px>"+e+"<td><b>"+t+"</b></table>"}function addHtmlValue2(e,t){return"<div><div style=display:inline-block;float:right>"+t+"</div><div style=display:inline-block>"+e+"</div></div>"}function addLink(e,t){return"<a style=cursor:pointer;color:darkblue;text-decoration:none onclick='"+t+"'>&diams; "+e+"</a>"}function addLinkConditional(e,t,o){return o?addLink(e,t):e}function passwordcheck(e){return/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/.test(e)}function getFileSizeStr(e){return 1==e?"1 byte":format("{0} bytes",e)}function joinPaths(){var e=[];for(var t in arguments){var o=arguments[t];if(null!=o&&""!=o){for(;o.endsWith("/")||o.endsWith("\\");)o=o.substring(0,o.length-1);for(;o.startsWith("/")||o.startsWith("\\");)o=o.substring(1);e.push(o)}}return e.join("/")}function focusTextBox(e){setTimeout(function(){Q(e).selectionStart=Q(e).selectionEnd=65535,Q(e).focus()},0)}isFilenameValid=function(){var t=/^[^\\/:\*\?"<>\|]+$/,o=/^\./,n=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i;return function(e){return t.test(e)&&!o.test(e)&&!n.test(e)&&"."!=e[0]}}();function parseUriArgs(){var e,t={},o=window.document.location.href.split(/[\?&|\=]/);for(n in o.splice(0,1),o)switch(n%2){case 0:e=decodeURIComponent(o[n]);break;case 1:t[e]=decodeURIComponent(o[n]);var n=parseInt(t[e]);n==t[e]&&(t[e]=n)}return t}function printDate(e){return e.toLocaleDateString(args.locale)}function printTime(e){return e.toLocaleTimeString(args.locale)}function printDateTime(e){return e.toLocaleString(args.locale)}function format(e){var o=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,t){return void 0!==o[t]?o[t]:e})}function nobreak(e){return e.split(" ").join("&nbsp;")}</script>
\ No newline at end of file
views/translations/default-mobile_pt.handlebars new
+3391
@@ -0,0 +1,3391 @@
1 +<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico">
8 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
9 + <script type="text/javascript" src="scripts/meshcentral.js"></script>
10 + <script type="text/javascript" src="scripts/agent-redir-ws-0.1.1.js"></script>
11 + <script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
12 + <script type="text/javascript" src="scripts/amt-0.2.0.js"></script>
13 + <script type="text/javascript" src="scripts/amt-redir-ws-0.1.0.js"></script>
14 + <script type="text/javascript" src="scripts/amt-desktop-0.0.2.js"></script>
15 + <script type="text/javascript" src="scripts/zlib.js"></script>
16 + <script type="text/javascript" src="scripts/zlib-inflate.js"></script>
17 + <script type="text/javascript" src="scripts/zlib-adler32.js"></script>
18 + <script type="text/javascript" src="scripts/zlib-crc32.js"></script>
19 + <script keeplink="1" type="text/javascript" src="scripts/filesaver.js"></script>
20 + <title>{{{title}}}</title>
21 + <style>
22 + a {
23 + color: #036;
24 + text-decoration: underline;
25 + }
26 +
27 + #footer a {
28 + color: #fff;
29 + text-decoration: underline;
30 + }
31 +
32 + #footer a:hover {
33 + color: #fff;
34 + text-decoration: none;
35 + }
36 +
37 + .i1 {
38 + background: url(../images/icons50.png) 0px 0px;
39 + height: 50px;
40 + width: 50px;
41 + border: none;
42 + }
43 +
44 + .i2 {
45 + background: url(../images/icons50.png) -50px 0px;
46 + height: 50px;
47 + width: 50px;
48 + border: none;
49 + }
50 +
51 + .i3 {
52 + background: url(../images/icons50.png) -100px 0px;
53 + height: 50px;
54 + width: 50px;
55 + border: none;
56 + }
57 +
58 + .i4 {
59 + background: url(../images/icons50.png) -150px 0px;
60 + height: 50px;
61 + width: 50px;
62 + border: none;
63 + }
64 +
65 + .i5 {
66 + background: url(../images/icons50.png) -200px 0px;
67 + height: 50px;
68 + width: 50px;
69 + border: none;
70 + }
71 +
72 + .i6 {
73 + background: url(../images/icons50.png) -250px 0px;
74 + height: 50px;
75 + width: 50px;
76 + border: none;
77 + }
78 +
79 + .m0 {
80 + background: url(../images/images16.png) -32px 0px;
81 + height: 16px;
82 + width: 16px;
83 + border: none;
84 + float: left;
85 + }
86 +
87 + .m1 {
88 + background: url(../images/images16.png) -16px 0px;
89 + height: 16px;
90 + width: 16px;
91 + border: none;
92 + float: left;
93 + }
94 +
95 + .m2 {
96 + background: url(../images/images16.png) -96px 0px;
97 + height: 16px;
98 + width: 16px;
99 + border: none;
100 + float: left;
101 + }
102 +
103 + .m3 {
104 + background: url(../images/images16.png) -112px 0px;
105 + height: 16px;
106 + width: 16px;
107 + border: none;
108 + float: left;
109 + }
110 +
111 + .gray {
112 + /*filter: url("data:image/svg+xml;utf8,&lt;svg xmlns=\'http://www.w3.org/2000/svg\'&gt;&lt;filter id=\'grayscale\'&gt;&lt;feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/&gt;&lt;/filter&gt;&lt;/svg&gt;#grayscale");*/ /* Firefox 10+, Firefox on Android */
113 + filter: gray; /* IE6-9 */
114 + -webkit-filter: grayscale(100%) opacity(60%); /* Chrome 19+, Safari 6+, Safari 6+ iOS */
115 + }
116 +
117 + .DevSt {
118 + padding-left: 5px;
119 + border-bottom-style: solid;
120 + border-bottom-width: 1px;
121 + border-bottom-color: #DDDDDD;
122 + }
123 +
124 + .noselect {
125 + -webkit-touch-callout: none;
126 + -webkit-user-select: none;
127 + -khtml-user-select: none;
128 + -moz-user-select: none;
129 + -ms-user-select: none;
130 + user-select: none;
131 + }
132 +
133 + .fileIcon1 {
134 + background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb49Y2Sj9LT2f///yH5BAEAAAMALAAAAAAQABAAAAImnI+py+1vhJwyUYAzHTL4D3qdlJWaIFJqmKod607sDKIiDUP63hQAOw==);
135 + height: 16px;
136 + width: 16px;
137 + cursor: pointer;
138 + border: none;
139 + float: left;
140 + margin-top: 1px;
141 + }
142 +
143 + .fileIcon2 {
144 + background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAM2xV/Xur+XPgP///yH5BAEAAAMALAAAAAAQABAAAAJD3ISZIGHWUGihznesYDYATFVM+D2hJ4lgN1olxALAtAlmPCJvuMmJd6PJckDYwicrHhTD5o7plJmg0Uc0asNMkphHAQA7);
145 + height: 16px;
146 + width: 16px;
147 + cursor: pointer;
148 + border: none;
149 + float: left;
150 + margin-top: 1px;
151 + }
152 +
153 + .fileIcon3 {
154 + background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb19IGBgbq6uv///yH5BAEAAAMALAAAAAAQABAAAAIy3ISpxgcPH2ouQgFEw1YmxnUXKEaaEZZnVWZk66JwzKpvuwZzwOgwb/C1gIOA8Yg8DgoAOw==);
155 + height: 16px;
156 + width: 16px;
157 + cursor: pointer;
158 + border: none;
159 + float: left;
160 + margin-top: 1px;
161 + }
162 +
163 + .fileIcon4 {
164 + background: url(../images/meshicon16.png);
165 + height: 16px;
166 + width: 16px;
167 + cursor: pointer;
168 + border: none;
169 + float: left;
170 + margin-top: 1px;
171 + }
172 +
173 + .filelist {
174 + -moz-user-select: none;
175 + -khtml-user-select: none;
176 + -webkit-user-select: none;
177 + -o-user-select: none;
178 + cursor: default;
179 + -khtml-user-drag: element;
180 + background-color: white;
181 + clear: both;
182 + }
183 + </style>
184 +</head>
185 +<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">
186 + <div id="container">
187 + <div id="mastheadx"></div>
188 + <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">
189 + <div style="width:calc(100% - 50px);overflow:hidden">
190 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px">
191 + <strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
192 + </div>
193 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px">
194 + <strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
195 + </div>
196 + </div>
197 + <img id="topMenuIcon" class="noselect" style="position:absolute;right:0;top:10px;bottom:50px;color:#c8c8c8;font-size:44px;margin-right:8px;cursor:pointer;display:none" onclick="topMenu()" src="/images/3bars-30.png" width="30" height="30">
198 + </div>
199 + <div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
200 + <div id="column_l" style="width:100%;padding:0;position:absolute;bottom:0px;top:0px">
201 + <div id="p0" style="display:none;width:100%;height:100%">
202 + <div style="display:flex;align-items:center;width:100%;height:100%">
203 + <div id="p0message" style="text-align:center;width:100%"><span id="p0span">Servidor desconectado</span>, <href onclick="reload()" style="cursor:pointer"><u>clique para reconectar</u></href>.</div>
204 + </div>
205 + </div>
206 + <div id="p1" style="display:none;width:100%;height:100%">
207 + <div style="display:flex;align-items:center;width:100%;height:100%">
208 + <div id="p1message" style="text-align:center;width:100%"></div>
209 + </div>
210 + </div>
211 + <div id="p2" style="display:none">
212 + <div id="xdevices"></div>
213 + </div>
214 + <div id="p3" style="display:none;position:absolute;bottom:0;top:0;width:100%">
215 + <table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;">
216 + <tbody><tr style="padding:0">
217 + <td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
218 + <div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
219 + <div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
220 + </div>
221 + <div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
222 + </td>
223 + <td>
224 + <img src="/images/user-50.png" width="50" height="50">
225 + </td>
226 + <td>
227 + <div style="margin-left:5px">
228 + <strong style="font-size:large"><span id="p3userName"></span></strong><br>
229 + </div>
230 + </td>
231 + </tr>
232 + </tbody></table>
233 + <div id="p3info" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
234 + <div style="margin-left:8px">
235 + <div id="p3AccountActions">
236 + <p><strong>Segurança da Conta</strong></p>
237 + <div style="margin-left:9px;margin-bottom:8px">
238 + <div id="manageAuthApp" style="margin-top:5px;display:none"><a onclick="account_manageAuthApp()" style="cursor:pointer">Gerenciar aplicativo autenticador</a></div>
239 + <div id="manageOtp" style="margin-top:5px;display:none"><a onclick="account_manageOtp(0)" style="cursor:pointer">Gerenciar códigos de backup</a></div>
240 + </div>
241 + <p><strong>Ações da Conta</strong></p>
242 + <div style="margin-left:9px;margin-bottom:8px">
243 + <div style="margin-top:5px"><span id="verifyEmailId" style="display:none"><a onclick="account_showVerifyEmail()" style="cursor:pointer">Verificar email</a></span></div>
244 + <div style="margin-top:5px"><span id="changeEmailId" style="display:none"><a onclick="account_showChangeEmail()" style="cursor:pointer">Mude o endereço de email</a></span></div>
245 + <div style="margin-top:5px"><a onclick="account_showChangePassword()" style="cursor:pointer">Mudar senha</a><span id="p2nextPasswordUpdateTime"></span></div>
246 + <div style="margin-top:5px"><a onclick="account_showDeleteAccount()" style="cursor:pointer">Deletar conta</a></div>
247 + </div>
248 + <br style="clear:both">
249 + </div>
250 + <strong>Grupos de dispositivos</strong>
251 + <span id="p3createMeshLink1">( <a onclick="account_createMesh()" style="cursor:pointer"><img src="images/icon-addnew.png" width="12" height="12" border="0"> Novo</a> )</span>
252 + <br><br>
253 + <div id="p3meshes"></div>
254 + <div id="p3noMeshFound" style="margin-left:9px;display:none">Nenhum grupo de dispositivos.<span id="p3createMeshLink2"> <a onclick="account_createMesh()" style="cursor:pointer"><strong>Comece aqui!</strong></a></span></div>
255 + <br style="clear:both">
256 + </div>
257 + </div>
258 + </div>
259 + <div id="p5" style="display:none">
260 + <table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;">
261 + <tbody><tr style="padding:0">
262 + <td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
263 + <div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
264 + <div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
265 + </div>
266 + <div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
267 + </td>
268 + <td>
269 + <img src="/images/user-50.png" width="50" height="50">
270 + </td>
271 + <td>
272 + <div style="margin-left:5px">
273 + <strong style="font-size:large">Meus arquivos</strong><br>
274 + </div>
275 + </td>
276 + </tr>
277 + </tbody></table>
278 + <div id="p5myfiles" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
279 + <table id="p5toolbar" style="width:100%;height:78px" cellpadding="0" cellspacing="0">
280 + <tbody><tr>
281 + <td style="width:100%;background-color:#d3d9d6;text-align:left;padding:4px" valign="bottom">
282 + <div style="width:100%;text-align:center">
283 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5FolderUp" disabled="disabled" onclick="p5folderup()" value="Acima">
284 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5SelectAllButton" disabled="disabled" onclick="p5selectallfile()" value="Selecionar tudo" onkeypress="return false" onkeydown="return false">
285 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5RenameFileButton" disabled="disabled" value="Renomear" onclick="p5renamefile()" onkeypress="return false" onkeydown="return false">
286 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5DeleteFileButton" disabled="disabled" value="Deletar" onclick="p5deletefile()" onkeypress="return false" onkeydown="return false">
287 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5NewFolderButton" disabled="disabled" value="Pasta" onclick="p5createfolder()" onkeypress="return false" onkeydown="return false">
288 + </div>
289 + <div style="width:100%;text-align:center">
290 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5UploadButton" disabled="disabled" value="Envio" onclick="p5uploadFile()" onkeypress="return false" onkeydown="return false">
291 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5CutButton" disabled="disabled" value="Cortar" onclick="p5copyFile(1)" onkeypress="return false" onkeydown="return false">
292 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5CopyButton" disabled="disabled" value="Copiar" onclick="p5copyFile(0)" onkeypress="return false" onkeydown="return false">
293 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5PasteButton" disabled="disabled" value="Colar" onclick="p5pasteFile()" onkeypress="return false" onkeydown="return false">
294 + <input type="button" style="width:calc(100%/5 - 5px)" id="p5RefreshButton" value="Atualizar" onclick="p5refreshFiles()" onkeypress="return false" onkeydown="return false">
295 + </div>
296 + </td>
297 + </tr>
298 + <tr>
299 + <td style="background-color:#E4E9E7;height:28px">
300 + <table style="width:100%">
301 + <tbody><tr>
302 + <td id="p5currentpath" style="overflow:hidden;padding-left:4px;padding-top:2px"></td>
303 + <td style="text-align:right;padding-right:4px">
304 + <select id="p5sortdropdown" onchange="updateFiles()">
305 + <option value="1" selected="selected">Classificar por nome</option>
306 + <option value="2">Classificar por tamanho</option>
307 + <option value="3">Classificar por data</option>
308 + <option value="4">Decrescente por nome</option>
309 + <option value="5">Decrescente por tamanho</option>
310 + <option value="6">Descrescente por data</option>
311 + </select>
312 + </td>
313 + </tr>
314 + </tbody></table>
315 + </td>
316 + </tr>
317 + </tbody></table>
318 + <div id="p5filetable" style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none">
319 + <!--
320 + <div id="p5bigok" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>&checkmark;</b></div>
321 + <div id="p5bigfail" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>&#10007;</b></div>
322 + -->
323 + <span id="p5files"></span>
324 + </div>
325 + <table id="p5toolbarBottom" style="width:100%;height:22px;position:absolute;bottom:0px;background-color:#D3D9D6" cellpadding="0" cellspacing="0">
326 + <tbody><tr>
327 + <td style="text-align:left;padding:3px">&nbsp;<span id="p5bottomstatus"></span></td>
328 + <td id="p5rightOfButtons" style="text-align:right;padding:3px"></td>
329 + </tr>
330 + </tbody></table>
331 + </div>
332 + </div>
333 + <div id="p10" style="display:none;position:absolute;bottom:0;top:0;width:100%;overflow:hidden">
334 + <table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;position:absolute;top:0">
335 + <tbody><tr style="padding:0">
336 + <td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
337 + <div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
338 + <div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
339 + </div>
340 + <div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
341 + </td>
342 + <td>
343 + <a id="MainComputerImage" style="cursor:pointer" onclick="p10showiconselector()"></a>
344 + </td>
345 + <td>
346 + <div style="margin-left:5px">
347 + <strong><span id="p10deviceName"></span></strong><br>
348 + <span id="MainComputerState"></span>
349 + </div>
350 + </td>
351 + </tr>
352 + </tbody></table>
353 + <div id="p10general" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
354 + <div id="p10html" style="margin-left:8px;margin-right:8px"></div>
355 + <div id="p10html2"></div>
356 + <div id="p10html3"></div>
357 + </div>
358 + <div id="p10desktop" style="overflow:hidden;position:absolute;top:55px;bottom:0px;width:100%;display:none">
359 + <div id="deskarea1" style="position:absolute;top:0px;width:100%;height:25px">
360 + <div style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
361 + <div style="float:right;text-align:right">
362 + <span id="p14power"></span>&nbsp;
363 + <input id="DeskSoftInput" type="text" style="width:25px;display:none;opacity:.2" onblur="toggleSoftKeys(0)" onkeypress="return ondeskkeypress(event)" onkeydown="return ondeskkeydown(event)" onkeyup="return ondeskkeyup(event)">
364 + </div>
365 + <div style="margin-left:3px">
366 + <input type="button" id="connectbutton1" value="Conectar" onclick="connectDesktop(event,1)" onkeypress="return false" onkeydown="return false" disabled="disabled">
367 + <input type="button" id="connectbutton1h" value="Conectar HW" onclick="connectDesktop(event,2)" onkeypress="return false" onkeydown="return false" disabled="disabled">
368 + <input type="button" id="disconnectbutton1" value="Desconectar" onclick="connectDesktop(event,0)" onkeypress="return false" onkeydown="return false">
369 + <span id="deskstatus">Desconectado</span>
370 + </div>
371 + </div>
372 + </div>
373 + <div id="deskarea3" style="position:absolute;top:25px;width:100%;height:calc(100% - 50px)">
374 + <div id="deskarea3x" style="background:black;text-align:center;height:100%;position:relative">
375 + <div id="DeskParent" style="height:100%">
376 + <canvas id="Desk" width="640" height="200" style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)" onmousewheel="dmousewheel(event)"></canvas>
377 + </div>
378 + <div id="DeskTools" style="position:absolute;width:400px;height:100%;background-color:gray;top:0;right:0;border-left:2px solid lightgray;display:none">
379 + <a id="DeskToolsRefreshButton" style="float:right;padding:3px;cursor:pointer" onclick="refreshDeskTools()">Atualizar</a>
380 + <div id="DeskToolsBar" style="position:absolute;padding:3px;border-radius: 3px 3px 0px 0px;top:5px;left:4px;bottom:26px;background-color:lightgray;cursor:pointer">Processos</div>
381 + <div style="position:absolute;top:26px;left:4px;right:4px;bottom:4px;background-color:lightgray;text-align:left">
382 + <div style="border-bottom:1px solid darkgray;padding:3px"><a style="width:50px;padding-right:5px;float:left;cursor:pointer" onclick="sortProcess(0)">PID</a><a style="cursor:pointer" onclick="sortProcess(1)">Nome</a></div>
383 + <div id="DeskToolsProcesses" style="overflow-y:scroll;position:absolute;top:24px;bottom:0px;width:100%"></div>
384 + </div>
385 + </div>
386 + </div>
387 + </div>
388 + <div id="deskarea4" style="position:absolute;bottom:0px;width:100%;height:25px">
389 + <div style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
390 + <div style="float:right;text-align:right">
391 + <select id="termdisplays" style="display:none" onchange="deskSetDisplay(event)" onclick="deskGetDisplayNumbers(event)"></select>&nbsp;
392 + <span id="DeskToastButton"><img src="images/icon-notify.png" onclick="deviceToastFunction()" height="16" width="16" style="padding-top:2px"></span>&nbsp;
393 + <!--<input id=DeskToolsButton type=button value=Tools onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">&nbsp;-->
394 + </div>
395 + <div>
396 + <input id="deskActionsBtn" type="button" style="margin-left:3px" onkeypress="return false" onkeydown="return false" value="Ações" onclick="deviceActionFunction()">
397 + <input type="button" value="Configurações" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()">
398 + <input type="button" onkeypress="return false" onkeydown="return false" value="Ações de energia (Ligar/Desligar)" onclick="showPowerActionDlg()" style="display:none">
399 + <input id="DeskSpecialKeys" type="button" value="Chaves especiais" onkeypress="return false" onkeydown="return false" onclick="sendSpecialKeys()">
400 + <input id="DeskSoftKeys" type="button" value="Teclado" onkeypress="return false" onkeydown="return false" onclick="toggleSoftKeys(1)">
401 + <label><span id="DeskControlSpan" style="display:none"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false">Entrada</span></label>
402 + </div>
403 + </div>
404 + </div>
405 + </div>
406 + <div id="p10files" style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%;display:none">
407 + <table id="p13toolbar" style="width:100%;height:111px" cellpadding="0" cellspacing="0">
408 + <tbody><tr>
409 + <td style="background-color:#C0C0C0;border-bottom:2px solid black;padding:2px">
410 + <div style="float:right;text-align:right">
411 + <input id="filesActionsBtn" type="button" onkeypress="return false" onkeydown="return false" value="Ações" onclick="deviceActionFunction()" style="margin-right:2px">
412 + </div>
413 + <div style="margin-left:2px">
414 + <input id="p13AutoConnect" value="Conexão automática" onclick="autoConnectFiles(event)" onkeypress="return false" onkeydown="return false" type="button" style="display:none">
415 + <input id="p13Connect" value="Conectar" onclick="connectFiles(event)" onkeypress="return false" onkeydown="return false" type="button">
416 + <span id="p13Status">Desconectado</span>
417 + </div>
418 + </td>
419 + </tr>
420 + <tr>
421 + <td style="width:100%;background-color:#d3d9d6;text-align:left;padding:4px" valign="bottom">
422 + <div style="width:100%;text-align:center">
423 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13FolderUp" disabled="disabled" onclick="p13folderup()" value="Acima">
424 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13SelectAllButton" disabled="disabled" onclick="p13selectallfile()" value="Selecionar tudo" onkeypress="return false" onkeydown="return false">
425 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13RenameFileButton" disabled="disabled" value="Renomear" onclick="p13renamefile()" onkeypress="return false" onkeydown="return false">
426 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13DeleteFileButton" disabled="disabled" value="Deletar" onclick="p13deletefile()" onkeypress="return false" onkeydown="return false">
427 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13NewFolderButton" disabled="disabled" value="Pasta" onclick="p13createfolder()" onkeypress="return false" onkeydown="return false">
428 + </div>
429 + <div style="width:100%;text-align:center">
430 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13UploadButton" disabled="disabled" value="Envio" onclick="p13uploadFile()" onkeypress="return false" onkeydown="return false">
431 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13CutButton" disabled="disabled" value="Cortar" onclick="p13copyFile(1)" onkeypress="return false" onkeydown="return false">
432 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13CopyButton" disabled="disabled" value="Copiar" onclick="p13copyFile(0)" onkeypress="return false" onkeydown="return false">
433 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13PasteButton" disabled="disabled" value="Colar" onclick="p13pasteFile()" onkeypress="return false" onkeydown="return false">
434 + <input type="button" style="width:calc(100%/5 - 5px)" id="p13RefreshButton" disabled="disabled" value="Atualizar" onclick="p13folderup(9999)" onkeypress="return false" onkeydown="return false">
435 + </div>
436 + </td>
437 + </tr>
438 + <tr>
439 + <td style="background-color:#E4E9E7;height:28px">
440 + <table style="width:100%">
441 + <tbody><tr>
442 + <td id="p13currentpath" style="overflow:hidden;padding-left:4px;padding-top:2px"></td>
443 + <td style="text-align:right;padding-right:4px">
444 + <select id="p13sortdropdown" onchange="p13updateFiles()">
445 + <option value="1" selected="selected">Classificar por nome</option>
446 + <option value="2">Classificar por tamanho</option>
447 + <option value="3">Classificar por data</option>
448 + <option value="4">Decrescente por nome</option>
449 + <option value="5">Decrescente por tamanho</option>
450 + <option value="6">Descrescente por data</option>
451 + </select>
452 + </td>
453 + </tr>
454 + </tbody></table>
455 + </td>
456 + </tr>
457 + </tbody></table>
458 + <div id="p13filetable" style="width:100%;height:calc(100% - 133px);overflow:auto;-webkit-user-select:none">
459 + <!--
460 + <div id="p13bigok" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>&checkmark;</b></div>
461 + <div id="p13bigfail" style="width:256px;overflow:hidden;position:absolute;left:337px;top:200px;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>&#10007;</b></div>
462 + -->
463 + <span id="p13files"></span>
464 + </div>
465 + <table id="p13toolbarBottom" style="width:100%;height:22px;position:absolute;bottom:0px" cellpadding="0" cellspacing="0">
466 + <tbody><tr><td style="text-align:left;padding:3px;text-align:center;background-color:#D3D9D6">&nbsp;<span id="p13bottomstatus"></span></td></tr>
467 + </tbody></table>
468 + </div>
469 + </div>
470 + <div id="p20" style="display:none;position:absolute;bottom:0;top:0;width:100%">
471 + <table cellspacing="0" style="margin:0;padding:0;border-spacing:0;border:0;">
472 + <tbody><tr style="padding:0">
473 + <td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width="60px" valign="top" onclick="goBack()">
474 + <div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
475 + <div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
476 + </div>
477 + <div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
478 + </td>
479 + <td onclick="p20editmesh(1)">
480 + <img src="/images/meshicon50.png" width="50" height="50">
481 + </td>
482 + <td onclick="p20editmesh(1)">
483 + <div style="margin-left:5px">
484 + <strong style="font-size:large"><span id="p20meshName"></span></strong><br>
485 + </div>
486 + </td>
487 + </tr>
488 + </tbody></table>
489 + <div id="p20info" style="margin-left:8px;margin-right:8px"></div>
490 + </div>
491 + </div>
492 + </div>
493 + <div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
494 + <table id="footerMenu" cellpadding="0" cellspacing="0" style="height:32px;width:100%;color:white;cursor:pointer;table-layout:fixed"></table>
495 + </div>
496 + </div>
497 + <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:90px;width:300px;display:none">
498 + <div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
499 + <div id="id_dialogclose" style="float:right;padding:5px;cursor:pointer" onclick="setDialogMode()"><b>X</b></div>
500 + <div id="id_dialogtitle" style="padding:5px"></div>
501 + <div style="width:100%;margin:6px"></div>
502 + </div>
503 + <div style="margin-right:16px;margin-left:8px">
504 + <div id="dialog1" style="margin:auto;text-align:center;margin:3px">
505 + <div id="id_dialogMessage" style="padding:10px"></div>
506 + </div>
507 + <div id="dialog2" style="margin:auto;margin:3px">
508 + <div id="id_dialogOptions"></div>
509 + </div>
510 + <div id="dialog3" style="margin:auto;margin:3px">
511 + <select id="deskkeys" style="width:100%">
512 + <option value="10">CTRL+ALT+DEL</option>
513 + <option value="11">Tab</option>
514 + <option value="5">Win</option>
515 + <option value="0">Win+Down</option>
516 + <option value="1">Win+Up</option>
517 + <option value="2">Win+L</option>
518 + <option value="3">Win+M</option>
519 + <option value="4">Shift+Win+M</option>
520 + <option value="6">Win+R</option>
521 + <option value="7">Alt-F4</option>
522 + <option value="8">CTRL-W</option>
523 + <option value="9">Alt-Tab</option>
524 + </select>
525 + </div>
526 + <div id="dialog7" style="margin:auto;margin:3px">
527 + <div id="d7meshkvm">
528 + <h4 style="width:100%;border-bottom:1px solid gray">Área de trabalho remota do agente</h4>
529 + <div style="margin:3px 0 3px 0">
530 + <select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl"></select>
531 + <div style="height:20px">Qualidade</div>
532 + </div>
533 + <div style="margin:3px 0 3px 0">
534 + <select id="d7bitmapscaling" style="float:right;width:200px;height:20px" dir="rtl">
535 + <option selected="selected" value="1024">100%</option>
536 + <option value="896">87.5%</option>
537 + <option value="768">75%</option>
538 + <option value="640">62.5%</option>
539 + <option value="512">50%</option>
540 + <option value="384">37..5%</option>
541 + <option value="256">25%</option>
542 + <option value="128">12.5%</option>
543 + </select>
544 + <div style="height:20px">Dimensionamento</div>
545 + </div>
546 + <div style="margin:3px 0 3px 0">
547 + <select id="d7framelimiter" style="float:right;width:200px;height:20px" dir="rtl">
548 + <option selected="selected" value="50">Rápido</option>
549 + <option value="100">Médio</option>
550 + <option value="400">Lento</option>
551 + <option value="1000">Muito devagar</option>
552 + </select>
553 + <div style="height:20px">Taxa</div>
554 + </div>
555 + </div>
556 + <div id="d7amtkvm">
557 + <h4 style="width:100%;border-bottom:1px solid gray">Intel® AMT Hardware KVM</h4>
558 + <div style="height:26px">
559 + <select id="d7desktopmode" style="float:right;width:200px">
560 + <option value="1">RLE8, mais rápido</option>
561 + <option value="2">RLE16, Recomendado</option>
562 + <option value="3">RAW8, lento</option>
563 + <option value="4">RAW16, muito lento</option>
564 + </select>
565 + <div>Codificação</div>
566 + </div>
567 + <div style="height:60px">
568 + <div style="float:right;border:1px solid #666;width:200px;height:60px;overflow-y:scroll;background-color:white">
569 + <label><input type="checkbox" id="d7showfocus">Mostrar ferramenta de foco</label><br>
570 + <label><input type="checkbox" id="d7showcursor">Mostrar Cursor do Mouse Local</label><br>
571 + </div>
572 + <div>Outro</div>
573 + </div>
574 + </div>
575 + </div>
576 + </div>
577 + <div id="idx_dlgButtonBar" style="padding:10px;margin-bottom:20px">
578 + <input id="idx_dlgCancelButton" type="button" value="Cancelar" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
579 + <input id="idx_dlgOkButton" type="button" value="Ok" style="float:right;width:80px" onclick="dialogclose(1)">
580 + </div>
581 + </div>
582 + <div id="topMenu" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:0px 0px 5px 5px;position:fixed;top:50px;right:5px;width:170px;display:none">
583 + <div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer" onclick="topMenu(2)">Meus arquivos</div>
584 + <div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer" onclick="topMenu(1)">Minha conta</div>
585 + <div id="logoutMenuOption"><a href="/logout"><div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer">Sair</div></a></div>
586 + </div>
587 + <iframe name="fileUploadFrame" style="display:none"></iframe>
588 + <script>
589 + 'use strict';
590 +
591 + // Process server-side web state
592 + var webState = '{{{webstate}}}';
593 + if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
594 + for (var i in webState) { localStorage.setItem(i, webState[i]); }
595 + if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
596 +
597 + var args = parseUriArgs();
598 + var debugLevel = parseInt('{{{debuglevel}}}');
599 + var features = parseInt('{{{features}}}');
600 + var sessionTime = parseInt('{{{sessiontime}}}');
601 + var domain = '{{{domain}}}';
602 + var domainUrl = '{{{domainurl}}}';
603 + var authCookie = '{{{authCookie}}}';
604 + var authRelayCookie = '{{{authRelayCookie}}}';
605 + var authCookieRenewTimer = null;
606 + var meshserver = null;
607 + var xdr = null;
608 + var serverinfo = null;
609 + var nodes = [];
610 + var meshes = {};
611 + var filetree = {};
612 + var userinfo = null;
613 + var serverinfo = null;
614 + var users = null;
615 + var nodeShortIdent = 0;
616 + var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
617 + var debugmode = false;
618 + var attemptWebRTC = ((features & 128) != 0);
619 + var StatusStrs = ["Desconectado", "Conectando...", "Configurando...", "Conectado", "Intel&reg; AMT conectado"];
620 + var files;
621 + var passRequirements = '{{{passRequirements}}}';
622 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
623 + var sessionActivity = Date.now();
624 +
625 + function startup() {
626 + if ((features & 32) == 0) {
627 + // Guard against other site's top frames (web bugs).
628 + var loc = null;
629 + try { loc = top.location.toString().toLowerCase(); } catch (e) { }
630 + if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
631 + }
632 +
633 + if (!args.locale) { var x = getstore('loctag', 0); if ((x != null) && (x != '*')) { args.locale = x; } }
634 +
635 + window.onresize = center;
636 + center();
637 + QV('changeEmailId', (features & 0x200000) == 0);
638 + QH('p1message', "Conectando...");
639 + go(1);
640 +
641 + // Connect to the mesh server
642 + meshserver = MeshServerCreateControl(domainUrl, authCookie);
643 + meshserver.onStateChanged = onStateChanged;
644 + meshserver.onMessage = onMessage;
645 + meshserver.Start();
646 +
647 + // Load desktop settings
648 + var t = localStorage.getItem('desktopsettings');
649 + if (t != null) { desktopsettings = JSON.parse(t); }
650 + applyDesktopSettings();
651 + }
652 +
653 + function onStateChanged(server, state, prevState, errorCode) {
654 + if (state == 0) {
655 + // Control web socket disconnected
656 + setDialogMode(0); // Close any dialog boxes if present
657 + go(0); // Go to disconnection panel
658 + if (errorCode == 'noauth') { QH('p0span', "Não foi possível executar a autenticação"); return; }
659 + if (prevState == 2) { setTimeout(serverPoll, 5000); } else { QH('p0span', "Não foi possível conectar o soquete da web"); }
660 + // Clean up here
661 + if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
662 + } else if (state == 2) {
663 + // Fetch list of meshes, nodes, files
664 + meshserver.send({ action: 'meshes' });
665 + meshserver.send({ action: 'nodes' });
666 + meshserver.send({ action: 'files' });
667 + if (xxcurrentView < 2) { go(2); }
668 + authCookieRenewTimer = setInterval(function () { meshserver.send({ action: 'authcookie' }); }, 1800000); // Request a cookie refresh every 30 minutes.
669 + }
670 + QV('topMenuIcon', state == 2);
671 + }
672 +
673 + // Poll the server, if it responds, refresh the page.
674 + function serverPoll() {
675 + xdr = null;
676 + try { xdr = new XDomainRequest(); } catch (e) { }
677 + if (!xdr) xdr = new XMLHttpRequest();
678 + xdr.open('HEAD', window.location.href);
679 + xdr.timeout = 15000;
680 + xdr.onload = function () { reload(); };
681 + xdr.onerror = xdr.ontimeout = function () { setTimeout(serverPoll, 10000); };
682 + xdr.send();
683 + }
684 +
685 + function updateSelf() {
686 + QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
687 + QV('manageAuthApp', features & 4096);
688 + QV('manageOtp', ((features & 4096) != 0) && ((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0)));
689 +
690 + // On the mobile app, don't allow group creation (for now).
691 + QV('p3createMeshLink1', false);
692 + QV('p3createMeshLink2', false);
693 +
694 + if (typeof userinfo.passchange == 'number') {
695 + if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', "- Redefinir no próximo login."); }
696 + else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
697 + var seconds = (userinfo.passchange) + (passRequirements.reset * 86400) - Math.floor(Date.now() / 1000);
698 + if (seconds < 0) { QH('p2nextPasswordUpdateTime', "- Redefinir no próximo login."); }
699 + else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} minuto {1}.", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
700 + else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} hora {1}.", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
701 + else { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} dia {1}."), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
702 + }
703 + }
704 + }
705 +
706 + function addLetterS(x) { return (x > 1) ? 's' : ''; }
707 + function setSessionActivity() { sessionActivity = Date.now(); }
708 + function checkIdleSessionTimeout() { var delta = (Date.now() - sessionActivity); if (delta > serverinfo.timeout) { window.location.href = 'logout'; } }
709 +
710 + function onMessage(server, message) {
711 + switch (message.action) {
712 + case 'serverinfo': {
713 + serverinfo = message.serverinfo;
714 + if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
715 + QV('p3AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
716 + QV('logoutMenuOption', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide logout if in single user mode or domain authentication
717 + break;
718 + }
719 + case 'authcookie': {
720 + // Got an authentication cookie refresh
721 + authCookie = message.cookie;
722 + authRelayCookie = message.rcookie;
723 + break;
724 + }
725 + case 'userinfo': {
726 + userinfo = message.userinfo;
727 + QH('p3userName', userinfo.name);
728 + //updateSiteAdmin();
729 + updateSelf();
730 + break;
731 + }
732 + case 'users': {
733 + users = {};
734 + for (var m in message.users) { users[message.users[m]._id] = message.users[m]; }
735 + updateUsers();
736 + break;
737 + }
738 + case 'wssessioncount': {
739 + wssessions = message.wssessions;
740 + updateUsers();
741 + break;
742 + }
743 + case 'meshes': {
744 + meshes = {};
745 + for (var m in message.meshes) { meshes[message.meshes[m]._id] = message.meshes[m]; }
746 + updateMeshes();
747 + updateDevices();
748 + break;
749 + }
750 + case 'files': {
751 + filetree = setupBackPointers(message.filetree);
752 + updateFiles();
753 + //d3updatefiles();
754 + break;
755 + }
756 + case 'nodes': {
757 + nodes = [];
758 + for (var m in message.nodes) {
759 + for (var n in message.nodes[m]) {
760 + if (!meshes[m]) { console.log('Invalid mesh (1): ' + m); continue; }
761 + message.nodes[m][n].namel = message.nodes[m][n].name.toLowerCase();
762 + if (message.nodes[m][n].rname) { message.nodes[m][n].rnamel = message.nodes[m][n].rname.toLowerCase(); } else { message.nodes[m][n].rnamel = message.nodes[m][n].namel; }
763 + message.nodes[m][n].meshnamel = meshes[m].name.toLowerCase();
764 + message.nodes[m][n].meshid = m;
765 + message.nodes[m][n].state = (message.nodes[m][n].state) ? (message.nodes[m][n].state) : 0;
766 + message.nodes[m][n].desc = message.nodes[m][n].desc;
767 + if (!message.nodes[m][n].icon) message.nodes[m][n].icon = 1;
768 + message.nodes[m][n].ident = ++nodeShortIdent;
769 + nodes.push(message.nodes[m][n]);
770 + }
771 + }
772 + //onSortSelectChange();
773 + //onSearchInputChanged();
774 + updateDevices();
775 + //refreshMap(false, true);
776 + if (xxcurrentView == 0) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(2); } }
777 + if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}', parseInt('{{viewmode}}')); }
778 + break;
779 + }
780 + case 'powertimeline': {
781 + if (message.nodeid != powerTimelineReq) break;
782 + powerTimelineNode = message.nodeid;
783 + powerTimeline = message.timeline;
784 + powerTimelineUpdate = Date.now() + 300000; // Update every 5 minutes
785 + if (currentNode._id == message.nodeid) { drawDeviceTimeline(); }
786 + break;
787 + }
788 + case 'otpauth-request': {
789 + if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-request')) {
790 + var secret = message.secret;
791 + if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
792 + else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
793 + QH('d2optinfo', "Install <a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank>Google Authenticator</a> or a compatible application, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login." + '<br /><br /><div style=width:100%;text-align:center><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:15px>' + secret + '</tt><br /><br />Token: <input type=text onkeypress=\"return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></div>');
794 + QV('idx_dlgOkButton', true);
795 + QE('idx_dlgOkButton', false);
796 + Q('d2otpauthinput').focus();
797 + }
798 + break;
799 + }
800 + case 'otpauth-setup': {
801 + if (xxdialogMode) return;
802 + setDialogMode(2, "Autenticador de aplicativo", 1, null, message.success ? "<b style=color:green> ativação de login em duas etapas </b>. Agora você precisará de um token válido para fazer login novamente." : "<b style=color:red> falha na ativação do login em duas etapas </b>. Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto.");
803 + break;
804 + }
805 + case 'otpauth-clear': {
806 + if (xxdialogMode) return;
807 + setDialogMode(2, "Autenticador de aplicativo", 1, null, message.success ? "<b style=color:green>Ativação de login em duas etapas removida</b>. Você pode reativar esse recurso a qualquer momento." : "<b style=color:red> falha na remoção da ativação do login em duas etapas </b>. Tente novamente.");
808 + break;
809 + }
810 + case 'otpauth-getpasswords': {
811 + if (xxdialogMode) return;
812 + var x = "Os tokens únicos podem ser usados como autenticação secundária. Gere um conjunto, imprima-os e mantenha-os em um local seguro.";
813 + x += '<div style=\'border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px\'><div style=\'padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold\'><table style=width:100%;text-align:center>';
814 + if (message.passwords) {
815 + var j = 0;
816 + for (var i in message.passwords) {
817 + if (++j % 2) { x += '<tr>'; }
818 + var p = '' + message.passwords[i].p;
819 + while (p.length < 8) { p = '0' + p; }
820 + if (message.passwords[i].u === true) { x += '<td>' + p.substring(0, 4) + '&nbsp;' + p.substring(4); } else { x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + '&nbsp;' + p.substring(4); + '</strike>'; }
821 + }
822 + } else {
823 + x += '<tr><td>' + "Nenhum token ativo";
824 + }
825 + x += '</table></div></div><br />';
826 + x += '<div><input type=button value=\'' + "Fechar" + '\' onclick=setDialogMode(0) style=float:right></input>';
827 + x += '<input type=button value=\'' + "Novos tokens" + '\' onclick=\'account_manageOtp(1);\'></input>';
828 + if (message.passwords != null) { x += '<input type=button value=\'' + "Limpo" + '\' onclick=\'account_manageOtp(2);\'></input>'; }
829 + x += '</div><br />';
830 + setDialogMode(2, "Gerenciar códigos de backup", 8, null, x, 'otpauth-manage');
831 + break;
832 + }
833 + case 'event': {
834 + /*
835 + if (!message.event.nolog) {
836 + events.unshift(message.event);
837 + var eventLimit = parseInt(p3limitdropdown.value);
838 + while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
839 + events_update();
840 + }
841 + */
842 + if (message.event.noact) break; // Take no action on this event
843 + switch (message.event.action) {
844 + case 'userWebState': {
845 + // New user web state, update the web page as needed
846 + if (localStorage != null) {
847 + var webstate = JSON.parse(message.event.state);
848 + for (var i in webstate) { localStorage.setItem(i, webstate[i]); }
849 +
850 + // Update the web page
851 + if ((webstate.loctag != null) && (webstate.loctag != oldLoctag)) {
852 + if (webstate.loctag != null) { args.locale = webstate.loctag; } else { delete args.locale; }
853 + updateDevices();
854 + updateMeshes();
855 + }
856 + }
857 + break;
858 + }
859 + case 'accountchange': {
860 + // An account was created or changed
861 + if (userinfo.name == message.event.account.name) {
862 + var newsiteadmin = message.event.account.siteadmin ? message.event.account.siteadmin : 0;
863 + var oldsiteadmin = userinfo.siteadmin ? userinfo.siteadmin : 0;
864 + if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
865 + userinfo = message.event.account;
866 + if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
867 + updateSelf();
868 + }
869 + break;
870 + }
871 + case 'createmesh': {
872 + // A new mesh was created
873 + if (message.event.links[userinfo._id] != null) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some.
874 + meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
875 + updateMeshes();
876 + updateDevices();
877 + meshserver.send({ action: 'files' });
878 + }
879 + break;
880 + }
881 + case 'meshchange': {
882 + // Update mesh information
883 + if (meshes[message.event.meshid] == null) {
884 + // This is a new mesh for us
885 + meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
886 + meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
887 + } else {
888 + // This is an existing mesh
889 + if (meshes[message.event.meshid].name != message.event.name) {
890 + meshes[message.event.meshid].name = message.event.name;
891 + for (var i in nodes) { if (nodes[i].meshid == message.event.meshid) { nodes[i].meshnamel = message.event.name.toLowerCase(); } }
892 + }
893 + meshes[message.event.meshid].desc = message.event.desc;
894 + meshes[message.event.meshid].links = message.event.links;
895 +
896 + // Check if we lost rights to this mesh in this change.
897 + if (meshes[message.event.meshid].links[userinfo._id] == null) {
898 + if ((xxcurrentView == 20) && (currentMesh == meshes[message.event.meshid])) go(2);
899 + delete meshes[message.event.meshid];
900 +
901 + // Delete all nodes in that mesh
902 + var newnodes = [];
903 + for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } }
904 + nodes = newnodes;
905 +
906 + // If we are looking at a node in the deleted mesh, move back to "My Devices"
907 + if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(2); }
908 + }
909 + }
910 + updateMeshes();
911 + updateDevices();
912 + meshserver.send({ action: 'files' });
913 +
914 + // If we are looking at a mesh that is now deleted, move back to "My Account"
915 + if (xxcurrentView == 20 && currentMesh._id == message.event.meshid) { p20updateMesh(); }
916 + break;
917 + }
918 + case 'deletemesh': {
919 + // Delete the mesh
920 + if (meshes[message.event.meshid]) {
921 + delete meshes[message.event.meshid];
922 + updateMeshes();
923 + meshserver.send({ action: 'files' });
924 + }
925 +
926 + // Delete all nodes in that mesh
927 + var newnodes = [];
928 + for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } }
929 + nodes = newnodes;
930 + updateDevices();
931 +
932 + // If we are looking at a mesh that is now deleted, move back to "My Account"
933 + if (xxcurrentView >= 20 && xxcurrentView < 30 && currentMesh._id == message.event.meshid) { setDialogMode(0); go(2); }
934 + // If we are looking at a node in the deleted mesh, move back to "My Devices"
935 + if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(2); }
936 +
937 + break;
938 + }
939 + case 'addnode': {
940 + var node = message.event.node;
941 + if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
942 + if (getNodeFromId(node._id) != null) break; // This node is already known.
943 + node.namel = node.name.toLowerCase();
944 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
945 + node.meshnamel = meshes[node.meshid].name.toLowerCase();
946 + node.state = 0;
947 + if (!node.icon) node.icon = 1;
948 + node.ident = ++nodeShortIdent;
949 + nodes.push(node);
950 + //onSortSelectChange();
951 + //onSearchInputChanged();
952 + updateDevices();
953 + //updateMapMarkers();
954 + break;
955 + }
956 + case 'removenode': {
957 + var index = -1;
958 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
959 + if (index != -1) {
960 + var node = nodes[index];
961 + if (currentNode == node) {
962 + if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(2); }
963 + currentNode = null;
964 + // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
965 + }
966 + nodes.splice(index, 1);
967 + updateDevices();
968 + //updateMapMarkers();
969 + }
970 + break;
971 + }
972 + case 'changenode': {
973 + var index = -1;
974 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
975 + if (index != -1) {
976 + var node = nodes[index];
977 +
978 + // Change the node
979 + node.name = message.event.node.name;
980 + node.rname = message.event.node.rname;
981 + node.host = message.event.node.host;
982 + node.desc = message.event.node.desc;
983 + node.publicip = message.event.node.publicip;
984 + node.iploc = message.event.node.iploc;
985 + node.wifiloc = message.event.node.wifiloc;
986 + node.gpsloc = message.event.node.gpsloc;
987 + node.tags = message.event.node.tags;
988 + node.userloc = message.event.node.userloc;
989 + if (message.event.node.agent != null) {
990 + if (node.agent == null) node.agent = {};
991 + if (message.event.node.agent.ver != null) { node.agent.ver = message.event.node.agent.ver; }
992 + if (message.event.node.agent.id != null) { node.agent.id = message.event.node.agent.id; }
993 + if (message.event.node.agent.caps != null) { node.agent.caps = message.event.node.agent.caps; }
994 + if (message.event.node.agent.core != null) { node.agent.core = message.event.node.agent.core; } else { if (node.agent.core) { delete node.agent.core; } }
995 + node.agent.tag = message.event.node.agent.tag;
996 + }
997 + if (message.event.node.intelamt != null) {
998 + if (node.intelamt == null) node.intelamt = {};
999 + if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; }
1000 + if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; }
1001 + if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; }
1002 + if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; }
1003 + if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; }
1004 + if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; }
1005 + if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; }
1006 + if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; }
1007 + }
1008 + node.namel = node.name.toLowerCase();
1009 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1010 + if (message.event.node.icon) { node.icon = message.event.node.icon; }
1011 +
1012 + //onSortSelectChange(true);
1013 + //drawNotifications();
1014 + refreshDevice(node._id);
1015 + //updateMapMarkers();
1016 + updateDevices();
1017 +
1018 + //if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
1019 + }
1020 + break;
1021 + }
1022 + case 'nodemeshchange': {
1023 + var index = -1;
1024 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1025 + if (index != -1) {
1026 + var node = nodes[index];
1027 + if (meshes[message.event.newMeshId] == null) {
1028 + // We don't see the new mesh, remove this device
1029 +
1030 + // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
1031 + if (currentNode == node) { if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(2); } currentNode = null; }
1032 + nodes.splice(index, 1);
1033 + } else {
1034 + // We see the new mesh, move this device
1035 + node.meshid = message.event.newMeshId;
1036 + node.meshnamel = meshes[message.event.newMeshId].name.toLowerCase();
1037 + }
1038 + updateDevices();
1039 + refreshDevice(message.event.nodeid);
1040 + } else {
1041 + // This is a new device, add it.
1042 + var node = message.event.node;
1043 + if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
1044 + node.namel = node.name.toLowerCase();
1045 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1046 + node.meshnamel = meshes[node.meshid].name.toLowerCase();
1047 + node.state = 0;
1048 + if (!node.icon) node.icon = 1;
1049 + node.ident = ++nodeShortIdent;
1050 + if (nodes == null) { }
1051 + nodes.push(node);
1052 +
1053 + // Web page update
1054 + //masterUpdate(1 | 2 | 4 | 16);
1055 + updateDevices();
1056 + }
1057 + break;
1058 + }
1059 + case 'nodeconnect': {
1060 + // Indicated a node has changed connectivity state
1061 + var index = -1;
1062 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
1063 + if (index != -1) {
1064 + var node = nodes[index];
1065 +
1066 + // Change the node connection state
1067 + node.conn = message.event.conn;
1068 + node.pwr = message.event.pwr;
1069 + updateDevices();
1070 + //updateMapMarkers();
1071 + //refreshDevice(node._id);
1072 + }
1073 + break;
1074 + }
1075 + case 'login': {
1076 + // Update the last login time
1077 + if (users != null && users['user/' + domain + '/' + message.event.username.toLowerCase()]) { users['user/' + domain + '/' + message.event.username.toLowerCase()].login = message.event.time; }
1078 + break;
1079 + }
1080 + case 'notify': {
1081 + //var n = { text: message.event.value };
1082 + //if (message.event.tag != null) { n.tag = message.event.tag; }
1083 + //addNotification(n);
1084 + break;
1085 + }
1086 + case 'stopped': { // Server is stopping.
1087 + // TODO: Disconnect
1088 + break;
1089 + }
1090 + default:
1091 + //console.log('Unknown message.event.action', message.event.action);
1092 + break;
1093 + }
1094 + break;
1095 + }
1096 + default:
1097 + //console.log('Unknown message.action', message.action);
1098 + break;
1099 + }
1100 + }
1101 +
1102 + //
1103 + // Menu System
1104 + //
1105 +
1106 + function topMenu(select) {
1107 + if ((xxdialogMode != null) && (xxdialogMode != 0) && (xxdialogMode != 999)) return;
1108 + if (select === undefined) {
1109 + var x = (QS('topMenu').display == 'none');
1110 + if (x == true) { if ((xxdialogMode == 0) || (xxdialogMode == null)) { QV('topMenu', true); xxdialogMode = 999; } } else { QV('topMenu', false); xxdialogMode = 0; }
1111 + } else {
1112 + QV('topMenu', false);
1113 + xxdialogMode = 0;
1114 + if ((select == 1) && (xxcurrentView != 3)) { goForward('account'); } // My Account
1115 + if ((select == 2) && (xxcurrentView != 5)) { goForward('files'); } // My Files
1116 + }
1117 + }
1118 +
1119 + var backStack = [];
1120 + function goBack() { if (xxdialogMode) return; if (backStack.length > 0) { backStack.pop(); } goStack(); }
1121 + function goForward(id) { if (xxdialogMode) return; backStack.push(id); goStack(); }
1122 + function goStack() {
1123 + if (backStack.length == 0) { go(2); return; }
1124 + var id = backStack[backStack.length - 1], idtype = id.split('/')[0];
1125 + if (idtype == 'node') { setupDeviceMenu(0); gotoDevice(id); }
1126 + if (idtype == 'mesh') { gotoMesh(id); }
1127 + if (idtype == 'account') { go(3); }
1128 + if (idtype == 'devices') { go(2); }
1129 + if (idtype == 'files') { go(5); }
1130 + }
1131 +
1132 + function updateFooterMenu(options) {
1133 + while (options != null && options.length < 3) { options.push({ n: '' }); }
1134 + var x = '', prev = '';
1135 + if (options != null) { for (var i in options) { x += '<td style="cursor:pointer' + ((prev == '') ? '' : ';border-left:solid 1px white') + '" onclick="' + options[i].f + '">' + options[i].n; prev = options[i].n; } }
1136 + QH('footerMenu', '<tr>' + x);
1137 + }
1138 +
1139 + //
1140 + // MY ACCOUNT
1141 + //
1142 +
1143 + function account_manageAuthApp() {
1144 + if (xxdialogMode || ((features & 4096) == 0)) return;
1145 + if (userinfo.otpsecret == 1) { account_removeOtp(); } else { account_addOtp(); }
1146 + }
1147 +
1148 + function account_addOtp() {
1149 + if (xxdialogMode || (userinfo.otpsecret == 1) || ((features & 4096) == 0)) return;
1150 + setDialogMode(2, "Autenticador de aplicativo", 2, function () { meshserver.send({ action: 'otpauth-setup', secret: Q('d2optsecret').attributes.secret.value, token: Q('d2otpauthinput').value }); }, '<div id=d2optinfo>' + "Carregando..." + '</div>', 'otpauth-request');
1151 + meshserver.send({ action: 'otpauth-request' });
1152 + }
1153 +
1154 + function account_addOtpCheck(e) {
1155 + var tokenIsValid = (Q('d2otpauthinput').value.length == 6);
1156 + QE('idx_dlgOkButton', tokenIsValid);
1157 + if (e && (e.keyCode == 13) && tokenIsValid) { dialogclose(1); }
1158 + }
1159 +
1160 + function account_removeOtp() {
1161 + if (xxdialogMode || (userinfo.otpsecret != 1) || ((features & 4096) == 0)) return;
1162 + setDialogMode(2, "Autenticador de aplicativo", 3, function () { meshserver.send({ action: 'otpauth-clear' }); }, "Confirmar remoção do login do aplicativo autenticador em duas etapas?");
1163 + }
1164 +
1165 + function account_manageOtp(action) {
1166 + if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-manage')) { dialogclose(0); }
1167 + if (xxdialogMode || (userinfo.otpsecret != 1) || ((features & 4096) == 0)) return;
1168 + meshserver.send({ action: 'otpauth-getpasswords', subaction: action });
1169 + }
1170 +
1171 + function account_showVerifyEmail() {
1172 + if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return;
1173 + var x = "Clique em ok para enviar um email de verificação para:" + '<br /><div style=padding:8px><b>' + EscapeHtml(userinfo.email) + '</b></div>' + "Aguarde alguns minutos para receber a verificação.";
1174 + setDialogMode(2, "verificação de e-mail", 3, account_showVerifyEmailEx, x);
1175 + }
1176 +
1177 + function account_showVerifyEmailEx() {
1178 + meshserver.send({ action: 'verifyemail', email: userinfo.email });
1179 + }
1180 +
1181 + function account_showChangeEmail() {
1182 + if (xxdialogMode) return;
1183 + var x = addHtmlValue("Email", '<input id=dp3email style=width:170px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />');
1184 + setDialogMode(2, "Alteração de endereço de email", 3, account_changeEmail, x);
1185 + if (userinfo.email != null) { Q('dp3email').value = userinfo.email; }
1186 + account_validateEmail();
1187 + Q('dp3email').focus();
1188 + }
1189 +
1190 + function account_validateEmail(e, email) {
1191 + QE('idx_dlgOkButton', validateEmail(Q('dp3email').value) && (Q('dp3email').value != userinfo.email));
1192 + if ((e != null) && (e.keyCode == 13)) { dialogclose(1); }
1193 + }
1194 +
1195 + function account_changeEmail() {
1196 + meshserver.send({ action: 'changeemail', email: Q('dp3email').value });
1197 + }
1198 +
1199 + function account_showDeleteAccount() {
1200 + if (xxdialogMode) return;
1201 + var x = '<form method=post><table style=margin-left:10px><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value=' + authCookie + ' /><tr>';
1202 + x += '<td align=right>' + "Senha:" + '</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
1203 + x += '</tr><tr><td align=right>' + "Senha:" + '</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
1204 + x += '</tr></table><div style=padding:10px;margin-bottom:4px>';
1205 + x += '<input id=account_dlgCancelButton type=button value=\"' + "Cancelar" + '\" style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
1206 + x += '<input id=account_dlgOkButton type=submit value=\"' + "Ok" + '\" style="float:right;width:80px" onclick=dialogclose(1)>';
1207 + x += '</div><br /></form>';
1208 + setDialogMode(2, "Deletar Conta", 0, null, x);
1209 + account_validateDeleteAccount();
1210 + Q('apassword1').focus();
1211 + }
1212 +
1213 +
1214 + function account_showChangePassword() {
1215 + if (xxdialogMode) return false;
1216 + var x = '<table style=margin-left:10px>';
1217 + x += '<tr><td align=right>' + nobreak("Senha Antiga:") + '</td><td><input id=apassword0 type=password name=apassword0 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b></b></td></tr>';
1218 + x += '<tr><td align=right>' + nobreak("Nova senha:") + '</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b><span id=dxPassWarn></span></b></td></tr>';
1219 + x += '<tr><td align=right>' + nobreak("Nova senha:") + '</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>';
1220 + if (features & 0x00010000) { x += '<tr><td align=right>' + "Dica de senha" + '</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>'; }
1221 + x += '</table>'
1222 + if (passRequirements) {
1223 + var r = [], rc = 0;
1224 + for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
1225 + if (rc > 0) { x += '<br /><span style=font-size:x-small>' + format("Requisitos: {0}.", r.join(', ')) + '</span>'; }
1226 + }
1227 + x += '<br />';
1228 + setDialogMode(2, "Mudar senha", 3, account_showChangePasswordEx, x);
1229 + Q('apassword0').focus();
1230 + account_validateNewPassword();
1231 + return false;
1232 + }
1233 +
1234 + function account_showChangePasswordEx() {
1235 + if (Q('apassword1').value == Q('apassword2').value) {
1236 + var r = { action: 'changepassword', oldpass: Q('apassword0').value, newpass: Q('apassword1').value };
1237 + if (features & 0x00010000) { r.hint = Q('apasswordhint').value; }
1238 + meshserver.send(r);
1239 + }
1240 + }
1241 +
1242 + function account_createMesh() {
1243 + if (xxdialogMode) return;
1244 +
1245 + // Check if we are disallowed from creating a device group
1246 + if ((userinfo.siteadmin != 0xFFFFFFFF) && ((userinfo.siteadmin & 64) != 0)) { setDialogMode(2, "Novo grupo de dispositivos", 1, null, "Esta conta não tem direitos para criar um novo grupo de dispositivos."); return; }
1247 +
1248 + // Remind the user to verify the email address
1249 + if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para \"Minha conta\" para alterar e verificar um endereço de email."); return; }
1250 +
1251 + // Remind the user to add two factor authentication
1252 + if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para \"Minha conta\" e veja a seção \"Segurança da conta\"."); return; }
1253 +
1254 + // We are allowed, let's prompt to information
1255 + var x = addHtmlValue("Nome", '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />');
1256 + x += addHtmlValue("Tipo", '<div style=width:170px;margin:0;padding:0><select id=dp3meshtype style=width:100% onchange=account_validateMeshCreate() ><option value=2>' + "Grupo de agentes de software" + '</option><option value=1>' + "Intel&reg; Apenas AMT" + '</option></select></div>');
1257 + x += addHtmlValue("Descrição", '<div style=width:170px;margin:0;padding:0><textarea id=dp3meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
1258 + setDialogMode(2, "Criar grupo de dispositivo", 3, account_createMeshEx, x);
1259 + account_validateMeshCreate();
1260 + Q('dp3meshname').focus();
1261 + }
1262 +
1263 + function account_validateMeshCreate() {
1264 + QE('idx_dlgOkButton', Q('dp3meshname').value.length > 0);
1265 + }
1266 +
1267 + function account_createMeshEx(button, tag) {
1268 + meshserver.send({ action: 'createmesh', meshname: Q('dp3meshname').value, meshtype: Q('dp3meshtype').value, desc: Q('dp3meshdesc').value });
1269 + }
1270 +
1271 + function account_validateDeleteAccount() {
1272 + QE('account_dlgOkButton', (Q('apassword1').value.length > 0) && (Q('apassword1').value == Q('apassword2').value));
1273 + }
1274 +
1275 + function account_validateNewPassword() {
1276 + var r = '', ok = (Q('apassword0').value.length > 0) && (Q('apassword1').value.length > 0) && (Q('apassword1').value == Q('apassword2').value) && (Q('apassword0').value != Q('apassword1').value);
1277 + if ((features & 0x00010000) && (Q('apasswordhint').value == Q('apassword1').value)) { ok = false; }
1278 + if (Q('apassword1').value != '') {
1279 + if (passRequirements == null || passRequirements == '') {
1280 + // No password requirements, display password strength
1281 + var passStrength = checkPasswordStrength(Q('apassword1').value);
1282 + if (passStrength >= 80) { r = '<span style=color:green>Strong<span>'; } else if (passStrength >= 60) { r = '<span style=color:blue>&#9679;<span>'; } else { r = '<span style=color:red>&#9679;<span>'; }
1283 + } else {
1284 + // Password requirements provided, use that
1285 + var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
1286 + if (passReq == false) { ok = false; r = '<span style=color:red>' + "Política" + '<span>' }
1287 + }
1288 + }
1289 + QH('dxPassWarn', r);
1290 + //QE('account_dlgOkButton', ok);
1291 + QE('idx_dlgOkButton', ok);
1292 + }
1293 +
1294 + // Return a password strength score
1295 + function checkPasswordStrength(password) {
1296 + 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) }
1297 + if (!password) return 0;
1298 + for (var i = 0; i < password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
1299 + for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
1300 + return parseInt(r + (varCount - 1) * 10);
1301 + }
1302 +
1303 + // Check password requirements
1304 + function checkPasswordRequirements(password, requirements) {
1305 + if ((requirements == null) || (requirements == '') || (typeof requirements != 'object')) return true;
1306 + if (requirements.min) { if (password.length < requirements.min) return false; }
1307 + if (requirements.max) { if (password.length > requirements.max) return false; }
1308 + var num = 0, lower = 0, upper = 0, nonalpha = 0;
1309 + for (var i = 0; i < password.length; i++) {
1310 + if (/\d/.test(password[i])) { num++; }
1311 + if (/[a-z]/.test(password[i])) { lower++; }
1312 + if (/[A-Z]/.test(password[i])) { upper++; }
1313 + if (/\W/.test(password[i])) { nonalpha++; }
1314 + }
1315 + if (requirements.num && (num < requirements.num)) return false;
1316 + if (requirements.lower && (lower < requirements.lower)) return false;
1317 + if (requirements.upper && (upper < requirements.upper)) return false;
1318 + if (requirements.nonalpha && (nonalpha < requirements.nonalpha)) return false;
1319 + return true;
1320 + }
1321 +
1322 + function updateMeshes() {
1323 + var r = '', count = 0;
1324 + for (i in meshes) {
1325 + count++;
1326 +
1327 + // Mesh rights
1328 + var meshrights = meshes[i].links[userinfo._id].rights;
1329 + var rights = "Direitos parciais";
1330 + if (meshrights == 0xFFFFFFFF) rights = "Administrador completo"; else if (meshrights == 0) rights = "Sem direitos";
1331 +
1332 + // Print the mesh information
1333 + r += '<div style=cursor:pointer onclick=goForward(\'' + i + '\')>';
1334 + r += '<div style="float:left;margin-left:4px"><img src="/images/meshicon50.png" width=50 height=50 /></div>';
1335 + r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">';
1336 + r += '<div><div style=padding-left:12px;padding-top:2px><b>' + EscapeHtml(meshes[i].name) + '</b></div><div style=padding-left:12px;padding-top:3px;color:gray>' + rights + '</div></div>';
1337 + r += '</div></div>';
1338 + }
1339 +
1340 + QH('p3meshes', r);
1341 + QV('p3noMeshFound', count == 0);
1342 + }
1343 +
1344 + function gotoMesh(meshid) {
1345 + currentMesh = meshes[meshid];
1346 + if (currentMesh == null) { goBack(); }
1347 + p20updateMesh();
1348 + go(20);
1349 + }
1350 +
1351 + //
1352 + // MY FILES
1353 + //
1354 +
1355 + var filetreelinkpath;
1356 + var filetreelocation = [];
1357 +
1358 + function p5refreshFiles() { meshserver.send({ action: 'files' }); }
1359 +
1360 + function updateFiles() {
1361 + QV('MainMenuMyFiles', ((features & 8) == 0));
1362 + if ((features & 8) != 0) return; // If running on a server without files, exit now.
1363 + var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p5folderup(0)>' + "Raiz" + '</a>', fullPath = 'Root', publicPath, filetreex = filetree, folderdepth = 1;
1364 +
1365 + // Navigate to path location, build the paths at the same time
1366 + var filetreelocation2 = [], oldlinkpath = filetreelinkpath, checkedBoxes = [], checkboxes = document.getElementsByName('fc');
1367 + for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedBoxes.push(checkboxes[i].value) }; } // Save all existing checked boxes
1368 +
1369 + filetreelinkpath = '';
1370 + for (var i in filetreelocation) {
1371 + if ((filetreex.f != null) && (filetreex.f[filetreelocation[i]] != null)) {
1372 + filetreelocation2.push(filetreelocation[i]);
1373 + fullPath += ' / ' + filetreelocation[i];
1374 + if ((folderdepth == 1)) {
1375 + var sp = filetreelocation[i].split('/');
1376 + publicPath = window.location + sp[0] + 'files/' + sp[2];
1377 + //if (filetreelocation[i] === userinfo._id) { filetreelinkpath += 'self'; } else { filetreelinkpath += (sp[0] + '/' + sp[2]); }
1378 + filetreelinkpath += filetreelocation[i];
1379 + } else {
1380 + if (filetreelinkpath != '') { filetreelinkpath += '/' + filetreelocation[i]; if (folderdepth > 2) { publicPath += '/' + filetreelocation[i]; } }
1381 + }
1382 + filetreex = filetreex.f[filetreelocation[i]];
1383 + displayPath += ' / <a style=cursor:pointer onclick=p5folderup(' + folderdepth + ')>' + (filetreex.n != null ? filetreex.n : filetreelocation[i]) + '</a>';
1384 + folderdepth++;
1385 + } else {
1386 + break;
1387 + }
1388 + }
1389 + filetreelocation = filetreelocation2; // In case we could not go down the full path, we set the new path location here.
1390 + var publicfolder = fullPath.toLowerCase().startsWith('root / ' + userinfo._id + ' / public');
1391 +
1392 + // Sort the files
1393 + var filetreexx = p5sort_files(filetreex.f);
1394 +
1395 + // Display all files and folders at this location
1396 + for (var i in filetreexx) {
1397 + // Figure out the name and shortname
1398 + var f = filetreexx[i], name = f.n, shortname;
1399 + shortname = name;
1400 + if (name.length > 40) { shortname = EscapeHtml(name.substring(0, 40)) + "..."; } else { shortname = EscapeHtml(name); }
1401 + name = EscapeHtml(name);
1402 +
1403 + // Figure out the date
1404 + //var fdatestr = '';
1405 + //if (f.d != null) { var fdate = new Date(f.d), fdatestr = (fdate.getMonth() + 1) + '/' + (fdate.getDate()) + '/' + fdate.getFullYear() + ' ' + printTime(fdate) + '&nbsp;'; }
1406 +
1407 + // Figure out the size
1408 + var fsize = '';
1409 + if (f.s != null) { fsize = getFileSizeStr(f.s); }
1410 +
1411 + var h = '';
1412 + if (f.t < 3 || f.t == 4) {
1413 + var right = (f.t == 1 || f.t == 4) ? p5getQuotabar(f) : '';
1414 + h = '<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value=\'' + name + '\'>&nbsp;<span style=float:right;padding-right:4px>' + right + '</span><span><div class=fileIcon' + f.t + '></div><a style=cursor:pointer onclick=p5folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
1415 + } else {
1416 + var link = shortname;
1417 + var publiclink = '';
1418 + if (publicfolder) { publiclink = ' (<a style=cursor:pointer onclick=\'p5showPublicLink(\"' + publicPath + '/' + f.nx + '\")\'>' + "Ligação" + '</a>)'; }
1419 + if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=' + encodeURIComponent(filetreelinkpath + '/' + f.nx) + '\">' + shortname + '</a>' + publiclink; }
1420 + h = '<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value=\'' + f.nx + '\'>&nbsp;<span style=float:right;padding-right:4px>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
1421 + }
1422 +
1423 + if (f.t < 3) { html1 += h; } else { html2 += h; }
1424 + }
1425 +
1426 + //if (f.parent == null) { }
1427 + QH('p5rightOfButtons', p5getQuotabar(filetreex));
1428 +
1429 + QH('p5files', html1 + html2);
1430 + QH('p5currentpath', displayPath);
1431 + QE('p5FolderUp', filetreelocation.length != 0);
1432 + QV('p5PublicShare', publicfolder);
1433 +
1434 + // Re-check all boxes if needed
1435 + if (oldlinkpath == filetreelinkpath) {
1436 + checkboxes = document.getElementsByName('fc');
1437 + for (var i = 0; i < checkboxes.length; i++) {
1438 + checkboxes[i].checked = (checkedBoxes.indexOf(checkboxes[i].value) >= 0);
1439 + }
1440 + }
1441 +
1442 + p5setActions();
1443 + }
1444 +
1445 + function getNiceSize(bytes) {
1446 + if (bytes <= 0) return "Armazenamento excedido";
1447 + if (bytes < 2048) return format("{0}b restante", bytes);
1448 + if (bytes < 2097152) return format("{0}k restante", Math.round(bytes / 1024));
1449 + if (bytes < 2147483648) return format("{0}m restante", Math.round(bytes / 1024 / 1024));
1450 + return format("{0}g restante", Math.round(bytes / 1024 / 1024 / 1024));
1451 + }
1452 +
1453 + function p5getQuotabar(f) {
1454 + while (f.t > 1 && f.t != 4) { f = f.parent; }
1455 + if ((f.t != 1 && f.t != 4) || (f.maxbytes == null)) return '';
1456 + return getNiceSize(f.maxbytes - f.s) + ' <progress style=height:10px;width:100px value=' + f.s + ' max=' + f.maxbytes + ' />';
1457 + }
1458 +
1459 + function p5showPublicLink(u) { setDialogMode(2, "Link Público", 1, null, '<input type=text style=width:100% value="' + u + '" readonly />'); }
1460 +
1461 + var sortorder;
1462 + function p5sort_filename(a, b) { if (a.ln > b.ln) return (1 * sortorder); if (a.ln < b.ln) return (-1 * sortorder); return 0; }
1463 + function p5sort_timestamp(a, b) { if (a.d > b.d) return (1 * sortorder); if (a.d < b.d) return (-1 * sortorder); return 0; }
1464 + function p5sort_bysize(a, b) { if (a.s == b.s) return p5sort_filename(a, b); return (((a.s - b.s)) * sortorder); }
1465 +
1466 + function p5sort_files(files) {
1467 + var r = [], sortselection = Q('p5sortdropdown').value;
1468 + for (var i in files) { files[i].nx = i; if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
1469 + sortorder = 1;
1470 + if (sortselection > 3) { sortorder = -1; sortselection -= 3; }
1471 + if (sortselection == 1) { r.sort(p5sort_filename); }
1472 + else if (sortselection == 2) { r.sort(p5sort_bysize); }
1473 + else if (sortselection == 3) { r.sort(p5sort_timestamp); }
1474 + return r;
1475 + }
1476 +
1477 + function p5setActions() {
1478 + var cc = getFileSelCount(), tc = getFileCount(), sfc = getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
1479 + QE('p5DeleteFileButton', (cc > 0) && (filetreelocation.length > 0));
1480 + QE('p5NewFolderButton', filetreelocation.length > 0);
1481 + QE('p5UploadButton', filetreelocation.length > 0);
1482 + QE('p5RenameFileButton', (cc == 1) && (filetreelocation.length > 0));
1483 + QE('p5SelectAllButton', tc > 0);
1484 + Q('p5SelectAllButton').value = (cc > 0 ? "Nenhum" : "Todos");
1485 + QE('p5CutButton', (sfc > 0) && (cc == sfc));
1486 + QE('p5CopyButton', (sfc > 0) && (cc == sfc));
1487 + QE('p5PasteButton', (p5clipboard != null) && (p5clipboard.length > 0) && (filetreelocation.length > 0));
1488 + }
1489 +
1490 + function getFileSelCount(includeDirs) { var cc = 0, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
1491 + function getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
1492 + function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
1493 + function p5selectallfile() { var nv = (getFileSelCount() == 0), checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p5setActions(); }
1494 + function setupBackPointers(x) { if (x.f != null) { var fs = 0, fc = 0; for (var i in x.f) { setupBackPointers(x.f[i]); x.f[i].parent = x; if (x.f[i].s) { fs += x.f[i].s; } if (x.f[i].c) { fc += x.f[i].c; } if (x.f[i].t == 3) { fc++; } } x.s = fs; x.c = fc; } return x; }
1495 + function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format("{0} bytes", size); }
1496 + function p5folderup(x) { if (x == null) { filetreelocation.pop(); } else { while (filetreelocation.length > x) { filetreelocation.pop(); } } updateFiles(); return false; }
1497 + function p5folderset(x) { filetreelocation.push(decodeURIComponent(x)); updateFiles(); return false; }
1498 + function p5createfolder() { setDialogMode(2, "Nova pasta", 3, p5createfolderEx, '<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% />'); focusTextBox('p5renameinput'); p5fileNameCheck(); }
1499 + function p5createfolderEx() { meshserver.send({ action: 'fileoperation', fileop: 'createfolder', path: filetreelocation, newfolder: Q('p5renameinput').value }); }
1500 + function p5deletefile() { var cc = getFileSelCount(), rec = (getFileSelDirCount() > 0) ? '<br /><br /><label><input type=checkbox id=p5recdeleteinput>' + "Exclusão recursiva" + '</label><br>' : '<input type=checkbox id=p5recdeleteinput style=\'display:none\'>'; setDialogMode(2, "Deletar", 3, p5deletefileEx, (cc > 1) ? (format("Excluir {0} itens selecionados?", cc) + rec) : ("Excluir item selecionado?" + rec)); }
1501 + function p5deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(checkboxes[i].value); } } meshserver.send({ action: 'fileoperation', fileop: 'delete', path: filetreelocation, delfiles: delfiles, rec: Q('p5recdeleteinput').checked }); }
1502 + function p5renamefile() { var renamefile, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = checkboxes[i].value; } } setDialogMode(2, "Renomear", 3, p5renamefileEx, '<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'fileoperation', fileop: 'rename', path: filetreelocation, oldname: renamefile }); focusTextBox('p5renameinput'); p5fileNameCheck(); }
1503 + function p5renamefileEx(b, t) { t.newname = Q('p5renameinput').value; meshserver.send(t); }
1504 + function p5fileNameCheck(e) { var x = isFilenameValid(Q('p5renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e && e.keyCode == 13)) { dialogclose(1); } }
1505 + var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
1506 + function p5uploadFile() { setDialogMode(2, "Subir arquivo", 3, p5uploadFileEx, '<form method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame><input type=text name=link style=display:none id=p5uploadpath value=\"' + encodeURIComponent(filetreelinkpath) + '\" /><input type=file name=files id=p5uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p5uploadinput\')" /><input type=hidden name=authCookie value=' + authCookie + ' /><input type=submit id=p5loginSubmit style=display:none /></form>'); updateUploadDialogOk('p5uploadinput'); }
1507 + function p5uploadFileEx() { Q('p5loginSubmit').click(); }
1508 + function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
1509 +
1510 + var p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0;
1511 + function p5copyFile(cut) { var checkboxes = document.getElementsByName('fc'); p5clipboard = []; p5clipboardCut = cut, p5clipboardFolder = Clone(filetreelocation); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '3')) { p5clipboard.push(checkboxes[i].value); } } p5updateClipview(); }
1512 + function p5pasteFile() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = format("Confirme {0} da {1} entrada {2} para este local?", (p5clipboardCut == 0 ? 'copy' : 'move'), p5clipboard.length, ((p5clipboard.length > 1) ? 's' : '')) } setDialogMode(2, "Colar", 3, p5pasteFileEx, x); }
1513 + function p5pasteFileEx() { meshserver.send({ action: 'fileoperation', fileop: (p5clipboardCut == 0 ? 'copy' : 'move'), scpath: p5clipboardFolder, path: filetreelocation, names: p5clipboard }); p5folderup(999); if (p5clipboardCut == 1) { p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0; p5updateClipview(); } }
1514 + function p5updateClipview() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = format("Mantendo {0} entrada {1} para {2}", p5clipboard.length, ((p5clipboard.length > 1) ? 's' : ''), (p5clipboardCut == 0 ? "Copiar" : "Mover")) + ', <a href=# onclick="return p5clearClip()" style=cursor:pointer>' + "Limpo" + '</a>.' } QH('p5bottomstatus', x); p5setActions(); }
1515 + function p5clearClip() { p5clipboard = null; p5clipboardFolder = null; p5clipboardCut = 0; p5updateClipview(); return false; }
1516 +
1517 + function p5fileDragDrop(e) {
1518 + haltEvent(e);
1519 + QV('bigfail', false);
1520 + QV('bigok', false);
1521 + //QV('p5fileCatchAllInput', false);
1522 + if (e.dataTransfer == null || e.dataTransfer.files.length == 0 || filetreelocation.length == 0) return;
1523 + var names = [], sizes = [], types = [], datas = [], readercount = e.dataTransfer.files.length;
1524 + for (var i = 0; i < e.dataTransfer.files.length; i++) {
1525 + var reader = new FileReader(), file = e.dataTransfer.files[i];
1526 + names.push(file.name);
1527 + sizes.push(file.size);
1528 + types.push(file.type);
1529 + reader.onload = function (event) {
1530 + datas.push(event.target.result);
1531 + if (--readercount == 0) {
1532 + Q('p5fileDragName').value = names.join('*');
1533 + Q('p5fileDragSize').value = sizes.join('*');
1534 + Q('p5fileDragType').value = types.join('*');
1535 + Q('p5fileDragData').value = datas.join('*');
1536 + Q('p5fileDragLink').value = encodeURIComponent(filetreelinkpath);
1537 + Q('p5loginSubmit2').click();
1538 + }
1539 + }
1540 + reader.readAsDataURL(file);
1541 + }
1542 + }
1543 +
1544 + var p5dragtimer = null;
1545 + function p5fileDragOver(e) {
1546 + haltEvent(e);
1547 + if (p5dragtimer != null) { clearTimeout(p5dragtimer); p5dragtimer = null; }
1548 + var ac = true; // TODO: Set to true if we can accept the file
1549 + if (filetreelocation.length == 0) { ac = false; }
1550 + QV('bigok', ac);
1551 + QV('bigfail', !ac);
1552 + //QV('p5fileCatchAllInput', ac);
1553 + }
1554 +
1555 + function p5fileDragLeave(e) {
1556 + haltEvent(e);
1557 + if (e.target.id != 'p5filetable') {
1558 + QV('bigfail', false);
1559 + QV('bigok', false);
1560 + //QV('p5fileCatchAllInput', false);
1561 + } else {
1562 + p5dragtimer = setTimeout('QV(\'bigfail\',false);QV(\'bigok\',false);p5dragtimer=null;', 200);
1563 + }
1564 + }
1565 +
1566 + //
1567 + // MY DEVICES
1568 + //
1569 +
1570 + function ondeskkeypress(e) {
1571 + toggleSoftKeys(0);
1572 + Q('DeskSoftInput').value = '';
1573 + setSessionActivity();
1574 + if (desktop && !xxdialogMode && xxcurrentView == 10) {
1575 + // Check what keys we are allows to send
1576 + if (currentNode != null) {
1577 + var mesh = meshes[currentNode.meshid];
1578 + var meshrights = mesh.links[userinfo._id].rights;
1579 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1580 + if (inputAllowed == false) return false;
1581 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1582 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1583 + }
1584 + return desktop.m.handleKeys(e);
1585 + }
1586 + }
1587 +
1588 + function ondeskkeydown(e) {
1589 + toggleSoftKeys(0);
1590 + Q('DeskSoftInput').value = '';
1591 + setSessionActivity();
1592 + if (desktop && !xxdialogMode && xxcurrentView == 10) {
1593 + // Check what keys we are allows to send
1594 + if (currentNode != null) {
1595 + var mesh = meshes[currentNode.meshid];
1596 + var meshrights = mesh.links[userinfo._id].rights;
1597 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1598 + if (inputAllowed == false) return false;
1599 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1600 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1601 + }
1602 + return desktop.m.handleKeyDown(e);
1603 + }
1604 + }
1605 +
1606 + function ondeskkeyup(e) {
1607 + toggleSoftKeys(0);
1608 + Q('DeskSoftInput').value = '';
1609 + setSessionActivity();
1610 + if (desktop && !xxdialogMode && xxcurrentView == 10) {
1611 + // Check what keys we are allows to send
1612 + if (currentNode != null) {
1613 + var mesh = meshes[currentNode.meshid];
1614 + var meshrights = mesh.links[userinfo._id].rights;
1615 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
1616 + if (inputAllowed == false) return false;
1617 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
1618 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
1619 + }
1620 + return desktop.m.handleKeyUp(e);
1621 + }
1622 + }
1623 +
1624 + // Since the update device call can be quite frequent, we can moderate it and only call it at most 5 times a second.
1625 + var updateDevicesTimer = null;
1626 + function updateDevices() { if (updateDevicesTimer != null) return; updateDevicesTimer = setTimeout(updateDevicesEx, 200); }
1627 +
1628 + var sort = 0;
1629 + var deviceHeaderId = 0;
1630 + var deviceHeaderCount;
1631 + var deviceHeaders = {};
1632 + var showRealNames = false;
1633 + var deviceHeaderTotal = 0;
1634 + var deviceHeaders = {};
1635 + var deviceHeadersTitles = {};
1636 + function updateDevicesEx() {
1637 + if (updateDevicesTimer != null) { clearTimeout(updateDevicesTimer); updateDevicesTimer = null; }
1638 + var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
1639 +
1640 + // 3 wide, list view or desktop view
1641 + deviceHeaderId = 0;
1642 + deviceHeaderCount = {};
1643 + deviceHeaderTotal = 0;
1644 + deviceHeaders = {};
1645 + deviceHeadersTitles = {};
1646 + var current;
1647 +
1648 + // Perform node sort
1649 + if (sort == 0) { nodes.sort(meshSort); }
1650 + else if (sort == 1) { nodes.sort(powerSort); }
1651 + else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
1652 +
1653 + // Go thru the list of nodes and display them
1654 + for (var i in nodes) {
1655 + if (nodes[i].v == false) continue;
1656 + var mesh2 = meshes[nodes[i].meshid], meshlinks = mesh2.links[userinfo._id];
1657 + if (meshlinks == null) continue;
1658 + var meshrights = meshlinks.rights;
1659 +
1660 + if (sort == 0) {
1661 + // Mesh header
1662 + nodes.sort(meshSort);
1663 + if (nodes[i].meshid != current) {
1664 + deviceHeaderSet();
1665 + var extra = '';
1666 + if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span style=color:lightgray>' + "Intelreg; " + '</span>'; }
1667 + if (current != null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1668 + r += '<div class=DevSt style=padding-top:4px><span style=float:right>';
1669 + //r += getMeshActions(mesh2, meshrights);
1670 + r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
1671 + current = nodes[i].meshid;
1672 + displayedMeshes[current] = 1;
1673 + c = 0;
1674 + }
1675 + } else if (sort == 1) {
1676 + // Power header
1677 + if (nodes[i].pwr !== current) {
1678 + deviceHeaderSet();
1679 + if (current !== null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1680 + r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
1681 + current = nodes[i].pwr;
1682 + c = 0;
1683 + }
1684 + } else if (sort == 2) {
1685 + // Device header
1686 + if (current == null) { current = '1'; }
1687 + }
1688 +
1689 + count++;
1690 + var title = EscapeHtml(nodes[i].name);
1691 + if (title.length == 0) { title = '<i>' + "Nenhum" + '</i>'; }
1692 + if ((nodes[i].rname != null) && (nodes[i].rname.length > 0)) { title += " / " + EscapeHtml(nodes[i].rname); }
1693 + var name = EscapeHtml(nodes[i].name);
1694 + if (showRealNames == true && nodes[i].rname != null) name = EscapeHtml(nodes[i].rname);
1695 + if (name.length == 0) { name = '<i>' + "Nenhum" + '</i>'; }
1696 +
1697 + // Node
1698 + var icon = nodes[i].icon, nodestate = NodeStateStr(nodes[i]);
1699 + if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
1700 + r += '<div style=cursor:pointer onclick=goForward(\'' + nodes[i]._id + '\')>';
1701 + r += '<div class="i' + icon + '" style="float:left;margin-left:4px"></div>';
1702 + r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">';
1703 + r += '<div><div style=padding-left:12px;padding-top:2px><b>' + name + '</b></div><div style=padding-left:12px;padding-top:3px;color:gray>' + nodestate + '</div></div>';
1704 + r += '</div></div>';
1705 +
1706 + // If we are displaying devices by group, put the device in the right group.
1707 + /*
1708 + if ((sort == 3) && (r != '')) {
1709 + if (nodes[i].tags) {
1710 + for (var j in nodes[i].tags) {
1711 + var tag = nodes[i].tags[j];
1712 + if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
1713 + if (view == 3) break;
1714 + }
1715 + }
1716 + r = '';
1717 + }
1718 + */
1719 +
1720 + deviceHeaderTotal++;
1721 + if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
1722 + }
1723 +
1724 + // Display all empty meshes, we need to do this because users can add devices to these at any time.
1725 + if (sort == 0) {
1726 + for (var i in meshes) {
1727 + var mesh = meshes[i], meshlink = mesh.links[userinfo._id];
1728 + if (meshlink != null) {
1729 + var meshrights = meshlink.rights;
1730 + if (displayedMeshes[mesh._id] == null) {
1731 + if ((current != '') && (r != '')) { r += '</tr></table>'; }
1732 + r += '<div><div colspan=3 class=DevSt><span style=float:right>';
1733 + //r += getMeshActions(mesh, meshrights);
1734 + r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></div>';
1735 + if (mesh.mtype == 1) { r += '<div style=padding:10px><i>' + "Nenhum Intel&reg; AMT devices in this group"; }
1736 + if (mesh.mtype == 2) { r += '<div style=padding:10px><i>' + "Nenhum dispositivo neste grupo"; }
1737 + r += '.</i></div></div>';
1738 + current = mesh._id;
1739 + count++;
1740 + }
1741 + }
1742 + }
1743 + }
1744 +
1745 + if (count == 0) {
1746 + QH('xdevices', '<div style="margin-top:50px;text-align:center"><span style="font-size:30px">' + "Nenhum dispositivo" + '</span><br /><br />' + "Use a versão desktop deste site para adicionar dispositivos." + '</div>');
1747 + } else {
1748 + QH('xdevices', r);
1749 + }
1750 + deviceHeaderSet();
1751 + for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
1752 + for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
1753 + }
1754 +
1755 + var powerStatetable = ['', "Ligado", "Hibernar", "Hibernar", "Hibernar", "Hibernando", "Desligar", "Presente"];
1756 + var powerStateStrings = ['', "Ligado", "Hibernando", "Hibernando", "Deep Sleep", "Hibernando", "Soft-Off", "Presente"];
1757 + var powerStateStrings2 = ['', "O dispositivo está ligado", "O dispositivo está no estado de suspensão (S1)", "O dispositivo está no estado de suspensão (S2)", "O dispositivo está no estado de sono profundo (S3)", "O dispositivo está hibernando (S4)", "O dispositivo está no estado soft-off (S5)", "O dispositivo está presente, mas o estado de energia não pode ser determinado"];
1758 + var powerColorTable = ['#00000000', 'black', 'blue', 'blue', 'lightblue', 'blueviolet', 'darkgreen', 'lightseagreen', 'lightseagreen'];
1759 + function NodeStateStr(node) {
1760 + var states = [];
1761 + if (node.state > 0 && node.state < powerStatetable.length) state.push(powerStatetable[node.state]);
1762 + if (node.conn) {
1763 + if ((node.conn & 1) != 0) { states.push('<span>' + "Agente" + '</span>'); }
1764 + if ((node.conn & 2) != 0) { states.push('<span>' + "CIRA" + '</span>'); }
1765 + else if ((node.conn & 4) != 0) { states.push('<span>' + "Intel&reg; AMT" + '</span>'); }
1766 + if ((node.conn & 8) != 0) { states.push('<span>' + "Retransmissão" + '</span>'); }
1767 + if ((node.conn & 16) != 0) { states.push('<span>' + "MQTT" + '</span>'); }
1768 + }
1769 + if ((node.pwr != null) && (node.pwr != 0)) { states.push(powerStateStrings[node.pwr]); }
1770 + return states.join(', ');
1771 + }
1772 +
1773 + function PowerStateStr(x) {
1774 + if (x < powerStatetable.length) return powerStatetable[x];
1775 + return '';
1776 + }
1777 +
1778 + function PowerStateStr2(x) {
1779 + if ((x != 0) && (x < powerStatetable.length)) return powerStatetable[x];
1780 + return "Desconhecido";
1781 + }
1782 +
1783 + function onSortSelectChange(skipsave) {
1784 + sort = document.getElementById('sortselect').selectedIndex;
1785 + if (!skipsave) { putstore('sort', sort); }
1786 + updateDevicesEx();
1787 + }
1788 +
1789 + function deviceHeaderSet() {
1790 + if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
1791 + deviceHeaders['DevxHeader' + deviceHeaderId] = ', ' + deviceHeaderTotal + ((deviceHeaderTotal == 1) ? "nó" : "nós");
1792 + var title = '';
1793 + for (var x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
1794 + deviceHeadersTitles['DevxHeader' + deviceHeaderId] = title;
1795 + deviceHeaderId++;
1796 + deviceHeaderCount = {};
1797 + deviceHeaderTotal = 0;
1798 + }
1799 +
1800 + function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
1801 + function powerSort(a, b) { var ap = a.pwr ? a.pwr : 0; var bp = b.pwr ? b.pwr : 0; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } if (ap > bp) return 1; if (ap < bp) return -1; return 0; }
1802 + function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
1803 + function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
1804 +
1805 + //
1806 + // MY DEVICE
1807 + //
1808 +
1809 + function refreshDevice(nodeid) {
1810 + if (!currentNode || currentNode._id != nodeid) return;
1811 + gotoDevice(nodeid, xxcurrentView, true);
1812 + }
1813 +
1814 + function getNodeRights(nodeid) {
1815 + var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
1816 + return mesh.links[userinfo._id].rights;
1817 + }
1818 +
1819 + var currentDevicePanel = 0;
1820 + var currentNode;
1821 + var powerTimelineNode = null;
1822 + var powerTimelineReq = null;
1823 + var powerTimelineUpdate = null;
1824 + var powerTimeline = null;
1825 + function getCurrentNode() { return currentNode; };
1826 + function gotoDevice(nodeid, panel, refresh) {
1827 +
1828 + // Remind the user to verify the email address
1829 + if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para \"Minha conta\" para alterar e verificar um endereço de email."); return; }
1830 +
1831 + // Remind the user to add two factor authentication
1832 + if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para \"Minha conta\" e veja a seção \"Segurança da conta\"."); return; }
1833 +
1834 + var node = getNodeFromId(nodeid);
1835 + if (node == null) { goBack(); return; }
1836 + var mesh = meshes[node.meshid];
1837 + if (mesh == null) { goBack(); return; }
1838 + var meshrights = mesh.links[userinfo._id].rights;
1839 + if (!currentNode || currentNode._id != node._id || refresh == true) {
1840 + currentNode = node;
1841 +
1842 + // Add node name
1843 + var nname = EscapeHtml(node.name);
1844 + if (nname.length == 0) { nname = '<i>' + "Nenhum" + '</i>'; }
1845 + if ((meshrights & 4) != 0) { nname = '<span onclick=showEditNodeValueDialog(0) style=cursor:pointer>' + nname + '</span>'; }
1846 + QH('p10deviceName', nname);
1847 +
1848 + // Node attributes
1849 + var x = '<table style=width:100%>';
1850 +
1851 + // Attribute: Mesh
1852 + x += addDeviceAttribute('<span>' + "Grupo" + '</span>', '<a onclick=goForward("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
1853 +
1854 + // Attribute: Name
1855 + if (node.rname != null) { x += addDeviceAttribute('<span>' + "Nome" + '</span>', '<span>' + EscapeHtml(node.rname) + '</span>'); }
1856 +
1857 + // Attribute: Host
1858 + if ((mesh.mtype == 1) || (node.name != node.host)) {
1859 + if ((meshrights & 4) != 0) {
1860 + if (node.host) {
1861 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
1862 + } else {
1863 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>' + "Nenhum" + '</i></span>');
1864 + }
1865 + } else {
1866 + x += addDeviceAttribute("Hostname", EscapeHtml(node.host));
1867 + }
1868 + }
1869 +
1870 + // Attribute: Description
1871 + var description = node.desc ? EscapeHtml(node.desc) : '<i>' + "Nenhum" + '</i>';
1872 + if ((meshrights & 4) != 0) {
1873 + x += addDeviceAttribute("Descrição", '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + '</span>');
1874 + } else {
1875 + x += addDeviceAttribute("Descrição", description);
1876 + }
1877 +
1878 + // Attribute: Mesh Agent
1879 + var agentsStr = ["Desconhecido", "Windows 32 Bits console", "Windows 64 Bits console", "Serviço Windows 32 Bits", "Serviço Windows 64 Bits", "Linux 32 bits", "Linux 64 bits", "MIPS", "XENx86", "Android ARM", "Linux ARM", "MacOS 32 bits", "Android x86", "PogoPlug ARM", "Android APK", "Linux Poky x86-32 bits", "MacOS 64 bits", "ChromeOS", "Linux Poky x86-64 bits", "Linux NoKVM x86-32 bits", "Linux NoKVM x86-64 bits", "Windows MinCore console", "Windows MinCore service", "NodeJS", "ARM-Linaro", "ARMv6l / ARMv7l", "ARMv8 64bit", "ARMv6l / ARMv7l / NoKVM", "Desconhecido", "Desconhecido", "FreeBSD x86-64"];
1880 + if ((node.agent != null) && (node.agent.id != null) && (node.agent.ver != null)) {
1881 + var str = '';
1882 + if (node.agent.id <= agentsStr.length) { str = agentsStr[node.agent.id]; } else { str = agentsStr[0]; }
1883 + if (node.agent.ver != 0) { str += ' v' + node.agent.ver; }
1884 + x += addDeviceAttribute("Agente", str);
1885 + }
1886 +
1887 + // Attribute: Intel AMT
1888 + if (node.intelamt != null) {
1889 + var str = '';
1890 + var provisioningStates = { 0: nobreak("Não ativado (pré)"), 1: nobreak("Não ativado (entrada)"), 2: nobreak("ativado") };
1891 + if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + nobreak("Estado desconhecido") + '</i>, v' + node.intelamt.ver; } else
1892 +
1893 + if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "ativado" + '</i>'; }
1894 + else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Estado da versão desconhecida" + '</i>'; }
1895 + else {
1896 + str += provisioningStates[node.intelamt.state];
1897 + if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str = ' <span>' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str = ' <span>' + "ACM" + '</span>'; } }
1898 + str += (', v' + node.intelamt.ver);
1899 + }
1900 +
1901 + if (node.intelamt.tls == 1) { str += ', <span>' + "TLS" + '</span>'; }
1902 + if (node.intelamt.state == 2) {
1903 + if (node.intelamt.user == null || node.intelamt.user == '') {
1904 + if ((meshrights & 4) != 0) {
1905 + str += ', <i style=color:#FF0000;cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>' + nobreak("Sem credenciais") + '</i>';
1906 + } else {
1907 + str += ', <i style=color:#FF0000>' + "Sem credenciais" + '</i>';
1908 + }
1909 + }
1910 + str += ' ';
1911 + if ((meshrights & 4) != 0) {
1912 + str += '<img src=images/link4.png height=10 width=10 style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
1913 + }
1914 + }
1915 +
1916 + var meName = "Intel&reg; ME";
1917 + if (typeof node.intelamt.sku == 'number') {
1918 + if ((node.intelamt.sku & 8) != 0) { meName = "Intel&reg; AMT"; }
1919 + else if ((node.intelamt.sku & 16) != 0) { meName = "Intel&reg; SM"; }
1920 + }
1921 + x += addDeviceAttribute(meName, str);
1922 + }
1923 +
1924 + // Attribute: Mesh Agent Tag
1925 + if ((node.agent != null) && (node.agent.tag != null) && (node.agent.tag != 'mailto:')) {
1926 + var tag = EscapeHtml(node.agent.tag);
1927 + if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
1928 + x += addDeviceAttribute("Etiqueta do agente", tag);
1929 + }
1930 +
1931 + // Attribute: Intel AMT
1932 + //if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel&reg; AMT', node.intelamt.user); }
1933 +
1934 + // Attribute: Connectivity (Only show this if more than just the agent is connected).
1935 + var connectivity = node.conn;
1936 + if (connectivity && connectivity > 1) {
1937 + var cstate = [];
1938 + if ((node.conn & 1) != 0) cstate.push('<span>' + "Agente" + '</span>');
1939 + if ((node.conn & 2) != 0) cstate.push('<span>' + "Intel&reg; AMT CIRA" + '</span>');
1940 + else if ((node.conn & 4) != 0) cstate.push('<span>' + "Intel&reg; AMT" + '</span>');
1941 + if ((node.conn & 8) != 0) cstate.push('<span>' + "Retransmissão do agente" + '</span>');
1942 + if ((node.conn & 16) != 0) cstate.push('<span>' + "MQTT" + '</span>');
1943 + x += addDeviceAttribute("Conectividade", cstate.join(', '));
1944 + }
1945 +
1946 + // Node tags
1947 + var groupingTags = '<i>' + "Nenhum" + '</i>';
1948 + if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">' + node.tags[i] + '</span>'; } }
1949 + if ((meshrights & 4) != 0) {
1950 + x += addDeviceAttribute("Tags", '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + '</span>');
1951 + } else {
1952 + x += addDeviceAttribute("Tags", groupingTags);
1953 + }
1954 +
1955 + x += '</table><br />';
1956 + // Show action button, only show if we have permissions 4, 8, 64
1957 + if ((meshrights & 76) != 0) { x += '<input type=button value=Actions onclick=deviceActionFunction() />'; }
1958 + //x += '<input type=button value=Notes onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
1959 + //if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast onclick=deviceToastFunction() />'; }
1960 + QH('p10html', x);
1961 +
1962 + // Show node last 7 days timeline
1963 + //drawDeviceTimeline();
1964 + setupFiles();
1965 +
1966 + // Show bottom buttons
1967 + x = '<div style=float:right;font-size:x-small;margin-right:10px>';
1968 + if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '")>' + "Excluir dispositivo" + '</a>';
1969 + x += '</div><div style=font-size:x-small>';
1970 + //if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '")>Interfaces</a>&nbsp;';
1971 + //if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '")>Location</a>&nbsp;';
1972 + x += '</div><br>'
1973 +
1974 + QH('p10html3', x);
1975 +
1976 + // Set the node power state
1977 + var powerstate = PowerStateStr(node.state);
1978 + //if (node.state == 0) { powerstate = 'Unknown State'; }
1979 + if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Mesh Agent" + '</span>'; }
1980 + if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Intel&reg; AMT conectado" + '</span>'; }
1981 + else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Intel&reg; AMT detectado" + '</span>'; }
1982 + if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px>' + "Canal MQTT conectado" + '</span>'; }
1983 + QH('MainComputerState', powerstate);
1984 +
1985 + // Set the node icon
1986 + QH('MainComputerImage', '<div class="i' + node.icon + '"></div>');
1987 +
1988 + // Request the power timeline
1989 + if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { QH('p10html2', ''); powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
1990 + }
1991 + setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
1992 + if (!panel) panel = 10;
1993 + go(panel);
1994 +
1995 + // Update the footer menu
1996 + setupDeviceMenu();
1997 + }
1998 +
1999 + function deviceToastFunction() {
2000 + if (xxdialogMode) return;
2001 + setDialogMode(2, "Brinde do dispositivo", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
2002 + }
2003 +
2004 + function deviceToastFunctionEx() {
2005 + meshserver.send({ action: 'toast', nodeids: [currentNode._id], title: 'MeshCentral', msg: Q('d2devToast').value });
2006 + }
2007 +
2008 + function setupDeviceMenu(op, obj) {
2009 + var meshrights = 0;
2010 + if (currentNode) { meshrights = meshes[currentNode.meshid].links[userinfo._id].rights; }
2011 + if (op != null) { currentDevicePanel = op; }
2012 + QV('p10general', currentDevicePanel == 0);
2013 + QV('p10desktop', currentDevicePanel == 1); // Show if we have remote control rights or desktop view only rights
2014 + QV('p10files', currentDevicePanel == 2);
2015 + var menus = [];
2016 + if (currentDevicePanel != 0) { menus.push({ n: 'General', f: 'setupDeviceMenu(0)' }); }
2017 + if ((currentDevicePanel != 1) &&
2018 + (currentNode != null) &&
2019 + ((meshrights & 8) || (meshrights & 256)) &&
2020 + (((meshes[currentNode.meshid].mtype == 1) && ((typeof currentNode.intelamt.sku !== 'number') || ((currentNode.intelamt.sku & 8) != 0))) || (currentNode.agent && (currentNode.agent.caps & 1)))
2021 + ) { menus.push({ n: 'Desktop', f: 'setupDeviceMenu(1)' }); }
2022 + if ((currentDevicePanel != 2) && (currentNode != null) && (meshrights & 8) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0)) && ((currentNode.mtype == 2) && (currentNode.agent.caps & 4))) { menus.push({ n: 'Files', f: 'setupDeviceMenu(2)' }); }
2023 + updateFooterMenu(menus);
2024 + }
2025 +
2026 + function deviceActionFunction() {
2027 + if (xxdialogMode) return;
2028 + var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
2029 + var x = "Selecione uma operação para executar neste dispositivo." + '<br /><br />';
2030 + var y = '<select id=d2deviceop style=float:right;width:170px>';
2031 + if ((meshrights & 64) != 0) { y += '<option value=100>' + "Ligar" + '</option>'; } // Wake-up permission
2032 + if ((meshrights & 8) != 0) { y += '<option value=4>' + "Hibernar" + '</option><option value=3>' + "Redefinir" + '</option><option value=2>' + "Desligar" + '</option>'; } // Remote control permission
2033 + y += '</select>';
2034 + x += addHtmlValue("Operação", y);
2035 + setDialogMode(2, "Ação do dispositivo", 3, deviceActionFunctionEx, x);
2036 + }
2037 +
2038 + function deviceActionFunctionEx() {
2039 + var op = Q('d2deviceop').value;
2040 + if (op == 100) {
2041 + // Device wake
2042 + meshserver.send({ action: 'wakedevices', nodeids: [currentNode._id] });
2043 + } else {
2044 + // Power operation
2045 + meshserver.send({ action: 'poweraction', nodeids: [currentNode._id], actiontype: op });
2046 + }
2047 + }
2048 +
2049 + // Look to see if we need to update the device timeline
2050 + function updateDeviceTimeline() {
2051 + if ((meshserver.State != 2) || (powerTimelineNode == null) || (powerTimelineUpdate == null) || (currentNode == null)) return;
2052 + if ((powerTimelineNode == powerTimelineReq) && (currentNode._id == powerTimelineNode) && (powerTimelineUpdate < Date.now())) { powerTimelineUpdate = null; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
2053 + }
2054 +
2055 + // Draw device power bars. The bars are 766px wide.
2056 + function drawDeviceTimeline() {
2057 + var timeline = null, now = Date.now();
2058 + if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
2059 +
2060 + // Calculate when the timeline starts
2061 + var d = new Date();
2062 + d.setHours(0, 0, 0, 0);
2063 + d = new Date(d.getTime() - (1000 * 60 * 60 * 24 * 6));
2064 + var timelineStart = d.getTime();
2065 +
2066 + // De-compact the timeline
2067 + var timeline2 = [];
2068 + if (timeline != null && timeline.length > 1) {
2069 + timeline2.push([0, timeline[1], timeline[0]]); // Start, End, Power
2070 + var ct = timeline[1];
2071 + for (var i = 2; i < timeline.length; i += 2) {
2072 + var power = timeline[i], dt = now;
2073 + if (timeline.length > (i + 1)) { dt = timeline[i + 1]; }
2074 + timeline2.push([ct, ct + dt, power]); // Start, End, Power
2075 + ct = ct + dt;
2076 + }
2077 + }
2078 +
2079 + // Draw the timeline
2080 + var x = '', count = 1, date = new Date();
2081 + var totalWidth = Q('masthead').offsetWidth - (90 + 9 + 9 + 14); // Compute the total width of the power bar
2082 + date.setHours(0, 0, 0, 0);
2083 + for (var i = 0; i < 7; i++) {
2084 + var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
2085 + for (var j in timeline2) {
2086 + var block = timeline2[j];
2087 + if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
2088 + var ts = Math.max(start, block[0]);
2089 + var te = Math.min(Math.min(end, block[1]), now);
2090 + var width = Math.round(((te - ts) * totalWidth) / 86400000);
2091 + if (width > 0) { datavalue += '<div style=display:table-cell;width:' + width + 'px;background-color:' + powerColor(block[2]) + ';height:16px></div>'; }
2092 + }
2093 + }
2094 + x += '<tr style=' + (((count % 2) == 0) ? 'background-color:#DDD' : '') + '><td><div>&nbsp;' + printDate(date) + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
2095 + ++count;
2096 + date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
2097 + }
2098 + QH('p10html2', '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse;width:calc(100% - 18px);margin:9px" border=0 cellpadding=2 cellspacing=0><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:center;width:90px>Day</th><th scope=col style=text-align:center>Power State</th></tr>' + x + '</tbody></table>');
2099 + }
2100 +
2101 + // Return a color for the given power state
2102 + function powerColor(x) { if (x < powerColorTable.length) { return powerColorTable[x]; } return 'yellow'; }
2103 +
2104 + // Return true if the time block is visible within the start/end period
2105 + function isTimeBlockInside(start, end, blockStart, blockEnd) {
2106 + if ((blockStart < start) && (blockEnd > end)) return true; // Block is wider than timespan
2107 + if ((blockStart > start) && (blockStart < end)) return true;
2108 + if ((blockEnd > start) && (blockEnd < end)) return true;
2109 + return false;
2110 + }
2111 +
2112 + function addDeviceAttribute(name, value) {
2113 + return '<tr><td style=width:100px;color:gray>' + name + '</td><td style=overflow:hidden>' + value + '</td></tr>';
2114 + }
2115 +
2116 + function editDeviceAmtSettings(nodeid, func) {
2117 + if (xxdialogMode) return;
2118 + var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
2119 + if ((meshrights & 4) == 0) return;
2120 + x += addHtmlValue("Nome de usuário", '<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
2121 + x += addHtmlValue("Senha", '<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
2122 + x += addHtmlValue("Segurança", '<select id=dp10tls style=width:176px><option value=0>' + "Sem segurança TLS" + '</option><option value=1>' + "Segurança TLS necessária" + '</option></select>');
2123 + if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
2124 + setDialogMode(2, "Editar Intel & reg; Credenciais AMT", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func });
2125 + if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
2126 + Q('dp10tls').value = node.intelamt.tls;
2127 + validateDeviceAmtSettings();
2128 + }
2129 +
2130 + function validateDeviceAmtSettings() {
2131 + QE('idx_dlgOkButton', passwordcheck(Q('dp10password').value));
2132 + }
2133 +
2134 + function editDeviceAmtSettingsEx(button, tag) {
2135 + if (button == 2) {
2136 + // Delete button pressed, remove credentials
2137 + meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: '', pass: '' } });
2138 + } else {
2139 + // Change Intel AMT credentials
2140 + var amtuser = Q('dp10username').value;
2141 + if (amtuser == '') amtuser = 'admin';
2142 + var amtpass = Q('dp10password').value;
2143 + if (amtpass == '') amtuser = '';
2144 + meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
2145 + tag.node.intelamt.user = amtuser;
2146 + tag.node.intelamt.tls = Q('dp10tls').value;
2147 + if (tag.func) { setTimeout(tag.func, 300); }
2148 + }
2149 + }
2150 +
2151 + function p10showDeleteNodeDialog(nodeid) {
2152 + if (xxdialogMode) return;
2153 + setDialogMode(2, "Excluir nó", 3, p10showDeleteNodeDialogEx, format("Excluir {0}?", EscapeHtml(currentNode.name)) + '<br /><br /><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirme", nodeid);
2154 + p10validateDeleteNodeDialog();
2155 + }
2156 +
2157 + function p10validateDeleteNodeDialog() {
2158 + QE('idx_dlgOkButton', Q('p10check').checked);
2159 + }
2160 +
2161 + function p10showDeleteNodeDialogEx(buttons, nodeid) {
2162 + meshserver.send({ action: 'removedevices', nodeids: [nodeid] });
2163 + }
2164 +
2165 + function p10showiconselector() {
2166 + if (xxdialogMode) return;
2167 + var mesh = meshes[currentNode.meshid];
2168 + var meshrights = mesh.links[userinfo._id].rights;
2169 + if ((meshrights & 4) == 0) return;
2170 +
2171 + var x = '<table align=center><td>';
2172 + x += '<div style=display:inline-block class=i1 onclick=p10setIcon(1)></div>';
2173 + x += '<div style=display:inline-block class=i2 onclick=p10setIcon(2)></div>';
2174 + x += '<div style=display:inline-block class=i3 onclick=p10setIcon(3)></div><br>';
2175 + x += '<div style=display:inline-block class=i4 onclick=p10setIcon(4)></div>';
2176 + x += '<div style=display:inline-block class=i5 onclick=p10setIcon(5)></div>';
2177 + x += '<div style=display:inline-block class=i6 onclick=p10setIcon(6)></div></table>';
2178 + setDialogMode(2, "Seleção de ícone", 0, null, x);
2179 + QV('id_dialogclose', true);
2180 + }
2181 +
2182 + function p10setIcon(icon) {
2183 + setDialogMode(0);
2184 + meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
2185 + }
2186 +
2187 + var showEditNodeValueDialog_modes = ["Nome do Dispositivo", "Hostname", "Descrição", "Tags"];
2188 + var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
2189 + var showEditNodeValueDialog_modes3 = ['', '', '', "Grupo1, Grupo2, Grupo3"];
2190 + function showEditNodeValueDialog(mode) {
2191 + if (xxdialogMode) return;
2192 + var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue style=width:170px maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
2193 + setDialogMode(2, "Editar dispositivo", 3, showEditNodeValueDialogEx, x, mode);
2194 + var v = currentNode[showEditNodeValueDialog_modes2[mode]];
2195 + if (v == null) v = '';
2196 + if (Array.isArray(v)) { v = v.join(', '); }
2197 + Q('dp10devicevalue').value = v;
2198 + p10editdevicevalueValidate();
2199 + Q('dp10devicevalue').focus();
2200 + }
2201 +
2202 + function showEditNodeValueDialogEx(button, mode) {
2203 + var x = { action: 'changedevice', nodeid: currentNode._id };
2204 + x[showEditNodeValueDialog_modes2[mode]] = Q('dp10devicevalue').value;
2205 + meshserver.send(x);
2206 + }
2207 +
2208 + function p10editdevicevalueValidate(mode, e) {
2209 + var x = ((mode > 1) || (Q('dp10devicevalue').value.length > 0));
2210 + QE('idx_dlgOkButton', x);
2211 + if ((e != null) && (x == true) && (e.keyCode == 13)) { dialogclose(1); }
2212 + }
2213 +
2214 + //
2215 + // DESKTOP
2216 + //
2217 +
2218 + var desktop;
2219 + var desktopNode;
2220 + var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50 };
2221 + function setupDesktop() {
2222 + // Setup the remote desktop
2223 + if ((desktopNode != currentNode) && (desktop != null)) { desktop.Stop(); desktopNode = null; desktop = null; }
2224 +
2225 + // If the device desktop is already connected in multi-desktop, use that.
2226 + if ((desktopNode != currentNode) || (desktop == null)) {
2227 + // Device is not already connected, just setup a blank canvas
2228 + QH('DeskParent', '<canvas id=Desk width=640 height=200 style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
2229 + desktopNode = currentNode;
2230 + // Setup the mouse wheel
2231 + Q('Desk').addEventListener('DOMMouseScroll', function (e) { return dmousewheel(e); });
2232 + Q('Desk').addEventListener('mousewheel', function (e) { return dmousewheel(e); });
2233 + }
2234 + desktopNode = currentNode;
2235 + updateDesktopButtons();
2236 +
2237 + // On some browsers like IE, we can't save screen shots. Hide the scheenshot/capture buttons.
2238 + if (!Q('Desk')['toBlob']) { QV('deskSaveBtn', false); }
2239 + }
2240 +
2241 + // Show and enable the right buttons
2242 + function updateDesktopButtons() {
2243 + var mesh = meshes[currentNode.meshid];
2244 + var deskState = 0;
2245 + if (desktop != null) { deskState = desktop.State; }
2246 + var meshrights = mesh.links[userinfo._id].rights;
2247 +
2248 + // Show the right buttons
2249 + QV('disconnectbutton1', (deskState != 0));
2250 + QV('connectbutton1', (deskState == 0) && (mesh.mtype == 2) && ((meshrights & 8) || (meshrights & 256)));
2251 + QV('connectbutton1h',
2252 + (deskState == 0) &&
2253 + (meshrights & 8) &&
2254 + ((mesh.mtype == 1) ||
2255 + (currentNode.intelamt != null) &&
2256 + ((currentNode.intelamt.state == 2) &&
2257 + (currentNode.intelamt.ver != null) &&
2258 + (typeof currentNode.intelamt.sku == 'number') &&
2259 + ((currentNode.intelamt.sku & 8) != 0))
2260 + )
2261 + );
2262 +
2263 + // Show the right settings
2264 + QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == 0) || (desktop.contype == 2)));
2265 + QV('d7meshkvm', (mesh.mtype == 2) && ((deskState == false) || (desktop.contype == 1)));
2266 +
2267 + // Enable buttons
2268 + var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
2269 + QE('connectbutton1', online);
2270 + var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
2271 + QE('connectbutton1h', hwonline);
2272 + //QE('deskSaveBtn', deskState == 3);
2273 + //QV('DeskCAD', meshrights & 8);
2274 + //QE('DeskCAD', deskState == 3);
2275 + //QV('DeskWD', (currentNode.agent) && (currentNode.agent.id < 5));
2276 + //QE('DeskWD', deskState == 3);
2277 + //QV('deskkeys', (currentNode.agent) && (currentNode.agent.id < 5));
2278 + //QE('deskkeys', deskState == 3);
2279 + //QE('DeskToolsButton', online);
2280 + QV('DeskToastButton', ((meshrights & 16384) != 0) && (currentNode.agent) && (currentNode.agent.id < 5) && (meshrights & 8));
2281 + //QE('DeskToastButton', online);
2282 + QV('deskActionsBtn', meshrights & 8);
2283 + Q('DeskControl').checked = ((meshrights & 8) != 0);
2284 + if (online == false) QV('DeskTools', false);
2285 + }
2286 +
2287 + function connectDesktop(e, contype) {
2288 + setSessionActivity();
2289 + if (desktop == null) {
2290 + desktopNode = currentNode;
2291 + if (contype == 2) {
2292 + // Setup the Intel AMT remote desktop
2293 + if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop); return; }
2294 + desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
2295 + desktop.debugmode = debugmode;
2296 + desktop.onStateChanged = onDesktopStateChange;
2297 + desktop.m.bpp = (desktopsettings.encoding == 1 || desktopsettings.encoding == 3) ? 1 : 2;
2298 + desktop.m.useZRLE = (desktopsettings.encoding < 3);
2299 + desktop.m.showmouse = desktopsettings.showmouse;
2300 + desktop.m.onScreenSizeChange = deskAdjust;
2301 + desktop.Start(desktopNode._id, 16994, '*', '*', 0);
2302 + desktop.contype = 2;
2303 + } else {
2304 + // Setup the Mesh Agent remote desktop
2305 + desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
2306 + desktop.debugmode = debugmode;
2307 + desktop.m.debugmode = debugmode;
2308 + desktop.attemptWebRTC = attemptWebRTC;
2309 + desktop.onStateChanged = onDesktopStateChange;
2310 + desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
2311 + desktop.m.ScalingLevel = desktopsettings.scaling;
2312 + desktop.m.FrameRateTimer = desktopsettings.framerate;
2313 + desktop.m.onDisplayinfo = deskDisplayInfo;
2314 + desktop.m.onScreenSizeChange = deskAdjust;
2315 + desktop.Start(desktopNode._id);
2316 + desktop.contype = 1;
2317 + }
2318 + } else {
2319 + // Disconnect and clean up the remote desktop
2320 + desktop.Stop();
2321 + desktopNode = desktop = null;
2322 + }
2323 + }
2324 +
2325 + function onDesktopStateChange(xdesktop, state) {
2326 + var xstate = state;
2327 + if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
2328 + var str = StatusStrs[xstate];
2329 + if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
2330 + //if (desktop.m.stopInput == true) { str += ', Loopback'; }
2331 + QH('deskstatus', str);
2332 + switch (state) {
2333 + case 0:
2334 + // Disconnect and clean up the remote desktop
2335 + desktop.Stop();
2336 + desktopNode = desktop = null;
2337 + QV('termdisplays', false);
2338 + if (fullscreen == true) { deskToggleFull(); }
2339 + break;
2340 + case 2:
2341 + break;
2342 + default:
2343 + //console.log('Unknown onDesktopStateChange state', state);
2344 + break;
2345 + }
2346 + updateDesktopButtons();
2347 + deskAdjust();
2348 + setTimeout(deskAdjust, 50);
2349 + }
2350 +
2351 + function showDesktopSettings() {
2352 + if (xxdialogMode) return;
2353 + applyDesktopSettings();
2354 + updateDesktopButtons();
2355 + setDialogMode(7, "Configurações da área de trabalho remota", 3, showDesktopSettingsChanged);
2356 + }
2357 +
2358 + function showDesktopSettingsChanged() {
2359 + desktopsettings.encoding = d7desktopmode.value;
2360 + desktopsettings.showfocus = d7showfocus.checked;
2361 + desktopsettings.showmouse = d7showcursor.checked;
2362 + desktopsettings.quality = d7bitmapquality.value;
2363 + desktopsettings.scaling = d7bitmapscaling.value;
2364 + desktopsettings.framerate = d7framelimiter.value;
2365 + localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
2366 + applyDesktopSettings();
2367 + if (desktop) {
2368 + if (desktop.contype == 1) {
2369 + if (desktop.State != 0) { desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate); }
2370 + }
2371 + if (desktop.contype == 2) {
2372 + if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
2373 + }
2374 + }
2375 + }
2376 +
2377 + function applyDesktopSettings() {
2378 + var r = '', ops = (features & 512) ? [90, 70, 50, 40, 30, 20, 10, 5, 1] : [50, 40, 30, 20, 10, 5, 1];
2379 + for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
2380 + QH('d7bitmapquality', r);
2381 + d7desktopmode.value = desktopsettings.encoding;
2382 + d7showfocus.checked = desktopsettings.showfocus;
2383 + d7showcursor.checked = desktopsettings.showmouse;
2384 + d7bitmapquality.value = 40; // Default value
2385 + if (ops.indexOf(parseInt(desktopsettings.quality)) >= 0) { d7bitmapquality.value = desktopsettings.quality; }
2386 + d7bitmapscaling.value = desktopsettings.scaling;
2387 + if (desktopsettings.framerate) { d7framelimiter.value = desktopsettings.framerate; }
2388 + }
2389 +
2390 + var fullscreen = false;
2391 + /*
2392 + function deskToggleFull() {
2393 + fullscreen = !fullscreen;
2394 + QV('mastheadx', !fullscreen);
2395 + QV('masthead', !fullscreen);
2396 + QV('topbar', !fullscreen);
2397 + QV('p11deviceNameHeader', !fullscreen);
2398 + QV('footer', !fullscreen);
2399 + QV('column_l_bottomgap', !fullscreen);
2400 + QV('idx_deskFullBtn2', fullscreen);
2401 + QV('deskFullBtn', !fullscreen);
2402 + if (fullscreen) {
2403 + QS('container').width = '100%';
2404 + QS('container')['border-right'] = '0';
2405 + QS('container')['border-left'] = '0';
2406 + QS('column_l').padding = '0';
2407 + QS('column_l').width = '100%';
2408 + } else {
2409 + QS('container').width = '960px';
2410 + QS('container')['border-right'] = '1px solid #b7b7b7';
2411 + QS('container')['border-left'] = '1px solid #b7b7b7';
2412 + QS('column_l').padding = '0 15px';
2413 + QS('column_l').width = '930px';
2414 + toggleFullScreen();
2415 + }
2416 + deskAdjust();
2417 + }
2418 + */
2419 +
2420 + function deskAdjust() {
2421 + var x = (Q('DeskParent').clientHeight - Q('Desk').clientHeight) / 2;
2422 + if (x < 0) {
2423 + var mh = Q('DeskParent').clientHeight, mw = 9999;
2424 + if (desktop) { mw = (desktop.m.width / desktop.m.height) * mh; }
2425 + QS('Desk')['max-height'] = mh + 'px';
2426 + QS('Desk')['max-width'] = mw + 'px';
2427 + x = 0;
2428 + } else {
2429 + QS('Desk')['max-height'] = null;
2430 + QS('Desk')['max-width'] = null;
2431 + }
2432 + QS('Desk')['margin-top'] = x + 'px';
2433 + QS('Desk')['margin-bottom'] = x + 'px';
2434 + }
2435 +
2436 + // Remote desktop special key combos for Windows
2437 + function deskSendKeys() {
2438 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
2439 + var ks = Q('deskkeys').value;
2440 + if (ks == 0) { // WIN+Down arrow
2441 + if (desktop.contype == 2) {
2442 + desktop.m.sendkey([[0xffe7, 1], [0xff54, 1], [0xff54, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Down arrow press, Down arrow release, Meta-left release
2443 + } else {
2444 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 40], [desktop.m.KeyAction.UP, 40], [desktop.m.KeyAction.EXUP, 0x5B]]); // Agent: L-Winkey press, Down arrow press, Down arrow release, L-Winkey release
2445 + }
2446 + } else if (ks == 1) { // WIN+Up arrow
2447 + if (desktop.contype == 2) {
2448 + desktop.m.sendkey([[0xffe7, 1], [0xff52, 1], [0xff52, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Up arrow press, Up arrow release, Meta-left release
2449 + } else {
2450 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 38], [desktop.m.KeyAction.UP, 38], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, Up arrow press, Up arrow release, L-Winkey release
2451 + }
2452 + } else if (ks == 2) { // WIN+L arrow
2453 + if (desktop.contype == 2) {
2454 + desktop.m.sendkey([[0xffe7, 1], [0x6c, 1], [0x6c, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
2455 + } else {
2456 + desktop.sendCtrlMsg('{"action":"lock"}');
2457 + //desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,76],[desktop.m.KeyAction.UP,76],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'L' press, 'L' release, L-Winkey release
2458 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXDOWN, 0x5B);
2459 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.DOWN, 76);
2460 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.UP, 76);
2461 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXUP, 0x5B);
2462 + }
2463 + } else if (ks == 3) { // WIN+M arrow
2464 + if (desktop.contype == 2) {
2465 + desktop.m.sendkey([[0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
2466 + } else {
2467 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 77], [desktop.m.KeyAction.UP, 77], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'M' press, 'M' release, L-Winkey release
2468 + }
2469 + } else if (ks == 4) { // Shift+WIN+M arrow
2470 + if (desktop.contype == 2) {
2471 + desktop.m.sendkey([[0xffe1, 1], [0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0], [0xffe1, 0]]); // Intel AMT: Shift-left down, Meta-left down, 'm' press, 'm' release, Meta-left release, Shift-left release
2472 + } else {
2473 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN, 16], [desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 77], [desktop.m.KeyAction.UP, 77], [desktop.m.KeyAction.EXUP, 0x5B], [desktop.m.KeyAction.UP, 16]]); // MeshAgent: L-shift press, L-Winkey press, 'M' press, 'M' release, L-Winkey release, L-shift release
2474 + }
2475 + } else if (ks == 5) { // WIN
2476 + if (desktop.contype == 2) {
2477 + desktop.m.sendkey([[0xffe7, 1], [0xffe7, 0]]); // Intel AMT: Meta-left down, Meta-left release
2478 + } else {
2479 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, L-Winkey release
2480 + }
2481 + } else if (ks == 6) { // WIN+R
2482 + if (desktop.contype == 2) {
2483 + desktop.m.sendkey([[0xffe7, 1], [0x72, 1], [0x72, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'r' press, 'r' release, Meta-left release
2484 + } else {
2485 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 82], [desktop.m.KeyAction.UP, 82], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'R' press, 'R' release, L-Winkey release
2486 + }
2487 + } else if (ks == 7) { // ALT-F4
2488 + if (desktop.contype == 2) {
2489 + desktop.m.sendkey([[0xffe9, 1], [0xffc1, 1], [0xffc1, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'F4' press, 'F4' release, Alt release
2490 + } else {
2491 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 115], [desktop.m.KeyAction.UP, 115], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'F4' press, 'F4' release, Alt release
2492 + }
2493 + } else if (ks == 8) { // CTRL-W
2494 + if (desktop.contype == 2) {
2495 + desktop.m.sendkey([[0xffe3, 1], [0x77, 1], [0x77, 0], [0xffe3, 0]]); // Intel AMT: Ctrl down, 'w' press, 'w' release, Ctrl release
2496 + } else {
2497 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 17], [desktop.m.KeyAction.DOWN, 87], [desktop.m.KeyAction.UP, 87], [desktop.m.KeyAction.EXUP, 17]]); // MeshAgent: Ctrl press, 'W' press, 'W' release, Ctrl release
2498 + }
2499 + } else if (ks == 9) { // ALT-TAB
2500 + if (desktop.contype == 2) {
2501 + desktop.m.sendkey([[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'TAB' press, 'TAB' release, Alt release
2502 + } else {
2503 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 9], [desktop.m.KeyAction.UP, 9], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'TAB' press, 'TAB' release, Alt release
2504 + }
2505 + } else if (ks == 10) { // CTRL-ALT-DEL
2506 + desktop.m.sendcad();
2507 + } else if (ks == 11) { // TAB
2508 + if (desktop.contype == 2) {
2509 + desktop.m.sendkey([[0xff09, 1], [0xff09, 0]]); // Intel AMT: 'TAB' press, 'TAB' release
2510 + } else {
2511 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN, 9], [desktop.m.KeyAction.UP, 9]]); // MeshAgent: 'TAB' press, 'TAB' release
2512 + }
2513 + }
2514 + }
2515 +
2516 + function sendSpecialKeys() {
2517 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
2518 + setDialogMode(3, "Chaves especiais", 3, deskSendKeys);
2519 + }
2520 +
2521 + // Send CTRL-ALT-DEL
2522 + /*
2523 + function sendCAD() {
2524 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
2525 + desktop.m.sendcad();
2526 + }
2527 + */
2528 +
2529 + // Toggle soft keyboard
2530 + function toggleSoftKeys(x) {
2531 + QV('DeskSoftInput', x == 1);
2532 + if (x == 1) { Q('DeskSoftInput').focus(); }
2533 + }
2534 +
2535 + // Show process dialogs
2536 + function toggleDeskTools() {
2537 + setSessionActivity();
2538 + if (xxdialogMode) return;
2539 + if (QS('DeskTools').display == 'none') {
2540 + QV('DeskTools', true);
2541 + Q('DeskTools').nodeid = currentNode._id;
2542 + refreshDeskTools();
2543 + } else {
2544 + QV('DeskTools', false);
2545 + }
2546 + }
2547 +
2548 + // Refresh all of the desktop tool panels
2549 + function refreshDeskTools() {
2550 + setSessionActivity();
2551 + QV('DeskToolsRefreshButton', false);
2552 + setTimeout(refreshDeskToolsEx, 500);
2553 + meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id });
2554 + }
2555 + function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
2556 + var deskTools = { sort: 1, msg: null };
2557 + function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
2558 + function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return 0; }
2559 + function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
2560 + function showDeskToolsProcesses(message) {
2561 + deskTools.msg = message;
2562 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
2563 + if (Q('DeskTools').nodeid != message.nodeid) return;
2564 + var p = [], processes = null;
2565 + try { processes = JSON.parse(message.value); } catch (e) { }
2566 + console.log(processes);
2567 + if (processes != null) {
2568 + for (var pid in processes) { p.push({ p: parseInt(pid), c: processes[pid].cmd, d: processes[pid].cmd.toLowerCase(), u: processes[pid].user }); }
2569 + if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
2570 + var x = '';
2571 + for (var i in p) { if (p[i].p != 0) { x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a style=float:right;padding-right:5px;cursor:pointer onclick=stopProcess(' + p[i].p + ',"' + p[i].c + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? p[i].u : '') + '</div><div>' + p[i].c + '</div></div>'; } }
2572 + QH('DeskToolsProcesses', x);
2573 + }
2574 + }
2575 +
2576 + // Save the desktop image to file
2577 + function deskSaveImage() {
2578 + setSessionActivity();
2579 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
2580 + var d = new Date(), n = 'Desktop-' + currentNode.name + '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + "-" + ("0" + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
2581 + Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.jpg'); });
2582 + }
2583 +
2584 + function deskDisplayInfo(sender, info, selDisplay, selItem) {
2585 + var txt = Q('termdisplays').value;
2586 + if (info.length > 0) { var options = ''; for (var x in info) { options += '<option' + ((txt == info[x]) ? ' selected' : '') + '>' + info[x] + '</option>'; } QH('termdisplays', options); }
2587 + QV('termdisplays', info.length > 0);
2588 + }
2589 +
2590 + function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
2591 +
2592 + function deskSetDisplay(e) {
2593 + setSessionActivity();
2594 + var display = 0, txt = Q('termdisplays').value;
2595 + if (txt == "Todas as telas") display = 65535; else display = parseInt(txt.substring(8));
2596 + desktop.m.SetDisplay(display);
2597 + }
2598 +
2599 + function dmousedown(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null)) desktop.m.mousedown(e) }
2600 + function dmouseup(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null)) desktop.m.mouseup(e) }
2601 + function dmousemove(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null)) desktop.m.mousemove(e) }
2602 + function dmousewheel(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null) && desktop.m.mousewheel) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; }
2603 + function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
2604 + function stopProcess(id, name) { setDialogMode(2, "Controle do processo", 3, stopProcessEx, format("Parar processo #{0} \"{1}\"?", id, name), id); return false; }
2605 + function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
2606 +
2607 + //
2608 + // FILES
2609 + //
2610 +
2611 + var filesNode;
2612 + function setupFiles() {
2613 + // Setup the files tab
2614 + var samenode = (filesNode == currentNode);
2615 + filesNode = currentNode;
2616 + var online = ((filesNode.conn & 1) != 0) ? true : false; // If Agent (1) connected, enable Terminal
2617 + QE('p13Connect', online);
2618 + if (((samenode == false) || (online == false)) && files) { files.Stop(); files = null; }
2619 + }
2620 +
2621 + function onFilesStateChange(xfiles, state) {
2622 + setSessionActivity();
2623 + p13Connect.value = (state == 0) ? "Conectar" : "Desconectar";
2624 + var str = StatusStrs[state];
2625 + if (files.webRtcActive == true) { str += ", WebRTC"; }
2626 + Q('p13Status').textContent = str;
2627 + switch (state) {
2628 + case 0:
2629 + // Disconnected, clear the files
2630 + QH('p13files', '');
2631 + p13filetree = null;
2632 + p13filetreelocation = [];
2633 + QH('p13currentpath', '');
2634 + QE('p13FolderUp', false);
2635 + p13setActions();
2636 + if (files != null) { files.Stop(); files = null; }
2637 + break;
2638 + case 3:
2639 + p13targetpath = '';
2640 + files.sendText({ action: 'ls', reqid: 1, path: '' });
2641 + break;
2642 + default:
2643 + //console.log('Unknown onFilesStateChange state', state);
2644 + break;
2645 + }
2646 + }
2647 +
2648 + function CreateRemoteFiles(onFileUpdate) {
2649 + var obj = { protocol: 5 };
2650 + obj.onFileUpdate = onFileUpdate;
2651 + obj.xxStateChange = function (state) { }
2652 + obj.ProcessData = function (data) { obj.onFileUpdate(data); }
2653 + return obj;
2654 + }
2655 +
2656 + // Debug Only
2657 + var autoConnectFilesTimer = null;
2658 + function autoConnectFiles(e) { if (autoConnectFilesTimer == null) { autoConnectFilesTimer = setInterval(connectFiles, 100); } else { clearInterval(autoConnectFilesTimer); autoConnectFilesTimer = null; } }
2659 +
2660 + function connectFiles(e) {
2661 + if (!files) {
2662 + // Setup a mesh agent files
2663 + files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
2664 + files.attemptWebRTC = attemptWebRTC;
2665 + files.onStateChanged = onFilesStateChange;
2666 + files.Start(filesNode._id);
2667 + } else {
2668 + //QH('Term', '');
2669 + files.Stop();
2670 + files = null;
2671 + }
2672 + p13clipboard = p13clipboardFolder = null;
2673 + p13clipboardCut = 0;
2674 + p13updateClipview();
2675 + }
2676 +
2677 + var p13filetree = null;
2678 + var p13targetpath = null;
2679 + var p13filetreelocation = [];
2680 +
2681 + function p13gotFiles(data) {
2682 + setSessionActivity();
2683 + //console.log('p13gotFiles', data);
2684 + if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p13gotDownloadBinaryData(data); return; }
2685 + //console.log('p13gotFiles', data);
2686 + data = JSON.parse(decode_utf8(data));
2687 + if (data.action == 'download') { p13gotDownloadCommand(data); return; }
2688 + data.path = data.path.replace(/\//g, "\\");
2689 + if ((p13filetree != null) && (data.path == p13filetree.path)) {
2690 + // This is an update to the same folder
2691 + var checkedNames = p13getCheckedNames();
2692 + p13filetree = data;
2693 + p13updateFiles(checkedNames);
2694 + } else {
2695 + // Make both paths use the same seperator not start with /
2696 + var x1 = data.path.replace(/\//g, "\\"), x2 = p13targetpath.replace(/\//g, "\\");
2697 + while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
2698 + while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
2699 + if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
2700 + // This is a different folder
2701 + p13filetree = data;
2702 + p13updateFiles();
2703 + }
2704 + }
2705 + }
2706 +
2707 + function p13getCheckedNames() {
2708 + // Save all existing checked boxes
2709 + var checkedNames = [], checkboxes = document.getElementsByName('fd');
2710 + for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedNames.push(p13filetree.dir[checkboxes[i].value].n) }; }
2711 + return checkedNames;
2712 + }
2713 +
2714 + function p13updateFiles(checkedNames) {
2715 + var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p13folderup(0)>' + "Raiz" + '</a>', fullPath = 'Root';
2716 +
2717 + // Work on parsing the file path
2718 + var x = p13filetree.path.split('\\');
2719 + p13filetreelocation = [];
2720 + for (var i in x) { if (x[i] != '') { p13filetreelocation.push(x[i]); } } // Remove empty spaces
2721 + for (var i in p13filetreelocation) { displayPath += ' / <a style=cursor:pointer onclick=p13folderup(' + (parseInt(i) + 1) + ')>' + p13filetreelocation[i] + '</a>' } // Setup the path we display
2722 + var newlinkpath = p13filetreelocation.join('/');
2723 +
2724 + // Sort the files
2725 + var filetreexx = p13sort_files(p13filetree.dir);
2726 +
2727 + // Display all files and folders at this location
2728 + for (var i in filetreexx) {
2729 + // Figure out the name and shortname
2730 + var f = filetreexx[i], name = f.n, shortname;
2731 + shortname = name;
2732 + if (name.length > 70) { shortname = EscapeHtml(name.substring(0, 70)) + "..."; } else { shortname = EscapeHtml(name); }
2733 + name = EscapeHtml(name);
2734 +
2735 + // Figure out the size
2736 + var fsize = '';
2737 + if (f.s != null) { fsize = getFileSizeStr(f.s); }
2738 +
2739 + var h = '';
2740 + if (f.t < 3) {
2741 + var right = '';
2742 + h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span style=float:right>' + right + '</span><span><div class=fileIcon' + f.t + '></div><a style=cursor:pointer onclick=p13folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
2743 + } else {
2744 + var link = shortname;
2745 + if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"p13downloadfile(\'' + encodeURIComponent(newlinkpath + '/' + name) + '\',\'' + encodeURIComponent(name) + '\',' + f.s + ')\">' + shortname + '</a>'; }
2746 + h = '<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span style=float:right;padding-right:4px>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
2747 + }
2748 +
2749 + if (f.t < 3) { html1 += h; } else { html2 += h; }
2750 + }
2751 +
2752 + // Display the files and path
2753 + QH('p13files', html1 + html2);
2754 + QH('p13currentpath', displayPath);
2755 + QE('p13FolderUp', p13filetreelocation.length != 0);
2756 +
2757 + // Re-check all boxes if needed using names
2758 + if (checkedNames != null) { var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkedNames.indexOf(p13filetree.dir[checkboxes[i].value].n) >= 0) { checkboxes[i].checked = true; } } }
2759 +
2760 + // Update the actions buttons
2761 + p13setActions();
2762 + }
2763 +
2764 + function p13folderset(x) {
2765 + p13targetpath = joinPaths(p13filetree.path, p13filetree.dir[x].n).split('\\').join('/');
2766 + files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
2767 + }
2768 +
2769 + function p13folderup(x) {
2770 + if (x == null) { p13filetreelocation.pop(); } else { while (p13filetreelocation.length > x) { p13filetreelocation.pop(); } }
2771 + p13targetpath = p13filetreelocation.join('/');
2772 + files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
2773 + }
2774 +
2775 + var p13sortorder;
2776 + function p13sort_filename(a, b) { if (a.ln > b.ln) return (1 * p13sortorder); if (a.ln < b.ln) return (-1 * p13sortorder); return 0; }
2777 + function p13sort_timestamp(a, b) { if (a.d > b.d) return (1 * p13sortorder); if (a.d < b.d) return (-1 * p13sortorder); return 0; }
2778 + function p13sort_bysize(a, b) { if (a.s == b.s) return p13sort_filename(a, b); return (((a.s - b.s)) * p13sortorder); }
2779 +
2780 + function p13sort_files(files) {
2781 + var r = [], sortselection = Q('p13sortdropdown').value;
2782 + for (var i in files) { files[i].nx = i; if (files[i].s == null) { files[i].s = 0; } if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
2783 + p13sortorder = 1;
2784 + if (sortselection > 3) { p13sortorder = -1; sortselection -= 3; }
2785 + if (sortselection == 1) { r.sort(p13sort_filename); }
2786 + else if (sortselection == 2) { r.sort(p13sort_bysize); }
2787 + else if (sortselection == 3) { r.sort(p13sort_timestamp); }
2788 + return r;
2789 + }
2790 +
2791 + function p13setActions() {
2792 + if (p13filetree == null) {
2793 + QE('p13DeleteFileButton', false);
2794 + QE('p13NewFolderButton', false);
2795 + QE('p13UploadButton', false);
2796 + QE('p13RenameFileButton', false);
2797 + QE('p13SelectAllButton', false);
2798 + Q('p13SelectAllButton').value = "Todos";
2799 + QE('p13RefreshButton', false);
2800 + QE('p13CutButton', false);
2801 + QE('p13CopyButton', false);
2802 + QE('p13PasteButton', false);
2803 + } else {
2804 + var cc = p13getFileSelCount(), tc = p13getFileCount(), sfc = p13getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
2805 + var winAgent = ((currentNode.agent.id > 0) && (currentNode.agent.id < 5));
2806 + QE('p13DeleteFileButton', (cc > 0) && ((p13filetreelocation.length > 0) || (winAgent == false)));
2807 + QE('p13NewFolderButton', ((p13filetreelocation.length > 0) || (winAgent == false)));
2808 + QE('p13UploadButton', ((p13filetreelocation.length > 0) || (winAgent == false)));
2809 + QE('p13RenameFileButton', (cc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
2810 + QE('p13SelectAllButton', tc > 0);
2811 + Q('p13SelectAllButton').value = (cc > 0 ? "Nenhum" : "Todos");
2812 + QE('p13RefreshButton', true);
2813 + QE('p13CutButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
2814 + QE('p13CopyButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
2815 + QE('p13PasteButton', ((p13filetreelocation.length > 0) || (winAgent == false)) && ((p13clipboard != null) && (p13clipboard.length > 0)));
2816 + }
2817 + }
2818 +
2819 + function p13getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
2820 + function p13getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
2821 + function p13getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
2822 + function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
2823 + function p13createfolder() { setDialogMode(2, "Nova pasta", 3, p13createfolderEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />'); focusTextBox('p13renameinput'); p13fileNameCheck(); }
2824 + function p13createfolderEx() { files.sendText({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value }); p13folderup(999); }
2825 + function p13deletefile() { var cc = p13getFileSelCount(), rec = (p13getFileSelDirCount() > 0) ? '<br /><br /><label><input type=checkbox id=p13recdeleteinput>' + "Exclusão recursiva" + '</label><br>' : '<input type=checkbox id=p13recdeleteinput style=\'display:none\'>'; setDialogMode(2, "Deletar", 3, p13deletefileEx, (cc > 1) ? (format("Excluir {0} itens selecionados?", cc) + rec) : ("Excluir item selecionado?" + rec)); }
2826 + function p13deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(p13filetree.dir[checkboxes[i].value].n); } } files.sendText({ action: 'rm', reqid: 1, path: p13filetreelocation.join('/'), delfiles: delfiles, rec: Q('p13recdeleteinput').checked }); p13folderup(999); }
2827 + function p13renamefile() { var renamefile, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = p13filetree.dir[checkboxes[i].value].n; } } setDialogMode(2, "Renomear", 3, p13renamefileEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'rename', path: p13filetreelocation.join('/'), oldname: renamefile }); focusTextBox('p13renameinput'); p13fileNameCheck(); }
2828 + function p13renamefileEx(b, t) { t.newname = Q('p13renameinput').value; files.sendText(t); p13folderup(999); }
2829 + function p13fileNameCheck(e) { var x = isFilenameValid(Q('p13renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e != null) && (e.keyCode == 13)) { dialogclose(1); } }
2830 + function p13uploadFile() { setDialogMode(2, "Subir arquivo", 3, p13uploadFileEx, '<input type=file name=files id=p13uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p13uploadinput\')" />'); updateUploadDialogOk('p13uploadinput'); }
2831 + function p13uploadFileEx() { p13doUploadFiles(Q('p13uploadinput').files); }
2832 + function p13viewfile() {
2833 + var checkboxes = document.getElementsByName('fd');
2834 + for (var i = 0; i < checkboxes.length; i++) {
2835 + if (checkboxes[i].checked) {
2836 + if (p13filetree.dir[checkboxes[i].value].s <= 204800) {
2837 + p13downloadfile(encodeURIComponent(p13filetreelocation.join('/') + '/' + p13filetree.dir[checkboxes[i].value].n), encodeURIComponent(p13filetree.dir[checkboxes[i].value].n), p13filetree.dir[checkboxes[i].value].s, 'viewer');
2838 + } else { messagebox("Editor de Arquivos", "Somente arquivos com menos de 200k podem ser editados."); }
2839 + break;
2840 + }
2841 + }
2842 + }
2843 +
2844 + var p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0;
2845 + function p13copyFile(cut) { var checkboxes = document.getElementsByName('fd'); p13clipboard = []; p13clipboardCut = cut, p13clipboardFolder = p13targetpath; for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '3')) { p13clipboard.push(p13filetree.dir[checkboxes[i].value].n); } } p13updateClipview(); }
2846 + function p13pasteFile() {
2847 + var x = '';
2848 + if ((p13clipboard != null) && (p13clipboard.length > 0)) {
2849 + if (p13clipboardCut == 0) {
2850 + if (p13clipboard.length > 1) { x = format("Confirmar cópia de {0} entradas para este local?", p13clipboard.length); } else { x = format("Confirmar cópia de 1 entrada para este local?"); }
2851 + } else {
2852 + if (p13clipboard.length > 1) { x = format("Confirmar a movimentação de {0} entradas para este local?", p13clipboard.length); } else { x = format("Confirmar a movimentação de 1 entrada para este local?"); }
2853 + }
2854 + }
2855 + setDialogMode(2, "Colar", 3, p13pasteFileEx, x);
2856 + }
2857 + function p13pasteFileEx() { files.sendText({ action: (p13clipboardCut == 0 ? 'copy' : 'move'), reqid: 1, scpath: p13clipboardFolder, dspath: p13targetpath, names: p13clipboard }); p13folderup(999); if (p13clipboardCut == 1) { p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0; p13updateClipview(); } }
2858 + function p13updateClipview() {
2859 + var x = '';
2860 + if ((p13clipboard != null) && (p13clipboard.length > 0)) {
2861 + if (p13clipboardCut == 0) {
2862 + if (p13clipboard.length > 1) {
2863 + x = format("Mantendo {0} entradas para cópia" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Limpo" + '</a>.', p13clipboard.length);
2864 + } else {
2865 + x = format("Mantendo 1 entrada para cópia" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Limpo" + '</a>.');
2866 + }
2867 + } else {
2868 + if (p13clipboard.length > 1) {
2869 + x = format("Manter {0} entradas para mover" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Limpo" + '</a>.', p13clipboard.length);
2870 + } else {
2871 + x = format("Segurando 1 entrada para mover" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Limpo" + '</a>.');
2872 + }
2873 + }
2874 + }
2875 + QH('p13bottomstatus', x);
2876 + p13setActions();
2877 + }
2878 + function p13clearClip() { p13clipboard = null; p13clipboardFolder = null; p13clipboardCut = 0; p13updateClipview(); return false; } function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
2879 + function getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
2880 + function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
2881 +
2882 + //
2883 + // FILES DOWNLOAD
2884 + //
2885 +
2886 + var downloadFile; // Global state for file download
2887 +
2888 + // Called by the html page to start a download, arguments are: path, file name and file size.
2889 + function p13downloadfile(x, y, z) {
2890 + if (xxdialogMode || downloadFile || !files) return;
2891 + downloadFile = { path: decodeURIComponent(x), file: decodeURIComponent(y), size: z, tsize: 0, data: '', state: 0, id: Math.random() }
2892 + //console.log('p13downloadFileCancel', downloadFile);
2893 + files.sendText({ action: 'download', sub: 'start', id: downloadFile.id, path: downloadFile.path });
2894 + setDialogMode(2, "⇬ Fazer download do arquivo", 10, p13downloadFileCancel, '<div>' + downloadFile.file + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
2895 + }
2896 +
2897 + // Called by the html page to cancel the download
2898 + function p13downloadFileCancel() { setDialogMode(0); files.sendText({ action: 'download', sub: 'cancel', id: downloadFile.id }); downloadFile = null; }
2899 +
2900 + // Called by the transport when download control command is received
2901 + function p13gotDownloadCommand(cmd) {
2902 + //console.log('p13gotDownloadCommand', cmd);
2903 + if ((downloadFile == null) || (cmd.id != downloadFile.id)) return;
2904 + if (cmd.sub == 'start') { downloadFile.state = 1; files.sendText({ action: 'download', sub: 'startack', id: downloadFile.id }); }
2905 + else if (cmd.sub == 'cancel') { downloadFile = null; setDialogMode(0); }
2906 + }
2907 +
2908 + // Called by the transport when binary data is received
2909 + function p13gotDownloadBinaryData(data) {
2910 + if (!downloadFile || downloadFile.state == 0) return;
2911 + if (data.length > 4) {
2912 + downloadFile.tsize += (data.length - 4); // Add to the total bytes received
2913 + downloadFile.data += data.substring(4); // Append the data
2914 + Q('d2progressBar').value = downloadFile.tsize; // Change the progress bar
2915 + }
2916 + if ((ReadInt(data, 0) & 1) != 0) { // Check end flag
2917 + saveAs(data2blob(downloadFile.data), downloadFile.file); downloadFile = null; setDialogMode(0); // Save the file
2918 + } else {
2919 + files.sendText({ action: 'download', sub: 'ack', id: downloadFile.id }); // Send the ACK
2920 + }
2921 + }
2922 +
2923 + /*
2924 + var downloadFile; // Global state for file download
2925 +
2926 + // Called by the html page to start a download, arguments are: path, file name and file size.
2927 + function p13downloadfile(x, y, z) {
2928 + if (xxdialogMode) return;
2929 + downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); // Create our websocket file transport
2930 + downloadFile.ctrlMsgAllowed = false;
2931 + downloadFile.onStateChanged = onFileDownloadStateChange;
2932 + downloadFile.xpath = decodeURIComponent(x);
2933 + downloadFile.xfile = decodeURIComponent(y);
2934 + downloadFile.xsize = z;
2935 + downloadFile.xtsize = 0;
2936 + downloadFile.xstate = 0;
2937 + downloadFile.Start(filesNode._id);
2938 + setDialogMode(2, "Download File", 10, p13downloadFileCancel, '<div>' + downloadFile.xfile + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
2939 + }
2940 +
2941 + // Called by the html page to cancel the download
2942 + function p13downloadFileCancel(button, tag) {
2943 + //console.log('p13downloadFileCancel');
2944 + downloadFile.Stop();
2945 + delete downloadFile;
2946 + downloadFile = null;
2947 + }
2948 +
2949 + // Called by the file transport to indicate when the transport connection state has changed
2950 + function onFileDownloadStateChange(xdownloadFile, state) {
2951 + switch (state) {
2952 + case 0: // Transport as disconnected. If this is not part of an abort, we need to save the file
2953 + setDialogMode(0); // Close any dialog boxes if present
2954 + if ((downloadFile != null) && (downloadFile.xstate == 1)) { saveAs(data2blob(downloadFile.xdata), downloadFile.xfile); } // Save the file
2955 + break;
2956 + case 3: // Transport as connected, send a command to indicate we want to start a file download
2957 + downloadFile.send(JSON.stringify({ action: 'download', reqid: 1, path: downloadFile.xpath }));
2958 + break;
2959 + default:
2960 + console.log('Unknown onFileDownloadStateChange state', state);
2961 + break;
2962 + }
2963 + }
2964 +
2965 + // Called by the transport when data is received
2966 + function p13gotDownloadData(data) {
2967 + if (downloadFile.xstate == 0) { // If state is 0, this is a command confirming if the file will be transfered.
2968 + var cmd = JSON.parse(data);
2969 + if (cmd.action == 'downloadstart') { // Yes, the file is about to start
2970 + downloadFile.xstate = 1; // Switch to state 1, we will start receiving the file data
2971 + downloadFile.xdata = ''; // Start with empty data
2972 + downloadFile.send('a'); // Send the first ACK
2973 + } else if (cmd.action == 'downloaderror') { // Problem opening this file, cancel
2974 + p13downloadFileCancel();
2975 + }
2976 + } else { // We are in the process of receiving the file
2977 + downloadFile.xtsize += (data.length); // Add to the total bytes received
2978 + downloadFile.xdata += data; // Append the data
2979 + Q('d2progressBar').value = downloadFile.xtsize; // Change the progress bar
2980 + downloadFile.send('a'); // Send the ACK
2981 + }
2982 + }
2983 + */
2984 +
2985 + //
2986 + // FILES UPLOAD
2987 + //
2988 +
2989 + var uploadFile;
2990 + function p13doUploadFiles(files) {
2991 + if (xxdialogMode) return;
2992 + uploadFile = {};
2993 + uploadFile.xpath = p13filetreelocation.join('/');
2994 + uploadFile.xfiles = files;
2995 + uploadFile.xfilePtr = -1;
2996 + setDialogMode(2, "Subir arquivo", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "Conectando..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
2997 + p13uploadReconnect();
2998 + }
2999 +
3000 + function onFileUploadStateChange(xdownloadFile, state) {
3001 + switch (state) {
3002 + case 0:
3003 + p13folderup(9999);
3004 + break;
3005 + case 3:
3006 + p13uploadNextFile();
3007 + break;
3008 + default:
3009 + console.log('Unknown onFileUploadStateChange state', state);
3010 + break;
3011 + }
3012 + }
3013 +
3014 + // Connect again
3015 + function p13uploadReconnect() {
3016 + uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
3017 + uploadFile.ws.attemptWebRTC = false;
3018 + uploadFile.ws.ctrlMsgAllowed = false;
3019 + uploadFile.ws.onStateChanged = onFileUploadStateChange;
3020 + uploadFile.ws.Start(filesNode._id);
3021 + }
3022 +
3023 + // Push the next file
3024 + function p13uploadNextFile() {
3025 + uploadFile.xfilePtr++;
3026 + if (uploadFile.xfiles.length > uploadFile.xfilePtr) {
3027 + uploadFile.xptr = 0;
3028 + var file = uploadFile.xfiles[uploadFile.xfilePtr];
3029 + QH('p13dfileName', file.name);
3030 + Q('d2progressBar').max = file.size;
3031 + Q('d2progressBar').value = 0;
3032 +
3033 + uploadFile.xreader = new FileReader();
3034 + uploadFile.xreader.onload = function () {
3035 + uploadFile.xdata = uploadFile.xreader.result;
3036 + uploadFile.ws.sendText({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength });
3037 + };
3038 + uploadFile.xreader.readAsArrayBuffer(file);
3039 + } else {
3040 + p13uploadFileCancel();
3041 + }
3042 + }
3043 +
3044 + // Used to cancel the entire transfer.
3045 + function p13uploadFileCancel(button, tag) {
3046 + if (uploadFile != null) {
3047 + if (uploadFile.ws != null) {
3048 + uploadFile.ws.Stop();
3049 + uploadFile.ws = null;
3050 + }
3051 + uploadFile = null;
3052 + }
3053 + setDialogMode(0); // Close any dialog boxes if present
3054 + }
3055 +
3056 + // Receive upload ack from the mesh agent, use this to keep sending more data
3057 + function p13gotUploadData(data) {
3058 + var cmd = JSON.parse(data);
3059 + if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
3060 +
3061 + if (cmd.action == 'uploadstart') {
3062 + p13uploadNextPart(false);
3063 + for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket.
3064 + } else if (cmd.action == 'uploadack') {
3065 + p13uploadNextPart(false);
3066 + } else if (cmd.action == 'uploaderror') {
3067 + p13uploadFileCancel();
3068 + }
3069 + }
3070 +
3071 + // Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
3072 + function p13uploadNextPart(dataPriming) {
3073 + var data = uploadFile.xdata;
3074 + var start = uploadFile.xptr;
3075 + var end = uploadFile.xptr + 4096;
3076 + if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
3077 + if (start == data.byteLength) {
3078 + if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; }
3079 + if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); }
3080 + } else {
3081 + var datapart = data.slice(start, end);
3082 + uploadFile.ws.send(datapart);
3083 + uploadFile.xptr = end;
3084 + Q('d2progressBar').value = end;
3085 + }
3086 + }
3087 +
3088 + //
3089 + // MY MESHS
3090 + //
3091 +
3092 + var currentMesh;
3093 + function p20updateMesh() {
3094 + if (currentMesh == null) return;
3095 + QH('p20meshName', EscapeHtml(currentMesh.name));
3096 + var meshtype = format("Desconhecido # {0}", currentMesh.mtype);
3097 + var meshrights = currentMesh.links[userinfo._id].rights;
3098 + if (currentMesh.mtype == 1) meshtype = "Intel&reg; Apenas AMT, nenhum agente";
3099 + if (currentMesh.mtype == 2) meshtype = "Gerenciado usando um agente de software";
3100 +
3101 + var x = '';
3102 + x += addHtmlValue("Nome", addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
3103 + x += addHtmlValue("Descrição", addLinkConditional(((currentMesh.desc && currentMesh.desc != '') ? EscapeHtml(currentMesh.desc) : ('<i>' + "Nenhum" + '</i>')), 'p20editmesh(2)', (meshrights & 1) != 0));
3104 + x += addHtmlValue("Tipo", meshtype);
3105 + //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
3106 +
3107 + //x += '<br><input type=button value=Notes onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />';
3108 +
3109 + x += '<br style=clear:both><br>';
3110 + var currentMeshLinks = currentMesh.links[userinfo._id];
3111 + if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<div style=margin-bottom:6px><a onclick=p20showAddMeshUserDialog() style=cursor:pointer><img src=images/icon-addnew.png border=0 height=12 width=12>' + "Adicionar usuário" + '</a></div>'; }
3112 +
3113 + /*
3114 + if ((meshrights & 4) != 0) {
3115 + if (currentMesh.mtype == 1) {
3116 + x += '<a onclick=addCiraDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-installmesh.png border=0 height=12 width=12> Install CIRA</a>';
3117 + x += '<a onclick=addDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-installmesh.png border=0 height=12 width=12> Install local</a>';
3118 + }
3119 + if (currentMesh.mtype == 2) {
3120 + x += '<a onclick=addAgentToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Install</a>';
3121 + }
3122 + }
3123 + */
3124 +
3125 + /*
3126 + function getMeshActions(mesh, meshrights) {
3127 + if ((meshrights & 4) == 0) return '';
3128 + var r = '';
3129 + if (mesh.mtype == 1) {
3130 + r += ' <a style=cursor:pointer;font-size:10px onclick=addCiraDeviceToMesh(\"' + mesh._id + '\")>Add CIRA</a>';
3131 + r += ' <a style=cursor:pointer;font-size:10px onclick=addDeviceToMesh(\"' + mesh._id + '\")>Add Local</a>';
3132 + }
3133 + if (mesh.mtype == 2) {
3134 + r += ' <a style=cursor:pointer;font-size:10px onclick=addAgentToMesh(\"' + mesh._id + '\")>Add Agent</a>';
3135 + }
3136 + return r;
3137 + }
3138 + */
3139 +
3140 + x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Autorizações de usuário" + '</th></tr>';
3141 +
3142 + // Sort the users for this mesh
3143 + var count = 1, sortedusers = [];
3144 + for (var i in currentMesh.links) { sortedusers.push({ id: i, name: i.split('/')[2], rights: currentMesh.links[i].rights }); }
3145 + sortedusers.sort(function (a, b) { if (a.name > b.name) return 1; if (a.name < b.name) return -1; return 0; });
3146 +
3147 + // Display all users for this mesh
3148 + for (var i in sortedusers) {
3149 + var trash = '', rights = "Direitos parciais", r = sortedusers[i].rights;
3150 + if (r == 0xFFFFFFFF) rights = "Administrador completo"; else if (r == 0) rights = "Sem direitos";
3151 + if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
3152 + x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=height:32px;cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td>';
3153 + x += '<div style=float:right>' + trash + '</div><div style=float:right;padding-right:4px>' + rights + '</div><div class=m2></div><div>&nbsp;' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div>';
3154 + x += '</td></tr>';
3155 + ++count;
3156 + }
3157 +
3158 + x += '</tbody></table>';
3159 +
3160 + // If we are full administrator on this mesh, allow deletion of the mesh
3161 + if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:small;text-align:right;margin-top:6px><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>' + "Excluir grupo" + '</a></span></div>'; }
3162 +
3163 + QH('p20info', x);
3164 + }
3165 +
3166 + function p20showDeleteMeshDialog() {
3167 + if (xxdialogMode) return false;
3168 + var x = format("Tem certeza de que deseja excluir o grupo {0}? A exclusão do grupo de dispositivos também excluirá todas as informações sobre os dispositivos desse grupo.", EscapeHtml(currentMesh.name)) + '<br /><br />';
3169 + x += '<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />' + "Confirme" + '</label>';
3170 + setDialogMode(2, "Excluir grupo", 3, p20showDeleteMeshDialogEx, x);
3171 + p20validateDeleteMeshDialog();
3172 + return false;
3173 + }
3174 +
3175 + function p20validateDeleteMeshDialog() {
3176 + QE('idx_dlgOkButton', Q('p20check').checked);
3177 + }
3178 +
3179 + function p20showDeleteMeshDialogEx(buttons, tag) {
3180 + meshserver.send({ action: 'deletemesh', meshid: currentMesh._id, meshname: currentMesh.name });
3181 + }
3182 +
3183 + function p20editmesh(focus) {
3184 + if (xxdialogMode) return;
3185 + var x = addHtmlValue("Nome", '<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
3186 + x += addHtmlValue("Descrição", '<input id=dp20meshdesc style=width:170px maxlength=1024 onkeyup=p20editmeshValidate() />');
3187 + setDialogMode(2, "Editar grupo de dispositivos", 3, p20editmeshEx, x);
3188 + Q('dp20meshname').value = currentMesh.name;
3189 + if (currentMesh.desc) Q('dp20meshdesc').value = currentMesh.desc;
3190 + p20editmeshValidate();
3191 + if (focus == 2) { Q('dp20meshdesc').focus(); } else { Q('dp20meshname').focus(); }
3192 + }
3193 +
3194 + function p20editmeshEx() {
3195 + meshserver.send({ action: 'editmesh', meshid: currentMesh._id, meshname: Q('dp20meshname').value, desc: Q('dp20meshdesc').value });
3196 + }
3197 +
3198 + function p20editmeshValidate() {
3199 + QE('idx_dlgOkButton', Q('dp20meshname').value.length > 0);
3200 + }
3201 +
3202 + function p20showAddMeshUserDialog() {
3203 + if (xxdialogMode) return;
3204 + var x = addHtmlValue('User', '<input id=dp20username style=width:170px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />');
3205 + x += '<div style="border:2px groove gray;background-color:white;max-height:120px;overflow-y:scroll">';
3206 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>' + "Administrador completo" + '</label><br>';
3207 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>' + "Editar grupo de dispositivos" + '</label><br>';
3208 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>' + "Gerenciar usuários do grupo de dispositivos" + '</label><br>';
3209 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>' + "Gerenciar computadores do grupo de dispositivos" + '</label><br>';
3210 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>' + "Controle remoto" + '</label><br>';
3211 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>' + "Somente visualização remota" + '</label><br>';
3212 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>' + "Somente entrada limitada" + '</label><br>';
3213 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>' + "Sem acesso ao terminal" + '</label><br>';
3214 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>' + "Sem acesso a arquivos" + '</label><br>';
3215 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>' + "Nenhum Intel&reg; AMT" + '</label><br>';
3216 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>' + "Mesh Agent Console" + '</label><br>';
3217 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>' + "Arquivos do servidor" + '</label><br>';
3218 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>' + "Reativar dispositivo" + '</label><br>';
3219 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>' + "Editar notas do dispositivo" + '</label><br>';
3220 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>' + "Mostrar apenas eventos próprios" + '</label><br>';
3221 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>' + "Chat & Notificação" + '</label><br>';
3222 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20uninstall>' + "Uninstall Agent" + '</label><br>';
3223 + x += '</div>';
3224 + setDialogMode(2, "Adicionar usuário à malha", 3, p20showAddMeshUserDialogEx, x);
3225 + p20validateAddMeshUserDialog();
3226 + Q('dp20username').focus();
3227 + }
3228 +
3229 + function p20validateAddMeshUserDialog() {
3230 + var meshrights = currentMesh.links[userinfo._id].rights;
3231 + var nc = !Q('p20fulladmin').checked;
3232 + QE('p20fulladmin', meshrights == 0xFFFFFFFF);
3233 + QE('p20editmesh', nc && (meshrights == 0xFFFFFFFF));
3234 + QE('p20manageusers', nc);
3235 + QE('p20managecomputers', nc);
3236 + QE('p20remotecontrol', nc);
3237 + QE('p20meshagentconsole', nc);
3238 + QE('p20meshserverfiles', nc);
3239 + QE('p20wakedevices', nc);
3240 + QE('p20editnotes', nc);
3241 + QE('p20limitevents', nc);
3242 + QE('p20remoteview', nc && Q('p20remotecontrol').checked);
3243 + QE('p20remotelimitedinput', nc && Q('p20remotecontrol').checked && !Q('p20remoteview').checked);
3244 + QE('p20noterminal', nc && Q('p20remotecontrol').checked);
3245 + QE('p20nofiles', nc && Q('p20remotecontrol').checked);
3246 + QE('p20noamt', nc && Q('p20remotecontrol').checked);
3247 + QE('p20chatnotify', nc);
3248 + QE('p20uninstall', nc);
3249 + }
3250 +
3251 + function p20showAddMeshUserDialogEx() {
3252 + var meshadmin = 0;
3253 + if (Q('p20fulladmin').checked == true) { meshadmin = 0xFFFFFFFF; } else {
3254 + if (Q('p20editmesh').checked == true) meshadmin += 1;
3255 + if (Q('p20manageusers').checked == true) meshadmin += 2;
3256 + if (Q('p20managecomputers').checked == true) meshadmin += 4;
3257 + if (Q('p20remotecontrol').checked == true) meshadmin += 8;
3258 + if (Q('p20meshagentconsole').checked == true) meshadmin += 16;
3259 + if (Q('p20meshserverfiles').checked == true) meshadmin += 32;
3260 + if (Q('p20wakedevices').checked == true) meshadmin += 64;
3261 + if (Q('p20editnotes').checked == true) meshadmin += 128;
3262 + if (Q('p20remoteview').checked == true) meshadmin += 256;
3263 + if (Q('p20noterminal').checked == true) meshadmin += 512;
3264 + if (Q('p20nofiles').checked == true) meshadmin += 1024;
3265 + if (Q('p20noamt').checked == true) meshadmin += 2048;
3266 + if (Q('p20remotelimitedinput').checked == true) meshadmin += 4096;
3267 + if (Q('p20limitevents').checked == true) meshadmin += 8192;
3268 + if (Q('p20chatnotify').checked == true) meshadmin += 16384;
3269 + if (Q('p20uninstall').checked == true) meshadmin += 32768;
3270 + }
3271 + var users = Q('dp20username').value.split(','), users2 = [];
3272 + for (var i in users) { users2.push(users[i].trim()); }
3273 + meshserver.send({ action: 'addmeshuser', meshid: currentMesh._id, meshname: currentMesh.name, usernames: users2, meshadmin: meshadmin });
3274 + }
3275 +
3276 + function p20viewuser(userid) {
3277 + if (xxdialogMode) return;
3278 + userid = decodeURIComponent(userid);
3279 + var r = [], cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights;
3280 + if (meshrights == 0xFFFFFFFF) r.push("Administrador completo"); else {
3281 + if ((meshrights & 1) != 0) r.push("Editar grupo de dispositivos");
3282 + if ((meshrights & 2) != 0) r.push("Gerenciar usuários do grupo de dispositivos");
3283 + if ((meshrights & 4) != 0) r.push("Gerenciar computadores do grupo de dispositivos");
3284 + if ((meshrights & 8) != 0) r.push("Controle remoto");
3285 + if ((meshrights & 16) != 0) r.push("Console do agente");
3286 + if ((meshrights & 32) != 0) r.push("Arquivos do servidor");
3287 + if ((meshrights & 64) != 0) r.push("Reativar dispositivo");
3288 + if ((meshrights & 128) != 0) r.push("Editar notas");
3289 + if ((meshrights & 256) != 0) r.push("Somente visualização remota");
3290 + if ((meshrights & 512) != 0) r.push("Sem terminal");
3291 + if ((meshrights & 1024) != 0) r.push("Sem arquivos");
3292 + if ((meshrights & 2048) != 0) r.push("Nenhum Intel&reg; AMT");
3293 + if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("Entrada limitada");
3294 + if ((meshrights & 8192) != 0) r.push("Somente Eventos Próprios");
3295 + if ((meshrights & 16384) != 0) r.push("Chat & Notificação");
3296 + if ((meshrights & 32768) != 0) r.push("Uninstall");
3297 + }
3298 + if (r.length == 0) { r.push("Sem direitos"); }
3299 + var buttons = 1, x = addHtmlValue("Do utilizador", EscapeHtml(decodeURIComponent(userid.split('/')[2])));
3300 + x += addHtmlValue("Permissões", r.join(","));
3301 + if (((userinfo._id) != userid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
3302 + setDialogMode(2, "Usuário do grupo de dispositivos", buttons, p20viewuserEx, x, userid);
3303 + }
3304 +
3305 + function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "Usuário de malha remota", 3, p20viewuserEx2, format("Confirmar remoção do usuário {0}?", userid.split('/')[2]), userid); }
3306 + function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
3307 + function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
3308 +
3309 + //
3310 + // PANELS
3311 + //
3312 +
3313 + var xxcurrentView = -1;
3314 + function go(x) {
3315 + setSessionActivity();
3316 + if (xxdialogMode || xxcurrentView == x) return;
3317 + updateFooterMenu();
3318 + setDialogMode(0);
3319 + // Edit this line when adding a new screen
3320 + for (var i = 0; i < 32; i++) { QV('p' + i, i == x); }
3321 + xxcurrentView = x;
3322 + }
3323 +
3324 + //
3325 + // POPUP DIALOG
3326 + //
3327 +
3328 + // undefined = Hidden, 1 = Generic Message
3329 + var xxdialogMode;
3330 + var xxdialogFunc;
3331 + var xxdialogButtons;
3332 + var xxdialogTag;
3333 +
3334 + // Display a dialog box
3335 + // 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)
3336 + function setDialogMode(x, y, b, f, c, tag) {
3337 + setSessionActivity();
3338 + xxdialogMode = x;
3339 + xxdialogFunc = f;
3340 + xxdialogButtons = b;
3341 + xxdialogTag = tag;
3342 + QE('idx_dlgOkButton', true);
3343 + QV('idx_dlgOkButton', b & 1);
3344 + QV('idx_dlgCancelButton', b & 2);
3345 + QV('id_dialogclose', (b & 2) || (b & 8));
3346 + QV('idx_dlgButtonBar', b & 7);
3347 + if (y) QH('id_dialogtitle', y);
3348 + for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
3349 + QV('dialog', x);
3350 + if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
3351 + }
3352 +
3353 + function dialogclose(x) {
3354 + setSessionActivity();
3355 + var f = xxdialogFunc;
3356 + var b = xxdialogButtons;
3357 + var t = xxdialogTag;
3358 + setDialogMode();
3359 + if (((b & 8) || x) && f) f(x, t);
3360 + }
3361 +
3362 + function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
3363 + 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; } }
3364 + function center() { QS('dialog').left = ((((getDocWidth() - 300) / 2)) + 'px'); deskAdjust(); deskAdjust(); /*drawDeviceTimeline();*/ }
3365 + function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
3366 + function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
3367 + 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; }
3368 + function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
3369 + function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
3370 + 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); }
3371 + function reload() { window.location.href = window.location.href; }
3372 + function getNodeFromId(id) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } return null; }
3373 + function addHtmlValue(t, v) { return '<table><td style=width:120px>' + t + '<td><b>' + v + '</b></table>'; }
3374 + function addHtmlValue2(t, v) { return '<div><div style=display:inline-block;float:right>' + v + '</div><div style=display:inline-block>' + t + '</div></div>'; }
3375 + function addLink(x, f) { return '<a style=cursor:pointer;color:darkblue;text-decoration:none onclick=\'' + f + '\'>&diams; ' + x + '</a>'; }
3376 + function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
3377 + function passwordcheck(p) { var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/; return re.test(p); }
3378 + function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format('{0} bytes', size); }
3379 + function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
3380 + function focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
3381 + var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
3382 + 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; }
3383 + function printDate(d) { return d.toLocaleDateString(args.locale); }
3384 + function printTime(d) { return d.toLocaleTimeString(args.locale); }
3385 + function printDateTime(d) { return d.toLocaleString(args.locale); }
3386 + 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; }); };
3387 + function nobreak(x) { return x.split(' ').join('&nbsp;'); }
3388 +
3389 + </script>
3390 +
3391 +</body></html>
\ No newline at end of file
views/translations/default_pt.handlebars new
+9720
@@ -0,0 +1,9720 @@
1 +<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico">
8 + <link keeplink="1" type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
9 + <link type="text/css" href="styles/ol.css" media="screen" rel="stylesheet" title="CSS">
10 + <link type="text/css" href="styles/ol3-contextmenu.min.css" media="screen" rel="stylesheet" title="CSS">
11 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
12 + <script type="text/javascript" src="scripts/meshcentral.js"></script>
13 + <script type="text/javascript" src="scripts/amt-0.2.0.js"></script>
14 + <script type="text/javascript" src="scripts/amt-wsman-0.2.0.js"></script>
15 + <script type="text/javascript" src="scripts/amt-desktop-0.0.2.js"></script>
16 + <script type="text/javascript" src="scripts/amt-terminal-0.0.2.js"></script>
17 + <script type="text/javascript" src="scripts/zlib.js"></script>
18 + <script type="text/javascript" src="scripts/zlib-inflate.js"></script>
19 + <script type="text/javascript" src="scripts/zlib-adler32.js"></script>
20 + <script type="text/javascript" src="scripts/zlib-crc32.js"></script>
21 + <script type="text/javascript" src="scripts/amt-redir-ws-0.1.0.js"></script>
22 + <script type="text/javascript" src="scripts/amt-wsman-ws-0.2.0.js"></script>
23 + <script type="text/javascript" src="scripts/agent-redir-ws-0.1.1.js"></script>
24 + <script type="text/javascript" src="scripts/agent-redir-rtc-0.1.0.js"></script>
25 + <script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
26 + <script type="text/javascript" src="scripts/qrcode.min.js"></script>
27 + <script keeplink="1" type="text/javascript" src="scripts/u2f-api.js"></script>
28 + <script keeplink="1" type="text/javascript" src="scripts/charts.js"></script>
29 + <script keeplink="1" type="text/javascript" src="scripts/filesaver.js"></script>
30 + </head><body id="body" onload="if (typeof(startup) !== 'undefined') startup();" oncontextmenu="handleContextMenu(event)" style="display:none;min-width:495px">{{{StartGeoLocation}}}
31 + <script keeplink="1" type="text/javascript" src="scripts/ol.js"></script>
32 + <script keeplink="1" type="text/javascript" src="scripts/ol3-contextmenu.js"></script>
33 + {{{EndGeoLocation}}}
34 + <title>{{{title}}}</title>
35 +
36 +
37 + <!-- right click menu -->
38 + <div id="contextMenu" class="contextMenu noselect" style="display:none">
39 + <div id="cxinfo" class="cmtext" onclick="cmaction(1,event)"><b>Informação</b></div>
40 + <div id="cxdesktop" class="cmtext" onclick="cmaction(3,event)">Área de Trabalho</div>
41 + <div id="cxterminal" class="cmtext" onclick="cmaction(2,event)">Terminal</div>
42 + <div id="cxfiles" class="cmtext" onclick="cmaction(4,event)">Arquivos</div>
43 + <div id="cxevents" class="cmtext" onclick="cmaction(5,event)">Eventos</div>
44 + <div id="cxconsole" class="cmtext" onclick="cmaction(6,event)">Console</div>
45 + <hr id="cxmgroupsplit">
46 + <div id="cxmdesktop" class="cmtext" onclick="cmaction(7,event)" style="display:none">Multi-Desktop</div>
47 + </div>
48 + <div id="meshContextMenu" class="contextMenu noselect" style="display:none;min-width:0px">
49 + <div id="cxselectall" class="cmtext" onclick="cmmeshaction(1,event)">Selecionar tudo</div>
50 + <div id="cxselectnone" class="cmtext" onclick="cmmeshaction(2,event)">Selecione nenhum</div>
51 + <!--
52 + <hr id="cxmgroupsplit2" style="display:none" />
53 + <div id="cxmmdesktop" class="cmtext" style="display:none" onclick="cmmeshaction(3,event)">Multi-Desktop</div>
54 + -->
55 + </div>
56 + <div id="termShellContextMenu" class="contextMenu noselect" style="display:none;min-width:0px">
57 + <div id="cxtermnorm" class="cmtext" onclick="cmtermaction(1,event)"><b>Admin Shell</b></div>
58 + <div id="cxtermps" class="cmtext" onclick="cmtermaction(6,event)">Admin PowerShell</div>
59 + <div id="cxtermunorm" class="cmtext" style="display:none" onclick="cmtermaction(8,event)">User Shell</div>
60 + <div id="cxtermups" class="cmtext" style="display:none" onclick="cmtermaction(9,event)">User PowerShell</div>
61 + </div>
62 + <div id="termShellContextMenuLinux" class="contextMenu noselect" style="display:none;min-width:0px">
63 + <div id="cxtermnorm" class="cmtext" onclick="cmtermaction(1,event)"><b>Root Shell</b></div>
64 + <div id="cxtermps" class="cmtext" onclick="cmtermaction(8,event)">User Shell</div>
65 + </div>
66 + <!--
67 + <div id="pluginTabContextMenu" class="contextMenu noselect" style="display:none;min-width:0px">
68 + <div id="cxclose" class="cmtext" onclick="pluginTabClose(event)">Close Tab</div>
69 + </div>
70 + -->
71 + <!-- main page -->
72 + <div id="container">
73 + <div id="notifiyBox" class="notifiyBox" style="display:none"></div>
74 + <div id="masthead" class="noselect">
75 + <div class="title">{{{title}}}</div>
76 + <div class="title2">{{{title2}}}</div>
77 + <div style="float:right">
78 + <div id="notificationCount" onclick="clickNotificationIcon()" class="unselectable" style="display: none;" title="Clique para visualizar as notificações atuais">0</div>
79 + </div>
80 + <p id="logoutControl"><span id="logoutControlSpan" style="color:white"></span><span id="idleTimeoutNotify" style="color:yellow"></span></p>
81 + </div>
82 + <div id="page_leftbar">
83 + <div style="height:16px"></div>
84 + <div id="LeftMenuMyDevices" tabindex="0" class="lbbutton lbbuttonsel" title="Meus dispositivos" onclick="go(1,event)" onkeypress="if (event.key=='Enter') { go(1); }">
85 + <div class="lb2"></div>
86 + </div>
87 + <div id="LeftMenuMyAccount" tabindex="0" class="lbbutton" title="Minha conta" onclick="go(2,event)" onkeypress="if (event.key=='Enter') { go(2); }">
88 + <div class="lb1"></div>
89 + </div>
90 + <div id="LeftMenuMyEvents" tabindex="0" class="lbbutton" title="Meus Eventos" onclick="go(3,event)" onkeypress="if (event.key=='Enter') { go(3); }">
91 + <div class="lb3"></div>
92 + </div>
93 + <div id="LeftMenuMyFiles" tabindex="0" class="lbbutton" style="display:none" title="Meus arquivos" onclick="go(5,event)" onkeypress="if (event.key=='Enter') { go(5); }">
94 + <div class="lb4"></div>
95 + </div>
96 + <div id="LeftMenuMyUsers" tabindex="0" class="lbbutton" style="display:none" title="Meus usuários" onclick="go(4,event)" onkeypress="if (event.key=='Enter') { go(4); }">
97 + <div class="lb5"></div>
98 + </div>
99 + <div id="LeftMenuMyServer" tabindex="0" class="lbbutton" style="display:none" title="Meu servidor" onclick="go(6,event)" onkeypress="if (event.key=='Enter') { go(6); }">
100 + <div class="lb6"></div>
101 + </div>
102 + </div>
103 + <div id="topbar" class="noselect">
104 + <div>
105 + <div style="position:relative">
106 + <div tabindex="0" id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()" onkeypress="if (event.key == 'Enter') showUserInterfaceSelectMenu()">
107 + ♦
108 + <div id="uiMenu" style="display:none">
109 + <div tabindex="0" id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(1)"><div class="uiSelector1"></div></div>
110 + <div tabindex="0" id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(2)"><div class="uiSelector2"></div></div>
111 + <div tabindex="0" id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(3)"><div class="uiSelector3"></div></div>
112 + <div tabindex="0" id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno" onkeypress="if (event.key == 'Enter') toggleNightMode()"><div class="uiSelector4"></div></div>
113 + </div>
114 + </div>
115 + <table id="MainMenuSpan" cellpadding="0" cellspacing="0" class="style1">
116 + <tbody><tr>
117 + <td tabindex="0" id="MainMenuMyDevices" class="topbar_td style3x" onclick="go(1,event)" onkeypress="if (event.key == 'Enter') go(1)">Meus dispositivos</td>
118 + <td tabindex="0" id="MainMenuMyAccount" class="topbar_td style3x" onclick="go(2,event)" onkeypress="if (event.key == 'Enter') go(2)">Minha conta</td>
119 + <td tabindex="0" id="MainMenuMyEvents" class="topbar_td style3x" onclick="go(3,event)" onkeypress="if (event.key == 'Enter') go(3)">Meus Eventos</td>
120 + <td tabindex="0" id="MainMenuMyFiles" class="topbar_td style3x" onclick="go(5,event)" onkeypress="if (event.key == 'Enter') go(5)">Meus arquivos</td>
121 + <td tabindex="0" id="MainMenuMyUsers" class="topbar_td style3x" onclick="go(4,event)" onkeypress="if (event.key == 'Enter') go(4)">Meus usuários</td>
122 + <td tabindex="0" id="MainMenuMyServer" class="topbar_td style3x" onclick="go(6,event)" onkeypress="if (event.key == 'Enter') go(6)">Meu servidor</td>
123 + <td class="topbar_td_end style3">&nbsp;</td>
124 + </tr>
125 + </tbody></table>
126 + <div id="MainSubMenuSpan" style="display:none">
127 + <table id="MainSubMenu" cellpadding="0" cellspacing="0" class="style1">
128 + <tbody><tr>
129 + <td tabindex="0" id="MainDev" class="topbar_td style3x" onclick="go(10,event)" onkeypress="if (event.key == 'Enter') go(10)">Geral</td>
130 + <td tabindex="0" id="MainDevDesktop" class="topbar_td style3x" onclick="go(11,event)" onkeypress="if (event.key == 'Enter') go(11)">Área de Trabalho</td>
131 + <td tabindex="0" id="MainDevTerminal" class="topbar_td style3x" onclick="go(12,event)" onkeypress="if (event.key == 'Enter') go(12)">Terminal</td>
132 + <td tabindex="0" id="MainDevFiles" class="topbar_td style3x" onclick="go(13,event)" onkeypress="if (event.key == 'Enter') go(13)">Arquivos</td>
133 + <td tabindex="0" id="MainDevEvents" class="topbar_td style3x" onclick="go(16,event)" onkeypress="if (event.key == 'Enter') go(16)">Eventos</td>
134 + <td tabindex="0" id="MainDevInfo" class="topbar_td style3x" onclick="go(17,event)" onkeypress="if (event.key == 'Enter') go(17)">Detalhes</td>
135 + <td tabindex="0" id="MainDevAmt" class="topbar_td style3x" onclick="go(14,event)" onkeypress="if (event.key == 'Enter') go(14)">Intel® AMT</td>
136 + <td tabindex="0" id="MainDevConsole" class="topbar_td style3x" onclick="go(15,event)" onkeypress="if (event.key == 'Enter') go(15)">Console</td>
137 + <td tabindex="0" id="MainDevPlugins" class="topbar_td style3x" onclick="go(19,event)" onkeypress="if (event.key == 'Enter') go(19)">Plugins</td>
138 + <td class="topbar_td_end style3">&nbsp;</td>
139 + </tr>
140 + </tbody></table>
141 + </div>
142 + <div id="MeshSubMenuSpan" style="display:none">
143 + <table id="MeshSubMenu" cellpadding="0" cellspacing="0" class="style1">
144 + <tbody><tr>
145 + <td tabindex="0" id="MeshGeneral" class="topbar_td style3x" onclick="go(20,event)" onkeypress="if (event.key == 'Enter') go(20)">Geral</td>
146 + <td class="topbar_td_end style3">&nbsp;</td>
147 + </tr>
148 + </tbody></table>
149 + </div>
150 + <div id="UserSubMenuSpan" style="display:none">
151 + <table id="UserSubMenu" cellpadding="0" cellspacing="0" class="style1">
152 + <tbody><tr>
153 + <td tabindex="0" id="UserGeneral" class="topbar_td style3x" onclick="go(30,event)" onkeypress="if (event.key == 'Enter') go(30)">Geral</td>
154 + <td tabindex="0" id="UserEvents" class="topbar_td style3x" onclick="go(31,event)" onkeypress="if (event.key == 'Enter') go(31)">Eventos</td>
155 + <td class="topbar_td_end style3">&nbsp;</td>
156 + </tr>
157 + </tbody></table>
158 + </div>
159 + <div id="ServerSubMenuSpan" style="display:none">
160 + <table id="ServerSubMenu" cellpadding="0" cellspacing="0" class="style1">
161 + <tbody><tr>
162 + <td tabindex="0" id="ServerGeneral" class="topbar_td style3x" onclick="go(6,event)" onkeypress="if (event.key == 'Enter') go(6)">Geral</td>
163 + <td tabindex="0" id="ServerStats" class="topbar_td style3x" onclick="go(40,event)" onkeypress="if (event.key == 'Enter') go(40)">Estatísticas</td>
164 + <td tabindex="0" id="ServerConsole" class="topbar_td style3x" onclick="go(115,event)" onkeypress="if (event.key == 'Enter') go(115)">Console</td>
165 + <td tabindex="0" id="ServerTrace" class="topbar_td style3x" onclick="go(41,event)" onkeypress="if (event.key == 'Enter') go(41)">Vestígio</td>
166 + <td tabindex="0" id="ServerPlugins" class="topbar_td style3x" onclick="go(42,event)" onkeypress="if (event.key == 'Enter') go(42)">Plugins</td>
167 + <td class="topbar_td_end style3">&nbsp;</td>
168 + </tr>
169 + </tbody></table>
170 + </div>
171 + <div id="UserDummyMenuSpan">
172 + <table id="UserDummyMenu" cellpadding="0" cellspacing="0" class="style1">
173 + <tbody><tr><td class="style3" style="">&nbsp;</td></tr>
174 + </tbody></table>
175 + </div>
176 + </div>
177 + </div>
178 + </div>
179 + <div id="column_l">
180 + <div id="p0" style="display:none">
181 + <div id="p0message"><span id="p0span">Servidor desconectado</span>, <href onclick="reload()" style="cursor:pointer"><u>clique para reconectar</u></href>.</div>
182 + </div>
183 + <div id="p1" style="display:none">
184 + <div style="display:none" id="devListToolbarViewIcons">
185 + <div tabindex="0" id="devViewButton1" class="viewSelector" onclick="onDeviceViewChange(1)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(1); }" title="Colunas"><div class="viewSelector2"></div></div>
186 + <div tabindex="0" id="devViewButton2" class="viewSelector" onclick="onDeviceViewChange(2)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(2); }" title="Lista"><div class="viewSelector1"></div></div>
187 + <div tabindex="0" id="devViewButton3" class="viewSelector" onclick="onDeviceViewChange(3)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(3); }" title="Áreas de trabalho"><div class="viewSelector3"></div></div>
188 + <div tabindex="0" id="devViewButton4" class="viewSelector" onclick="onDeviceViewChange(4)" onkeypress="if (event.key == 'Enter') { onDeviceViewChange(4); }" title="Mapa" style="display:none"><div class="viewSelector4"></div></div>
189 + </div><div><h1>Meus dispositivos</h1></div>
190 + <table id="devListToolbarSpan" class="noselect">
191 + <tbody><tr>
192 + <td class="h1"></td>
193 + <td id="devListToolbar" class="style14" style="display:none">
194 + &nbsp;&nbsp;<input type="button" id="SelectAllButton" onclick="selectallButtonFunction();" value="Selecionar tudo">&nbsp;
195 + <input type="button" id="GroupActionButton" disabled="disabled" value="Ações do grupo" onclick="groupActionFunction()">&nbsp;
196 + <input id="SearchInput" type="text" placeholder="Filtro" onchange="masterUpdate(5)" onkeyup="masterUpdate(5)" autocomplete="off" onfocus="onSearchFocus(1)" onblur="onSearchFocus(0)">&nbsp;
197 + <label><input type="checkbox" id="RealNameCheckBox" onclick="onRealNameCheckBox()"><span title="Mostrar o nome do sistema operacional dos dispositivos">Nome do SO</span></label>
198 + </td>
199 + <td id="kvmListToolbar" class="style14" style="display:none">
200 + &nbsp;&nbsp;<input type="button" onclick="connectAllKvmFunction()" value="Conectar todos">&nbsp;
201 + <input type="button" onclick="disconnectAllKvmFunction()" value="Desconectar todos">&nbsp;
202 + <label><input type="checkbox" id="autoConnectDesktopCheckbox" onclick="autoConnectDesktops(event)" title="Conexão automática">Auto&nbsp;</label>
203 + <input type="button" onclick="showMultiDesktopSettings()" value="Configurações">&nbsp;
204 + </td>
205 + <td id="devMapToolbar" class="style14" style="display:none">
206 + &nbsp;&nbsp;<input type="text" id="mapSearchLocation" placeholder="Pesquisar Localização" onfocus="onMapSearchFocus(1)" onblur="onMapSearchFocus(0)">
207 + <input type="button" value="Procurar" title="Pesquisar localização" onclick="getSearchLocation()">
208 + <input type="button" id="refreshmap" title="Redefinir visualização de mapa" value="Redefinir" onclick="refreshMap(false,true)">
209 + </td>
210 + <td class="auto-style1" style="height:100%">
211 + <div style="display:none" id="devListToolbarView">
212 + Visualizar
213 + <select id="viewselect" onchange="onDeviceViewChange()">
214 + <option value="1">Colunas</option>
215 + <option value="2">Lista</option>
216 + <option value="3">Áreas de trabalho</option>
217 + <option id="viewselectmapoption" value="4" style="display:none">Mapa</option>
218 + </select>
219 + </div>
220 + <div style="display:none" id="devListToolbarSort">
221 + Classificar
222 + <select id="sortselect" onchange="masterUpdate(6)">
223 + <option>Grupo</option>
224 + <option>Ligar</option>
225 + <option>Dispositivo</option>
226 + <option>Tags</option>
227 + </select>
228 + &nbsp;
229 + </div>
230 + <div style="display:none" id="devListToolbarSize">
231 + Tamanho
232 + <select id="sizeselect" onchange="onDeviceViewChange()">
233 + <option value="0">Pequeno</option>
234 + <option value="1">Médio</option>
235 + <option value="2">ampla</option>
236 + </select>
237 + &nbsp;
238 + </div>
239 + </td>
240 + <td class="h2"></td>
241 + </tr>
242 + </tbody></table>
243 + <div id="NoMeshesPanel" style="display:none">
244 + <table>
245 + <tbody><tr>
246 + <td valign="top" style="width: 50px">
247 + <img src="images/info.png">
248 + </td>
249 + <td>
250 + <div id="getStarted1">Para começar, <a href="#" onclick="return account_createMesh()"><strong>clique aqui para criar um grupo de dispositivos</strong></a>.</div>
251 + <div id="getStarted2">Nenhum grupo de dispositivos.</div>
252 + </td>
253 + </tr>
254 + </tbody></table>
255 + </div>
256 + <div id="xdevices" class="noselect" style="display:none"></div>
257 + <div id="xdevicesmap" style="display:none">
258 + <div id="xmapSearchResultsDlg" style="display:none">
259 + <div id="xmapSearchResultsBck">
260 + <div id="xmapSearchClose" onclick="mapCloseSearchWindow()"><b>X</b></div>
261 + <div style="padding:5px">Resultados da Localização</div>
262 + <div style="width:100%;margin:6px"></div>
263 + </div>
264 + <div id="xmapSearchResults" style="margin:6px"></div>
265 + </div>
266 + </div>
267 + <div id="xmap-info-window"></div>
268 + </div>
269 + <div id="p2" style="display:none">
270 + <h1>Minha conta</h1>
271 + <img id="p2AccountImage" alt="" src="images/clipboard-128.png">
272 + <div id="p2AccountSecurity" style="display:none">
273 + <p><strong>Segurança da conta</strong></p>
274 + <div style="margin-left:25px">
275 + <div id="manageAuthApp"><div class="p2AccountActions"><span id="authAppSetupCheck"><strong>✓</strong></span></div><span><a href="#" onclick="return account_manageAuthApp()">Gerenciar aplicativo autenticador</a><br></span></div>
276 + <div id="manageHardwareOtp"><div class="p2AccountActions"><span id="authKeySetupCheck"><strong>✓</strong></span></div><span><a href="#" onclick="return account_manageHardwareOtp(0)">Gerenciar chaves de segurança</a><br></span></div>
277 + <div id="manageOtp"><div class="p2AccountActions"><span id="authCodesSetupCheck"><strong>✓</strong></span></div><span><a href="#" onclick="return account_manageOtp(0)">Gerenciar códigos de backup</a><br></span></div>
278 + </div>
279 + </div>
280 + <div id="p2AccountActions">
281 + <p><strong>Ações da conta</strong></p>
282 + <p class="mL">
283 + <span id="verifyEmailId" style="display:none"><a href="#" onclick="return account_showVerifyEmail()">Verificar email</a><br></span>
284 + <span id="accountEnableNotificationsSpan" style="display:none"><a href="#" onclick="return account_enableNotifications()">Ativar notificações da web</a><br></span>
285 + <a href="#" onclick="return account_showLocalizationSettings()">Configurações de localização</a><br>
286 + <a href="#" onclick="return account_showAccountNotifySettings()">Configurações de notificação</a><br>
287 + <span id="accountChangeEmailAddressSpan" style="display:none"><a href="#" onclick="return account_showChangeEmail()">Mude o endereço de email</a><br></span>
288 + <a href="#" onclick="return account_showChangePassword()">Mudar senha</a><span id="p2nextPasswordUpdateTime"></span><br>
289 + <a href="#" onclick="return account_showDeleteAccount()">Deletar conta</a><br>
290 + </p>
291 + <br style="clear:both">
292 + </div>
293 + <strong>Grupos de dispositivos</strong>
294 + <span id="p2createMeshLink1">( <a href="#" onclick="return account_createMesh()" class="newMeshBtn"> Novo</a> )</span>
295 + <br><br>
296 + <div id="p2meshes"></div>
297 + <div id="p2noMeshFound" style="display:none">Nenhum grupo de dispositivos.<span id="p2createMeshLink2"> <a href="#" onclick="return account_createMesh()"><strong>Comece aqui!</strong></a></span></div>
298 + <br style="clear:both">
299 + </div>
300 + <div id="p3" style="display:none">
301 + <h1>Meus Eventos</h1>
302 + <table class="pTable">
303 + <tbody><tr>
304 + <td class="h1"></td>
305 + <td class="auto-style1">
306 + Mostrar
307 + <select id="p3limitdropdown" onchange="refreshEvents()">
308 + <option value="60">Últimos 60</option>
309 + <option value="120">Últimos 120</option>
310 + <option value="250">Últimos 250</option>
311 + <option value="500">Últimos 500</option>
312 + <option value="1000">Últimos 1000</option>
313 + </select>&nbsp;
314 + <a href="#" onclick="p3showDownloadEventsDialog(2)"><img src="images/link4.png" height="10" width="10" title="Download de Eventos" style="cursor:pointer"></a>&nbsp;
315 + </td>
316 + <td class="h2"></td>
317 + </tr>
318 + </tbody></table>
319 + <div id="p3events" style=""></div>
320 + </div>
321 + <div id="p4" style="display:none">
322 + <h1>Meus usuários</h1>
323 + <table class="pTable">
324 + <tbody><tr>
325 + <td class="h1"></td>
326 + <td class="style14">
327 + <div style="float:right">
328 + <input type="button" onclick="showUserBroadcastDialog()" style="margin-right:6px" value="Broadcast">
329 + <a href="#" onclick="p4downloadUserInfo()"><img style="cursor:pointer" title="Baixar informações do usuário" src="images/link4.png"></a>
330 + <a href="#" onclick="p4batchAccountCreate()"><img id="p4UserBatchCreate" style="cursor:pointer;display:none" title="Lote criar muitas contas de usuário" src="images/link6.png"></a>
331 + </div>
332 + <div>
333 + <input id="UserNewAccountButton" type="button" style="margin-left:6px" onclick="showCreateNewAccountDialog()" value="Nova conta...">
334 + <input id="UserSearchInput" type="text" style="width:120px;margin-left:6px" placeholder="Filtro" onchange="onUserSearchInputChanged()" onkeyup="onUserSearchInputChanged()" autocomplete="off" onfocus="onUserSearchFocus(1)" onblur="onUserSearchFocus(0)">
335 + </div>
336 + </td>
337 + <td class="h2"></td>
338 + </tr>
339 + </tbody></table>
340 + <div id="p3users"></div>
341 + </div>
342 + <div id="p5" style="display:none">
343 + <h1>Meus arquivos</h1>
344 + <table id="p5toolbar" cellpadding="0" cellspacing="0">
345 + <tbody><tr>
346 + <td id="p5filehead" valign="bottom">
347 + <div id="p5rightOfButtons"></div>
348 + <div>
349 + <input type="button" id="p5FolderUp" disabled="disabled" onclick="return p5folderup();" value="Acima">&nbsp;
350 + <input type="button" id="p5SelectAllButton" disabled="disabled" onclick="p5selectallfile();" value="Selecionar tudo">&nbsp;
351 + <input type="button" id="p5RenameFileButton" disabled="disabled" value="Renomear" onclick="p5renamefile();">&nbsp;
352 + <input type="button" id="p5DeleteFileButton" disabled="disabled" value="Deletar" onclick="p5deletefile();">&nbsp;
353 + <!--<input type=button id=p5ViewFileButton disabled="disabled" value="View" onclick="p5viewfile()" />&nbsp;-->
354 + <input type="button" id="p5NewFolderButton" disabled="disabled" value="Nova pasta" onclick="p5createfolder();">&nbsp;
355 + <input type="button" id="p5UploadButton" disabled="disabled" value="Envio" onclick="p5uploadFile()">&nbsp;
356 + <input type="button" id="p5CutButton" disabled="disabled" value="Cortar" onclick="p5copyFile(1)">&nbsp;
357 + <input type="button" id="p5CopyButton" disabled="disabled" value="Copiar" onclick="p5copyFile(0)">&nbsp;
358 + <input type="button" id="p5PasteButton" disabled="disabled" value="Colar" onclick="p5pasteFile()">&nbsp;
359 + </div>
360 + </td>
361 + </tr>
362 + <tr>
363 + <td id="p5filesubhead">
364 + <div style="float:right">
365 + <select id="p5sortdropdown" onchange="updateFiles()">
366 + <option value="1" selected="selected">Classificar por nome</option>
367 + <option value="2">Classificar por tamanho</option>
368 + <option value="3">Classificar por data</option>
369 + <option value="4">Decrescente por nome</option>
370 + <option value="5">Decrescente por tamanho</option>
371 + <option value="6">Descrescente por data</option>
372 + </select>
373 + </div>
374 + <div>&nbsp;&nbsp;<span id="p5currentpath"></span></div>
375 + </td>
376 + </tr>
377 + </tbody></table>
378 + <div id="p5filetable">
379 + <!--
380 + <form id=p5fileCatchAll method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame>
381 + <input type=file id=p5fileCatchAllInput name=files style="position:absolute;left:0;width:100%;top:0;bottom:0;opacity:0;display:none" onchange="p5fileCatchAllInputChanged(event)" />
382 + <input id=p5fileDragLink2 name="link" style="display:none" />
383 + <input type=submit id=p5fileCatchAllSubmit style="display:none" />
384 + </form>
385 + -->
386 + <div id="p5PublicShare" style=""><div>Esses arquivos são compartilhados publicamente, clique em "link" para obter o URL público.</div></div>
387 + <div id="bigok" style="display:none"><b>✓</b></div>
388 + <div id="bigfail" style="display:none"><b>✗</b></div>
389 + <span id="p5files"></span>
390 + </div>
391 + <table id="p5toolbarBottom" style="width:100%" cellpadding="0" cellspacing="0">
392 + <tbody><tr><td class="style6">&nbsp;<span id="p5bottomstatus"></span></td></tr>
393 + </tbody></table>
394 + </div>
395 + <div id="p6" style="display:none">
396 + <img id="MainMeshImage" src="serverpic.ashx">
397 + <h1>Meu servidor</h1>
398 + <div id="p2ServerActions">
399 + <p><strong>Ações do servidor</strong></p>
400 + <div class="mL">
401 + <div id="p2ServerActionsBackup"><a href="{{{domainurl}}}backup.zip" rel="noreferrer noopener" target="_blank">Fazer o download do backup do servidor</a></div>
402 + <div id="p2ServerActionsRestore"><a href="#" onclick="return server_showRestoreDlg()">Restaurar servidor com backup</a></div>
403 + <div id="p2ServerActionsVersion"><a href="#" onclick="return server_showVersionDlg()">Verifique a versão do servidor</a></div>
404 + <div id="p2ServerActionsErrors"><a href="#" onclick="return server_showErrorsDlg()">Mostrar log de erros do servidor</a></div>
405 + </div>
406 + </div>
407 + <br><strong>Estatísticas do servidor</strong><br><br>
408 + <div id="serverStats">
409 + <div id="serverCpuChartView" style="display:none">
410 + <div class="chartViewCanvas"><canvas id="serverCpuChart"></canvas></div>
411 + <div class="chartViewText" id="serverCpuChartText"></div>
412 + </div>
413 + <div id="serverMemoryChartView" style="display:none">
414 + <div class="chartViewCanvas"><canvas id="serverMemoryChart"></canvas></div>
415 + <div class="chartViewText" id="serverMemoryChartText"></div>
416 + </div><br><br>
417 + <div id="serverStatsTable"></div>
418 + </div>
419 + <div id="serverWarningsDiv" style="display:none">
420 + <br><strong>Server Warnings</strong><br><br>
421 + <div id="serverWarnings"></div>
422 + </div>
423 + </div>
424 + <div id="p10" style="display:none">
425 + <table style="width:100%" cellpadding="0" cellspacing="0">
426 + <tbody><tr>
427 + <td style="width:auto" valign="top">
428 + <div id="p10title">
429 + <div id="p10BackButton"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
430 + <h1>Geral - <span id="p10deviceName"></span></h1>
431 + </div>
432 + <div id="p10html"></div>
433 + </td>
434 + <td style="width:20px"></td>
435 + <td style="width:200px">
436 + <a href="#" onclick="p10showiconselector()"><img id="MainComputerImage"></a>
437 + <div id="MainComputerState"></div>
438 + </td>
439 + </tr>
440 + </tbody></table><br>
441 + <div id="p10html2"></div>
442 + <div id="p10html3"></div>
443 + </div>
444 + <div id="p11" class="noselect" style="display:none">
445 + <div id="p11title">
446 + <div id="p11deviceNameHeader">
447 + <div id="p11BackButton"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
448 + <div id="devListToolbarViewIcons"><div class="viewSelector" onclick="deskToggleFull(event)" title="Tela cheia. Mantenha a tecla Shift pressionada no navegador em tela cheia."><div class="viewSelector5"></div></div></div>
449 + <h1>Área de Trabalho - <span id="p11deviceName"></span></h1>
450 + </div>
451 + </div>
452 + <div id="p11warning" onclick="showFeaturesDlg()">
453 + <div class="icon2"></div>
454 + <div class="warningbox">Intel® Porta de redirecionamento AMT ou recurso KVM desativado<span id="p11warninga">, clique aqui para habilitá-lo.</span></div>
455 + </div>
456 + <div id="p11warning2" onclick="showPowerActionDlg()">
457 + <div class="icon2"></div>
458 + <div class="warningbox">O computador remoto não está ligado, clique aqui para emitir um comando de energia.</div>
459 + </div>
460 + <div id="deskarea0" cellpadding="0" cellspacing="0">
461 + <div id="deskarea1" class="areaHead">
462 + <div class="toright2">
463 + <span id="p11power"></span>&nbsp;
464 + <div class="deskareaicon" title="Alternar modo de exibição" onclick="toggleAspectRatio(1)">⇲</div>
465 + <div class="deskareaicon" title="Vire à esquerda" onclick="drotate(-1)">↺</div>
466 + <div class="deskareaicon" title="Vire à direita" onclick="drotate(1)">↻</div>
467 + <div id="deskRecordIcon" class="deskareaicon" title="O servidor está gravando esta sessão" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px"></div>
468 + <input id="deskFocusBtn" type="button" title="Alternar modo de foco, quando ativo, apenas a região ao redor do mouse é atualizada" onkeypress="return false" onkeydown="return false" value="Focus All" onclick="deskToggleFocus()" style="margin-right:3px;display:none">
469 + <input id="deskSaveBtn" type="button" title="Salvar uma captura de tela da área de trabalho remota" onkeypress="return false" onkeydown="return false" value="Salvar..." onclick="deskSaveImage()" class="mR">
470 + <input id="deskActionsBtn" type="button" title="Execute ações de energia no dispositivo" onkeypress="return false" onkeydown="return false" value="Ações" onclick="deviceActionFunction()" class="mR">
471 + <input id="deskActionsSettings" type="button" value="Configurações..." title="Editar configurações da área de trabalho remota" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" class="mR">
472 + <input type="button" title="Alterar o estado de energia da máquina remota" onkeypress="return false" onkeydown="return false" value="Ações de energia (Ligar/Desligar)" onclick="showPowerActionDlg()" style="display:none">
473 + </div>
474 + <div>
475 + <div id="idx_deskFullBtn2" onclick="deskToggleFull(event)">&nbsp;✖</div>
476 + <input type="button" id="autoconnectbutton1" value="Conexão automática" onclick="autoConnectDesktop(event)" onkeypress="return false" onkeydown="return false" style="display:none">
477 + <span id="connectbutton1span"><input type="button" id="connectbutton1" value="Conectar" onclick="connectDesktop(event,1)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
478 + <span id="connectbutton1hspan">&nbsp;<input type="button" id="connectbutton1h" value="Conectar HW" title="Connect using Intel AMT hardware KVM" onclick="connectDesktop(event,2)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
479 + <span id="disconnectbutton1span">&nbsp;<input type="button" id="disconnectbutton1" value="Desconectar" onclick="connectDesktop(event,0)" onkeypress="return false" onkeydown="return false"></span>
480 + &nbsp;<span id="deskstatus">Desconectado</span>
481 + </div>
482 + </div>
483 + <div id="deskarea2" style="">
484 + <div class="areaProgress"><div id="progressbar" style=""></div></div>
485 + </div>
486 + <div id="deskarea3x">
487 + <div id="DeskFocus" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)"></div>
488 + <div id="DeskParent">
489 + <canvas id="Desk" width="640" height="480" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)" onmousewheel="dmousewheel(event)"></canvas>
490 + </div>
491 + <div id="DeskTools">
492 + <div id="deskToolsAreaTop">
493 + <a id="DeskToolsRefreshButton" style="right:2px" onclick="refreshDeskTools()">Atualizar</a>
494 + <div id="deskToolsTopTabProcess" class="deskToolsTopTab" onclick="changeDeskToolTab(0)" style="left:0px;bottom:0px">Processos</div>
495 + <div id="deskToolsTopTabService" class="deskToolsTopTab" onclick="changeDeskToolTab(1)" style="display:none;left:90px;color:gray">Serviços</div>
496 + </div>
497 + <div id="deskToolsArea">
498 + <div id="DeskToolsProcessTab">
499 + <div id="deskToolsHeader">
500 + <a class="colmn1" title="Classificar por ID do processo" onclick="sortProcess(0)">PID</a>
501 + <a class="colmn2" title="Classificar por nome" onclick="sortProcess(1)">Nome</a>
502 + </div>
503 + <div id="DeskToolsProcesses" style=""></div>
504 + </div>
505 + <div id="DeskToolsServiceTab" style="display:none">
506 + <div id="deskToolsServiceHeader">
507 + <a class="colmn1" style="width:70px" title="Classificar por estado" onclick="sortService(0)">Estado</a>
508 + <a class="colmn2" title="Classificar por nome" onclick="sortService(1)">Nome</a>
509 + </div>
510 + <div id="DeskToolsServices" style=""></div>
511 + </div>
512 + </div>
513 + </div>
514 + <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="p11clearConsoleMsg()"></div>
515 + </div>
516 + <div id="deskarea4" class="areaFoot">
517 + <div class="toright2">
518 + <span id="DeskTimer" title="Tempo de sessão"></span>&nbsp;
519 + <select id="termdisplays" style="display:none" onchange="deskSetDisplay(event)" onkeypress="return false" onkeydown="return false"></select>&nbsp;
520 + <input id="DeskToolsButton" type="button" value="Ferramentas" title="Alternar visualização de ferramentas" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">&nbsp;
521 + <span id="DeskChatButton" class="deskarea" title="Abra a janela de bate-papo neste computador"><img src="images/icon-chat.png" onclick="deviceChat(event)" height="16" width="16" style="padding-top:2px"></span>
522 + <span id="DeskNotifyButton" title="Exibir uma notificação no computador remoto"><img src="images/icon-notify.png" onclick="deviceToastFunction()" height="16" width="16" style="padding-top:2px"></span>
523 + <span id="DeskOpenWebButton" title="Open a web address on the remote computer"><img src="images/icon-url2.png" onclick="deviceUrlFunction()" height="16" width="16" style="padding-top:2px"></span>
524 + <span id="DeskBackgroundButton" title="Toggle remote desktop background"><img src="images/icon-background.png" onclick="deviceToggleBackground(event)" height="16" width="16" style="padding-top:2px"></span>
525 + </div>
526 + <div>
527 + <select id="deskkeys">
528 + <option value="10">CTRL+ALT+DEL</option>
529 + <option value="5">Win</option>
530 + <option value="0">Win+Down</option>
531 + <option value="1">Win+Up</option>
532 + <option value="2">Win+L</option>
533 + <option value="3">Win+M</option>
534 + <option value="4">Shift+Win+M</option>
535 + <option value="6">Win+R</option>
536 + <option value="7">Alt-F4</option>
537 + <option value="8">CTRL-W</option>
538 + <option value="9">Alt-Tab</option>
539 + <option value="11">Win+Left</option>
540 + <option value="12">Win+Right</option>
541 + </select>
542 + <input id="DeskWD" type="button" value="Enviar" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()">
543 + <input id="DeskClip" style="" type="button" value="Área de transferência" onkeypress="return false" onkeydown="return false" onclick="showDeskClip()">
544 + <input id="DeskType" style="" type="button" value="Tipo" onkeypress="return false" onkeydown="return false" onclick="showDeskType()">
545 + <label><span id="DeskControlSpan" title="Alternar entrada de mouse e teclado"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false" onclick="toggleKvmControl()">Entrada</span></label>&nbsp;
546 + </div>
547 + </div>
548 + </div>
549 + </div>
550 + <div id="p12" style="display:none">
551 + <div id="p12title">
552 + <div id="p12BackButton"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
553 + <h1>Terminal - <span id="p12deviceName"></span></h1>
554 + </div>
555 + <div id="p12warning" onclick="showFeaturesDlg()">
556 + <div class="icon2"></div>
557 + <div class="warningbox">Intel® Porta de redirecionamento AMT ou recurso KVM desativado<span id="p12warninga">, clique aqui para habilitá-lo.</span></div>
558 + </div>
559 + <div id="p12warning2" onclick="showPowerActionDlg()">
560 + <div class="icon2"></div>
561 + <div class="warningbox">O computador remoto não está ligado, clique aqui para emitir um comando de energia.</div>
562 + </div>
563 + <div id="termTable" style="position:relative">
564 + <table style="width:100%" cellpadding="0" cellspacing="0">
565 + <tbody><tr>
566 + <td class="areaHead">
567 + <div class="toright2">
568 + <div id="termRecordIcon" class="deskareaicon" title="O servidor está gravando esta sessão" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px"></div>
569 + <input id="termActionsBtn" type="button" title="Execute ações de energia no dispositivo" onkeypress="return false" onkeydown="return false" value="Ações" onclick="deviceActionFunction()">
570 + </div>
571 + <div>
572 + <input type="button" id="autoconnectbutton2" value="Conexão automática" onclick="autoConnectTerminal(event)" onkeypress="return false" onkeydown="return false" style="display:none">
573 + <span id="connectbutton2span"><input type="button" id="connectbutton2" value="Conectar" onclick="connectTerminal(event,1)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
574 + <span id="connectbutton2hspan">&nbsp;<input type="button" id="connectbutton2h" value="Conectar HW" title="Connect using Intel AMT hardware KVM" onclick="connectTerminal(event,2)" onkeypress="return false" onkeydown="return false" disabled="disabled"></span>
575 + <span id="disconnectbutton2span">&nbsp;<input type="button" id="disconnectbutton2" value="Desconectar" onclick="connectTerminal(event,0)" onkeypress="return false" onkeydown="return false"></span>
576 + &nbsp;<span id="termstatus">Desconectado</span><span id="termtitle"></span>
577 + </div>
578 + </td>
579 + </tr>
580 + <tr>
581 + <td>
582 + <div class="areaProgress"><div id="termprogressbar" style=""></div></div>
583 + </td>
584 + </tr>
585 + <tr>
586 + <td id="termarea3x">
587 + <pre id="Term"></pre>
588 + </td>
589 + </tr>
590 + <tr>
591 + <td class="areaFoot">
592 + <div class="toright2">
593 + <span id="TermTimer" title="Tempo de sessão"></span>&nbsp;
594 + <span id="terminalSettingsButtons" style="display:none">
595 + <input id="id_tcrbutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="CR + LF" title="Alterne o que a chave de retorno enviará" onclick="termToggleCr()">
596 + <input id="id_tfxkeysbutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="Intel (F10 = ESC+[OM)" title="Alterna o tipo de emulação de teclas F1 a F10" onclick="termToggleFx()">
597 + <input id="id_ttypebutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="Ascii estendido" title="Alternar tipo de emulação de terminal" onclick="termToggleType()">
598 + </span>
599 + <span id="terminalSizeDropDown">
600 + <select id="termSizeList" onkeypress="return false"><option value="1">80x25</option><option value="2">100x30</option><option value="3" selected="">Auto</option></select>
601 + </span>
602 + <select id="specialkeylist" onkeypress="return false"></select>
603 + <input id="specialkeylistinput" type="button" onkeypress="return false" class="bottombutton" value="Enviar" title="Enviar a chave especial selecionada" onclick="sendSpecialKey()">
604 + </div>
605 + <div>
606 + &nbsp;
607 + <input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="ctrlcbutton" value="CTRL-C" onclick="termSendKey(3,'ctrlcbutton')">
608 + <input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="ctrlxbutton" value="CTRL-X" onclick="termSendKey(24,'ctrlxbutton')">
609 + <input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="escbutton" value="ESC" onclick="termSendKey(27,'escbutton')">
610 + <input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="bsbutton" value="Excluir" onclick="termSendKey(8,'bsbutton')">
611 + <input type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" id="pastebutton" value="Colar" title="Cole o texto no terminal" onclick="showTermPasteDialog()">
612 + </div>
613 + </td>
614 + </tr>
615 + </tbody></table>
616 + <div id="p12TermConsoleMsg" style="display:none;cursor:pointer;position:absolute;left:30px;top:45px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick="p12clearConsoleMsg()"></div>
617 + </div>
618 + </div>
619 + <div id="p13" style="display:none">
620 + <div id="p13title">
621 + <div id="p13BackButton" style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
622 + <h1>Arquivos - <span id="p13deviceName"></span></h1>
623 + </div>
624 + <table id="p13toolbar" cellpadding="0" cellspacing="0">
625 + <tbody><tr>
626 + <td class="areaHead">
627 + <div class="toright2">
628 + <input id="filesActionsBtn" type="button" title="Execute ações de energia no dispositivo" value="Ações" onclick="deviceActionFunction()">
629 + <div id="filesRecordIcon" class="deskareaicon" title="O servidor está gravando esta sessão" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px"></div>
630 + </div>
631 + <div>
632 + <input id="p13AutoConnect" value="Conexão automática" onclick="autoConnectFiles(event)" type="button" style="display:none">
633 + <input id="p13Connect" value="Conectar" onclick="connectFiles(event)" type="button">
634 + <span id="p13Status">Desconectado</span>
635 + </div>
636 + </td>
637 + </tr>
638 + <tr>
639 + <td class="areaHead2" valign="bottom">
640 + <div id="p13rightOfButtons" class="toright2"></div>
641 + <div>
642 + <input type="button" id="p13FolderUp" disabled="disabled" onclick="p13folderup()" value="Acima">&nbsp;
643 + <input type="button" id="p13SelectAllButton" disabled="disabled" onclick="p13selectallfile()" value="Selecionar tudo">&nbsp;
644 + <input type="button" id="p13RenameFileButton" disabled="disabled" value="Renomear" onclick="p13renamefile()">&nbsp;
645 + <input type="button" id="p13DeleteFileButton" disabled="disabled" value="Deletar" onclick="p13deletefile()">&nbsp;
646 + <input type="button" id="p13ViewFileButton" disabled="disabled" value="Editar" onclick="p13viewfile()">&nbsp;
647 + <input type="button" id="p13NewFolderButton" disabled="disabled" value="Nova pasta" onclick="p13createfolder()">&nbsp;
648 + <input type="button" id="p13UploadButton" disabled="disabled" value="Envio" onclick="p13uploadFile()">&nbsp;
649 + <input type="button" id="p13CutButton" disabled="disabled" value="Cortar" onclick="p13copyFile(1)">&nbsp;
650 + <input type="button" id="p13CopyButton" disabled="disabled" value="Copiar" onclick="p13copyFile(0)">&nbsp;
651 + <input type="button" id="p13PasteButton" disabled="disabled" value="Colar" onclick="p13pasteFile()">&nbsp;
652 + <input type="button" id="p13RefreshButton" disabled="disabled" value="Atualizar" onclick="p13folderup(9999)">&nbsp;
653 + </div>
654 + </td>
655 + </tr>
656 + <tr>
657 + <td class="areaHead3">
658 + <div class="toright2">
659 + <select id="p13sortdropdown" onchange="p13updateFiles()">
660 + <option value="1" selected="selected">Classificar por nome</option>
661 + <option value="2">Classificar por tamanho</option>
662 + <option value="3">Classificar por data</option>
663 + <option value="4">Decrescente por nome</option>
664 + <option value="5">Decrescente por tamanho</option>
665 + <option value="6">Descrescente por data</option>
666 + </select>
667 + </div>
668 + <div>&nbsp;&nbsp;<span id="p13currentpath"></span></div>
669 + </td>
670 + </tr>
671 + </tbody></table>
672 + <div id="p13FilesConsoleMsg" style="display:none;cursor:pointer;position:absolute;left:30px;top:165px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick="p13clearConsoleMsg()"></div>
673 + <div id="p13filetable" style="">
674 + <div id="p13bigok" style="display:none"><b>✓</b></div>
675 + <div id="p13bigfail" style="display:none"><b>✗</b></div>
676 + <span id="p13files"></span>
677 + </div>
678 + <table id="p13toolbarBottom" cellpadding="0" cellspacing="0">
679 + <tbody><tr><td class="style6">&nbsp;<span id="p13bottomstatus"></span></td></tr>
680 + </tbody></table>
681 + </div>
682 + <div id="p14" style="display:none">
683 + <div id="p14title">
684 + <div id="p14BackButton" style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
685 + <div id="devListToolbarViewIcons"><div class="viewSelector" onclick="deskToggleFull(event)" title="Tela cheia. Mantenha a tecla Shift pressionada no navegador em tela cheia."><div class="viewSelector5"></div></div></div>
686 + <h1>Intel® AMT - <span id="p14deviceName"></span></h1>
687 + </div>
688 + <iframe id="p14iframe" src="{{{domainurl}}}commander.htm"></iframe>
689 + </div>
690 + <div id="p15" style="display:none">
691 + <div id="p15title">
692 + <div id="p15BackButton" style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
693 + <h1><span id="p15deviceName"></span></h1>
694 + </div>
695 + <table id="consoleTable" cellpadding="0" cellspacing="0">
696 + <tbody><tr>
697 + <td class="areaHead">
698 + <div class="toright2">
699 + <div id="p15coreName" title="Informações sobre o núcleo atual em execução neste agente"></div>
700 + <input type="button" id="p15uploadCore" value="Ação do agente" onclick="p15uploadCore(event)" title="Alterar o módulo de código Java Script do agente">
701 + <img onclick="p15downloadConsoleText()" style="cursor:pointer;margin-top:6px" title="Baixar do texto do console" src="images/link4.png">
702 + </div>
703 + <div id="p15statetext"></div>
704 + </td>
705 + </tr>
706 + <tr>
707 + <td>
708 + <div class="areaProgress"><div id="consoleprogressbar" style=""></div></div>
709 + </td>
710 + </tr>
711 + <tr>
712 + <td id="p15agentConsole">
713 + <pre id="p15agentConsoleText"></pre>
714 + </td>
715 + </tr>
716 + <tr>
717 + <td class="areaFoot">
718 + <table style="width:100%">
719 + <tbody><tr>
720 + <td style="width:99%">
721 + <input id="p15consoleText" style="width:100%" onkeyup="p15consoleSend(event)" onfocus="onConsoleFocus(1)" onblur="onConsoleFocus(0)">
722 + </td>
723 + <td>&nbsp;</td>
724 + <td id="p15outputselecttd">
725 + <select id="p15outputselect">
726 + <option value="1">Agente</option>
727 + <option value="2">MQTT</option>
728 + </select>
729 + </td>
730 + <td style="width:1%"><input id="id_p15consoleClear" type="button" class="bottombutton" value="Limpo" onclick="p15consoleClear()"></td>
731 + </tr>
732 + </tbody></table>
733 + </td>
734 + </tr>
735 + </tbody></table>
736 + </div>
737 + <div id="p16" style="display:none">
738 + <div id="p16title">
739 + <div id="p16BackButton" style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
740 + <h1>Eventos - <span id="p16deviceName"></span></h1>
741 + </div>
742 + <table class="pTable">
743 + <tbody><tr>
744 + <td class="h1"></td>
745 + <!--<td>&nbsp;<input type=button onclick=refreshDeviceEvents() value="Refresh" /></td>-->
746 + <td class="auto-style1">
747 + Mostrar
748 + <select id="p16limitdropdown" onchange="refreshDeviceEvents()">
749 + <option value="60">Últimos 60</option>
750 + <option value="120">Últimos 120</option>
751 + <option value="250">Últimos 250</option>
752 + <option value="500">Últimos 500</option>
753 + <option value="1000">Últimos 1000</option>
754 + </select>
755 + <a href="#" onclick="p3showDownloadEventsDialog(1)"><img src="images/link4.png" height="10" width="10" title="Download de Eventos" style="cursor:pointer"></a>&nbsp;
756 + </td>
757 + <td class="h2"></td>
758 + </tr>
759 + </tbody></table>
760 + <div id="p16events"></div>
761 + </div>
762 + <div id="p17" style="display:none">
763 + <div id="p17title">
764 + <div id="p17BackButton" style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
765 + <h1>Detalhes - <span id="p17deviceName"></span></h1>
766 + </div>
767 + <div id="p17info"></div>
768 + </div>
769 + <div id="p20" style="display:none">
770 + <picture id="MainMeshImage" style="border-width:0px;height:200px;width:200px;float:right">
771 + <source type="image/webp" width="200" height="200" srcset="images/webp/mesh-256.webp">
772 + <img alt="" width="200" height="200" src="images/mesh-256.png">
773 + </picture>
774 + <div style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
775 + <h1>Geral - <span id="p20meshName"></span></h1>
776 + <p id="p20info"></p>
777 + </div>
778 + <div id="p30" style="display:none">
779 + <table style="width:100%" cellpadding="0" cellspacing="0">
780 + <tbody><tr>
781 + <td style="width:auto" valign="top">
782 + <div id="p30title">
783 + <div style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
784 + <h1>Geral - <span id="p30userName"></span></h1>
785 + </div>
786 + <div id="p30html"></div>
787 + </td>
788 + <td style="width:20px"></td>
789 + <td style="width:200px">
790 + <picture id="MainUserImage" style="border-width:0px;height:200px;width:200px;float:right">
791 + <source type="image/webp" width="200" height="200" srcset="images/webp/user-256.webp">
792 + <img alt="" width="200" height="200" src="images/user-256.png">
793 + </picture>
794 + <div style="width:100%;text-align:center"><strong><span id="MainUserState"></span></strong></div>
795 + </td>
796 + </tr>
797 + </tbody></table><br>
798 + <div id="p30html2"></div>
799 + <div id="p30html3"></div>
800 + </div>
801 + <div id="p31" style="display:none">
802 + <div style="float:left"><div class="backButton" tabindex="0" onclick="goBack()" title="Voltar" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
803 + <h1>Eventos - <span id="p31userName"></span></h1>
804 + <table class="pTable">
805 + <tbody><tr>
806 + <td class="h1"></td>
807 + <!--<td>&nbsp;<input type=button onclick=refreshUsersEvents() value="Refresh" /></td>-->
808 + <td class="auto-style1">
809 + Mostrar
810 + <select id="p31limitdropdown" onchange="refreshUsersEvents()">
811 + <option value="60">Últimos 60</option>
812 + <option value="120">Últimos 120</option>
813 + <option value="250">Últimos 250</option>
814 + <option value="500">Últimos 500</option>
815 + <option value="1000">Últimos 1000</option>
816 + </select>
817 + <a href="#" onclick="p3showDownloadEventsDialog(3)"><img src="images/link4.png" height="10" width="10" title="Download de Eventos" style="cursor:pointer"></a>&nbsp;
818 + </td>
819 + <td class="h2"></td>
820 + </tr>
821 + </tbody></table>
822 + <div id="p31events" style=""></div>
823 + </div>
824 + <div id="p40" style="display:none">
825 + <h1>Estatísticas do meu servidor</h1>
826 + <div class="areaHead">
827 + <div class="toright2">
828 + <select id="p40type" onchange="updateServerTimelineStats()">
829 + <option value="0">Conexões</option>
830 + <option value="1">Memória</option>
831 + </select>&nbsp;
832 + <select id="p40time" onchange="updateServerTimelineHours()">
833 + <option value="3">Últimas 3 horas</option>
834 + <option value="8">Últimas 8 horas</option>
835 + <option value="24">Último dia</option>
836 + <option value="168">Semana passada</option>
837 + <option value="720">Últimos 30 dias</option>
838 + </select>&nbsp;
839 + <img src="images/link4.png" height="10" width="10" title="Baixar pontos de dados (.csv)" style="cursor:pointer" onclick="p40downloadEvents()">&nbsp;
840 + </div>
841 + <div>
842 + <input value="Atualizar" type="button" onclick="refreshServerTimelineStats()">
843 + &nbsp;<label><input id="p40log" type="checkbox" onclick="updateServerTimelineHours()">Log-X</label>
844 + </div>
845 + </div>
846 + <canvas id="serverMainStats" style=""></canvas>
847 + </div>
848 + <div id="p41" style="display:none">
849 + <h1>Rastreio do meu servidor</h1>
850 + <div class="areaHead">
851 + <div class="toright2">
852 + Mostrar
853 + <select id="p41limitdropdown" onchange="displayServerTrace()">
854 + <option value="100">Últimos 100</option>
855 + <option value="250">Últimos 250</option>
856 + <option value="500">Últimos 500</option>
857 + <option value="1000">Últimos 1000</option>
858 + </select>
859 + <input value="Limpo" type="button" onclick="clearServerTracing()">
860 + <img src="images/link4.png" height="10" width="10" title="Rastreio de download (.csv)" style="cursor:pointer" onclick="p41downloadServerTrace()">&nbsp;
861 + </div>
862 + <div>
863 + <input value="Rastreamento" type="button" onclick="setServerTracing()">
864 + <span id="p41traceStatus">Nenhum</span>
865 + </div>
866 + </div>
867 + <div id="p41events" style=""></div>
868 + </div>
869 + <div id="p42" style="display:none">
870 + <h1>My Server Plugins</h1>
871 + <div class="areaHead">
872 + <div class="toright2">
873 + </div>
874 + <div>
875 + <input value="Download Plugin" type="button" onclick="return pluginHandler.addPluginDlg();">
876 + </div>
877 + </div>
878 + <div id="pluginRestartNotice" class="areaHead" style="background-color:gold;display:none">
879 + <div class="toright2">
880 + <input value="Refresh Agent Cores" type="button" onclick="distributeCore();return false">
881 + </div>
882 + <div style="padding:2px">
883 + <div style="padding:2px"><b>Notice:</b> Plugins have been altered, this may require agent core update.</div>
884 + </div>
885 + </div>
886 + <table id="p42tbl">
887 + <tbody><tr class="DevSt"><th style="width:26px"></th><th style="width:10px"></th><th class="chName">Nome</th><th class="chDescription">Descrição</th><th class="chSite" style="text-align:center">Ligação</th><th class="chVersion" style="text-align:center">Versão</th><th class="chUpgradeAvail" style="text-align:center">Latest</th><th class="chStatus" style="text-align:center">Status</th><th class="chAction" style="text-align:center">Ação</th><th style="width:10px"></th></tr>
888 + </tbody></table>
889 + <div id="pluginNoneNotice" style="width:100%;text-align:center;padding-top:10px;display:none"><i>No plugins on server.</i></div>
890 + </div>
891 + <div id="p43" style="display:none">
892 + <div id="p43BackButton"><div class="backButton" tabindex="0" onclick="go(42)" title="Voltar" onkeypress="if (event.key == 'Enter') go(42)"><div class="backButtonEx"></div></div></div>
893 + <h1>My Server Plugins - <span id="p43title"></span></h1>
894 + <iframe id="p43iframe" frameborder="0" style="width:100%;height:calc(100vh - 245px);max-height:calc(100vh - 245px)"></iframe>
895 + </div>
896 + <div id="p19" style="display:none">
897 + <h1>Plugins - <span id="p19deviceName"></span></h1>
898 + <div id="p19headers"></div>
899 + <div id="p19pages"></div>
900 + </div>
901 + <br id="column_l_bottomgap">
902 + </div>
903 + <div id="footer">
904 + <div class="footer1">{{{footer}}}</div>
905 + <div class="footer2">
906 + <a id="verifyEmailId2" style="display:none" href="#" onclick="account_showVerifyEmail()">Verificar Email</a>
907 + &nbsp;<a href="terms">Termos &amp; Privacidade</a>
908 + </div>
909 + </div>
910 + <div id="dialog" class="noselect" style="display:none">
911 + <div id="dialogHeader">
912 + <div tabindex="0" id="id_dialogclose" onclick="setDialogMode()" onkeypress="if (event.key == 'Enter') setDialogMode()">✖</div>
913 + <div id="id_dialogtitle"></div>
914 + </div>
915 + <div id="dialogBody">
916 + <div id="dialog1">
917 + <div id="id_dialogMessage" style=""></div>
918 + </div>
919 + <div id="dialog2" style="">
920 + <div id="id_dialogOptions"></div>
921 + </div>
922 + <div id="dialog3" style="">
923 + <div id="d3upload">
924 + <div>Seleção de arquivo</div>
925 + <select id="d3uploadMode" onchange="d3modechange()">
926 + <option value="1">Upload de arquivo local</option>
927 + <option value="2">Seleção de arquivo do servidor</option>
928 + </select>
929 + </div>
930 + <div id="d3localmode" style="display:none">
931 + <div>Subir arquivo</div>
932 + <form id="d3localmodeform" method="post" enctype="multipart/form-data" action="uploadfile.ashx" target="fileUploadFrame">
933 + <input type="text" id="d3auth" name="auth" style="display:none">
934 + <input type="text" id="d3attrib" name="attrib" style="display:none">
935 + <input type="file" id="d3localFile" name="files" onchange="d3setActions()">
936 + <input type="submit" id="d3submit" style="display:none">
937 + </form>
938 + </div>
939 + <div id="d3servermode">
940 + <div id="d3serveraction" valign="bottom">
941 + <input type="button" id="p3FolderUp" disabled="disabled" onclick="d3folderup()" value="Acima">&nbsp;
942 + </div>
943 + <div id="d3serverfiles"></div>
944 + </div>
945 + </div>
946 + <div id="dialog7" style="">
947 + <div id="d7meshkvm">
948 + <h4>Área de trabalho remota do agente</h4>
949 + <div>
950 + <div>Qualidade</div>
951 + <select id="d7bitmapquality" dir="rtl"></select>
952 + </div>
953 + <div>
954 + <div>Dimensionamento</div>
955 + <select id="d7bitmapscaling" style="" dir="rtl">
956 + <option selected="selected" value="1024">100%</option>
957 + <option value="896">87.5%</option>
958 + <option value="768">75%</option>
959 + <option value="640">62.5%</option>
960 + <option value="512">50%</option>
961 + <option value="384">37..5%</option>
962 + <option value="256">25%</option>
963 + <option value="128">12.5%</option>
964 + </select>
965 + </div>
966 + <div>
967 + <div>Taxa de quadros</div>
968 + <select id="d7framelimiter" dir="rtl">
969 + <option selected="selected" value="50">Rápido</option>
970 + <option value="100">Médio</option>
971 + <option value="400">Lento</option>
972 + <option value="1000">Muito devagar</option>
973 + </select>
974 + </div>
975 + </div>
976 + <div id="d7amtkvm">
977 + <h4>Intel® AMT Hardware KVM</h4>
978 + <div>
979 + <div>Codificação de Imagem</div>
980 + <select id="d7desktopmode">
981 + <option value="1">RLE8, mais rápido</option>
982 + <option value="2">RLE16, Recomendado</option>
983 + <option value="3">RAW8, lento</option>
984 + <option value="4">RAW16, muito lento</option>
985 + </select>
986 + </div>
987 + <div>
988 + <div>Outros ajustes</div>
989 + <div id="d7otherset" style="display:block">
990 + <label style="display:block"><input type="checkbox" id="d7showfocus">Mostrar ferramenta de foco</label>
991 + <label style="display:block"><input type="checkbox" id="d7showcursor">Mostrar Cursor do Mouse Local</label>
992 + <label style="display:block"><input type="checkbox" id="d7localKeyMap">Mapa do teclado local</label>
993 + </div>
994 + </div>
995 + </div>
996 + </div>
997 + </div>
998 + <div id="idx_dlgButtonBar">
999 + <input id="idx_dlgCancelButton" type="button" value="Cancelar" style="" onclick="dialogclose(0)">
1000 + <input id="idx_dlgOkButton" type="button" value="Ok" style="" onclick="dialogclose(1)">
1001 + <div><input id="idx_dlgDeleteButton" type="button" value="Deletar" style="display:none" onclick="dialogclose(2)"></div>
1002 + </div>
1003 + </div>
1004 + <iframe name="fileUploadFrame" style="display:none"></iframe>
1005 + <form style="display:none" method="post" action="uploadfile.ashx" enctype="multipart/form-data" target="fileUploadFrame"><input id="p5fileDragName" name="name"><input id="p5fileDragAuthCookie" name="auth"><input id="p5fileDragSize" name="size"><input id="p5fileDragType" name="type"><input id="p5fileDragData" name="data"><input id="p5fileDragLink" name="link"><input type="submit" id="p5loginSubmit2" style="display:none"></form>
1006 + <form style="display:none" method="post" action="uploadnodefile.ashx" enctype="multipart/form-data" target="fileUploadFrame"><input id="p13fileDragName" name="name"><input id="p13fileDragSize" name="size"><input id="p13fileDragType" name="type"><input id="p13fileDragData" name="data"><input id="p13fileDragLink" name="link"><input type="submit" id="p13loginSubmit2" style="display:none"></form>
1007 + <audio id="chimes"><source src="sounds/chimes.mp3" type="audio/mp3"></audio>
1008 + </div>
1009 + <script type="text/javascript">
1010 + 'use strict';
1011 +
1012 + // Process server-side web state
1013 + var webState = '{{{webstate}}}';
1014 + if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
1015 + for (var i in webState) { localStorage.setItem(i, webState[i]); }
1016 + if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
1017 +
1018 + var args;
1019 + var autoReconnect = true;
1020 + var powerStatetable = ['', "Ligado", "Hibernar", "Hibernar", "Hibernar", "Hibernando", "Desligar", "Presente"];
1021 + var StatusStrs = ["Desconectado", "Conectando...", "Configurando...", "Conectado", "Intel&reg; AMT conectado"];
1022 + var sort = 0;
1023 + var searchFocus = 0;
1024 + var mapSearchFocus = 0;
1025 + var userSearchFocus = 0;
1026 + var consoleFocus = 0;
1027 + var showRealNames = false;
1028 + var meshserver = null;
1029 + var meshes = {};
1030 + var meshcount = 0;
1031 + var nodes = null;
1032 + var filetree = {};
1033 + var userinfo = null;
1034 + var serverinfo = null;
1035 + var events = [];
1036 + var users = null;
1037 + var wssessions = null;
1038 + var nodeShortIdent = 0;
1039 + var desktop;
1040 + var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50, localkeymap: false };
1041 + var multidesktopsettings = { quality: 20, scaling: 128, framerate: 1000 };
1042 + var terminal;
1043 + var files;
1044 + var debugLevel = parseInt('{{{debuglevel}}}');
1045 + var features = parseInt('{{{features}}}');
1046 + var sessionTime = parseInt('{{{sessiontime}}}');
1047 + var domain = '{{{domain}}}';
1048 + var domainUrl = '{{{domainurl}}}';
1049 + var authCookie = '{{{authCookie}}}';
1050 + var authRelayCookie = '{{{authRelayCookie}}}';
1051 + var logoutControls = {{{logoutControls}}};
1052 + var authCookieRenewTimer = null;
1053 + var multiDesktop = {};
1054 + var multiDesktopFilter = null;
1055 + var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
1056 + var amtScanResults = null;
1057 + var debugmode = 0;
1058 + var clickOnce = (((features & 256) != 0) && detectClickOnce());
1059 + var attemptWebRTC = ((features & 128) != 0);
1060 + var passRequirements = '{{{passRequirements}}}';
1061 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
1062 + var deskAspectRatio = 0;
1063 + try { deskAspectRatio = parseInt(getstore('deskAspectRatio', '0')); } catch (ex) { }
1064 + var uiMode = parseInt(getstore('uiMode', 1));
1065 + var webPageStackMenu = false;
1066 + var webPageFullScreen = true;
1067 + var nightMode = (getstore('_nightMode', '0') == '1');
1068 + var sessionActivity = Date.now();
1069 + var updateSessionTimer = null;
1070 + var pluginHandlerBuilder = {{{pluginHandler}}};
1071 + var pluginHandler = null;
1072 + if (pluginHandlerBuilder != null) { pluginHandler = new pluginHandlerBuilder(); }
1073 + var installedPluginList = null;
1074 +
1075 + // Console Message Display Timers
1076 + var p11DeskConsoleMsgTimer = null;
1077 + var p12TermConsoleMsgTimer = null;
1078 + var p13FilesConsoleMsgTimer = null;
1079 +
1080 + function startup() {
1081 + if ((features & 32) == 0) {
1082 + // Guard against other site's top frames (web bugs).
1083 + var loc = null;
1084 + try { loc = top.location.toString().toLowerCase(); } catch (e) { }
1085 + if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
1086 + }
1087 +
1088 + // Setup logout control
1089 + var logoutControl = '';
1090 + if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); }
1091 + if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Sair" + '</a>'); }
1092 + QH('logoutControlSpan', logoutControl);
1093 +
1094 + // Check if we are in debug mode
1095 + args = parseUriArgs();
1096 + if (!args.locale) { var x = getstore('loctag', 0); if ((x != null) && (x != '*')) { args.locale = x; } }
1097 + debugmode = args.debug;
1098 + if (args.webrtc != null) { attemptWebRTC = (args.webrtc == 1); }
1099 + QV('p13AutoConnect', debugmode); // Files
1100 + QV('autoconnectbutton2', debugmode); // Terminal
1101 + QV('autoconnectbutton1', debugmode); // Desktop
1102 + //QV('DeskClip', debugmode); // Clipboard feature, not completed so show in in debug mode only.
1103 +
1104 + if (nightMode) { QC('body').add('night'); }
1105 + toggleFullScreen();
1106 +
1107 + // Debug
1108 + QV('cxtermunorm', debugmode == 1);
1109 + QV('cxtermups', debugmode == 1);
1110 +
1111 + // Setup page visuals
1112 + if (args.hide) {
1113 + var hide = parseInt(args.hide);
1114 + QV('masthead', !(hide & 1));
1115 + QV('topbar', !(hide & 2));
1116 + QV('footer', !(hide & 4));
1117 + QV('p10title', !(hide & 8));
1118 + QV('p11title', !(hide & 8));
1119 + QV('p12title', !(hide & 8));
1120 + QV('p13title', !(hide & 8));
1121 + QV('p14title', !(hide & 8));
1122 + QV('p15title', !(hide & 8));
1123 + QV('p16title', !(hide & 8));
1124 + //if (hide & 16) {
1125 + // QV('page_leftbar', false);
1126 + // QS('page_content').left = '0px';
1127 + //}
1128 +
1129 + // Fix the main grid to zero-height elements we want to hide.
1130 + QS('container')['grid-template-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
1131 + QS('container')['-ms-grid-rows'] = ((hide & 1) ? '0' : '66') + 'px ' + ((hide & 2) ? '0' : '24') + 'px auto ' + ((hide & 4) ? '0' : '45') + 'px';
1132 +
1133 + // Adjust height of remote desktop, files and Intel AMT
1134 + var xh = (((hide & 1) ? 0 : 66) + ((hide & 2) ? 0 : 24) + ((hide & 4) ? 0 : 45) + ((hide & 8) ? 0 : 60)); // 0 to 195
1135 + QS('p3users')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
1136 + QS('p3events')['height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
1137 + QS('deskarea3x')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
1138 + QS('deskarea3x')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
1139 + QS('p5filetable')['height'] = 'calc(100vh - ' + (160 + xh) + 'px)';
1140 + QS('p13filetable')['height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
1141 + QS('serverMainStats')['height'] = 'calc(100vh - ' + (110 + xh) + 'px)';
1142 + QS('serverMainStats')['max-height'] = 'calc(100vh - ' + (110 + xh) + 'px)';
1143 + QS('xdevices')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
1144 + QS('xdevicesmap')['max-height'] = 'calc(100vh - ' + (124 + xh) + 'px)';
1145 + QS('p15agentConsole')['height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
1146 + QS('p15agentConsole')['max-height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
1147 + QS('p15agentConsoleText')['height'] = 'calc(100vh - ' + (81 + xh) + 'px)';
1148 + QS('p15agentConsoleText')['max-height'] = 'calc(100vh - ' + (81 + xh) + 'px)';
1149 + QS('p43iframe')['height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
1150 + QS('p43iframe')['max-height'] = 'calc(100vh - ' + (84 + xh) + 'px)';
1151 + }
1152 +
1153 + // We are looking at a single device, remove all the back buttons
1154 + if ('{{currentNode}}' != '') {
1155 + QV('p10BackButton', false);
1156 + QV('p11BackButton', false);
1157 + QV('p12BackButton', false);
1158 + QV('p13BackButton', false);
1159 + QV('p14BackButton', false);
1160 + QV('p15BackButton', false);
1161 + QV('p16BackButton', false);
1162 + }
1163 + p1updateInfo();
1164 +
1165 + // Setup the context menu
1166 + document.onclick = function (e) { hideContextMenu(); }
1167 + document.onkeypress = ondockeypress;
1168 + document.onkeydown = ondockeydown;
1169 + document.onkeyup = ondockeyup;
1170 + //window.addEventListener('focus', ondocfocus, false);
1171 + window.addEventListener('blur', ondocblur, false);
1172 + window.onresize = function () { masterUpdate(512); }
1173 + setTimeout(function() { masterUpdate(512); }, 200);
1174 +
1175 + // Connect to the mesh server
1176 + meshserver = MeshServerCreateControl(domainUrl, authCookie);
1177 + meshserver.onStateChanged = onStateChanged;
1178 + meshserver.onMessage = onMessage;
1179 + meshserver.trace = (args.trace == 1);
1180 + meshserver.Start();
1181 +
1182 + // Setup page controls
1183 + Q('sortselect').selectedIndex = sort = getstore('sort', 0);
1184 + Q('sizeselect').selectedIndex = getstore('_viewsize', 1);
1185 + Q('SearchInput').value = getstore('_search', '');
1186 + showRealNames = (getstore('showRealNames', 0) == 1);
1187 + Q('RealNameCheckBox').checked = showRealNames;
1188 + Q('viewselect').value = getstore('_deviceView', 1);
1189 + Q('DeskControl').checked = (getstore('DeskControl', 1) == 1);
1190 + QV('accountChangeEmailAddressSpan', (features & 0x200000) == 0);
1191 +
1192 + // Display the page devices
1193 + masterUpdate(3)
1194 + for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
1195 + Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
1196 +
1197 + // Setup upload drag & drop
1198 + Q('p5filetable').addEventListener('drop', p5fileDragDrop, false);
1199 + Q('p5filetable').addEventListener('dragover', p5fileDragOver, false);
1200 + Q('p5filetable').addEventListener('dragleave', p5fileDragLeave, false);
1201 + //Q('p5fileCatchAllInput').addEventListener('drop', p5fileDragDrop, false);
1202 + //Q('p5fileCatchAllInput').addEventListener('dragover', p5fileDragOver, false);
1203 + //Q('p5fileCatchAllInput').addEventListener('dragleave', p5fileDragLeave, false);
1204 +
1205 + // Setup upload drag & drop
1206 + Q('p13filetable').addEventListener('drop', p13fileDragDrop, false);
1207 + Q('p13filetable').addEventListener('dragover', p13fileDragOver, false);
1208 + Q('p13filetable').addEventListener('dragleave', p13fileDragLeave, false);
1209 +
1210 + // Timeline update interval
1211 + setInterval(updateDeviceTimeline, 120000); // Check every 2 minutes
1212 +
1213 + // Load desktop settings
1214 + var t = localStorage.getItem('desktopsettings');
1215 + if (t != null) { desktopsettings = JSON.parse(t); }
1216 + t = localStorage.getItem('multidesktopsettings');
1217 + if (t != null) { multidesktopsettings = JSON.parse(t); }
1218 + applyDesktopSettings();
1219 +
1220 + // Terminal special keys
1221 + var x = '';
1222 + for (var c = 1; c < 27; c++) x += '<option value=\'' + c + '\'>' + "CTRL" + '-' + String.fromCharCode(64 + c) + ' (' + c + ')</option>';
1223 + QH('specialkeylist', x);
1224 +
1225 + // Setup server stats panels
1226 + setupGeneralServerStats();
1227 + setupServerTimelineStats();
1228 +
1229 + // Setup the user interface in the right mode
1230 + userInterfaceSelectMenu();
1231 +
1232 + // If SSPI or LDAP authentication not used, allow batch account creation.
1233 + QV('p4UserBatchCreate', (features & 0x00080000) == 0);
1234 + }
1235 +
1236 + // Toggle the web page to full screen
1237 + function toggleAspectRatio(toggle) {
1238 + if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); putstore('deskAspectRatio', deskAspectRatio); }
1239 + deskAdjust();
1240 + }
1241 +
1242 + // If FullScreen, toggle menu to be horisontal or vertical
1243 + function toggleStackMenu(toggle) {
1244 + if (webPageFullScreen == true) {
1245 + if (toggle === 1) {
1246 + webPageStackMenu = !webPageStackMenu;
1247 + putstore('webPageStackMenu', webPageStackMenu);
1248 + }
1249 + if (webPageStackMenu == false) {
1250 + QC('body').remove('menu_stack');
1251 + } else {
1252 + QC('body').add('menu_stack');
1253 + if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
1254 + }
1255 + deskAdjust();
1256 + }
1257 + }
1258 +
1259 + // Toggle user interface menu
1260 + function showUserInterfaceSelectMenu() {
1261 + Q('uiViewButton1').classList.remove('uiSelectorSel');
1262 + Q('uiViewButton2').classList.remove('uiSelectorSel');
1263 + Q('uiViewButton3').classList.remove('uiSelectorSel');
1264 + Q('uiViewButton4').classList.remove('uiSelectorSel');
1265 + try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
1266 + QV('uiMenu', (QS('uiMenu').display == 'none'));
1267 + //Q('uiViewButton1').focus();
1268 + if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
1269 + }
1270 +
1271 + function userInterfaceSelectMenu(s) {
1272 + if (s) { uiMode = s; putstore('uiMode', uiMode); }
1273 + webPageFullScreen = (uiMode < 3);
1274 + webPageStackMenu = (uiMode > 1);
1275 + toggleFullScreen(0);
1276 + toggleStackMenu(0);
1277 + if (webPageStackMenu && (xxcurrentView >= 10)) { QC('column_l').add('room4submenu'); } else { QC('column_l').remove('room4submenu'); }
1278 + }
1279 +
1280 + function toggleNightMode() {
1281 + nightMode = !nightMode;
1282 + if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
1283 + putstore('_nightMode', nightMode?'1':'0');
1284 + }
1285 +
1286 + // Toggle the web page to full screen
1287 + function toggleFullScreen(toggle) {
1288 + if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
1289 + var hide = 0;
1290 + if (args.hide) { hide = parseInt(args.hide); }
1291 + if (webPageFullScreen == false) {
1292 + QC('body').remove('menu_stack');
1293 + QC('body').remove('fullscreen');
1294 + QC('body').remove('arg_hide');
1295 + if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
1296 + QV('UserDummyMenuSpan', false);
1297 + //QV('page_leftbar', false);
1298 + } else {
1299 + QC('body').add('fullscreen');
1300 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
1301 + QV('page_leftbar', !(hide & 16));
1302 + QV('MainMenuSpan', !(hide & 16));
1303 + if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
1304 + QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
1305 + }
1306 + masterUpdate(512);
1307 + QV('body', true);
1308 + }
1309 +
1310 + function getNodeFromId(id) { if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } } return null; }
1311 + function reload() {
1312 + var x = window.location.href;
1313 + if (x.endsWith('/#')) { x = x.substring(0, x.length - 2); }
1314 + window.location.href = x;
1315 + }
1316 +
1317 + function onStateChanged(server, state, prevState, errorCode) {
1318 + if (state == 0) {
1319 + // Control web socket disconnected
1320 + setDialogMode(0); // Close any dialog boxes if present
1321 + go(0); // Go to disconnection panel
1322 +
1323 + // Clean up
1324 + powerTimeline = null;
1325 + powerTimelineReq = null;
1326 + powerTimelineNode = null;
1327 + powerTimelineUpdate = null;
1328 + deleteAllNotifications(); // Close and clear notifications if present
1329 + hideContextMenu(); // Hide the context menu if present
1330 + QV('verifyEmailId2', false);
1331 + QV('logoutControl', false);
1332 + if (errorCode == 'noauth') { QH('p0span', "Não foi possível executar a autenticação"); return; }
1333 + if (prevState == 2) { if (autoReconnect) { setTimeout(serverPoll, 5000); } } else { QH('p0span', "Não foi possível conectar o soquete da web"); }
1334 + if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
1335 + } else if (state == 2) {
1336 + // Fetch list of meshes, nodes, files
1337 + meshserver.send({ action: 'meshes' });
1338 + meshserver.send({ action: 'nodes', id: '{{currentNode}}' });
1339 + if (pluginHandler != null) { meshserver.send({ action: 'plugins' }); }
1340 + if ('{{currentNode}}' == '') { meshserver.send({ action: 'files' }); }
1341 + if ('{{viewmode}}' == '') { go(1); }
1342 + authCookieRenewTimer = setInterval(function () { meshserver.send({ action: 'authcookie' }); }, 1800000); // Request a cookie refresh every 30 minutes.
1343 + }
1344 + }
1345 +
1346 + // Poll the server, if it responds, refresh the page.
1347 + function serverPoll() {
1348 + var xdr = null;
1349 + try { xdr = new XDomainRequest(); } catch (e) { }
1350 + if (!xdr) xdr = new XMLHttpRequest();
1351 + xdr.open('HEAD', window.location.href);
1352 + xdr.timeout = 15000;
1353 + xdr.onload = function () { reload(); };
1354 + xdr.onerror = xdr.ontimeout = function () { setTimeout(serverPoll, 10000); };
1355 + xdr.send();
1356 + }
1357 +
1358 + // Return true if this browser supports clickonce
1359 + function detectClickOnce() {
1360 + for (var i in window.navigator.mimeTypes) { if (window.navigator.mimeTypes[i].type == 'application/x-ms-application') { return true; } }
1361 + var userAgent = window.navigator.userAgent.toUpperCase();
1362 + return (userAgent.indexOf('.NET CLR 3.5') >= 0) || (userAgent.indexOf('(WINDOWS NT ') >= 0);
1363 + }
1364 +
1365 + function updateSiteAdmin() {
1366 + var noServerBackup = '{{{noServerBackup}}}';
1367 + var siteRights = userinfo.siteadmin;
1368 + if (noServerBackup == 1) { siteRights &= 0xFFFFFFFA; } // If not server backups allowed, remove server backup and restore permissions
1369 +
1370 + // Update account actions
1371 + QV('p2AccountSecurity', ((features & 4) == 0) && (serverinfo.domainauth == false) && ((features & 4096) != 0)); // Hide Account Security if in single user mode, domain authentication to 2 factor auth not supported.
1372 + QV('p2AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
1373 + QV('p2AccountImage', ((features & 4) == 0) && (serverinfo.domainauth == false)); // If account actions are not visible, also remove the image on that panel
1374 + QV('p2ServerActions', siteRights & 21);
1375 + QV('LeftMenuMyServer', siteRights & 21); // 16 + 4 + 1
1376 + QV('MainMenuMyServer', siteRights & 21);
1377 + QV('p2ServerActionsBackup', siteRights & 1);
1378 + QV('p2ServerActionsRestore', siteRights & 4);
1379 + QV('p2ServerActionsVersion', siteRights & 16);
1380 + QV('MainMenuMyFiles', siteRights & 8);
1381 + QV('LeftMenuMyFiles', siteRights & 8);
1382 + if (((siteRights & 8) == 0) && (xxcurrentView == 5)) { setDialogMode(0); go(1); }
1383 + if (currentNode != null) { gotoDevice(currentNode._id, xxcurrentView, true); }
1384 +
1385 + // Update user management state
1386 + if ((userinfo.siteadmin & 2) != 0)
1387 + {
1388 + // We are user administrator
1389 + if (users == null) { meshserver.send({ action: 'users' }); }
1390 + if (wssessions == null) { meshserver.send({ action: 'wssessioncount' }); }
1391 + } else {
1392 + // We are not user administrator
1393 + users = null;
1394 + wssessions = null;
1395 + updateUsers();
1396 + if (xxcurrentView == 4 || ((xxcurrentView >= 30) && (xxcurrentView < 40))) { setDialogMode(0); go(1); currentUser = null; }
1397 + }
1398 + meshserver.send({ action: 'events', limit: parseInt(p3limitdropdown.value) });
1399 + QV('ServerConsole', userinfo.siteadmin === 0xFFFFFFFF);
1400 + QV('ServerTrace', userinfo.siteadmin === 0xFFFFFFFF);
1401 + if ((xxcurrentView == 115) && (userinfo.siteadmin != 0xFFFFFFFF)) { go(6); }
1402 + if ((xxcurrentView == 6) && ((userinfo.siteadmin & 21) == 0)) { go(1); }
1403 +
1404 + // If we are site administrator, register to get server statistics
1405 + if ((siteRights & 21) != 0) { meshserver.send({ action: 'serverstats', interval: 10000 }); }
1406 + }
1407 +
1408 + // To boost the speed of the web page when even floods occur, this method perform a delayed update on the web page.
1409 + var updateNaggleTimer = null;
1410 + var updateNaggleFlags = 0;
1411 + function masterUpdate(flags) {
1412 + updateNaggleFlags |= flags;
1413 + if (updateNaggleTimer == null) {
1414 + updateNaggleTimer = setTimeout(function () {
1415 + if (updateNaggleFlags & 512) { center(); }
1416 + if (updateNaggleFlags & 1) { onSearchInputChanged(); }
1417 + if (updateNaggleFlags & 2) { onSortSelectChange(false); }
1418 + if (updateNaggleFlags & 128) { updateMeshes(); }
1419 + if (updateNaggleFlags & 4) { updateDevices(); }
1420 + if (updateNaggleFlags & 8) { drawNotifications(); }
1421 + {{{StartGeoLocationJS}}}if (updateNaggleFlags & 16) { updateMapMarkers(); }{{{EndGeoLocationJS}}}
1422 + if (updateNaggleFlags & 32) { eventsUpdate(); }
1423 + {{{StartGeoLocationJS}}}if (updateNaggleFlags & 64) { refreshMap(false, true); }{{{EndGeoLocationJS}}}
1424 + if (updateNaggleFlags & 256) { drawDeviceTimeline(); }
1425 + if (updateNaggleFlags & 1024) { deviceEventsUpdate(); }
1426 + if (updateNaggleFlags & 2048) { userEventsUpdate(); }
1427 + if (updateNaggleFlags & 4096) { p20updateMesh(); }
1428 + updateNaggleTimer = null;
1429 + updateNaggleFlags = 0;
1430 + }, 150);
1431 + }
1432 + }
1433 +
1434 + var backupCodesWarningDone = false;
1435 + function updateSelf() {
1436 + QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
1437 + QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
1438 + QV('manageOtp', (userinfo.otpsecret == 1) || (userinfo.otphkeys > 0));
1439 + QV('authAppSetupCheck', userinfo.otpsecret == 1);
1440 + QV('authKeySetupCheck', userinfo.otphkeys > 0);
1441 + QV('authCodesSetupCheck', userinfo.otpkeys > 0);
1442 + masterUpdate(4 + 128 + 4096);
1443 +
1444 + // Check if backup codes should really be enabled
1445 + if ((backupCodesWarningDone == false) && !(userinfo.otpkeys > 0) && (((userinfo.otpsecret == 1) && !(userinfo.otphkeys > 0)) || ((userinfo.otpsecret != 1) && (userinfo.otphkeys == 1)))) {
1446 + var n = { text: "Adicione códigos de backup de dois fatores. Se o fator atual for perdido, não há como recuperar esta conta.", title: "Autenticação de dois fatores" };
1447 + addNotification(n);
1448 + backupCodesWarningDone = true;
1449 + }
1450 +
1451 + // If we can't create new groups, hide all links that can do that.
1452 + var newGroupsAllowed = ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0));
1453 + QV('p2createMeshLink1', newGroupsAllowed);
1454 + QV('p2createMeshLink2', newGroupsAllowed);
1455 + QV('getStarted1', newGroupsAllowed);
1456 + QV('getStarted2', !newGroupsAllowed);
1457 +
1458 + if (typeof userinfo.passchange == 'number') {
1459 + if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', "- Redefinir no próximo login."); }
1460 + else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
1461 + var seconds = (userinfo.passchange) + (passRequirements.reset * 86400) - Math.floor(Date.now() / 1000);
1462 + if (seconds < 0) { QH('p2nextPasswordUpdateTime', "- Redefinir no próximo login."); }
1463 + else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} minuto {1}.", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
1464 + else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} hora {1}.", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
1465 + else { QH('p2nextPasswordUpdateTime', format("- Redefinir em {0} dia {1}."), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
1466 + }
1467 + }
1468 + }
1469 +
1470 + function addLetterS(x) { return (x > 1) ? 's' : ''; }
1471 + function setSessionActivity() { sessionActivity = Date.now(); QH('idleTimeoutNotify', ''); }
1472 + function checkIdleSessionTimeout() {
1473 + var delta = (Date.now() - sessionActivity);
1474 + if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else {
1475 + var ds = Math.round((serverinfo.timeout - delta) / 1000);
1476 + if (ds <= 60) {
1477 + QH('idleTimeoutNotify', '<br />' + format("{0} segundo{1} até desconectar", ds, addLetterS(ds)));
1478 + } else {
1479 + ds = Math.round(ds / 60);
1480 + if (ds <= 5) { QH('idleTimeoutNotify', '<br />' + format("{0} minutos{1} até desconectar", ds, addLetterS(ds))); }
1481 + }
1482 + }
1483 + }
1484 +
1485 + function onMessage(server, message) {
1486 + switch (message.action) {
1487 + case 'trace': {
1488 + serverTrace.unshift(message);
1489 + displayServerTrace();
1490 + break;
1491 + }
1492 + case 'traceinfo': {
1493 + if (typeof message.traceSources == 'object') {
1494 + if ((message.traceSources != null) && (message.traceSources.length > 0)) {
1495 + serverTraceSources = message.traceSources;
1496 + QH('p41traceStatus', EscapeHtml(message.traceSources.join(', ')));
1497 + } else {
1498 + serverTraceSources = [];
1499 + QH('p41traceStatus', "Nenhum");
1500 + }
1501 + }
1502 + break;
1503 + }
1504 + case 'serverstats': {
1505 + updateGeneralServerStats(message);
1506 + break;
1507 + }
1508 + case 'serverwarnings': {
1509 + if ((message.warnings != null) && (message.warnings.length > 0)) {
1510 + var x = '';
1511 + for (var i in message.warnings) { x += '<div style=color:red;padding-bottom:6px><b>' + "WARNING: " + message.warnings[i] + '</b></div>'; }
1512 + QH('serverWarnings', x);
1513 + QV('serverWarningsDiv', true);
1514 + }
1515 + break;
1516 + }
1517 + case 'servertimelinestats': {
1518 + setServerTimelineStats(message.events);
1519 + break;
1520 + }
1521 + case 'authcookie': {
1522 + // Got an authentication cookie refresh
1523 + authCookie = message.cookie;
1524 + authRelayCookie = message.rcookie;
1525 + break;
1526 + }
1527 + case 'serverinfo': {
1528 + serverinfo = message.serverinfo;
1529 + if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
1530 + if (debugmode == 1) { console.log('Server time: ', printDateTime(new Date(serverinfo.serverTime))); }
1531 + break;
1532 + }
1533 + case 'userinfo': {
1534 + userinfo = message.userinfo;
1535 + updateSiteAdmin();
1536 + updateSelf();
1537 + break;
1538 + }
1539 + case 'users': {
1540 + users = {};
1541 + for (var m in message.users) { users[message.users[m]._id] = message.users[m]; }
1542 + updateUsers();
1543 + break;
1544 + }
1545 + case 'wssessioncount': {
1546 + wssessions = message.wssessions;
1547 + updateUsers();
1548 + break;
1549 + }
1550 + case 'meshes': {
1551 + meshes = {};
1552 + for (var m in message.meshes) { meshes[message.meshes[m]._id] = message.meshes[m]; }
1553 + masterUpdate(4 + 128);
1554 + break;
1555 + }
1556 + case 'files': {
1557 + filetree = setupBackPointers(message.filetree);
1558 + updateFiles();
1559 + d3updatefiles();
1560 + break;
1561 + }
1562 + case 'nodes': {
1563 + nodes = [];
1564 + for (var m in message.nodes) {
1565 + if (!meshes[m]) { console.log('Invalid mesh (1): ' + m); continue; }
1566 + for (var n in message.nodes[m]) {
1567 + if (message.nodes[m][n]._id == null) { console.log('Invalid node (' + n + '): ' + JSON.stringify(message.nodes)); continue; }
1568 + message.nodes[m][n].namel = message.nodes[m][n].name.toLowerCase();
1569 + if (message.nodes[m][n].rname) { message.nodes[m][n].rnamel = message.nodes[m][n].rname.toLowerCase(); } else { message.nodes[m][n].rnamel = message.nodes[m][n].namel; }
1570 + message.nodes[m][n].meshnamel = meshes[m].name.toLowerCase();
1571 + message.nodes[m][n].meshid = m;
1572 + message.nodes[m][n].state = (message.nodes[m][n].state)?(message.nodes[m][n].state):0;
1573 + message.nodes[m][n].desc = message.nodes[m][n].desc;
1574 + message.nodes[m][n].ip = message.nodes[m][n].ip;
1575 + if (!message.nodes[m][n].icon) message.nodes[m][n].icon = 1;
1576 + message.nodes[m][n].ident = ++nodeShortIdent;
1577 + nodes.push(message.nodes[m][n]);
1578 + }
1579 + }
1580 + masterUpdate(1 | 2 | 4 | 64);
1581 +
1582 + if (xxcurrentView == -1) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(1); } }
1583 + if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}',parseInt('{{viewmode}}'));}
1584 + break;
1585 + }
1586 + case 'powertimeline': {
1587 + if (message.nodeid != powerTimelineReq) break;
1588 + powerTimelineNode = message.nodeid;
1589 + powerTimeline = message.timeline;
1590 + powerTimelineUpdate = Date.now() + 300000; // Update every 5 minutes
1591 + for (var i in powerTimeline) { if (i % 2 == 1) { powerTimeline[i] = powerTimeline[i] * 1000; } } // Decompress time
1592 + if (currentNode._id == message.nodeid) { masterUpdate(256); }
1593 + break;
1594 + }
1595 + case 'getsysinfo': {
1596 + if (message.nodeid != powerTimelineReq) break;
1597 + //console.log('getsysinfo', message); // ***********************
1598 + if (message.noinfo === true) {
1599 + QH('p17info', "Nenhuma informação para este dispositivo.");
1600 + } else {
1601 + var x = '', s = {};
1602 + if (message.hardware) {
1603 + if (message.hardware.identifiers) {
1604 + var ident = message.hardware.identifiers;
1605 + // BIOS
1606 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "BIOS" + '</b></div>';
1607 + if (ident.bios_vendor) { x += addDetailItem("Fornecedor", ident.bios_vendor, s); }
1608 + if (ident.bios_version) { x += addDetailItem("Versão", ident.bios_version, s); }
1609 + x += '<br />';
1610 +
1611 + // Motherboard
1612 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Placa-mãe" + '</b></div>';
1613 + if (ident.board_vendor) { x += addDetailItem("Fornecedor", ident.board_vendor, s); }
1614 + if (ident.board_name) { x += addDetailItem("Nome", ident.board_name, s); }
1615 + if (ident.board_serial && (ident.board_serial != '')) { x += addDetailItem("Serial", ident.board_serial, s); }
1616 + if (ident.board_version) { x += addDetailItem("Versão", ident.board_version, s); }
1617 + if (ident.product_uuid) { x += addDetailItem("Identificador", ident.product_uuid, s); }
1618 + x += '<br />';
1619 + }
1620 +
1621 + if (message.hardware.windows) {
1622 + if (message.hardware.windows.memory) {
1623 + // Memory
1624 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Memória" + '</b></div>';
1625 +
1626 + // Sort Memory
1627 + function memorySort(a, b) { if (a.BankLabel > b.BankLabel) return 1; if (a.BankLabel < b.BankLabel) return -1; return 0; }
1628 + message.hardware.windows.memory.sort(memorySort);
1629 +
1630 + x += '<table style=width:100%>';
1631 + for (var i in message.hardware.windows.memory) {
1632 + var m = message.hardware.windows.memory[i];
1633 + x += '<tr><td VALIGN=Top style=width:38px><img src="images/ram2.png" />'
1634 + x += '<td><div style=background-color:lightgray;border-radius:5px;padding:8px>';
1635 + x += '<div><b>' + m.BankLabel + '</b></div>';
1636 + if (m.Capacity) { x += addDetailItem("Capacidade / velocidade", format("{0} Mb, {1} Mhz", (m.Capacity / 1024 / 1024), m.Speed), s); }
1637 + if (m.PartNumber) { x += addDetailItem("Número Parcial", ((m.Manufacturer && m.Manufacturer != 'Undefined')?(m.Manufacturer + ', '):'') + m.PartNumber, s); }
1638 + x += '</div>';
1639 + }
1640 + x += '</table><br />';
1641 + }
1642 +
1643 + if (message.hardware.windows.osinfo) {
1644 + // Operating System
1645 + var m = message.hardware.windows.osinfo;
1646 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Sistema operacional" + '</b></div>';
1647 + if (m.Caption) { x += addDetailItem("Nome", m.Caption, s); }
1648 + if (m.Version) { x += addDetailItem("Versão", m.Version, s); }
1649 + if (m.OSArchitecture) { x += addDetailItem("Arquitetura", m.OSArchitecture, s); }
1650 + x += '<br />';
1651 + }
1652 +
1653 + // Disks
1654 + //x += '<div class=DevSt style=margin-bottom:3px><b>Disks</b></div>';
1655 + //x += '<br />';
1656 + }
1657 + }
1658 +
1659 + QH('p17info', x);
1660 + }
1661 + break;
1662 + }
1663 + case 'lastconnect': {
1664 + var node = getNodeFromId(message.nodeid);
1665 + if (node != null) {
1666 + node.lastconnect = message.time;
1667 + node.lastaddr = message.addr;
1668 + if ((currentNode._id == node._id) && (Q('MainComputerState').innerHTML == '')) {
1669 + QH('MainComputerState', '<span>' + "Visto pela última vez:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>');
1670 + }
1671 + }
1672 + break;
1673 + }
1674 + case 'msg': {
1675 + // Check if this is a message from a node
1676 + if (message.nodeid != null) {
1677 + var index = -1;
1678 + if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } } }
1679 + if (index != -1) {
1680 + // Node was found, dispatch the message
1681 + if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
1682 + else if (message.type == 'notify') { // This is a notification message.
1683 + var n = getstore('notifications', 0);
1684 + if (((n & 8) == 0) && (message.amtMessage != null)) { break; } // Intel AMT desktop & terminal messages should be ignored.
1685 + var n = { text: message.value, title: message.title, icon: message.icon };
1686 + if (message.nodeid != null) { n.nodeid = message.nodeid; }
1687 + if (message.tag != null) { n.tag = message.tag; }
1688 + if (message.username != null) { n.username = message.username; }
1689 + addNotification(n);
1690 + } else if (message.type == 'ps') {
1691 + showDeskToolsProcesses(message);
1692 + } else if (message.type == 'services') {
1693 + showDeskToolsServices(message);
1694 + } else if ((message.type == 'getclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
1695 + Q('d2clipText').value = message.data;
1696 + } else if ((message.type == 'setclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
1697 + // Display success/fail on the clipboard dialog box.
1698 + QH('dlgClipStatus', message.success ? '<span style=color:green>' + "Sucesso" + '</span>' : '<span style=color:red>' + "Falhou" + '</span>')
1699 + setTimeout(function () { try { QH('dlgClipStatus', ''); } catch (ex) { } }, 2000);
1700 + }
1701 + }
1702 + } else {
1703 + if (message.type == 'notify') { // This is a notification message.
1704 + var n = { text: message.value, title: message.title, icon: message.icon };
1705 + if (message.tag != null) { n.tag = message.tag; }
1706 + if (message.username != null) { n.username = message.username; }
1707 + addNotification(n);
1708 + }
1709 + }
1710 + break;
1711 + }
1712 + case 'getnetworkinfo': {
1713 + if ((currentNode._id == message.nodeid) && (xxdialogMode == 2) && (xxdialogTag == 'if' + message.nodeid)) {
1714 + if (message.netif == null) {
1715 + QH('d2netinfo', "Nenhuma informação de interface de rede disponível para este dispositivo.");
1716 + } else {
1717 + var x = '<div class=dialogText>';
1718 +
1719 + if (currentNode.lastconnect) { x += addHtmlValue2("Última conexão do agente", printDateTime(new Date(currentNode.lastconnect))); }
1720 + if (currentNode.lastaddr) {
1721 + var splitip = currentNode.lastaddr.split(':');
1722 + if (splitip.length > 2) {
1723 + // IPv6
1724 + x += addHtmlValue2("Último endereço do agente", currentNode.lastaddr + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(currentNode.lastaddr) + '\") width=10 height=10>');
1725 + } else {
1726 + // IPv4
1727 + if (isPrivateIP(currentNode.lastaddr)) {
1728 + x += addHtmlValue2("Último endereço do agente", splitip[0] + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
1729 + } else {
1730 + x += addHtmlValue2("Último endereço do agente", '<a href="https://iplocation.com/?ip=' + splitip[0] + '" rel="noreferrer noopener" target="MeshIPLoopup">' + splitip[0] + '</a> <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
1731 + }
1732 + }
1733 + }
1734 +
1735 + x += addHtmlValue2("Última atualização de interfaces", printDateTime(new Date(message.updateTime)));
1736 + for (var i in message.netif) {
1737 + var net = message.netif[i];
1738 + x += '<hr />'
1739 + if (net.name) { x += addHtmlValue2("Nome", '<b>' + EscapeHtml(net.name) + '</b>'); }
1740 + if (net.desc) { x += addHtmlValue2("Descrição", EscapeHtml(net.desc).replace('(R)', '&reg;').replace('(r)', '&reg;')); }
1741 + if (net.dnssuffix) { x += addHtmlValue2("Sufixo DNS", EscapeHtml(net.dnssuffix) + ' <img src="images/link4.png" title="' + "Copiar nome para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.dnssuffix) + '\") width=10 height=10>'); }
1742 + if (net.mac) { x += addHtmlValue2("Endereço MAC", '<a href="https://dnslytics.com/mac-address-lookup/' + net.mac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.mac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copiar endereço MAC para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.mac.toLowerCase()) + '\") width=10 height=10>'); }
1743 + if (net.v4addr) { x += addHtmlValue2("Endereço IPv4", EscapeHtml(net.v4addr) + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4addr) + '\") width=10 height=10>'); }
1744 + if (net.v4mask) { x += addHtmlValue2("Máscara IPv4", EscapeHtml(net.v4mask) + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4mask) + '\") width=10 height=10>'); }
1745 + if (net.v4gateway) { x += addHtmlValue2("Gateway IPv4", EscapeHtml(net.v4gateway) + ' <img src="images/link4.png" title="' + "Copiar endereço para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4gateway) + '\") width=10 height=10>'); }
1746 + if (net.gatewaymac) { x += addHtmlValue2("Gateway MAC", '<a href="https://dnslytics.com/mac-address-lookup/' + net.gatewaymac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.gatewaymac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copiar endereço MAC para a área de transferência" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.gatewaymac.toLowerCase()) + '\") width=10 height=10>'); }
1747 + }
1748 + x += '</div>';
1749 + QH('d2netinfo', x);
1750 + }
1751 + }
1752 + break;
1753 + }
1754 + case 'serverversion': {
1755 + if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerUpdate')) {
1756 + var x = '<div class=dialogText>';
1757 + if (!message.current) { message.current = "Desconhecido"; }
1758 + if (!message.latest) { message.latest = "Desconhecido"; }
1759 + x += addHtmlValue2("Versão Atual", '<b>' + EscapeHtml(message.current) + '</b>');
1760 + x += addHtmlValue2("Última versão", '<b>' + EscapeHtml(message.latest) + '</b>');
1761 + x += '</div>';
1762 + if ((message.latest.indexOf('.') == -1) || (message.current == message.latest) || ((features & 2048) == 0)) {
1763 + setDialogMode(2, "Versão MeshCentral", 1, null, x);
1764 + } else {
1765 + setDialogMode(2, "Versão MeshCentral", 3, server_showVersionDlgEx, x + '<br /><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Marque e clique em OK para iniciar a atualização automática do servidor." + '</label>');
1766 + server_showVersionDlgUpdate();
1767 + }
1768 + }
1769 + break;
1770 + }
1771 + case 'servererrors': {
1772 + if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerErrors')) {
1773 + if (message.data == null) {
1774 + setDialogMode(2, "Erros do servidor MeshCentral", 1, null, "O servidor não possui log de erros.");
1775 + } else {
1776 + var x = '<div class="dialogText dialogTextLog"><pre id=d2ServerErrorsLogPre>' + message.data + '<pre></div>';
1777 + setDialogMode(2, "Erros do servidor MeshCentral", 3, server_showErrorsDlgEx, x + '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="' + "Baixar log de erro" + '" style=cursor:pointer onclick=d2CopyServerErrorsToClip()></div><div><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Verifique e clique em OK para limpar o log de erros." + '</label></div>');
1778 + server_showVersionDlgUpdate();
1779 + }
1780 + }
1781 + break;
1782 + }
1783 + case 'serverconsole': {
1784 + p15consoleReceive('serverconsole', message.value);
1785 + break;
1786 + }
1787 + case 'events': {
1788 + if ((message.nodeid != null) && (message.nodeid == currentNode._id)) {
1789 + currentDeviceEvents = message.events;
1790 + masterUpdate(1024);
1791 + } else if ((message.user != null) && (message.user == currentUser.name)) {
1792 + currentUserEvents = message.events;
1793 + masterUpdate(2048);
1794 + } else {
1795 + events = message.events;
1796 + masterUpdate(32);
1797 + }
1798 + break;
1799 + }
1800 + case 'getcookie': {
1801 + if (message.tag == 'clickonce') {
1802 + var basicPort = '{{{serverRedirPort}}}' == '' ? '{{{serverPublicPort}}}' : '{{{serverRedirPort}}}';
1803 + var rdpurl = 'http://' + window.location.hostname + ':' + basicPort + '/clickonce/minirouter/MeshMiniRouter.application?WS=wss%3A%2F%2F' + window.location.hostname + '%2Fmeshrelay.ashx%3Fauth=' + message.cookie + '&CH={{{webcerthash}}}&AP=' + message.protocol + ((debugmode == 1) ? '' : '&HOL=1');
1804 + var newWindow = window.open(rdpurl, '_blank');
1805 + newWindow.opener = null;
1806 + }
1807 + break;
1808 + }
1809 + case 'getNotes': {
1810 + var n = Q('d2devNotes');
1811 + if (n && (message.id == decodeURIComponent(n.attributes['noteid'].value))) {
1812 + if (message.notes) { QH('d2devNotes', decodeURIComponent(message.notes)); } else { QH('d2devNotes', ''); }
1813 + var ro = (n.attributes['ro'].value == 'true');
1814 + if (ro == false) { // If we have permissions, set read/write on this note.
1815 + n.removeAttribute('readonly');
1816 + QE('idx_dlgOkButton', true);
1817 + QV('idx_dlgOkButton', true);
1818 + focusTextBox('d2devNotes');
1819 + }
1820 + }
1821 + break;
1822 + }
1823 + case 'otpauth-request': {
1824 + if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-request')) {
1825 + var secret = message.secret;
1826 + if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
1827 + else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
1828 + QH('d2optinfo', '<table style=width:380px><tr><td style=vertical-align:top>' + "Install <a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank>Google Authenticator</a> or a compatible application and scan the barcode, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login." + '<br /><br />Secret<br /><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:12px>' + secret + '</tt><br /><br /></td><td style=width:1px;vertical-align:top><a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank><div id="qrcode"></div></a></td><tr><td colspan=2 style="text-align:center;border-top:1px solid black"><br />' + "Digite o token aqui para o login em duas etapas:" + ' <input type=text onkeypress=\"return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></td></table>');
1829 + new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H });
1830 + QV('idx_dlgOkButton', true);
1831 + QE('idx_dlgOkButton', false);
1832 + Q('d2otpauthinput').focus();
1833 + }
1834 + break;
1835 + }
1836 + case 'otpauth-setup': {
1837 + if (xxdialogMode) return;
1838 + setDialogMode(2, "Autenticador de aplicativo", 1, null, message.success ? ('<b style=color:green>' + "Ativação do aplicativo autenticador bem-sucedida." + '</b> ' + "Agora você precisará de um token válido para fazer login novamente.") : ('<b style=color:red>' + "Falha na ativação do login em duas etapas." + '</b> ' + "Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto."));
1839 + break;
1840 + }
1841 + case 'otpauth-clear': {
1842 + if (xxdialogMode) return;
1843 + setDialogMode(2, "Autenticador de aplicativo", 1, null, message.success ? ('<b>' + "Aplicativo autenticador removido." + '</b> ' + "Você pode reativar esse recurso a qualquer momento.") : ('<b style=color:red>' + "A remoção da ativação do login em duas etapas falhou." + '</b> ' + "Tente novamente."));
1844 + break;
1845 + }
1846 + case 'otpauth-getpasswords': {
1847 + if (xxdialogMode) return;
1848 + var x = "Os tokens únicos podem ser usados como autenticação secundária. Gere um conjunto, imprima-os e mantenha-os em um local seguro.";
1849 + x += '<div style="border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px"><div style="padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold"><table class=selecttext style=width:100%;text-align:center>';
1850 + if (message.passwords) {
1851 + var j = 0, clipb = '';
1852 + for (var i in message.passwords) {
1853 + if (++j % 2) { x += '<tr>'; }
1854 + var p = '' + message.passwords[i].p;
1855 + while (p.length < 8) { p = '0' + p; }
1856 + if (message.passwords[i].u === true) {
1857 + x += '<td>' + p.substring(0, 4) + '&nbsp;' + p.substring(4);
1858 + if (clipb != '') { clipb += ' '; }
1859 + clipb += p;
1860 + } else {
1861 + x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + '&nbsp;' + p.substring(4); + '</strike>';
1862 + }
1863 + }
1864 + } else {
1865 + x += '<tr><td>' + "Nenhum token ativo";
1866 + }
1867 + x += '</table></div></div><br />';
1868 + x += '<div><input type=button value=' + "Fechar" + ' onclick=setDialogMode(0) style=float:right></input>';
1869 + x += '<input type=button value="' + "Gere novos tokens" + '" onclick="account_manageOtp(1);"></input>';
1870 + if (message.passwords != null) {
1871 + x += '<input type=button value="' + "Limpar Tokens" + '" onclick="account_manageOtp(2);"></input>';
1872 + x += '&nbsp;<img src=images/link4.png height=10 width=10 title="' + "Copiar códigos válidos para a área de transferência" + '" style=cursor:pointer onclick=copyTextToClip2("' + encodeURIComponent(clipb) + '")>';
1873 + }
1874 + x += '</div><br />';
1875 + setDialogMode(2, "Gerenciar códigos de backup", 8, null, x, 'otpauth-manage');
1876 + break;
1877 + }
1878 + case 'otp-hkey-get': {
1879 + if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
1880 + var start = '<div style="border-radius:6px;border:2px solid #CCC;background-color:#BBB;width:100%;box-sizing:border-box;margin-bottom:6px"><div style="margin:3px;font-family:Arial, Helvetica, sans-serif;font-size:16px;font-weight:bold"><table style=width:100%;text-align:left>';
1881 + var end = '</table></div></div>';
1882 + var x = "<a href=\"https://www.yubico.com/\" rel=\"noreferrer noopener\" target=\"_blank\">Chaves Hardware</a> são usados como autenticação de login secundária.";
1883 + x += '<div style="max-height:150px;overflow-y:auto;overflow-x:hidden;margin-top:6px;margin-bottom:6px">';
1884 + if (message.keys && message.keys.length > 0) {
1885 + for (var i in message.keys) {
1886 + var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
1887 + x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remover" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
1888 + }
1889 + } else {
1890 + x += start + '<tr style=text-align:center><td>' + "Nenhuma chave configurada" + end;
1891 + }
1892 + x += '</div>';
1893 + x += '<div><input type=button value="' + "Fechar" + '" onclick=setDialogMode(0) style=float:right></input>';
1894 + if ((features & 0x00020000) != 0) { x += '<input id=d2addkey3 type=button value="' + "Adicionar chave" + '" onclick="account_addhkey(3);"></input>'; }
1895 + if ((features & 0x00004000) != 0) { x += '<input id=d2addkey2 type=button value="' + "Adicione YubiKeyreg; OTP" + '" onclick="account_addhkey(2);"></input>'; }
1896 + x += '</div><br />';
1897 + setDialogMode(2, "Gerenciar chaves de segurança", 8, null, x, 'otpauth-hardware-manage');
1898 + if (u2fSupported() == false) { QE('d2addkey1', false); }
1899 + break;
1900 + }
1901 + case 'otp-hkey-yubikey-add': {
1902 + if (message.result) {
1903 + meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
1904 + } else {
1905 + setDialogMode(2, "Adicionar chave de segurança", 1, null, '<br />' + "Erro, não foi possível adicionar a chave." + '<br /><br />');
1906 + }
1907 + break;
1908 + }
1909 + case 'otp-hkey-setup-response': {
1910 + if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
1911 + if (message.result == true) {
1912 + meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
1913 + } else {
1914 + setDialogMode(2, "Adicionar chave de segurança", 1, null, '<br />' + "ERRO: Não foi possível adicionar a chave." + '<br /><br />', 'otpauth-hardware-manage');
1915 + }
1916 + break;
1917 + }
1918 + case 'webauthn-startregister': {
1919 + if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
1920 + var x = "Pressione o botão da tecla agora." + '<br /><br /><div style=width:100%;text-align:center><img width=120 height=117 src="images/hardware-keypress-120.png" /></div><input id=dp1keyname style=display:none value=' + message.name + ' />';
1921 + setDialogMode(2, "Adicionar chave de segurança", 2, null, x);
1922 +
1923 + var publicKey = message.request;
1924 + message.request.challenge = Uint8Array.from(atob(message.request.challenge), function (c) { return c.charCodeAt(0) })
1925 + message.request.user.id = Uint8Array.from(atob(message.request.user.id), function (c) { return c.charCodeAt(0) })
1926 + navigator.credentials.create({ publicKey: publicKey })
1927 + .then(function(newCredentialInfo) {
1928 + // Public key credential
1929 + var r = { rawId: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.rawId))), response: { attestationObject: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.attestationObject))), clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.clientDataJSON))) }, type: newCredentialInfo.type };
1930 + meshserver.send({ action: 'webauthn-endregister', response: r });
1931 + setDialogMode(0);
1932 + }, function(error) {
1933 + // Error
1934 + setDialogMode(2, "Adicionar chave de segurança", 1, null, "ERRO:" + error);
1935 + });
1936 + break;
1937 + }
1938 + case 'event': {
1939 + if (!message.event.nolog) {
1940 + if (currentNode && (message.event.nodeid == currentNode._id)) {
1941 + // If this event has a nodeid and we are looking at this node, update the log in real time.
1942 + currentDeviceEvents.unshift(message.event);
1943 + var eventLimit = parseInt(p16limitdropdown.value);
1944 + while (currentDeviceEvents.length > eventLimit) { currentDeviceEvents.pop(); } // Remove element(s) at the end
1945 + masterUpdate(1024);
1946 + }
1947 +
1948 + if (currentUser && (message.event.userid == currentUser._id)) {
1949 + // If this event has a userid and we are looking at this user, update the log in real time.
1950 + currentUserEvents.unshift(message.event);
1951 + var eventLimit = parseInt(p31limitdropdown.value);
1952 + while (currentUserEvents.length > eventLimit) { currentUserEvents.pop(); } // Remove element(s) at the end
1953 + masterUpdate(2048);
1954 + }
1955 +
1956 + // Add this event to the master events log.
1957 + events.unshift(message.event);
1958 + var eventLimit = parseInt(p3limitdropdown.value);
1959 + while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
1960 + masterUpdate(32);
1961 + }
1962 + if (message.event.noact) break; // Take no action on this event
1963 + switch (message.event.action) {
1964 + case 'userWebState': {
1965 + // New user web state, update the web page as needed
1966 + if (localStorage != null) {
1967 + var oldShowRealNames = localStorage.getItem('showRealNames');
1968 + var oldUiMode = localStorage.getItem('uiMode');
1969 + var oldSort = localStorage.getItem('sort');
1970 + var oldLoctag = localStorage.getItem('loctag');
1971 +
1972 + var webstate = JSON.parse(message.event.state);
1973 + for (var i in webstate) { localStorage.setItem(i, webstate[i]); }
1974 +
1975 + // Update the web page
1976 + if ((webstate.deskAspectRatio != null) && (webstate.deskAspectRatio != deskAspectRatio)) { deskAspectRatio = webstate.deskAspectRatio; deskAdjust(); }
1977 + if ((webstate.showRealNames != null) && (webstate.showRealNames != oldShowRealNames)) { showRealNames = Q('RealNameCheckBox').checked = (webstate.showRealNames == '1'); masterUpdate(6); }
1978 + if ((webstate.uiMode != null) && (webstate.uiMode != oldUiMode)) { userInterfaceSelectMenu(parseInt(webstate.uiMode)); }
1979 + if ((webstate.sort != null) && (webstate.sort != oldSort)) { document.getElementById('sortselect').selectedIndex = sort = parseInt(webstate.sort); masterUpdate(6); }
1980 + if ((webstate.loctag != null) && (webstate.loctag != oldLoctag)) { if (webstate.loctag != null) { args.locale = webstate.loctag; } else { delete args.locale; } masterUpdate(0xFFFFFFFF); }
1981 + }
1982 + break;
1983 + }
1984 + case 'servertimelinestats': { addServerTimelineStats(message.event.data); break; }
1985 + case 'accountcreate':
1986 + case 'accountchange': {
1987 + // An account was created or changed
1988 + if (userinfo.name == message.event.account.name) {
1989 + var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
1990 + var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
1991 + if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
1992 + var oldgroups = userinfo.groups;
1993 + userinfo = message.event.account;
1994 + if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
1995 + updateSelf();
1996 +
1997 + if ((userinfo.siteadmin & 2) != 0) {
1998 + // Compare our groups
1999 + var og = oldgroups ? oldgroups : [];
2000 + var ng = userinfo.groups ? userinfo.groups : [];
2001 + if (og.join(',') != ng.join(',')) {
2002 + // Our groups have changed, re-ask for a list of users.
2003 + users = wssessions = null;
2004 + meshserver.send({ action: 'users' });
2005 + meshserver.send({ action: 'wssessioncount' });
2006 + }
2007 + }
2008 + }
2009 + if (users == null) break;
2010 +
2011 + // Check if the account is part of our user group
2012 + if ((userinfo.groups == null) || (userinfo.groups.length == 0) || (findOne(message.event.account.groups, userinfo.groups) == true)) {
2013 + users[message.event.account._id] = message.event.account; // Part of our groups, update this user.
2014 + } else {
2015 + delete users[message.event.account._id]; // No longer part of our groups, remove this user.
2016 + }
2017 +
2018 + updateUsers();
2019 + break;
2020 + }
2021 + case 'accountremove': {
2022 + // An account was removed
2023 + if (users == null) break;
2024 + delete users['user/' + domain + '/' + message.event.username.toLowerCase()];
2025 + updateUsers();
2026 + break;
2027 + }
2028 + case 'createmesh': {
2029 + // A new mesh was created
2030 + if ((meshes[message.event.meshid] == null) && (message.event.links[userinfo._id] != null)) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some.
2031 + meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
2032 + masterUpdate(4 + 128);
2033 + meshserver.send({ action: 'files' });
2034 + }
2035 + break;
2036 + }
2037 + case 'meshchange': {
2038 + // Update mesh information
2039 + if (meshes[message.event.meshid] == null) {
2040 + // This is a new mesh for us
2041 + meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
2042 + meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
2043 + } else {
2044 + // This is an existing mesh
2045 + if (message.event.name != null) {
2046 + meshes[message.event.meshid].name = message.event.name;
2047 + for (var i in nodes) { if (nodes[i].meshid == message.event.meshid) { nodes[i].meshnamel = message.event.name.toLowerCase(); } }
2048 + }
2049 + if (message.event.desc != null) { meshes[message.event.meshid].desc = message.event.desc; }
2050 + if (message.event.flags != null) { meshes[message.event.meshid].flags = message.event.flags; }
2051 + if (message.event.consent != null) { meshes[message.event.meshid].consent = message.event.consent; }
2052 + if (message.event.links) { meshes[message.event.meshid].links = message.event.links; }
2053 + if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; }
2054 +
2055 + // Check if we lost rights to this mesh in this change.
2056 + if (meshes[message.event.meshid].links[userinfo._id] == null) {
2057 + if ((xxcurrentView == 20) && (currentMesh == meshes[message.event.meshid])) go(2);
2058 + delete meshes[message.event.meshid];
2059 +
2060 + // Delete all nodes in that mesh
2061 + var newnodes = [];
2062 + for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } }
2063 + nodes = newnodes;
2064 +
2065 + // If we are looking at a node in the deleted mesh, move back to "My Devices"
2066 + if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
2067 + }
2068 + }
2069 + masterUpdate(4 + 128);
2070 + if (currentNode && (currentNode.meshid == message.event.meshid)) { currentNode = null; if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } }
2071 + //meshserver.send({ action: 'files' }); // TODO: Why do we need to do this??
2072 +
2073 + // If we are looking at a mesh that is now deleted, move back to "My Account"
2074 + if (xxcurrentView == 20 && currentMesh._id == message.event.meshid) { masterUpdate(4096); }
2075 + break;
2076 + }
2077 + case 'deletemesh': {
2078 + // Delete the mesh
2079 + if (meshes[message.event.meshid]) {
2080 + delete meshes[message.event.meshid];
2081 + masterUpdate(128);
2082 + meshserver.send({ action: 'files' });
2083 + }
2084 +
2085 + // Delete all nodes in that mesh
2086 + var newnodes = [];
2087 + if (nodes != null) { for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } } }
2088 + nodes = newnodes;
2089 + masterUpdate(4);
2090 +
2091 + // If we are looking at a mesh that is now deleted, move back to "My Account"
2092 + if (xxcurrentView >= 20 && xxcurrentView < 30 && currentMesh._id == message.event.meshid) { setDialogMode(0); go(2); }
2093 + // If we are looking at a node in the deleted mesh, move back to "My Devices"
2094 + if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); }
2095 +
2096 + break;
2097 + }
2098 + case 'addnode': {
2099 + var node = message.event.node;
2100 + if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
2101 + if (getNodeFromId(node._id) != null) break; // This node is already known.
2102 + node.namel = node.name.toLowerCase();
2103 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
2104 + node.meshnamel = meshes[node.meshid].name.toLowerCase();
2105 + node.state = 0;
2106 + if (!node.icon) node.icon = 1;
2107 + node.ident = ++nodeShortIdent;
2108 + if (nodes == null) { }
2109 + nodes.push(node);
2110 +
2111 + // Web page update
2112 + masterUpdate(1 | 2 | 4 | 16);
2113 +
2114 + break;
2115 + }
2116 + case 'removenode': {
2117 + var index = -1;
2118 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
2119 + if (index != -1) {
2120 + var node = nodes[index];
2121 + if (currentNode == node) {
2122 + if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); }
2123 + currentNode = null;
2124 + // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
2125 + }
2126 + nodes.splice(index, 1);
2127 +
2128 + // Web page update
2129 + masterUpdate(4 | 16);
2130 + }
2131 + break;
2132 + }
2133 + case 'changenode': {
2134 + var index = -1;
2135 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
2136 + if (index != -1) {
2137 + var node = nodes[index];
2138 +
2139 + // Change the node
2140 + node.name = message.event.node.name;
2141 + node.rname = message.event.node.rname;
2142 + node.users = message.event.node.users;
2143 + node.host = message.event.node.host;
2144 + node.desc = message.event.node.desc;
2145 + node.ip = message.event.node.ip;
2146 + node.osdesc = message.event.node.osdesc;
2147 + node.publicip = message.event.node.publicip;
2148 + node.iploc = message.event.node.iploc;
2149 + node.wifiloc = message.event.node.wifiloc;
2150 + node.gpsloc = message.event.node.gpsloc;
2151 + node.tags = message.event.node.tags;
2152 + node.userloc = message.event.node.userloc;
2153 + if (message.event.node.agent != null) {
2154 + if (node.agent == null) node.agent = {};
2155 + if (message.event.node.agent.ver != null) { node.agent.ver = message.event.node.agent.ver; }
2156 + if (message.event.node.agent.id != null) { node.agent.id = message.event.node.agent.id; }
2157 + if (message.event.node.agent.caps != null) { node.agent.caps = message.event.node.agent.caps; }
2158 + if (message.event.node.agent.core != null) { node.agent.core = message.event.node.agent.core; } else { if (node.agent.core) { delete node.agent.core; } }
2159 + node.agent.tag = message.event.node.agent.tag;
2160 + }
2161 + if (message.event.node.intelamt != null) {
2162 + if (node.intelamt == null) node.intelamt = {};
2163 + if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; }
2164 + if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; }
2165 + if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; }
2166 + if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; }
2167 + if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; }
2168 + if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; }
2169 + if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; }
2170 + if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; }
2171 + }
2172 + if (message.event.node.av != null) { node.av = message.event.node.av; }
2173 + node.namel = node.name.toLowerCase();
2174 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
2175 + if (message.event.node.icon) { node.icon = message.event.node.icon; }
2176 +
2177 + // Web page update
2178 + masterUpdate(2 | 4 | 8 | 16);
2179 + refreshDevice(node._id);
2180 +
2181 + if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
2182 + }
2183 + break;
2184 + }
2185 + case 'nodemeshchange': {
2186 + var index = -1;
2187 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
2188 + if (index != -1) {
2189 + var node = nodes[index];
2190 + if (meshes[message.event.newMeshId] == null) {
2191 + // We don't see the new mesh, remove this device
2192 +
2193 + // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
2194 + if (currentNode == node) { if (xxcurrentView >= 10 && xxcurrentView < 20) { setDialogMode(0); go(1); } currentNode = null; }
2195 + nodes.splice(index, 1);
2196 + masterUpdate(4 | 16);
2197 + } else {
2198 + // We see the new mesh, move this device
2199 + node.meshid = message.event.newMeshId;
2200 + node.meshnamel = meshes[message.event.newMeshId].name.toLowerCase();
2201 + masterUpdate(1 | 2 | 4);
2202 + }
2203 + refreshDevice(message.event.nodeid);
2204 + } else {
2205 + // This is a new device, add it.
2206 + var node = message.event.node;
2207 + if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages.
2208 + node.namel = node.name.toLowerCase();
2209 + if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
2210 + node.meshnamel = meshes[node.meshid].name.toLowerCase();
2211 + node.state = 0;
2212 + if (!node.icon) node.icon = 1;
2213 + node.ident = ++nodeShortIdent;
2214 + if (nodes == null) { }
2215 + nodes.push(node);
2216 +
2217 + // Web page update
2218 + masterUpdate(1 | 2 | 4 | 16);
2219 + }
2220 + break;
2221 + }
2222 + case 'nodeconnect': {
2223 + // Indicated a node has changed connectivity state
2224 + var index = -1;
2225 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
2226 + if (index != -1) {
2227 + var node = nodes[index];
2228 +
2229 + // Event the connection change if needed
2230 + var n = getstore('notifications', 0); // Account notification settings
2231 +
2232 + // Per-group notification settings
2233 + if (message.event.meshid && userinfo.links && userinfo.links[message.event.meshid] && userinfo.links[message.event.meshid].notify) {
2234 + n &= userinfo.links[message.event.meshid].notify;
2235 + } else {
2236 + n = 0;
2237 + }
2238 +
2239 + // Show the notification
2240 + if (n & 2) {
2241 + if (((node.conn & 1) == 0) && ((message.event.conn & 1) != 0)) { addNotification({ text: "Agente conectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2242 + if (((node.conn & 2) == 0) && ((message.event.conn & 2) != 0)) { addNotification({ text: "Intel AMT detectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2243 + if (((node.conn & 4) == 0) && ((message.event.conn & 4) != 0)) { addNotification({ text: "Intel AMT CIRA conectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2244 + if (((node.conn & 16) == 0) && ((message.event.conn & 16) != 0)) { addNotification({ text: "MQTT conectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2245 + }
2246 + if (n & 4) {
2247 + if (((node.conn & 1) != 0) && ((message.event.conn & 1) == 0)) { addNotification({ text: "Agente desconectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2248 + if (((node.conn & 2) != 0) && ((message.event.conn & 2) == 0)) { addNotification({ text: "Intel AMT não detectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2249 + if (((node.conn & 4) != 0) && ((message.event.conn & 4) == 0)) { addNotification({ text: "Intel AMT CIRA desconectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2250 + if (((node.conn & 16) != 0) && ((message.event.conn & 16) == 0)) { addNotification({ text: "MQTT desconectado", title: node.name, icon: node.icon, nodeid: node._id }); }
2251 + }
2252 +
2253 + // Change the node connection state
2254 + node.conn = message.event.conn;
2255 + node.pwr = message.event.pwr;
2256 +
2257 + // Web page update
2258 + masterUpdate(4 | 16);
2259 + refreshDevice(node._id);
2260 + }
2261 + break;
2262 + }
2263 + case 'wssessioncount': {
2264 + // Update the active web socket session count for a user
2265 + if (wssessions != null) {
2266 + if (message.event.count == 0 && wssessions['user/' + domain + '/' + message.event.username.toLowerCase()]) {
2267 + delete wssessions['user/' + domain + '/' + message.event.username.toLowerCase()];
2268 + } else {
2269 + wssessions['user/' + domain + '/' + message.event.username.toLowerCase()] = message.event.count;
2270 + }
2271 + updateUsers();
2272 + }
2273 + break;
2274 + }
2275 + case 'login': {
2276 + // Update the last login time
2277 + if (users != null && users['user/' + domain + '/' + message.event.username.toLowerCase()]) {
2278 + users['user/' + domain + '/' + message.event.username.toLowerCase()].login = Math.floor(new Date(message.event.time).getTime() / 1000);
2279 + }
2280 + break;
2281 + }
2282 + case 'scanamtdevice': {
2283 + // Populate the Intel AMT scan dialog box with the result of the RMCP scan
2284 + if ((xxdialogMode == null) || (!Q('dp1range')) || (Q('dp1range').value != message.event.range)) return;
2285 + var x = '';
2286 + if (message.event.results == null) {
2287 + // The scan could not occur because of an error. Likely the user range was invalid.
2288 + x = '<div style=width:100%;text-align:center;margin-top:12px>' + "Não foi possível verificar este intervalo de endereços." + '</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Valores de intervalo de IP de amostra<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100" + '</div>';
2289 + } else {
2290 + // Go thru all the results and populate the dialog box
2291 + amtScanResults = message.event.results;
2292 + for (var i in message.event.results) {
2293 + var r = message.event.results[i], shortname = r.hostname;
2294 + if (shortname.length > 20) { shortname = shortname.substring(0, 20) + '...'; }
2295 + var str = '<b title="' + EscapeHtml(r.hostname) + '">' + EscapeHtml(shortname) + '</b> - v' + r.ver;
2296 + if (r.state == 2) { if (r.tls == 1) { str += "com TLS."; } else { str += "sem TLS."; } } else { str += ' not activated.'; }
2297 + x += '<div style=width:100%;margin-bottom:2px;background-color:lightgray><div style=padding:4px><div style=display:inline-block;margin-right:5px><input class=DevScanCheckbox name=dp1checkbox tag="' + EscapeHtml(i) + '" type=checkbox onclick=addAmtScanToMeshCheckbox() /></div><div class=j1 style=display:inline-block></div><div style=display:inline-block;margin-left:5px;overflow-x:auto;white-space:nowrap>' + str + '</div></div></div>';
2298 + }
2299 + // If no results where found, display a nice message
2300 + if (x == '') { x = '<div style=width:100%;text-align:center;margin-top:12px>Scan returned no results.</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100</div>'; }
2301 + }
2302 + // Set the html in the dialog box and re-enable the scan button
2303 + QH('dp1results', x);
2304 + QE('dp1range', true);
2305 + QE('dp1rangebutton', true);
2306 + break;
2307 + }
2308 + case 'notify': {
2309 + var n = { text: message.event.value, title: message.event.title, icon: message.event.icon };
2310 + if (message.event.tag != null) { n.tag = message.event.tag; }
2311 + addNotification(n);
2312 + break;
2313 + }
2314 + case 'traceinfo': {
2315 + if (typeof message.event.traceSources == 'object') {
2316 + if ((message.event.traceSources != null) && (message.event.traceSources.length > 0)) {
2317 + serverTraceSources = message.event.traceSources;
2318 + QH('p41traceStatus', EscapeHtml(message.event.traceSources.join(', ')));
2319 + } else {
2320 + serverTraceSources = [];
2321 + QH('p41traceStatus', "Nenhum");
2322 + }
2323 + }
2324 + break;
2325 + }
2326 + case 'sysinfohash': {
2327 + // If the sysinfo document has changed and we are looking at it, request an update.
2328 + if ((currentNode != null) && (message.event.nodeid == powerTimelineReq)) {
2329 + meshserver.send({ action: 'getsysinfo', nodeid: message.event.nodeid });
2330 + }
2331 + break;
2332 + }
2333 + case 'stopped': { // Server is stopping.
2334 + // Disconnect
2335 + //console.log(message.msg);
2336 + break;
2337 + }
2338 + case 'updatePluginList': {
2339 + installedPluginList = message.event.list;
2340 + updatePluginList();
2341 + break;
2342 + }
2343 + case 'pluginStateChange': {
2344 + if (pluginHandler == null) break;
2345 + pluginHandler.refreshPluginHandler();
2346 + break;
2347 + }
2348 + default:
2349 + //console.log('Unknown message.event.action', message.event.action);
2350 + break;
2351 + }
2352 + break;
2353 + }
2354 + case 'createInviteLink': { // Agent installation invitation link
2355 + if (xxdialogTag != message.meshid) break;
2356 + var servername = serverinfo.name;
2357 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
2358 + var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2359 + var url;
2360 + if (serverinfo.https == true) {
2361 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2362 + url = 'https://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
2363 + } else {
2364 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2365 + url = 'http://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
2366 + }
2367 + Q('agentInvitationLink').href = url;
2368 + var t = format("{0} horas{1}", message.expire, addLetterS(message.expire));
2369 + if (message.expire == 24) { t = "1 dia"; }
2370 + if (message.expire == 168) { t = "1 semana"; }
2371 + if (message.expire == 5040) { t = "1 mês"; }
2372 + if (message.expire == 0) { t = "Ilimitado"; }
2373 + QH('agentInvitationLink', format("Link de convite ({0})", t));
2374 + QV('agentInvitationLinkDiv', true);
2375 + break;
2376 + }
2377 + case 'getmqttlogin': {
2378 + if ((currentNode == null) || (currentNode._id != message.nodeid) || (xxdialogMode != null)) return;
2379 + var x = "Essas configurações podem ser usadas para conectar o MQTT a este dispositivo." + '<br /><br />';
2380 + delete message.action;
2381 + delete message.nodeid;
2382 + x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>' + JSON.stringify(message) + '</textarea>';
2383 + /*
2384 + x += addHtmlValue('Username', '<input style=width:230px readonly value="' + message.user + '" />');
2385 + x += addHtmlValue('Password', '<input style=width:230px readonly value="' + message.pass + '" />');
2386 + x += addHtmlValue('WS URL', '<input style=width:230px readonly value="' + message.wsUrl + '" />');
2387 + if (message.mpsUrl && message.mpsCertHash) {
2388 + x += addHtmlValue('MPS URL', '<input style=width:230px readonly value="' + message.mpsUrl + '" />');
2389 + x += addHtmlValue('MPS Cert Hash', '<input style=width:230px readonly value="' + message.mpsCertHash + '" />');
2390 + }
2391 + */
2392 + setDialogMode(2, "Credenciais MQTT", 1, null, x);
2393 + break;
2394 + }
2395 + case 'stopped': { // Server is stopping.
2396 + // Disconnect
2397 + autoReconnect = false;
2398 + QH('p0span', message.msg);
2399 + break;
2400 + }
2401 + case 'updatePluginList': {
2402 + installedPluginList = message.list;
2403 + updatePluginList();
2404 + break;
2405 + }
2406 + case 'pluginVersionsAvailable': {
2407 + if (pluginHandler == null) break;
2408 + updatePluginList(message.list);
2409 + break;
2410 + }
2411 + case 'downgradePluginVersions': {
2412 + var vSelect = '<select id="lastPluginVersion">';
2413 + message.info.versionList.forEach(function(v) { vSelect += '<option value="' + v.zipball_url + '">' + v.name + '</option>'; });
2414 + vSelect += '</select>';
2415 + setDialogMode(2, "Plugin Action", 3, pluginActionEx, format('Select the version to downgrade the plugin: {0}', message.info.name) + '<hr />' + vSelect + '<hr />' + "Please be aware that downgrading is not recommended. Please only do so in the event that a recent upgrade has broken something." + + '<input id="lastPluginAct" type="hidden" value="downgrade" /><input id="lastPluginId" type="hidden" value="' + message.info.id + '" />');
2416 + break;
2417 + }
2418 + case 'pluginError': {
2419 + setDialogMode(2, "Plugin Error", 1, null, message.msg);
2420 + break;
2421 + }
2422 + case 'plugin': {
2423 + if ((pluginHandler == null) || (typeof message.plugin != 'string')) break;
2424 + try { pluginHandler[message.plugin][message.method](server, message); } catch (e) { console.log('Error loading plugin handler ('+ e + ')'); }
2425 + break;
2426 + }
2427 + default:
2428 + //console.log('Unknown message.action', message.action);
2429 + break;
2430 + }
2431 + }
2432 +
2433 + //
2434 + // MY DEVICES
2435 + //
2436 +
2437 + function onRealNameCheckBox() {
2438 + showRealNames = Q('RealNameCheckBox').checked;
2439 + putstore('showRealNames', showRealNames ? 1 : 0);
2440 + masterUpdate(6);
2441 + return;
2442 + }
2443 +
2444 + function onDeviceViewChange(i) {
2445 + if (i != null) { Q('viewselect').value = i; }
2446 + for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
2447 + Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
2448 + putstore('_deviceView', Q('viewselect').value);
2449 + putstore('_viewsize', Q('sizeselect').value);
2450 + masterUpdate(4);
2451 + setTimeout(function () { masterUpdate(512); }, 200);
2452 + }
2453 +
2454 + function ondockeypress(e) {
2455 + setSessionActivity();
2456 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
2457 + // Check what keys we are allows to send
2458 + if (currentNode != null) {
2459 + var mesh = meshes[currentNode.meshid];
2460 + var meshrights = mesh.links[userinfo._id].rights;
2461 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
2462 + if (inputAllowed == false) return false;
2463 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
2464 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
2465 + }
2466 + return desktop.m.handleKeys(e);
2467 + }
2468 + if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeys(e); }
2469 + if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) return agentConsoleHandleKeys(e);
2470 + if (!xxdialogMode && xxcurrentView == 4) {
2471 + if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
2472 + var processed = 0;
2473 + if (e.key) {
2474 + if (e.key.length === 1 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + e.key)); processed = 1; }
2475 + if (e.keyCode == 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = x.substring(0, x.length - 1); processed = 1; }
2476 + if (e.keyCode == 27) { Q('UserSearchInput').value = ''; processed = 1; }
2477 + } else {
2478 + if (e.charCode != 0 && userSearchFocus == 0) { Q('UserSearchInput').value = ((Q('UserSearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
2479 + }
2480 + if (processed > 0) { if (processed == 1) { onUserSearchInputChanged(); } return haltEvent(e); }
2481 + }
2482 + if (xxdialogMode || xxcurrentView != 1) return;
2483 + if (e.ctrlKey == true && e.charCode == 96) {
2484 + showRealNames = !showRealNames;
2485 + Q('RealNameCheckBox').value = showRealNames;
2486 + putstore('showRealNames', showRealNames ? 1 : 0);
2487 + masterUpdate(6)
2488 + return;
2489 + }
2490 + if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
2491 + if (Q('viewselect').value < 3) {
2492 + var processed = 0;
2493 + if (e.key) {
2494 + if (e.key.length === 1 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + e.key)); processed = 1; }
2495 + if (e.keyCode == 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = x.substring(0, x.length - 1); processed = 1; }
2496 + if (e.keyCode == 27) { Q('SearchInput').value = ''; processed = 1; }
2497 + } else {
2498 + if (e.charCode != 0 && searchFocus == 0) { Q('SearchInput').value = ((Q('SearchInput').value + String.fromCharCode(e.charCode))); processed = 1; }
2499 + }
2500 + if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
2501 + }
2502 + if (Q('viewselect').value == 3) {
2503 + if (e.key) {
2504 + if (e.key.length === 1 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + e.key)); processed = 1; }
2505 + //if (e.keyCode == 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = x.substring(0, x.length - 1); processed = 1; }
2506 + if (e.keyCode == 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
2507 + if (e.keyCode == 13) { getSearchLocation(); }
2508 + } else {
2509 + if (e.charCode != 0 && mapSearchFocus == 0) { Q('mapSearchLocation').value = ((Q('mapSearchLocation').value + String.fromCharCode(e.charCode))); processed = 1; }
2510 + }
2511 + }
2512 + }
2513 +
2514 + function ondockeydown(e) {
2515 + setSessionActivity();
2516 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
2517 + // Check what keys we are allows to send
2518 + if (currentNode != null) {
2519 + var mesh = meshes[currentNode.meshid];
2520 + var meshrights = mesh.links[userinfo._id].rights;
2521 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
2522 + if (inputAllowed == false) return false;
2523 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
2524 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
2525 + }
2526 + return desktop.m.handleKeyDown(e);
2527 + }
2528 + if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { terminal.m.TermHandleKeyDown(e); if ((e.keyCode >= 37) && (e.keyCode <= 40)) { haltEvent(e); } }
2529 + if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { haltEvent(e); return false; } // F5 Refresh on files
2530 + if (!xxdialogMode && ((xxcurrentView == 15) || (xxcurrentView == 115))) { return agentConsoleHandleKeys(e); }
2531 + if (!xxdialogMode && xxcurrentView == 4) {
2532 + if (e.keyCode === 8 && userSearchFocus == 0) { var x = Q('UserSearchInput').value; Q('UserSearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
2533 + if (e.keyCode === 27) { Q('UserSearchInput').value = ''; processed = 1; }
2534 + if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
2535 + }
2536 + if (xxdialogMode || xxcurrentView != 1 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
2537 + var processed = 0;
2538 + if (Q('viewselect').value < 3) {
2539 + if (e.keyCode === 8 && searchFocus == 0) { var x = Q('SearchInput').value; Q('SearchInput').value = (x.substring(0, x.length - 1)); processed = 1; }
2540 + if (e.keyCode === 27) { Q('SearchInput').value = ''; processed = 1; }
2541 + if (processed > 0) { if (processed == 1) { masterUpdate(5); } return haltEvent(e); }
2542 + }
2543 + if (Q('viewselect').value == 3) {
2544 + if (e.keyCode === 8 && mapSearchFocus == 0) { var x = Q('mapSearchLocation').value; Q('mapSearchLocation').value = (x.substring(0, x.length - 1)); processed = 1; }
2545 + if (e.keyCode === 27) { Q('mapSearchLocation').value = ''; mapCloseSearchWindow(); processed = 1; }
2546 + }
2547 + }
2548 +
2549 + function ondockeyup(e) {
2550 + setSessionActivity();
2551 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
2552 + // Check what keys we are allows to send
2553 + if (currentNode != null) {
2554 + var mesh = meshes[currentNode.meshid];
2555 + var meshrights = mesh.links[userinfo._id].rights;
2556 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
2557 + if (inputAllowed == false) return false;
2558 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
2559 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
2560 + }
2561 + return desktop.m.handleKeyUp(e);
2562 + }
2563 + if (!xxdialogMode && xxcurrentView == 12 && terminal && terminal.State == 3) { return terminal.m.TermHandleKeyUp(e); }
2564 + if (!xxdialogMode && xxcurrentView == 13 && e.keyCode == 116 && p13filetree != null) { p13folderup(9999); haltEvent(e); return false; } // F5 Refresh on files
2565 + if (!xxdialogMode && xxcurrentView == 4) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
2566 + if (xxdialogMode && e.keyCode == 27) { dialogclose(0); }
2567 + if (xxdialogMode || xxcurrentView != 0 || e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
2568 + if (Q('viewselect').value < 3) { if ((e.keyCode === 8 && searchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
2569 + if (Q('viewselect').value == 3) { if ((e.keyCode === 8 && mapSearchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
2570 + }
2571 +
2572 + //function ondocfocus() { }
2573 + // TODO: Add handleReleaseKeys() for Intel AMT.
2574 + function ondocblur() { if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked && desktop.m.handleReleaseKeys) { return desktop.m.handleReleaseKeys(); } }
2575 +
2576 + // Highlights the device being hovered
2577 + function devMouseHover(element, over) {
2578 + setSessionActivity();
2579 + var view = Q('viewselect').value;
2580 + if (view == 1) {
2581 + var e = element.children[1].children[1];
2582 + e.children[0].classList.remove('g1s');
2583 + e.children[1].classList.remove('e2s');
2584 + e.children[2].classList.remove('g2s');
2585 + if (over == 1) {
2586 + e.children[0].classList.add('g1s');
2587 + e.children[1].classList.add('e2s');
2588 + e.children[2].classList.add('g2s');
2589 + }
2590 + } else if (view == 2) {
2591 + var e = element;
2592 + e.children[2].classList.remove('g1s');
2593 + e.children[4].classList.remove('e2s');
2594 + e.children[3].classList.remove('g2s');
2595 + if (over == 1) {
2596 + e.children[2].classList.add('g1s');
2597 + e.children[4].classList.add('e2s');
2598 + e.children[3].classList.add('g2s');
2599 + }
2600 + }
2601 + }
2602 +
2603 + var deviceHeaderId = 0;
2604 + var deviceHeaderTotal = 0;
2605 + var deviceHeadersTitles = {};
2606 + var deviceHeaderCount;
2607 + var deviceHeaders = {};
2608 + var oldviewmode = 0;
2609 + function updateDevices() {
2610 + if (nodes == null) { return; }
2611 + var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
2612 + QV('xdevices', view < 4);
2613 + QV('xdevicesmap', view == 4);
2614 + QV('devListToolbar', view < 3);
2615 + QV('kvmListToolbar', view == 3);
2616 + QV('devMapToolbar', view == 4);
2617 + QV('devListToolbarSize', view == 3);
2618 + QV('NoMeshesPanel', meshcount == 0);
2619 + //QV('devListToolbarView', (meshcount != 0) && (nodes.length > 0));
2620 + QV('devListToolbarViewIcons', (meshcount != 0) && (nodes.length > 0));
2621 + QV('devListToolbarSort', (meshcount != 0) && (nodes.length > 0) && (view < 4));
2622 + if ((meshcount == 0) || (nodes.length == 0)) { view = 1; sort = 0; }
2623 + if (view == 4) {
2624 + setTimeout( function() { if (xxmap.map != null) { xxmap.map.updateSize(); } }, 200);
2625 + // TODO
2626 + } else {
2627 + // 3 wide, list view or desktop view
2628 + deviceHeaderId = 0;
2629 + deviceHeaderCount = {};
2630 + deviceHeaderTotal = 0;
2631 + deviceHeaders = {};
2632 + deviceHeadersTitles = {};
2633 + var kvmDivs = [];
2634 +
2635 + // Perform node sort
2636 + if (sort == 0) { nodes.sort(meshSort); }
2637 + else if (sort == 1) { nodes.sort(powerSort); }
2638 + else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
2639 +
2640 + // Save the list of currently checked nodeid's
2641 + var checkedNodeids = [], elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
2642 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
2643 + if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
2644 + else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
2645 +
2646 + // Compute the width of the device view.
2647 + var totalDeviceViewWidth = Q('column_l').clientWidth - 60;
2648 + var deviceBoxWidth = Math.floor(totalDeviceViewWidth / 301);
2649 + deviceBoxWidth = 301 + Math.floor((totalDeviceViewWidth - (deviceBoxWidth * 301)) / deviceBoxWidth);
2650 +
2651 + if ((view == 2) && (sort != 3)) {
2652 + r += '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>' + "Do utilizador" + '<th style=color:gray;width:120px>' + "Endereço" + '<th style=color:gray;width:100px>' + "Conectividade"; //<th style=color:gray;width:100px>State';
2653 + }
2654 +
2655 + // Go thru the list of nodes and display them
2656 + for (var i in nodes) {
2657 + var node = nodes[i];
2658 + if (node.v == false) continue;
2659 + var mesh2 = meshes[node.meshid], meshlinks = mesh2.links[userinfo._id];
2660 + if (meshlinks == null) continue;
2661 + var meshrights = meshlinks.rights;
2662 + if ((view == 3) && (mesh2.mtype == 1)) continue;
2663 + if (sort == 0) {
2664 + // Mesh header
2665 + if (node.meshid != current) {
2666 + deviceHeaderSet();
2667 + var extra = '';
2668 + if (view == 2) { r += '<tr><td colspan=5>'; }
2669 + if (meshes[node.meshid].mtype == 1) { extra = '<span class=devHeaderx>' + "Intelreg; " + '</span>'; }
2670 + if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
2671 + if (view == 2) { r += '<div>'; }
2672 + r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
2673 + r += '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span>' + extra;
2674 + r += '</span><span id=MxMESH tabindex=0 style=cursor:pointer onclick=gotoMesh("' + node.meshid + '") onkeypress="if (event.key==\'Enter\') gotoMesh(\'' + node.meshid + '\')">' + EscapeHtml(meshes[node.meshid].name) + '</span>' + getMeshActions(mesh2, meshrights) + '</div>';
2675 + if (view == 2) { r += '</div>'; }
2676 + current = node.meshid;
2677 + displayedMeshes[current] = 1;
2678 + c = 0;
2679 + }
2680 + } else if (sort == 1) {
2681 + // Power header
2682 + var pwr = node.pwr?node.pwr:0;
2683 + if (pwr !== current) {
2684 + deviceHeaderSet();
2685 + if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
2686 +
2687 + if (view == 2) { r += '<tr><td>'; }
2688 + r += '<div class=DevSt style=width:100%;padding-top:4px><span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx style=float:right></span><span>' + PowerStateStr2(node.pwr) + '</span></div>';
2689 +
2690 + current = pwr;
2691 + c = 0;
2692 + }
2693 + } else if (sort == 2) {
2694 + // Device header
2695 + if (current == null) { current = '1'; }
2696 + }
2697 +
2698 + count++;
2699 + var title = EscapeHtml(node.name);
2700 + if (title.length == 0) { title = '<i>' + "Nenhum" + '</i>'; }
2701 + if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
2702 + var name = EscapeHtml(node.name);
2703 + if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
2704 + if (name.length == 0) { name = '<i>' + "Nenhum" + '</i>'; }
2705 +
2706 + // Node
2707 + var icon = node.icon;
2708 + if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
2709 + if (view == 1) {
2710 + r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer tabindex=0 onclick=gotoDevice(\'' + node._id + '\',null,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)"><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div></div>';
2711 + } else if (view == 2) {
2712 + var states = [];
2713 + if (node.conn) {
2714 + if ((node.conn & 1) != 0) { states.push('<span title=\"' + "O agente de malha está conectado e pronto para uso." + '\">' + "Agente" + '</span>'); }
2715 + if ((node.conn & 2) != 0) { states.push('<span title=\"' + "Intel&reg; O AMT CIRA está conectado e pronto para uso." + '\">' + "CIRA" + '</span>'); }
2716 + else if ((node.conn & 4) != 0) { states.push('<span title=\"' + "Intel&reg; AMT é roteável." + '\">' + "AMT" + '</span>'); }
2717 + if ((node.conn & 8) != 0) { states.push('<span title=\"' + "O agente de malha é alcançável usando outro agente como retransmissão." + '\">' + "Retransmissão" + '</span>'); }
2718 + if ((node.conn & 16) != 0) { states.push('<span title=\"' + "A conexão MQTT com o dispositivo está ativa." + '\">' + "MQTT" + '</span>'); }
2719 + }
2720 + r += '<tr><td><div id=devs class=bar18 tabindex=0 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)">';
2721 + r += '<div class=deviceBarCheckbox><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div>';
2722 + r += '<div class=deviceBarIcon onclick=gotoDevice(\'' + node._id + '\',null,null,event)><div class=\"j' + icon + '\" style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
2723 + r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
2724 + r += '<div style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + node._id + '\',null,null,event)><span style=width:300px>' + name + '</span></div></div></td>';
2725 + r += '<td style=text-align:center>' + getUserShortStr(node);
2726 + r += '<td style=text-align:center>' + (node.ip != null ? node.ip : '');
2727 + r += '<td style=text-align:center>' + states.join('&nbsp;+&nbsp;');
2728 + //r += '<td style=text-align:center>' + (node.pwr != null ? powerStateStrings[node.pwr] : '');
2729 + r += '</tr>';
2730 + } else if ((view == 3) && (node.conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((node.agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
2731 + if ((multiDesktopFilter) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + node._id) >= 0))) {
2732 + r += '<div id=devs style=display:inline-block;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div tabindex=0 style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + node._id + '\',11,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',11,null,event)">';
2733 + //r += '<input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox style=float:left>';
2734 + r += '<div class="j' + icon + '" style=width:16px;float:left></div>&nbsp;' + name + '</div>';
2735 + r += '<span onclick=gotoDevice(\'' + node._id + '\',null,null,event)></span><div id=xkvmid_' + node._id.split('/')[2] + '><div id=skvmid_' + node._id.split('/')[2] + ' tabindex=0 style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + node._id + '\') onkeypress="if (event.key==\'Enter\') toggleKvmDevice(\'' + node._id + '\')">' + "Desconectado" + '</div></div>';
2736 + r += '</div>';
2737 + kvmDivs.push(node._id);
2738 + }
2739 + }
2740 +
2741 + // If we are displaying devices by group, put the device in the right group.
2742 + if ((sort == 3) && (r != '')) {
2743 + if (node.tags) {
2744 + for (var j in node.tags) {
2745 + var tag = node.tags[j];
2746 + if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
2747 + if (view == 3) break;
2748 + }
2749 + }
2750 + r = '';
2751 + }
2752 +
2753 + deviceHeaderTotal++;
2754 + if (typeof deviceHeaderCount[node.state] == 'undefined') { deviceHeaderCount[node.state] = 1; } else { deviceHeaderCount[node.state]++; }
2755 + }
2756 +
2757 + // Above 32 devices, gray out the auto connect feature.
2758 + if (kvmDivs.length >= 32) { Q('autoConnectDesktopCheckbox').checked = false; }
2759 + QE('autoConnectDesktopCheckbox', kvmDivs.length < 32);
2760 +
2761 + // If displaying devices by groups, sort the group names and display the devices.
2762 + if (sort == 3) {
2763 + if (view == 2) { r = '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>' + "Do utilizador" + '<th style=color:gray;width:120px>' + "Endereço" + '<th style=color:gray;width:100px>' + "Conectividade"; }
2764 +
2765 + var groupNames = [];
2766 + for (var i in groups) { groupNames.push(i); }
2767 + groupNames.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
2768 + for (var j in groupNames) {
2769 + var i = groupNames[j];
2770 + if (view == 2) {
2771 + r += '<tr><td colspan=4><div class=DevSt style=width:100%;padding-top:4px><span class=devHeaderx style=float:right>' + groupCount[i] + ' node' + ((groupCount[i] > 1) ? 's' : '') + '</span><span>' + i + '</span></div>' + groups[i];
2772 + } else {
2773 + r += '<div class=DevSt style=width:100%;padding-top:4px><span class=devHeaderx style=float:right>' + groupCount[i] + ' node' + ((groupCount[i] > 1) ? 's' : '') + '</span><span>' + i + '</span></div>' + groups[i];
2774 + }
2775 + }
2776 + }
2777 +
2778 + // If there is nothing to display, explain the problem
2779 + if ((r == '') && (meshcount > 0) && (Q('SearchInput').value != '')) {
2780 + if (sort == 3) {
2781 + r = '<div style="margin:30px">' + "Nenhum dispositivo está incluído em nenhum grupo, clique no \"Grupo\" de um dispositivo para adicionar a um grupo" + '</div>';
2782 + } else {
2783 + r = '<div style="margin:30px">' + "Nenhum dispositivo correspondente a esta pesquisa." + '</div>';
2784 + }
2785 + }
2786 +
2787 + if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
2788 +
2789 + // Display all empty device groups, we need to do this because users can add devices to these at any time.
2790 + if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) {
2791 + for (var i in meshes) {
2792 + var mesh = meshes[i], meshlink = mesh.links[userinfo._id];
2793 + if (meshlink != null) {
2794 + var meshrights = meshlink.rights;
2795 + if (displayedMeshes[mesh._id] == null) {
2796 + if ((current != '') && (r != '')) { r += '</tr></table>'; }
2797 + r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span><span>';
2798 + r += getMeshActions(mesh, meshrights);
2799 + r += '</span></td></tr><tr>';
2800 + if (mesh.mtype == 1) {
2801 + r += '<td><div style=padding:10px><i>' + "Nenhum Intel&reg; dispositivos AMT nessa malha";
2802 + if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "Adicione um" + '</a>'; }
2803 + }
2804 + if (mesh.mtype == 2) {
2805 + r += '<td><div style=padding:10px><i>' + "Nenhum dispositivo neste grupo";
2806 + if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "Adicione um" + '</a>'; }
2807 + }
2808 + r += '.</i></div></td>';
2809 + current = mesh._id;
2810 + count++;
2811 + }
2812 + }
2813 + }
2814 + }
2815 + r += '</tr></table><div style=height:1px></div>'; // This height of 1 div fixes a problem in Linux firefox browsers
2816 +
2817 + // Add a "Add Device Group" option
2818 + r += '<div style=border-top-style:solid;border-top-width:1px;border-top-color:#DDDDDD;cursor:pointer;font-size:10px>';
2819 + if ((view < 3) && (sort == 0) && (meshcount > 0) && ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 64) == 0))) {
2820 + r += '<a href=# onclick="return account_createMesh()" title=\"' + "Crie um novo grupo de dispositivos." + '\" style=cursor:pointer>' + "Adicionar grupo de dispositivos" + '</a>&nbsp';
2821 + }
2822 + if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 128) == 0)) {
2823 + r += '<a href=# onclick=\'return p10showMeshCmdDialog(0)\' style=cursor:pointer title=\"' + "Faça o download do MeshCmd, uma ferramenta de linha de comando que executa muitas funções." + '\">' + "MeshCmd" + '</a>&nbsp';
2824 + if (navigator.platform.toLowerCase() == 'win32') { r += '<a href=# onclick=\'return p10showMeshRouterDialog()\' style=cursor:pointer title=\"' + "Faça o download do MeshCentral Router, uma ferramenta de mapeamento de portas TCP." + '\">' + "Roteador" + '</a>&nbsp'; }
2825 + }
2826 + r += '</div><br/>';
2827 +
2828 + QH('xdevices', r);
2829 + deviceHeaderSet();
2830 +
2831 + // Re-check nodeid's
2832 + var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
2833 + if (checkedNodeids) { for (var i=0;i<elements.length;i++) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); } }
2834 +
2835 + for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
2836 + for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
2837 + p1updateInfo();
2838 +
2839 + // Take care of KVM surfaces in desktop view mode
2840 + if (view == 3) {
2841 + // Figure out and adjust the size to fill the width of the div
2842 + var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
2843 + //var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
2844 + var realw = vsize.x + 2, tw = totalDeviceViewWidth - 5, xw = Math.floor(tw / realw);
2845 + xw = realw + Math.floor((tw - (xw * realw)) / xw);
2846 + vsize.y = vsize.y * (xw / vsize.x);
2847 + vsize.x = xw;
2848 +
2849 + for (var i in multiDesktop) { multiDesktop[i].xxdelete = true; }
2850 + for (var i in kvmDivs) {
2851 + var id = kvmDivs[i], shortid = id.split('/')[2], desk = multiDesktop[id];
2852 + if (desk != null) {
2853 + // This device already has a canvas, use it.
2854 + desk.m.CanvasId.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
2855 + Q('xkvmid_' + shortid).appendChild(desk.m.CanvasId);
2856 + delete desk.xxdelete;
2857 + QH('skvmid_' + shortid, ["Desconectado", "Conectando...", "Configurando...", '', ''][((desk.m.State == null)?desk.m.state:desk.m.State)]);
2858 + } else {
2859 + var node = getNodeFromId(id);
2860 + if ((desktopNode == node) && (desktop != null)) { // Check if the main desktop is this device, if it is, use that.
2861 + // This device already has a canvas, use it.
2862 + var c = desktop.m.CanvasId;
2863 + c.setAttribute('id', 'kvmid_' + shortid);
2864 + c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
2865 + c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
2866 + c.removeAttribute('onmousedown');
2867 + c.removeAttribute('onmouseup');
2868 + c.removeAttribute('onmousemove');
2869 + Q('xkvmid_' + shortid).appendChild(c);
2870 + QH('skvmid_' + shortid, ["Desconectado", "Conectando...", "Configurando...", '', ''][((desktop.m.State == null)?desktop.m.state:desktop.m.State)]);
2871 + if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
2872 + desktop.shortid = shortid;
2873 + desktop.onStateChanged = onMultiDesktopStateChange;
2874 + multiDesktop[id] = desktop;
2875 + desktop = desktopNode = currentNode = null;
2876 + // Setup a replacement desktop
2877 + QH('DeskParent', '<canvas id="Desk" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
2878 + } else {
2879 + // This is a new device, create a canvas for it.
2880 + var c = document.createElement('canvas');
2881 + c.setAttribute('id', 'kvmid_' + shortid);
2882 + c.setAttribute('width', 640);
2883 + c.setAttribute('height', 480);
2884 + c.setAttribute('oncontextmenu', 'return false');
2885 + c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
2886 + c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
2887 + try { Q('xkvmid_' + shortid).appendChild(c); } catch (ex) {}
2888 + // Check if we need to auto-connect
2889 + if (Q('autoConnectDesktopCheckbox').checked == true) { setTimeout(function() { connectMultiDesktop(node, 1); }, 100); }
2890 + }
2891 + }
2892 + }
2893 + for (var i in multiDesktop) {
2894 + // If a device is no longer viewed, disconnect it.
2895 + if (multiDesktop[i].xxdelete == true) { multiDesktop[i].Stop(); delete multiDesktop[i]; }
2896 + else if (debugmode && multiDesktop[i].m && multiDesktop[i].m.onScreenSizeChange) {
2897 + mdeskAdjust(multiDesktop[i].m, multiDesktop[i].m.ScreenWidth, multiDesktop[i].m.ScreenHeight, multiDesktop[i].m.CanvasId); // Adjust screen size change
2898 + }
2899 + }
2900 + deskAdjust();
2901 + } else {
2902 + disconnectAllKvmFunction();
2903 + Q('autoConnectDesktopCheckbox').checked = false;
2904 + }
2905 + }
2906 + oldviewmode = view;
2907 + }
2908 +
2909 + function toggleKvmDevice(node) {
2910 + if (typeof node == 'string') { node = getNodeFromId(node); } // Convert nodeid to node if needed
2911 + var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
2912 + if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
2913 + //var conn = 0;
2914 + //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
2915 + if (node.conn & 1) { connectMultiDesktop(node, 1); }
2916 + }
2917 + }
2918 +
2919 + function getUserShortStr(node) {
2920 + if (node == null || node.users == null || node.users.length == 0) return '';
2921 + if (node.users.length > 1) { return '<span title="' + EscapeHtml(node.users.join(', ')) + '">' + nobreak(format("{0} usuários", node.users.length)) + '</span>'; }
2922 + var u = node.users[0], su = u, i = u.indexOf('\\');
2923 + if (i > 0) { su = u.substring(i + 1); }
2924 + su = EscapeHtml(su);
2925 + if (su.length > 15) { su = su.substring(0, 14) + '&#8230;'; }
2926 + return '<span title="' + EscapeHtml(u) + '">' + su + '</span>';
2927 + }
2928 +
2929 + function autoConnectDesktops() { if (Q('autoConnectDesktopCheckbox').checked == true) { connectAllKvmFunction(); } }
2930 + function connectAllKvmFunction(force) {
2931 + if (xxdialogMode) return false;
2932 + if (force !== true) { // We need to count how many devices will need to be connected, if it's a lot, prompt first.
2933 + var count = 0;
2934 + for (var i in nodes) {
2935 + var node = nodes[i], nodeid = nodes[i]._id;
2936 + if (multiDesktop[nodeid] == null) {
2937 + var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
2938 + if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
2939 + //var conn = 0;
2940 + //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
2941 + if (node.conn & 1) { count++; }
2942 + }
2943 + }
2944 + }
2945 + if (count > 8) { setDialogMode(2, "Conectar todos", 3, function() { connectAllKvmFunction(true); }, format("Are you sure you want to connect to {0} devices?", count)); return; }
2946 + }
2947 +
2948 + // Perform connect all
2949 + for (var i in nodes) { if (multiDesktop[nodes[i]._id] == null) { toggleKvmDevice(nodes[i]._id); } }
2950 + }
2951 + function disconnectAllKvmFunction() { if (xxdialogMode) return false; for (var nodeid in multiDesktop) { multiDesktop[nodeid].Stop(); } multiDesktop = {}; }
2952 + function onMultiDesktopStateChange(desk, state) { try { QH('skvmid_' + desk.shortid, ["Desconectado", "Conectando...", "Configurando...", '', ''][state]); } catch (ex) {} }
2953 +
2954 + function showMultiDesktopSettings() {
2955 + QV('d7amtkvm', false);
2956 + QV('d7meshkvm', true);
2957 + d7bitmapquality.value = multidesktopsettings.quality;
2958 + d7bitmapscaling.value = multidesktopsettings.scaling;
2959 + if (multidesktopsettings.framerate) { d7framelimiter.value = multidesktopsettings.framerate; } else { d7framelimiter.value = 1000; }
2960 + setDialogMode(7, "Configurações da área de trabalho remota", 3, showMultiDesktopSettingsChanged);
2961 + }
2962 +
2963 + function showMultiDesktopSettingsChanged() {
2964 + multidesktopsettings.quality = d7bitmapquality.value;
2965 + multidesktopsettings.scaling = d7bitmapscaling.value;
2966 + multidesktopsettings.framerate = d7framelimiter.value;
2967 + localStorage.setItem('multidesktopsettings', JSON.stringify(multidesktopsettings));
2968 + // Make changes to all current connections
2969 + for (var i in multiDesktop) { multiDesktop[i].m.SendCompressionLevel(1, multidesktopsettings.quality, multidesktopsettings.scaling, multidesktopsettings.framerate); }
2970 + }
2971 +
2972 + function connectMultiDesktop(node, contype) {
2973 + var nodeid = node._id, shortid = nodeid.split('/')[2];
2974 + var desk = multiDesktop[nodeid];
2975 + if (desk == null) {
2976 + if (Q('kvmid_' + shortid) == null) return; // Check if this device is being displayed, if not, exit now.
2977 + if (contype == 2) {
2978 + // Setup the Intel AMT remote desktop
2979 + if ((node.intelamt.user == null) || (node.intelamt.user == '')) { return; }
2980 + desk = CreateAmtRedirect(CreateAmtRemoteDesktop('kvmid_' + shortid), authCookie);
2981 + desk.shortid = shortid;
2982 + //desk.debugmode = debugmode;
2983 + desk.onStateChanged = onMultiDesktopStateChange;
2984 + desk.m.bpp = 1;
2985 + desk.m.useZRLE = true;
2986 + desk.m.showmouse = true;
2987 + desk.m.onKvmData = function (data) { console.log('KVM Data received in multi-desktop mode, this is not supported.'); }; // KVM Data Channel not supported in multi-desktop right now.
2988 + //desk.m.onScreenSizeChange = deskAdjust;
2989 + if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
2990 + desk.Start(nodeid, 16994, '*', '*', 0);
2991 + desk.contype = 2;
2992 + multiDesktop[nodeid] = desk;
2993 + } else if (contype == 1) {
2994 + // Setup the Mesh Agent remote desktop
2995 + desk = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('kvmid_' + shortid), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
2996 + desk.shortid = shortid;
2997 + desk.attemptWebRTC = attemptWebRTC;
2998 + desk.onStateChanged = onMultiDesktopStateChange;
2999 + //desk.onConsoleMessageChange = function () { console.log('CONSOLEMSG:', desk.consoleMessage); }
3000 + desk.m.CompressionLevel = multidesktopsettings.quality;
3001 + desk.m.ScalingLevel = multidesktopsettings.scaling;
3002 + desk.m.FrameRateTimer = multidesktopsettings.framerate;
3003 + //desk.m.onDisplayinfo = deskDisplayInfo;
3004 + //desk.m.onScreenSizeChange = deskAdjust;
3005 + if (debugmode > 0) { desk.m.onScreenSizeChange = mdeskAdjust; } // Multi-Desktop Adjust
3006 + desk.Start(nodeid);
3007 + desk.contype = 1;
3008 + multiDesktop[nodeid] = desk;
3009 + }
3010 + } else {
3011 + // Disconnect and clean up the remote desktop
3012 + desk.Stop();
3013 + delete multiDesktop[nodeid];
3014 + }
3015 + }
3016 +
3017 + function getMeshActions(mesh, meshrights) {
3018 + if ((meshrights & 4) == 0) return '';
3019 + var r = '';
3020 + if ((features & 1024) == 0) { // If CIRA is allowed
3021 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo Intel&reg; Computador AMT localizado na Internet." + '\" onclick=\'return addCiraDeviceToMesh(\"' + mesh._id + '\")\'>' + "Adicionar CIRA" + '</a>';
3022 + }
3023 + if (mesh.mtype == 1) {
3024 + if ((features & 1) == 0) { // If not WAN-Only
3025 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo Intel&reg; AMT computer that is located on the local network." + '\" onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "Adicionar local" + '</a>';
3026 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo Intelreg; Computador AMT digitalizando a rede local." + '\" onclick=\'return addAmtScanToMesh(\"' + mesh._id + '\")\'>' + "Escaneamento via rede" + '</a>';
3027 + }
3028 + if (mesh.amt && (mesh.amt.type == 2)) { // CCM activation
3029 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Execute a ativação do modo de controle do cliente Intel AMT (CCM)." + '\" onclick=\'return showCcmActivation(\"' + mesh._id + '\")\'>' + "Ativação" + '</a>';
3030 + } else if (mesh.amt && (mesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation
3031 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Execute a ativação do modo de controle de administração Intel AMT (ACM)." + '\" onclick=\'return showAcmActivation(\"' + mesh._id + '\")\'>' + "Ativação" + '</a>';
3032 + }
3033 + }
3034 + if (mesh.mtype == 2) {
3035 + r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Adicione um novo computador a essa malha instalando o agente de malha." + '\" onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "Adicionar agente" + '</a>';
3036 + if ((features & 2) == 0) { r += ' <a href=# style=cursor:pointer;font-size:10px title=\"' + "Convide alguém para instalar o agente de malha nessa malha." + '\" onclick=\'return inviteAgentToMesh(\"' + mesh._id + '\")\'>' + "Convite" + '</a>'; }
3037 + }
3038 + return r;
3039 + }
3040 +
3041 + function addDeviceToMesh(meshid) {
3042 + if (xxdialogMode) return false;
3043 + var mesh = meshes[meshid];
3044 + var x = format("Adicione um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
3045 + x += addHtmlValue("Nome do Dispositivo", '<input id=dp1devicename style=width:230px maxlength=32 autocomplete=off onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
3046 + x += addHtmlValue("Hostname", '<input id=dp1hostname style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "Igual ao nome do dispositivo" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
3047 + x += addHtmlValue("Nome de usuário", '<input id=dp1username style=width:230px maxlength=32 autocomplete=off placeholder=\"' + "admin" + '\" onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
3048 + x += addHtmlValue("Senha", '<input id=dp1password type=password style=width:230px autocomplete=off maxlength=32 onchange=validateDeviceToMesh() onkeyup=validateDeviceToMesh() />');
3049 + x += addHtmlValue("Segurança", '<select id=dp1tls style=width:236px><option value=0>' + "Sem segurança TLS" + '</option><option value=1>' + "Segurança TLS necessária" + '</option></select>');
3050 + setDialogMode(2, "Adicione Intelreg; dispositivo AMT", 3, addDeviceToMeshEx, x, meshid);
3051 + validateDeviceToMesh();
3052 + Q('dp1devicename').focus();
3053 + return false;
3054 + }
3055 +
3056 + // Intel AMT CCM Activation
3057 + function showCcmActivation(meshid) {
3058 + if (xxdialogMode) return false;
3059 + var servername = serverinfo.name, mesh = meshes[meshid];
3060 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
3061 + var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
3062 + if (serverinfo.https == true) {
3063 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
3064 + url = 'wss://' + servername + portStr + domainUrl;
3065 + } else {
3066 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
3067 + url = 'ws://' + servername + portStr + domainUrl;
3068 + }
3069 + var x = format("Execute a ativação do modo de controle de cliente Intel AMT (CCM) para agrupar \"{0}\" baixando a ferramenta MeshCMD e executando-a assim:", EscapeHtml(mesh.name)) + '<br /><br />';
3070 + x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>meshcmd amtccm --url ' + url + 'amtactivate?id=' + meshid.split('/')[2] + ' --serverhttpshash ' + serverinfo.tlshash + '</textarea>';
3071 + setDialogMode(2, "Intel&reg; Ativação AMT", 9, null, x);
3072 + Q('idx_dlgOkButton').focus();
3073 + return false;
3074 + }
3075 +
3076 + // Intel AMT ACM Activation
3077 + function showAcmActivation(meshid) {
3078 + if (xxdialogMode) return false;
3079 + var servername = serverinfo.name, mesh = meshes[meshid];
3080 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
3081 + var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
3082 + if (serverinfo.https == true) {
3083 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
3084 + url = 'wss://' + servername + portStr + domainUrl;
3085 + } else {
3086 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
3087 + url = 'ws://' + servername + portStr + domainUrl;
3088 + }
3089 + var x = format("Execute a ativação do modo de controle de administração Intel AMT (ACM) para agrupar \"{0}\" baixando a ferramenta MeshCMD e executando-a assim:", EscapeHtml(mesh.name)) + '<br /><br />';
3090 + x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>meshcmd amtacm --url ' + url + 'amtactivate?id=' + meshid.split('/')[2] + ' --serverhttpshash ' + serverinfo.tlshash + '</textarea>';
3091 + if (serverinfo.amtAcmFqdn != null) {
3092 + x += ('<div style=margin-top:8px>' + "A Intel AMT precisará ser configurada com um FQDN confiável na MEBx ou ter uma LAN com fio na rede:" + ' <b>' + serverinfo.amtAcmFqdn.join(', ') + '</b></div>');
3093 + }
3094 + setDialogMode(2, "Intel&reg; Ativação AMT", 9, null, x);
3095 + Q('idx_dlgOkButton').focus();
3096 + return false;
3097 + }
3098 +
3099 + // Display the Intel AMT scanning dialog box
3100 + function addAmtScanToMesh(meshid) {
3101 + if (xxdialogMode) return false;
3102 + var x = "Digite um intervalo de endereços IP para procurar dispositivos Intel AMT." + '<br /><br />';
3103 + x += addHtmlValue("IP Range", '<input id=dp1range style=width:184px value="192.168.1.0/24" onkeyup=addAmtScanToMeshKeyUp(event) /><input id=dp1rangebutton type=button value=\"' + "Scan" + '\" onclick=addAmtScanToMeshButton()></input>');
3104 + x += '<div id=dp1results style="width:100%;height:200px;background-color:white;border:1px gray solid;overflow-y:scroll"></div>';
3105 + setDialogMode(2, "Digitalizar para Intel&reg; dispositivos AMT", 3, addAmtScanToMeshEx, x, meshid);
3106 + QE('idx_dlgOkButton', false);
3107 + QH('dp1results', '<div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100</div>');
3108 + focusTextBox('dp1range');
3109 + return false;
3110 + }
3111 +
3112 + function addAmtScanToMeshKeyUp(e) {
3113 + if (e.keyCode == 13) { haltEvent(e); addAmtScanToMeshButton(); }
3114 + }
3115 +
3116 + // Called when OK is pressed on the Intel AMT scanning box
3117 + function addAmtScanToMeshEx(button, meshid) {
3118 + var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
3119 + for (var i=0;i<elements.length;i++) {
3120 + if (elements[i].checked) {
3121 + var ipaddr = elements[i].getAttribute('tag');
3122 + var amtinfo = amtScanResults[ipaddr];
3123 + meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: ipaddr, hostname: amtinfo.hostname, amtusername: '', amtpassword: '', amttls: amtinfo.tls });
3124 + }
3125 + }
3126 + }
3127 +
3128 + // If the user presses the "Scan" button on the Intel AMT scanning dialog box, start a scan.
3129 + function addAmtScanToMeshButton() {
3130 + QE('dp1range', false);
3131 + QE('dp1rangebutton', false);
3132 + QH('dp1results', '<div style=width:100%;text-align:center;margin-top:12px>' + "Escaneando..." + '</div>');
3133 + meshserver.send({ action: 'scanamtdevice', range: Q('dp1range').value });
3134 + }
3135 +
3136 + // Called when a scanned computer is checked or unchecked.
3137 + function addAmtScanToMeshCheckbox() {
3138 + var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
3139 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) checkcount++; }
3140 + QE('idx_dlgOkButton', checkcount > 0);
3141 + }
3142 +
3143 + function addCiraDeviceToMesh(meshid) {
3144 + if (xxdialogMode) return false;
3145 + var mesh = meshes[meshid];
3146 +
3147 + // Replace non alphabetic characters (@ and $) with 'X' because MPS username cannot accept it.
3148 + var meshidx = meshid.split('/')[2].replace(/\@/g, 'X').replace(/\$/g, 'X');
3149 +
3150 + var y = '<select id=dlgAddCiraSel onclick=dlgAddCiraSelClick() style=width:230px><option value=0>' + "MeshCommander Script" + '</option><option value=1>' + "Nome de usuário / senha manual" + '</option>';
3151 + if ((features & 16) == 0) { y += ('<option value=2>' + "Certificado manual" + '</option></select>'); } // Only display this option if Intel AMT CIRA with Mutual-Auth is allowed.
3152 +
3153 + var x = '';
3154 + x += addHtmlValue("Método de instalação", y);
3155 + x += '<hr>';
3156 +
3157 + // Setup CIRA using a MeshCommander script (Pretty Simple)
3158 + x += '<div id=dlgAddCira0>' + format("Para adicionar um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\" com CIRA, baixe os seguintes arquivos de script e use <a href='http://meshcommander.com' rel='noreferrer noopener' target='_blank'>MeshCommander</a> para executar o script para configurar computadores.", EscapeHtml(mesh.name)) + '<br /><br />';
3159 + //x += addHtmlValue('Setup CIRA', '<a href="mescript.ashx?type=1&meshid=' + meshidx.substring(0, 16) + '" download>cira_setup.mescript</a>');
3160 + x += addHtmlValue("Configuração CIRA", '<a href="mescript.ashx?type=1&meshid=' + meshid + '" download>cira_setup.mescript</a>');
3161 + x += addHtmlValue("Limpeza CIRA", '<a href="mescript.ashx?type=2" download>cira_clean.mescript</a>');
3162 + x += '</div>';
3163 +
3164 + // Setup CIRA with user/pass authentication (Somewhat difficult)
3165 + x += '<div id=dlgAddCira1 style=display:none>' + format("Para adicionar um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\" com CIRA, carregue o seguinte certificado como raiz confiável no Intel AMT", EscapeHtml(mesh.name));
3166 + if (serverinfo.mpspass) { x += ("e autenticar no servidor usando esse nome de usuário e senha." + '<br /><br />'); } else { x += ("e autenticar no servidor usando esse nome de usuário e qualquer senha." + '<br /><br />'); }
3167 + x += addHtmlValue("Certificado raiz", '<a href=\"' + "MeshServerRootCert.cer" + '\" download>' + "Arquivo de certificado raiz" + '</a>');
3168 + x += addHtmlValue("Nome de usuário", '<input style=width:230px readonly value="' + meshidx.substring(0, 16) + '" />');
3169 + if (serverinfo.mpspass) { x += addHtmlValue("Senha", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpspass) + '" />'); }
3170 + if (serverinfo != null) { x += addHtmlValue("Servidor MPS", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
3171 + x += '</div>';
3172 +
3173 + // Setup CIRA with certificate authentication (Really difficult, only if TLS offload is not used)
3174 + if ((features & 16) == 0) {
3175 + x += '<div id=dlgAddCira2 style=display:none>' + format("Para adicionar um novo Intel&reg; Dispositivo AMT para grupo de dispositivos \"{0}\" com CIRA, carregue o seguinte certificado como raiz confiável no Intel AMT, autentique usando um certificado de cliente com o seguinte nome comum e conecte-se ao servidor a seguir.", EscapeHtml(mesh.name)) + '<br /><br />';
3176 + x += addHtmlValue("Certificado raiz", '<a href="MeshServerRootCert.cer" download>' + "Arquivo de certificado raiz" + '</a>');
3177 + x += addHtmlValue("Organização", '<input style=width:230px readonly value="' + meshidx + '" />');
3178 + if (serverinfo != null) { x += addHtmlValue("Servidor MPS", '<input style=width:230px readonly value="' + EscapeHtml(serverinfo.mpsname) + ':' + serverinfo.mpsport + '" />'); }
3179 + x += '</div>';
3180 + }
3181 +
3182 + setDialogMode(2, "Adicione Intelreg; ", 2, null, x, 'fileDownload');
3183 + Q('dlgAddCiraSel').focus();
3184 + return false;
3185 + }
3186 +
3187 + function dlgAddCiraSelClick() {
3188 + var val = Q('dlgAddCiraSel').value;
3189 + QV('dlgAddCira0', val == 0);
3190 + QV('dlgAddCira1', val == 1);
3191 + QV('dlgAddCira2', val == 2);
3192 + }
3193 +
3194 + // Return true is the input string looks like an email address
3195 + function checkEmail(str) {
3196 + var x = str.split('@');
3197 + var ok = ((x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2));
3198 + if (ok == true) { var y = x[1].split('.'); for (var i in y) { if (y[i].length == 0) { ok = false; } } }
3199 + return ok;
3200 + }
3201 +
3202 + function inviteAgentToMesh(meshid) {
3203 + if (xxdialogMode) return false;
3204 + var x = '', mesh = meshes[meshid];
3205 + if (features & 64) {
3206 + x += addHtmlValue("Tipo de convite", '<select id=d2InviteType onchange=d2ChangedInviteType() style=width:236px><option value=0>Link invitation</option><option value=1>Email invitation</option></select>') + '<hr />';
3207 + x += '<div id=emailInviteDiv style=display:none>' + format("Convide alguém para instalar o agente de malha.Um email será enviado com o link para a instalação do agente de malha para o grupo de dispositivos \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
3208 + x += addHtmlValue("Nome (Opcional)", '<input id=agentInviteName value="" style=width:230px maxlength=64 />');
3209 + x += addHtmlValue("Email", '<input id=agentInviteEmail style=width:230px placeholder=\"' + "example@email.com" + '\" onkeyup=validateAgentInvite()></input>');
3210 + x += addHtmlValue("Sistema operacional", '<select id=agentInviteNameOs onchange=d2ChangedInviteType() style=width:236px><option value=4>' + "Enviar link de instalação" + '</option><option value=0 selected>' + "Qualquer suportado" + '</option><option value=1>' + "Apenas Windows" + '</option><option value=3>' + "Apenas Apple MacOS " + '</option><option value=2>' + "Apenas Linux" + '</option></select>');
3211 + x += '<div id=d2agentexpirediv>';
3212 + x += addHtmlValue("Expiração do link", '<select id=agentInviteExpire style=width:236px><option value=1>' + "1 hora" + '</option><option value=8>' + "8 horas" + '</option><option value=24>' + "1 dia" + '</option><option value=168>' + "1 semana" + '</option><option value=5040>' + "1 mês" + '</option><option value=0>' + "Ilimitado" + '</option></select>');
3213 + x += '</div>';
3214 + x += addHtmlValue("Tipo de instalação ", '<select id=agentInviteType style=width:236px><option value=0>' + "Segundo plano e interativo" + '</option><option value=2>' + "Apenas em segundo plano" + '</option><option value=1>' + "Apenas interativo" + '</option></select>');
3215 + x += addHtmlValue("Mensagem" + '<br />' + "(opcional)", '<textarea id=agentInviteMessage value="" style=width:230px;height:100px;resize:none maxlength=1024 /></textarea>');
3216 + x += '</div>';
3217 + }
3218 + x += '<div id=urlInviteDiv>' + format("Convide alguém para instalar o agente de malha compartilhando um link de convite.Este link indica ao usuário instruções de instalação para o grupo de dispositivos \"{0}\". O link é público e nenhuma conta para este servidor é necessária.", EscapeHtml(mesh.name)) + '<br /><br />';
3219 + x += addHtmlValue("Expiração do link", '<select id=d2inviteExpire style=width:236px onchange=d2RequestInvitationLink()><option value=1>' + "1 hora" + '</option><option value=8>' + "8 horas" + '</option><option value=24>' + "1 dia" + '</option><option value=168>' + "1 semana" + '</option><option value=5040>' + "1 mês" + '</option><option value=0>' + "Ilimitado" + '</option></select>');
3220 + x += '<div id=agentInvitationLinkDiv style="text-align:center;font-size:large;margin:16px;display:none"><a href=# id=agentInvitationLink target="_blank" style=cursor:pointer></a> <img src=images/link4.png height=10 width=10 title=\"' + "Copiar link para a área de transferência" + '\" style=cursor:pointer onclick=d2CopyInviteToClip()></div></div>';
3221 + setDialogMode(2, "Convite", 3, performAgentInvite, x, meshid);
3222 + if (features & 64) { Q('d2InviteType').focus(); d2ChangedInviteType(); } else { Q('d2inviteExpire').focus(); validateAgentInvite(); }
3223 + d2RequestInvitationLink();
3224 + return false;
3225 + }
3226 +
3227 + function d2RequestInvitationLink() {
3228 + meshserver.send({ action: 'createInviteLink', meshid: xxdialogTag, expire: parseInt(Q('d2inviteExpire').value), flags: 0 });
3229 + }
3230 +
3231 + function d2ChangedInviteType() {
3232 + QV('urlInviteDiv', Q('d2InviteType').value == 0);
3233 + QV('d2agentexpirediv', Q('agentInviteNameOs').value == 4);
3234 + QV('emailInviteDiv', Q('d2InviteType').value == 1);
3235 + validateAgentInvite();
3236 + }
3237 +
3238 + function d2CopyInviteToClip() { copyTextToClip(Q('agentInvitationLink').href); }
3239 +
3240 + function validateAgentInvite() {
3241 + if ((features & 64) && (Q('d2InviteType').value == 1)) {
3242 + QE('idx_dlgOkButton', checkEmail(Q('agentInviteEmail').value));
3243 + QV('idx_dlgCancelButton', true);
3244 + } else {
3245 + QE('idx_dlgOkButton', true);
3246 + QV('idx_dlgCancelButton', false);
3247 + }
3248 + }
3249 +
3250 + function performAgentInvite(button, meshid) {
3251 + if ((features & 64) && (Q('d2InviteType').value == 1)) {
3252 + meshserver.send({ action: 'inviteAgent', meshid: meshid, email: Q('agentInviteEmail').value, name: Q('agentInviteName').value, os: Q('agentInviteNameOs').value, flags: Q('agentInviteType').value, msg: Q('agentInviteMessage').value, expire: parseInt(Q('agentInviteExpire').value) });
3253 + }
3254 + }
3255 +
3256 + function addAgentToMesh(meshid) {
3257 + if (xxdialogMode) return false;
3258 + var mesh = meshes[meshid], x = '', installType = 0;
3259 + x += addHtmlValue("Sistema operacional", '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Windows" + '</option><option value=1>' + "Linux / BSD" + '</option><option value=2>' + "Apple MacOS" + '</option><option value=3>' + "Windows (Desinstalador)" + '</option><option value=4>' + "Linux / BSD (desinstalação)" + '</option></select>');
3260 + x += '<div id=aginsTypeDiv>';
3261 + x += addHtmlValue("Tipo de instalação ", '<select id=aginsType onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Segundo plano e interativo" + '</option><option value=2>' + "Apenas em segundo plano" + '</option><option value=1>' + "Apenas interativo" + '</option></select>');
3262 + x += '</div><hr>';
3263 +
3264 + // \/:*?"<>|
3265 + var meshfilename = mesh.name
3266 + meshfilename = meshfilename.split('\\').join('').split('/').join('').split(':').join('').split('*').join('').split('?').join('').split('"').join('').split('<').join('').split('>').join('').split('|').join('').split(' ').join('').split('\'').join('');
3267 +
3268 + // Windows agent install
3269 + //x += "<div id=agins_windows>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and configuration file and install the agent on the computer to manage.<br /><br />";
3270 + x += '<div id=agins_windows>' + format("Para adicionar um novo computador ao grupo de dispositivos \"{0}\", faça o download do agente de malha e instale-o no computador para gerenciar. Este agente possui informações de servidor e grupo de dispositivos incorporadas.", EscapeHtml(mesh.name)) + '<br /><br />';
3271 + x += addHtmlValue("Mesh Agent", '<a id=aginsw32lnk href="meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "Versão de 32 bits do MeshAgent" + '\">' + "Windows (.exe)" + '</a> <img src=images/link4.png height=10 width=10 title="Copy Windows 32bit agent URL to clipboard" style=cursor:pointer onclick=copyAgentUrl("meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=",1)>');
3272 + x += addHtmlValue("Mesh Agent", '<a id=aginsw64lnk href="meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=0" download onclick="setDialogMode(0)" title=\"' + "Versão de 64 bits do MeshAgent" + '\">' + "Windows x64 (.exe)" + '</a> <img src=images/link4.png height=10 width=10 title="Copy Windows 64bit agent URL to clipboard" style=cursor:pointer onclick=copyAgentUrl("meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=",1)>');
3273 + if (debugmode > 0) { x += addHtmlValue("Arquivo de configurações", '<a id=aginswmshlnk href="meshsettings?id=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank">' + format("{0} configurações (.msh)", EscapeHtml(mesh.name)) + '</a>'); }
3274 + x += '</div>';
3275 +
3276 + // Linux agent install
3277 + x += '<div id=agins_linux style=display:none>' + format("Para adicionar um computador a {0}, execute o seguinte comando.Serão necessárias credenciais raiz.", EscapeHtml(mesh.name)) + '<br />';
3278 + x += '<textarea id=agins_linux_area rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
3279 + x += '<div style=\'font-size:x-small\'>' + "* Para o BSD, execute \"pkg install wget sudo bash\"." + '</div></div>';
3280 +
3281 + // MacOS agent install
3282 + x += '<div id=agins_osx style=display:none>' + format("Para adicionar um novo computador ao grupo de dispositivos \"{0}\", faça o download do agente de malha e instale-o no computador para gerenciar. Este instalador do agente possui informações de servidor e grupo de dispositivos incorporadas.", EscapeHtml(mesh.name)) + '<br /><br />';
3283 + x += addHtmlValue("Mesh Agent", '<a href="meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '" rel="noreferrer noopener" target="_blank" title="64bit version of MacOS Mesh Agent">MacOS Agent (64bit)</a> <img src=images/link4.png height=10 width=10 title="' + "Copiar o URL do agente MacOS para a área de transferência" + '" style=cursor:pointer onclick=copyAgentUrl("meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '",0)>');
3284 + x += '</div>';
3285 +
3286 + // Windows agent uninstall
3287 + x += '<div id=agins_windows_un style=display:none>' + "Para remover um agente de malha, faça o download do arquivo abaixo, execute-o e clique em \"uninstall\"." + '<br /><br />';
3288 + x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=3" download onclick="setDialogMode(0)" title="' + "Versão de 32 bits do MeshAgent" + '">' + "Windows (.exe)" + '</a>');
3289 + x += addHtmlValue("Mesh Agent", '<a href="meshagents?id=4" download onclick="setDialogMode(0)" title="' + "Versão de 64 bits do MeshAgent" + '">' + "Windows x64 (.exe)" + '</a>');
3290 + x += '</div>';
3291 +
3292 + // Linux agent uninstall
3293 + x += '<div id=agins_linux_un style=display:none>' + "Para remover um agente de malha, execute o seguinte comando. Serão necessárias credenciais raiz." + '<br />';
3294 + x += '<textarea id=agins_linux_area_un rows=2 cols=20 readonly=readonly style=width:100%;resize:none;height:120px;overflow:scroll;font-size:12px readonly></textarea>';
3295 + x += '</div>';
3296 +
3297 + setDialogMode(2, "Adicionar agente de malha", 2, null, x, 'fileDownload');
3298 + var servername = serverinfo.name;
3299 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
3300 + var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
3301 +
3302 + if (serverinfo.https == true)
3303 + {
3304 + var portStr = (serverinfo.port == 443)?'':(':' + serverinfo.port);
3305 + if ((features & 0x2000) == 0)
3306 + {
3307 + Q('agins_linux_area').value = '(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 -E ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\' || ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
3308 + Q('agins_linux_area_un').value = '(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';
3309 + }
3310 + else
3311 + {
3312 + // Server asked that agent be installed to preferably not use a HTTP proxy.
3313 + Q('agins_linux_area').value = '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.split('/')[2] + '\' || ./meshinstall.sh https://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
3314 + Q('agins_linux_area_un').value = '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';
3315 + }
3316 + }
3317 + else
3318 + {
3319 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
3320 + if ((features & 0x2000) == 0)
3321 + {
3322 + Q('agins_linux_area').value = '(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 -E ./meshinstall.sh http://' + servername + portStr + domainUrlNoSlash + ' \'' + meshid.split('/')[2] + '\'\r\n';
3323 + Q('agins_linux_area_un').value = '(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';
3324 + }
3325 + else
3326 + {
3327 + // Server asked that agent be installed to preferably not use a HTTP proxy.
3328 + Q('agins_linux_area').value = '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.split('/')[2] + '\'\r\n';
3329 + Q('agins_linux_area_un').value = 'wget http://' + servername + portStr + domainUrl + 'meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n';
3330 + }
3331 + }
3332 + Q('aginsSelect').focus();
3333 + addAgentToMeshClick();
3334 + return false;
3335 + }
3336 +
3337 + function copyAgentUrl(url,addflag) {
3338 + var servername = serverinfo.name;
3339 + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
3340 + var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
3341 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
3342 + var c = 'https://' + servername + portStr + domainUrl + url;
3343 + if (addflag == 1) c += Q('aginsType').value;
3344 + copyTextToClip(c);
3345 + }
3346 +
3347 + function addAgentToMeshClick() {
3348 + var v = Q('aginsSelect').value;
3349 + QV('agins_windows', v == 0);
3350 + QV('agins_linux', v == 1);
3351 + QV('agins_osx', v == 2);
3352 + QV('agins_windows_un', v == 3);
3353 + QV('agins_linux_un', v == 4);
3354 + QV('aginsTypeDiv', v == 0);
3355 +
3356 + // Fix the links if needed
3357 + Q('aginsw32lnk').href = (Q('aginsw32lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
3358 + Q('aginsw64lnk').href = (Q('aginsw64lnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value;
3359 + if (debugmode > 0) { Q('aginswmshlnk').href = (Q('aginswmshlnk').href.split('installflags=')[0]) + 'installflags=' + Q('aginsType').value; }
3360 + }
3361 +
3362 + function validateDeviceToMesh() {
3363 + QE('idx_dlgOkButton', (Q('dp1devicename').value.length > 0) && (passwordcheck(Q('dp1password').value)));
3364 + }
3365 +
3366 + function addDeviceToMeshEx(button, meshid) {
3367 + var amtuser = Q('dp1username').value;
3368 + if (amtuser == '') amtuser = 'admin';
3369 + var host = Q('dp1hostname').value;
3370 + if (host == '') host = Q('dp1devicename').value;
3371 + meshserver.send({ action: 'addamtdevice', meshid: meshid, devicename: Q('dp1devicename').value, hostname: host, amtusername: amtuser, amtpassword: Q('dp1password').value, amttls: Q('dp1tls').value });
3372 + }
3373 +
3374 + function deviceHeaderSet() {
3375 + if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
3376 + deviceHeaders['DevxHeader' + deviceHeaderId] = ((deviceHeaderTotal == 1) ? "1 nó" : format("{0} nós", deviceHeaderTotal));
3377 + //var title = '';
3378 + //for (x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
3379 + //deviceHeadersTitles["DevxHeader" + deviceHeaderId] = title;
3380 + deviceHeaderId++;
3381 + deviceHeaderCount = {};
3382 + deviceHeaderTotal = 0;
3383 + }
3384 +
3385 + var powerStateStrings = ['', '<span title=\"' + "O dispositivo está ligado." + '\">' + "Ligado" + '</span>', '<span title=\"' + "O dispositivo está no estado de suspensão (S1)." + '\">' + "Hibernando" + '</span>', '<span title=\"' + "O dispositivo está no estado de suspensão (S2)." + '\">' + "Hibernando" + '</span>', '<span title=\"' + "O dispositivo está no estado de suspensão profunda (S3)." + '\">' + "Deep Sleep" + '</span>', '<span title=\"' + "O dispositivo está no estado de hibernação (S4)." + '\">' + "Hibernando" + '</span>', '<span title=\"' + "O dispositivo está no estado desligado (S5)." + '\">' + "Soft-Off" + '</span>', '<span title=\"' + "O dispositivo foi detectado, mas não foi possível obter o estado de energia." + '\">' + "Presente" + '</span>'];
3386 + var powerStateStrings2 = ['', "O dispositivo está ligado", "O dispositivo está no estado de suspensão (S1)", "O dispositivo está no estado de suspensão (S2)", "O dispositivo está no estado de sono profundo (S3)", "O dispositivo está hibernando (S4)", "O dispositivo está no estado soft-off (S5)", "O dispositivo está presente, mas o estado de energia não pode ser determinado"];
3387 + var powerColorTable = ['pwsTransparent', 'pwsBlack', 'pwsBlue', 'pwsBlue2', 'pwsLightblue', 'pwsBlueviolet', 'pwsDarkgreen', 'pwsLightseagreen', 'pwsLightseagreen2'];
3388 + function NodeStateStr(node) {
3389 + var states = [];
3390 + if (node.state > 0 && node.state < powerStatetable.length) state.push(powerStatetable[node.state]);
3391 + if (node.conn) {
3392 + if ((node.conn & 1) != 0) { states.push('<span title=\"' + "O agente de malha está conectado e pronto para uso." + '\">' + "Agente" + '</span>'); }
3393 + if ((node.conn & 2) != 0) { states.push('<span title=\"' + "Intel&reg; O AMT CIRA está conectado e pronto para uso." + '\">' + "CIRA" + '</span>'); }
3394 + else if ((node.conn & 4) != 0) { states.push('<span title=\"' + "Intel&reg; AMT é roteável." + '\">' + "AMT" + '</span>'); }
3395 + if ((node.conn & 8) != 0) { states.push('<span title=\"' + "O agente de malha é alcançável usando outro agente como retransmissão." + '\">' + "Retransmissão" + '</span>'); }
3396 + if ((node.conn & 16) != 0) { states.push('<span title=\"' + "A conexão MQTT com o dispositivo está ativa." + '\">' + "MQTT" + '</span>'); }
3397 + }
3398 + if ((node.pwr != null) && (node.pwr != 0)) { states.push(powerStateStrings[node.pwr]); }
3399 + return states.join(', ');
3400 + }
3401 +
3402 + function PowerStateStr(x) {
3403 + if (x < powerStatetable.length) return powerStatetable[x];
3404 + return '';
3405 + }
3406 +
3407 + function PowerStateStr2(x) {
3408 + if ((x != 0) && (x < powerStatetable.length)) return powerStatetable[x];
3409 + return "Desconhecido";
3410 + }
3411 +
3412 + function selectallButtonFunction() {
3413 + var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
3414 + for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) checkcount++; }
3415 + for (var i=0;i<elements.length;i++) { elements[i].checked = (checkcount == 0); }
3416 + p1updateInfo();
3417 + }
3418 +
3419 + function p1updateInfo() {
3420 + var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
3421 + for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) { checkcount++; } }
3422 + if (checkcount > 0) {
3423 + QE('GroupActionButton', true);
3424 + Q('SelectAllButton').value = "Selecione nenhum";
3425 + QV('cxmgroupsplit', true);
3426 + QV('cxmdesktop', true);
3427 + } else {
3428 + QE('GroupActionButton', false);
3429 + Q('SelectAllButton').value = "Selecionar tudo";
3430 + QV('cxmgroupsplit', false);
3431 + QV('cxmdesktop', false);
3432 + }
3433 + }
3434 +
3435 + function groupActionFunction() {
3436 + var addedOptions = '', nodeids = getCheckedDevices();
3437 +
3438 + // Check if any of the selected devices have a MQTT connection active
3439 + if (features & 0x00400000) {
3440 + for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { addedOptions += '<option value=103>' + "Enviar Mensagem MQTT" + '</option>'; break; } }
3441 + }
3442 +
3443 + // Display the "Uninstall Agent" option if allowed and we selected connected devices.
3444 + for (var i in nodeids) {
3445 + var node = getNodeFromId(nodeids[i]);
3446 + var mesh = meshes[node.meshid];
3447 + var meshrights = mesh.links[userinfo._id].rights;
3448 + if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
3449 + }
3450 +
3451 + var x = "Selecione uma operação para executar em todos os dispositivos selecionados. As ações serão executadas apenas com os direitos adequados." + '<br /><br />';
3452 + x += addHtmlValue("Operação", '<select id=d2groupop><option value=100>' + "Acordar dispositivo" + '</option><option value=4>' + "Hibernar dispositivo" + '</option><option value=3>' + "Redefinir dispositivos" + '</option><option value=2>' + "Desligar dispositivos" + '</option><option value=102>' + "Mover para o grupo de dispositivos" + '</option>' + addedOptions + '<option value=101>' + "Excluir Dispositivos" + '</option></select>');
3453 + setDialogMode(2, "Ações do grupo", 3, groupActionFunctionEx, x);
3454 + }
3455 +
3456 + // Get the list of checked devices, removes any duplicates.
3457 + function getCheckedDevices() {
3458 + var nodeids = [], elements = document.getElementsByClassName("Caixa de seleção do dispositivo"), checkcount = 0;
3459 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
3460 + return nodeids;
3461 + }
3462 +
3463 + function groupActionFunctionEx() {
3464 + var op = Q('d2groupop').value;
3465 + if (op == 100) {
3466 + // Group wake
3467 + meshserver.send({ action: 'wakedevices', nodeids: getCheckedDevices() });
3468 + } else if (op == 101) {
3469 + // Group delete, ask for confirmation
3470 + var x = "Confirmar a exclusão dos dispositivos selecionados?" + '<br /><br />';
3471 + x += '<label><input id=d2check type=checkbox onchange=d2groupActionFunctionDelEx() />' + "Confirme" + '</label>';
3472 + setDialogMode(2, "Excluir nós", 3, groupActionFunctionDelEx, x);
3473 + QE('idx_dlgOkButton', false);
3474 + } else if (op == 102) {
3475 + // Move computers to a different group
3476 + p10showChangeGroupDialog(getCheckedDevices());
3477 + } else if (op == 103) {
3478 + // Send MQTT Message
3479 + p10showSendMqttMsgDialog(getCheckedDevices());
3480 + } else if (op == 104) {
3481 + // Uninstall agent
3482 + p10showSendUninstallAgentDialog(getCheckedDevices());
3483 + } else {
3484 + // Power operation
3485 + meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: parseInt(op) });
3486 + }
3487 + }
3488 +
3489 + function d2groupActionFunctionDelEx() { QE('idx_dlgOkButton', Q('d2check').checked); }
3490 + function groupActionFunctionDelEx() { meshserver.send({ action: 'removedevices', nodeids: getCheckedDevices() }); }
3491 +
3492 + function onSortSelectChange(skipsave) {
3493 + sort = document.getElementById('sortselect').selectedIndex;
3494 + if (!skipsave) { putstore('sort', sort); }
3495 + }
3496 +
3497 + function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
3498 + function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap > bp) return -1; if (ap < bp) return 1; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
3499 + function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
3500 + function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
3501 + function onSearchFocus(x) { searchFocus = x; }
3502 + function onMapSearchFocus(x) { mapSearchFocus = x; }
3503 + function onUserSearchFocus(x) { userSearchFocus = x; }
3504 + function onConsoleFocus(x) { consoleFocus = x; }
3505 +
3506 + function onSearchInputChanged() {
3507 + var x = Q('SearchInput').value.toLowerCase().trim(); putstore('_search', x);
3508 + var userSearch = null, ipSearch = null, groupSearch = null;
3509 + if (x.startsWith('user:')) { userSearch = x.substring(5); }
3510 + else if (x.startsWith('u:')) { userSearch = x.substring(2); }
3511 + else if (x.startsWith('ip:')) { ipSearch = x.substring(3); }
3512 + else if (x.startsWith('group:')) { groupSearch = x.substring(6); }
3513 + else if (x.startsWith('g:')) { groupSearch = x.substring(2); }
3514 +
3515 + if (x == '') {
3516 + // No search
3517 + for (var d in nodes) { nodes[d].v = true; }
3518 + } else if (ipSearch != null) {
3519 + // IP address search
3520 + for (var d in nodes) { nodes[d].v = ((nodes[d].ip != null) && (nodes[d].ip.indexOf(ipSearch) >= 0)); }
3521 + } else if (groupSearch != null) {
3522 + // Group filter
3523 + for (var d in nodes) { nodes[d].v = (meshes[nodes[d].meshid].name.toLowerCase().indexOf(groupSearch) >= 0); }
3524 + } else if (userSearch != null) {
3525 + // User search
3526 + for (var d in nodes) {
3527 + nodes[d].v = false;
3528 + if (nodes[d].users && nodes[d].users.length > 0) { for (var i in nodes[d].users) { if (nodes[d].users[i].toLowerCase().indexOf(userSearch) >= 0) { nodes[d].v = true; } } }
3529 + }
3530 + } else {
3531 + // Device name search
3532 + try {
3533 + var rs = x.split(/\s+/).join('|'), rx = new RegExp(rs); // In some cases (like +), this can throw an exception.
3534 + for (var d in nodes) {
3535 + nodes[d].v = (rx.test(nodes[d].name.toLowerCase())) || (nodes[d].rnamel != null && rx.test(nodes[d].rnamel.toLowerCase()));
3536 + if ((nodes[d].v == false) && nodes[d].tags) {
3537 + for (var s in nodes[d].tags) {
3538 + if (rx.test(nodes[d].tags[s].toLowerCase())) {
3539 + nodes[d].v = true;
3540 + break;
3541 + } else {
3542 + nodes[d].v = false;
3543 + }
3544 + }
3545 + }
3546 + }
3547 + } catch (ex) { for (var d in nodes) { nodes[d].v = true; } }
3548 + }
3549 + }
3550 +
3551 + var contextelement = null;
3552 + function handleContextMenu(event) {
3553 + hideContextMenu();
3554 + var scrollLeft = (window.pageXOffset !== null) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
3555 + var scrollTop = (window.pageYOffset !== null) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
3556 + var elem = document.elementFromPoint(event.pageX - scrollLeft, event.pageY - scrollTop);
3557 + if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 0) && (currentNode.agent.id < 5)) {
3558 + contextelement = elem;
3559 + var contextmenudiv = document.getElementById('termShellContextMenu');
3560 + contextmenudiv.style.left = event.pageX + 'px';
3561 + contextmenudiv.style.top = event.pageY + 'px';
3562 + contextmenudiv.style.display = 'block';
3563 + } else if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 4)) {
3564 + contextelement = elem;
3565 + var contextmenudiv = document.getElementById('termShellContextMenuLinux');
3566 + contextmenudiv.style.left = event.pageX + 'px';
3567 + contextmenudiv.style.top = event.pageY + 'px';
3568 + contextmenudiv.style.display = 'block';
3569 + } else if (elem && elem != null && elem.id == 'MxMESH') {
3570 + contextelement = elem;
3571 + var contextmenudiv = document.getElementById('meshContextMenu');
3572 + contextmenudiv.style.left = event.pageX + 'px';
3573 + contextmenudiv.style.top = event.pageY + 'px';
3574 + contextmenudiv.style.display = 'block';
3575 + /*} else if (elem && elem != null && elem.classList.contains('pluginTab')) {
3576 + contextelement = elem;
3577 + var contextmenudiv = document.getElementById('pluginTabContextMenu');
3578 + contextmenudiv.style.left = event.pageX + 'px';
3579 + contextmenudiv.style.top = event.pageY + 'px';
3580 + contextmenudiv.style.display = 'block';*/
3581 + } else {
3582 + while (elem && elem != null && elem.id != 'devs') { elem = elem.parentElement; }
3583 + if (!elem || elem == null) return true;
3584 + contextelement = elem;
3585 + var contextmenudiv = document.getElementById('contextMenu');
3586 + contextmenudiv.style.left = event.pageX + 'px';
3587 + contextmenudiv.style.top = event.pageY + 'px';
3588 + contextmenudiv.style.display = 'block';
3589 +
3590 + // Get the node and set the menu options
3591 + var nodeid = contextelement.children[1].attributes.onclick.value;
3592 + var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
3593 + var mesh = meshes[node.meshid];
3594 + var meshlinks = mesh.links[userinfo._id];
3595 + var meshrights = meshlinks.rights;
3596 + var consoleRights = ((meshrights & 16) != 0);
3597 +
3598 + // Check if we have terminal and file access
3599 + var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
3600 + var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
3601 +
3602 + QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((meshrights & 8) || (meshrights & 256)));
3603 + QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
3604 + QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
3605 + QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
3606 + QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
3607 + }
3608 +
3609 + return haltEvent(event);
3610 + }
3611 +
3612 + function cmaction(action,event) {
3613 + var nodeid = contextelement.children[1].attributes.onclick.value;
3614 + nodeid = nodeid.substring(12, nodeid.length - 18);
3615 + if (action == 7) { Q('viewselect').value = 3; Q('viewselect').onchange(); Q('autoConnectDesktopCheckbox').checked = true; Q('autoConnectDesktopCheckbox').onclick(); } // Multi-Desktop
3616 + if ((action > 0) && (action < 7)) {
3617 + var panel = [0, 10, 12, 11, 13, 16, 15][action]; // (invalid), General, Desktop, Terminal, Files, Events, Console
3618 + if (event && (event.shiftKey == true)) {
3619 + // Open the device in a different tab
3620 + window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=' + panel + '&hide=16', 'meshcentral:' + nodeid);
3621 + } else {
3622 + // Go to the right panel
3623 + gotoDevice(nodeid, panel);
3624 +
3625 + // If possible, connect...
3626 + var mesh = meshes[currentNode.meshid];
3627 + if ((currentNode.conn & 1) && (mesh.mtype == 2)) {
3628 + if ((panel == 11) && (desktop == null) && (currentNode.agent.caps & 1)) { connectDesktop(null, 1); } // Desktop
3629 + if ((panel == 12) && (terminal == null) && (currentNode.agent.caps & 2)) { connectTerminal(null, 1); } // Terminal
3630 + if ((panel == 13) && (files == null)) { connectFiles(null); } // files
3631 + }
3632 + }
3633 + }
3634 + }
3635 +
3636 + function cmmeshaction(action) {
3637 + var meshid = contextelement.attributes.onclick.value.substring(10, contextelement.attributes.onclick.value.length - 2);
3638 + var elements = document.getElementsByClassName('DeviceCheckbox');
3639 + if ((action == 1) || (action == 2)) {
3640 + for (var i = 0; i < elements.length; i++) {
3641 + if ((elements[i].attributes) && (elements[i].attributes['class']['value'].split(' ')[0] == meshid)) { elements[i].checked = (action == 1); }
3642 + }
3643 + }
3644 + //if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
3645 + p1updateInfo();
3646 + }
3647 +
3648 + function cmtermaction(action) {
3649 + connectTerminal(null, 1, { protocol: action });
3650 + }
3651 +
3652 + /*
3653 + function pluginTabClose() {
3654 + var pluginTab = contextelement;
3655 + var pname = pluginTab.getAttribute('x-data-plugin-sname');
3656 + var pdiv = Q('plugin-'+pname);
3657 + pdiv.parentNode.removeChild(pdiv);
3658 + pluginTab.parentNode.removeChild(pluginTab);
3659 + QV('p42', true);
3660 + goPlugin(-1);
3661 + }
3662 + */
3663 +
3664 + function hideContextMenu() {
3665 + QV('contextMenu', false);
3666 + QV('meshContextMenu', false);
3667 + QV('termShellContextMenu', false);
3668 + QV('termShellContextMenuLinux', false);
3669 + //QV('pluginTabContextMenu', false);
3670 + contextelement = null;
3671 + }
3672 +
3673 + //
3674 + // DEVICES MAP
3675 + //
3676 +
3677 + // Maps code starts from here. Initialize all the variables
3678 + var xxmap = {
3679 + map: null,
3680 + contextmenu: null,
3681 + activeInteractions: [], // Save Modified features in this list
3682 + showindex: 0,
3683 + markersSource: null, // Initialize a Source Vector
3684 + markersLayer: null,
3685 + mapLayer: null, // Create a tile and use OSM source
3686 + mapView: null, // Sets the initial view
3687 + }
3688 +
3689 + {{{StartGeoLocationJS}}}
3690 +
3691 + // Add a feature for every Node and change style if connection status changes
3692 + function updateMapMarkers(selectedMesh) {
3693 + if ((xxmap != null) && (xxmap.map == null)) { try { loadmap(); } catch (ex) { console.error('loadmap() exception', ex); } }
3694 + if (xxmap == null) return;
3695 + var boundingBox = null;
3696 + for (var i in nodes) {
3697 + try {
3698 + var loc = map_parseNodeLoc(nodes[i]), feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
3699 + if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
3700 + var lat = loc[0], lon = loc[1], type = loc[2];
3701 + if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
3702 + if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature
3703 + } else {
3704 + if (feature) { xxmap.markersSource.removeFeature(feature); }
3705 + }
3706 + } catch (ex) { console.error('updateMapMarkers() exception', ex, JSON.stringify(nodes[i])); }
3707 + }
3708 + return boundingBox;
3709 + }
3710 +
3711 + // Show node details on hovering over a feature
3712 + var map_cm_popup = new ol.Overlay({ element: Q('xmap-info-window'), positioning: 'bottom-center', stopEvent: false });
3713 +
3714 + // Edit Marker item
3715 + var map_cm_editMarker = { text: "Modificar localização do nó", callback: function (obj) { modifyMarkerloc(obj.data); } };
3716 +
3717 + // Clear Marker item
3718 + var map_cm_clearMarker = { text: "Remover localização do nó", callback: function (obj) {
3719 + meshserver.send({ action: 'changedevice', nodeid: obj.data.a, userloc: [] }); // Clear the user position marker
3720 + }};
3721 +
3722 + // Save Marker item
3723 + var map_cm_saveMarker = { text: "Salvar localização do nó", callback: function (obj) { saveMarkerloc(obj.data); } };
3724 +
3725 + // Build a context menu for a feature
3726 + var map_cm_nodemenu_items = [
3727 + { text: "Informações gerais", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 10); } } },
3728 + { text: "Área de Trabalho", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 11); } } },
3729 + { text: "Terminal", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 12); } } },
3730 + { text: "Intel&reg; AMT", callback: function (obj) { if (obj.data !=null) { gotoDevice(obj.data, 14); } } },
3731 + '-',
3732 + { text: "Aumentar o zoom até o limite", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 19); } },
3733 + { text: "Diminuir o zoom até o limite", callback: function(obj) { var coords = obj.data.getGeometry().getCoordinates(); zoomToLocation(coords, 2); } }
3734 + ];
3735 +
3736 + // Context menu for clicks other than on feature
3737 + var contextmenu_items = [
3738 + { text: "Atualizar", callback: function () { refreshMap(true, true); } },
3739 + { text: "Zoom para ajustar a extensão", callback: function () { zoomToFitExtent(); } },
3740 + { text: "Centralize o mapa aqui", callback: function(obj) { xxmap.mapView.animate({ center: obj.coordinate } ); } },
3741 + { text: "Coloque o nó aqui", callback: function(obj) { placeNode(obj.coordinate); } }
3742 + ];
3743 +
3744 + function stringToIntHash(str) {
3745 + var hash = 0, i;
3746 + for (i = 0; i < str.length; i++) { hash = ((hash << 5) - hash) + str.charCodeAt(i); hash |= 0; }
3747 + return hash;
3748 + };
3749 +
3750 + // Get the lat/lon from a node
3751 + function map_parseNodeLoc(node) {
3752 + var loc = null, t = 0;
3753 + if (node.iploc) { loc = node.iploc; t = 1; }
3754 + if (node.wifiloc) { loc = node.wifiloc; t = 2; }
3755 + if (node.gpsloc) { loc = node.gpsloc; t = 3; }
3756 + if (node.userloc) { loc = node.userloc; t = 4; }
3757 + if ((loc == null) || (typeof loc != 'string')) return null;
3758 + loc = loc.split(',');
3759 + if (t == 1) {
3760 + // If this is IP location, randomize the position a little.
3761 + return [ parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000), t ];
3762 + } else {
3763 + // Return the real position
3764 + return [ parseFloat(loc[0]), parseFloat(loc[1]), t ];
3765 + }
3766 + }
3767 +
3768 + // Load the entire map
3769 + function loadmap() {
3770 + if (xxmap == null) return;
3771 + if ((features & 0x8000) == 0) { xxmap = null; return; } // Geolocation not supported
3772 + QV('viewselectmapoption', true);
3773 + QV('devViewButton4', true);
3774 + try {
3775 + // Initialize a Source Vector
3776 + xxmap.markersSource = new ol.source.Vector();
3777 +
3778 + xxmap.markersLayer = new ol.layer.Vector({
3779 + source: xxmap.markersSource
3780 + });
3781 +
3782 + // Create a tile and use OSM source
3783 + xxmap.mapLayer = new ol.layer.Tile({ source: new ol.source.OSM() });
3784 +
3785 + xxmap.mapView = new ol.View({ // Set the initial view
3786 + center: ol.proj.transform([0, 0], 'EPSG:4326', 'EPSG:3857'),
3787 + zoom: 2,
3788 + minZoom: 2,
3789 + maxZoom: 20,
3790 + extent: ol.proj.transformExtent([-100000, -69.55, 100000, 69.55], 'EPSG:4326', 'EPSG:3857')
3791 + });
3792 +
3793 + xxmap.map = new ol.Map({
3794 + target: 'xdevicesmap',
3795 + layers: [xxmap.mapLayer, xxmap.markersLayer],
3796 + view: xxmap.mapView
3797 + });
3798 +
3799 + xxmap.map.addOverlay(map_cm_popup);
3800 +
3801 + // Goto information tab if a user clicks on a feature
3802 + xxmap.map.on('click', function(evt) {
3803 + var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
3804 + if (feature) {
3805 + var nodeid = feature.getId();
3806 + if (nodeid != null) { gotoDevice(nodeid, 10); } // Goto general info tab
3807 + else { // For pointer
3808 + var nodeFeatgoto = getCorrespondingFeature(feature); gotoDevice(nodeFeatgoto.getId(), 10);
3809 + }
3810 + }
3811 + });
3812 +
3813 + // On hover feature show the name of the node. Also add pointer style
3814 + xxmap.map.on('pointermove', function(evt) {
3815 + var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(feat, layer) { return feat; });
3816 + if (feature) {
3817 + xxmap.map.getTargetElement().style.cursor = 'pointer';
3818 + var coord = feature.getGeometry().getCoordinates();
3819 + // map_cm_popup.setPosition(evt.coordinate);
3820 + map_cm_popup.setPosition(coord);
3821 + var featid = feature.getId();
3822 + if (featid) {
3823 + QH('xmap-info-window', feature.get('name'));
3824 + } else {
3825 + var nodeFeat = getCorrespondingFeature(feature); // Return the node feature associated to pointer.
3826 + QH('xmap-info-window', nodeFeat.get('name'));
3827 + }
3828 + } else {
3829 + xxmap.map.getTargetElement().style.cursor = '';
3830 + QH('xmap-info-window', '');
3831 + }
3832 + });
3833 +
3834 + // Initialize context menu for openlayers
3835 + var contextmenu = new ContextMenu({
3836 + width: 160,
3837 + defaultItems: false, // defaultItems are Zoom In/Zoom Out
3838 + items: contextmenu_items
3839 + });
3840 +
3841 + // On right click open the context menu
3842 + contextmenu.on("abrir", function (evt) {
3843 + var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(ft, l){ return ft; });
3844 + xxmap.contextmenu.clear(); //Clear the context menu
3845 + if (feature) {
3846 + var featId = feature.getId();
3847 + if (featId) { addContextMenuItems(feature); } // Node feature will have an id
3848 + else { // If the feature is a pointer, Get its corresponding Node feature
3849 + var nodeFeature = getCorrespondingFeature(feature); //return the node feature associated to pointer.
3850 + if (nodeFeature) { addContextMenuItems(nodeFeature); }
3851 + else{ xxmap.contextmenu.extend(contextmenu_items); }
3852 + }
3853 + }
3854 + else { xxmap.contextmenu.extend(contextmenu_items); }
3855 + });
3856 + if (xxmap.contextmenu == null) { xxmap.contextmenu = contextmenu; }
3857 + xxmap.map.addControl(xxmap.contextmenu);
3858 + //addMeshOptions(); // Adds Mesh names to mesh dropdown
3859 + } catch (ex) {
3860 + console.log(ex);
3861 + QV('viewselectmapoption', false);
3862 + QV('devViewButton4', false);
3863 + xxmap = null;
3864 + }
3865 + }
3866 +
3867 + // Add feature on to Map for a Node
3868 + function addFeature(node, lat, lon) {
3869 + var existingfeature = getModifiedFeature(node._id); // Check if Corresponding feature was Modified ( Modifed feature are in active interactions list)
3870 + if (existingfeature) { xxmap.markersSource.addFeature(existingfeature); } // Add that existing feature
3871 + else { // Add new feature for this node
3872 + if (!lat && !lon) { var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1]; }
3873 +
3874 + // Fix the longiture and send an event to patch the db to correct coordinate format. It will cause second unnecessary updateFeature on this node to the map.
3875 + if (lon > 180) { lon = 180 - lon; meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: [ lat, lon ] }); }
3876 +
3877 + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
3878 + var feature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326','EPSG:3857')), name: node.name, status: node.conn, lat: lat, lon: lon });
3879 + feature.setId(node._id); // Set id for the device as nodeid
3880 + feature.setStyle(markerStyle(node));
3881 + xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source
3882 + }
3883 + }
3884 + }
3885 +
3886 + // Removing any feature from map
3887 + function removeFeature(node) {
3888 + var feature = xxmap.markersSource.getFeatureById(node._id);
3889 + if (feature) { xxmap.markersSource.removeFeature(feature); }
3890 + }
3891 +
3892 + // Update feature
3893 + function updateFeature(node, feature) {
3894 + if (node.conn != feature.get('status') ) { // Update status if changed
3895 + feature.set('status',node.conn)
3896 + feature.setStyle(markerStyle(node));
3897 + }
3898 +
3899 + // Since this is IP address location, add some fixed randomness to the location. Avoid pin pile-up.
3900 + var loc = map_parseNodeLoc(node);
3901 + if (loc != null) {
3902 + var lat = loc[0], lon = loc[1];
3903 + if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
3904 + feature.set('lat', lat); feature.set('lon', lon);
3905 + var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326', 'EPSG:3857');
3906 + feature.getGeometry().setCoordinates(modifiedCoordinates);
3907 + }
3908 + }
3909 +
3910 + if (node.name != feature.get('name') ) { feature.set('name', node.name); } // Update name
3911 + }
3912 +
3913 + // Enable dragging of a marker after edit option is clicked in context menu
3914 + function modifyMarkerloc(ft){
3915 + var featid = ft.getId();
3916 + if (featid) {
3917 + ft.setStyle(markerStyle(getNodeFromId(ft.a), 4)); // Switch to a user marker
3918 + if ( !getActiveInteractions(ft)) {
3919 + var dragInteration = new ol.interaction.Modify({
3920 + features: new ol.Collection([ft]),
3921 + pixelTolerance: 10
3922 + });
3923 + xxmap.activeInteractions.push({ featureid: featid, feature:ft, interaction: dragInteration }); // Also keep track of Interactions
3924 + xxmap.map.addInteraction(dragInteration);
3925 + }
3926 + }
3927 + }
3928 +
3929 + // This will be called when save location option is clicked in context menu
3930 + function saveMarkerloc(ft){
3931 + var featid = ft.getId()
3932 + if (featid) {
3933 + var actInteraction = getActiveInteractions(ft);
3934 + if (actInteraction) { // Check if the interaction exists
3935 + xxmap.map.removeInteraction(actInteraction); //Clear Interaction for that node
3936 + removeInteraction(featid);
3937 + var coord = ft.getGeometry().getCoordinates();
3938 + var v = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
3939 + if (v[0] > 180) { v[0] = 180 - v[0]; }
3940 + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
3941 + meshserver.send({ action: 'changedevice', nodeid: featid, userloc: vx }); // Send them to server to save changes
3942 + }
3943 + }
3944 + }
3945 +
3946 + // Style the Markers
3947 + function markerStyle(node, type) {
3948 + if (type == null) {
3949 + type = 0;
3950 + if (node.iploc) { type = 1; }
3951 + if (node.wifiloc) { type = 2; }
3952 + if (node.gpsloc) { type = 3; }
3953 + if (node.userloc) { type = 4; }
3954 + }
3955 + var types = ['', '-ip','-wifi','-gps','-user'];
3956 + var color = connStateColor(node);
3957 + var style = new ol.style.Style({
3958 + image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker' + types[type] + '.png' })
3959 + //stroke: new ol.style.Stroke({ color: '#000', width: 20 })
3960 + //text: new ol.style.Text({ text: 'bob!', textAlign: 'right', offsetX: -10, fill: new ol.style.Fill({ color: '#000' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) })
3961 + });
3962 +
3963 + //deviceMark.setStyle(new ol.style.Style({
3964 + // text: new ol.style.Text({
3965 + // //font: '12px helvetica,sans-serif',
3966 + // text: currentNode.name,
3967 + // textAlign: 'right',
3968 + // offsetX: -10,
3969 + // fill: new ol.style.Fill({ color: '#000' }),
3970 + // stroke: new ol.style.Stroke({ color: '#fff', width: 2 })
3971 + // }),
3972 + // image: new ol.style.Icon(({ color: [113, 140, 0], src: 'images/dot.png' })) }));
3973 +
3974 + return [ style ];
3975 + }
3976 +
3977 + // TODO: Add more connection status types. Currently we only change color if connection status changes
3978 + function connStateColor(nodeConn){
3979 + if (nodeConn.conn == 1 || nodeConn.conn == 3 || nodeConn.conn == 5) { return '#00ffdd'; } // Green for connected devices
3980 + return '#C70039'; // Red if the Agent is not connected
3981 + }
3982 +
3983 + // Add save/edit option to context menu
3984 + function addContextMenuItems(feature) {
3985 + if (getActiveInteractions(feature)) { // If this feature is modified then display save option in contextmenu
3986 + map_cm_saveMarker.data = feature;
3987 + xxmap.contextmenu.push(map_cm_saveMarker);
3988 + } else {
3989 + map_cm_editMarker.data = feature;
3990 + xxmap.contextmenu.push(map_cm_editMarker);
3991 + var node = getNodeFromId(feature.a);
3992 + if (node.userloc) {
3993 + map_cm_clearMarker.data = feature;
3994 + xxmap.contextmenu.push(map_cm_clearMarker);
3995 + }
3996 + }
3997 + map_cm_nodemenu_items.forEach(function (item){
3998 + if (item.text == "Aumentar o zoom até o limite" || item.text == "Diminuir o zoom até o limite") { item.data = feature; }
3999 + else { if (item != '-') { item.data = feature.getId(); } }
4000 + });
4001 + xxmap.contextmenu.extend(map_cm_nodemenu_items);
4002 + }
4003 +
4004 + // Return a active Interaction if it exists in activeInteractions list
4005 + function getActiveInteractions(feature) {
4006 + var featid = feature.getId();
4007 + for (var i = 0; i < xxmap.activeInteractions.length; i++) {
4008 + if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].interaction; }
4009 + }
4010 + return false;
4011 + }
4012 +
4013 + // Return Modified feature based on Id
4014 + function getModifiedFeature(featid) {
4015 + if (featid) {
4016 + for (var i = 0; i < xxmap.activeInteractions.length; i++) {
4017 + if (xxmap.activeInteractions[i].featureid == featid) { return xxmap.activeInteractions[i].feature; }
4018 + }
4019 + }
4020 + return null;
4021 + }
4022 +
4023 + // Remove Interaction
4024 + function removeInteraction(ftid) {
4025 + var index = -1;
4026 + for (var i = 0; i < xxmap.activeInteractions.length; i++) {
4027 + if (xxmap.activeInteractions[i].featureid === ftid) { index = i; break; }
4028 + }
4029 + if (index >= 0) { xxmap.activeInteractions.splice(index, 1); }
4030 + }
4031 +
4032 + // Check if pointer coordinates are equal to features and return node feature
4033 + function getCorrespondingFeature(pointerFeat) {
4034 + var pointerCoord = pointerFeat.getGeometry().getCoordinates();
4035 + for (var i = 0; i < xxmap.activeInteractions.length ; i++) {
4036 + var modifiedFeatures = xxmap.activeInteractions[i].feature;
4037 + var fearCoord = modifiedFeatures.getGeometry().getCoordinates();
4038 + if (fearCoord[0].toFixed(5) == pointerCoord[0].toFixed(5) && fearCoord[1].toFixed(5) == pointerCoord[1].toFixed(5) ) { return modifiedFeatures; }
4039 + }
4040 + return null;
4041 + }
4042 +
4043 + // Refresh the map and clear list
4044 + function refreshMap(reset, rebound){
4045 + if (reset) {
4046 + xxmap.map.setTarget(null);
4047 + xxmap.map = null;
4048 + xxmap.markersSource = null;
4049 + xxmap.mapView = null;
4050 + xxmap.mapLayer = null;
4051 + xxmap.activeInteractions = []; // Clear Active Interaction list
4052 + }
4053 + //clearMeshOptions();
4054 + //onSelectMeshChange();
4055 + var box = updateMapMarkers();
4056 + if ((box != null) && (rebound || (box[4] == 1))) {
4057 + var clat = (box[0] + box[2]) / 2;
4058 + var clon = (box[1] + box[3]) / 2;
4059 + var cscale = Math.max(Math.abs(box[0] - box[2]), Math.abs(box[1] - box[3]));
4060 + var view = xxmap.map.getView();
4061 + view.setCenter(ol.proj.transform([clon, clat], 'EPSG:4326', 'EPSG:3857'));
4062 + var i = 360, j = -2;
4063 + while (i > cscale) { j++; i = i / 2; }
4064 + view.setZoom(j);
4065 + }
4066 + }
4067 +
4068 + // Called When Place a node option is clicked from context menu
4069 + function placeNode(coords) {
4070 + if (xxdialogMode) return;
4071 + var x = '<div style=margin-bottom:6px><label for=selectnode-search>' + "Procurar" + '</label>&nbsp&nbsp<input type=text placeholder="' + "Nome do dispositivo" + '" id="selectnode-search" onchange=onPlaceNodeInputChange() onkeyup=onPlaceNodeInputChange() autocomplete=off style=width:120px></div><div id=placenode style="height:254px;overflow-y:auto;width:100%;margin:12px 1px 4px 1px;"><div id=noNodesMapPlace style=text-align:center;width:100%;display:none>' + "Nenhum dispositivo encontrado." + '</div>';
4072 + for (var i in nodes) {
4073 + x += '<div class=noselect id=' + nodes[i]._id + '-rowid onclick=selectNodeToPlace(event,\''+ nodes[i]._id +'\') style=background-color:lightgray;margin-bottom:4px;border-radius:2px><input name=PlaceMapDeviceCheckbox id=' + nodes[i]._id + '-checkid type=checkbox style=width:16px;display:inline />';
4074 + x += '<div class=j' + nodes[i].icon + ' style=width:16px;height:16px;margin-top:2px;margin-right:4px;display:inline-block></div><div style=width:16px;display:inline>' + nodes[i].name + '</div></div>';
4075 + }
4076 + setDialogMode(2, "Selecione um nó para colocar", 3, placeNodeEx, x + '</div>', coords);
4077 + onPlaceNodeInputChange();
4078 + }
4079 +
4080 + function placeNodeEx(button, coords) {
4081 + var elements = document.getElementsByName('PlaceMapDeviceCheckbox');
4082 + for (var i in elements) {
4083 + if (elements[i].checked) {
4084 + var node = getNodeFromId(elements[i].id.substring(0, elements[i].id.length - 8));
4085 + if (node) {
4086 + var feature = xxmap.markersSource.getFeatureById(i);
4087 + var v = ol.proj.transform(coords, 'EPSG:3857', 'EPSG:4326');
4088 + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
4089 + if (feature) {
4090 + feature.getGeometry().setCoordinates(coords);
4091 + var activeInteraction = getActiveInteractions(feature);
4092 + if (activeInteraction) {
4093 + saveMarkerloc(feature);
4094 + } else { // If this feature is not saved after its location is changed, then send updated coords to server.
4095 + meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // Send them to server to save changes
4096 + }
4097 + } else {
4098 + meshserver.send({ action: 'changedevice', nodeid: node._id, userloc: vx }); // This Node is not yet added to maps.
4099 + }
4100 + }
4101 + }
4102 + }
4103 + }
4104 +
4105 + // Called when the user changes the search box
4106 + function onPlaceNodeInputChange() {
4107 + updatePlaceNodeTable(Q('selectnode-search').value.trim().toLowerCase());
4108 + }
4109 +
4110 + // Update the list of devices in the "place on map" table
4111 + function updatePlaceNodeTable(inputSearch) {
4112 + var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), count = 0;
4113 + for (var i in nodes) {
4114 + var visible = ((nodes[i].namel.indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.indexOf(inputSearch) >= 0));
4115 + if (visible) { count++; }
4116 + QV(nodes[i]._id + '-rowid', visible);
4117 + }
4118 + QV('noNodesMapPlace', count == 0);
4119 + //console.log(selected);
4120 + //for (var i in nodes) {
4121 + // if ((nodes[i].name.toLowerCase().indexOf(inputSearch) >= 0 || inputSearch == '') || (nodes[i].rnamel != null && nodes[i].rnamel.toLowerCase().indexOf(inputSearch) >= 0)) {
4122 + // console.log(selected.indexOf(nodes[i]._id));
4123 + // x += '<div class=noselect id=' + nodes[i]._id + '-rowid onclick=selectNodeToPlace(event,\''+ nodes[i]._id +'\') style=background-color:lightgray;margin-bottom:4px;border-radius:2px><input name=PlaceMapDeviceCheckbox id=' + nodes[i]._id + '-checkid type=checkbox style=width:16px;display:inline ' + ((selected.indexOf(nodes[i]._id) >= 0)?'checked':'') + ' />';
4124 + // x += '<div class=j' + nodes[i].icon + ' style=width:16px;height:16px;margin-top:2px;margin-right:4px;display:inline-block></div><div style=width:16px;display:inline>' + nodes[i].name + '</div></div>';
4125 + // }
4126 + //}
4127 + //if (x == '') { x = '<div style=text-align:center;width:100%>No devices found.</div>'; }
4128 + //QH('placenode', '');
4129 + }
4130 +
4131 + // Called when a user clicks on a device to toggle selection for placement on map.
4132 + function selectNodeToPlace(e, id) {
4133 + // Toggle checkbox if needed
4134 + if (e.target.name != 'PlaceMapDeviceCheckbox') { var inputElement = Q(id + '-checkid'); inputElement.checked = !inputElement.checked; }
4135 +
4136 + // Check button state
4137 + var elements = document.getElementsByName('PlaceMapDeviceCheckbox'), checkcount = 0;
4138 + for (var i in elements) { if (elements[i].checked) checkcount++; }
4139 + QE('idx_dlgOkButton', checkcount > 0);
4140 + }
4141 +
4142 + // Add option for available meshes in mesh Dropdown
4143 + function addMeshOptions(addMeshid, meshName) {
4144 + //var meshOptions = Q('select-mesh');
4145 + //if (addMeshid && meshName) {
4146 + // var option = document.createElement('option');
4147 + // option.value =addMeshid;
4148 + // option.text = meshName;
4149 + // meshOptions.add(option); // Add specific option
4150 + //}
4151 + //else {
4152 + // for (var i in meshes) { // Add all options
4153 + // var option = document.createElement('option');
4154 + // option.value = i;
4155 + // option.text = meshes[i].name;
4156 + // meshOptions.add(option);
4157 + // }
4158 + //}
4159 + }
4160 +
4161 + // Remove/Modify options in Mesh dropdown (if modMeshname is defined then Modify else Remove)
4162 + function meshOptionRmvMod(delMeshid, modMeshname){
4163 + //var meshOptions = Q('select-mesh');
4164 + //if (delMeshid) {
4165 + // var index=-1;
4166 + // for (var i = 1; i < meshOptions.options.length; i++) {
4167 + // if (meshOptions[i].value === delMeshid) { index=i; }
4168 + // }
4169 + // if (index > 0) {
4170 + // if (modMeshname) {
4171 + // meshOptions[index].innerHTML=modMeshname; // If Mesh name is Modified
4172 + // }
4173 + // else { meshOptions.remove(index); }
4174 + // }
4175 + //}
4176 + }
4177 +
4178 + //Check if there is any mesh created
4179 + function meshExists() {
4180 + for (var i in meshes) { if (meshes[i]) { return true; } }
4181 + return false;
4182 + }
4183 +
4184 + // Reset Mesh dropdown option to 'All' when a current view mesh is deleted.
4185 + function setMeshView(emeshid) {
4186 + var selectMeshElement=Q('select-mesh');
4187 + var selectedIndex = selectMeshElement.selectedIndex;
4188 + if (selectMeshElement[selectedIndex].value == emeshid) { selectMeshElement[0].selected = true; onSelectMeshChange(); }
4189 + }
4190 +
4191 + // Clear all mesh options except 'All'
4192 + function clearMeshOptions() {
4193 + //var meshOptions=Q('select-mesh');
4194 + //for(var i = meshOptions.options.length - 1 ; i > 0 ; i--) { meshOptions.remove(i); }
4195 + }
4196 +
4197 + // Make a http get call- Replace this with AJAX get if jquery is used
4198 + function getSearchLocation() {
4199 + try {
4200 + var searchdata = Q('mapSearchLocation').value.trim();
4201 + if (searchdata.length > 0) {
4202 + var xmlhttp = new XMLHttpRequest(); // Compatible with Chrome, Opera, Safari, IE7+, Firefox.
4203 + xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { formatSearchData(xmlhttp.responseText); } }
4204 + xmlhttp.open('GET', 'https://nominatim.openstreetmap.org/search?q=' + searchdata + '&format=json', true); // Get request
4205 + xmlhttp.send();
4206 + }
4207 + } catch (e) {}
4208 + }
4209 +
4210 + // Format data recieved from nominatim API and display it on content window
4211 + function formatSearchData(data) {
4212 + try {
4213 + QH('xmapSearchResults','');
4214 + var dataInfo = JSON.parse(data), count = 0, x = '<div class="xmapItem">';
4215 + for (var i = 0; i < dataInfo.length; i++) {
4216 + if (dataInfo[i].display_name && dataInfo[i].boundingbox[0] && dataInfo[i].boundingbox[1] && dataInfo[i].boundingbox[2] && dataInfo[i].boundingbox[3]) {
4217 + count++;
4218 + var itemclass = (i % 2 == 0)?'xmapItemSel1':'xmapItemSel1';
4219 + x += '<div class="' + itemclass + '" onclick=mapGotoSelectedLocation(this)><div>' + dataInfo[i].display_name + '</div><div style=display:none>' + dataInfo[i].boundingbox[0] + '!#!' + dataInfo[i].boundingbox[1] + '!#!' + dataInfo[i].boundingbox[2] + '!#!' + dataInfo[i].boundingbox[3] + '</div></div>';
4220 + }
4221 + }
4222 + x += '</div>';
4223 + if (count == 1) {
4224 + // If only one result is returned then zoom to that location
4225 + var extent = [ parseFloat(dataInfo[0].boundingbox[2]), parseFloat(dataInfo[0].boundingbox[0]), parseFloat(dataInfo[0].boundingbox[3]), parseFloat(dataInfo[0].boundingbox[1]) ];
4226 + zoomToExtent(extent);
4227 + } else {
4228 + if (count == 0) { x = '<div style=width:200px>' + "Nenhum local encontrado." + '<div>'; }
4229 + QV('xmapSearchResultsDlg', true);
4230 + }
4231 + QH('xmapSearchResults', x);
4232 + }
4233 + catch (e) {}
4234 + }
4235 +
4236 + // Zoom into the bounding box
4237 + function mapGotoSelectedLocation(obj) {
4238 + var objchildren = obj.children;
4239 + var boundingBox = objchildren[1].innerHTML.split('!#!');
4240 + var extent = [parseFloat(boundingBox[2]), parseFloat(boundingBox[0]), parseFloat(boundingBox[3]), parseFloat(boundingBox[1])];
4241 + //Q('search-location').value = objchildren[0].innerHTML;
4242 + zoomToExtent(extent);
4243 + mapCloseSearchWindow();
4244 + }
4245 +
4246 + // Close the search window
4247 + function mapCloseSearchWindow() {
4248 + QH('xmapSearchResults', '');
4249 + QV('xmapSearchResultsDlg', false);
4250 + }
4251 +
4252 + // Zoom to specific cordinates
4253 + function zoomToLocation(coordinates, zoomVal) {
4254 + var view = xxmap.map.getView();
4255 + view.setCenter(coordinates);
4256 + view.setZoom(zoomVal);
4257 + }
4258 +
4259 + function zoomToFitExtent() {
4260 + var features = xxmap.markersSource.getFeatures();
4261 + if (features.length > 0) {
4262 + var extent = xxmap.markersSource.getExtent();
4263 + xxmap.map.getView().fit(extent, xxmap.map.getSize());
4264 + }
4265 + }
4266 +
4267 + function zoomToExtent(extent){
4268 + var boundingExtent = ol.proj.transformExtent(extent, ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
4269 + xxmap.map.getView().fit(boundingExtent, xxmap.map.getSize());
4270 + }
4271 +
4272 + {{{EndGeoLocationJS}}}
4273 +
4274 + //
4275 + // MY DEVICE
4276 + //
4277 + function refreshDevice(nodeid) {
4278 + if (!currentNode || currentNode._id != nodeid) return;
4279 + gotoDevice(nodeid, xxcurrentView, true);
4280 + }
4281 +
4282 + function getNodeRights(nodeid) {
4283 + var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
4284 + return mesh.links[userinfo._id].rights;
4285 + }
4286 +
4287 + var currentNode;
4288 + var powerTimelineNode = null;
4289 + var powerTimelineReq = null;
4290 + var powerTimelineUpdate = null;
4291 + var powerTimeline = null;
4292 + function getCurrentNode() { return currentNode; };
4293 + function gotoDevice(nodeid, panel, refresh, event) {
4294 + // Remind the user to verify the email address
4295 + if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para a guia \"Minha conta\" para alterar e verificar um endereço de email."); return; }
4296 +
4297 + // Remind the user to add two factor authentication
4298 + if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Segurança da Conta", 1, null, "Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para a guia \"Minha conta\" e consulte a seção \"Segurança da conta\"."); return; }
4299 +
4300 + if (event && (event.shiftKey == true)) {
4301 + // Open the device in a different tab
4302 + window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid);
4303 + return;
4304 + }
4305 +
4306 + //disconnectAllKvmFunction();
4307 + var node = getNodeFromId(nodeid);
4308 + var mesh = meshes[node.meshid];
4309 + var meshrights = mesh.links[userinfo._id].rights;
4310 + if (!currentNode || currentNode._id != node._id || refresh == true) {
4311 + currentNode = node;
4312 +
4313 + // Add node name
4314 + var nname = EscapeHtml(node.name);
4315 + if (nname.length == 0) { nname = '<i>' + "Nenhum" + '</i>'; }
4316 + if (((meshrights & 4) != 0) && ((!mesh.flags) || ((mesh.flags & 2) == 0))) { nname = '<span tabindex=0 title=\"' + "clique aqui para criar um grupo de dispositivos" + '\" onclick=showEditNodeValueDialog(0) onkeyup="if (event.key == \'Enter\') showEditNodeValueDialog(0)" style=cursor:pointer>' + nname + ' <img class=hoverButton src="images/link5.png" /></span>'; }
4317 + nname += '<span style=color:#AAA;font-size:small> - ' + EscapeHtml(mesh.name) + '</span>';
4318 + QH('p10deviceName', nname);
4319 + QH('p11deviceName', nname);
4320 + QH('p12deviceName', nname);
4321 + QH('p13deviceName', nname);
4322 + QH('p14deviceName', nname);
4323 + QH('p15deviceName', "Console - " + nname);
4324 + QH('p16deviceName', nname);
4325 + QH('p17deviceName', nname);
4326 + QH('p19deviceName', nname);
4327 +
4328 + // Node attributes
4329 + var x = '<table style=width:100%>';
4330 +
4331 + // Attribute: Mesh
4332 + x += addDeviceAttribute('<span title=\"' + "O nome do grupo de dispositivos ao qual este computador pertence." + '\">' + "Grupo" + '</span>', '<a href=# title=\"' + "O nome do grupo de dispositivos ao qual este computador pertence" + '\" onclick=gotoMesh("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
4333 +
4334 + // Attribute: Name
4335 + if ((node.rname != null) && (node.name != node.rname)) { x += addDeviceAttribute('<span title="The name of this computer as set in the operating system">Name</span>', '<span title="The name of this computer as set in the operating system">' + EscapeHtml(node.rname) + '</span>'); }
4336 +
4337 + // Attribute: Host
4338 + if ((features & 1) == 0) { // If not WAN-only, local hostname is in use
4339 + if ((meshrights & 4) != 0) {
4340 + if (node.host) {
4341 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
4342 + } else {
4343 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>' + "Nenhum" + '</i></span>');
4344 + }
4345 + } else {
4346 + x += addDeviceAttribute("Hostname", EscapeHtml(node.host));
4347 + }
4348 + }
4349 +
4350 + // Attribute: Description
4351 + var description = node.desc?EscapeHtml(node.desc):('<i>' + "Nenhum" + '</i>');
4352 + if ((meshrights & 4) != 0) {
4353 + x += addDeviceAttribute("Descrição", '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + ' <img class=hoverButton src="images/link5.png" /></span>');
4354 + } else {
4355 + x += addDeviceAttribute("Descrição", description);
4356 + }
4357 +
4358 + // Attribute: Mesh Agent
4359 + var agentsStr = ["Desconhecido", "Windows 32 Bits console", "Windows 64 Bits console", "Serviço Windows 32 Bits", "Serviço Windows 64 Bits", "Linux 32 bits", "Linux 64 bits", "MIPS", "XENx86", "Android ARM", "Linux ARM", "MacOS 32 bits", "Android x86", "PogoPlug ARM", "Android APK", "Linux Poky x86-32 bits", "MacOS 64 bits", "ChromeOS", "Linux Poky x86-64 bits", "Linux NoKVM x86-32 bits", "Linux NoKVM x86-64 bits", "Windows MinCore console", "Windows MinCore service", "NodeJS", "ARM-Linaro", "ARMv6l / ARMv7l", "ARMv8 64bit", "ARMv6l / ARMv7l / NoKVM", "Desconhecido", "Desconhecido", "FreeBSD x86-64"];
4360 + if ((node.agent != null) && (node.agent.id != null) && (node.agent.ver != null)) {
4361 + var str = '';
4362 + if (node.agent.id <= agentsStr.length) { str = agentsStr[node.agent.id]; } else { str = agentsStr[0]; }
4363 + if (node.agent.ver != 0) { str += ' v' + node.agent.ver; }
4364 + x += addDeviceAttribute("Mesh Agent", str);
4365 + }
4366 +
4367 + // Attribute: Intel AMT
4368 + if (node.intelamt != null) {
4369 + var str = '';
4370 + var provisioningStates = { 0: nobreak("Não ativado (pré)"), 1: nobreak("Não ativado (entrada)"), 2: nobreak("ativado") };
4371 + if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + "Estado desconhecido" + '</i>, v' + node.intelamt.ver; } else
4372 +
4373 + if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "ativado" + '</i>'; }
4374 + else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Estado da versão desconhecida" + '</i>'; }
4375 + else {
4376 + str += provisioningStates[node.intelamt.state];
4377 + if ((node.intelamt.state == 2) && node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' <span title=\"' + "O Intel AMT é ativado no modo de controle do cliente" + '\">' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str += ' <span title=\"' + "O Intel AMT é ativado no modo de controle de administrador" + '\">' + "ACM" + '</span>'; } }
4378 + str += (', v' + node.intelamt.ver);
4379 + }
4380 +
4381 + if (node.intelamt.tls == 1) { str += ', <span title=\"' + "O Intel AMT está configurado com segurança de rede TLS" + '\">' + "TLS" + '</span>'; }
4382 + if (node.intelamt.state == 2) {
4383 + if (node.intelamt.user == null || node.intelamt.user == '') {
4384 + if ((meshrights & 4) != 0) {
4385 + str += ', <i style=color:#FF0000;cursor:pointer title=\"' + "Editar Intel & reg; Credenciais AMT" + '\" onclick=editDeviceAmtSettings("' + node._id + '")>' + "Sem credenciais" + '</i>';
4386 + } else {
4387 + str += ', <i style=color:#FF0000>' + "Sem credenciais" + '</i>';
4388 + }
4389 + }
4390 + str += ' ';
4391 + if ((meshrights & 4) != 0) {
4392 + str += '<img src=images/link4.png height=10 width=10 title=\"' + "Editar Intel & reg; Credenciais AMT" + '\" style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
4393 + }
4394 + }
4395 +
4396 + var meName = '<span title=\"Intel&reg; Manageability Engine\">' + "Intel&reg; ME" + '<span>';
4397 + if (typeof node.intelamt.sku == 'number') {
4398 + if ((node.intelamt.sku & 8) != 0) { meName = '<span title=\"' + "Intel&reg; Tecnologia de gerenciamento ativo" + '\">' + "Intel&reg; AMT" + '<span>'; }
4399 + else if ((node.intelamt.sku & 16) != 0) { meName = '<span title=\"' + "Intel&reg; Gerenciamento padrão" + '\">' + "Intel&reg; SM" + '<span>'; }
4400 + }
4401 + x += addDeviceAttribute(meName, str);
4402 + }
4403 +
4404 + if (mesh.mtype == 2) {
4405 + // Attribute: Mesh Agent Tag
4406 + if ((node.agent != null) && (node.agent.tag != null)) {
4407 + var tag = EscapeHtml(node.agent.tag);
4408 + if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
4409 + x += addDeviceAttribute("Etiqueta do agente", tag);
4410 + }
4411 + } else {
4412 + // Attribute: Intel AMT Tag
4413 + if ((node.intelamt != null) && (node.intelamt.tag != null)) {
4414 + var tag = EscapeHtml(node.intelamt.tag);
4415 + if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
4416 + x += addDeviceAttribute("Intel&reg; Tag AMT ", tag);
4417 + }
4418 + }
4419 +
4420 + // Attribute: Intel AMT
4421 + //if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel&reg; AMT', node.intelamt.user); }
4422 +
4423 + // Operating system description
4424 + if (node.osdesc) { x += addDeviceAttribute("Sistema operacional", node.osdesc); }
4425 +
4426 + // Antivirus
4427 + if (node.av && node.av.length > 0) {
4428 + var y = [];
4429 + for (var i in node.av) {
4430 + if (node.av[i].product) {
4431 + var avx = EscapeHtml(node.av[i].product);
4432 + if (node.av[i].enabled !== true) { avx += ' - <span style=color:red>' + "Desativado" + '</span>'; }
4433 + if (node.av[i].updated !== true) { avx += ' - <span style=color:red>' + "Desatualizado" + '</span>'; }
4434 + if ((node.av[i].enabled == true) && (node.av[i].updated == true)) { avx += ' - <span style=color:green>' + "Ok" + '</span>'; }
4435 + y.push(avx);
4436 + }
4437 + }
4438 + x += addDeviceAttribute("Antivírus", y.join('<br />'));
4439 + }
4440 +
4441 + // Active Users
4442 + if (node.users && node.conn && (node.users.length > 0) && (node.conn & 1)) { x += addDeviceAttribute(format("Usuário ativo {0}", ((node.users.length > 1)?'s':'')), node.users.join(', ')); }
4443 +
4444 + // Attribute: Connectivity (Only show this if more than just the agent is connected).
4445 + var connectivity = node.conn;
4446 + if (connectivity && connectivity > 1) {
4447 + var cstate = [];
4448 + if ((node.conn & 1) != 0) cstate.push('<span title=\"' + "O agente de malha está conectado e pronto para uso." + '\">' + "Mesh Agent" + '</span>');
4449 + if ((node.conn & 2) != 0) cstate.push('<span title=\"' + "Intel&reg; O AMT CIRA está conectado e pronto para uso." + '\">' + "Intel&reg; AMT CIRA" + '</span>');
4450 + else if ((node.conn & 4) != 0) cstate.push('<span title=\"' + "Intel&reg; O AMT é roteável e pronto para uso." + '\">' + "Intel&reg; AMT" + '</span>');
4451 + if ((node.conn & 8) != 0) cstate.push('<span title=\"' + "O agente de malha é alcançável usando outro agente como retransmissão." + '\">' + "Mesh Relay" + '</span>');
4452 + if ((node.conn & 16) != 0) { cstate.push('<span title=\"' + "A conexão MQTT com o dispositivo está ativa." + '\">' + "MQTT" + '</span>'); }
4453 + x += addDeviceAttribute("Conectividade", cstate.join(', '));
4454 + }
4455 +
4456 + // Node grouping tags
4457 + var groupingTags = '<i>' + "Nenhum" + '</i>';
4458 + if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span class="tagSpan">' + node.tags[i] + '</span>'; } }
4459 + if ((meshrights & 4) != 0) {
4460 + x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + ' <img class=hoverButton src="images/link5.png" /></span>');
4461 + } else {
4462 + x += addDeviceAttribute('Tags', groupingTags);
4463 + }
4464 +
4465 + x += '</table><br />';
4466 + // Show action button, only show if we have permissions 4, 8, 64
4467 + if ((meshrights & 76) != 0) { x += '<input type=button value=\"' + "Ações" + '\" title=\"' + "Execute ações de energia no dispositivo" + '\" onclick=deviceActionFunction() />'; }
4468 + x += '<input type=button value=\"' + "Notas" + '\" title=\"' + "Ver notas sobre este dispositivo" + '\" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
4469 + x += '<input type=button value=\"' + "Log de Evento" + '\" title=\"' + "Escreva um evento para este dispositivo" + '\" onclick=writeDeviceEvent("' + encodeURIComponent(node._id) + '") />';
4470 + //if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="Display a text message of the remote device" onclick=deviceToastFunction() />'; }
4471 + QH('p10html', x);
4472 +
4473 + // Show node last 7 days timeline
4474 + masterUpdate(256);
4475 +
4476 + // Show bottom buttons
4477 + x = '<div class="p10html3right">';
4478 + if ((meshrights & 4) != 0) {
4479 + // TODO: Show change group only if there is another mesh of the same type.
4480 + x += '&nbsp;<a href=# onclick=p10showChangeGroupDialog(["' + node._id + '"]) title=\"' + "Mova este dispositivo para um grupo de dispositivos diferente" + '\">' + "Alterar grupo" + '</a>';
4481 + x += '&nbsp;<a href=# onclick=p10showDeleteNodeDialog("' + node._id + '") title=\"' + "Remova este dispositivo" + '\">' + "Excluir dispositivo" + '</a>';
4482 + }
4483 + x += '</div><div class="p10html3left">';
4484 + if (mesh.mtype == 2) x += '<a href=# onclick=p10showNodeNetInfoDialog("' + node._id + '") title=\"' + "Mostrar informações da interface de rede do dispositivo" + '\">' + "Interfaces" + '</a>&nbsp;';
4485 + if (xxmap != null) x += '<a href=# onclick=p10showNodeLocationDialog("' + node._id + '") title=\"' + "Mostrar informações de localizações do dispositivo" + '\">' + "Localização" + '</a>&nbsp;';
4486 + if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a href=# onclick=p10showMeshCmdDialog(1,"' + node._id + '") title=\"' + "Roteador de tráfego usado para conectar-se a um dispositivo através deste servidor" + '.\">' + "Roteador" + '</a>&nbsp;';
4487 +
4488 + // RDP link, show this link only of the remote machine is Windows.
4489 + if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
4490 + if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a href=# onclick=p10clickOnce("' + node._id + '","RDP2",3389) title=\"' + "Requer o suporte Microsoft ClickOnce no seu navegador" + '.\">' + "RDP" + '</a>&nbsp;'; }
4491 + if (node.agent.id > 4) {
4492 + x += '<a href=# onclick=p10clickOnce("' + node._id + '","PSSH",22) title=\"' + "Requer o suporte Microsoft ClickOnce no seu navegador." + '\">' + "Putty" + '</a>&nbsp;';
4493 + x += '<a href=# onclick=p10clickOnce("' + node._id + '","WSCP",22) title=\"' + "Requer o suporte Microsoft ClickOnce no seu navegador." + '\">' + "WinSCP" + '</a>&nbsp;';
4494 + }
4495 + }
4496 +
4497 + // MQTT options
4498 + if ((meshrights == 0xFFFFFFFF) && (features & 0x00400000)) { x += '<a href=# onclick=p10showMqttLoginDialog("' + node._id + '") title=\"' + "Obtenha credenciais de login do MQTT para este dispositivo." + '\">' + "Login do MQTT" + '</a>&nbsp;'; }
4499 + x += '</div><br>'
4500 +
4501 + QH('p10html3', x);
4502 +
4503 + // Set the node power state
4504 + var powerstate = PowerStateStr(node.state);
4505 + //if (node.state == 0) { powerstate = 'Unknown State'; }
4506 + if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Agente conectado" + '\">' + "Agente conectado" + '</span>'; }
4507 + if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel&reg; AMT conectado" + '\">' + "Intel&reg; AMT conectado" + '</span>'; }
4508 + else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "Intel&reg; AMT detectado" + '\">' + "Intel&reg; AMT detectado" + '</span>'; }
4509 + if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title=\"' + "MQTT conectado" + '\">' + "Canal MQTT conectado" + '</span>'; }
4510 + if ((powerstate == '') && node.lastconnect) { powerstate = '<span style=font-size:12px>' + "Visto pela última vez:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>'; }
4511 + QH('MainComputerState', powerstate);
4512 +
4513 + // Set the node icon
4514 + Q('MainComputerImage').setAttribute('src', 'images/icons256-' + node.icon + '-1.png');
4515 + Q('MainComputerImage').className = ((!node.conn) || (node.conn == 0)?'gray':'');
4516 +
4517 + // Check if we have terminal and file access
4518 + var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
4519 + var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
4520 + var amtAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 2048) == 0));
4521 +
4522 + // Setup/Refresh the desktop tab
4523 + if (terminalAccess) { setupTerminal(); }
4524 + if (fileAccess) { setupFiles(); }
4525 + var consoleRights = ((meshrights & 16) != 0);
4526 + if (consoleRights) { setupConsole(); } else { if (panel == 15) { panel = 10; } }
4527 +
4528 + // Show or hide the tabs
4529 + // mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent
4530 + // node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console
4531 + QV('MainDevDesktop', (((mesh.mtype == 1) && ((typeof node.intelamt.sku !== 'number') || ((node.intelamt.sku & 8) != 0)))
4532 + || ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2)))))
4533 + && ((meshrights & 8) || (meshrights & 256))
4534 + );
4535 + QV('MainDevTerminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
4536 + QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
4537 + QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8) && amtAccess);
4538 + QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
4539 + QV('MainDevPlugins', false);
4540 + QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0));
4541 + QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
4542 +
4543 + // Setup/Refresh Intel AMT tab
4544 + var amtFrameNode = Q('p14iframe').contentWindow.getCurrentMeshNode();
4545 + if ((amtFrameNode != null) && (amtFrameNode._id != currentNode._id)) { Q('p14iframe').contentWindow.disconnect(); }
4546 + var online = ((node.conn & 6) != 0)?true:false; // If CIRA (2) or AMT (4) connected, enable Commander
4547 + Q('p14iframe').contentWindow.setConnectionState(online);
4548 + Q('p14iframe').contentWindow.setFrameHeight('650px');
4549 + Q('p14iframe').contentWindow.setAuthCallback(updateAmtCredentials);
4550 +
4551 + // Display "action" button on desktop/terminal/files
4552 + QV('deskActionsBtn', (meshrights & 72) != 0); // 72 = Wake-up + Remote Control permissions
4553 + QV('termActionsBtn', (meshrights & 72) != 0);
4554 + QV('filesActionsBtn', (meshrights & 72) != 0);
4555 +
4556 + // Request the power timeline
4557 + if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) {
4558 + QH('p10html2', '');
4559 + powerTimelineReq = currentNode._id;
4560 + meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
4561 + meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
4562 + meshserver.send({ action: 'getsysinfo', nodeid: currentNode._id });
4563 + QH('p17info', '');
4564 + }
4565 +
4566 + // Reset the desktop tools
4567 + QV('DeskTools', false);
4568 + showDeskToolsProcesses();
4569 +
4570 + // Ask for device events
4571 + refreshDeviceEvents();
4572 +
4573 + // Update the web page title
4574 + if ((currentNode) && (xxcurrentView >= 10) && (xxcurrentView < 20)) {
4575 + document.title = decodeURIComponent('{{{extitle}}}') + ' - ' + currentNode.name + ' - ' + mesh.name;
4576 + } else {
4577 + document.title = decodeURIComponent('{{{extitle}}}');
4578 + }
4579 +
4580 + // Clear user consent status if present
4581 + p11clearConsoleMsg();
4582 + p12clearConsoleMsg();
4583 + p13clearConsoleMsg();
4584 +
4585 + // Device refresh plugin handler
4586 + if (pluginHandler != null) { pluginHandler.callHook('onDeviceRefreshEnd', nodeid, panel, refresh, event); }
4587 + }
4588 + setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
4589 + if (!panel) panel = 10;
4590 + go(panel);
4591 + }
4592 +
4593 + function writeDeviceEvent(nodeid) {
4594 + if (xxdialogMode) return;
4595 + setDialogMode(2, "Adicionar evento do dispositivo", 3, writeDeviceEventEx, '<textarea id=d2devEvent style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>' + "Isso adicionará uma entrada ao log de eventos deste dispositivo." + '<span>', nodeid);
4596 + }
4597 +
4598 + function writeDeviceEventEx(buttons, tag) { meshserver.send({ action: 'setDeviceEvent', nodeid: decodeURIComponent(tag), msg: encodeURIComponent(Q('d2devEvent').value) }); }
4599 +
4600 + function showNotes(readonly, noteid) {
4601 + if (xxdialogMode) return;
4602 + setDialogMode(2, "Notas", 2, showNotesEx, '<textarea id=d2devNotes ro=' + readonly + ' noteid=' + noteid + ' readonly style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>' + "As notas do grupo de dispositivos podem ser visualizadas e alteradas por outros administradores do grupo de dispositivos." + '<span>', noteid);
4603 + meshserver.send({ action: 'getNotes', id: decodeURIComponent(noteid) });
4604 + }
4605 +
4606 + function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
4607 +
4608 + function deviceChat(e) {
4609 + if (xxdialogMode) return;
4610 + var url = '/messenger?id=meshmessenger/' + encodeURIComponent(currentNode._id) + '/' + encodeURIComponent(userinfo._id) + '&title=' + currentNode.name;
4611 + if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; }
4612 + if (e && (e.shiftKey == true)) {
4613 + window.open(url, 'meshmessenger:' + currentNode._id);
4614 + } else {
4615 + window.open(url, 'meshmessenger:' + currentNode._id, 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=400,height=560');
4616 + }
4617 + meshserver.send({ action: 'meshmessenger', nodeid: decodeURIComponent(currentNode._id) });
4618 + }
4619 +
4620 + function deviceToggleBackground() {
4621 + if (xxdialogMode) return;
4622 + meshserver.send({ action: 'msg', type: 'deskBackground', nodeid: currentNode._id, op: 1 }); // Toggle desktop background image
4623 + }
4624 +
4625 + function deviceUrlFunction() {
4626 + if (xxdialogMode) return;
4627 + setDialogMode(2, "Abrir página no dispositivo", 3, deviceUrlFunctionEx, '<input id=d2devurl placeholder="http://server.com" style=width:100%;overflow-y:scroll></input>');
4628 + Q('d2devurl').focus();
4629 + }
4630 +
4631 + function deviceUrlFunctionEx() {
4632 + meshserver.send({ action: 'msg', type: 'openUrl', nodeid: currentNode._id, url: Q('d2devurl').value });
4633 + }
4634 +
4635 + function deviceToastFunction() {
4636 + if (xxdialogMode) return;
4637 + setDialogMode(2, "Notificação de dispositivo", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
4638 + Q('d2devToast').focus();
4639 + }
4640 +
4641 + function deviceToastFunctionEx() {
4642 + meshserver.send({ action: 'toast', nodeids: [ currentNode._id ], title: 'MeshCentral', msg: Q('d2devToast').value });
4643 + }
4644 +
4645 + function deviceActionFunction() {
4646 + if (xxdialogMode) return;
4647 + var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
4648 + var x = "Selecione uma operação para executar neste dispositivo." + '<br /><br />';
4649 + var y = '<select id=d2deviceop style=float:right;width:250px>';
4650 + if ((meshrights & 64) != 0) { y += '<option value=100>' + "Ligar" + '</option>'; } // Wake-up permission
4651 + if ((meshrights & 8) != 0) { y += '<option value=4>' + "Hibernar" + '</option><option value=3>' + "Redefinir" + '</option><option value=2>' + "Desligar" + '</option>'; } // Remote control permission
4652 + if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Enviar Mensagem MQTT" + '</option>'; }
4653 + if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
4654 + y += '</select>';
4655 + x += addHtmlValue("Operação", y);
4656 + setDialogMode(2, "Ação do dispositivo", 3, deviceActionFunctionEx, x);
4657 + }
4658 +
4659 + function deviceActionFunctionEx() {
4660 + var op = Q('d2deviceop').value;
4661 + if (op == 100) {
4662 + // Device wake
4663 + meshserver.send({ action: 'wakedevices', nodeids: [currentNode._id] });
4664 + } else if (op == 103) {
4665 + // Send MQTT Message
4666 + p10showSendMqttMsgDialog([currentNode._id]);
4667 + } else if (op == 104) {
4668 + // Uninstall agent
4669 + p10showSendUninstallAgentDialog([currentNode._id]);
4670 + } else {
4671 + // Power operation
4672 + meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: parseInt(op) });
4673 + }
4674 + }
4675 +
4676 + // Called when MeshCommander needs new credentials or updated credentials.
4677 + function updateAmtCredentials(forceDialog) {
4678 + var node = getNodeFromId(currentNode._id);
4679 + if ((forceDialog == true) || (node.intelamt.user == null) || (node.intelamt.user == '')) {
4680 + editDeviceAmtSettings(currentNode._id, updateAmtCredentialsEx);
4681 + } else {
4682 + Q('p14iframe').contentWindow.connectButtonfunctionEx();
4683 + }
4684 + }
4685 +
4686 + function updateAmtCredentialsEx(button, tag) {
4687 + Q('p14iframe').contentWindow.connectButtonfunctionEx();
4688 + }
4689 +
4690 + // Look to see if we need to update the device timeline
4691 + function updateDeviceTimeline() {
4692 + if ((meshserver.State != 2) || (powerTimelineNode == null) || (powerTimelineUpdate == null) || (currentNode == null)) return;
4693 + if ((powerTimelineNode == powerTimelineReq) && (currentNode._id == powerTimelineNode) && (powerTimelineUpdate < Date.now())) {
4694 + powerTimelineUpdate = null;
4695 + meshserver.send({ action: 'powertimeline', nodeid: currentNode._id });
4696 + meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
4697 + }
4698 + }
4699 +
4700 + // Draw device power bars. The bars are 766px wide.
4701 + function drawDeviceTimeline() {
4702 + if ((currentNode == null) || (xxcurrentView < 10) || (xxcurrentView > 19)) return;
4703 + var timeline = null, now = Date.now();
4704 + if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
4705 +
4706 + // Calculate when the timeline starts
4707 + var d = new Date();
4708 + d.setHours(0, 0, 0, 0);
4709 + d = new Date(d.getTime() - (1000 * 60 * 60 * 24 * 6));
4710 + var timelineStart = d.getTime();
4711 +
4712 + // De-compact the timeline
4713 + var timeline2 = [];
4714 + if (timeline != null && timeline.length > 1) {
4715 + timeline2.push([ 0, timeline[1], timeline[0] ]); // Start, End, Power
4716 + var ct = timeline[1];
4717 + for (var i = 2; i < timeline.length; i += 2) {
4718 + var power = timeline[i], dt = now;
4719 + if (timeline.length > (i + 1)) { dt = timeline[i + 1]; }
4720 + timeline2.push([ ct, ct + dt, power ]); // Start, End, Power
4721 + ct = ct + dt;
4722 + }
4723 + }
4724 +
4725 + // Draw the timeline
4726 + var x = '', count = 1, date = new Date();
4727 + var totalWidth = Q('masthead').offsetWidth - (160 + 9 + 9 + 14); // Compute the total width of the power bar
4728 + date.setHours(0, 0, 0, 0);
4729 + for (var i = 0; i < 7; i++) {
4730 + var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
4731 + for (var j in timeline2) {
4732 + var block = timeline2[j];
4733 + if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
4734 + var ts = Math.max(start, block[0]);
4735 + var te = Math.min(Math.min(end, block[1]), now);
4736 + var width = Math.round(((te - ts) * totalWidth) / 86400000);
4737 + if (width > 0) {
4738 + var title = format('{0} from {1} to {2}.', powerStateStrings2[block[2]], printTime(new Date(ts)), printTime(new Date(te)));
4739 + datavalue += '<div class="pwState ' + powerColor(block[2]) + '" title="' + title + '" style="width:' + width + 'px;"></div>';
4740 + }
4741 + }
4742 + }
4743 + x += '<tr class=' + (((count % 2) == 0)?'altBack':'') + '><td><div>&nbsp;' + printDate(date) + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
4744 + ++count;
4745 + date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
4746 + }
4747 + QH('p10html2', '<table cellpadding=2 cellspacing=0><thead><tr style=><th scope=col style=text-align:center;width:150px>' + "Dia" + '</th><th scope=col style=text-align:center><a download href="devicepowerevents.ashx?id=' + currentNode._id + '" onclick="setDialogMode(0)"><img title=\"' + "Download de eventos de energia" + '\" src="images/link4.png" /></a>' + "Estado de energia de 7 dias" + '</th></tr></thead><tbody>' + x + '</tbody></table>');
4748 + }
4749 +
4750 + // Return a color for the given power state
4751 + function powerColor(x) { if (x < powerColorTable.length) { return powerColorTable[x]; } return 'pwsYellow'; }
4752 +
4753 + // Return true if the time block is visible within the start/end period
4754 + function isTimeBlockInside(start, end, blockStart, blockEnd) {
4755 + if ((blockStart < start) && (blockEnd > end)) return true; // Block is wider than timespan
4756 + if ((blockStart > start) && (blockStart < end)) return true;
4757 + if ((blockEnd > start) && (blockEnd < end)) return true;
4758 + return false;
4759 + }
4760 +
4761 + function addDeviceAttribute(name, value) { return '<tr><td class=style7>' + name + '</td><td class=style9>' + value + '</td></tr>'; }
4762 +
4763 + function editDeviceAmtSettings(nodeid, func, arg) {
4764 + if (xxdialogMode) return;
4765 + var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
4766 + if ((meshrights & 4) == 0) return;
4767 + x += addHtmlValue("Nome de usuário", '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
4768 + x += addHtmlValue("Senha", '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
4769 + x += addHtmlValue("Segurança", '<select id=dp10tls style=width:236px><option value=0>' + "Sem segurança TLS" + '</option><option value=1>' + "Segurança TLS necessária" + '</option></select>');
4770 + if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
4771 + setDialogMode(2, "Editar Intel & reg; Credenciais AMT", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg });
4772 + if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
4773 + Q('dp10tls').value = node.intelamt.tls;
4774 + validateDeviceAmtSettings();
4775 + }
4776 +
4777 + function validateDeviceAmtSettings() {
4778 + QE('idx_dlgOkButton', passwordcheck(Q('dp10password').value));
4779 + }
4780 +
4781 + function editDeviceAmtSettingsEx(button, tag) {
4782 + if (button == 2) {
4783 + // Delete button pressed, remove credentials
4784 + meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: '', pass: '' } });
4785 + } else {
4786 + // Change Intel AMT credentials
4787 + var amtuser = Q('dp10username').value;
4788 + if (amtuser == '') amtuser = 'admin';
4789 + var amtpass = Q('dp10password').value;
4790 + if (amtpass == '') amtuser = '';
4791 + meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
4792 + tag.node.intelamt.user = amtuser;
4793 + tag.node.intelamt.tls = Q('dp10tls').value;
4794 + if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); }
4795 + }
4796 + }
4797 +
4798 + function p10showSendMqttMsgDialog(nodeids) {
4799 + if (xxdialogMode) return false;
4800 + var x = addHtmlValue("Tema", '<input id=dp2topic style=width:230px maxlength=64 onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1) />');
4801 + x += addHtmlValue("Mensagem", '<div style=width:230px;margin:0;padding:0><textarea id=dp2msg maxlength=4096 style=width:100%;height:150px;resize:none onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1)></textarea></div>');
4802 + setDialogMode(2, "Enviar mensagem MQTT", 3, p10showSendMqttMsgDialogEx, x, nodeids);
4803 + p10validateSendMqttMsgDialog();
4804 + Q('dp2topic').focus();
4805 + return false;
4806 + }
4807 +
4808 + function p10validateSendMqttMsgDialog() {
4809 + QE('idx_dlgOkButton', (Q('dp2topic').value.length > 0) && (Q('dp2msg').value.length > 0));
4810 + }
4811 +
4812 + function p10showSendMqttMsgDialogEx(b, nodeids) {
4813 + meshserver.send({ action: 'sendmqttmsg', nodeids: nodeids, topic: Q('dp2topic').value, msg: Q('dp2msg').value });
4814 + }
4815 +
4816 + function p10showSendUninstallAgentDialog(nodeids) {
4817 + if (xxdialogMode) return false;
4818 + var x = '';
4819 + if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
4820 + x += '<br /><br />';
4821 + if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
4822 + x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirme" + '</label>';
4823 + setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
4824 + p10validateSendUninstallAgentDialog();
4825 + return false;
4826 + }
4827 +
4828 + function p10validateSendUninstallAgentDialog() { QE('idx_dlgOkButton', Q('p10check').checked); }
4829 + function p10showSendUninstallAgentDialogEx(b, nodeids) { meshserver.send({ action: 'uninstallagent', nodeids: nodeids }); }
4830 +
4831 + function p10showChangeGroupDialog(nodeids) {
4832 + if (xxdialogMode) return false;
4833 + var targetMeshId = null;
4834 + if (nodeids.length == 1) { try { targetMeshId = meshes[getNodeFromId(nodeids[0])]._id; } catch (ex) { } }
4835 +
4836 + // List all available alternative groups
4837 + var y = '<select id=p10newGroup style=width:236px>', count = 0;
4838 + for (var i in meshes) {
4839 + var meshrights = meshes[i].links[userinfo._id].rights;
4840 + if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += '<option value=\'' + meshes[i]._id + '\'>' + meshes[i].name + '</option>'; }
4841 + }
4842 + y += '</select>';
4843 +
4844 + if (count > 0) {
4845 + var x = (nodeids.length == 1) ? ("Selecione um novo grupo para este dispositivo" + '<br /><br />') : ("Selecione um novo grupo para dispositivos selecionados" + '<br /><br />');
4846 + x += addHtmlValue("Novo grupo de dispositivos", y);
4847 + setDialogMode(2, "Alterar grupo", 3, p10showChangeGroupDialogEx, x, nodeids);
4848 + } else {
4849 + setDialogMode(2, "Alterar grupo", 1, null, "Não existe outro grupo de dispositivos do mesmo tipo.");
4850 + }
4851 + return false;
4852 + }
4853 +
4854 + function p10showChangeGroupDialogEx(b, nodeids) {
4855 + meshserver.send({ action: 'changeDeviceMesh', nodeids: nodeids, meshid: Q('p10newGroup').value });
4856 + }
4857 +
4858 + function p10showDeleteNodeDialog(nodeid) {
4859 + if (xxdialogMode) return false;
4860 + var x = format("Tem certeza de que deseja excluir o nó {0}?", EscapeHtml(currentNode.name)) + '<br /><br /><label><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirme" + '</label>';
4861 + setDialogMode(2, "Excluir nó", 3, p10showDeleteNodeDialogEx, x, nodeid);
4862 + p10validateDeleteNodeDialog();
4863 + return false;
4864 + }
4865 +
4866 + function p10validateDeleteNodeDialog() {
4867 + QE('idx_dlgOkButton', Q('p10check').checked);
4868 + }
4869 +
4870 + function p10showDeleteNodeDialogEx(buttons, nodeid) {
4871 + meshserver.send({ action: 'removedevices', nodeids: [ nodeid ] });
4872 + }
4873 +
4874 + function p10clickOnce(nodeid, protocol, port) {
4875 + meshserver.send({ action: 'getcookie', nodeid: nodeid, tcpport: port, tag: 'clickonce', protocol: protocol });
4876 + return false;
4877 + }
4878 +
4879 + // Show current location
4880 + var d2map = null;
4881 + function p10showNodeLocationDialog() {
4882 + if ((xxdialogMode != null) && (xxdialogTag == '@xxmap')) { setDialogMode(0); } else { if (xxdialogMode) return false; }
4883 + var markers = [], types = ['iploc', 'wifiloc', 'gpsloc', 'userloc'], boundingBox = null;
4884 +
4885 + for (var loctype in types) {
4886 + if (currentNode[types[loctype]] != null) {
4887 + var loc = currentNode[types[loctype]].split(','), lat = parseFloat(loc[0]), lon = parseFloat(loc[1]);
4888 + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
4889 + var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lon, lat])) });
4890 + deviceMark.setStyle(markerStyle(currentNode, parseInt(loctype) + 1));
4891 + markers.push(deviceMark);
4892 +
4893 + if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
4894 + }
4895 + }
4896 + }
4897 +
4898 + // Setup the device mark layer
4899 + var vectorSource = new ol.source.Vector({ features: markers });
4900 + var vectorLayer = new ol.layer.Vector({ source: vectorSource });
4901 +
4902 + //var x = '<div><a href="https://www.google.com/maps/preview/@' + lat + ',' + lng + ',12z" rel="noreferrer noopener" target=_blank>Open in Google maps</a></div>';
4903 + var x = '<div id=d2map style=width:100%;height:300px></div>';
4904 + setDialogMode(2, "Localização do dispositivo", 1, null, x, '@xxmap');
4905 +
4906 + var clng = 0, clat = 0, zoom = 8;
4907 + if (boundingBox != null) {
4908 + var clat = (boundingBox[0] + boundingBox[2]) / 2;
4909 + var clng = (boundingBox[1] + boundingBox[3]) / 2;
4910 + var cscale = Math.max(Math.abs(boundingBox[0] - boundingBox[2]), Math.abs(boundingBox[1] - boundingBox[3]));
4911 + var i = 360, zoom = -2;
4912 + while (i > cscale) { zoom++; i = i / 2; }
4913 + }
4914 +
4915 + if (markers.length == 1) { zoom = 8; }
4916 +
4917 + // Setup the map
4918 + d2map = new ol.Map({
4919 + target: 'd2map',
4920 + interactions: ol.interaction.defaults({dragPan:false, mouseWheelZoom:false}),
4921 + layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ],
4922 + view: new ol.View({ center: ol.proj.fromLonLat([clng, clat]), zoom: zoom })
4923 + });
4924 + return false;
4925 + }
4926 +
4927 + // Show network interfaces
4928 + function p10showNodeNetInfoDialog() {
4929 + if (xxdialogMode) return false;
4930 + setDialogMode(2, "Interfaces de rede", 1, null, '<div id=d2netinfo>' + "Carregando..." + '</div>', 'if' + currentNode._id );
4931 + meshserver.send({ action: 'getnetworkinfo', nodeid: currentNode._id });
4932 + return false;
4933 + }
4934 +
4935 + // Show MeshCentral Router dialog
4936 + function p10showMeshRouterDialog() {
4937 + if (xxdialogMode) return;
4938 + var x = '<div>' + "O MeshCentral Router é uma ferramenta do Windows para mapeamento de portas TCP. Você pode, por exemplo, RDP em um dispositivo remoto através deste servidor." + '</div><br />';
4939 + x += addHtmlValue('Win32 Executable', '<a style=cursor:pointer download href="meshagents?meshaction=winrouter" onclick="setDialogMode(0)">MeshCentralRouter.exe</a>');
4940 + setDialogMode(2, "MeshCentral Router", 1, null, x, 'fileDownload');
4941 + }
4942 +
4943 + // Request MQTT login credentials
4944 + function p10showMqttLoginDialog(nodeid) { meshserver.send({ action: 'getmqttlogin', nodeid: nodeid }); }
4945 +
4946 + // Show MeshCmd dialog
4947 + function p10showMeshCmdDialog(mode, nodeid) {
4948 + if (xxdialogMode) return;
4949 + var y = '<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>';
4950 + y += '<option value=3>' + "Windows (32 Bits)" + '</option>';
4951 + y += '<option value=4>' + "Windows (64 Bits)" + '</option>';
4952 + y += '<option value=5>' + "Linux x86 (32 bits)" + '</option>';
4953 + y += '<option value=6>' + "Linux x86 (64 bits)" + '</option>';
4954 + y += '<option value=16>' + "MacOS (64 bits)" + '</option>';
4955 + y += '<option value=25>' + "Linux ARM, Raspberry Pi (32 bits)" + '</option>';
4956 + y += '</select>';
4957 +
4958 + var x = '';
4959 + if (mode == 0) { x += '<div>MeshCmd is a command line tool that performs lots of different operations. The action file can optionally be downloaded and edited to provide server information and credentials.<br /><br />'; }
4960 + if (mode == 1) { x += '<div>Download "meshcmd" with an action file to route traffic thru this server to this device. Make sure to edit meshaction.txt and add your account password or make any changes needed.<br /><br />'; }
4961 + x += addHtmlValue('Operating System', y);
4962 + x += addHtmlValue('MeshCmd', '<a id=meshcmddownloadid href="meshagents?meshcmd=3" download></a>');
4963 + if (mode == 0) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=generic" download>MeshAction (.txt)</a>'); }
4964 + if (mode == 1) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=route&nodeid=' + nodeid + '" download>MeshAction (.txt)</a>'); }
4965 + x += '</div>';
4966 + setDialogMode(2, [ "Baixar MeshCmd", "Roteador de rede" ][mode], 9, null, x, 'fileDownload');
4967 + meshCmdOsClick();
4968 + }
4969 +
4970 + function meshCmdOsClick() {
4971 + var os = Q('aginsSelect').value, osn = '', osurl = '';
4972 + //Q('meshcmddownloadid').href = 'meshagents?meshcmd=' + os;
4973 + if (os == 3) { osn = 'MeshCmd (Win32 executable)'; }
4974 + if (os == 4) { osn = 'MeshCmd (Win64 executable)'; }
4975 + if (os == 5) { osn = 'MeshCmd (Linux x86, 32bit)'; }
4976 + if (os == 6) { osn = 'MeshCmd (Linux x86, 64bit)'; }
4977 + if (os == 16) { osn = 'MeshCmd (MacOS, 64bit)'; }
4978 + if (os == 25) { osn = 'MeshCmd (Linux ARM, 32bit)'; }
4979 + QH('meshcmddownloadid', osn);
4980 + Q('meshcmddownloadid').setAttribute('href', 'meshagents?meshcmd=' + os);
4981 + }
4982 +
4983 + function p10showiconselector() {
4984 + if (xxdialogMode) return;
4985 + var mesh = meshes[currentNode.meshid];
4986 + var meshrights = mesh.links[userinfo._id].rights;
4987 + if ((meshrights & 4) == 0) return;
4988 +
4989 + var x = '<br><div style=display:inline-block;width:40px></div>';
4990 + x += '<div tabindex=0 style=display:inline-block class=i1 onclick=p10setIcon(1) onkeypress="if (event.key==\'Enter\') p10setIcon(1)"></div>';
4991 + x += '<div tabindex=0 style=display:inline-block class=i2 onclick=p10setIcon(2) onkeypress="if (event.key==\'Enter\') p10setIcon(2)"></div>';
4992 + x += '<div tabindex=0 style=display:inline-block class=i3 onclick=p10setIcon(3) onkeypress="if (event.key==\'Enter\') p10setIcon(3)"></div>';
4993 + x += '<div tabindex=0 style=display:inline-block class=i4 onclick=p10setIcon(4) onkeypress="if (event.key==\'Enter\') p10setIcon(4)"></div>';
4994 + x += '<div tabindex=0 style=display:inline-block class=i5 onclick=p10setIcon(5) onkeypress="if (event.key==\'Enter\') p10setIcon(5)"></div>';
4995 + x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div><br><br>';
4996 + setDialogMode(2, "Seleção de ícone", 0, null, x);
4997 + QV('id_dialogclose', true);
4998 + }
4999 +

This file is too large to show in full.

views/translations/download-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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}}} &nbsp;<a href=terms>Termos &amp; Privacidade</a></table></div></div></div>
\ No newline at end of file
views/translations/download_pt.handlebars new
+41
@@ -0,0 +1,41 @@
1 +<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link type="text/css" href="/styles/style.css" media="screen" rel="stylesheet" title="CSS">
8 + <title>MeshCentral - Download</title>
9 +</head>
10 +<body>
11 + <div id="container" style="max-height:100vh">
12 + <div id="mastheadx"></div>
13 + <div id="masthead" style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden">
14 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px">
15 + <strong><font style="font-size:46px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
16 + </div>
17 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px">
18 + <strong><font style="font-size:14px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
19 + </div>
20 + </div>
21 + <div id="page_content" style="max-height:calc(100vh-138px)">
22 + <div id="column_l">
23 + <h1>Baixar</h1>
24 + <p style="margin-left:20px">{{{message}}}</p>
25 + <br>
26 + </div>
27 + <div id="footer">
28 + <table cellpadding="0" cellspacing="10" style="width:100%">
29 + <tbody><tr>
30 + <td style="text-align:left"></td>
31 + <td style="text-align:right">
32 + {{{rootCertLink}}}
33 + &nbsp;<a href="terms">Termos &amp; Privacidade</a>
34 + </td>
35 + </tr>
36 + </tbody></table>
37 + </div>
38 + </div>
39 + </div>
40 +
41 +</body></html>
\ No newline at end of file
views/translations/error404-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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>
\ No newline at end of file
views/translations/error404-mobile-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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}}}&nbsp;<a href=/ >Voltar</a></table></div></div>
\ No newline at end of file
views/translations/error404-mobile_pt.handlebars new
+54
@@ -0,0 +1,54 @@
1 +<!DOCTYPE html><html><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <title>MeshCentral</title>
8 + <style type="text/css">
9 + a {
10 + color: #036;
11 + text-decoration: underline;
12 + }
13 +
14 + #footer a {
15 + color: #fff;
16 + text-decoration: underline;
17 + }
18 +
19 + #footer a:hover {
20 + color: #fff;
21 + text-decoration: none;
22 + }
23 + </style>
24 +</head>
25 +<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">
26 + <div id="container">
27 + <!-- Begin Masthead -->
28 + <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">
29 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px">
30 + <strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
31 + </div>
32 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px">
33 + <strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
34 + </div>
35 + </div>
36 + <div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
37 + <div id="column_l" style="padding-left:10px;padding-right:10px">
38 + <div style="text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb"><b>404</b></div>
39 + <div style="text-align:center;font-size:16px;font-family:Arial;color:#999">Esta página não existe</div>
40 + <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>
41 + </div>
42 + </div>
43 + <div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
44 + <table cellpadding="0" cellspacing="6" style="width:100%">
45 + <tbody><tr>
46 + <td style="text-align:left;color:white">{{{footer}}}</td>
47 + <td style="text-align:right">{{{rootCertLink}}}&nbsp;<a href="/">Voltar</a></td>
48 + </tr>
49 + </tbody></table>
50 + </div>
51 + </div>
52 +
53 +
54 +</body></html>
\ No newline at end of file
views/translations/error404_pt.handlebars new
+131
@@ -0,0 +1,131 @@
1 +<!DOCTYPE html><html><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
8 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
9 + <title>MeshCentral</title>
10 +</head>
11 +<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
12 + <div id="container">
13 + <!-- Begin Masthead -->
14 + <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;">
15 + <div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
16 + <strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
17 + </div>
18 + <div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
19 + <strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
20 + </div>
21 + </div>
22 + <div id="page_leftbar">
23 + <div style="height:16px"></div>
24 + </div>
25 + <div id="topbar" class="noselect style3" style="height:24px;position:relative">
26 + <div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
27 + ♦
28 + <div id="uiMenu" style="display:none">
29 + <div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
30 + <div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
31 + <div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
32 + <div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
33 + </div>
34 + </div>
35 + </div>
36 + <div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
37 + <div style="text-align:center;padding-top:30px;font-size:200px;font-family:Arial;color:#bbb"><b>404</b></div>
38 + <div style="text-align:center;font-size:20px;font-family:Arial;color:#999">Esta página não existe</div>
39 + <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>
40 + </div>
41 + <div id="footer">
42 + <table cellpadding="0" cellspacing="10" style="width: 100%">
43 + <tbody><tr>
44 + <td style="text-align:left"></td>
45 + <td style="text-align:right"><a href="/">Voltar</a></td>
46 + </tr>
47 + </tbody></table>
48 + </div>
49 + </div>
50 + <script>
51 + 'use strict';
52 + var uiMode = parseInt(getstore('uiMode', 1));
53 + var webPageStackMenu = false;
54 + var webPageFullScreen = true;
55 + var nightMode = (getstore('_nightMode', '0') == '1');
56 +
57 + var terms = '{{{terms}}}';
58 + if (terms != '') { QH('column_l', decodeURIComponent(terms)); }
59 + QV('column_l', true);
60 + userInterfaceSelectMenu();
61 +
62 + // Toggle user interface menu
63 + function showUserInterfaceSelectMenu() {
64 + Q('uiViewButton1').classList.remove('uiSelectorSel');
65 + Q('uiViewButton2').classList.remove('uiSelectorSel');
66 + Q('uiViewButton3').classList.remove('uiSelectorSel');
67 + Q('uiViewButton4').classList.remove('uiSelectorSel');
68 + try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
69 + QV('uiMenu', (QS('uiMenu').display == 'none'));
70 + if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
71 + }
72 +
73 + function userInterfaceSelectMenu(s) {
74 + if (s) { uiMode = s; putstore('uiMode', uiMode); }
75 + webPageFullScreen = (uiMode < 3);
76 + webPageStackMenu = true;//(uiMode > 1);
77 + toggleFullScreen(0);
78 + toggleStackMenu(0);
79 + QC('column_l').add('room4submenu');
80 + }
81 +
82 + function toggleNightMode() {
83 + nightMode = !nightMode;
84 + if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
85 + putstore('_nightMode', nightMode ? '1' : '0');
86 + }
87 +
88 + // Toggle the web page to full screen
89 + function toggleFullScreen(toggle) {
90 + if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
91 + var hide = 0;
92 + //if (args.hide) { hide = parseInt(args.hide); }
93 + if (webPageFullScreen == false) {
94 + QC('body').remove('menu_stack');
95 + QC('body').remove('fullscreen');
96 + QC('body').remove('arg_hide');
97 + //if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
98 + //QV('UserDummyMenuSpan', false);
99 + //QV('page_leftbar', false);
100 + } else {
101 + QC('body').add('fullscreen');
102 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
103 + //QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
104 + //QV('page_leftbar', true);
105 + }
106 + QV('body', true);
107 + }
108 +
109 + // If FullScreen, toggle menu to be horisontal or vertical
110 + function toggleStackMenu(toggle) {
111 + if (webPageFullScreen == true) {
112 + if (toggle === 1) {
113 + webPageStackMenu = !webPageStackMenu;
114 + putstore('webPageStackMenu', webPageStackMenu);
115 + }
116 + if (webPageStackMenu == false) {
117 + QC('body').remove('menu_stack');
118 + } else {
119 + QC('body').add('menu_stack');
120 + //if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
121 + }
122 + }
123 + }
124 +
125 + function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
126 + 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; } }
127 +
128 + </script>
129 +
130 +
131 +</body></html>
\ No newline at end of file
views/translations/login-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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 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 src=scripts/common-0.0.1.js></script><script keeplink=1 src=scripts/u2f-api.js></script><title>{{{title}}} - Login</title><body id=body onload='"undefined"!=typeof startup&&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><tr><td id=welcomeimage><picture><img alt=""src=welcome.jpg style=border-radius:20px></picture><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><tr><td id=loginusername align=right width=100>Nome de usuário:<td><input id=username maxlength=64 name=username onchange=validateLogin(1) onkeyup=validateLogin(1,event)><tr><td align=right>Senha:<td><input id=password type=password maxlength=256 name=password autocomplete=off onchange=validateLogin(2) onkeyup=validateLogin(2,event)><tr><td><div id=showPassHintLink style=display:none><a onclick="return showPassHint(event)"href=# style=cursor:pointer>Mostrar dica</a></div><td align=right><input id=loginButton type=submit value=Entrar disabled></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></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><tr id=nuUserRow><td id=nuUser align=right width=100>Nome de usuário:<td><input id=ausername name=username onchange=validateCreate(1) maxlength=64 onkeydown=haltReturn(event) onkeyup=validateCreate(1,event)><tr><td id=nuEmail align=right width=100>Email:<td><input id=aemail name=email onchange=validateCreate(2) maxlength=256 onkeydown=haltReturn(event) onkeyup=validateCreate(2,event)><tr><td id=nuPass1 align=right>Senha:<td><input id=apassword1 type=password name=password1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(3,event) onkeyup=validateCreate(3,event)><tr><td id=nuPass2 align=right>Senha:<td><input id=apassword2 type=password name=password2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(4,event) onkeyup=validateCreate(4,event)><tr id=createPanelHint style=display:none><td id=nuHint align=right>Dica de senha<td><input id=apasswordhint name=apasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(5,event) onkeyup=validateCreate(5,event)><tr id=newAccountPass title="Insira o token de criação da conta"><td id=nuToken align=right>Token de criação<td><input id=anewaccountpass type=password name=anewaccountpass autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6,event) onkeyup=validateCreate(6,event)><tr><td colspan=2><div style=float:right><input id=createButton type=submit value="Criar conta"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Volte ao login</a> <input id=createformargs name=urlargs type=hidden></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><tr><td align=right width=100>Email:<td><input id=remail name=email maxlength=256 onchange=validateReset() onkeyup=validateReset(event)><tr><td colspan=2><div style=float:right><input id=eresetButton type=submit value="Redefinir Conta"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Volte ao login</a> <input id=resetformargs name=urlargs type=hidden></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><tr><td align=right width=100>Token de logon:<td><input id=tokenInput name=token maxlength=50 onchange=checkToken(event) onpaste=resetCheckToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event)><br><input id=hwtokenInput name=hwtoken style=display:none><tr><td colspan=2 style=align-content:center><label><input id=tokenInputRemember name=remembertoken type=checkbox>Remember this device for 30 days.</label><tr><td colspan=2><div style=float:right><input id=tokenOkButton type=submit value=Entrar disabled></div><div style=float:right><input style=display:none;float:right id=securityKeyButton type=button value="Use Security Key"onclick=useSecurityKey()></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Volte ao login</a> <input id=tokenformargs name=urlargs type=hidden></form></div><div id=resettokenpanel style=display:none><form method=post><input type=hidden name=action value=resetaccount><div id=message5></div><table><tr><td align=right width=100>Token de logon:<td><input id=resetTokenInput name=token maxlength=50 onchange=resetCheckToken(event) onkeyup=resetCheckToken(event) onkeydown=resetCheckToken(event)> <input id=resetHwtokenInput name=hwtoken style=display:none><tr><td colspan=2><div style=float:right><input id=resetTokenOkButton type=submit value=Entrar disabled></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Volte ao login</a> <input id=resettokenformargs name=urlargs type=hidden></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><tr><td id=rnuPass1 width=100 align=right>Senha:<td><input id=rapassword1 type=password name=rpassword1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(3,event) onkeyup=validatePassReset(3,event)><tr><td id=rnuPass2 align=right>Senha:<td><input id=rapassword2 type=password name=rpassword2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(4,event) onkeyup=validatePassReset(4,event)><tr id=resetpasswordpanelHint style=display:none><td id=rnuHint align=right>Dica de senha<td><input id=rapasswordhint name=rpasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(5,event) onkeyup=validatePassReset(5,event)><tr><td colspan=2><div style=float:right><input id=resetPassButton type=submit value="Redefinir senha"disabled></div><div id=rpassWarning style=padding-top:6px></div></table><hr><a onclick="return xgo(1,event)"href=# style=cursor:pointer>Volte ao login</a> <input id=resetpasswordformargs name=urlargs type=hidden></form></div></table><br></div><div id=footer><div class=footer1>{{{footer}}}</div><div class=footer2>{{{rootCertLink}}} &nbsp;<a href=terms>Termos &amp; 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></div></div><div id=dialog2><div id=id_dialogOptions></div></div></div><div id=idx_dlgButtonBar><input id=idx_dlgCancelButton type=button value=Cancelar onclick=dialogclose(0)> <input id=idx_dlgOkButton type=button value=Ok onclick=dialogclose(1)></div></div><script>"use strict";var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,passhint="{{{passhint}}}",loginMode="{{{loginmode}}}",newAccount="{{{newAccount}}}",newAccountPass=parseInt("{{{newAccountPass}}}"),emailCheck=!1,passRequirements="{{{passRequirements}}}",hardwareKeyChallenge=decodeURIComponent("{{{hkey}}}"),passRequirementsEx=null!=(passRequirements=""!=passRequirements?JSON.parse(decodeURIComponent(passRequirements)):{}).min||null!=passRequirements.max||null!=passRequirements.upper||null!=passRequirements.lower||null!=passRequirements.numeric||null!=passRequirements.nonalpha,features=parseInt("{{{features}}}"),welcomeText=decodeURIComponent("{{{welcometext}}}"),currentpanel=0,uiMode=parseInt(getstore("uiMode","1")),webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),publicKeyCredentialRequestOptions=null,messageid=parseInt("{{{messageid}}}"),okmessages=["","Hold on, reset mail sent."],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(0<messageid){var msg="";if(messageid<100&&messageid<okmessages.length?msg=okmessages[messageid]:100<=messageid&&messageid-100<failmessages.length&&(msg=failmessages[messageid-100]),""!=msg){msg=100<=messageid?'<span class="msg error"><b style=color:#8C001A>'+msg+"<b></span><br /><br />":'<span class="msg success"><b>'+msg+"</b></span><br /><br />";for(var i=1;i<7;i++)QH("message"+i,msg)}}if(0<window.location.href.indexOf("?")){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(0==(32&features)){var e=null;try{e=top.location.toString().toLowerCase()}catch(e){}if(top!=self&&(null==e||0==top.active))return void(top.location=self.location)}if(2097152&features&&(QH("loginusername","Email:"),QH("resetAccountSpan","Esqueceu a senha?"),QV("nuUserRow",!1)),nightMode&&QC("body").add("night"),QV("createPanelHint",!0===passRequirements.hint),QV("resetpasswordpanelHint",!0===passRequirements.hint),welcomeText&&QH("welcomeText",welcomeText),QH("welcomeText",addTextLink("MeshCentral",Q("welcomeText").innerHTML,"http://www.meshcommander.com/meshcentral2")),QV("welcomeText",!0),(window.onresize=center)(),validateLogin(),validateCreate(),0!=loginMode.length?go(parseInt(loginMode)):go(1),QV("newAccountDiv","1"===newAccount||"true"===newAccount),null!=passhint&&0<passhint.length&&QV("showPassHintLink",!0),QV("newAccountPass",1==newAccountPass),QV("resetAccountDiv",1==emailCheck),QV("hrAccountDiv",1==emailCheck||1==newAccountPass),"4"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}QV("securityKeyButton",null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type)}if("5"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var a=0;a<hardwareKeyChallenge.keyIds.length;a++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[a]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("resetHwtokenInput").value=JSON.stringify(a),QE("resetTokenOkButton",!0),Q("resetTokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}userInterfaceSelectMenu()}function useSecurityKey(){if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var e=0;e<hardwareKeyChallenge.keyIds.length;e++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[e]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("hwtokenInput").value=JSON.stringify(a),QE("tokenOkButton",!0),Q("tokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}function showPassHint(e){return messagebox("Dica de Senha",passhint),haltEvent(e),!1}function xgo(e,a){return QV("message1",!1),QV("message2",!1),QV("message3",!1),QV("message4",!1),QV("message5",!1),QV("message6",!1),go(e),haltEvent(a),!1}function go(e){currentpanel=e,setDialogMode(0),QV("showPassHintLink",!1),QV("loginpanel",1==e),QV("createpanel",2==e),QV("resetpanel",3==e),QV("tokenpanel",4==e),QV("resettokenpanel",5==e),QV("resetpasswordpanel",6==e),1==e&&Q("username").focus(),2==e&&(2097152&features?Q("aemail").focus():Q("ausername").focus()),3==e&&Q("remail").focus(),4==e&&Q("tokenInput").focus(),5==e&&Q("resetTokenInput").focus(),6==e&&Q("rapassword1").focus()}function validateLogin(e,a){var n=0<Q("username").value.length&&-1==Q("username").value.indexOf(" ")&&0<Q("password").value.length;QE("loginButton",n),setDialogMode(0),null!=a&&13==a.keyCode&&(1==e&&""!=Q("username").value?Q("password").focus():2==e&&""!=Q("password").value&&Q("loginButton").click()),null!=a&&haltEvent(a)}function validateCreate(e,a){setDialogMode(0);var n=!1;n=!!(2097152&features)||0<Q("ausername").value.length&&-1==Q("ausername").value.indexOf(" ")&&-1==Q("ausername").value.indexOf('"')&&-1==Q("ausername").value.indexOf(",");var t=1==validateEmail(Q("aemail").value),r=0<Q("apassword1").value.length,s=0<Q("apassword2").value.length&&Q("apassword2").value==Q("apassword1").value,o=0==newAccountPass||0<Q("anewaccountpass").value.length,l=n&&t&&r&&s&&o;if(QS("nuUser").color=n?"black":"#7b241c",QS("nuEmail").color=t?"black":"#7b241c",QS("nuPass1").color=r?"black":"#7b241c",QS("nuPass2").color=s?"black":"#7b241c",QS("nuToken").color=o?"black":"#7b241c",""==Q("apassword1").value)QH("passWarning",""),QV("passwordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("apassword1").value,passRequirements)?(l=!1,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>"),QV("passwordPolicyCallout",!0),QH("passwordPolicyCallout",passwordPolicyText(Q("apassword1").value))):(QH("passWarning",""),QV("passwordPolicyCallout",!1))}else{var i=checkPasswordStrength(Q("apassword1").value);80<=i?QH("passWarning","<span style=color:green><b>Senha forte</b><span>"):60<=i?QH("passWarning","<span style=color:blue><b>Boa senha</b><span>"):QH("passWarning","<span style=color:red><b>Senha fraca</b><span>")}null!=a&&13==a.keyCode&&(1==e&&n&&Q("aemail").focus(),2==e&&t&&Q("apassword1").focus(),3==e&&r&&Q("apassword2").focus(),4==e&&s&&(!0===passRequirements.hint?Q("apasswordhint").focus():e=5),5==e&&(1==newAccountPass?Q("anewaccountpass").focus():e=6),6==e&&Q("createButton").click()),null!=a&&haltEvent(a),QE("createButton",l)}function validatePassReset(e,a){setDialogMode(0);var n=0<Q("rapassword1").value.length,t=0<Q("rapassword2").value.length&&Q("rapassword2").value==Q("rapassword1").value,r=n&&t;if(QS("rnuPass1").color=n?"black":"#7b241c",QS("rnuPass2").color=t?"black":"#7b241c",""==Q("rapassword1").value)QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("rapassword1").value,passRequirements)?(r=!1,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>"),QV("rpasswordPolicyCallout",!0),QH("rpasswordPolicyCallout",passwordPolicyText(Q("rapassword1").value))):(QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1))}else{var s=checkPasswordStrength(Q("rapassword1").value);80<=s?QH("rpassWarning","<span style=color:green><b>Senha forte</b><span>"):60<=s?QH("rpassWarning","<span style=color:blue><b>Boa senha</b><span>"):QH("rpassWarning","<span style=color:red><b>Senha fraca</b><span>")}null!=a&&13==a.keyCode&&(2==e&&Q("rapassword1").focus(),3==e&&Q("rapassword2").focus(),4==e&&Q("rapasswordhint").focus(),6==e&&Q("resetPassButton").click()),null!=a&&haltEvent(a),QE("resetPassButton",r)}function passwordPolicyText(e){var a="<div style=text-align:left>",n=strCount(e);return passRequirements.min&&(null==e||e.length<passRequirements.min)&&(a+=format("Comprimento mínimo de {0}",passRequirements.min)+"<br />"),passRequirements.max&&(null==e||e.length>passRequirements.max)&&(a+=format("Comprimento máximo de {0}",passRequirements.max)+"<br />"),passRequirements.upper&&(null==e||n.upper<passRequirements.upper)&&(a+=format("{0} maiúsculas",passRequirements.upper)+"<br />"),passRequirements.lower&&(null==e||n.lower<passRequirements.lower)&&(a+=format("{0} letras minúsculas",passRequirements.lower)+"<br />"),passRequirements.numeric&&(null==e||n.numeric<passRequirements.numeric)&&(a+=format("{0} numérico",passRequirements.numeric)+"<br />"),passRequirements.nonalpha&&(null==e||n.nonalpha<passRequirements.nonalpha)&&(a+=format("{0} não alfanumérico",passRequirements.nonalpha)+"<br />"),a+="</div>"}function showPasswordPolicy(){messagebox("Política de senha",passwordPolicyText())}function validateReset(e){setDialogMode(0);var a=validateEmail(Q("remail").value);QE("eresetButton",a),null!=e&&13==e.keyCode&&1==a&&Q("eresetButton").click(),null!=e&&haltEvent(e)}function checkPasswordStrength(e){var a=0,n={},t=0,r={digits:/\d/.test(e),lower:/[a-z]/.test(e),upper:/[A-Z]/.test(e),nonWords:/\W/.test(e)};if(!e)return 0;for(var s=0;s<e.length;s++)n[e[s]]=(n[e[s]]||0)+1,a+=5/n[e[s]];for(var o in r)t+=1==r[o]?1:0;return parseInt(a+10*(t-1))}function checkPasswordRequirements(e,a){if(null==a||""==a||"object"!=typeof a)return!0;if(a.min&&e.length<a.min)return!1;if(a.max&&e.length>a.max)return!1;var n=strCount(e);return!(a.numeric&&n.numeric<a.numeric)&&(!(a.lower&&n.lower<a.lower)&&(!(a.upper&&n.upper<a.upper)&&!(a.nonalpha&&n.nonalpha<a.nonalpha)))}function strCount(e){var a={numeric:0,lower:0,upper:0,nonalpha:0};if("string"!=typeof e)return a;for(var n=0;n<e.length;n++)/\d/.test(e[n])&&a.numeric++,/[a-z]/.test(e[n])&&a.lower++,/[A-Z]/.test(e[n])&&a.upper++,/\W/.test(e[n])&&a.nonalpha++;return a}function checkToken(){var e=Q("tokenInput").value,a=e.split(" ").join("");e!=a&&(Q("tokenInput").value=a),QE("tokenOkButton",6==Q("tokenInput").value.length||8==Q("tokenInput").value.length||44==Q("tokenInput").value.length)}function resetCheckToken(){var e=Q("resetTokenInput").value,a=e.split(" ").join("");e!=a&&(Q("resetTokenInput").value=a),QE("resetTokenOkButton",6==Q("resetTokenInput").value.length||8==Q("resetTokenInput").value.length||44==Q("resetTokenInput").value.length)}var xxcurrentView=0;function setDialogMode(e,a,n,t,r,s){xxdialogMode=e,xxdialogFunc=t,xxdialogButtons=n,xxdialogTag=s,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&n),QV("idx_dlgCancelButton",2&n),QV("id_dialogclose",2&n||8&n),QV("idx_dlgButtonBar",7&n),a&&QH("id_dialogtitle",a);for(var o=1;o<24;o++)QV("dialog"+o,o==e);QV("dialog",e),r&&(2==e?QH("id_dialogOptions",r):QH("id_dialogMessage",r))}function dialogclose(e){var a=xxdialogFunc,n=xxdialogButtons,t=xxdialogTag;setDialogMode(),(8&n||e)&&a&&a(e,t)}function toggleFullScreen(e){0==webPageFullScreen?QC("body").remove("fullscreen"):QC("body").add("fullscreen"),QV("body",!0),center()}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(e){}QV("uiMenu","none"==QS("uiMenu").display),nightMode&&Q("uiViewButton4").classList.add("uiSelectorSel")}function userInterfaceSelectMenu(e){e&&putstore("uiMode",uiMode=e),webPageFullScreen=uiMode<3,toggleFullScreen(0)}function toggleNightMode(){(nightMode=!nightMode)?QC("body").add("night"):QC("body").remove("night"),putstore("_nightMode",nightMode?"1":"0")}function center(){if(0==webPageFullScreen)QS("centralTable")["margin-top"]="";else{var e=Q("column_l").clientHeight/2-220;e<0&&(e=0),QS("centralTable")["margin-top"]=e+"px"}}function messagebox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e,1)}function statusbox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e)}function getDocWidth(){return window.innerWidth?window.innerWidth:document.documentElement&&document.documentElement.clientWidth&&0!=document.documentElement.clientWidth?document.documentElement.clientWidth:document.getElementsByTagName("body")[0].clientWidth}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function haltReturn(e){13==e.keyCode&&haltEvent(e)}function validateEmail(e){return/^(([^<>()\[\]\\.,;:\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,}))$/.test(e)}function putstore(e,a){try{if("undefined"==typeof localStorage)return;localStorage.setItem(e,a)}catch(e){}}function getstore(e,a){try{if("undefined"==typeof localStorage)return a;var n=localStorage.getItem(e);return null==n||null==n?a:n}catch(e){return a}}function format(e){var n=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,a){return void 0!==n[a]?n[a]:e})}function addTextLink(e,a,n){var t=a.toLowerCase().indexOf(e.toLowerCase());return-1==t?a:a.substring(0,t)+'<a href="'+n+'">'+e+"</a>"+a.substring(t+e.length)}</script>
\ No newline at end of file
views/translations/login-mobile-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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 rel="shortcut icon"type=image/x-icon href={{{domainurl}}}favicon.ico><script src=scripts/common-0.0.1.js></script><script 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><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;margin:0;padding:0;border:0;color:#000;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) 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: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%><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><tr><td id=loginusername align=right width=100>Nome de usuário:<td><input id=username maxlength=64 name=username onchange=validateLogin(1) onkeyup=validateLogin(1,event)><tr><td align=right>Senha:<td><input id=password type=password maxlength=256 name=password autocomplete=off onchange=validateLogin(2) onkeyup=validateLogin(2,event)><tr><td><div id=showPassHintLink style=display:none><a onclick=showPassHint() style=cursor:pointer>Mostrar dica</a></div><td align=right><input id=loginButton type=submit value=Entrar disabled></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></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:0 0 15px #666;font-size:10px"></div><table><tr id=nuUserRow><td align=right width=100>Nome de usuário:<td><input id=ausername name=username onchange=validateCreate(1) maxlength=64 onkeydown=haltReturn(event) onkeyup=validateCreate(1,event)><tr><td align=right width=100>Email:<td><input id=aemail name=email onchange=validateCreate(2) maxlength=256 onkeydown=haltReturn(event) onkeyup=validateCreate(2,event)><tr><td align=right>Senha:<td><input id=apassword1 type=password name=password1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(3) onkeyup=validateCreate(3,event)><tr><td align=right>Senha:<td><input id=apassword2 type=password name=password2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(4) onkeyup=validateCreate(4,event)><tr id=createPanelHint style=display:none><td align=right>Dica de passe:<td><input id=apasswordhint name=apasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(5) onkeyup=validateCreate(5,event)><tr id=newAccountPass title="Insira o token de criação da conta"><td align=right>Token de criação<td><input id=anewaccountpass type=password name=anewaccountpass autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6) onkeyup=validateCreate(6,event)><tr><td colspan=2><div style=float:right><input id=createButton type=submit value="Criar conta"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Volte ao login</a> <input id=createformargs name=urlargs type=hidden></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><tr><td align=right width=100>Email:<td><input id=remail name=email maxlength=256 onchange=validateReset() onkeyup=validateReset(event)><tr><td colspan=2><div style=float:right><input id=eresetButton type=submit value="Redefinir Conta"disabled></div><div id=passWarning style=padding-top:6px></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Volte ao login</a> <input id=resetformargs name=urlargs type=hidden></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><tr><td align=right width=100>Token de logon:<td><input id=tokenInput name=token maxlength=50 onchange=checkToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event) onfocus=checkTokenTimer(1) onblur=checkTokenTimer(0)> <input id=hwtokenInput name=hwtoken style=display:none><tr><td colspan=2 style=align-content:center><label><input id=tokenInputRemember name=remembertoken type=checkbox>Remember this device for 30 days.</label><tr><td colspan=2><div style=float:right><input id=tokenOkButton type=submit value=Entrar disabled></div><div style=float:right><input style=display:none;float:right id=securityKeyButton type=button value="Use Security Key"onclick=useSecurityKey()></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Volte ao login</a> <input id=tokenformargs name=urlargs type=hidden></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><tr><td align=right width=100>Token de logon:<td><input id=resetTokenInput name=token maxlength=50 onchange=resetCheckToken(event) onpaste=resetCheckToken(event) onkeyup=resetCheckToken(event) onkeydown=resetCheckToken(event)> <input id=resetHwtokenInput name=hwtoken style=display:none><tr><td colspan=2><div style=float:right><input id=resetTokenOkButton type=submit value=Entrar disabled></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Volte ao login</a> <input id=resettokenformargs name=urlargs type=hidden></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:0 0 15px #666;font-size:10px"></div><table><tr><td id=rnuPass1 width=100 align=right>Senha:<td><input id=rapassword1 type=password name=rpassword1 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(3,event) onkeyup=validatePassReset(3,event)><tr><td id=rnuPass2 align=right>Senha:<td><input id=rapassword2 type=password name=rpassword2 autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(4,event) onkeyup=validatePassReset(4,event)><tr id=resetpasswordpanelHint style=display:none><td id=rnuHint align=right>Dica de senha<td><input id=rapasswordhint name=rpasswordhint autocomplete=off maxlength=256 onkeydown=haltReturn(event) onchange=validatePassReset(5,event) onkeyup=validatePassReset(5,event)><tr><td colspan=2><div style=float:right><input id=resetPassButton type=submit value="Redefinir senha"disabled></div><div id=rpassWarning style=padding-top:6px></div></table><hr><a onclick=xgo(1) style=cursor:pointer>Volte ao login</a> <input id=resetpasswordformargs name=urlargs type=hidden></form></div></table></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}}}&nbsp;<a href=terms>Termos &amp; Privacidade</a></table></div></div><div id=dialog style="z-index:1000;background-color:#eee;box-shadow:0 0 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:#036;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}}}",newAccount="{{{newAccount}}}",passhint="{{{passhint}}}",newAccountPass=parseInt("{{{newAccountPass}}}"),emailCheck=!1,features=parseInt("{{{features}}}"),passRequirements="{{{passRequirements}}}",passRequirementsEx=null!=(passRequirements=""!=passRequirements?JSON.parse(decodeURIComponent(passRequirements)):{}).min||null!=passRequirements.max||null!=passRequirements.upper||null!=passRequirements.lower||null!=passRequirements.numeric||null!=passRequirements.nonalpha,hardwareKeyChallenge=decodeURIComponent("{{{hkey}}}"),publicKeyCredentialRequestOptions=null,currentpanel=0,messageid=parseInt("{{{messageid}}}"),okmessages=["","Hold on, reset mail sent."],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(0<messageid){var msg="";if(messageid<100&&messageid<okmessages.length?msg=okmessages[messageid]:100<=messageid&&messageid-100<failmessages.length&&(msg=failmessages[messageid-100]),""!=msg){msg=100<=messageid?'<span class="msg error"><b style=color:#8C001A>'+msg+"<b></span><br /><br />":'<span class="msg success"><b>'+msg+"</b></span><br /><br />";for(var i=1;i<7;i++)QH("message"+i,msg)}}if(0<window.location.href.indexOf("?")){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(0==(32&features)){var e=null;try{e=top.location.toString().toLowerCase()}catch(e){}if(top!=self&&(null==e||0==top.active))return void(top.location=self.location)}if(2097152&features&&(QH("loginusername","Email:"),QH("resetAccountSpan","Esqueceu a senha?"),QV("nuUserRow",!1)),QV("createPanelHint",!0===passRequirements.hint),QV("resetpasswordpanelHint",!0===passRequirements.hint),(window.onresize=center)(),validateLogin(),validateCreate(),0!=loginMode.length?go(parseInt(loginMode)):go(1),QV("newAccountDiv","1"===newAccount||"true"===newAccount),!0===passRequirements.hint&&null!=passhint&&0<passhint.length&&QV("showPassHintLink",!0),QV("newAccountPass",1==newAccountPass),QV("resetAccountDiv",1==emailCheck),QV("hrAccountDiv",1==emailCheck||1==newAccountPass),"4"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}QV("securityKeyButton",null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type)}if("5"==loginMode){try{hardwareKeyChallenge=0<hardwareKeyChallenge.length?JSON.parse(hardwareKeyChallenge):null}catch(e){hardwareKeyChallenge=null}if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var a=0;a<hardwareKeyChallenge.keyIds.length;a++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[a]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("resetHwtokenInput").value=JSON.stringify(a),QE("resetTokenOkButton",!0),Q("resetTokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}}function useSecurityKey(){if(null!=hardwareKeyChallenge&&"webAuthn"==hardwareKeyChallenge.type){"string"==typeof hardwareKeyChallenge.challenge&&(hardwareKeyChallenge.challenge=Uint8Array.from(atob(hardwareKeyChallenge.challenge),function(e){return e.charCodeAt(0)}).buffer),publicKeyCredentialRequestOptions={challenge:hardwareKeyChallenge.challenge,allowCredentials:[],timeout:hardwareKeyChallenge.timeout};for(var e=0;e<hardwareKeyChallenge.keyIds.length;e++)publicKeyCredentialRequestOptions.allowCredentials.push({id:Uint8Array.from(atob(hardwareKeyChallenge.keyIds[e]),function(e){return e.charCodeAt(0)}),type:"public-key",transports:["usb","ble","nfc"]});navigator.credentials.get({publicKey:publicKeyCredentialRequestOptions}).then(function(e){var a={id:btoa(String.fromCharCode.apply(null,new Uint8Array(e.rawId))),clientDataJSON:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.clientDataJSON))),userHandle:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.userHandle))),signature:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.signature))),authenticatorData:btoa(String.fromCharCode.apply(null,new Uint8Array(e.response.authenticatorData)))};Q("hwtokenInput").value=JSON.stringify(a),QE("tokenOkButton",!0),Q("tokenOkButton").click()},function(e){console.log("credentials-get error",e)})}}function showPassHint(){!0===passRequirements.hint&&messagebox("Dica de Senha",passhint)}function xgo(e){QV("message1",!1),QV("message2",!1),QV("message3",!1),QV("message4",!1),QV("message5",!1),QV("message6",!1),go(e)}function go(e){currentpanel=e,setDialogMode(0),QV("showPassHintLink",!1),QV("loginpanel",1==e),QV("createpanel",2==e),QV("resetpanel",3==e),QV("tokenpanel",4==e),QV("resettokenpanel",5==e),QV("resetpasswordpanel",6==e),1==e&&Q("username").focus(),2==e&&(2097152&features?Q("aemail").focus():Q("ausername").focus()),3==e&&Q("remail").focus(),4==e&&Q("tokenInput").focus(),5==e&&Q("resetTokenInput").focus(),6==e&&Q("rapassword1").focus()}function validateLogin(e,a){var n=0<Q("username").value.length&&-1==Q("username").value.indexOf(" ")&&0<Q("password").value.length;QE("loginButton",n),setDialogMode(0),null!=a&&13==a.keyCode&&(1==e?Q("password").focus():2==e&&Q("loginButton").click()),null!=a&&haltEvent(a)}function validateCreate(e,a){setDialogMode(0);var n=!1;if(n=!!(2097152&features)||0<Q("ausername").value.length&&-1==Q("ausername").value.indexOf(" ")&&-1==Q("ausername").value.indexOf('"')&&-1==Q("ausername").value.indexOf(","),n&=1==validateEmail(Q("aemail").value)&&0<Q("apassword1").value.length&&Q("apassword2").value==Q("apassword1").value,1==newAccountPass&&0==Q("anewaccountpass").value.length&&(n=!1),""==Q("apassword1").value)QH("passWarning",""),QV("passwordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("apassword1").value,passRequirements)?(n=!1,QH("passWarning","<span style=color:red><b>Política de senha</b><span>"),QV("passwordPolicyCallout",!0),QH("passwordPolicyCallout",passwordPolicyText(Q("apassword1").value))):(QH("passWarning",""),QV("passwordPolicyCallout",!1))}else{var t=checkPasswordStrength(Q("apassword1").value);80<=t?QH("passWarning","<span style=color:green><b>Senha forte</b><span>"):60<=t?QH("passWarning","<span style=color:blue><b>Boa senha</b><span>"):QH("passWarning","<span style=color:red><b>Senha fraca</b><span>")}QE("createButton",n),null!=a&&13==a.keyCode&&(1==e&&Q("aemail").focus(),2==e&&Q("apassword1").focus(),3==e&&Q("apassword2").focus(),4==e&&Q("apasswordhint").focus(),5==e&&(1==newAccountPass?Q("anewaccountpass").focus():Q("createButton").click()),6==e&&Q("createButton").click()),null!=a&&haltEvent(a)}function validatePassReset(e,a){setDialogMode(0);var n=0<Q("rapassword1").value.length,t=0<Q("rapassword2").value.length&&Q("rapassword2").value==Q("rapassword1").value,s=n&&t;if(QS("rnuPass1").color=n?"black":"#7b241c",QS("rnuPass2").color=t?"black":"#7b241c",""==Q("rapassword1").value)QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1);else if(passRequirementsEx){0==checkPasswordRequirements(Q("rapassword1").value,passRequirements)?(s=!1,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>"),QV("rpasswordPolicyCallout",!0),QH("rpasswordPolicyCallout",passwordPolicyText(Q("rapassword1").value))):(QH("rpassWarning",""),QV("rpasswordPolicyCallout",!1))}else{var r=checkPasswordStrength(Q("rapassword1").value);80<=r?QH("rpassWarning","<span style=color:green><b>Senha forte</b><span>"):60<=r?QH("rpassWarning","<span style=color:blue><b>Boa senha</b><span>"):QH("rpassWarning","<span style=color:red><b>Senha fraca</b><span>")}null!=a&&13==a.keyCode&&(2==e&&Q("rapassword1").focus(),3==e&&Q("rapassword2").focus(),4==e&&Q("rapasswordhint").focus(),6==e&&Q("resetPassButton").click()),null!=a&&haltEvent(a),QE("resetPassButton",s)}function validateReset(e){setDialogMode(0);var a=validateEmail(Q("remail").value);QE("eresetButton",a),null!=e&&13==e.keyCode&&1==a&&Q("eresetButton").click(),null!=e&&haltEvent(e)}function passwordPolicyText(e){var a="<div style=text-align:left>",n=strCount(e);return passRequirements.min&&(null==e||e.length<passRequirements.min)&&(a+=format("Comprimento mínimo de {0}",passRequirements.min)+"<br />"),passRequirements.max&&(null==e||e.length>passRequirements.max)&&(a+=format("Comprimento máximo de {0}",passRequirements.max)+"<br />"),passRequirements.upper&&(null==e||n.upper<passRequirements.upper)&&(a+=format("{0} maiúsculas",passRequirements.upper)+"<br />"),passRequirements.lower&&(null==e||n.lower<passRequirements.lower)&&(a+=format("{0} letras minúsculas",passRequirements.lower)+"<br />"),passRequirements.numeric&&(null==e||n.numeric<passRequirements.numeric)&&(a+=format("{0} numérico",passRequirements.numeric)+"<br />"),passRequirements.nonalpha&&(null==e||n.nonalpha<passRequirements.nonalpha)&&(a+=format("{0} não alfanumérico",passRequirements.nonalpha)+"<br />"),a+="</div>"}function checkPasswordStrength(e){var a=0,n={},t=0,s={digits:/\d/.test(e),lower:/[a-z]/.test(e),upper:/[A-Z]/.test(e),nonWords:/\W/.test(e)};if(!e)return 0;for(var r=0;r<e.length;r++)n[e[r]]=(n[e[r]]||0)+1,a+=5/n[e[r]];for(var l in s)t+=1==s[l]?1:0;return parseInt(a+10*(t-1))}function checkPasswordRequirements(e,a){if(null==a||""==a||"object"!=typeof a)return!0;if(a.min&&e.length<a.min)return!1;if(a.max&&e.length>a.max)return!1;var n=strCount(e);return!(a.numeric&&n.numeric<a.numeric)&&(!(a.lower&&n.lower<a.lower)&&(!(a.upper&&n.upper<a.upper)&&!(a.nonalpha&&n.nonalpha<a.nonalpha)))}function strCount(e){var a={numeric:0,lower:0,upper:0,nonalpha:0};if("string"!=typeof e)return a;for(var n=0;n<e.length;n++)/\d/.test(e[n])&&a.numeric++,/[a-z]/.test(e[n])&&a.lower++,/[A-Z]/.test(e[n])&&a.upper++,/\W/.test(e[n])&&a.nonalpha++;return a}var xxdialogMode,xxdialogFunc,xxdialogButtons,xxdialogTag,xcheckTokenTimer=null;function checkTokenTimer(e){0==e&&null!=xcheckTokenTimer&&(clearInterval(xcheckTokenTimer),xcheckTokenTimer=null),1==e&&null==xcheckTokenTimer&&(xcheckTokenTimer=setInterval(checkToken,200))}function checkToken(){var e=Q("tokenInput").value,a=e.split(" ").join("");e!=a&&(Q("tokenInput").value=a),QE("tokenOkButton",6==Q("tokenInput").value.length||8==Q("tokenInput").value.length||44==Q("tokenInput").value.length)}function resetCheckToken(){var e=Q("resetTokenInput").value,a=e.split(" ").join("");e!=a&&(Q("resetTokenInput").value=a),QE("resetTokenOkButton",6==Q("resetTokenInput").value.length||8==Q("resetTokenInput").value.length||44==Q("resetTokenInput").value.length)}var xxcurrentView=0;function setDialogMode(e,a,n,t,s,r){xxdialogMode=e,xxdialogFunc=t,xxdialogButtons=n,xxdialogTag=r,QE("idx_dlgOkButton",!0),QV("idx_dlgOkButton",1&n),QV("idx_dlgCancelButton",2&n),QV("id_dialogclose",2&n||8&n),QV("idx_dlgButtonBar",7&n),a&&QH("id_dialogtitle",a);for(var l=1;l<24;l++)QV("dialog"+l,l==e);QV("dialog",e),s&&(2==e?QH("id_dialogOptions",s):QH("id_dialogMessage",s))}function dialogclose(e){var a=xxdialogFunc,n=xxdialogButtons,t=xxdialogTag;setDialogMode(),(8&n||e)&&a&&a(e,t)}function center(){QS("dialog").left=(getDocWidth()-400)/2+"px"}function messagebox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e,1)}function statusbox(e,a){QH("id_dialogMessage",a),setDialogMode(1,e)}function getDocWidth(){return window.innerWidth?window.innerWidth:document.documentElement&&document.documentElement.clientWidth&&0!=document.documentElement.clientWidth?document.documentElement.clientWidth:document.getElementsByTagName("body")[0].clientWidth}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function haltReturn(e){13==e.keyCode&&haltEvent(e)}function validateEmail(e){return/^(([^<>()\[\]\\.,;:\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,}))$/.test(e)}function format(e){var n=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,a){return void 0!==n[a]?n[a]:e})}</script>
\ No newline at end of file
views/translations/login-mobile_pt.handlebars new
+647
@@ -0,0 +1,647 @@
1 +<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico">
8 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
9 + <script type="text/javascript" src="scripts/u2f-api.js"></script>
10 + <title>MeshCentral - Login</title>
11 + <style>
12 + a {
13 + color: #036;
14 + text-decoration: underline;
15 + }
16 +
17 + #footer a {
18 + color: #fff;
19 + text-decoration: underline;
20 + }
21 +
22 + #footer a:hover {
23 + color: #fff;
24 + text-decoration: none;
25 + }
26 + </style>
27 +</head>
28 +<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">
29 + <div id="container">
30 + <div id="mastheadx"></div>
31 + <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">
32 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px">
33 + <strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
34 + </div>
35 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px">
36 + <strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
37 + </div>
38 + </div>
39 + <div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%;display:flex;align-items:center">
40 + <div id="column_l" style="padding:10px;width:100%">
41 + <table style="width:100%">
42 + <tbody><tr>
43 + <td align="center">
44 + <div id="loginpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;display:none">
45 + <form method="post">
46 + <input type="hidden" name="action" value="login">
47 + <div id="message1"></div>
48 + <div>
49 + <b>Entrar</b>
50 + </div>
51 + <table>
52 + <tbody><tr>
53 + <td id="loginusername" align="right" width="100">Nome de usuário:</td>
54 + <td><input id="username" type="text" maxlength="64" name="username" onchange="validateLogin(1)" onkeyup="validateLogin(1,event)"></td>
55 + </tr>
56 + <tr>
57 + <td align="right">Senha:</td>
58 + <td><input id="password" type="password" maxlength="256" name="password" autocomplete="off" onchange="validateLogin(2)" onkeyup="validateLogin(2,event)"></td>
59 + </tr>
60 + <tr>
61 + <td><div id="showPassHintLink" style="display:none"><a onclick="showPassHint()" style="cursor:pointer">Mostrar dica</a></div></td>
62 + <td align="right"><input id="loginButton" type="submit" value="Entrar" disabled="disabled"></td>
63 + </tr>
64 + </tbody></table>
65 + <div id="hrAccountDiv" style="display:none"><hr></div>
66 + <div id="resetAccountDiv" style="display:none;padding:2px">
67 + <span id="resetAccountSpan">Esqueceu usuário / senha?</span> <a onclick="xgo(3)" style="cursor:pointer">Redefinir conta</a>.
68 + </div>
69 + <div id="newAccountDiv" style="display:none;padding:2px">
70 + Não possui uma conta? <a onclick="xgo(2)" style="cursor:pointer">Crie um</a>.
71 + </div>
72 + <input id="loginformargs" name="urlargs" type="hidden" value="">
73 + </form>
74 + </div>
75 + <div id="createpanel" style="display:none">
76 + <div style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;position:relative">
77 + <form method="post">
78 + <input type="hidden" name="action" value="createaccount">
79 + <div id="message2"></div>
80 + <div>
81 + <b>Criação de conta</b>
82 + </div>
83 + <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>
84 + <table>
85 + <tbody><tr id="nuUserRow">
86 + <td align="right" width="100">Nome de usuário:</td>
87 + <td><input id="ausername" type="text" name="username" onchange="validateCreate(1)" maxlength="64" onkeydown="haltReturn(event)" onkeyup="validateCreate(1,event)"></td>
88 + </tr>
89 + <tr>
90 + <td align="right" width="100">Email:</td>
91 + <td><input id="aemail" type="text" name="email" onchange="validateCreate(2)" maxlength="256" onkeydown="haltReturn(event)" onkeyup="validateCreate(2,event)"></td>
92 + </tr>
93 + <tr>
94 + <td align="right">Senha:</td>
95 + <td><input id="apassword1" type="password" name="password1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(3)" onkeyup="validateCreate(3,event)"></td>
96 + </tr>
97 + <tr>
98 + <td align="right">Senha:</td>
99 + <td><input id="apassword2" type="password" name="password2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(4)" onkeyup="validateCreate(4,event)"></td>
100 + </tr>
101 + <tr id="createPanelHint" style="display:none">
102 + <td align="right">Dica de passe:</td>
103 + <td><input id="apasswordhint" type="text" name="apasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(5)" onkeyup="validateCreate(5,event)"></td>
104 + </tr>
105 + <tr id="newAccountPass" title="Insira o token de criação da conta">
106 + <td align="right">Token de criação</td>
107 + <td><input id="anewaccountpass" type="password" name="anewaccountpass" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(6)" onkeyup="validateCreate(6,event)"></td>
108 + </tr>
109 + <tr>
110 + <td colspan="2">
111 + <div style="float:right"><input id="createButton" type="submit" value="Criar conta" disabled="disabled"></div>
112 + <div id="passWarning" style="padding-top:6px"></div>
113 + </td>
114 + </tr>
115 + </tbody></table>
116 + <hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
117 + <input id="createformargs" name="urlargs" type="hidden" value="">
118 + </form>
119 + </div>
120 + </div>
121 + <div id="resetpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
122 + <form method="post">
123 + <input type="hidden" name="action" value="resetaccount">
124 + <div id="message3"></div>
125 + <div>
126 + <b>Redefinição de conta</b>
127 + </div>
128 + <table>
129 + <tbody><tr>
130 + <td align="right" width="100">Email:</td>
131 + <td><input id="remail" type="text" name="email" maxlength="256" onchange="validateReset()" onkeyup="validateReset(event)"></td>
132 + </tr>
133 + <tr>
134 + <td colspan="2">
135 + <div style="float:right"><input id="eresetButton" type="submit" value="Redefinir Conta" disabled="disabled"></div>
136 + <div id="passWarning" style="padding-top:6px"></div>
137 + </td>
138 + </tr>
139 + </tbody></table>
140 + <hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
141 + <input id="resetformargs" name="urlargs" type="hidden" value="">
142 + </form>
143 + </div>
144 + <div id="tokenpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
145 + <form method="post" autocomplete="off">
146 + <input type="hidden" name="action" value="tokenlogin">
147 + <input type="hidden" name="hwstate" value="{{{hwstate}}}">
148 + <div id="message4"></div>
149 + <table>
150 + <tbody><tr>
151 + <td align="right" width="100">Token de logon:</td>
152 + <td>
153 + <input id="tokenInput" type="text" name="token" maxlength="50" onchange="checkToken(event)" onkeyup="checkToken(event)" onkeydown="checkToken(event)" onfocus="checkTokenTimer(1)" onblur="checkTokenTimer(0)">
154 + <input id="hwtokenInput" type="text" name="hwtoken" style="display:none">
155 + </td>
156 + </tr>
157 + <tr>
158 + <td colspan="2" style="align-content:center">
159 + <label><input id="tokenInputRemember" name="remembertoken" type="checkbox">Remember this device for 30 days.</label>
160 + </td>
161 + </tr>
162 + <tr>
163 + <td colspan="2">
164 + <div style="float:right"><input id="tokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
165 + <div style="float:right"><input style="display:none;float:right" id="securityKeyButton" type="button" value="Use Security Key" onclick="useSecurityKey()"></div>
166 + </td>
167 + </tr>
168 + </tbody></table>
169 + <hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
170 + <input id="tokenformargs" name="urlargs" type="hidden" value="">
171 + </form>
172 + </div>
173 +
174 + <div id="resettokenpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
175 + <form method="post" autocomplete="off">
176 + <input type="hidden" name="action" value="resetaccount">
177 + <div id="message5"></div>
178 + <table>
179 + <tbody><tr>
180 + <td align="right" width="100">Token de logon:</td>
181 + <td>
182 + <input id="resetTokenInput" type="text" name="token" maxlength="50" onchange="resetCheckToken(event)" onpaste="resetCheckToken(event)" onkeyup="resetCheckToken(event)" onkeydown="resetCheckToken(event)">
183 + <input id="resetHwtokenInput" type="text" name="hwtoken" style="display:none">
184 + </td>
185 + </tr>
186 + <tr>
187 + <td colspan="2">
188 + <div style="float:right"><input id="resetTokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
189 + </td>
190 + </tr>
191 + </tbody></table>
192 + <hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
193 + <input id="resettokenformargs" name="urlargs" type="hidden" value="">
194 + </form>
195 + </div>
196 +
197 + <div id="resetpasswordpanel" style="position:relative;background-color:#979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
198 + <form method="post">
199 + <input type="hidden" name="action" value="resetpassword">
200 + <div id="message6"></div>
201 + <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>
202 + <table>
203 + <tbody><tr>
204 + <td id="rnuPass1" width="100" align="right">Senha:</td>
205 + <td><input id="rapassword1" type="password" name="rpassword1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(3,event)" onkeyup="validatePassReset(3,event)"></td>
206 + </tr>
207 + <tr>
208 + <td id="rnuPass2" align="right">Senha:</td>
209 + <td><input id="rapassword2" type="password" name="rpassword2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(4,event)" onkeyup="validatePassReset(4,event)"></td>
210 + </tr>
211 + <tr id="resetpasswordpanelHint" style="display:none">
212 + <td id="rnuHint" align="right">Dica de senha</td>
213 + <td><input id="rapasswordhint" type="text" name="rpasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(5,event)" onkeyup="validatePassReset(5,event)"></td>
214 + </tr>
215 + <tr>
216 + <td colspan="2">
217 + <div style="float:right"><input id="resetPassButton" type="submit" value="Redefinir senha" disabled="disabled"></div>
218 + <div id="rpassWarning" style="padding-top:6px"></div>
219 + </td>
220 + </tr>
221 + </tbody></table>
222 + <hr><a onclick="xgo(1)" style="cursor:pointer">Volte ao login</a>
223 + <input id="resetpasswordformargs" name="urlargs" type="hidden" value="">
224 + </form>
225 + </div>
226 +
227 + </td>
228 + </tr>
229 + </tbody></table>
230 + </div>
231 + </div>
232 + <div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
233 + <table cellpadding="0" cellspacing="6" style="width:100%">
234 + <tbody><tr>
235 + <td style="text-align:left;color:white">{{{footer}}}</td>
236 + <td style="text-align:right">{{{rootCertLink}}}&nbsp;<a href="terms">Termos &amp; Privacidade</a></td>
237 + </tr>
238 + </tbody></table>
239 + </div>
240 + </div>
241 + <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">
242 + <div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
243 + <div id="id_dialogclose" style="float:right;padding:5px;cursor:pointer" onclick="setDialogMode()"><b>X</b></div>
244 + <div id="id_dialogtitle" style="padding:5px"></div>
245 + <div style="width:100%;margin:6px"></div>
246 + </div>
247 + <div style="margin-right:16px;margin-left:8px">
248 + <div id="dialog1" style="margin:auto;text-align:center;margin:3px">
249 + <div id="id_dialogMessage" style="padding:10px"></div>
250 + </div>
251 + <div id="dialog2" style="margin:auto;margin:3px">
252 + <div id="id_dialogOptions"></div>
253 + </div>
254 + </div>
255 + <div id="idx_dlgButtonBar" style="padding:10px;margin-bottom:20px">
256 + <input id="idx_dlgCancelButton" type="button" value="Cancelar" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
257 + <input id="idx_dlgOkButton" type="button" value="Ok" style="float:right;width:80px" onclick="dialogclose(1)">
258 + </div>
259 + </div>
260 + <script>
261 + 'use strict';
262 + var loginMode = '{{{loginmode}}}';
263 + var newAccount = '{{{newAccount}}}';
264 + var passhint = '{{{passhint}}}';
265 + var newAccountPass = parseInt('{{{newAccountPass}}}');
266 + var emailCheck = ('{{{emailcheck}}}' == 'true');
267 + var features = parseInt('{{{features}}}');
268 + var passRequirements = '{{{passRequirements}}}';
269 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
270 + var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
271 + var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
272 + var publicKeyCredentialRequestOptions = null;
273 + var currentpanel = 0;
274 +
275 + // Display the right server message
276 + var messageid = parseInt('{{{messageid}}}');
277 + var okmessages = ['', "Hold on, reset mail sent."];
278 + 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."];
279 + if (messageid > 0) {
280 + var msg = '';
281 + if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
282 + else if ((messageid >= 100) && ((messageid - 100) < failmessages.length)) { msg = failmessages[messageid - 100]; }
283 + if (msg != '') {
284 + 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 />'); }
285 + for (var i = 1; i < 7; i++) { QH('message' + i, msg); }
286 + }
287 + }
288 +
289 + // If URL arguments are provided, add them to form posts
290 + if (window.location.href.indexOf('?') > 0) {
291 + var urlargs = window.location.href.substring(window.location.href.indexOf('?'));
292 + Q('loginformargs').value = urlargs;
293 + Q('createformargs').value = urlargs;
294 + Q('resetformargs').value = urlargs;
295 + Q('tokenformargs').value = urlargs;
296 + Q('resettokenformargs').value = urlargs;
297 + Q('resetpasswordformargs').value = urlargs;
298 + }
299 +
300 + function startup() {
301 + if ((features & 32) == 0) {
302 + // Guard against other site's top frames (web bugs).
303 + var loc = null;
304 + try { loc = top.location.toString().toLowerCase(); } catch (e) { }
305 + if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
306 + }
307 +
308 + if (features & 0x200000) { // Email is username
309 + QH('loginusername', "Email:");
310 + QH('resetAccountSpan', "Esqueceu a senha?");
311 + QV('nuUserRow', false);
312 + }
313 +
314 + QV('createPanelHint', passRequirements.hint === true);
315 + QV('resetpasswordpanelHint', passRequirements.hint === true);
316 +
317 + window.onresize = center;
318 + center();
319 + validateLogin();
320 + validateCreate();
321 + if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
322 + QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
323 + if ((passRequirements.hint === true) && (passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
324 + QV('newAccountPass', (newAccountPass == 1));
325 + QV('resetAccountDiv', (emailCheck == true));
326 + QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
327 +
328 + if (loginMode == '4') {
329 + try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
330 + QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
331 + }
332 +
333 + if (loginMode == '5') {
334 + try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
335 + if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
336 + if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
337 +
338 + publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
339 + for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
340 + publicKeyCredentialRequestOptions.allowCredentials.push(
341 + { id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
342 + );
343 + }
344 +
345 + // New WebAuthn hardware keys
346 + navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
347 + function (rawAssertion) {
348 + var assertion = {
349 + id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
350 + clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
351 + userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
352 + signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
353 + authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
354 + };
355 + Q('resetHwtokenInput').value = JSON.stringify(assertion);
356 + QE('resetTokenOkButton', true);
357 + Q('resetTokenOkButton').click();
358 + },
359 + function (error) { console.log('credentials-get error', error); }
360 + );
361 + }
362 + }
363 + }
364 +
365 + // Use a hardware security key
366 + function useSecurityKey() {
367 + if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
368 + if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
369 +
370 + publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
371 + for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
372 + publicKeyCredentialRequestOptions.allowCredentials.push(
373 + { id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
374 + );
375 + }
376 +
377 + // New WebAuthn hardware keys
378 + navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
379 + function (rawAssertion) {
380 + var assertion = {
381 + id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
382 + clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
383 + userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
384 + signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
385 + authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
386 + };
387 + Q('hwtokenInput').value = JSON.stringify(assertion);
388 + QE('tokenOkButton', true);
389 + Q('tokenOkButton').click();
390 + },
391 + function (error) { console.log('credentials-get error', error); }
392 + );
393 + }
394 + }
395 +
396 + function showPassHint() {
397 + if (passRequirements.hint === true) { messagebox("Dica de Senha", passhint); }
398 + }
399 +
400 + function xgo(x) {
401 + QV('message1', false);
402 + QV('message2', false);
403 + QV('message3', false);
404 + QV('message4', false);
405 + QV('message5', false);
406 + QV('message6', false);
407 + go(x);
408 + }
409 +
410 + function go(x) {
411 + currentpanel = x;
412 + setDialogMode(0);
413 + QV('showPassHintLink', false);
414 + QV('loginpanel', x == 1);
415 + QV('createpanel', x == 2);
416 + QV('resetpanel', x == 3);
417 + QV('tokenpanel', x == 4);
418 + QV('resettokenpanel', x == 5);
419 + QV('resetpasswordpanel', x == 6);
420 + if (x == 1) { Q('username').focus(); }
421 + if (x == 2) { if (features & 0x200000) { Q('aemail').focus(); } else { Q('ausername').focus(); } } // Email is username
422 + if (x == 3) { Q('remail').focus(); }
423 + if (x == 4) { Q('tokenInput').focus(); }
424 + if (x == 5) { Q('resetTokenInput').focus(); }
425 + if (x == 6) { Q('rapassword1').focus(); }
426 + }
427 +
428 + function validateLogin(box, e) {
429 + var ok = ((Q('username').value.length > 0) && (Q('username').value.indexOf(' ') == -1) && (Q('password').value.length > 0));
430 + QE('loginButton', ok);
431 + setDialogMode(0);
432 + if ((e != null) && (e.keyCode == 13)) { if (box == 1) { Q('password').focus(); } else if (box == 2) { Q('loginButton').click(); } }
433 + if (e != null) { haltEvent(e); }
434 + }
435 +
436 + function validateCreate(box,e) {
437 + setDialogMode(0);
438 + var ok = false;
439 + 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); }
440 + ok &= ((validateEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
441 + if ((newAccountPass == 1) && (Q('anewaccountpass').value.length == 0)) { ok = false; }
442 + if (Q('apassword1').value == '') {
443 + QH('passWarning', '');
444 + QV('passwordPolicyCallout', false);
445 + } else {
446 + if (!passRequirementsEx) {
447 + // No password requirements, display password strength
448 + var passStrength = checkPasswordStrength(Q('apassword1').value);
449 + if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
450 + else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
451 + else { QH('passWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
452 + } else {
453 + // Password requirements provided, use that
454 + var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
455 + if (passReq == false) {
456 + ok = false;
457 + //QS('nuPass1').color = '#7b241c';
458 + //QS('nuPass2').color = '#7b241c';
459 + QH('passWarning', '<span style=color:red><b>' + "Política de senha" + '</b><span>'); // TODO: Display problem hint
460 + QV('passwordPolicyCallout', true);
461 + QH('passwordPolicyCallout', passwordPolicyText(Q('apassword1').value));
462 + } else {
463 + QH('passWarning', '');
464 + QV('passwordPolicyCallout', false);
465 + }
466 + }
467 + }
468 + QE('createButton', ok);
469 + if ((e != null) && (e.keyCode == 13)) {
470 + if (box == 1) { Q('aemail').focus(); }
471 + if (box == 2) { Q('apassword1').focus(); }
472 + if (box == 3) { Q('apassword2').focus(); }
473 + if (box == 4) { Q('apasswordhint').focus(); }
474 + if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { Q('createButton').click(); } }
475 + if (box == 6) { Q('createButton').click(); }
476 + }
477 + if (e != null) { haltEvent(e); }
478 + }
479 +
480 + function validatePassReset(box, e) {
481 + setDialogMode(0);
482 + var pass1ok = (Q('rapassword1').value.length > 0);
483 + var pass2ok = (Q('rapassword2').value.length > 0) && (Q('rapassword2').value == Q('rapassword1').value);
484 + var ok = (pass1ok && pass2ok);
485 +
486 + // Color the fields
487 + QS('rnuPass1').color = pass1ok ? 'black' : '#7b241c';
488 + QS('rnuPass2').color = pass2ok ? 'black' : '#7b241c';
489 +
490 + if (Q('rapassword1').value == '') {
491 + QH('rpassWarning', '');
492 + QV('rpasswordPolicyCallout', false);
493 + } else {
494 + if (!passRequirementsEx) {
495 + // No password requirements, display password strength
496 + var passStrength = checkPasswordStrength(Q('rapassword1').value);
497 + if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
498 + else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
499 + else { QH('rpassWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
500 + } else {
501 + // Password requirements provided, use that
502 + var passReq = checkPasswordRequirements(Q('rapassword1').value, passRequirements);
503 + if (passReq == false) {
504 + ok = false;
505 + QS('rnuPass1').color = '#7b241c';
506 + QS('rnuPass2').color = '#7b241c';
507 + 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
508 + QV('rpasswordPolicyCallout', true);
509 + QH('rpasswordPolicyCallout', passwordPolicyText(Q('rapassword1').value));
510 + } else {
511 + QH('rpassWarning', '');
512 + QV('rpasswordPolicyCallout', false);
513 + }
514 + }
515 + }
516 + if ((e != null) && (e.keyCode == 13)) {
517 + if (box == 2) { Q('rapassword1').focus(); }
518 + if (box == 3) { Q('rapassword2').focus(); }
519 + if (box == 4) { Q('rapasswordhint').focus(); }
520 + if (box == 6) { Q('resetPassButton').click(); }
521 + }
522 + if (e != null) { haltEvent(e); }
523 + QE('resetPassButton', ok);
524 + }
525 +
526 + function validateReset(e) {
527 + setDialogMode(0);
528 + var x = validateEmail(Q('remail').value);
529 + QE('eresetButton', x);
530 + if ((e != null) && (e.keyCode == 13) && (x == true)) { Q('eresetButton').click(); }
531 + if (e != null) { haltEvent(e); }
532 + }
533 +
534 + function passwordPolicyText(pass) {
535 + var policy = '<div style=text-align:left>';
536 + var counts = strCount(pass);
537 + if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += format("Comprimento mínimo de {0}", passRequirements.min) + '<br />'; }
538 + if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += format("Comprimento máximo de {0}", passRequirements.max) + '<br />'; }
539 + if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += format("{0} maiúsculas", passRequirements.upper) + '<br />'; }
540 + if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += format("{0} letras minúsculas", passRequirements.lower) + '<br />'; }
541 + if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += format("{0} numérico", passRequirements.numeric) + '<br />'; }
542 + if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += format("{0} não alfanumérico", passRequirements.nonalpha) + '<br />'; }
543 + policy += '</div>';
544 + return policy;
545 + }
546 +
547 + // Return a password strength score
548 + function checkPasswordStrength(password) {
549 + 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) }
550 + if (!password) return 0;
551 + for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
552 + for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
553 + return parseInt(r + (varCount - 1) * 10);
554 + }
555 +
556 + // Check password requirements
557 + function checkPasswordRequirements(password, requirements) {
558 + if ((requirements == null) || (requirements == '') || (typeof requirements != 'object')) return true;
559 + if (requirements.min) { if (password.length < requirements.min) return false; }
560 + if (requirements.max) { if (password.length > requirements.max) return false; }
561 + var counts = strCount(password);
562 + if (requirements.numeric && (counts.numeric < requirements.numeric)) return false;
563 + if (requirements.lower && (counts.lower < requirements.lower)) return false;
564 + if (requirements.upper && (counts.upper < requirements.upper)) return false;
565 + if (requirements.nonalpha && (counts.nonalpha < requirements.nonalpha)) return false;
566 + return true;
567 + }
568 +
569 + function strCount(password) {
570 + var counts = { numeric: 0, lower: 0, upper: 0, nonalpha: 0 };
571 + if (typeof password != 'string') return counts;
572 + for (var i = 0; i < password.length; i++) {
573 + if (/\d/.test(password[i])) { counts.numeric++; }
574 + if (/[a-z]/.test(password[i])) { counts.lower++; }
575 + if (/[A-Z]/.test(password[i])) { counts.upper++; }
576 + if (/\W/.test(password[i])) { counts.nonalpha++; }
577 + }
578 + return counts;
579 + }
580 +
581 + var xcheckTokenTimer = null;
582 + function checkTokenTimer(enter) {
583 + if ((enter == 0) && (xcheckTokenTimer != null)) { clearInterval(xcheckTokenTimer); xcheckTokenTimer = null; }
584 + if ((enter == 1) && (xcheckTokenTimer == null)) { xcheckTokenTimer = setInterval(checkToken, 200); }
585 + }
586 +
587 + function checkToken() {
588 + var t1 = Q('tokenInput').value, t2 = t1.split(' ').join('');
589 + if (t1 != t2) { Q('tokenInput').value = t2; }
590 + QE('tokenOkButton', (Q('tokenInput').value.length == 6) || (Q('tokenInput').value.length == 8) || (Q('tokenInput').value.length == 44));
591 + }
592 +
593 + function resetCheckToken() {
594 + var t1 = Q('resetTokenInput').value, t2 = t1.split(' ').join('');
595 + if (t1 != t2) { Q('resetTokenInput').value = t2; }
596 + QE('resetTokenOkButton', (Q('resetTokenInput').value.length == 6) || (Q('resetTokenInput').value.length == 8) || (Q('resetTokenInput').value.length == 44));
597 + }
598 +
599 + //
600 + // POPUP DIALOG
601 + //
602 +
603 + // undefined = Hidden, 1 = Generic Message
604 + var xxdialogMode;
605 + var xxdialogFunc;
606 + var xxdialogButtons;
607 + var xxdialogTag;
608 + var xxcurrentView = 0;
609 +
610 + // Display a dialog box
611 + // 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)
612 + function setDialogMode(x, y, b, f, c, tag) {
613 + xxdialogMode = x;
614 + xxdialogFunc = f;
615 + xxdialogButtons = b;
616 + xxdialogTag = tag;
617 + QE('idx_dlgOkButton', true);
618 + QV('idx_dlgOkButton', b & 1);
619 + QV('idx_dlgCancelButton', b & 2);
620 + QV('id_dialogclose', (b & 2) || (b & 8));
621 + QV('idx_dlgButtonBar', b & 7);
622 + if (y) QH('id_dialogtitle', y);
623 + for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
624 + QV('dialog', x);
625 + if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
626 + }
627 +
628 + function dialogclose(x) {
629 + var f = xxdialogFunc;
630 + var b = xxdialogButtons;
631 + var t = xxdialogTag;
632 + setDialogMode();
633 + if (((b & 8) || x) && f) f(x, t);
634 + }
635 +
636 + function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + 'px'); }
637 + function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
638 + function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
639 + 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; }
640 + function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
641 + function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
642 + 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
643 + 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; }); };
644 +
645 + </script>
646 +
647 +</body></html>
\ No newline at end of file
views/translations/login_pt.handlebars new
+727
@@ -0,0 +1,727 @@
1 +<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico">
8 + <link keeplink="1" type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
9 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
10 + <script keeplink="1" type="text/javascript" src="scripts/u2f-api.js"></script>
11 + <title>{{{title}}} - Login</title>
12 +</head>
13 +<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" class="arg_hide login">
14 + <div id="container">
15 + <div id="masthead">
16 + <div class="title">{{{title}}}</div>
17 + <div class="title2">{{{title2}}}</div>
18 + </div>
19 + <div id="topbar" class="noselect style3" style="height:24px">
20 + <div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
21 + ♦
22 + <div id="uiMenu" style="display:none">
23 + <div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
24 + <div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
25 + <div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
26 + <div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
27 + </div>
28 + </div>
29 + </div>
30 + <div id="column_l">
31 + <h1>Bem vindo</h1>
32 + <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>
33 + <table id="centralTable" style="">
34 + <tbody><tr>
35 + <td id="welcomeimage">
36 + <picture>
37 + <img alt="" src="welcome.jpg" style="border-radius:20px">
38 + </picture>
39 + </td>
40 + <td id="logincell">
41 + <div id="loginpanel" style="display:none">
42 + <form method="post">
43 + <input type="hidden" name="action" value="login">
44 + <div id="message1"></div>
45 + <div>
46 + <b>Entrar</b>
47 + </div>
48 + <table>
49 + <tbody><tr>
50 + <td id="loginusername" align="right" width="100">Nome de usuário:</td>
51 + <td><input id="username" type="text" maxlength="64" name="username" onchange="validateLogin(1)" onkeyup="validateLogin(1,event)"></td>
52 + </tr>
53 + <tr>
54 + <td align="right">Senha:</td>
55 + <td><input id="password" type="password" maxlength="256" name="password" autocomplete="off" onchange="validateLogin(2)" onkeyup="validateLogin(2,event)"></td>
56 + </tr>
57 + <tr>
58 + <td><div id="showPassHintLink" style="display:none"><a onclick="return showPassHint(event);" href="#" style="cursor:pointer">Mostrar dica</a></div></td>
59 + <td align="right"><input id="loginButton" type="submit" value="Entrar" disabled="disabled"></td>
60 + </tr>
61 + </tbody></table>
62 + <div id="hrAccountDiv" style="display:none"><hr></div>
63 + <div id="resetAccountDiv" style="display:none;padding:2px">
64 + <span id="resetAccountSpan">Esqueceu seu nome de usuário / senha?</span> <a onclick="return xgo(3,event);" href="#" style="cursor:pointer">Redefinir conta</a>.
65 + </div>
66 + <div id="newAccountDiv" style="display:none;padding:2px">
67 + Não possui uma conta? <a onclick="return xgo(2,event);" href="#" style="cursor:pointer">Crie um</a>.
68 + </div>
69 + <input id="loginformargs" name="urlargs" type="hidden" value="">
70 + </form>
71 + </div>
72 + <div id="createpanel" style="display:none;position:relative">
73 + <form method="post">
74 + <input type="hidden" name="action" value="createaccount">
75 + <div id="message2"></div>
76 + <div>
77 + <b>Criação de conta</b>
78 + </div>
79 + <div id="passwordPolicyCallout" style="display:none"></div>
80 + <table>
81 + <tbody><tr id="nuUserRow">
82 + <td id="nuUser" align="right" width="100">Nome de usuário:</td>
83 + <td><input id="ausername" type="text" name="username" onchange="validateCreate(1)" maxlength="64" onkeydown="haltReturn(event)" onkeyup="validateCreate(1,event)"></td>
84 + </tr>
85 + <tr>
86 + <td id="nuEmail" align="right" width="100">Email:</td>
87 + <td><input id="aemail" type="text" name="email" onchange="validateCreate(2)" maxlength="256" onkeydown="haltReturn(event)" onkeyup="validateCreate(2,event)"></td>
88 + </tr>
89 + <tr>
90 + <td id="nuPass1" align="right">Senha:</td>
91 + <td><input id="apassword1" type="password" name="password1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(3,event)" onkeyup="validateCreate(3,event)"></td>
92 + </tr>
93 + <tr>
94 + <td id="nuPass2" align="right">Senha:</td>
95 + <td><input id="apassword2" type="password" name="password2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(4,event)" onkeyup="validateCreate(4,event)"></td>
96 + </tr>
97 + <tr id="createPanelHint" style="display:none">
98 + <td id="nuHint" align="right">Dica de senha</td>
99 + <td><input id="apasswordhint" type="text" name="apasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(5,event)" onkeyup="validateCreate(5,event)"></td>
100 + </tr>
101 + <tr id="newAccountPass" title="Insira o token de criação da conta">
102 + <td id="nuToken" align="right">Token de criação</td>
103 + <td><input id="anewaccountpass" type="password" name="anewaccountpass" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(6,event)" onkeyup="validateCreate(6,event)"></td>
104 + </tr>
105 + <tr>
106 + <td colspan="2">
107 + <div style="float:right"><input id="createButton" type="submit" value="Criar conta" disabled="disabled"></div>
108 + <div id="passWarning" style="padding-top:6px"></div>
109 + </td>
110 + </tr>
111 + </tbody></table>
112 + <hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
113 + <input id="createformargs" name="urlargs" type="hidden" value="">
114 + </form>
115 + </div>
116 + <div id="resetpanel" style="display:none">
117 + <form method="post">
118 + <input type="hidden" name="action" value="resetaccount">
119 + <div id="message3"></div>
120 + <div>
121 + <b>Redefinição de conta</b>
122 + </div>
123 + <table>
124 + <tbody><tr>
125 + <td align="right" width="100">Email:</td>
126 + <td><input id="remail" type="text" name="email" maxlength="256" onchange="validateReset()" onkeyup="validateReset(event)"></td>
127 + </tr>
128 + <tr>
129 + <td colspan="2">
130 + <div style="float:right"><input id="eresetButton" type="submit" value="Redefinir Conta" disabled="disabled"></div>
131 + <div id="passWarning" style="padding-top:6px"></div>
132 + </td>
133 + </tr>
134 + </tbody></table>
135 + <hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
136 + <input id="resetformargs" name="urlargs" type="hidden" value="">
137 + </form>
138 + </div>
139 + <div id="tokenpanel" style="display:none">
140 + <form method="post" autocomplete="off">
141 + <input type="hidden" name="action" value="tokenlogin">
142 + <input type="hidden" name="hwstate" value="{{{hwstate}}}">
143 + <div id="message4"></div>
144 + <table>
145 + <tbody><tr>
146 + <td align="right" width="100">Token de logon:</td>
147 + <td>
148 + <input id="tokenInput" type="text" name="token" maxlength="50" onchange="checkToken(event)" onpaste="resetCheckToken(event)" onkeyup="checkToken(event)" onkeydown="checkToken(event)"><br>
149 + <input id="hwtokenInput" type="text" name="hwtoken" style="display:none">
150 + </td>
151 + </tr>
152 + <tr>
153 + <td colspan="2" style="align-content:center">
154 + <label><input id="tokenInputRemember" name="remembertoken" type="checkbox">Remember this device for 30 days.</label>
155 + </td>
156 + </tr>
157 + <tr>
158 + <td colspan="2">
159 + <div style="float:right"><input id="tokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
160 + <div style="float:right"><input style="display:none;float:right" id="securityKeyButton" type="button" value="Use Security Key" onclick="useSecurityKey()"></div>
161 + </td>
162 + </tr>
163 + </tbody></table>
164 + <hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
165 + <input id="tokenformargs" name="urlargs" type="hidden" value="">
166 + </form>
167 + </div>
168 + <div id="resettokenpanel" style="display:none">
169 + <form method="post">
170 + <input type="hidden" name="action" value="resetaccount">
171 + <div id="message5"></div>
172 + <table>
173 + <tbody><tr>
174 + <td align="right" width="100">Token de logon:</td>
175 + <td>
176 + <input id="resetTokenInput" type="text" name="token" maxlength="50" onchange="resetCheckToken(event)" onkeyup="resetCheckToken(event)" onkeydown="resetCheckToken(event)">
177 + <input id="resetHwtokenInput" type="text" name="hwtoken" style="display:none">
178 + </td>
179 + </tr>
180 + <tr>
181 + <td colspan="2">
182 + <div style="float:right"><input id="resetTokenOkButton" type="submit" value="Entrar" disabled="disabled"></div>
183 + </td>
184 + </tr>
185 + </tbody></table>
186 + <hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
187 + <input id="resettokenformargs" name="urlargs" type="hidden" value="">
188 + </form>
189 + </div>
190 + <div id="resetpasswordpanel" style="display:none;position:relative">
191 + <form method="post">
192 + <input type="hidden" name="action" value="resetpassword">
193 + <div id="message6"></div>
194 + <div id="rpasswordPolicyCallout" style="display:none"></div>
195 + <table>
196 + <tbody><tr>
197 + <td id="rnuPass1" width="100" align="right">Senha:</td>
198 + <td><input id="rapassword1" type="password" name="rpassword1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(3,event)" onkeyup="validatePassReset(3,event)"></td>
199 + </tr>
200 + <tr>
201 + <td id="rnuPass2" align="right">Senha:</td>
202 + <td><input id="rapassword2" type="password" name="rpassword2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(4,event)" onkeyup="validatePassReset(4,event)"></td>
203 + </tr>
204 + <tr id="resetpasswordpanelHint" style="display:none">
205 + <td id="rnuHint" align="right">Dica de senha</td>
206 + <td><input id="rapasswordhint" type="text" name="rpasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(5,event)" onkeyup="validatePassReset(5,event)"></td>
207 + </tr>
208 + <tr>
209 + <td colspan="2">
210 + <div style="float:right"><input id="resetPassButton" type="submit" value="Redefinir senha" disabled="disabled"></div>
211 + <div id="rpassWarning" style="padding-top:6px"></div>
212 + </td>
213 + </tr>
214 + </tbody></table>
215 + <hr><a onclick="return xgo(1,event);" href="#" style="cursor:pointer">Volte ao login</a>
216 + <input id="resetpasswordformargs" name="urlargs" type="hidden" value="">
217 + </form>
218 + </div>
219 + </td>
220 + </tr>
221 + </tbody></table>
222 + <br>
223 + </div>
224 + <div id="footer">
225 + <div class="footer1">{{{footer}}}</div>
226 + <div class="footer2">
227 + {{{rootCertLink}}}
228 + &nbsp;<a href="terms">Termos &amp; Privacidade</a>
229 + </div>
230 + </div>
231 +
232 + </div>
233 + <div id="dialog" style="display:none">
234 + <div id="dialogHeader">
235 + <div id="id_dialogclose" style="float:right;padding:5px;cursor:pointer" onclick="setDialogMode()"><b>X</b></div>
236 + <div id="id_dialogtitle" style="padding:5px"></div>
237 + <div style="width:100%;margin:6px"></div>
238 + </div>
239 + <div id="dialogBody">
240 + <div id="dialog1">
241 + <div id="id_dialogMessage" style=""></div>
242 + </div>
243 + <div id="dialog2" style="">
244 + <div id="id_dialogOptions"></div>
245 + </div>
246 + </div>
247 + <div id="idx_dlgButtonBar" style="">
248 + <input id="idx_dlgCancelButton" type="button" value="Cancelar" style="" onclick="dialogclose(0)">
249 + <input id="idx_dlgOkButton" type="button" value="Ok" style="" onclick="dialogclose(1)">
250 + </div>
251 + </div>
252 + <script>
253 + 'use strict';
254 + var passhint = '{{{passhint}}}';
255 + var loginMode = '{{{loginmode}}}';
256 + var newAccount = '{{{newAccount}}}';
257 + var newAccountPass = parseInt('{{{newAccountPass}}}');
258 + var emailCheck = ('{{{emailcheck}}}' == 'true');
259 + var passRequirements = '{{{passRequirements}}}';
260 + var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
261 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
262 + var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
263 + var features = parseInt('{{{features}}}');
264 + var welcomeText = decodeURIComponent('{{{welcometext}}}');
265 + var currentpanel = 0;
266 + var uiMode = parseInt(getstore('uiMode', '1'));
267 + var webPageFullScreen = true;
268 + var nightMode = (getstore('_nightMode', '0') == '1');
269 + var publicKeyCredentialRequestOptions = null;
270 +
271 + // Display the right server message
272 + var messageid = parseInt('{{{messageid}}}');
273 + var okmessages = ['', "Hold on, reset mail sent."];
274 + 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."];
275 + if (messageid > 0) {
276 + var msg = '';
277 + if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
278 + else if ((messageid >= 100) && ((messageid - 100) < failmessages.length)) { msg = failmessages[messageid - 100]; }
279 + if (msg != '') {
280 + 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 />'); }
281 + for (var i = 1; i < 7; i++) { QH('message' + i, msg); }
282 + }
283 + }
284 +
285 + // If URL arguments are provided, add them to form posts
286 + if (window.location.href.indexOf('?') > 0) {
287 + var urlargs = window.location.href.substring(window.location.href.indexOf('?'));
288 + Q('loginformargs').value = urlargs;
289 + Q('createformargs').value = urlargs;
290 + Q('resetformargs').value = urlargs;
291 + Q('tokenformargs').value = urlargs;
292 + Q('resettokenformargs').value = urlargs;
293 + Q('resetpasswordformargs').value = urlargs;
294 + }
295 +
296 + //var webPageFullScreen = getstore('webPageFullScreen', true);
297 + //if (webPageFullScreen == 'false') { webPageFullScreen = false; }
298 + //if (webPageFullScreen == 'true') { webPageFullScreen = true; }
299 + //toggleFullScreen();
300 +
301 + function startup() {
302 + if ((features & 32) == 0) {
303 + // Guard against other site's top frames (web bugs).
304 + var loc = null;
305 + try { loc = top.location.toString().toLowerCase(); } catch (e) { }
306 + if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
307 + }
308 +
309 + if (features & 0x200000) { // Email is username
310 + QH('loginusername', "Email:");
311 + QH('resetAccountSpan', "Esqueceu a senha?");
312 + QV('nuUserRow', false);
313 + }
314 +
315 + if (nightMode) { QC('body').add('night'); }
316 +
317 + QV('createPanelHint', passRequirements.hint === true);
318 + QV('resetpasswordpanelHint', passRequirements.hint === true);
319 +
320 + // Display the welcome text
321 + if (welcomeText) { QH('welcomeText', welcomeText); }
322 + QH('welcomeText', addTextLink('MeshCentral', Q('welcomeText').innerHTML, 'http://www.meshcommander.com/meshcentral2'));
323 + QV('welcomeText', true);
324 +
325 + window.onresize = center;
326 + center();
327 +
328 + validateLogin();
329 + validateCreate();
330 + if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
331 + QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
332 + if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
333 + QV('newAccountPass', (newAccountPass == 1));
334 + QV('resetAccountDiv', (emailCheck == true));
335 + QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
336 +
337 + if (loginMode == '4') {
338 + try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
339 + QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
340 + }
341 +
342 + if (loginMode == '5') {
343 + try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
344 + if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
345 + if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
346 +
347 + publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
348 + for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
349 + publicKeyCredentialRequestOptions.allowCredentials.push(
350 + { id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
351 + );
352 + }
353 +
354 + // New WebAuthn hardware keys
355 + navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
356 + function (rawAssertion) {
357 + var assertion = {
358 + id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
359 + clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
360 + userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
361 + signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
362 + authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
363 + };
364 + Q('resetHwtokenInput').value = JSON.stringify(assertion);
365 + QE('resetTokenOkButton', true);
366 + Q('resetTokenOkButton').click();
367 + },
368 + function (error) { console.log('credentials-get error', error); }
369 + );
370 + }
371 + }
372 +
373 + // Setup the user interface in the right mode
374 + userInterfaceSelectMenu();
375 + }
376 +
377 + // Use a hardware security key
378 + function useSecurityKey() {
379 + if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
380 + if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
381 +
382 + publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
383 + for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
384 + publicKeyCredentialRequestOptions.allowCredentials.push(
385 + { id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
386 + );
387 + }
388 +
389 + // New WebAuthn hardware keys
390 + navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
391 + function (rawAssertion) {
392 + var assertion = {
393 + id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
394 + clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
395 + userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
396 + signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
397 + authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
398 + };
399 + Q('hwtokenInput').value = JSON.stringify(assertion);
400 + QE('tokenOkButton', true);
401 + Q('tokenOkButton').click();
402 + },
403 + function (error) { console.log('credentials-get error', error); }
404 + );
405 + }
406 + }
407 +
408 + function showPassHint(e) {
409 + messagebox("Dica de Senha", passhint);
410 + haltEvent(e);
411 + return false;
412 + }
413 +
414 + function xgo(x, e) {
415 + QV('message1', false);
416 + QV('message2', false);
417 + QV('message3', false);
418 + QV('message4', false);
419 + QV('message5', false);
420 + QV('message6', false);
421 + go(x);
422 + haltEvent(e);
423 + return false;
424 + }
425 +
426 + function go(x) {
427 + currentpanel = x;
428 + setDialogMode(0);
429 + QV('showPassHintLink', false);
430 + QV('loginpanel', x == 1);
431 + QV('createpanel', x == 2);
432 + QV('resetpanel', x == 3);
433 + QV('tokenpanel', x == 4);
434 + QV('resettokenpanel', x == 5);
435 + QV('resetpasswordpanel', x == 6);
436 + if (x == 1) { Q('username').focus(); }
437 + if (x == 2) { if (features & 0x200000) { Q('aemail').focus(); } else { Q('ausername').focus(); } } // Email is username
438 + if (x == 3) { Q('remail').focus(); }
439 + if (x == 4) { Q('tokenInput').focus(); }
440 + if (x == 5) { Q('resetTokenInput').focus(); }
441 + if (x == 6) { Q('rapassword1').focus(); }
442 + }
443 +
444 + function validateLogin(box, e) {
445 + var ok = ((Q('username').value.length > 0) && (Q('username').value.indexOf(' ') == -1) && (Q('password').value.length > 0));
446 + QE('loginButton', ok);
447 + setDialogMode(0);
448 + 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(); } }
449 + if (e != null) { haltEvent(e); }
450 + }
451 +
452 + function validateCreate(box, e) {
453 + setDialogMode(0);
454 + var userok = false;
455 + 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); }
456 + var emailok = (validateEmail(Q('aemail').value) == true);
457 + var pass1ok = (Q('apassword1').value.length > 0);
458 + var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
459 + var newAccOk = (newAccountPass == 0) || (Q('anewaccountpass').value.length > 0);
460 + var ok = (userok && emailok && pass1ok && pass2ok && newAccOk);
461 +
462 + // Color the fields
463 + QS('nuUser').color = userok?'black':'#7b241c';
464 + QS('nuEmail').color = emailok?'black':'#7b241c';
465 + QS('nuPass1').color = pass1ok?'black':'#7b241c';
466 + QS('nuPass2').color = pass2ok?'black':'#7b241c';
467 + QS('nuToken').color = newAccOk?'black':'#7b241c';
468 +
469 + if (Q('apassword1').value == '') {
470 + QH('passWarning', '');
471 + QV('passwordPolicyCallout', false);
472 + } else {
473 + if (!passRequirementsEx) {
474 + // No password requirements, display password strength
475 + var passStrength = checkPasswordStrength(Q('apassword1').value);
476 + if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
477 + else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
478 + else { QH('passWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
479 + } else {
480 + // Password requirements provided, use that
481 + var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
482 + if (passReq == false) {
483 + ok = false;
484 + QS('nuPass1').color = '#7b241c';
485 + QS('nuPass2').color = '#7b241c';
486 + 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
487 + QV('passwordPolicyCallout', true);
488 + QH('passwordPolicyCallout', passwordPolicyText(Q('apassword1').value));
489 + } else {
490 + QH('passWarning', '');
491 + QV('passwordPolicyCallout', false);
492 + }
493 + }
494 + }
495 + if ((e != null) && (e.keyCode == 13)) {
496 +
497 + if ((box == 1) && userok) { Q('aemail').focus(); }
498 + if ((box == 2) && emailok) { Q('apassword1').focus(); }
499 + if ((box == 3) && pass1ok) { Q('apassword2').focus(); }
500 + if ((box == 4) && pass2ok) { if (passRequirements.hint === true) { Q('apasswordhint').focus(); } else { box = 5; } }
501 + if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { box = 6; } }
502 + if (box == 6) { Q('createButton').click(); }
503 + }
504 + if (e != null) { haltEvent(e); }
505 + QE('createButton', ok);
506 + }
507 +
508 + function validatePassReset(box, e) {
509 + setDialogMode(0);
510 + var pass1ok = (Q('rapassword1').value.length > 0);
511 + var pass2ok = (Q('rapassword2').value.length > 0) && (Q('rapassword2').value == Q('rapassword1').value);
512 + var ok = (pass1ok && pass2ok);
513 +
514 + // Color the fields
515 + QS('rnuPass1').color = pass1ok ? 'black' : '#7b241c';
516 + QS('rnuPass2').color = pass2ok ? 'black' : '#7b241c';
517 +
518 + if (Q('rapassword1').value == '') {
519 + QH('rpassWarning', '');
520 + QV('rpasswordPolicyCallout', false);
521 + } else {
522 + if (!passRequirementsEx) {
523 + // No password requirements, display password strength
524 + var passStrength = checkPasswordStrength(Q('rapassword1').value);
525 + if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>' + "Senha forte" + '</b><span>'); }
526 + else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>' + "Boa senha" + '</b><span>'); }
527 + else { QH('rpassWarning', '<span style=color:red><b>' + "Senha fraca" + '</b><span>'); }
528 + } else {
529 + // Password requirements provided, use that
530 + var passReq = checkPasswordRequirements(Q('rapassword1').value, passRequirements);
531 + if (passReq == false) {
532 + ok = false;
533 + QS('rnuPass1').color = '#7b241c';
534 + QS('rnuPass2').color = '#7b241c';
535 + 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
536 + QV('rpasswordPolicyCallout', true);
537 + QH('rpasswordPolicyCallout', passwordPolicyText(Q('rapassword1').value));
538 + } else {
539 + QH('rpassWarning', '');
540 + QV('rpasswordPolicyCallout', false);
541 + }
542 + }
543 + }
544 + if ((e != null) && (e.keyCode == 13)) {
545 + if (box == 2) { Q('rapassword1').focus(); }
546 + if (box == 3) { Q('rapassword2').focus(); }
547 + if (box == 4) { Q('rapasswordhint').focus(); }
548 + if (box == 6) { Q('resetPassButton').click(); }
549 + }
550 + if (e != null) { haltEvent(e); }
551 + QE('resetPassButton', ok);
552 + }
553 +
554 + function passwordPolicyText(pass) {
555 + var policy = '<div style=text-align:left>';
556 + var counts = strCount(pass);
557 + if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += format("Comprimento mínimo de {0}", passRequirements.min) + '<br />'; }
558 + if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += format("Comprimento máximo de {0}", passRequirements.max) + '<br />'; }
559 + if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += format("{0} maiúsculas", passRequirements.upper) + '<br />'; }
560 + if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += format("{0} letras minúsculas", passRequirements.lower) + '<br />'; }
561 + if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += format("{0} numérico", passRequirements.numeric) + '<br />'; }
562 + if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += format("{0} não alfanumérico", passRequirements.nonalpha) + '<br />'; }
563 + policy += '</div>';
564 + return policy;
565 + }
566 +
567 + function showPasswordPolicy() {
568 + messagebox("Política de senha", passwordPolicyText());
569 + }
570 +
571 + function validateReset(e) {
572 + setDialogMode(0);
573 + var x = validateEmail(Q('remail').value);
574 + QE('eresetButton', x);
575 + if ((e != null) && (e.keyCode == 13) && (x == true)) {
576 + Q('eresetButton').click();
577 + }
578 + if (e != null) { haltEvent(e); }
579 + }
580 +
581 + // Return a password strength score
582 + function checkPasswordStrength(password) {
583 + 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) }
584 + if (!password) return 0;
585 + for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
586 + for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
587 + return parseInt(r + (varCount - 1) * 10);
588 + }
589 +
590 + // Check password requirements
591 + function checkPasswordRequirements(password, requirements) {
592 + if ((requirements == null) || (requirements == '') || (typeof requirements != 'object')) return true;
593 + if (requirements.min) { if (password.length < requirements.min) return false; }
594 + if (requirements.max) { if (password.length > requirements.max) return false; }
595 + var counts = strCount(password);
596 + if (requirements.numeric && (counts.numeric < requirements.numeric)) return false;
597 + if (requirements.lower && (counts.lower < requirements.lower)) return false;
598 + if (requirements.upper && (counts.upper < requirements.upper)) return false;
599 + if (requirements.nonalpha && (counts.nonalpha < requirements.nonalpha)) return false;
600 + return true;
601 + }
602 +
603 + function strCount(password) {
604 + var counts = { numeric: 0, lower: 0, upper: 0, nonalpha: 0 };
605 + if (typeof password != 'string') return counts;
606 + for (var i = 0; i < password.length; i++) {
607 + if (/\d/.test(password[i])) { counts.numeric++; }
608 + if (/[a-z]/.test(password[i])) { counts.lower++; }
609 + if (/[A-Z]/.test(password[i])) { counts.upper++; }
610 + if (/\W/.test(password[i])) { counts.nonalpha++; }
611 + }
612 + return counts;
613 + }
614 +
615 + function checkToken() {
616 + var t1 = Q('tokenInput').value;
617 + var t2 = t1.split(' ').join('');
618 + if (t1 != t2) { Q('tokenInput').value = t2; }
619 + QE('tokenOkButton', (Q('tokenInput').value.length == 6) || (Q('tokenInput').value.length == 8) || (Q('tokenInput').value.length == 44));
620 + }
621 +
622 + function resetCheckToken() {
623 + var t1 = Q('resetTokenInput').value;
624 + var t2 = t1.split(' ').join('');
625 + if (t1 != t2) { Q('resetTokenInput').value = t2; }
626 + QE('resetTokenOkButton', (Q('resetTokenInput').value.length == 6) || (Q('resetTokenInput').value.length == 8) || (Q('resetTokenInput').value.length == 44));
627 + }
628 +
629 + //
630 + // POPUP DIALOG
631 + //
632 +
633 + // undefined = Hidden, 1 = Generic Message
634 + var xxdialogMode;
635 + var xxdialogFunc;
636 + var xxdialogButtons;
637 + var xxdialogTag;
638 + var xxcurrentView = 0;
639 +
640 + // Display a dialog box
641 + // 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)
642 + function setDialogMode(x, y, b, f, c, tag) {
643 + xxdialogMode = x;
644 + xxdialogFunc = f;
645 + xxdialogButtons = b;
646 + xxdialogTag = tag;
647 + QE('idx_dlgOkButton', true);
648 + QV('idx_dlgOkButton', b & 1);
649 + QV('idx_dlgCancelButton', b & 2);
650 + QV('id_dialogclose', (b & 2) || (b & 8));
651 + QV('idx_dlgButtonBar', b & 7);
652 + if (y) QH('id_dialogtitle', y);
653 + for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
654 + QV('dialog', x);
655 + if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
656 + }
657 +
658 + function dialogclose(x) {
659 + var f = xxdialogFunc;
660 + var b = xxdialogButtons;
661 + var t = xxdialogTag;
662 + setDialogMode();
663 + if (((b & 8) || x) && f) f(x, t);
664 + }
665 +
666 + // Toggle the web page to full screen
667 + function toggleFullScreen(toggle) {
668 + //if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
669 + if (webPageFullScreen == false) {
670 + // By adding body class, it will change a style of all ellements using CSS selector
671 + // No need for JS anymore and it will be consistent style for all the templates.
672 + QC('body').remove('fullscreen');
673 + } else {
674 + QC('body').add('fullscreen');
675 + }
676 + QV('body', true);
677 + center();
678 + }
679 +
680 + // Toggle user interface menu
681 + function showUserInterfaceSelectMenu() {
682 + Q('uiViewButton1').classList.remove('uiSelectorSel');
683 + Q('uiViewButton2').classList.remove('uiSelectorSel');
684 + Q('uiViewButton3').classList.remove('uiSelectorSel');
685 + try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
686 + QV('uiMenu', (QS('uiMenu').display == 'none'));
687 + if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
688 + }
689 +
690 + function userInterfaceSelectMenu(s) {
691 + if (s) { uiMode = s; putstore('uiMode', uiMode); }
692 + webPageFullScreen = (uiMode < 3);
693 + //webPageStackMenu = (uiMode > 1);
694 + toggleFullScreen(0);
695 + //toggleStackMenu(0);
696 + }
697 +
698 + function toggleNightMode() {
699 + nightMode = !nightMode;
700 + if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
701 + putstore('_nightMode', (nightMode ? '1' : '0'));
702 + }
703 +
704 + function center() {
705 + /* Now we use CSS media to achive the same effect as deleted JS */
706 + if (webPageFullScreen == false) {
707 + QS('centralTable')['margin-top'] = '';
708 + } else {
709 + var h = ((Q('column_l').clientHeight) / 2) - 220;
710 + if (h < 0) h = 0;
711 + QS('centralTable')['margin-top'] = h + 'px';
712 + }
713 + }
714 + function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
715 + function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
716 + 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; }
717 + function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
718 + function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
719 + 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
720 + function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
721 + 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; } }
722 + 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; }); };
723 + 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); }
724 +
725 + </script>
726 +
727 +</body></html>
\ No newline at end of file
views/translations/message-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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 &amp; Privacidade</a></table></div></div></div>
\ No newline at end of file
views/translations/message_pt.handlebars new
+40
@@ -0,0 +1,40 @@
1 +<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link type="text/css" href="/styles/style.css" media="screen" rel="stylesheet" title="CSS">
8 + <title>MeshCentral - {{{title3}}}</title>
9 +</head>
10 +<body>
11 + <div id="container" style="max-height:100vh">
12 + <div id="mastheadx"></div>
13 + <div id="masthead" style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden">
14 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px">
15 + <strong><font style="font-size:46px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
16 + </div>
17 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px">
18 + <strong><font style="font-size:14px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
19 + </div>
20 + </div>
21 + <div id="page_content" style="max-height:calc(100vh-138px)">
22 + <div id="column_l">
23 + <h1>{{{title3}}}</h1>
24 + <p style="margin-left:20px">{{{message}}}</p>
25 + <br>
26 + </div>
27 + <div id="footer">
28 + <table cellpadding="0" cellspacing="10" style="width:100%">
29 + <tbody><tr>
30 + <td style="text-align:left"></td>
31 + <td style="text-align:right">
32 + <a href="terms">Termos &amp; Privacidade</a>
33 + </td>
34 + </tr>
35 + </tbody></table>
36 + </div>
37 + </div>
38 + </div>
39 +
40 +</body></html>
\ No newline at end of file
views/translations/messenger-min_pt.handlebars new
+1
@@ -0,0 +1 @@
1 +<!doctypehtml><html style=height:100%><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 src=scripts/common-0.0.1.js></script><script src=scripts/filesaver.js></script><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:0;height:30px;background-color:#036><div style=position:absolute;left:5px;right:215px;bottom:4px;top:4px;background-color:#f0f8ff><input id=xouttext 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:#000"></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:#000"></video></div><input id=uploadFileInput type=file multiple style=display:none><script onunload=onUnLoad()>var userInputFocus=0,args=parseUriArgs(),socket=null,state=0,random=Math.random(),webrtcSessions={},webchannel=null,localStream=null,remoteStream=null,multiWebRtc=!0,userMediaSupport=0,notification=null;getUserMediaSupport(function(e){userMediaSupport=e});var webrtcconfiguration="{{{webrtconfig}}}";if(""==webrtcconfiguration)webrtcconfiguration=null;else try{webrtcconfiguration=JSON.parse(decodeURIComponent(webrtcconfiguration))}catch(e){console.log('Invalid WebRTC config: "'+webrtcconfiguration+'".'),webrtcconfiguration=null}var fileUploads=[],fileDownloads={},currentFileUpload=null,currentFileDownload=null;function onUserInputFocus(e){userInputFocus=e}function displayClear(){QH("xmsg",""),cancelAllFileTransfers(),fileUploads=[],fileDownloads={}}function getUserMediaSupport(i){try{navigator.mediaDevices.enumerateDevices().then(function(e){try{var t=0,n=0;e.forEach(function(e){"audioinput"===e.kind&&(t=1),"videoinput"===e.kind&&(n=1)}),0==t&&i(0),i(t+n)}catch(e){}})}catch(e){}}function displayControl(e){QA("xmsg",'<div style="clear:both"><div style="color:gray;float:left;margin-bottom:2px">'+e+"</div><div></div></div>"),Q("xmsg").scrollTop=Q("xmsg").scrollHeight}function displayLocalVideo(e){QV("localVideo",e),adjustVideoWindows()}function displayRemoteVideo(e){QV("remoteVideo",e),adjustVideoWindows()}function adjustVideoWindows(){var e="none"!=QS("remoteVideo").display;QS("localVideo").top=e?"320px":"45px"}function displayRemote(e){QA("xmsg",'<div style="clear:both"><div class="remoteBubble">'+e+"</div><div></div></div>"),Q("xmsg").scrollTop=Q("xmsg").scrollHeight,Notification&&QV("notifyButton","granted"!=Notification.permission),Notification&&"granted"==Notification.permission&&(null!=notification&&(notification.close(),notification=null),notification=args.title?new Notification("MeshMessenger - "+args.title,{body:e}):new Notification("MeshMessenger",{body:e}))}function xsend(e){null!=notification&&(notification.close(),notification=null),Notification&&QV("notifyButton","granted"!=Notification.permission);var t=Q("xouttext").value;0<t.length&&(Q("xouttext").value="",QA("xmsg",'<div style="clear:both"><div class="localBubble">'+t+"</div><div></div></div>"),Q("xmsg").scrollTop=Q("xmsg").scrollHeight,send({action:"chat",msg:t}))}function haltEvent(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),!1}function parseUriArgs(){var e,t={},n=window.document.location.href.split(/[\?&|\=]/);for(i in n.splice(0,1),n)switch(i%2){case 0:e=decodeURIComponent(n[i]);break;case 1:t[e]=decodeURIComponent(n[i]);var i=parseInt(t[e]);i==t[e]&&(t[e]=i)}return t}function updateControls(){QE("sendButton",2==state),QE("clearButton",2==state),QE("xouttext",2==state),QV("fileButton",2==state),QV("camButton",webchannel&&webchannel.ok&&!localStream&&2==userMediaSupport),QV("micButton",webchannel&&webchannel.ok&&!localStream&&0<userMediaSupport),QV("hangupButton",webchannel&&webchannel.ok&&localStream)}function startWebRTC(t,e){if(null!=webrtcSessions[0]&&0==multiWebRtc)return webrtcSessions[0];var n=null;return"undefined"!=typeof RTCPeerConnection?n=new RTCPeerConnection(webrtcconfiguration):"undefined"!=typeof webkitRTCPeerConnection&&(n=new webkitRTCPeerConnection(webrtcconfiguration)),null==n?null:(n.id=t,n.onicecandidate=function(e){try{null!=e.candidate&&sendws({action:"webRtcIce",ice:e.candidate,id:this.id})}catch(e){}},n.oniceconnectionstatechange=function(){n&&"failed"==n.iceConnectionState&&(n.close(),webrtcSessions[n.id]&&delete webrtcSessions[n.id])},n.ondatachannel=function(e){(webchannel=e.channel).onmessage=function(e){processMessage(e.data,2)},webchannel.onopen=function(){webchannel.ok=!0,updateControls(),sendws({action:"rtcSwitch",v:0})},webchannel.onclose=function(e){webchannel&&webchannel.ok?disconnect():hangUpButtonClick(0)}},n.onnegotiationneeded=function(e){null==n.holdTimer&&(n.holdTimer=setTimeout(function(){n.holdTimer=null,n.createOffer(function(e){n.setLocalDescription(e,function(){sendws({action:"webRtcSdp",sdp:e,id:t})},function(){hangUpButtonClick(t)})},function(){hangUpButtonClick(t)})},20))},n.ontrack=function(e){var t=Q("remoteVideoCanvas");t.srcObject=remoteStream=e.streams[0],t.onloadedmetadata=function(e){t.play()},displayRemoteVideo(!0)},1==e&&((webchannel=n.createDataChannel("DataChannel",{})).onmessage=function(e){processMessage(e.data,2)},webchannel.onopen=function(){webchannel.ok=!0,updateControls(),sendws({action:"rtcSwitch",v:0})},webchannel.onclose=function(e){webchannel&&webchannel.ok?disconnect():hangUpButtonClick(0)}),webrtcSessions[t]=n)}function webRtcHandleOffer(i,e){var t=webrtcSessions[i];t&&t.setRemoteDescription(new RTCSessionDescription(e),function(){"offer"==e.type&&t.createAnswer(function(n){t.setLocalDescription(n,function(e,t){try{sendws({action:"webRtcSdp",sdp:n,id:i})}catch(e){}},function(){hangUpButtonClick(i)})},function(){hangUpButtonClick(i)})},function(){hangUpButtonClick(i)})}function performWebRtcSwitch(){webchannel&&webchannel.ok&&(sendws({action:"rtcSwitch",v:1}),webchannel.xoutBuffer=[])}function disconnect(){0<state&&displayControl("Conexão fechada."),1<state&&setTimeout(start,500),cancelAllFileTransfers(),hangUpButtonClick(0,!0),hangUpButtonClick(1,!0),hangUpButtonClick(2,!0),null!=socket&&(socket.close(),socket=null),updateControls(),state=0}function send(e){if(2==state)if("object"==typeof e&&(e=JSON.stringify(e)),webchannel&&webchannel.ok)null!=webchannel.xoutBuffer?webchannel.xoutBuffer.push(e):webchannel.send(e);else if(null!=socket)try{socket.send(e)}catch(e){}}function sendws(e){2==state&&("object"==typeof e&&(e=JSON.stringify(e)),null!=socket&&socket.send(e))}function webRtcIdSwitch(e){return 0==e?0:3-e}function processMessage(t,e){if("string"==typeof t){try{t=JSON.parse(t)}catch(e){return void console.log("Unable to parse",t)}switch(t.action){case"chat":displayRemote(t.msg);break;case"random":random>t.random&&startWebRTC(0,!0);break;case"webRtcSdp":webrtcSessions[webRtcIdSwitch(t.id)]||startWebRTC(webRtcIdSwitch(t.id),!1),webRtcHandleOffer(webRtcIdSwitch(t.id),t.sdp);break;case"webRtcIce":var n=webrtcSessions[webRtcIdSwitch(t.id)];if(n)try{n.addIceCandidate(new RTCIceCandidate(t.ice))}catch(e){}break;case"videoStop":hangUpButtonClick(webRtcIdSwitch(t.id),!0);break;case"rtcSwitch":switch(t.v){case 0:performWebRtcSwitch();break;case 1:sendws({action:"rtcSwitch",v:2});break;case 2:for(var i in webchannel.xoutBuffer)webchannel.send(webchannel.xoutBuffer[i]);delete webchannel.xoutBuffer;break;default:console.log("Unknown rtcSwitch value: "+t.action)}break;case"file":startFileDownload(t);break;case"fileUploadCancel":cancelFileTransfer(t.id);break;case"fileUploadStart":fileDownloads[t.id]&&((currentFileDownload=fileDownloads[t.id]).data="",changeFileInfo(t.id,2,0),continueFileDownload(t),send({action:"fileUploadAck",id:t.id}));break;case"fileUploadEnd":currentFileDownload&&currentFileDownload.id==t.id&&(changeFileInfo(t.id,3,200),currentFileDownload.done=1,currentFileDownload=null,send({action:"fileUploadAck",id:t.id})),currentFileDownload=null;break;case"fileUploadAck":continueFileUpload();break;case"fileData":currentFileDownload&&currentFileDownload.id==t.id&&(currentFileDownload.data+=t.data,changeFileInfo(t.id,2,200*currentFileDownload.data.length/currentFileDownload.size),send({action:"fileUploadAck",id:t.id}));break;default:console.log("Unhandled object data",t)}}else console.log("Unhandled data",typeof t,t)}function fileButtonClick(){var e=Q("uploadFileInput");1!=e.getAttribute("eventset")&&(e.setAttribute("eventset","1"),e.addEventListener("change",fileSelect,!1)),e.value=null,e.click()}function fileSelect(){if(2==state){var e=Q("uploadFileInput");if(10<e.files.length)displayControl("Limite de 10 uploads de arquivos ao mesmo tempo.");else for(var t=0;t<e.files.length;t++)if(0<e.files[t].size){var n=new FileReader;n.onload=function(e){this.xfile.data=e.target.result,startFileUpload(this.xfile)},n.xfile=e.files[t],n.readAsBinaryString(e.files[t])}}}function fileDrop(e){if(haltEvent(e),2==state&&null!=e.dataTransfer)if(10<e.dataTransfer.files.length)displayControl("Limite de 10 uploads de arquivos ao mesmo tempo.");else for(var t=0;t<e.dataTransfer.files.length;t++)if(0<e.dataTransfer.files[t].size){var n=new FileReader;n.onload=function(e){this.xfile.data=e.target.result,startFileUpload(this.xfile)},n.xfile=e.dataTransfer.files[t],n.readAsBinaryString(e.dataTransfer.files[t])}}function startFileUpload(e){2==state&&(e.id=Math.random(),fileUploads.push(e),QA("xmsg",'<div style="clear:both"></div><div id="FILEUP-'+e.id+'" class="localBubble" style="width:240px;cursor:pointer" onclick="cancelFileTransfer(\''+e.id+'\')"><div id="FILEUP-ICON-'+e.id+'" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-'+e.id+'" style="height:16px;overflow:hidden;white-space:nowrap;" title="'+e.name+'">'+e.name+'</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-'+e.id+'" style="width:0px;background-color:green;border-radius:3px;height:11px">&nbsp;</div></div></div></div>'),Q("xmsg").scrollTop=Q("xmsg").scrollHeight,send({action:"file",size:e.size,id:e.id,type:e.type,name:e.name}),null==currentFileUpload&&continueFileUpload())}function startFileDownload(e){2==state&&(fileDownloads[e.id]=e,QA("xmsg",'<div style="clear:both"></div><div id="FILEUP-'+e.id+'" class="remoteBubble" style="width:240px;cursor:pointer" onclick="saveFileTransfer(\''+e.id+'\')"><div id="FILEUP-ICON-'+e.id+'" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-'+e.id+'" style="height:16px;overflow:hidden;white-space:nowrap;" title="'+e.name+'">'+e.name+'</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-'+e.id+'" style="width:0px;background-color:green;border-radius:3px;height:11px">&nbsp;</div></div></div></div>'),Q("xmsg").scrollTop=Q("xmsg").scrollHeight)}function changeFileInfo(e,t,n,i){t&&(Q("FILEUP-ICON-"+e).classList.remove("fileicon"),Q("FILEUP-ICON-"+e).classList.remove("fileiconx"),Q("FILEUP-ICON-"+e).classList.remove("fileicontransfer"),Q("FILEUP-ICON-"+e).classList.remove("fileicondone"),Q("FILEUP-ICON-"+e).classList.add(["fileicon","fileiconx","fileicontransfer","fileicondone"][t])),n&&(QS("FILEUP-PROGRESS-"+e).width=n+"px"),i&&(QS("FILEUP-PROGRESS-"+e)["background-color"]=i)}function data2blob(e){for(var t=new Array(e.length),n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return new Blob([new Uint8Array(t)])}function saveFileTransfer(e){var t=fileDownloads[e];t&&1==t.done&&saveAs(data2blob(t.data),t.name)}function cancelFileTransfer(e){null!=currentFileUpload&&currentFileUpload.id==e&&(currentFileUpload=null),null!=currentFileDownload&&currentFileDownload.id==e&&(currentFileDownload=null);var t=!1;if(fileDownloads[e]&&1!=fileDownloads[e].done)delete fileDownloads[e],t=!0;else for(var n in fileUploads)if(fileUploads[n].id==e){send({action:"fileUploadCancel",id:e}),fileUploads.splice(n,1),t=!0;break}t&&changeFileInfo(e,1,200,"gray")}function cancelAllFileTransfers(){for(var e in fileDownloads)cancelFileTransfer(fileDownloads[e].id);for(var e in fileUploads)cancelFileTransfer(fileUploads[e].id)}function continueFileUpload(){if(null==currentFileUpload){if(0==fileUploads.length)return;(currentFileUpload=fileUploads[0]).ptr=0,send({action:"fileUploadStart",size:currentFileUpload.size,id:currentFileUpload.id,type:currentFileUpload.type,name:currentFileUpload.name})}else if(currentFileUpload.size<=currentFileUpload.ptr)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();else{var e=Math.min(4e3,currentFileUpload.data.length-currentFileUpload.ptr),t=currentFileUpload.data.substring(currentFileUpload.ptr,currentFileUpload.ptr+e);send({action:"fileData",id:currentFileUpload.id,data:t}),currentFileUpload.ptr+=e,changeFileInfo(currentFileUpload.id,0,200*currentFileUpload.ptr/currentFileUpload.size)}}function continueFileDownload(e){send({action:"fileUploadAck",id:e.id})}function enableNotificationsButtonClick(){return Notification&&Notification.requestPermission().then(function(e){QV("notifyButton","granted"!=e)}),!1}function camButtonClick(){null==localStream&&startLocalStream({video:!0,audio:!0})}function micButtonClick(){null==localStream&&startLocalStream({video:!1,audio:!0})}function hangUpButtonClick(e,t){var n=Q("localVideoCanvas"),i=Q("remoteVideoCanvas"),o=webrtcSessions[1==multiWebRtc?e:0];if(0==e&&null!=webchannel){try{webchannel.close()}catch(e){}webchannel=null}if(o){if(1!=multiWebRtc&&0!=e||(o.ontrack=null,o.onremovetrack=null,o.onremovestream=null,o.onnicecandidate=null,o.oniceconnectionstatechange=null,o.onsignalingstatechange=null,o.onicegatheringstatechange=null,o.onnotificationneeded=null),1==e&&localStream){var a=localStream.getTracks();for(var l in a)a[l].stop();localStream=null}if(2==e&&remoteStream){a=remoteStream.getTracks();for(var l in a)a[l].stop();remoteStream=null}1!=multiWebRtc&&0!=e||(o.close(),delete webrtcSessions[e])}1==e?(n.removeAttribute("src"),n.removeAttribute("srcObject"),null!=localStream&&(localStream=null),displayLocalVideo(!1)):2==e&&(i.removeAttribute("src"),i.removeAttribute("srcObject"),displayRemoteVideo(!1)),1!=t&&send({action:"videoStop",id:e}),updateControls()}function startLocalStream(a){var l=1==multiWebRtc?1:0;null==localStream&&(1==multiWebRtc&&null!=webrtcSessions[1]||navigator.mediaDevices.getUserMedia&&(localStream=1,updateControls(),navigator.mediaDevices.getUserMedia(a).then(function(e){var t=(localStream=e).getTracks(),n=startWebRTC(l);if(1==a.video){var i=Q("localVideoCanvas");i.srcObject=e,i.onloadedmetadata=function(e){i.play()},displayLocalVideo(!0)}for(var o in t)n.addTrack(t[o],localStream)},function(e){displayControl(e.message+"."),hangUpButtonClick(1)})))}function start(){if(updateControls(),"string"==typeof args.id&&0<args.id.length){var e=window.location.protocol.replace("http","ws")+"//"+window.location.host+window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/meshrelay.ashx?id="+args.id;null!=args.auth&&""!=args.auth&&(e+="&auth="+args.auth),(socket=new WebSocket(e)).onopen=function(){state=1,displayControl("Aguardando outro usuário ...")},socket.onerror=function(e){},socket.onclose=function(){disconnect()},socket.onmessage=function(e){if(state<2&&"string"==typeof e.data&&("c"==e.data||"cr"==e.data))return hangUpButtonClick(0,!0),hangUpButtonClick(1,!0),hangUpButtonClick(2,!0),displayControl("Conectado."),state=2,updateControls(),void sendws({action:"random",random:random});2==state&&processMessage(e.data,1)}}else displayControl("Erro: Nenhuma chave de conexão especificada.")}function onUnLoad(){for(var e=0;e<3;e++)webrtcSessions[e]&&(webrtcSessions[e].close(),delete webrtcSessions[e]);if(null!=webchannel){try{webchannel.close()}catch(e){}webchannel=null}if(null!=socket){try{socket.close()}catch(e){}socket=null}}args.title&&(QH("xtitle",args.title.split(" ").join("&nbsp")),document.title=document.title+" - "+args.title),Notification&&QV("notifyButton","granted"!=Notification.permission),document.addEventListener("dragover",haltEvent,!1),document.addEventListener("dragleave",haltEvent,!1),document.addEventListener("drop",fileDrop,!1),document.onclick=function(e){Notification&&QV("notifyButton","granted"!=Notification.permission),null!=notification&&(notification.close(),notification=null)},document.onkeyup=function(e){if(Notification&&QV("notifyButton","granted"!=Notification.permission),null!=notification&&(notification.close(),notification=null),2==state&&8==e.keyCode&&0==userInputFocus){var t=Q("xouttext").value;0<t.length&&(Q("xouttext").value=t.substring(0,t.length-1))}if(0==userInputFocus)return haltEvent(e),!1},document.onkeypress=function(e){if(Notification&&QV("notifyButton","granted"!=Notification.permission),null!=notification&&(notification.close(),notification=null),2==state&&(13==e.keyCode?xsend(e):0==userInputFocus&&1==e.key.length&&(Q("xouttext").value=Q("xouttext").value+e.key)),0==userInputFocus)return haltEvent(e),!1},FileReader.prototype.readAsBinaryString||(FileReader.prototype.readAsBinaryString=function(e){var i="",o=this,a=new FileReader;a.onload=function(e){for(var t=new Uint8Array(a.result),n=0;n<t.byteLength;n++)i+=String.fromCharCode(t[n]);o.onload({target:{result:i}})},a.readAsArrayBuffer(e)}),start()</script>
\ No newline at end of file
views/translations/messenger_pt.handlebars new
+642
@@ -0,0 +1,642 @@
1 +<!DOCTYPE html><html style="height:100%"><head>
2 + <title>MeshMessenger</title>
3 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
4 + <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
5 + <meta name="format-detection" content="telephone=no">
6 + <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
7 + <link type="text/css" href="styles/messenger.css" media="screen" rel="stylesheet" title="CSS">
8 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
9 + <script type="text/javascript" src="scripts/filesaver.js"></script>
10 + </head>
11 + <body style="font-family:Arial,Helvetica,sans-serif">
12 + <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">
13 + <div style="position:absolute;background-color:#036;right:0;height:38px">
14 + <div id="notifyButton" class="icon13 topButton" style="margin-right:4px;display:none" title="Ativar notificação do navegador" onclick="enableNotificationsButtonClick()"></div>
15 + <div id="fileButton" class="icon4 topButton" title="Compartilhar um arquivo" style="display:none" onclick="fileButtonClick()"></div>
16 + <div id="camButton" class="icon2 topButton" title="Ativar câmera e microfone" style="display:none" onclick="camButtonClick()"></div>
17 + <div id="micButton" class="icon6 topButton" title="Ativar microfone" style="display:none" onclick="micButtonClick()"></div>
18 + <div id="hangupButton" class="icon11 topRedButton" title="Desligar" style="display:none" onclick="hangUpButtonClick(1)"></div>
19 + </div>
20 + <div style="padding-top:9px;padding-left:6px;font-size:20px;display:inline-block"><b><span id="xtitle">MeshMessenger</span></b></div>
21 + </div>
22 + <div id="xmiddle" style="position:absolute;left:0;right:0;top:38px;bottom:30px">
23 + <div style="position:absolute;left:0;right:0;top:0;bottom:0;overflow-y:scroll">
24 + <div id="xmsg" style="position:absolute;left:0;right:0;bottom:0;padding:5px"></div>
25 + </div>
26 + </div>
27 + <div id="xbottom" style="position:absolute;left:0;right:0;bottom:0px;height:30px;background-color:#036">
28 + <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>
29 + <input type="button" id="sendButton" value="Enviar" style="position:absolute;right:110px;width:100px;top:4px;" onclick="xsend(event)">
30 + <input type="button" id="clearButton" value="Limpo" style="position:absolute;right:5px;width:100px;top:4px;" onclick="displayClear()">
31 + </div>
32 + <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">
33 + <div style="position:absolute;right:0;left:0;top:2.5px;text-align:center">Remoto</div>
34 + <video id="remoteVideoCanvas" autoplay="" style="position:absolute;top:20px;left:0;width:100%;height:calc(100% - 30px);background-color:black"></video>
35 + </div>
36 + <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">
37 + <div style="position:absolute;right:0;left:0;top:2.5px;text-align:center">Local</div>
38 + <video id="localVideoCanvas" autoplay="" muted="" style="position:absolute;top:20px;left:0;width:100%;height:calc(100% - 30px);background-color:black"></video>
39 + </div>
40 + <input id="uploadFileInput" type="file" multiple="" style="display:none">
41 + <script type="text/javascript" onunload="onUnLoad()">
42 + var userInputFocus = 0;
43 + var args = parseUriArgs();
44 + var socket = null; // Websocket object
45 + var state = 0; // Connection state. 0 = Disconnected, 1 = Connecting, 2 = Connected.
46 +
47 + // WebRTC sessions and data, audio and video channels
48 + var random = Math.random(); // Selected random, larger value initiates WebRTC.
49 + var webrtcSessions = { }; // WebRTC objects: 0 for data, 1 for outbound audio/video, 2 for inbound audio/video
50 + var webchannel = null; // WebRTC data channel
51 + var localStream = null;
52 + var remoteStream = null;
53 + var multiWebRtc = true; // if set to true, multiple WebRTC sessions will be setup. If false, everything uses one session.
54 + var userMediaSupport = 0;
55 + var notification = null;
56 + getUserMediaSupport(function (x) { userMediaSupport = x; })
57 + var webrtcconfiguration = '{{{webrtconfig}}}';
58 + if (webrtcconfiguration == '') { webrtcconfiguration = null; } else { try { webrtcconfiguration = JSON.parse(decodeURIComponent(webrtcconfiguration)); } catch (ex) { console.log('Invalid WebRTC config: \"' + webrtcconfiguration + '\".'); webrtcconfiguration = null; } }
59 +
60 + // File transfer state
61 + var fileUploads = [];
62 + var fileDownloads = {};
63 + var currentFileUpload = null;
64 + var currentFileDownload = null;
65 +
66 + // Set the title
67 + if (args.title) { QH('xtitle', args.title.split(' ').join('&nbsp')); document.title = document.title + ' - ' + args.title; }
68 +
69 + // Setup web notifications
70 + if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
71 +
72 + // Listen to drag & drop events
73 + document.addEventListener('dragover', haltEvent, false);
74 + document.addEventListener('dragleave', haltEvent, false);
75 + document.addEventListener('drop', fileDrop, false);
76 +
77 + document.onclick = function (e) {
78 + if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
79 + if (notification != null) { notification.close(); notification = null; }
80 + }
81 +
82 + // Trap document key up events
83 + document.onkeyup = function ondockeypress(e) {
84 + if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
85 + if (notification != null) { notification.close(); notification = null; }
86 + if (state == 2) {
87 + if ((e.keyCode == 8) && (userInputFocus == 0)) {
88 + // Backspace
89 + var outtext = Q('xouttext').value;
90 + if (outtext.length > 0) { Q('xouttext').value = outtext.substring(0, outtext.length - 1); }
91 + }
92 + }
93 + if (userInputFocus == 0) { haltEvent(e); return false; }
94 + }
95 +
96 + // Trap document key presses
97 + document.onkeypress = function ondockeypress(e) {
98 + if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
99 + if (notification != null) { notification.close(); notification = null; }
100 + if (state == 2) {
101 + if (e.keyCode == 13) {
102 + // Return
103 + xsend(e);
104 + } else {
105 + // Any other key
106 + if ((userInputFocus == 0) && (e.key.length == 1)) { Q('xouttext').value = Q('xouttext').value + e.key; }
107 + }
108 + }
109 + if (userInputFocus == 0) { haltEvent(e); return false; }
110 + }
111 +
112 + function onUserInputFocus(x) { userInputFocus = x; }
113 + function displayClear() { QH('xmsg', ''); cancelAllFileTransfers(); fileUploads = [], fileDownloads = {}; }
114 +
115 + // Polyfill FileReader if needed
116 + if (!FileReader.prototype.readAsBinaryString) {
117 + FileReader.prototype.readAsBinaryString = function (fileData) {
118 + var binary = '', self = this, reader = new FileReader();
119 + reader.onload = function (e) {
120 + var bytes = new Uint8Array(reader.result);
121 + for (var i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); }
122 + self.onload({ target: { result: binary } });
123 + }
124 + reader.readAsArrayBuffer(fileData);
125 + }
126 + }
127 +
128 + // Detect if microphone & camera are present
129 + // 0 = nomedia, 1 = miconly, 2 = mic&cam
130 + function getUserMediaSupport(func) {
131 + try {
132 + navigator.mediaDevices.enumerateDevices().then(function (devices) {
133 + try {
134 + var mic = 0, cam = 0;
135 + devices.forEach(function (device) {
136 + if (device.kind === 'audioinput') { mic = 1; }
137 + if (device.kind === 'videoinput') { cam = 1; }
138 + });
139 + if (mic == 0) { func(0); }
140 + func(mic + cam);
141 + } catch (ex) { }
142 + })
143 + } catch (ex) { }
144 + }
145 +
146 + // Display a control message
147 + function displayControl(msg) {
148 + QA('xmsg', '<div style="clear:both"><div style="color:gray;float:left;margin-bottom:2px">' + msg + '</div><div></div></div>');
149 + Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
150 + }
151 +
152 + function displayLocalVideo(active) { QV('localVideo', active); adjustVideoWindows(); }
153 + function displayRemoteVideo(active) { QV('remoteVideo', active); adjustVideoWindows(); }
154 + function adjustVideoWindows() {
155 + //var lv = (QS('localVideo')['display'] != 'none');
156 + var rv = (QS('remoteVideo')['display'] != 'none');
157 + QS('localVideo')['top'] = rv ? '320px' : '45px';
158 + }
159 +
160 + // Display a message from the remote user
161 + function displayRemote(msg) {
162 + QA('xmsg', '<div style="clear:both"><div class="remoteBubble">' + msg + '</div><div></div></div>');
163 + Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
164 +
165 + // If web notifications are granted, use it.
166 + if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
167 + if (Notification && (Notification.permission == 'granted')) {
168 + if (notification != null) { notification.close(); notification = null; }
169 + if (args.title) {
170 + notification = new Notification("MeshMessenger" + ' - ' + args.title, { body: msg });
171 + } else {
172 + notification = new Notification("MeshMessenger", { body: msg });
173 + }
174 + }
175 + }
176 +
177 + // Display and send a message from the local user
178 + function xsend(event) {
179 + if (notification != null) { notification.close(); notification = null; }
180 + if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
181 + var outtext = Q('xouttext').value;
182 + if (outtext.length > 0) {
183 + Q('xouttext').value = '';
184 + QA('xmsg', '<div style="clear:both"><div class="localBubble">' + outtext + '</div><div></div></div>');
185 + Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
186 + send({ action: 'chat', msg: outtext });
187 + }
188 + }
189 +
190 + function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
191 + 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; }
192 +
193 + // Update user controls
194 + function updateControls() {
195 + QE('sendButton', state == 2);
196 + QE('clearButton', state == 2);
197 + QE('xouttext', state == 2);
198 + QV('fileButton', state == 2);
199 + QV('camButton', webchannel && webchannel.ok && !localStream && (userMediaSupport == 2));
200 + QV('micButton', webchannel && webchannel.ok && !localStream && (userMediaSupport > 0));
201 + QV('hangupButton', webchannel && webchannel.ok && localStream);
202 + }
203 +
204 + // This is the WebRTC setup
205 + function startWebRTC(id, startDataChannel) {
206 + if ((webrtcSessions[0] != null) && (multiWebRtc == false)) { return webrtcSessions[0]; };
207 +
208 + // Setup the WebRTC object
209 + var webrtc = null;
210 + if (typeof RTCPeerConnection !== 'undefined') { webrtc = new RTCPeerConnection(webrtcconfiguration); }
211 + else if (typeof webkitRTCPeerConnection !== 'undefined') { webrtc = new webkitRTCPeerConnection(webrtcconfiguration); }
212 + if (webrtc == null) return null; // No WebRTC support.
213 +
214 + webrtc.id = id;
215 + webrtc.onicecandidate = function (e) { try { if (e.candidate != null) { sendws({ action: 'webRtcIce', ice: e.candidate, id: this.id }); } } catch (ex) { } }
216 + webrtc.oniceconnectionstatechange = function () { if (webrtc && webrtc.iceConnectionState == 'failed') { webrtc.close(); if (webrtcSessions[webrtc.id]) { delete webrtcSessions[webrtc.id]; } } }
217 + webrtc.ondatachannel = function (ev) {
218 + //console.log('ondatachannel');
219 + webchannel = ev.channel;
220 + webchannel.onmessage = function (event) { processMessage(event.data, 2); };
221 + webchannel.onopen = function () { webchannel.ok = true; updateControls(); sendws({ action: 'rtcSwitch', v: 0 }); };
222 + webchannel.onclose = function (event) { if (webchannel && webchannel.ok) { disconnect(); } else { hangUpButtonClick(0); } }
223 + }
224 + webrtc.onnegotiationneeded = function (event) {
225 + if (webrtc.holdTimer != null) return;
226 + 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.
227 + //console.log('onnegotiationneeded', id);
228 + webrtc.holdTimer = null;
229 + 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); });
230 + }, 20);
231 + }
232 + webrtc.ontrack = function (event) {
233 + //console.log('ontrack', id);
234 + var video = Q('remoteVideoCanvas');
235 + video.srcObject = remoteStream = event.streams[0];
236 + video.onloadedmetadata = function (e) { video.play(); };
237 + displayRemoteVideo(true);
238 + }
239 + //webrtc.onremovetrack = function (event) { console.log('onremovetrack'); }
240 + //webrtc.onicegatheringstatechange = function (event) { console.log('onicegatheringstatechange', event); }
241 + //webrtc.onsignalingstatechange = function (event) { console.log('onsignalingstatechange', event); }
242 +
243 + // Initiate the WebRTC offer or handle the offer from the peer.
244 + if (startDataChannel == true) {
245 + webchannel = webrtc.createDataChannel('DataChannel', {}); // { ordered: false, maxRetransmits: 2 }
246 + webchannel.onmessage = function (event) { processMessage(event.data, 2); };
247 + webchannel.onopen = function () { webchannel.ok = true; updateControls(); sendws({ action: 'rtcSwitch', v: 0 }); };
248 + webchannel.onclose = function (event) { if (webchannel && webchannel.ok) { disconnect(); } else { hangUpButtonClick(0); } }
249 + }
250 +
251 + webrtcSessions[id] = webrtc;
252 + return webrtc;
253 + }
254 +
255 + function webRtcHandleOffer(id, description) {
256 + //console.log('webRtcHandleOffer', description.sdp.length);
257 + var webrtc = webrtcSessions[id];
258 + if (webrtc) {
259 + webrtc.setRemoteDescription(new RTCSessionDescription(description), function () {
260 + if (description.type == 'offer') {
261 + webrtc.createAnswer(function (answer) {
262 + webrtc.setLocalDescription(answer, function (a, b) {
263 + try { sendws({ action: 'webRtcSdp', sdp: answer, id: id }); } catch (ex) { }
264 + }, function () { hangUpButtonClick(id); });
265 + }, function () { hangUpButtonClick(id); });
266 + }
267 + }, function () { hangUpButtonClick(id); });
268 + }
269 + }
270 +
271 + // Indicate to peer that data traffic will no longer be sent over websocket and start holding traffic.
272 + function performWebRtcSwitch() {
273 + if (webchannel && webchannel.ok) { sendws({ action: 'rtcSwitch', v: 1 }); webchannel.xoutBuffer = []; }
274 + }
275 +
276 + // Disconnect everything
277 + function disconnect() {
278 + if (state > 0) { displayControl("Conexão fechada."); }
279 + if (state > 1) { setTimeout(start, 500); }
280 + cancelAllFileTransfers();
281 + hangUpButtonClick(0, true); // Data channel
282 + hangUpButtonClick(1, true); // Local audio/video
283 + hangUpButtonClick(2, true); // Remote audio/video
284 + if (socket != null) { socket.close(); socket = null; }
285 + updateControls();
286 + state = 0;
287 + }
288 +
289 + // Send data over the current transport (WebRTC first)
290 + function send(data) {
291 + if (state != 2) return; // If not in connected state, ignore this.
292 + if (typeof data == 'object') { data = JSON.stringify(data); } // If this is an object, convert it to a string.
293 + 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.
294 + else { if (socket != null) { try { socket.send(data); } catch (ex) { } } } // If a websocket channel is present, use that.
295 + }
296 +
297 + // Send data over the websocket transport (WebSocket only)
298 + function sendws(data) {
299 + if (state != 2) return;
300 + //console.log('SEND', data);
301 + if (typeof data == 'object') { data = JSON.stringify(data); }
302 + if (socket != null) { socket.send(data); }
303 + }
304 +
305 + // WebRTC id switcher (0 -> 0, 1 -> 2, 2 -> 1)
306 + function webRtcIdSwitch(id) { if (id == 0) { return 0; } return 3 - id; }
307 +
308 + // Process incoming messages
309 + function processMessage(data, transport) {
310 + if (typeof data == 'string') {
311 + try { data = JSON.parse(data); } catch (ex) { console.log('Unable to parse', data); return; }
312 + //console.log('RECV', data);
313 + switch (data.action) {
314 + case 'chat': { displayRemote(data.msg); break; } // Incoming chat message.
315 + case 'random': { if (random > data.random) { startWebRTC(0, true); } break; } // If we have a larger random value, we start WebRTC.
316 + case 'webRtcSdp': { if (!webrtcSessions[webRtcIdSwitch(data.id)]) { startWebRTC(webRtcIdSwitch(data.id), false); } webRtcHandleOffer(webRtcIdSwitch(data.id), data.sdp); break; } // Remote WebRTC offer or answer.
317 + case 'webRtcIce': { var webrtc = webrtcSessions[webRtcIdSwitch(data.id)]; if (webrtc) { try { webrtc.addIceCandidate(new RTCIceCandidate(data.ice)); } catch (ex) { } } break; } // Remote ICE candidate
318 + case 'videoStop': { hangUpButtonClick(webRtcIdSwitch(data.id), true); break; }
319 + case 'rtcSwitch': { // WebRTC switch over commands.
320 + switch (data.v) {
321 + case 0: { performWebRtcSwitch(); break; } // Other side is ready for switch over to WebRTC
322 + case 1: { sendws({ action: 'rtcSwitch', v: 2 }); break; } // Other side no longer sending data on websocket, confirm we got the end marker
323 + 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
324 + default: { console.log('Unknown rtcSwitch value: ' + data.action); break; } //
325 + }
326 + break;
327 + }
328 + case 'file': { startFileDownload(data); break; }
329 + case 'fileUploadCancel': { cancelFileTransfer(data.id); break; }
330 + case 'fileUploadStart': {
331 + if (fileDownloads[data.id]) {
332 + currentFileDownload = fileDownloads[data.id];
333 + currentFileDownload.data = '';
334 + changeFileInfo(data.id, 2, 0);
335 + continueFileDownload(data);
336 + send({ action: 'fileUploadAck', id: data.id });
337 + } break;
338 + }
339 + case 'fileUploadEnd': {
340 + if (currentFileDownload && (currentFileDownload.id == data.id)) {
341 + changeFileInfo(data.id, 3, 200);
342 + currentFileDownload.done = 1;
343 + currentFileDownload = null;
344 + send({ action: 'fileUploadAck', id: data.id });
345 + }
346 + currentFileDownload = null;
347 + break;
348 + }
349 + case 'fileUploadAck': {
350 + continueFileUpload();
351 + break;
352 + }
353 + case 'fileData': {
354 + if (currentFileDownload && (currentFileDownload.id == data.id)) {
355 + currentFileDownload.data += data.data;
356 + changeFileInfo(data.id, 2, (currentFileDownload.data.length * 200 / currentFileDownload.size));
357 + send({ action: 'fileUploadAck', id: data.id });
358 + }
359 + break;
360 + }
361 + default: { console.log('Unhandled object data', data); break; }
362 + }
363 + } else {
364 + console.log('Unhandled data', typeof data, data);
365 + }
366 + }
367 +
368 + // File sharing button
369 + function fileButtonClick() {
370 + var chooser = Q('uploadFileInput');
371 + if (chooser.getAttribute('eventset') != 1) {
372 + chooser.setAttribute('eventset', '1');
373 + chooser.addEventListener('change', fileSelect, false);
374 + }
375 + chooser.value = null;
376 + chooser.click();
377 + }
378 +
379 + // User selected one or more files to upload to remote user.
380 + function fileSelect() {
381 + if (state != 2) return;
382 + var x = Q('uploadFileInput');
383 + if (x.files.length > 10) {
384 + displayControl("Limite de 10 uploads de arquivos ao mesmo tempo.");
385 + } else {
386 + for (var i = 0; i < x.files.length; i++) {
387 + if (x.files[i].size > 0) {
388 + var reader = new FileReader();
389 + reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
390 + reader.xfile = x.files[i];
391 + reader.readAsBinaryString(x.files[i]);
392 + }
393 + }
394 + }
395 + }
396 +
397 + // User drag & droped one or more files to upload to remote user.
398 + function fileDrop(e) {
399 + haltEvent(e);
400 + if ((state != 2) || (e.dataTransfer == null)) return;
401 + if (e.dataTransfer.files.length > 10) {
402 + displayControl("Limite de 10 uploads de arquivos ao mesmo tempo.");
403 + } else {
404 + for (var i = 0; i < e.dataTransfer.files.length; i++) {
405 + if (e.dataTransfer.files[i].size > 0) {
406 + var reader = new FileReader();
407 + reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
408 + reader.xfile = e.dataTransfer.files[i];
409 + reader.readAsBinaryString(e.dataTransfer.files[i]);
410 + }
411 + }
412 + }
413 + }
414 +
415 + function startFileUpload(file) {
416 + if (state != 2) return;
417 + file.id = Math.random();
418 + fileUploads.push(file);
419 + 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">&nbsp;</div></div></div></div>');
420 + Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
421 + send({ action: 'file', size: file.size, id: file.id, type: file.type, name: file.name });
422 + if (currentFileUpload == null) continueFileUpload();
423 + }
424 +
425 + function startFileDownload(file) {
426 + if (state != 2) return;
427 + fileDownloads[file.id] = file;
428 + 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">&nbsp;</div></div></div></div>');
429 + Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
430 + }
431 +
432 + // Change the file icon and progress
433 + function changeFileInfo(id, icon, progress, progressColor) {
434 + if (icon) {
435 + Q('FILEUP-ICON-' + id).classList.remove('fileicon');
436 + Q('FILEUP-ICON-' + id).classList.remove('fileiconx');
437 + Q('FILEUP-ICON-' + id).classList.remove('fileicontransfer');
438 + Q('FILEUP-ICON-' + id).classList.remove('fileicondone');
439 + Q('FILEUP-ICON-' + id).classList.add(['fileicon', 'fileiconx', 'fileicontransfer', 'fileicondone'][icon]);
440 + }
441 + if (progress) { QS('FILEUP-PROGRESS-' + id)['width'] = progress + 'px'; }
442 + if (progressColor) { QS('FILEUP-PROGRESS-' + id)['background-color'] = progressColor; }
443 + }
444 +
445 + // Convert a string into a blob
446 + function data2blob(data) {
447 + var bytes = new Array(data.length);
448 + for (var i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i);
449 + return new Blob([new Uint8Array(bytes)]);
450 + };
451 +
452 + function saveFileTransfer(id) {
453 + var f = fileDownloads[id];
454 + if (f && f.done == 1) { saveAs(data2blob(f.data), f.name); }
455 + }
456 +
457 + function cancelFileTransfer(id) {
458 + if ((currentFileUpload != null) && (currentFileUpload.id == id)) { currentFileUpload = null; }
459 + if ((currentFileDownload != null) && (currentFileDownload.id == id)) { currentFileDownload = null; }
460 +
461 + var found = false;
462 + if (fileDownloads[id] && (fileDownloads[id].done != 1)) {
463 + delete fileDownloads[id];
464 + found = true;
465 + } else {
466 + for (var i in fileUploads) {
467 + if (fileUploads[i].id == id) {
468 + send({ action: 'fileUploadCancel', id: id });
469 + fileUploads.splice(i, 1);
470 + found = true;
471 + break;
472 + }
473 + }
474 + }
475 + if (found) { changeFileInfo(id, 1, 200, 'gray'); } // Only cancel a file if it was in the file queue.
476 + }
477 +
478 + function cancelAllFileTransfers() {
479 + for (var i in fileDownloads) { cancelFileTransfer(fileDownloads[i].id); }
480 + for (var i in fileUploads) { cancelFileTransfer(fileUploads[i].id); }
481 + }
482 +
483 + function continueFileUpload() {
484 + if (currentFileUpload == null) {
485 + // Select the next file to upload
486 + if (fileUploads.length == 0) { return; } // Nothing to do
487 + currentFileUpload = fileUploads[0];
488 + currentFileUpload.ptr = 0;
489 +
490 + // Indicate that we are sending this file
491 + send({ action: 'fileUploadStart', size: currentFileUpload.size, id: currentFileUpload.id, type: currentFileUpload.type, name: currentFileUpload.name });
492 + } else {
493 + if (currentFileUpload.size <= currentFileUpload.ptr) {
494 + // If we are done, send the end marker
495 + send({ action: 'fileUploadEnd', size: currentFileUpload.size, id: currentFileUpload.id, type: currentFileUpload.type, name: currentFileUpload.name });
496 + changeFileInfo(currentFileUpload.id, 3, 200);
497 + fileUploads.splice(0, 1);
498 + currentFileUpload = null;
499 + continueFileUpload(); // Send the next file
500 + } else {
501 + // Send the next block
502 + var nextBlockLen = Math.min(4000, currentFileUpload.data.length - currentFileUpload.ptr);
503 + var data = currentFileUpload.data.substring(currentFileUpload.ptr, currentFileUpload.ptr + nextBlockLen);
504 + send({ action: 'fileData', id: currentFileUpload.id, data: data });
505 + currentFileUpload.ptr += nextBlockLen;
506 + changeFileInfo(currentFileUpload.id, 0, (currentFileUpload.ptr * 200 / currentFileUpload.size));
507 + }
508 + }
509 + }
510 +
511 + function continueFileDownload(msg) {
512 + send({ action: 'fileUploadAck', id: msg.id });
513 + }
514 +
515 + // Toggle notification
516 + function enableNotificationsButtonClick() {
517 + if (Notification) { Notification.requestPermission().then(function (permission) { QV('notifyButton', permission != 'granted'); }); }
518 + return false;
519 + }
520 +
521 + // Camera button
522 + function camButtonClick() {
523 + if (localStream == null) { startLocalStream({ video: true, audio: true }); }
524 + }
525 +
526 + // Microphone
527 + function micButtonClick() {
528 + if (localStream == null) { startLocalStream({ video: false, audio: true }); }
529 + }
530 +
531 + function hangUpButtonClick(id, fromRemote) {
532 + //console.log('hangUpButtonClick', id);
533 + var localVideo = Q('localVideoCanvas');
534 + var remoteVideo = Q('remoteVideoCanvas');
535 + var webrtc = webrtcSessions[(multiWebRtc == true)? id : 0];
536 +
537 + if ((id == 0) && (webchannel != null)) { try { webchannel.close(); } catch (e) { } webchannel = null; }
538 +
539 + if (webrtc) {
540 + if ((multiWebRtc == true) || (id == 0)) {
541 + webrtc.ontrack = null;
542 + webrtc.onremovetrack = null;
543 + webrtc.onremovestream = null;
544 + webrtc.onnicecandidate = null;
545 + webrtc.oniceconnectionstatechange = null;
546 + webrtc.onsignalingstatechange = null;
547 + webrtc.onicegatheringstatechange = null;
548 + webrtc.onnotificationneeded = null;
549 + }
550 +
551 + if ((id == 1) && localStream) { var tracks = localStream.getTracks(); for (var i in tracks) { tracks[i].stop(); } localStream = null; }
552 + if ((id == 2) && remoteStream) { var tracks = remoteStream.getTracks(); for (var i in tracks) { tracks[i].stop(); } remoteStream = null; }
553 +
554 + if ((multiWebRtc == true) || (id == 0)) {
555 + webrtc.close();
556 + delete webrtcSessions[id];
557 + }
558 + }
559 +
560 + if (id == 1) {
561 + localVideo.removeAttribute('src');
562 + localVideo.removeAttribute('srcObject');
563 + if (localStream != null) { localStream = null; }
564 + displayLocalVideo(false);
565 + } else if (id == 2) {
566 + remoteVideo.removeAttribute('src');
567 + remoteVideo.removeAttribute('srcObject');
568 + displayRemoteVideo(false);
569 + }
570 +
571 + if (fromRemote != true) { send({ action: 'videoStop', id: id }); }
572 + updateControls();
573 + }
574 +
575 + // Setup local audio/video
576 + function startLocalStream(constraints) {
577 + var channel = (multiWebRtc == true) ? 1 : 0;
578 + if (localStream != null) return;
579 + if ((multiWebRtc == true) && (webrtcSessions[1] != null)) return;
580 + if (navigator.mediaDevices.getUserMedia) {
581 + localStream = 1;
582 + updateControls();
583 + navigator.mediaDevices.getUserMedia(constraints)
584 + .then(function (stream) {
585 + localStream = stream;
586 + var tracks = localStream.getTracks();
587 + var webrtc = startWebRTC(channel);
588 + if (constraints.video == true) {
589 + var video = Q('localVideoCanvas');
590 + video.srcObject = stream;
591 + video.onloadedmetadata = function (e) { video.play(); };
592 + displayLocalVideo(true);
593 + }
594 + for (var i in tracks) { webrtc.addTrack(tracks[i], localStream); }
595 + }, function (err) {
596 + displayControl(err.message + '.');
597 + hangUpButtonClick(1);
598 + });
599 + }
600 + }
601 +
602 + // This is the main start
603 + function start() {
604 + // Get started
605 + updateControls();
606 + if ((typeof args.id == 'string') && (args.id.length > 0)) {
607 + 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;
608 + if ((args.auth != null) && (args.auth != '')) { url += '&auth=' + args.auth; }
609 + socket = new WebSocket(url);
610 + socket.onopen = function () { state = 1; displayControl("Aguardando outro usuário ..."); }
611 + socket.onerror = function (e) { /*console.error(e);*/ }
612 + socket.onclose = function () { disconnect(); }
613 + socket.onmessage = function (msg) {
614 + if ((state < 2) && (typeof msg.data == 'string') && ((msg.data == 'c') || (msg.data == 'cr'))) {
615 + hangUpButtonClick(0, true);
616 + hangUpButtonClick(1, true);
617 + hangUpButtonClick(2, true);
618 + displayControl("Conectado.");
619 + state = 2;
620 + updateControls();
621 + sendws({ action: 'random', random: random }); // Send a random number. Higher number starts the WebRTC session.
622 + return;
623 + }
624 + if (state == 2) { processMessage(msg.data, 1); }
625 + }
626 + } else {
627 + displayControl("Erro: Nenhuma chave de conexão especificada.");
628 + }
629 + }
630 +
631 + start();
632 +
633 + function onUnLoad() {
634 + for (var i = 0; i < 3; i++) { if (webrtcSessions[i]) { webrtcSessions[i].close(); delete webrtcSessions[i]; } }
635 + if (webchannel != null) { try { webchannel.close(); } catch (e) { } webchannel = null; }
636 + if (socket != null) { try { socket.close(); } catch (e) { } socket = null; }
637 + }
638 +
639 + </script>
640 +
641 +
642 +</body></html>
\ No newline at end of file
views/translations/terms-min_pt.handlebars new
+84
@@ -0,0 +1,84 @@
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 - Terms of use</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><p id=logoutControl style="color:#fff;font-size:11px;margin:10px 10px 0"></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.<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 class=MsoNormal><b><span>1.AJAX Control Toolkit - Nova licença BSD</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados.<o:p></o:p></span><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 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 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 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 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 class=MsoNormal><b><span>2.OpenSSL - Licença OpenSSL e SSLeay</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=http://www.openssl.org/source/license.html>http://www.openssl.org/source/license.html</a></span><p class=MsoNormal><span>Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados.<o:p></o:p></span><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 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 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 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 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 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 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 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 class=MsoNormal><b><span>3.jQuery Foundation - Licença MIT</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation e outros colaboradores <a href=http://jquery.com/ >http://jquery.com/</a></span><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 class=MsoNormal><b><span>4.Interface do Usuário jQuery - Licença MIT</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation e outros colaboradores, <a href=http://jqueryui.com/ >http://jqueryui.com/</a></span><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 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 class=MsoNormal><b><span>5.noVNC - Licença Pública Mozilla 2.0 0</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><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 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 class=MsoNormal><b><span>6.Rcarousel - License MIT</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><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 class=MsoNormal><span>Copyright (c) 2010 Wojciech 'RRH' Ryrych<o:p></o:p></span><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 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 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%><tr><td style=text-align:left><td style=text-align:right><a href=/ >Voltar</a></table></div></div><script>'use strict';
2 + var uiMode = parseInt(getstore('uiMode', 1));
3 + var webPageStackMenu = false;
4 + var webPageFullScreen = true;
5 + var nightMode = (getstore('_nightMode', '0') == '1');
6 + var logoutControls = {{{logoutControls}}};
7 +
8 + var terms = '{{{terms}}}';
9 + if (terms != '') { QH('column_l', decodeURIComponent(terms)); }
10 + QV('column_l', true);
11 + userInterfaceSelectMenu();
12 +
13 + // Setup logout control
14 + var logoutControl = '';
15 + if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); }
16 + if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Sair" + '</a>'); }
17 + QH('logoutControl', logoutControl);
18 +
19 + // Toggle user interface menu
20 + function showUserInterfaceSelectMenu() {
21 + Q('uiViewButton1').classList.remove('uiSelectorSel');
22 + Q('uiViewButton2').classList.remove('uiSelectorSel');
23 + Q('uiViewButton3').classList.remove('uiSelectorSel');
24 + Q('uiViewButton4').classList.remove('uiSelectorSel');
25 + try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
26 + QV('uiMenu', (QS('uiMenu').display == 'none'));
27 + if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
28 + }
29 +
30 + function userInterfaceSelectMenu(s) {
31 + if (s) { uiMode = s; putstore('uiMode', uiMode); }
32 + webPageFullScreen = (uiMode < 3);
33 + webPageStackMenu = true;//(uiMode > 1);
34 + toggleFullScreen(0);
35 + toggleStackMenu(0);
36 + QC('column_l').add('room4submenu');
37 + }
38 +
39 + function toggleNightMode() {
40 + nightMode = !nightMode;
41 + if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
42 + putstore('_nightMode', nightMode ? '1' : '0');
43 + }
44 +
45 + // Toggle the web page to full screen
46 + function toggleFullScreen(toggle) {
47 + if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
48 + var hide = 0;
49 + //if (args.hide) { hide = parseInt(args.hide); }
50 + if (webPageFullScreen == false) {
51 + QC('body').remove('menu_stack');
52 + QC('body').remove('fullscreen');
53 + QC('body').remove('arg_hide');
54 + //if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
55 + //QV('UserDummyMenuSpan', false);
56 + //QV('page_leftbar', false);
57 + } else {
58 + QC('body').add('fullscreen');
59 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
60 + //QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
61 + //QV('page_leftbar', true);
62 + }
63 + QV('body', true);
64 + }
65 +
66 + // If FullScreen, toggle menu to be horisontal or vertical
67 + function toggleStackMenu(toggle) {
68 + if (webPageFullScreen == true) {
69 + if (toggle === 1) {
70 + webPageStackMenu = !webPageStackMenu;
71 + putstore('webPageStackMenu', webPageStackMenu);
72 + }
73 + if (webPageStackMenu == false) {
74 + QC('body').remove('menu_stack');
75 + } else {
76 + QC('body').add('menu_stack');
77 + //if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
78 + }
79 + }
80 + }
81 +
82 + function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
83 + 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; } }
84 + 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>
\ No newline at end of file
views/translations/terms-mobile-min_pt.handlebars new
+1
@@ -0,0 +1 @@
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 - 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><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><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.<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 class=MsoNormal><b><span>1.AJAX Control Toolkit - Nova licença BSD</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados.<o:p></o:p></span><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 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 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 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 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 class=MsoNormal><b><span>2.OpenSSL - Licença OpenSSL e SSLeay</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span><a href=http://www.openssl.org/source/license.html>http://www.openssl.org/source/license.html</a></span><p class=MsoNormal><span>Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados.<o:p></o:p></span><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 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 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 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 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 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 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 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 class=MsoNormal><b><span>3.jQuery Foundation - Licença MIT</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation e outros colaboradores <a href=http://jquery.com/ >http://jquery.com/</a></span><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 class=MsoNormal><b><span>4.Interface do Usuário jQuery - Licença MIT</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><p class=MsoNormal><span>Copyright 2013 jQuery Foundation e outros colaboradores, <a href=http://jqueryui.com/ >http://jqueryui.com/</a></span><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 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 class=MsoNormal><b><span>5.noVNC - Licença Pública Mozilla 2.0 0</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><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 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 class=MsoNormal><b><span>6.Rcarousel - License MIT</span></b><span style=font-size:10pt;font-family:&quot><o:p></o:p></span><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 class=MsoNormal><span>Copyright (c) 2010 Wojciech 'RRH' Ryrych<o:p></o:p></span><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 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 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:0><table cellpadding=0 cellspacing=6 style=width:100%><tr><td style=text-align:left;color:#fff>{{{footer}}}<td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href=/ >Voltar</a></table></div></div>
\ No newline at end of file
views/translations/terms-mobile_pt.handlebars new
+160
@@ -0,0 +1,160 @@
1 +<!DOCTYPE html><html><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <title>MeshCentral - Terms of use</title>
8 + <style type="text/css">
9 + a {
10 + color: #036;
11 + text-decoration: underline;
12 + }
13 +
14 + #footer a {
15 + color: #fff;
16 + text-decoration: underline;
17 + }
18 +
19 + #footer a:hover {
20 + color: #fff;
21 + text-decoration: none;
22 + }
23 + </style>
24 +</head>
25 +<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">
26 + <div id="container">
27 + <!-- Begin Masthead -->
28 + <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">
29 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px">
30 + <strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
31 + </div>
32 + <div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px">
33 + <strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
34 + </div>
35 + </div>
36 + <div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px">
37 + <div id="column_l" style="padding-left:10px;padding-right:10px">
38 + <h1>Termos de uso</h1>
39 + <p>Entre em contato com o administrador do site para obter os termos de uso.</p>
40 + <hr>
41 + <p class="MsoNormal">
42 + A seguir, são apresentadas as divulgações necessárias de componentes e software de código aberto incorporados neste software.
43 + </p>
44 + <p class="MsoNormal">
45 + <b><span>1.AJAX Control Toolkit - Nova licença BSD</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
46 + </p>
47 + <p class="MsoNormal">
48 + <span>Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados.<o:p></o:p></span>
49 + </p>
50 + <p class="MsoNormal">
51 + <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>
52 + </p>
53 + <p class="MsoNormal">
54 + <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>
55 + </p>
56 + <p class="MsoNormal">
57 + <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>
58 + </p>
59 + <p class="MsoNormal">
60 + <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>
61 + </p>
62 + <p class="MsoNormal">
63 + <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>
64 + </p>
65 + <p class="MsoNormal">
66 + <b><span>2.OpenSSL - Licença OpenSSL e SSLeay</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
67 + </p>
68 + <p class="MsoNormal">
69 + <span><a href="http://www.openssl.org/source/license.html">http://www.openssl.org/source/license.html</a> </span>
70 + </p>
71 + <p class="MsoNormal">
72 + <span>Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados.<o:p></o:p></span>
73 + </p>
74 + <p class="MsoNormal">
75 + <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>
76 + </p>
77 + <p class="MsoNormal">
78 + <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>
79 + </p>
80 + <p class="MsoNormal">
81 + <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>
82 + </p>
83 + <p class="MsoNormal">
84 + <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>
85 + </p>
86 + <p class="MsoNormal">
87 + <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>
88 + </p>
89 + <p class="MsoNormal">
90 + <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>
91 + </p>
92 + <p class="MsoNormal">
93 + <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>
94 + </p>
95 + <p class="MsoNormal">
96 + <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>
97 + </p>
98 + <p class="MsoNormal">
99 + <b><span>3.jQuery Foundation - Licença MIT</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
100 + </p>
101 + <p class="MsoNormal">
102 + <span>Copyright 2013 jQuery Foundation e outros colaboradores <a href="http://jquery.com/">http://jquery.com/</a></span>
103 + </p>
104 + <p class="MsoNormal">
105 + <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>
106 + </p>
107 + <p class="MsoNormal">
108 + <b><span>4.Interface do Usuário jQuery - Licença MIT</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
109 + </p>
110 + <p class="MsoNormal">
111 + <span>Copyright 2013 jQuery Foundation e outros colaboradores, <a href="http://jqueryui.com/">http://jqueryui.com/</a></span>
112 + </p>
113 + <p class="MsoNormal">
114 + <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>
115 + </p>
116 + <p class="MsoNormal">
117 + <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>
118 + </p>
119 + <p class="MsoNormal">
120 + <b><span>5.noVNC - Licença Pública Mozilla 2.0 0</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
121 + </p>
122 + <p class="MsoNormal">
123 + <span><a href="https://github.com/kanaka/noVNC/blob/master/LICENSE.txt">https://github.com/kanaka/noVNC/blob/master/LICENSE.txt</a></span>
124 + </p>
125 + <p class="MsoNormal">
126 + <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>
127 + </p>
128 + <p class="MsoNormal">
129 + <b><span>6.Rcarousel - License MIT</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
130 + </p>
131 + <p class="MsoNormal">
132 + <span><a href="https://github.com/ryrych/rcarousel/blob/master/widget/license">https://github.com/ryrych/rcarousel/blob/master/widget/license</a></span>
133 + </p>
134 + <p class="MsoNormal">
135 + <span>Copyright (c) 2010 Wojciech 'RRH' Ryrych<o:p></o:p></span>
136 + </p>
137 + <p class="MsoNormal">
138 + <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>
139 + </p>
140 + <p class="MsoNormal">
141 + <b><span>7.Webtoolkit Javascript Base 64 - Licença Creative Commons Attribution 2.0 UK</span></b><span><o:p></o:p></span>
142 + </p>
143 + <p class="MsoNormal">
144 + <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>
145 + </p>
146 + <br>
147 + </div>
148 + </div>
149 + <div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
150 + <table cellpadding="0" cellspacing="6" style="width:100%">
151 + <tbody><tr>
152 + <td style="text-align:left;color:white">{{{footer}}}</td>
153 + <td style="text-align:right">{{{rootCertLink}}}&nbsp;<a href="/">Voltar</a></td>
154 + </tr>
155 + </tbody></table>
156 + </div>
157 + </div>
158 +
159 +
160 +</body></html>
\ No newline at end of file
views/translations/terms_pt.handlebars new
+246
@@ -0,0 +1,246 @@
1 +<!DOCTYPE html><html><head>
2 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
3 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
4 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
5 + <meta name="apple-mobile-web-app-capable" content="yes">
6 + <meta name="format-detection" content="telephone=no">
7 + <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS">
8 + <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
9 + <title>MeshCentral - Terms of use</title>
10 +</head>
11 +<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
12 + <div id="container">
13 + <!-- Begin Masthead -->
14 + <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;">
15 + <div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
16 + <strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
17 + </div>
18 + <div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
19 + <strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
20 + </div>
21 + <p id="logoutControl" style="color:white;font-size:11px;margin: 10px 10px 0;"></p>
22 + </div>
23 + <div id="page_leftbar">
24 + <div style="height:16px"></div>
25 + </div>
26 + <div id="topbar" class="noselect style3" style="height:24px;position:relative">
27 + <div id="uiMenuButton" title="Seleção da interface do usuário" onclick="showUserInterfaceSelectMenu()">
28 + ♦
29 + <div id="uiMenu" style="display:none">
30 + <div id="uiViewButton1" class="uiSelector" onclick="userInterfaceSelectMenu(1)" title="Interface da barra esquerda"><div class="uiSelector1"></div></div>
31 + <div id="uiViewButton2" class="uiSelector" onclick="userInterfaceSelectMenu(2)" title="Interface da barra superior"><div class="uiSelector2"></div></div>
32 + <div id="uiViewButton3" class="uiSelector" onclick="userInterfaceSelectMenu(3)" title="Interface de largura fixa"><div class="uiSelector3"></div></div>
33 + <div id="uiViewButton4" class="uiSelector" onclick="toggleNightMode()" title="Alternar modo noturno"><div class="uiSelector4"></div></div>
34 + </div>
35 + </div>
36 + </div>
37 + <div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
38 + <h1>Termos de uso</h1>
39 + <p>Entre em contato com o administrador do site para obter os termos de uso.</p>
40 + <hr>
41 + <p class="MsoNormal">
42 + A seguir, são apresentadas as divulgações necessárias de componentes e software de código aberto incorporados neste software.
43 + </p>
44 + <p class="MsoNormal">
45 + <b><span>1.AJAX Control Toolkit - Nova licença BSD</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
46 + </p>
47 + <p class="MsoNormal">
48 + <span>Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados.<o:p></o:p></span>
49 + </p>
50 + <p class="MsoNormal">
51 + <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>
52 + </p>
53 + <p class="MsoNormal">
54 + <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>
55 + </p>
56 + <p class="MsoNormal">
57 + <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>
58 + </p>
59 + <p class="MsoNormal">
60 + <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>
61 + </p>
62 + <p class="MsoNormal">
63 + <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>
64 + </p>
65 + <p class="MsoNormal">
66 + <b><span>2.OpenSSL - Licença OpenSSL e SSLeay</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
67 + </p>
68 + <p class="MsoNormal">
69 + <span><a href="http://www.openssl.org/source/license.html">http://www.openssl.org/source/license.html</a> </span>
70 + </p>
71 + <p class="MsoNormal">
72 + <span>Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados.<o:p></o:p></span>
73 + </p>
74 + <p class="MsoNormal">
75 + <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>
76 + </p>
77 + <p class="MsoNormal">
78 + <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>
79 + </p>
80 + <p class="MsoNormal">
81 + <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>
82 + </p>
83 + <p class="MsoNormal">
84 + <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>
85 + </p>
86 + <p class="MsoNormal">
87 + <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>
88 + </p>
89 + <p class="MsoNormal">
90 + <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>
91 + </p>
92 + <p class="MsoNormal">
93 + <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>
94 + </p>
95 + <p class="MsoNormal">
96 + <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>
97 + </p>
98 + <p class="MsoNormal">
99 + <b><span>3.jQuery Foundation - Licença MIT</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
100 + </p>
101 + <p class="MsoNormal">
102 + <span>Copyright 2013 jQuery Foundation e outros colaboradores <a href="http://jquery.com/">http://jquery.com/</a></span>
103 + </p>
104 + <p class="MsoNormal">
105 + <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>
106 + </p>
107 + <p class="MsoNormal">
108 + <b><span>4.Interface do Usuário jQuery - Licença MIT</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
109 + </p>
110 + <p class="MsoNormal">
111 + <span>Copyright 2013 jQuery Foundation e outros colaboradores, <a href="http://jqueryui.com/">http://jqueryui.com/</a></span>
112 + </p>
113 + <p class="MsoNormal">
114 + <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>
115 + </p>
116 + <p class="MsoNormal">
117 + <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>
118 + </p>
119 + <p class="MsoNormal">
120 + <b><span>5.noVNC - Licença Pública Mozilla 2.0 0</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
121 + </p>
122 + <p class="MsoNormal">
123 + <span><a href="https://github.com/kanaka/noVNC/blob/master/LICENSE.txt">https://github.com/kanaka/noVNC/blob/master/LICENSE.txt</a></span>
124 + </p>
125 + <p class="MsoNormal">
126 + <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>
127 + </p>
128 + <p class="MsoNormal">
129 + <b><span>6.Rcarousel - License MIT</span></b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:&quot;Times New Roman&quot;"><o:p></o:p></span>
130 + </p>
131 + <p class="MsoNormal">
132 + <span><a href="https://github.com/ryrych/rcarousel/blob/master/widget/license">https://github.com/ryrych/rcarousel/blob/master/widget/license</a></span>
133 + </p>
134 + <p class="MsoNormal">
135 + <span>Copyright (c) 2010 Wojciech 'RRH' Ryrych<o:p></o:p></span>
136 + </p>
137 + <p class="MsoNormal">
138 + <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>
139 + </p>
140 + <p class="MsoNormal">
141 + <b><span>7.Webtoolkit Javascript Base 64 - Licença Creative Commons Attribution 2.0 UK</span></b><span><o:p></o:p></span>
142 + </p>
143 + <p class="MsoNormal">
144 + <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>
145 + </p>
146 + <br>
147 + </div>
148 + <div id="footer">
149 + <table cellpadding="0" cellspacing="10" style="width: 100%">
150 + <tbody><tr>
151 + <td style="text-align:left"></td>
152 + <td style="text-align:right"><a href="/">Voltar</a></td>
153 + </tr>
154 + </tbody></table>
155 + </div>
156 + </div>
157 + <script>
158 + 'use strict';
159 + var uiMode = parseInt(getstore('uiMode', 1));
160 + var webPageStackMenu = false;
161 + var webPageFullScreen = true;
162 + var nightMode = (getstore('_nightMode', '0') == '1');
163 + var logoutControls = {{{logoutControls}}};
164 +
165 + var terms = '{{{terms}}}';
166 + if (terms != '') { QH('column_l', decodeURIComponent(terms)); }
167 + QV('column_l', true);
168 + userInterfaceSelectMenu();
169 +
170 + // Setup logout control
171 + var logoutControl = '';
172 + if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); }
173 + if (logoutControls.logoutUrl != null) { logoutControl += format(' <a href=\"' + logoutControls.logoutUrl + '\" style="color:white">' + "Sair" + '</a>'); }
174 + QH('logoutControl', logoutControl);
175 +
176 + // Toggle user interface menu
177 + function showUserInterfaceSelectMenu() {
178 + Q('uiViewButton1').classList.remove('uiSelectorSel');
179 + Q('uiViewButton2').classList.remove('uiSelectorSel');
180 + Q('uiViewButton3').classList.remove('uiSelectorSel');
181 + Q('uiViewButton4').classList.remove('uiSelectorSel');
182 + try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
183 + QV('uiMenu', (QS('uiMenu').display == 'none'));
184 + if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
185 + }
186 +
187 + function userInterfaceSelectMenu(s) {
188 + if (s) { uiMode = s; putstore('uiMode', uiMode); }
189 + webPageFullScreen = (uiMode < 3);
190 + webPageStackMenu = true;//(uiMode > 1);
191 + toggleFullScreen(0);
192 + toggleStackMenu(0);
193 + QC('column_l').add('room4submenu');
194 + }
195 +
196 + function toggleNightMode() {
197 + nightMode = !nightMode;
198 + if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
199 + putstore('_nightMode', nightMode ? '1' : '0');
200 + }
201 +
202 + // Toggle the web page to full screen
203 + function toggleFullScreen(toggle) {
204 + if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
205 + var hide = 0;
206 + //if (args.hide) { hide = parseInt(args.hide); }
207 + if (webPageFullScreen == false) {
208 + QC('body').remove('menu_stack');
209 + QC('body').remove('fullscreen');
210 + QC('body').remove('arg_hide');
211 + //if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
212 + //QV('UserDummyMenuSpan', false);
213 + //QV('page_leftbar', false);
214 + } else {
215 + QC('body').add('fullscreen');
216 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
217 + //QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
218 + //QV('page_leftbar', true);
219 + }
220 + QV('body', true);
221 + }
222 +
223 + // If FullScreen, toggle menu to be horisontal or vertical
224 + function toggleStackMenu(toggle) {
225 + if (webPageFullScreen == true) {
226 + if (toggle === 1) {
227 + webPageStackMenu = !webPageStackMenu;
228 + putstore('webPageStackMenu', webPageStackMenu);
229 + }
230 + if (webPageStackMenu == false) {
231 + QC('body').remove('menu_stack');
232 + } else {
233 + QC('body').add('menu_stack');
234 + //if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
235 + }
236 + }
237 + }
238 +
239 + function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
240 + 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; } }
241 + 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; }); };
242 +
243 + </script>
244 +
245 +
246 +</body></html>
\ No newline at end of file
webserver.js
+4 -4
@@ -1690,9 +1690,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1690 var logoutcontrols = { name: user.name };
1691 var extras = (req.query.key != null) ? ('&key=' + req.query.key) : '';
1692 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
1693 - 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) });
1693 + 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) });
1694 } else {
1695 - render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()), logoutControls: '{}' });
1695 + 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: '{}' });
1696 }
1697 } else {
1698 // See if there is a terms.txt file in meshcentral-data
@@ -1709,9 +1709,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1709 var logoutcontrols = { name: user.name };
1710 var extras = (req.query.key != null) ? ('&key=' + req.query.key) : '';
1711 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
1712 - render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data), logoutControls: JSON.stringify(logoutcontrols) });
1712 + render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: JSON.stringify(logoutcontrols) });
1713 } else {
1714 - render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data), logoutControls: '{}' });
1714 + render(req, res, getRenderPage('terms', req), { title: domain.title, title2: domain.title2, domainurl: domain.url, terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: '{}' });
1715 }
1716 });
1717 } else {