Improved MeshCmd.

This commit is contained in:
Ylian Saint-Hilaire 2018-02-07 18:45:14 -08:00
parent 143d4cb647
commit 2a835d25cd
20 changed files with 174 additions and 121 deletions

File diff suppressed because one or more lines are too long

View File

@ -548,7 +548,8 @@ function createMeshCore(agent) {
this.prependListener('end', function () { this.httprequest.process.kill(); });
this.removeAllListeners('data');
this.on('data', onTunnelControlData);
//this.write('MeshCore Terminal Hello!1');
//this.write('MeshCore Terminal Hello');
if (process.platform != 'win32') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nclear\n"); }
}
if (this.httprequest.protocol == 2) {
// Remote desktop using native pipes

View File

@ -316,6 +316,18 @@ function lme_heci(options) {
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
}
break;
case APF_CHANNEL_OPEN_FAILURE:
var rChannelId = chunk.readUInt32BE(1);
var reasonCode = chunk.readUInt32BE(5);
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
this.sockets[rChannelId].end();
delete this.sockets[rChannelId];
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
delete this.insockets[rChannelId];
} else {
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_OPEN_FAILURE');
}
break;
case APF_CHANNEL_CLOSE:
var rChannelId = chunk.readUInt32BE(1);
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {

View File

@ -46,6 +46,7 @@ function amt_heci() {
});
});
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
function trim(x) { var y = x.indexOf('\0'); if (y >= 0) { return x.substring(0, y); } else { return x; } }
this.getCommand = function (chunk) {
var command = chunk.length == 0 ? (this._amt.rq.peekQueue().cmd | 0x800000) : chunk.readUInt32LE(4);
@ -216,6 +217,7 @@ function amt_heci() {
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
}, callback, optional);
};
this._getHashEntrySink = function (result, fn, opt, entries, handles) {
entries.push(result);
if (handles.length > 0) {
@ -229,7 +231,7 @@ function amt_heci() {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) {
if (header.Data.length == 68) { opt.unshift({ user: header.Data.slice(0, 34).toString(), pass: header.Data.slice(34, 67).toString(), raw: header.Data }); } else { opt.unshift(null); }
if (header.Data.length == 68) { opt.unshift({ user: trim(header.Data.slice(0, 34).toString()), pass: trim(header.Data.slice(34, 67).toString()), raw: header.Data }); } else { opt.unshift(null); }
fn.apply(this, opt);
}, callback, optional);
}

View File

@ -36,10 +36,10 @@ function ReadShortX(v, p) { return (v[p + 1] << 8) + v[p]; }
function ReadInt(v, p) { return (v[p] * 0x1000000) + (v[p + 1] << 16) + (v[p + 2] << 8) + v[p + 3]; } // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
function ReadSInt(v, p) { return (v[p] << 24) + (v[p + 1] << 16) + (v[p + 2] << 8) + v[p + 3]; }
function ReadIntX(v, p) { return (v[p + 3] * 0x1000000) + (v[p + 2] << 16) + (v[p + 1] << 8) + v[p]; }
function ShortToStr(v) { return ''; } // TODO
function ShortToStrX(v) { return ''; } // TODO
function IntToStr(v) { return ''; } // TODO
function IntToStrX(v) { return ''; } // TODO
function ShortToStr(v) { var b = Buffer.alloc(2); b.writeInt16BE(v); return b; }
function ShortToStrX(v) { var b = Buffer.alloc(2); b.writeInt16LE(v); return b; }
function IntToStr(v) { var b = Buffer.alloc(4); b.writeInt32BE(v); return b; }
function IntToStrX(v) { var b = Buffer.alloc(4); b.writeInt32LE(v); return b; }
function btoa(x) { return Buffer.from(x).toString('base64'); }
function atob(x) { var z = null; try { z = Buffer.from(x, 'base64').toString(); } catch (e) { console.log(e); } return z; }
function passwordcheck(p) { if (p.length < 8) return false; var upper = 0, lower = 0, number = 0, nonalpha = 0; for (var i in p) { var c = p.charCodeAt(i); if ((c > 64) && (c < 91)) { upper = 1; } else if ((c > 96) && (c < 123)) { lower = 1; } else if ((c > 47) && (c < 58)) { number = 1; } else { nonalpha = 1; } } return ((upper + lower + number + nonalpha) == 4); }
@ -47,20 +47,32 @@ function hex2rstr(x) { Buffer.from(x, 'hex').toString(); }
function rstr2hex(x) { Buffer.from(x).toString('hex'); }
function random() { return 0; } // TODO
function rstr_md5(x) { return null; } // TODO
function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
var httpErrorTable = {
200: 'OK',
401: 'Authentication Error',
408: 'Timeout Error',
601: 'WSMAN Parsing Error',
602: 'Unable to parse HTTP response header',
603: 'Unexpected HTTP enum response',
604: 'Unexpected HTTP pull response',
998: 'Invalid TLS certificate'
}
// Setup the script state
module.exports.setup = function(binary, startvars) {
var obj = { startvars: startvars };
var obj = { startvars: startvars, onCompleted: null };
obj.wsRetryCall = null;
obj.wsRetryArgs = null;
obj.wsRetryTimes = null;
if (binary.length < 6) { console.error('Invalid script length'); return null; } // Script must have at least 6 byte header
if (ReadInt(binary, 0) != 0x247D2945) { console.error('Invalid binary script'); return null; } // Check the script magic header
if (ReadShort(binary, 4) > 1) { console.error('Unsupported script version'); return null; } // Check the script version
obj.script = binary.slice(6);
// obj.onStep;
// obj.onConsole;
// Reset the script to the start
obj.reset = function (stepspeed) {
console.log('reset');
obj.stop();
obj.ip = 0;
obj.variables = startvars;
@ -69,15 +81,13 @@ module.exports.setup = function(binary, startvars) {
// Start the script
obj.start = function (stepspeed) {
console.log('start');
obj.stop();
if (stepspeed == null) { obj.stepspeed = 100; } else { obj.stepspeed = stepspeed; }
if (stepspeed == null) { obj.stepspeed = 10; } else { obj.stepspeed = stepspeed; }
if (obj.stepspeed > 0) { obj.timer = setInterval(function () { obj.step() }, obj.stepspeed); }
}
// Stop the script
obj.stop = function () {
console.log('stop');
if (obj.timer != null) { clearInterval(obj.timer); }
obj.timer = null;
obj.stepspeed = 0;
@ -91,7 +101,6 @@ module.exports.setup = function(binary, startvars) {
// Run the script one step forward
obj.step = function () {
console.log('step');
if (obj.state != 1) return;
if (obj.ip < obj.script.length) {
var cmdid = ReadShort(obj.script, obj.ip);
@ -99,18 +108,20 @@ module.exports.setup = function(binary, startvars) {
var argcount = ReadShort(obj.script, obj.ip + 4);
var argptr = obj.ip + 6;
var args = [];
// Clear all temp variables (This is optional)
for (var i in obj.variables) { if (i.startsWith('__')) { delete obj.variables[i]; } }
// Loop on each argument, moving forward by the argument length each time
for (var i = 0; i < argcount; i++) {
var arglen = ReadShort(obj.script, argptr);
var argval = obj.script.substring(argptr + 2, argptr + 2 + arglen); // <----------- Problem area
var argtyp = argval.charCodeAt(0);
argval = argval.substring(1);
var argval = obj.script.slice(argptr + 2, argptr + 2 + arglen);
var argtyp = argval[0];
argval = argval.slice(1);
if (argtyp < 2) {
// Get the value and replace all {var} with variable values
argval = argval.toString();
//console.log(argval);
while (argval.split("{").length > 1) { var t = argval.split("{").pop().split("}").shift(); argval = argval.replace('{' + t + '}', obj.getVar(t)); }
if (argtyp == 1) { obj.variables['__' + i] = decodeURI(argval); argval = '__' + i; } // If argtyp is 1, this is a literal. Store in temp variable.
args.push(argval);
@ -122,6 +133,8 @@ module.exports.setup = function(binary, startvars) {
argptr += (2 + arglen);
}
//console.log('CMD: ' + cmdid, args.join(', '));
// Move instruction pointer forward by command size
obj.ip += cmdlen;
@ -130,13 +143,18 @@ module.exports.setup = function(binary, startvars) {
for (var i = 0; i < 10; i++) { argsval.push(obj.getVar(args[i])); }
var storeInArg0;
//console.log('VAR: ' + JSON.stringify(obj.variables));
//console.log('CMD: ' + cmdid, argsval.join(', '));
try {
if (cmdid < 10000) {
// Lets run the actual command
//console.log(cmdid);
switch (cmdid) {
case 0: // nop
break;
case 1: // jump(label) or jump(label, a, compare, b)
//console.log('JUMP ' + argsval[1] + ' ' + argsval[2] + ' ' + argsval[3]);
if (argsval[2]) {
if (
(argsval[2] == '<' && argsval[1] < argsval[3]) ||
@ -145,16 +163,24 @@ module.exports.setup = function(binary, startvars) {
(argsval[2] == '=' && argsval[1] == argsval[3]) ||
(argsval[2] == '>=' && argsval[1] >= argsval[3]) ||
(argsval[2] == '>' && argsval[1] > argsval[3])
) { obj.ip = argsval[0]; }
) {
obj.ip = argsval[0];
}
} else {
obj.ip = argsval[0]; // Set the instruction pointer to the new location in the script
}
break;
case 2: // set(variable, value)
if (args[1] == undefined) delete obj.variables[args[0]]; else obj.setVar(args[0], argsval[1]);
if (args[1] == undefined) { if (obj.variables[args[0]]) { delete obj.variables[args[0]]; } } else {
//console.log('SET ' + args[0] + ' TO ' + argsval[1]);
obj.setVar(args[0], argsval[1]);
}
break;
case 3: // print(message)
if (obj.onConsole) { obj.onConsole(obj.toString(argsval[0]), obj); } else { console.log(obj.toString(argsval[0])); }
var v = obj.toString(argsval[0]);
if (v.indexOf('INFO: ') == 0) { v = v.substring(6); }
if (v.indexOf('SUCCESS: ') == 0) { v = v.substring(9); }
if (obj.onConsole) { obj.onConsole(v, obj); } else { console.log(v); }
// Q(obj.consoleid).value += () + '\n'); Q(obj.console).scrollTop = Q(obj.console).scrollHeight;
break;
case 4: // dialog(title, content, buttons)
@ -178,7 +204,7 @@ module.exports.setup = function(binary, startvars) {
storeInArg0 = argsval[1].join(argsval[2]);
break;
case 10: // length(variable_dest, variable_src)
storeInArg0 = argsval[1].length;
if (argsval[1] == null) { storeInArg0 = 0; } else { storeInArg0 = argsval[1].length; }
break;
case 11: // jsonparse(variable_dest, json)
storeInArg0 = JSON.parse(argsval[1]);
@ -228,15 +254,11 @@ module.exports.setup = function(binary, startvars) {
obj.amtstack.UnSubscribe(argsval[0], obj.xxWsmanReturn, obj, 0, argsval[1]);
break;
case 24: // readchar(str, pos)
console.log(argsval[1], argsval[2], argsval[1].charCodeAt(argsval[2]));
//console.log('readchar', argsval[1], argsval[2], argsval[1].charCodeAt(argsval[2]));
storeInArg0 = argsval[1].charCodeAt(argsval[2]);
break;
case 25: // signWithDummyCa
// ###BEGIN###{Certificates}
obj.state = 2;
// DERKey, xxCaPrivateKey, certattributes, issuerattributes
amtcert_signWithCaKey(argsval[0], null, argsval[1], { 'CN': 'Untrusted Root Certificate' }, obj.xxSignWithDummyCaReturn);
// ###END###{Certificates}
// Not supported
break;
default: {
obj.state = 9;
@ -246,23 +268,24 @@ module.exports.setup = function(binary, startvars) {
} else {
if (cmdid < 20000) {
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
//storeInArg0 = script_functionTableX2[cmdid - 10000](argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]);
storeInArg0 = script_functionTableX2[cmdid - 10000](argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]);
} else {
//if (cmdid == 20009) { console.log('--------------------------------------'); }
// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
//if (script_functionTableX3 && script_functionTableX3[cmdid - 20000]) {
// storeInArg0 = script_functionTableX3[cmdid - 20000](obj, argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]); // Note that optional calls start with "obj" as first argument.
//}
}
}
if (storeInArg0 != undefined) obj.setVar(args[0], storeInArg0);
} catch (e) {
if (typeof e == 'object') { e = e.message; }
obj.setVar('_exception', e);
console.log('EXCEPTION: ' + e);
}
}
if (obj.state == 1 && obj.ip >= obj.script.length) { obj.state = 0; obj.stop(); }
if (obj.state == 1 && obj.ip >= obj.script.length) { obj.state = 0; obj.stop(); if (obj.onCompleted) { obj.onCompleted(); } }
if (obj.onStep) obj.onStep(obj);
return obj;
}
@ -274,28 +297,7 @@ module.exports.setup = function(binary, startvars) {
if (obj.onStep) obj.onStep(obj);
}
// ###BEGIN###{**ClosureAdvancedMode}
obj.xxWsmanReturnFix = function (x) {
if (!x || x == null) return;
if (x.Header) { x['Header'] = x.Header; delete x.Header; }
if (x.Body) { x['Body'] = x.Body; delete x.Body; }
if (x.Responses) { x['Responses'] = x.Responses; delete x.Responses; }
if (x.Response) { x['Response'] = x.Response; delete x.Response; }
if (x.ReturnValueStr) { x['ReturnValueStr'] = x.ReturnValueStr; delete x.ReturnValueStr; }
}
// ###END###{**ClosureAdvancedMode}
obj.xxWsmanReturn = function (stack, name, responses, status) {
// ###BEGIN###{**ClosureAdvancedMode}
// This is required when Google Closure is used
if (responses) {
obj.xxWsmanReturnFix(responses);
for (var i in responses) {
obj.xxWsmanReturnFix(responses[i]);
for (var j in responses[i]) { obj.xxWsmanReturnFix(responses[i][j]); }
}
}
// ###END###{**ClosureAdvancedMode}
obj.setVar(name, responses);
obj.setVar('wsman_result', status);
obj.setVar('wsman_result_str', ((httpErrorTable[status]) ? (httpErrorTable[status]) : ('Error #' + status)));
@ -303,14 +305,6 @@ module.exports.setup = function(binary, startvars) {
if (obj.onStep) obj.onStep(obj);
}
// ###BEGIN###{Certificates}
obj.xxSignWithDummyCaReturn = function (cert) {
obj.setVar('signed_cert', btoa(_arrayBufferToString(cert)));
obj.state = 1;
if (obj.onStep) obj.onStep(obj);
}
// ###END###{Certificates}
obj.toString = function (x) { if (typeof x == 'object') return JSON.stringify(x); return x; }
obj.reset();

View File

@ -70,7 +70,7 @@ function CreateWsmanComm(host, port, user, pass, tls, extra) {
req.on('response', function (response) {
//console.log('Response: ' + response.statusCode);
if (response.statusCode != 200) {
console.log('ERR:' + JSON.stringify(response));
//console.log('ERR:' + JSON.stringify(response));
obj.gotNextMessagesError({ status: response.statusCode }, 'error', null, [postdata, callback, tag]);
} else {
response.acc = '';
@ -80,8 +80,7 @@ function CreateWsmanComm(host, port, user, pass, tls, extra) {
});
// Send POST body, this work with binary.
req.write(postdata);
req.end();
req.end(postdata);
obj.ActiveAjaxCount++;
return req;
}

View File

@ -181,8 +181,7 @@ function WsmanStackCreateService(CreateWsmanComm, host, port, user, pass, tls, e
for (var i = 0; i < selectorArray.length; i++) {
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
}
}
else {
} else {
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
}
result += '</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>';

View File

@ -356,6 +356,7 @@ function AmtStackCreateService(wsmanStack) {
obj.IPS_HostBasedSetupService_UpgradeClientToAdmin = function (McNonce, SigningAlgorithm, DigitalSignature, callback_func) { obj.Exec("IPS_HostBasedSetupService", "UpgradeClientToAdmin", { "McNonce": McNonce, "SigningAlgorithm": SigningAlgorithm, "DigitalSignature": DigitalSignature }, callback_func); }
obj.IPS_HostBasedSetupService_DisableClientControlMode = function (_method_dummy, callback_func) { obj.Exec("IPS_HostBasedSetupService", "DisableClientControlMode", { "_method_dummy": _method_dummy }, callback_func); }
obj.IPS_KVMRedirectionSettingData_TerminateSession = function (callback_func) { obj.Exec("IPS_KVMRedirectionSettingData", "TerminateSession", {}, callback_func); }
obj.IPS_KVMRedirectionSettingData_DataChannelRead = function (callback_func) { obj.Exec("IPS_KVMRedirectionSettingData", "DataChannelRead", {}, callback_func); }
obj.IPS_OptInService_StartOptIn = function (callback_func) { obj.Exec("IPS_OptInService", "StartOptIn", {}, callback_func); }
obj.IPS_OptInService_CancelOptIn = function (callback_func) { obj.Exec("IPS_OptInService", "CancelOptIn", {}, callback_func); }
obj.IPS_OptInService_SendOptInCode = function (OptInCode, callback_func) { obj.Exec("IPS_OptInService", "SendOptInCode", { "OptInCode": OptInCode }, callback_func); }

View File

@ -316,9 +316,21 @@ function lme_heci(options) {
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
}
break;
case APF_CHANNEL_OPEN_FAILURE:
var rChannelId = chunk.readUInt32BE(1);
var reasonCode = chunk.readUInt32BE(5);
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
this.sockets[rChannelId].end();
delete this.sockets[rChannelId];
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
delete this.insockets[rChannelId];
} else {
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_OPEN_FAILURE');
}
break;
case APF_CHANNEL_CLOSE:
var rChannelId = chunk.readUInt32BE(1);
if (this.sockets[rChannelId] != undefined) {
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
this.sockets[rChannelId].end();
var amtId = this.sockets[rChannelId].lme.amtId;
var buffer = Buffer.alloc(5);
@ -498,6 +510,7 @@ var lmsEvents = {
"iAMT0052-0": "User Notification Alert - KVM session requested.",
"iAMT0052-1": "User Notification Alert - KVM session started.",
"iAMT0052-2": "User Notification Alert - KVM session stopped.",
"iAMT0052-3": "User Notification Alert - KVM data channel.",
"iAMT0053": "User Notification Alert - RCS notification.",
"iAMT0053-50": "User Notification Alert - RCS notification (HW button pressed. Connection initiated automatically).",
"iAMT0053-52": "User Notification Alert - RCS notification (HW button pressed. Connection wasn't initiated automatically).",
@ -512,7 +525,7 @@ var lmsEvents = {
"iAMT0057": "User Notification Alert - Network State change notification.",
"iAMT0058": "User Notification Alert - Remote Access change notification.",
"iAMT0058-1": "User Notification Alert - Remote Access change notification - tunnel is closed.",
//"iAMT0058-1": "User Notification Alert - Remote Access change notification - tunnel is open.",
//"iAMT0058-1": "User Notification Alert - Remote Access change notification - tunnel is open.", // TODO
"iAMT0059": "User Notification Alert - KVM enabled event.",
"iAMT0059-0": "User Notification Alert - KVM enabled event - KVM disabled.",
"iAMT0059-1": "User Notification Alert - KVM enabled event - KVM enabled (both from MEBx and PTNI).",

View File

@ -46,6 +46,7 @@ function amt_heci() {
});
});
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
function trim(x) { var y = x.indexOf('\0'); if (y >= 0) { return x.substring(0, y); } else { return x; } }
this.getCommand = function (chunk) {
var command = chunk.length == 0 ? (this._amt.rq.peekQueue().cmd | 0x800000) : chunk.readUInt32LE(4);
@ -216,6 +217,7 @@ function amt_heci() {
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
}, callback, optional);
};
this._getHashEntrySink = function (result, fn, opt, entries, handles) {
entries.push(result);
if (handles.length > 0) {
@ -229,7 +231,7 @@ function amt_heci() {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) {
if (header.Data.length == 68) { opt.unshift({ user: header.Data.slice(0, 34).toString(), pass: header.Data.slice(34, 67).toString(), raw: header.Data }); } else { opt.unshift(null); }
if (header.Data.length == 68) { opt.unshift({ user: trim(header.Data.slice(0, 34).toString()), pass: trim(header.Data.slice(34, 67).toString()), raw: header.Data }); } else { opt.unshift(null); }
fn.apply(this, opt);
}, callback, optional);
}

View File

@ -229,7 +229,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
});
// If error, do nothing
ws.on('error', function (err) { console.log(err); });
ws.on('error', function (err) { console.log('AGENT WSERR: ' + err); });
// If the mesh agent web socket is closed, clean up.
ws.on('close', function (req) { obj.parent.parent.debug(1, 'Agent disconnect ' + obj.nodeid + ' (' + obj.remoteaddr + ')'); obj.close(0); });

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.1.4-b",
"version": "0.1.4-f",
"keywords": [
"Remote Management",
"Intel AMT",

File diff suppressed because one or more lines are too long

View File

@ -99,11 +99,8 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
if (obj.webrtc != null) {
obj.webchannel = obj.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
obj.webchannel.onmessage = function (event) { obj.xxOnMessage({ data: event.data }); };
obj.webchannel.onopen = function () {
obj.webRtcActive = true;
performWebRtcSwitch();
};
obj.webchannel.onclose = function (event) { /*console.log('WebRTC close');*/ obj.Stop(); }
obj.webchannel.onopen = function () { obj.webRtcActive = true; performWebRtcSwitch(); };
obj.webchannel.onclose = function (event) { /*console.log('WebRTC close');*/ if (obj.webRtcActive) { obj.Stop(); } }
obj.webrtc.onicecandidate = function (e) {
if (e.candidate == null) {
obj.socket.send(JSON.stringify(obj.webrtcoffer)); // End of candidates, send the offer

View File

@ -17,6 +17,8 @@ var CreateAmtRemoteTerminal = function (divid) {
obj.width = 80; // 80 or 100
obj.height = 25; // 25 or 30
obj.lineFeed = '\r\n';
var _Terminal_CellHeight = 21;
var _Terminal_CellWidth = 13;
var _TermColors = ['000000', 'BB0000', '00BB00', 'BBBB00', '0000BB', 'BB00BB', '00BBBB', 'BBBBBB', '555555', 'FF5555', '55FF55', 'FFFF55', '5555FF', 'FF55FF', '55FFFF', 'FFFFFF'];
@ -574,7 +576,7 @@ var CreateAmtRemoteTerminal = function (divid) {
obj.TermHandleKeys = function (e) {
if (!e.ctrlKey) {
if (e.which == 127) obj.TermSendKey(8);
else if (e.which == 13) obj.TermSendKeys("\r\n");
else if (e.which == 13) obj.TermSendKeys(obj.lineFeed);
else if (e.which != 0) obj.TermSendKey(e.which);
return false;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -663,7 +663,7 @@
// Check if we are in debug mode
args = parseUriArgs();
debugmode = (args.debug == 1);
//attemptWebRTC = (args.webrtc == 1);
if (args.webrtc) { attemptWebRTC = (args.webrtc == 1); }
QV('p13AutoConnect', debugmode); // Files
QV('autoconnectbutton2', debugmode); // Terminal
QV('autoconnectbutton1', debugmode); // Desktop
@ -3226,6 +3226,7 @@
terminal = CreateAgentRedirect(meshserver, CreateAmtRemoteTerminal('Term'), serverPublicNamePort);
terminal.debugmode = debugmode;
terminal.m.debugmode = debugmode;
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
terminal.attemptWebRTC = attemptWebRTC;
terminal.onStateChanged = onTerminalStateChange;
terminal.Start(terminalNode._id);

View File

@ -1104,7 +1104,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
});
// If error, do nothing
ws.on('error', function (err) { console.log(err); });
ws.on('error', function (err) { console.log('WEBSERVER WSERR1: ' + err); });
// If the web socket is closed, close the associated TCP connection.
ws.on('close', function (req) {
@ -1156,7 +1156,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
});
// If error, do nothing
ws.on('error', function (err) { console.log(err); });
ws.on('error', function (err) { console.log('WEBSERVER WSERR2: ' + err); });
// If the web socket is closed, close the associated TCP connection.
ws.on('close', function (req) {
@ -1244,7 +1244,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
});
// If error, do nothing
ws.on('error', function (err) { console.log(err); });
ws.on('error', function (err) { console.log('WEBSERVER WSERR3: ' + err); });
// If closed, do nothing
ws.on('close', function (req) { });