diff --git a/meshdesktopmultiplex.js b/meshdesktopmultiplex.js
index 4d763f4e..d0cee1ee 100644
--- a/meshdesktopmultiplex.js
+++ b/meshdesktopmultiplex.js
@@ -86,8 +86,10 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
obj.protocolOptions = null; // Set to the protocol options of the first viewer that connected.
obj.viewerConnected = false; // Set to true if one viewer attempted to connect to the agent.
obj.recordingFile = null; // Present if we are recording to file.
+ obj.recordingFileSize = 0; // Current size of the recording file.
obj.recordingFileWriting = false; // Set to true is we are in the process if writing to the recording file.
obj.startTime = null; // Starting time of the multiplex session.
+ obj.userIds = []; // List of userid's that have intertracted with this session.
// Add an agent or viewer
obj.addPeer = function (peer) {
@@ -108,6 +110,9 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
peer.sendQueue = [];
peer.paused = false;
+ // Add the user to the userids list if needed
+ if ((peer.user != null) && (obj.userIds.indexOf(peer.user._id) == -1)) { obj.userIds.push(peer.user._id); }
+
// Setup slow relay is requested. This will show down sending any data to this viewer.
if ((peer.req.query.slowrelay != null)) {
var sr = null;
@@ -125,7 +130,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
// Log joining the multiplex session
if (obj.startTime != null) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msg: "Joined desktop multiplex session", protocol: 2 };
- parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id], obj, event); // TODO: Add Node MeshID to targets
+ parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id, obj.meshid], obj, event);
}
} else {
//console.log('addPeer-agent', obj.nodeid);
@@ -149,7 +154,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
// Log multiplex session start
if ((obj.agent != null) && (obj.viewers.length > 0) && (obj.startTime == null)) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: obj.viewers[0].user._id, username: obj.viewers[0].user.name, msg: "Started desktop multiplex session", protocol: 2 };
- parent.parent.DispatchEvent(['*', obj.nodeid, obj.viewers[0].user._id], obj, event); // TODO: Add Node MeshID to targets
+ parent.parent.DispatchEvent(['*', obj.nodeid, obj.viewers[0].user._id, obj.meshid], obj, event);
obj.startTime = Date.now();
}
return true;
@@ -195,7 +200,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
// Log leaving the multiplex session
if (obj.startTime != null) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msg: "Left the desktop multiplex session", protocol: 2 };
- parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id], obj, event); // TODO: Add Node MeshID to targets
+ parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id, obj.meshid], obj, event);
}
// If this is the last viewer, disconnect the agent
@@ -214,12 +219,26 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
// Close the recording file if needed
if (obj.recordingFile != null) {
+ // Compute session length
+ if (obj.startTime != null) { obj.sessionStart = obj.startTime; obj.sessionLength = Math.round((Date.now() - obj.startTime) / 1000); }
+
+ // Write the last record of the recording file
var rf = obj.recordingFile;
delete obj.recordingFile;
recordingEntry(rf.fd, 3, 0, 'MeshCentralMCREC', function (fd, filename) {
parent.parent.fs.close(fd);
+
// Now that the recording file is closed, check if we need to index this file.
if (domain.sessionrecording.index !== false) { parent.parent.certificateOperations.acceleratorPerformOperation('indexMcRec', filename); }
+
+ // Add a event entry about this recording
+ var basefile = parent.parent.path.basename(filename);
+ var event = { etype: 'relay', action: 'recording', domain: domain.id, nodeid: obj.nodeid, msg: "Finished recording session" + (obj.sessionLength ? (', ' + obj.sessionLength + ' second(s)') : ''), filename: basefile, size: obj.recordingFileSize, protocol: 2, icon: obj.icon, name: obj.name, meshid: obj.meshid, userids: obj.userIds, multiplex: true };
+ var mesh = parent.meshes[obj.meshid];
+ if (mesh != null) { event.meshname = mesh.name; }
+ if (obj.sessionStart) { event.startTime = obj.sessionStart; event.lengthTime = obj.sessionLength; }
+ parent.parent.DispatchEvent(['*', 'recording', obj.nodeid, obj.meshid], obj, event);
+
cleanUpRecordings();
}, rf.filename);
}
@@ -227,7 +246,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
// Log end of multiplex session
if (obj.startTime != null) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, msg: "Closed desktop multiplex session" + ', ' + Math.floor((Date.now() - obj.startTime) / 1000) + ' second(s)', protocol: 2 };
- parent.parent.DispatchEvent(['*', obj.nodeid], obj, event); // TODO: Add Node MeshID to targets
+ parent.parent.DispatchEvent(['*', obj.nodeid, obj.meshid], obj, event);
obj.startTime = null;
}
@@ -647,7 +666,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
}
// Write the recording file header
parent.parent.debug('relay', 'Relay: Started recoding to file: ' + recFullFilename);
- var metadata = { magic: 'MeshCentralRelaySession', ver: 1, nodeid: obj.nodeid, time: new Date().toLocaleString(), protocol: 2 };
+ var metadata = { magic: 'MeshCentralRelaySession', ver: 1, nodeid: obj.nodeid, meshid: obj.meshid, time: new Date().toLocaleString(), protocol: 2, devicename: obj.name, devicegroup: obj.meshname };
var firstBlock = JSON.stringify(metadata);
recordingEntry(fd, 1, 0, firstBlock, function () {
obj.recordingFile = { fd: fd, filename: recFullFilename };
@@ -684,6 +703,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
header.writeIntBE(new Date(), 10, 6); // Time
var block = Buffer.concat([header, blockData]);
parent.parent.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
+ obj.recordingFileSize += block.length;
} else {
// Binary write
var header = Buffer.alloc(16); // Header: Type (2) + Flags (2) + Size(4) + Time(8)
@@ -693,6 +713,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
header.writeIntBE(new Date(), 10, 6); // Time
var block = Buffer.concat([header, data]);
parent.parent.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
+ obj.recordingFileSize += block.length;
}
} catch (ex) { console.log(ex); func(fd, tag); }
}
@@ -725,7 +746,14 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
}
}
- recordingSetup(domain, function () { func(obj); });
+ // Get node information
+ parent.db.Get(nodeid, function (err, nodes) {
+ if ((err != null) || (nodes.length != 1)) { func(null); }
+ obj.meshid = nodes[0].meshid;
+ obj.icon = nodes[0].icon;
+ obj.name = nodes[0].name;
+ recordingSetup(domain, function () { func(obj); });
+ });
return obj;
}
@@ -784,7 +812,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
if ((arg == 1) || (arg == null)) { try { ws.close(); parent.parent.debug('relay', 'DesktopRelay: Soft disconnect (' + cleanRemoteAddr(obj.req.ip) + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
if (arg == 2) { try { ws._socket._parent.end(); parent.parent.debug('relay', 'DesktopRelay: Hard disconnect (' + cleanRemoteAddr(obj.req.ip) + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
if (obj.relaySessionCounted) { parent.relaySessionCount--; delete obj.relaySessionCounted; }
- if (obj.deskDecoder != null) { if (obj.deskDecoder.removePeer(obj) == true) { delete parent.desktoprelays[obj.nodeid]; } }
+ if (obj.deskMultiplexor != null) { if (obj.deskMultiplexor.removePeer(obj) == true) { delete parent.desktoprelays[obj.nodeid]; } }
// Aggressive cleanup
delete obj.id;
@@ -793,7 +821,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
delete obj.user;
delete obj.nodeid;
delete obj.ruserid;
- delete obj.deskDecoder;
+ delete obj.deskMultiplexor;
// Clear timers if present
if (obj.pingtimer != null) { clearInterval(obj.pingtimer); delete obj.pingtimer; }
@@ -885,23 +913,30 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
}
// Create if needed and add this peer to the desktop multiplexor
- obj.deskDecoder = parent.desktoprelays[obj.nodeid];
- if (obj.deskDecoder == null) {
+ obj.deskMultiplexor = parent.desktoprelays[obj.nodeid];
+ if (obj.deskMultiplexor == null) {
parent.desktoprelays[obj.nodeid] = 1; // Indicate that the creating of the desktop multiplexor is pending.
parent.parent.debug('relay', 'DesktopRelay: Creating new desktop multiplexor');
- CreateDesktopMultiplexor(parent, domain, obj.nodeid, function (deskDecoder) {
- obj.deskDecoder = deskDecoder;
- parent.desktoprelays[obj.nodeid] = obj.deskDecoder;
- obj.deskDecoder.addPeer(obj);
- ws._socket.resume(); // Release the traffic
+ CreateDesktopMultiplexor(parent, domain, obj.nodeid, function (deskMultiplexor) {
+ if (deskMultiplexor != null) {
+ // Desktop multiplexor was created, use it.
+ obj.deskMultiplexor = deskMultiplexor;
+ parent.desktoprelays[obj.nodeid] = obj.deskMultiplexor;
+ obj.deskMultiplexor.addPeer(obj);
+ ws._socket.resume(); // Release the traffic
+ } else {
+ // An error has occured, close this connection
+ delete parent.desktoprelays[obj.nodeid];
+ ws.close();
+ }
});
} else {
- if (obj.deskDecoder == 1) {
+ if (obj.deskMultiplexor == 1) {
// The multiplexor is being created, hold a little and try again. This is to prevent a possible race condition.
setTimeout(function () { performRelay(++retryCount); }, 50);
} else {
// Hook up this peer to the multiplexor and release the traffic
- obj.deskDecoder.addPeer(obj);
+ obj.deskMultiplexor.addPeer(obj);
ws._socket.resume();
}
}
@@ -910,7 +945,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
// When data is received from the mesh relay web socket
ws.on('message', function (data) {
// If this data was received by the agent, decode it.
- if (this.me.deskDecoder != null) { this.me.deskDecoder.processData(this.me, data); }
+ if (this.me.deskMultiplexor != null) { this.me.deskMultiplexor.processData(this.me, data); }
});
// If error, close both sides of the relay.
diff --git a/meshrelay.js b/meshrelay.js
index 65f9a81a..a23deb95 100644
--- a/meshrelay.js
+++ b/meshrelay.js
@@ -222,8 +222,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
if ((sessionUser != null) && (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(parseInt(obj.req.query.p)) >= 0))))) {
// Get the computer name
parent.db.Get(obj.req.query.nodeid, function (err, nodes) {
- var xusername = '', xdevicename = '', xdevicename2 = null;
- if ((nodes != null) && (nodes.length == 1)) { xdevicename2 = nodes[0].name; xdevicename = '-' + parent.common.makeFilename(nodes[0].name); }
+ var xusername = '', xdevicename = '', xdevicename2 = null, node = null;
+ if ((nodes != null) && (nodes.length == 1)) { node = nodes[0]; xdevicename2 = node.name; xdevicename = '-' + parent.common.makeFilename(node.name); }
// Get the username and make it acceptable as a filename
if (sessionUser._id) { xusername = '-' + parent.common.makeFilename(sessionUser._id.split('/')[2]); }
@@ -250,8 +250,9 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
var metadata = { magic: 'MeshCentralRelaySession', ver: 1, userid: sessionUser._id, username: sessionUser.name, sessionid: obj.id, ipaddr1: cleanRemoteAddr(obj.req.ip), ipaddr2: cleanRemoteAddr(obj.peer.req.ip), time: new Date().toLocaleString(), protocol: (((obj.req == null) || (obj.req.query == null)) ? null : obj.req.query.p), nodeid: (((obj.req == null) || (obj.req.query == null)) ? null : obj.req.query.nodeid ) };
if (xdevicename2 != null) { metadata.devicename = xdevicename2; }
var firstBlock = JSON.stringify(metadata);
- recordingEntry(fd, 1, 0, firstBlock, function () {
- try { relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false, filename: recFullFilename }; } catch (ex) {
+ var logfile = { fd: fd, lock: false, filename: recFullFilename, startTime: Date.now(), size: 0, nodeid: node._id, meshid: node.meshid, name: node.name, icon: node.icon };
+ recordingEntry(logfile, 1, 0, firstBlock, function () {
+ try { relayinfo.peer1.ws.logfile = ws.logfile = logfile; } catch (ex) {
try { ws.send('c'); } catch (ex) { } // Send connect to both peers, 'cr' indicates the session is being recorded.
try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
return;
@@ -323,7 +324,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
if (this.logfile != null) {
// Write data to log file then perform relay
var xthis = this;
- recordingEntry(this.logfile.fd, 2, ((obj.req.query.browser) ? 2 : 0), data, function () { xthis.peer.send(data, ws.flushSink); });
+ recordingEntry(this.logfile, 2, ((obj.req.query.browser) ? 2 : 0), data, function () { xthis.peer.send(data, ws.flushSink); });
} else {
// Perform relay
this.peer.send(data, ws.flushSink);
@@ -335,7 +336,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
if (this.logfile != null) {
// Write data to log file then perform slow relay
var xthis = this;
- recordingEntry(this.logfile.fd, 2, ((obj.req.query.browser) ? 2 : 0), data, function () {
+ recordingEntry(this.logfile, 2, ((obj.req.query.browser) ? 2 : 0), data, function () {
setTimeout(function () { xthis.peer.send(data, ws.flushSink); }, xthis.peer.slowRelay);
});
} else {
@@ -406,10 +407,29 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
var logfile = ws.logfile;
delete ws.logfile;
if (peer.ws) { delete peer.ws.logfile; }
- recordingEntry(logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, tag) {
- parent.parent.fs.close(fd);
+ recordingEntry(logfile, 3, 0, 'MeshCentralMCREC', function (logfile, tag) {
+ parent.parent.fs.close(logfile.fd);
+
// Now that the recording file is closed, check if we need to index this file.
if (domain.sessionrecording.index !== false) { parent.parent.certificateOperations.acceleratorPerformOperation('indexMcRec', tag.logfile.filename); }
+
+ // Compute session length
+ var sessionLength = null;
+ if (tag.logfile.startTime != null) { sessionLength = Math.round((Date.now() - tag.logfile.startTime) / 1000); }
+
+ // Add a event entry about this recording
+ var basefile = parent.parent.path.basename(tag.logfile.filename);
+ var event = { etype: 'relay', action: 'recording', domain: domain.id, nodeid: tag.logfile.nodeid, msg: "Finished recording session" + (sessionLength ? (', ' + sessionLength + ' second(s)') : ''), filename: basefile, size: tag.logfile.size };
+ if (user) { event.userids = [user._id]; } else if (peer.user) { event.userids = [peer.user._id]; }
+ var xprotocol = (((obj.req == null) || (obj.req.query == null)) ? null : obj.req.query.p);
+ if (xprotocol != null) { event.protocol = parseInt(xprotocol); }
+ var mesh = parent.meshes[tag.logfile.meshid];
+ if (mesh != null) { event.meshname = mesh.name; event.meshid = mesh._id; }
+ if (tag.logfile.startTime) { event.startTime = tag.logfile.startTime; event.lengthTime = sessionLength; }
+ if (tag.logfile.name) { event.name = tag.logfile.name; }
+ if (tag.logfile.icon) { event.icon = tag.logfile.icon; }
+ parent.parent.DispatchEvent(['*', 'recording', obj.nodeid, obj.meshid], obj, event);
+
cleanUpRecordings();
}, { ws: ws, pws: peer.ws, logfile: logfile });
}
@@ -428,7 +448,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
}
// Record a new entry in a recording log
- function recordingEntry(fd, type, flags, data, func, tag) {
+ function recordingEntry(logfile, type, flags, data, func, tag) {
try {
if (typeof data == 'string') {
// String write
@@ -438,7 +458,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
header.writeInt32BE(blockData.length, 4); // Size
header.writeIntBE(new Date(), 10, 6); // Time
var block = Buffer.concat([header, blockData]);
- parent.parent.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
+ parent.parent.fs.write(logfile.fd, block, 0, block.length, function () { func(logfile, tag); });
+ logfile.size += block.length;
} else {
// Binary write
var header = Buffer.alloc(16); // Header: Type (2) + Flags (2) + Size(4) + Time(8)
@@ -447,9 +468,10 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
header.writeInt32BE(data.length, 4); // Size
header.writeIntBE(new Date(), 10, 6); // Time
var block = Buffer.concat([header, data]);
- parent.parent.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
+ parent.parent.fs.write(logfile.fd, block, 0, block.length, function () { func(logfile, tag); });
+ logfile.size += block.length;
}
- } catch (ex) { console.log(ex); func(fd, tag); }
+ } catch (ex) { console.log(ex); func(logfile, tag); }
}
// Mark this relay session as authenticated if this is the user end.
diff --git a/meshuser.js b/meshuser.js
index c42bb440..3dda61c2 100644
--- a/meshuser.js
+++ b/meshuser.js
@@ -1211,6 +1211,37 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
}
break;
}
+ case 'recordings': {
+ if (((user.siteadmin & SITERIGHT_RECORDINGS) == 0) || (domain.sessionrecording == null)) return; // Check if recordings is enabled and we have rights to do this.
+ var recordingsPath = null;
+ if (domain.sessionrecording.filepath) { recordingsPath = domain.sessionrecording.filepath; } else { recordingsPath = parent.parent.recordpath; }
+ if (recordingsPath == null) return;
+ fs.readdir(recordingsPath, function (err, files) {
+ if (err != null) return;
+ if ((command.limit == null) || (typeof command.limit != 'number')) {
+ // Send the list of all recordings
+ db.GetEvents(['recording'], domain.id, function (err, docs) {
+ if (err != null) return;
+ for (var i in docs) {
+ delete docs[i].action; delete docs[i].etype; delete docs[i].msg; // TODO: We could make a more specific query in the DB and never have these.
+ if (files.indexOf(docs[i].filename) >= 0) { docs[i].present = 1; }
+ }
+ try { ws.send(JSON.stringify({ action: 'recordings', events: docs, tag: command.tag })); } catch (ex) { }
+ });
+ } else {
+ // Send the list of most recent recordings, up to 'limit' count
+ db.GetEventsWithLimit(['recording'], domain.id, command.limit, function (err, docs) {
+ if (err != null) return;
+ for (var i in docs) {
+ delete docs[i].action; delete docs[i].etype; delete docs[i].msg; // TODO: We could make a more specific query in the DB and never have these.
+ if (files.indexOf(docs[i].filename) >= 0) { docs[i].present = 1; }
+ }
+ try { ws.send(JSON.stringify({ action: 'recordings', events: docs, tag: command.tag })); } catch (ex) { }
+ });
+ }
+ });
+ break;
+ }
case 'users':
{
// Request a list of all users
diff --git a/translate/translate.json b/translate/translate.json
index 45f428aa..8cf545f4 100644
--- a/translate/translate.json
+++ b/translate/translate.json
@@ -607,7 +607,7 @@
"default-mobile.handlebars->9->248",
"default-mobile.handlebars->9->77",
"default.handlebars->25->1339",
- "default.handlebars->25->1649",
+ "default.handlebars->25->1676",
"default.handlebars->25->727"
]
},
@@ -2956,7 +2956,7 @@
"ru": "Счетчик ошибок агента",
"zh-chs": "座席錯誤計數器",
"xloc": [
- "default.handlebars->25->1659"
+ "default.handlebars->25->1686"
]
},
{
@@ -3025,7 +3025,7 @@
"ru": "Сессии агентов",
"zh-chs": "座席會議",
"xloc": [
- "default.handlebars->25->1675"
+ "default.handlebars->25->1702"
]
},
{
@@ -3148,7 +3148,7 @@
"ru": "Агенты",
"zh-chs": "代理商",
"xloc": [
- "default.handlebars->25->1688"
+ "default.handlebars->25->1715"
]
},
{
@@ -3970,7 +3970,7 @@
"ru": "Вы уверенны, что {0} плагин: {1}",
"zh-chs": "您確定要{0}插件嗎:{1}",
"xloc": [
- "default.handlebars->25->1728"
+ "default.handlebars->25->1755"
]
},
{
@@ -4399,7 +4399,7 @@
"ru": "Плохой ключ",
"zh-chs": "錯誤的簽名",
"xloc": [
- "default.handlebars->25->1666"
+ "default.handlebars->25->1693"
]
},
{
@@ -4416,7 +4416,7 @@
"ru": "Плохой веб-сертификат",
"zh-chs": "錯誤的網絡證書",
"xloc": [
- "default.handlebars->25->1665"
+ "default.handlebars->25->1692"
]
},
{
@@ -4679,7 +4679,7 @@
"ru": "CIRA Сервер",
"zh-chs": "CIRA服務器",
"xloc": [
- "default.handlebars->25->1716"
+ "default.handlebars->25->1743"
]
},
{
@@ -4696,7 +4696,7 @@
"ru": "CIRA Сервер команды",
"zh-chs": "CIRA服務器命令",
"xloc": [
- "default.handlebars->25->1717"
+ "default.handlebars->25->1744"
]
},
{
@@ -4729,7 +4729,7 @@
"ru": "Загрузка CPU",
"zh-chs": "CPU負載",
"xloc": [
- "default.handlebars->25->1680"
+ "default.handlebars->25->1707"
]
},
{
@@ -4746,7 +4746,7 @@
"ru": "Загрузка CPU за последние 15 минут",
"zh-chs": "最近15分鐘的CPU負載",
"xloc": [
- "default.handlebars->25->1683"
+ "default.handlebars->25->1710"
]
},
{
@@ -4763,7 +4763,7 @@
"ru": "Загрузка CPU за последние 5 минут",
"zh-chs": "最近5分鐘的CPU負載",
"xloc": [
- "default.handlebars->25->1682"
+ "default.handlebars->25->1709"
]
},
{
@@ -4780,7 +4780,7 @@
"ru": "Загрузка CPU за последнюю минуту",
"zh-chs": "最後一分鐘的CPU負載",
"xloc": [
- "default.handlebars->25->1681"
+ "default.handlebars->25->1708"
]
},
{
@@ -4835,7 +4835,7 @@
"ru": "Ошибка вызова",
"zh-chs": "通話錯誤",
"xloc": [
- "default.handlebars->25->1729"
+ "default.handlebars->25->1756"
]
},
{
@@ -5302,7 +5302,7 @@
"ru": "Проверка...",
"zh-chs": "檢查...",
"xloc": [
- "default.handlebars->25->1723",
+ "default.handlebars->25->1750",
"default.handlebars->25->865"
]
},
@@ -5518,7 +5518,7 @@
"nl": "Wis alle meldingen",
"zh-chs": "全部清除",
"xloc": [
- "default.handlebars->25->1653"
+ "default.handlebars->25->1680"
]
},
{
@@ -5568,7 +5568,7 @@
"ru": "Очистить это уведомление",
"zh-chs": "清除此通知",
"xloc": [
- "default.handlebars->25->1652"
+ "default.handlebars->25->1679"
]
},
{
@@ -6380,7 +6380,7 @@
"ru": "Подключено Intel® AMT",
"zh-chs": "連接的英特爾®AMT",
"xloc": [
- "default.handlebars->25->1671"
+ "default.handlebars->25->1698"
]
},
{
@@ -6397,7 +6397,7 @@
"ru": "Подключенные пользователи",
"zh-chs": "關聯用戶",
"xloc": [
- "default.handlebars->25->1676"
+ "default.handlebars->25->1703"
]
},
{
@@ -6473,7 +6473,7 @@
"ru": "Подключений ",
"zh-chs": "連接數",
"xloc": [
- "default.handlebars->25->1687"
+ "default.handlebars->25->1714"
]
},
{
@@ -6490,7 +6490,7 @@
"ru": "Ретранслятор подключения",
"zh-chs": "連接繼電器",
"xloc": [
- "default.handlebars->25->1715"
+ "default.handlebars->25->1742"
]
},
{
@@ -6617,7 +6617,7 @@
"ru": "Cookie-кодировщик",
"zh-chs": "Cookie編碼器",
"xloc": [
- "default.handlebars->25->1701"
+ "default.handlebars->25->1728"
]
},
{
@@ -6922,7 +6922,7 @@
"ru": "Основной сервер",
"zh-chs": "核心服務器",
"xloc": [
- "default.handlebars->25->1700"
+ "default.handlebars->25->1727"
]
},
{
@@ -7872,6 +7872,7 @@
"zh-chs": "桌面",
"xloc": [
"default.handlebars->25->1217",
+ "default.handlebars->25->1657",
"default.handlebars->25->432",
"default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevDesktop",
"default.handlebars->contextMenu->cxdesktop"
@@ -8092,7 +8093,8 @@
"default.handlebars->25->1238",
"default.handlebars->25->1512",
"default.handlebars->25->1518",
- "default.handlebars->25->1619"
+ "default.handlebars->25->1619",
+ "default.handlebars->25->1666"
]
},
{
@@ -8132,7 +8134,7 @@
"default.handlebars->25->1477",
"default.handlebars->25->1499",
"default.handlebars->25->1563",
- "default.handlebars->25->1674",
+ "default.handlebars->25->1701",
"default.handlebars->container->column_l->p2->p2info->7"
]
},
@@ -8185,6 +8187,7 @@
"zh-chs": "設備名稱",
"xloc": [
"default-mobile.handlebars->9->232",
+ "default.handlebars->25->1665",
"default.handlebars->25->231",
"default.handlebars->25->669",
"player.handlebars->3->9"
@@ -9185,7 +9188,7 @@
"nl": "Dubbele agent",
"zh-chs": "代理重复",
"xloc": [
- "default.handlebars->25->1670"
+ "default.handlebars->25->1697"
]
},
{
@@ -9250,6 +9253,8 @@
"ru": "Длительность",
"zh-chs": "持續時間",
"xloc": [
+ "default.handlebars->25->1651",
+ "default.handlebars->25->1671",
"player.handlebars->3->2"
]
},
@@ -9999,7 +10004,7 @@
"nl": "Email/SMS verkeer",
"zh-chs": "电子邮件/短信流量",
"xloc": [
- "default.handlebars->25->1709"
+ "default.handlebars->25->1736"
]
},
{
@@ -10093,6 +10098,12 @@
"default.handlebars->container->column_l->p2->p2info->p2AccountActions->3->accountEnableNotificationsSpan->0"
]
},
+ {
+ "en": "Enabled",
+ "xloc": [
+ "default.handlebars->25->1673"
+ ]
+ },
{
"cs": "Kódování",
"de": "Kodierung",
@@ -10110,6 +10121,12 @@
"default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->3"
]
},
+ {
+ "en": "End Time",
+ "xloc": [
+ "default.handlebars->25->1670"
+ ]
+ },
{
"cs": "angličtina",
"de": "Englisch",
@@ -10670,7 +10687,7 @@
"ru": "Внешний",
"zh-chs": "外部",
"xloc": [
- "default.handlebars->25->1694"
+ "default.handlebars->25->1721"
]
},
{
@@ -10874,6 +10891,7 @@
"zh-chs": "檔案",
"xloc": [
"default.handlebars->25->1224",
+ "default.handlebars->25->1658",
"default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevFiles",
"default.handlebars->contextMenu->cxfiles"
]
@@ -11176,8 +11194,8 @@
"ru": "Свободно",
"zh-chs": "自由",
"xloc": [
- "default.handlebars->25->1655",
- "default.handlebars->25->1657"
+ "default.handlebars->25->1682",
+ "default.handlebars->25->1684"
]
},
{
@@ -12094,7 +12112,7 @@
"ru": "Всего кучи",
"zh-chs": "堆總數",
"xloc": [
- "default.handlebars->25->1696"
+ "default.handlebars->25->1723"
]
},
{
@@ -12111,7 +12129,7 @@
"ru": "Куча используется",
"zh-chs": "堆使用",
"xloc": [
- "default.handlebars->25->1695"
+ "default.handlebars->25->1722"
]
},
{
@@ -12897,8 +12915,8 @@
"xloc": [
"default.handlebars->25->1326",
"default.handlebars->25->1334",
- "default.handlebars->25->1692",
- "default.handlebars->25->1714"
+ "default.handlebars->25->1719",
+ "default.handlebars->25->1741"
]
},
{
@@ -12935,6 +12953,18 @@
"default.handlebars->25->150"
]
},
+ {
+ "en": "Intel AMT Redirection",
+ "xloc": [
+ "default.handlebars->25->1660"
+ ]
+ },
+ {
+ "en": "Intel AMT WSMAN",
+ "xloc": [
+ "default.handlebars->25->1659"
+ ]
+ },
{
"cs": "Intel AMT zjištěno",
"de": "Intel AMT erkannt",
@@ -13616,7 +13646,7 @@
"ru": "Некорректный тип группы устройств",
"zh-chs": "無效的設備組類型",
"xloc": [
- "default.handlebars->25->1669"
+ "default.handlebars->25->1696"
]
},
{
@@ -13633,7 +13663,7 @@
"ru": "Некорректный JSON",
"zh-chs": "無效的JSON",
"xloc": [
- "default.handlebars->25->1663"
+ "default.handlebars->25->1690"
]
},
{
@@ -13685,7 +13715,7 @@
"ru": "Некорректная сигнатура PKCS",
"zh-chs": "無效的PKCS簽名",
"xloc": [
- "default.handlebars->25->1661"
+ "default.handlebars->25->1688"
]
},
{
@@ -13702,7 +13732,7 @@
"ru": "Некорректная сигнатура RSA",
"zh-chs": "無效的RSA密碼",
"xloc": [
- "default.handlebars->25->1662"
+ "default.handlebars->25->1689"
]
},
{
@@ -14785,7 +14815,7 @@
"ru": "Меньше",
"zh-chs": "減",
"xloc": [
- "default.handlebars->25->1731"
+ "default.handlebars->25->1758"
]
},
{
@@ -15882,7 +15912,7 @@
"ru": "Сообщения главного сервера",
"zh-chs": "主服務器消息",
"xloc": [
- "default.handlebars->25->1703"
+ "default.handlebars->25->1730"
]
},
{
@@ -16308,7 +16338,7 @@
"ru": "Достигнуто максимальное число сессий",
"zh-chs": "達到的會話數上限",
"xloc": [
- "default.handlebars->25->1667"
+ "default.handlebars->25->1694"
]
},
{
@@ -16362,7 +16392,7 @@
"ru": "Мегабайт",
"zh-chs": "兆字節",
"xloc": [
- "default.handlebars->25->1693"
+ "default.handlebars->25->1720"
]
},
{
@@ -16379,7 +16409,7 @@
"ru": "ОЗУ",
"zh-chs": "記憶",
"xloc": [
- "default.handlebars->25->1684",
+ "default.handlebars->25->1711",
"default.handlebars->25->819",
"default.handlebars->container->column_l->p40->3->1->p40type->3"
]
@@ -16515,7 +16545,7 @@
"ru": "Трафик MeshAgent",
"zh-chs": "MeshAgent流量",
"xloc": [
- "default.handlebars->25->1705"
+ "default.handlebars->25->1732"
]
},
{
@@ -16532,7 +16562,7 @@
"ru": "Обновление MeshAgent",
"zh-chs": "MeshAgent更新",
"xloc": [
- "default.handlebars->25->1706"
+ "default.handlebars->25->1733"
]
},
{
@@ -16635,7 +16665,7 @@
"ru": "Соединения сервера MeshCentral",
"zh-chs": "MeshCentral服務器對等",
"xloc": [
- "default.handlebars->25->1704"
+ "default.handlebars->25->1731"
]
},
{
@@ -16898,7 +16928,7 @@
"ru": "Диспетчер сообщения",
"zh-chs": "郵件調度程序",
"xloc": [
- "default.handlebars->25->1702"
+ "default.handlebars->25->1729"
]
},
{
@@ -17046,7 +17076,7 @@
"ru": "Еще",
"zh-chs": "更多",
"xloc": [
- "default.handlebars->25->1730"
+ "default.handlebars->25->1757"
]
},
{
@@ -17117,6 +17147,12 @@
"default.handlebars->contextMenu->cxmdesktop"
]
},
+ {
+ "en": "Multiplexor",
+ "xloc": [
+ "default.handlebars->25->1672"
+ ]
+ },
{
"cs": "Můj účet",
"de": "Mein Konto",
@@ -18638,6 +18674,12 @@
"default.handlebars->25->802"
]
},
+ {
+ "en": "Not on server",
+ "xloc": [
+ "default.handlebars->25->1664"
+ ]
+ },
{
"cs": "Nenastaveno",
"de": "Nicht gesetzt",
@@ -18907,7 +18949,7 @@
"ru": "Произошло в {0}",
"zh-chs": "發生在{0}",
"xloc": [
- "default.handlebars->25->1651"
+ "default.handlebars->25->1678"
]
},
{
@@ -20011,7 +20053,7 @@
"zh-chs": "插件動作",
"xloc": [
"default.handlebars->25->169",
- "default.handlebars->25->1727"
+ "default.handlebars->25->1754"
]
},
{
@@ -20317,6 +20359,12 @@
"default.handlebars->25->7"
]
},
+ {
+ "en": "Present on server",
+ "xloc": [
+ "default.handlebars->25->1663"
+ ]
+ },
{
"cs": "Pro pokračování/pozastavení stiskněte [mezerník].",
"de": "Für Abspielen/Pause [Leertaste] drücken,",
@@ -20421,6 +20469,7 @@
"ru": "Протокол",
"zh-chs": "協議",
"xloc": [
+ "default.handlebars->25->1661",
"player.handlebars->3->15"
]
},
@@ -20727,7 +20776,7 @@
"ru": "RSS",
"zh-chs": "的RSS",
"xloc": [
- "default.handlebars->25->1697"
+ "default.handlebars->25->1724"
]
},
{
@@ -20818,6 +20867,12 @@
"default.handlebars->container->column_l->p11->deskarea0->deskarea4->1"
]
},
+ {
+ "en": "Recording Details",
+ "xloc": [
+ "default.handlebars->25->1675"
+ ]
+ },
{
"en": "Recordings",
"nl": "Opnames",
@@ -20885,7 +20940,8 @@
"default.handlebars->25->437",
"default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsAreaTop->DeskToolsRefreshButton",
"default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
- "default.handlebars->container->column_l->p40->3->3"
+ "default.handlebars->container->column_l->p40->3->3",
+ "default.handlebars->container->column_l->p52->3->1->0->3->3"
]
},
{
@@ -20938,7 +20994,7 @@
"ru": "Число ретрансляций",
"zh-chs": "中繼計數",
"xloc": [
- "default.handlebars->25->1679"
+ "default.handlebars->25->1706"
]
},
{
@@ -20955,7 +21011,7 @@
"ru": "Ошибки ретранслятора",
"zh-chs": "中繼錯誤",
"xloc": [
- "default.handlebars->25->1672"
+ "default.handlebars->25->1699"
]
},
{
@@ -20972,8 +21028,8 @@
"ru": "Сессии ретранслятора",
"zh-chs": "接力會議",
"xloc": [
- "default.handlebars->25->1678",
- "default.handlebars->25->1691"
+ "default.handlebars->25->1705",
+ "default.handlebars->25->1718"
]
},
{
@@ -23002,7 +23058,7 @@
"ru": "Сертификат сервера",
"zh-chs": "服務器證書",
"xloc": [
- "default.handlebars->25->1707"
+ "default.handlebars->25->1734"
]
},
{
@@ -23019,7 +23075,7 @@
"ru": "База данных сервера",
"zh-chs": "服務器數據庫",
"xloc": [
- "default.handlebars->25->1708"
+ "default.handlebars->25->1735"
]
},
{
@@ -23128,7 +23184,7 @@
"ru": "Состояние сервера",
"zh-chs": "服務器狀態",
"xloc": [
- "default.handlebars->25->1658"
+ "default.handlebars->25->1685"
]
},
{
@@ -23162,7 +23218,7 @@
"ru": "Трассировка сервера",
"zh-chs": "服務器跟踪",
"xloc": [
- "default.handlebars->25->1718"
+ "default.handlebars->25->1745"
]
},
{
@@ -23301,7 +23357,7 @@
"ru": "ServerStats.csv",
"zh-chs": "ServerStats.csv",
"xloc": [
- "default.handlebars->25->1699"
+ "default.handlebars->25->1726"
]
},
{
@@ -23338,6 +23394,12 @@
"default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsAreaTop->deskToolsTopTabService"
]
},
+ {
+ "en": "Session",
+ "xloc": [
+ "default.handlebars->25->1649"
+ ]
+ },
{
"cs": "Čas spojení",
"de": "Sitzungszeit",
@@ -23795,6 +23857,8 @@
"ru": "Размер",
"zh-chs": "尺寸",
"xloc": [
+ "default.handlebars->25->1652",
+ "default.handlebars->25->1667",
"default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize"
]
},
@@ -24602,6 +24666,13 @@
"default.handlebars->25->705"
]
},
+ {
+ "en": "Start Time",
+ "xloc": [
+ "default.handlebars->25->1650",
+ "default.handlebars->25->1669"
+ ]
+ },
{
"cs": "Stav",
"de": "Zustand",
@@ -24652,6 +24723,7 @@
"zh-chs": "狀態",
"xloc": [
"default.handlebars->25->1601",
+ "default.handlebars->25->1662",
"default.handlebars->container->column_l->p42->p42tbl->1->0->7"
]
},
@@ -25193,6 +25265,7 @@
"zh-chs": "終奌站",
"xloc": [
"default.handlebars->25->1221",
+ "default.handlebars->25->1656",
"default.handlebars->25->433",
"default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevTerminal",
"default.handlebars->contextMenu->cxterminal"
@@ -25393,7 +25466,7 @@
"ru": "На данный момент уведомлений нет",
"zh-chs": "目前沒有任何通知",
"xloc": [
- "default.handlebars->25->1650"
+ "default.handlebars->25->1677"
]
},
{
@@ -26623,6 +26696,8 @@
"default-mobile.handlebars->9->182",
"default.handlebars->25->13",
"default.handlebars->25->1641",
+ "default.handlebars->25->1654",
+ "default.handlebars->25->1655",
"default.handlebars->25->379",
"default.handlebars->25->41",
"default.handlebars->25->42",
@@ -26667,7 +26742,7 @@
"ru": "Неизвестное действие",
"zh-chs": "未知動作",
"xloc": [
- "default.handlebars->25->1664"
+ "default.handlebars->25->1691"
]
},
{
@@ -26704,7 +26779,7 @@
"xloc": [
"default.handlebars->25->1510",
"default.handlebars->25->1617",
- "default.handlebars->25->1668"
+ "default.handlebars->25->1695"
]
},
{
@@ -26721,7 +26796,7 @@
"ru": "Неизвестная группа",
"zh-chs": "未知群組",
"xloc": [
- "default.handlebars->25->1660"
+ "default.handlebars->25->1687"
]
},
{
@@ -26845,7 +26920,7 @@
"ru": "Актуально",
"zh-chs": "最新",
"xloc": [
- "default.handlebars->25->1725"
+ "default.handlebars->25->1752"
]
},
{
@@ -27094,8 +27169,8 @@
"ru": "Использовано",
"zh-chs": "用過的",
"xloc": [
- "default.handlebars->25->1654",
- "default.handlebars->25->1656"
+ "default.handlebars->25->1681",
+ "default.handlebars->25->1683"
]
},
{
@@ -27116,6 +27191,7 @@
"default.handlebars->25->1179",
"default.handlebars->25->1402",
"default.handlebars->25->1506",
+ "default.handlebars->25->1674",
"default.handlebars->25->193",
"default.handlebars->25->562"
]
@@ -27171,7 +27247,7 @@
"ru": "Учетные записи пользователей",
"zh-chs": "用戶帳號",
"xloc": [
- "default.handlebars->25->1673"
+ "default.handlebars->25->1700"
]
},
{
@@ -27383,7 +27459,7 @@
"ru": "Сессии пользователя",
"zh-chs": "用戶會話",
"xloc": [
- "default.handlebars->25->1690"
+ "default.handlebars->25->1717"
]
},
{
@@ -27572,7 +27648,7 @@
"xloc": [
"default.handlebars->25->1476",
"default.handlebars->25->1498",
- "default.handlebars->25->1689",
+ "default.handlebars->25->1716",
"default.handlebars->container->topbar->1->1->UsersSubMenuSpan->UsersSubMenu->1->0->UsersGeneral"
]
},
@@ -27590,7 +27666,7 @@
"ru": "Сессии пользователей",
"zh-chs": "用戶會話",
"xloc": [
- "default.handlebars->25->1677"
+ "default.handlebars->25->1704"
]
},
{
@@ -27773,7 +27849,7 @@
"ru": "Версия несовместима, пожалуйста, сначала обновите установку MeshCentral",
"zh-chs": "版本不兼容,请先升级您的MeshCentral安装",
"xloc": [
- "default.handlebars->25->1721"
+ "default.handlebars->25->1748"
]
},
{
@@ -27841,8 +27917,8 @@
"ru": "Просмотр журнала изменений",
"zh-chs": "查看变更日志",
"xloc": [
- "default.handlebars->25->1724",
- "default.handlebars->25->1726"
+ "default.handlebars->25->1751",
+ "default.handlebars->25->1753"
]
},
{
@@ -28100,8 +28176,8 @@
"ru": "Веб-сервер",
"zh-chs": "網絡服務器",
"xloc": [
- "default.handlebars->25->1710",
- "default.handlebars->25->1711"
+ "default.handlebars->25->1737",
+ "default.handlebars->25->1738"
]
},
{
@@ -28118,7 +28194,7 @@
"ru": "Запросы веб-сервера",
"zh-chs": "Web服務器請求",
"xloc": [
- "default.handlebars->25->1712"
+ "default.handlebars->25->1739"
]
},
{
@@ -28135,7 +28211,7 @@
"ru": "Ретранслятор Web Socket",
"zh-chs": "Web套接字中繼",
"xloc": [
- "default.handlebars->25->1713"
+ "default.handlebars->25->1740"
]
},
{
@@ -29200,7 +29276,7 @@
"ru": "\\\\'",
"zh-chs": "\\\\'",
"xloc": [
- "default.handlebars->25->1722"
+ "default.handlebars->25->1749"
]
},
{
@@ -29475,7 +29551,7 @@
"ru": "свободно",
"zh-chs": "自由",
"xloc": [
- "default.handlebars->25->1685"
+ "default.handlebars->25->1712"
]
},
{
@@ -29839,7 +29915,7 @@
"ru": "servertrace.csv",
"zh-chs": "servertrace.csv",
"xloc": [
- "default.handlebars->25->1720"
+ "default.handlebars->25->1747"
]
},
{
@@ -29892,7 +29968,7 @@
"ru": "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss",
"zh-chs": "時間,conn.agent,conn.users,conn.usersessions,conn.relaysession,conn.intelamt,mem.external,mem.heapused,mem.heaptotal,mem.rss",
"xloc": [
- "default.handlebars->25->1698"
+ "default.handlebars->25->1725"
]
},
{
@@ -29909,7 +29985,7 @@
"ru": "time, source, message",
"zh-chs": "時間,來源,訊息",
"xloc": [
- "default.handlebars->25->1719"
+ "default.handlebars->25->1746"
]
},
{
@@ -29940,7 +30016,7 @@
"ru": "всего",
"zh-chs": "總",
"xloc": [
- "default.handlebars->25->1686"
+ "default.handlebars->25->1713"
]
},
{
@@ -30094,7 +30170,8 @@
"ru": "{0} Kб",
"zh-chs": "{0} Kb",
"xloc": [
- "default.handlebars->25->1349"
+ "default.handlebars->25->1349",
+ "default.handlebars->25->1653"
]
},
{
@@ -30181,7 +30258,8 @@
"zh-chs": "{0}個字節",
"xloc": [
"default-mobile.handlebars->9->88",
- "default.handlebars->25->1359"
+ "default.handlebars->25->1359",
+ "default.handlebars->25->1668"
]
},
{
@@ -30796,4 +30874,4 @@
]
}
]
-}
+}
\ No newline at end of file
diff --git a/views/default.handlebars b/views/default.handlebars
index eb10d050..d2bb64d2 100644
--- a/views/default.handlebars
+++ b/views/default.handlebars
@@ -1047,12 +1047,13 @@
+
-
+
@@ -1489,6 +1490,8 @@
QS('p31events')['max-height'] = 'calc(100vh - ' + (50 + xh + xh2) + 'px)';
QS('p41events')['height'] = 'calc(100vh - ' + (48 + xh + xh2) + 'px)';
QS('p41events')['max-height'] = 'calc(100vh - ' + (48 + xh + xh2) + 'px)';
+ QS('p52recordings')['height'] = 'calc(100vh - ' + (48 + xh + xh2) + 'px)';
+ QS('p52recordings')['max-height'] = 'calc(100vh - ' + (48 + xh + xh2) + 'px)';
// We are looking at a single device, remove all the back buttons
if ('{{currentNode}}'.toLowerCase() != '') {
@@ -2094,6 +2097,11 @@
}
break;
}
+ case 'recordings': {
+ p52recordings = message.events;
+ updateRecordings();
+ break;
+ }
case 'getcookie': {
if (message.tag == 'clickonce') {
if (message.trustedCert == true) {
@@ -2278,6 +2286,10 @@
}
if (message.event.noact) break; // Take no action on this event
switch (message.event.action) {
+ case 'recording': {
+ if (p52recordings != null) { p52recordings.unshift(message.event); message.event.present = 1; updateRecordings(); }
+ break;
+ }
case 'userWebState': {
// New user web state, update the web page as needed
try {
@@ -6595,7 +6607,7 @@
function deskSaveImage() {
if (xxdialogMode || desktop == null || desktop.State != 3) return;
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);
- Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.jpg'); });
+ Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.png'); });
}
function deskDisplayInfo(sender, displays, selDisplay) {
@@ -11124,15 +11136,92 @@
var p52recordings = null;
function updateRecordings() {
- var x = 'Under construction';
+ // Display the users using the sorted list
+ var x = '', addHeader = true;
+ x += '' + "Session" + ' ' + nobreak("Start Time") + ' ' + "Duration" + ' ' + "Size";
+ if (p52recordings != null) {
+ var recdate = null;
+ for (var i in p52recordings) {
+ var rec = p52recordings[i], rect = new Date(rec.time), day = printDate(rect);
+ if (day != recdate) { recdate = day; x += '
';
QH('p52recordings', x);
}
- function openRecodringPlayer() {
- if (xxdialogMode) return;
- window.open(window.location.origin + '{{{domainurl}}}player.htm', 'meshcentral-deskplayer');
+ function addRecordingHtml(i, rec) {
+ var sessionLengthStr = '';
+ if (rec.lengthTime) { sessionLengthStr = pad2(Math.floor(rec.lengthTime / 3600)) + ':' + pad2(Math.floor((rec.lengthTime % 3600) / 60)) + ':' + pad2(Math.floor(rec.lengthTime % 60)); }
+ var sessionStartStr = printTime(new Date(rec.time));
+ if (rec.sessionStart) { sessionStartStr = printTime(new Date(rec.sessionStart)); }
+ var sessionSize = '';
+ if (rec.size) { sessionSize = format("{0} Kb", Math.round(rec.size / 1024)); }
+ var sessionName = '' + "Unknown" + ' ';
+ if (rec.name && rec.meshname) {
+ var recmesh = meshes[rec.meshid];
+ if (recmesh != null) {
+ sessionName = '' + EscapeHtml(rec.meshname) + ' - ' + EscapeHtml(rec.name) + ' ';
+ } else {
+ sessionName = EscapeHtml(rec.meshname) + ' - ' + EscapeHtml(rec.name);
+ }
+ }
+ if ((rec.userids != null) && (rec.userids.length > 0)) {
+ if (rec.userids.length > 1) {
+ sessionName += ' - ' + format('{0} users', rec.userids.length);
+ } else {
+ var ruser = null;
+ if (users != null) { ruser = users[rec.userids[0]]; }
+ if (ruser != null) {
+ sessionName += ' - ' + EscapeHtml(ruser.name) + ' ';
+ } else {
+ sessionName += ' - ' + EscapeHtml(rec.userids[0].split('/')[2]);
+ }
+ }
+ }
+ var actions = '', icon = 'm0';
+ if (rec.present == 1) { icon = 'm1'; actions = ' '; }
+ var x = '';
+ x += '';
+ x += '
';
+ x += '
';
+ x += '
';
+ x += '
' + actions + '
' + sessionName + '
' + sessionStartStr + ' ' + sessionLengthStr + ' ' + sessionSize;
+ return x;
}
+ function showRecordingDialog(event, i) {
+ if (xxdialogMode) return;
+ if ((event.target.tagName == 'IMG') || (event.target.tagName == 'A')) return;
+ var rec = p52recordings[i];
+ //console.log(rec);
+ var x = '';
+ if (rec.protocol) {
+ var protocolStr = "Unknown";
+ if (rec.protocol == 1) { protocolStr = "Terminal"; }
+ if (rec.protocol == 2) { protocolStr = "Desktop"; }
+ if (rec.protocol == 5) { protocolStr = "Files"; }
+ if (rec.protocol == 100) { protocolStr = "Intel AMT WSMAN"; }
+ if (rec.protocol == 101) { protocolStr = "Intel AMT Redirection"; }
+ x += addHtmlValue4("Protocol", protocolStr);
+ }
+ x += addHtmlValue4("Status", (rec.present == 1)?"Present on server":"Not on server");
+ if (rec.name) { x += addHtmlValue4("Device Name", EscapeHtml(rec.name)); }
+ if (rec.meshname) { x += addHtmlValue4("Device Group", EscapeHtml(rec.meshname)); }
+ if (rec.size) { x += addHtmlValue4("Size", format("{0} bytes", rec.size)); }
+ if (rec.startTime) { x += addHtmlValue4("Start Time", printTime(new Date(rec.startTime))); }
+ if (rec.time) { x += addHtmlValue4("End Time", printTime(new Date(rec.time))); }
+ if (rec.lengthTime) { x += addHtmlValue4("Duration", pad2(Math.floor(rec.lengthTime / 3600)) + ':' + pad2(Math.floor((rec.lengthTime % 3600) / 60)) + ':' + pad2(Math.floor(rec.lengthTime % 60))); }
+ if (rec.multiplex == true) { x += addHtmlValue4("Multiplexor", "Enabled"); }
+ if (rec.userids) { for (var i in rec.userids) { x += addHtmlValue4("User", rec.userids[i].split('/')[2]); } }
+ setDialogMode(2, "Recording Details", 9, null, x);
+ }
+
+ function refreshRecodings() { meshserver.send({ action: 'recordings', limit: 1000 }); }
+ function openRecodringPlayer() { if (!xxdialogMode) window.open(window.location.origin + '{{{domainurl}}}player.htm', 'meshcentral-deskplayer'); }
+ function p52updateInfo() { }
+
//
// FILE SELECTOR, DIALOG 3
//
@@ -11856,7 +11945,7 @@
if (x == 21) { p21updateMesh(); }
// Update Recordings
- if (x == 52) { updateRecordings(); }
+ if (x == 52) { if (p52recordings == null) { refreshRecodings(); } updateRecordings(); }
// Update the web page title
if ((currentNode) && (x >= 10) && (x < 20)) {
@@ -12223,6 +12312,7 @@
function addHtmlValue(t, v) { return ''; }
function addHtmlValue2(t, v) { return ''; }
function addHtmlValue3(t, v) { return '' + t + '
' + v + '
'; }
+ function addHtmlValue4(t, v) { return ''; }
function parseUriArgs() { var href = window.document.location.href; if (href.endsWith('#')) { href = href.substring(0, href.length - 1); } var name, r = {}, parsedUri = 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; }
function focusTextBox(x) { setTimeout(function(){ Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
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
@@ -12241,6 +12331,7 @@
function getOrderedList(objList, oname) { var r = []; for (var i in objList) { r.push(objList[i]); } r.sort(function(a, b) { var aa = a[oname].toLowerCase(), bb = b[oname].toLowerCase(); if (aa > bb) return 1; if (aa < bb) return -1; return 0; }); return r; }
function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); }
function nobreak(x) { return x.split(' ').join(' '); }
+ function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }