Merge pull request #751 from TotallyNotElite/terminalimprovements
Various (linux) terminal improvements
This commit is contained in:
commit
bf7dfce58f
|
@ -1184,8 +1184,7 @@ function createMeshCore(agent) {
|
|||
}
|
||||
});
|
||||
}
|
||||
} catch (e)
|
||||
{
|
||||
} catch (e) {
|
||||
MeshServerLog('Failed to start remote terminal session, ' + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);
|
||||
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() }));
|
||||
this.end();
|
||||
|
@ -1202,15 +1201,33 @@ function createMeshCore(agent) {
|
|||
{
|
||||
try
|
||||
{
|
||||
if (fs.existsSync('/usr/bin/python') && fs.existsSync('/bin/bash')) {
|
||||
this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write("export TERM='xterm'\nalias ls='ls --color=auto'\nclear\n"); }
|
||||
} else if (fs.existsSync('/bin/bash')) {
|
||||
this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); }
|
||||
var bash = fs.existsSync('/bin/bash') ? '/bin/bash' : false;
|
||||
var sh = fs.existsSync('/bin/sh') ? '/bin/sh' : false;
|
||||
var script = fs.existsSync('/usr/bin/script') ? '/usr/bin/script' : false;
|
||||
var python = fs.existsSync('/usr/bin/python') ? '/usr/bin/python' : false;
|
||||
var shell = bash || sh;
|
||||
|
||||
var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } };
|
||||
var setupcommands = " alias ls='ls --color=auto'\n";
|
||||
if (shell == sh) setupcommands += "stty erase ^H\n"
|
||||
|
||||
if (script && shell) {
|
||||
this.httprequest.process = childProcess.execFile(script, ['script', '--return', '--quiet', '-c', '"' + shell + '"', '/dev/null'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); }
|
||||
} else if (python && shell) {
|
||||
this.httprequest.process = childProcess.execFile(python, ['python', '-c', 'import pty; pty.spawn(["' + shell + '"])'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); }
|
||||
} else if (bash) {
|
||||
options.type = childProcess.SpawnTypes.TERM;
|
||||
this.httprequest.process = childProcess.execFile(bash, ['bash', '-i'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); }
|
||||
} else if (sh) {
|
||||
options.type = childProcess.SpawnTypes.TERM;
|
||||
this.httprequest.process = childProcess.execFile(sh, ['sh'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands + "PS1='$ '\n"); }
|
||||
} else {
|
||||
this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8)?require('user-sessions').consoleUid():null }); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); }
|
||||
MeshServerLog("Failed to start remote terminal session, no shell found");
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
MeshServerLog("Failed to start remote terminal session, " + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);
|
||||
|
@ -2967,4 +2984,4 @@ try {
|
|||
}
|
||||
} catch (ex) {
|
||||
require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": "uncaughtException2: " + ex });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -768,13 +768,20 @@ function createMeshCore(agent) {
|
|||
//sendConsoleText('setClip: ' + JSON.stringify(data));
|
||||
if (typeof data.data == 'string') {
|
||||
MeshServerLog('Setting clipboard content, ' + data.data.length + ' byte(s)', data);
|
||||
if (typeof data.data == 'string') {
|
||||
if (require('MeshAgent').isService) { require('clipboard').dispatchWrite(data.data); } else { require("clipboard")(data.data); } // Set the clipboard
|
||||
mesh.SendCommand({ "action": "msg", "type": "setclip", "sessionid": data.sessionid, "success": true });
|
||||
}
|
||||
if (require('MeshAgent').isService) { require('clipboard').dispatchWrite(data.data); } else { require("clipboard")(data.data); } // Set the clipboard
|
||||
mesh.SendCommand({ "action": "msg", "type": "setclip", "sessionid": data.sessionid, "success": true });
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'userSessions': {
|
||||
// Send back current user sessions list, this is Windows only.
|
||||
//sendConsoleText('userSessions: ' + JSON.stringify(data));
|
||||
if (process.platform != 'win32') break;
|
||||
var p = require('user-sessions').enumerateUsers();
|
||||
p.sessionid = data.sessionid;
|
||||
p.then(function (u) { mesh.SendCommand({ 'action': 'msg', 'type': 'userSessions', 'sessionid': u.sessionid, 'data': u }); });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Unknown action, ignore it.
|
||||
break;
|
||||
|
@ -1088,6 +1095,7 @@ function createMeshCore(agent) {
|
|||
// Handle tunnel data
|
||||
if (this.httprequest.protocol == 0) { // 1 = Terminal (admin), 2 = Desktop, 5 = Files, 6 = PowerShell (admin), 7 = Plugin Data Exchange, 8 = Terminal (user), 9 = PowerShell (user)
|
||||
// Take a look at the protocol
|
||||
if ((data.length > 3) && (data[0] == '{')) { onTunnelControlData(data, this); return; }
|
||||
this.httprequest.protocol = parseInt(data);
|
||||
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
|
||||
if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6) || (this.httprequest.protocol == 8) || (this.httprequest.protocol == 9)) {
|
||||
|
@ -1143,29 +1151,40 @@ function createMeshCore(agent) {
|
|||
else
|
||||
{
|
||||
// Logged in user
|
||||
var username = require('user-sessions').getUsername(require('user-sessions').consoleUid());
|
||||
if (require('win-virtual-terminal').supported)
|
||||
var userPromise = require('user-sessions').enumerateUsers();
|
||||
userPromise.that = this;
|
||||
userPromise.then(function (u)
|
||||
{
|
||||
// ConPTY PseudoTerminal
|
||||
this.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (this.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } });
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy Terminal
|
||||
this.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-terminal', script: getJSModule('win-terminal') }], launch: { module: 'win-terminal', method: (this.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } });
|
||||
}
|
||||
this.httprequest._dispatcher.ws = this;
|
||||
this.httprequest._dispatcher.on('connection', function (c)
|
||||
{
|
||||
console.log('client connected');
|
||||
this.ws._term = c;
|
||||
c.pipe(this.ws, { dataTypeSkip: 1 });
|
||||
this.ws.pipe(c, { dataTypeSkip: 1, end: false });
|
||||
this.ws.prependListener('end', function () { this.httprequest._term.end(function () { console.log("Terminal was closed"); }); });
|
||||
});
|
||||
var that = this.that;
|
||||
if (u.Active.length > 0)
|
||||
{
|
||||
var username = u.Active[0].Username;
|
||||
if (require('win-virtual-terminal').supported)
|
||||
{
|
||||
// ConPTY PseudoTerminal
|
||||
that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } });
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy Terminal
|
||||
that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-terminal', script: getJSModule('win-terminal') }], launch: { module: 'win-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } });
|
||||
}
|
||||
that.httprequest._dispatcher.ws = that;
|
||||
that.httprequest._dispatcher.on('connection', function (c)
|
||||
{
|
||||
console.log('client connected');
|
||||
this.ws._term = c;
|
||||
c.pipe(this.ws, { dataTypeSkip: 1 });
|
||||
this.ws.pipe(c, { dataTypeSkip: 1, end: false });
|
||||
this.ws.prependListener('end', function ()
|
||||
{
|
||||
if (this.httprequest._term) { this.httprequest._term.end(function () { console.log("Terminal was closed"); }); }
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e)
|
||||
{
|
||||
} catch (e) {
|
||||
MeshServerLog('Failed to start remote terminal session, ' + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);
|
||||
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() }));
|
||||
this.end();
|
||||
|
@ -1182,15 +1201,33 @@ function createMeshCore(agent) {
|
|||
{
|
||||
try
|
||||
{
|
||||
if (fs.existsSync('/usr/bin/python') && fs.existsSync('/bin/bash')) {
|
||||
this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write("export TERM='xterm'\nalias ls='ls --color=auto'\nclear\n"); }
|
||||
} else if (fs.existsSync('/bin/bash')) {
|
||||
this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); }
|
||||
var bash = fs.existsSync('/bin/bash') ? '/bin/bash' : false;
|
||||
var sh = fs.existsSync('/bin/sh') ? '/bin/sh' : false;
|
||||
var script = fs.existsSync('/usr/bin/script') ? '/usr/bin/script' : false;
|
||||
var python = fs.existsSync('/usr/bin/python') ? '/usr/bin/python' : false;
|
||||
var shell = bash || sh;
|
||||
|
||||
var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } };
|
||||
var setupcommands = " alias ls='ls --color=auto'\n";
|
||||
if (shell == sh) setupcommands += "stty erase ^H\n"
|
||||
|
||||
if (script && shell) {
|
||||
this.httprequest.process = childProcess.execFile(script, ['script', '--return', '--quiet', '-c', '"' + shell + '"', '/dev/null'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); }
|
||||
} else if (python && shell) {
|
||||
this.httprequest.process = childProcess.execFile(python, ['python', '-c', 'import pty; pty.spawn(["' + shell + '"])'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); }
|
||||
} else if (bash) {
|
||||
options.type = childProcess.SpawnTypes.TERM;
|
||||
this.httprequest.process = childProcess.execFile(bash, ['bash', '-i'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); }
|
||||
} else if (sh) {
|
||||
options.type = childProcess.SpawnTypes.TERM;
|
||||
this.httprequest.process = childProcess.execFile(sh, ['sh'], options); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands + "PS1='$ '\n"); }
|
||||
} else {
|
||||
this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8)?require('user-sessions').consoleUid():null }); // Start as active user
|
||||
if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); }
|
||||
MeshServerLog("Failed to start remote terminal session, no shell found");
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
MeshServerLog("Failed to start remote terminal session, " + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);
|
||||
|
@ -1257,8 +1294,13 @@ function createMeshCore(agent) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Look for a TSID
|
||||
var tsid = null;
|
||||
if ((this.httprequest.xoptions != null) && (typeof this.httprequest.xoptions.tsid == 'number')) { tsid = this.httprequest.xoptions.tsid; }
|
||||
require('MeshAgent')._tsid = tsid;
|
||||
|
||||
// Remote desktop using native pipes
|
||||
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(require('MeshAgent')._tsid == null ? undefined : require('MeshAgent')._tsid), tunnel: this };
|
||||
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(tsid), tunnel: this };
|
||||
this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
|
||||
this.desktop = this.httprequest.desktop;
|
||||
|
||||
|
@ -1739,7 +1781,12 @@ function createMeshCore(agent) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (obj.type == 'close') {
|
||||
if (obj.type == 'options') {
|
||||
// These are additional connection options passed in the control channel.
|
||||
//sendConsoleText('options: ' + JSON.stringify(obj));
|
||||
delete obj.type;
|
||||
ws.httprequest.xoptions = obj;
|
||||
} else if (obj.type == 'close') {
|
||||
// We received the close on the websocket
|
||||
//sendConsoleText('Tunnel #' + ws.tunnel.index + ' WebSocket control close');
|
||||
try { ws.close(); } catch (e) { }
|
||||
|
@ -1871,7 +1918,7 @@ function createMeshCore(agent) {
|
|||
var response = null;
|
||||
switch (cmd) {
|
||||
case 'help': { // Displays available commands
|
||||
var fin = '', f = '', availcommands = 'help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper';
|
||||
var fin = '', f = '', availcommands = 'version,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper';
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
availcommands += ',safemode,wpfhwacceleration';
|
||||
|
@ -1885,6 +1932,9 @@ function createMeshCore(agent) {
|
|||
response = 'Available commands: \r\n' + fin + '.';
|
||||
break;
|
||||
}
|
||||
case 'version':
|
||||
response = 'Mesh Agent Version: ' + process.versions.meshAgent;
|
||||
break;
|
||||
case 'wpfhwacceleration':
|
||||
if (process.platform != 'win32') { throw ('wpfhwacceleration setting is only supported on Windows'); }
|
||||
if (args['_'].length != 1)
|
||||
|
@ -1979,10 +2029,7 @@ function createMeshCore(agent) {
|
|||
var v = [];
|
||||
for(var i in u)
|
||||
{
|
||||
if(u[i].State == 'Active' || u[i].State == 'Connected')
|
||||
{
|
||||
v.push({ tsid: i, type: u[i].StationName, user: u[i].Username });
|
||||
}
|
||||
if(u[i].State == 'Active') { v.push({ tsid: i, type: u[i].StationName, user: u[i].Username, domain: u[i].Domain }); }
|
||||
}
|
||||
sendConsoleText(JSON.stringify(v, null, 1), this.sessionid);
|
||||
});
|
||||
|
@ -2937,4 +2984,4 @@ try {
|
|||
}
|
||||
} catch (ex) {
|
||||
require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": "uncaughtException2: " + ex });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ var CreateAmtRemoteTerminal = function (divid, options) {
|
|||
}
|
||||
|
||||
obj.xxStateChange = function (newstate) {
|
||||
if ((newstate == 3) && (options != null) && (options.xterm == true)) { obj.TermSendKeys('stty rows ' + obj.height + ' cols ' + obj.width + '\nclear\n'); }
|
||||
if ((newstate == 3) && (options != null) && (options.xterm == true)) { obj.TermSendKeys(' stty rows ' + obj.height + ' cols ' + obj.width + '\n clear\n'); }
|
||||
}
|
||||
|
||||
obj.ProcessData = function (str) {
|
||||
|
@ -807,4 +807,4 @@ var CreateAmtRemoteTerminal = function (divid, options) {
|
|||
obj.DivElement.style['height'] = '';
|
||||
if ((options != null) && (options.width != null) && (options.height != null)) { obj.Init(options.width, options.height); } else { obj.Init(); }
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2930,7 +2930,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
archive.on('error', function (err) { throw err; });
|
||||
|
||||
// Set the archive name
|
||||
res.attachment(domain.title + '-Backup-' + new Date().toLocaleDateString().replace('/', '-').replace('/', '-') + '.zip');
|
||||
res.attachment((domain.title ? domain.title : "Meshcentral") + '-Backup-' + new Date().toLocaleDateString().replace('/', '-').replace('/', '-') + '.zip');
|
||||
|
||||
// Pipe archive data to the file
|
||||
archive.pipe(res);
|
||||
|
|
Loading…
Reference in New Issue