Improved UTF8 support on the server
Ylian Saint-Hilaire committed
Jul 6, 2018 at 10:13 UTC
b41eb7fb551f7ed24a3706092e43806e6210773e
14 files changed
+41
-111
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/MeshService-signed.exe
Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ
agents/MeshService.exe
Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ
agents/MeshService64-signed.exe
Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ
agents/MeshService64.exe
Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ
agents/meshcore.js
+2
-4
@@ -438,9 +438,7 @@ function createMeshCore(agent) {
438
} else {
439
// List all the files and folders in this path
440
if (reqpath == '') { reqpath = '/'; }
441
- var xpath = obj.path.join(reqpath, '*');
442
- var results = null;
443
-
441
+ var results = null, xpath = obj.path.join(reqpath, '*');
442
try { results = fs.readdirSync(xpath); } catch (e) { }
443
if (results != null) {
444
for (var i = 0; i < results.length; ++i) {
@@ -530,7 +528,7 @@ function createMeshCore(agent) {
528
function onTunnelSendOk() { sendConsoleText("Tunnel #" + this.index + " SendOK.", this.sessionid); }
529
function onTunnelData(data) {
530
//console.log("OnTunnelData");
533
- //sendConsoleText('OnTunnelData, ' + data.length + ', ' + typeof data + ', ' + data);
531
+ //sendConsoleText('OnTunnelData, ' + data.length + ', ' + typeof data + ', ' + data);
532
533
// If this is upload data, save it to file
534
if (this.httprequest.uploadFile) {
meshagent.js
+1
-1
@@ -411,7 +411,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
411
function processAgentData(msg) {
412
var str = msg.toString('utf8');
413
if (str[0] == '{') {
414
- try { command = JSON.parse(str) } catch (e) { console.log('Unable to parse JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
414
+ try { command = JSON.parse(str) } catch (e) { console.log('Unable to parse agent JSON (' + obj.remoteaddr + '): ' + str); return; } // If the command can't be parsed, ignore it.
415
switch (command.action) {
416
case 'msg':
417
{
meshrelay.js
+1
-1
@@ -182,7 +182,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
182
ws.on('message', function (data) {
183
//console.log(typeof data, data.length);
184
if (this.peer != null) {
185
- //if (typeof data == 'string') { console.log('Relay: ' + data); }
185
+ //if (typeof data == 'string') { console.log('Relay: ' + data); } else { console.log('Relay:' + data.length + ' byte(s)'); }
186
try { this.pause(); this.peer.send(data, ws.flushSink); } catch (e) { }
187
}
188
});
multiserver.js
+2
-2
@@ -173,7 +173,7 @@ module.exports.CreateMultiServer = function (parent, args) {
173
function processServerData(msg) {
174
var str = msg.toString('utf8');
175
if (str[0] == '{') {
176
- try { command = JSON.parse(str) } catch (e) { obj.parent.parent.debug(1, 'Unable to parse JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
176
+ try { command = JSON.parse(str) } catch (e) { obj.parent.parent.debug(1, 'Unable to parse server JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
177
if (command.action == 'info') {
178
if (obj.authenticated != 3) {
179
// We get the peer's serverid and database identifier.
@@ -337,7 +337,7 @@ module.exports.CreateMultiServer = function (parent, args) {
337
function processServerData(msg) {
338
var str = msg.toString('utf8');
339
if (str[0] == '{') {
340
- try { command = JSON.parse(str) } catch (e) { obj.parent.parent.debug(1, 'Unable to parse JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
340
+ try { command = JSON.parse(str) } catch (e) { obj.parent.parent.debug(1, 'Unable to parse server JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
341
if (command.action == 'info') {
342
if (obj.authenticated != 3) {
343
// We get the peer's serverid and database identifier.
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.1.8-k",
3
+ "version": "0.1.8-l",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
public/scripts/agent-redir-ws-0.1.0.js
+6
-1
@@ -166,7 +166,12 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
166
//console.log("xxOnSocketData", rstr2hex(data));
167
return obj.m.ProcessData(data);
168
}
169
-
169
+
170
+ obj.sendText = function (x) {
171
+ if (typeof x != 'string') { x = JSON.stringify(x); } // Turn into a string if needed
172
+ obj.send(encode_utf8(x)); // Encode UTF8 correctly
173
+ }
174
+
175
obj.send = function (x) {
176
//obj.debug("Agent Redir Send(" + obj.webRtcActive + ", " + x.length + "): " + rstr2hex(x));
177
//console.log("Agent Redir Send(" + obj.webRtcActive + ", " + x.length + "): " + ((typeof x == 'string')?x:rstr2hex(x)));
public/scripts/amt-terminal-0.0.2.js
+12
-87
@@ -35,14 +35,6 @@ var CreateAmtRemoteTerminal = function (divid) {
35
var _tscreen = [];
36
var _VTUNDERLINE = 1;
37
var _VTREVERSE = 2;
38
- // ###BEGIN###{Terminal-Enumation-All}
39
- var _utf8accumulator = 0;
40
- var _utf8accumulatorCount = 0;
41
- // ###END###{Terminal-Enumation-All}
42
- // ###BEGIN###{Terminal-Enumation-UTF8}
43
- var _utf8accumulator = 0;
44
- var _utf8accumulatorCount = 0;
45
- // ###END###{Terminal-Enumation-UTF8}
38
39
obj.Start = function () { }
40
@@ -60,7 +52,15 @@ var CreateAmtRemoteTerminal = function (divid) {
52
53
obj.xxStateChange = function(newstate) { }
54
63
- obj.ProcessData = function (str) { if (obj.capture != null) obj.capture += str; _ProcessVt100EscString(str); obj.TermDraw(); }
55
+ obj.ProcessData = function (str) {
56
+ // ###BEGIN###{Terminal-Enumation-UTF8}
57
+ //str = decode_utf8(str);
58
+ // ###END###{Terminal-Enumation-UTF8}
59
+ // ###BEGIN###{Terminal-Enumation-All}
60
+ if (obj.terminalEmulation == 0) { str = decode_utf8(str); }
61
+ // ###END###{Terminal-Enumation-All}
62
+ if (obj.capture != null) obj.capture += str; _ProcessVt100EscString(str); obj.TermDraw();
63
+ }
64
65
function _ProcessVt100EscString(str) { for (var i = 0; i < str.length; i++) _ProcessVt100EscChar(String.fromCharCode(str.charCodeAt(i)), str.charCodeAt(i)); }
66
@@ -363,48 +363,11 @@ var CreateAmtRemoteTerminal = function (divid) {
363
364
function _ProcessVt100Char(c) {
365
if (c == '\0' || c.charCodeAt() == 7) return; // Ignore null & bell
366
-
366
var ch = c.charCodeAt();
367
368
// ###BEGIN###{Terminal-Enumation-All}
369
// UTF8 Terminal
371
- if (obj.terminalEmulation == 0) {
372
- // VT100 - UTF-8 emulation
373
- var fallout = true;
374
- if ((ch & 0x80) == 0) {
375
- // Sub 127 char.
376
- _utf8accumulator = ch;
377
- _utf8accumulatorCount = 0;
378
- fallout = false;
379
- }
380
- else if ((ch & 0xE0) == 0xC0) {
381
- // 2 byte char
382
- _utf8accumulator = (ch & 0x1F);
383
- _utf8accumulatorCount = 1;
384
- fallout = true;
385
- }
386
- else if ((ch & 0xF0) == 0xE0) {
387
- // 3 byte char
388
- _utf8accumulator = (ch & 0x0F);
389
- _utf8accumulatorCount = 2;
390
- fallout = true;
391
- }
392
- else if ((ch & 0xC0) == 0x80) {
393
- if (_utf8accumulatorCount > 0) {
394
- _utf8accumulator = (_utf8accumulator << 6);
395
- _utf8accumulator += (ch & 0x3F);
396
- _utf8accumulatorCount--;
397
- fallout = (_utf8accumulatorCount != 0);
398
- }
399
- else {
400
- _utf8accumulator = 0;
401
- _utf8accumulatorCount = 0;
402
- fallout = true;
403
- }
404
- }
405
- if (fallout == true) return;
406
- c = String.fromCharCode(_utf8accumulator);
407
- } else if (obj.terminalEmulation == 1) {
370
+ if (obj.terminalEmulation == 1) {
371
// ANSI - Extended ASCII emulation.
372
if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicode[ch & 0x7F]); }
373
} else if (obj.terminalEmulation == 2) {
@@ -413,52 +376,14 @@ var CreateAmtRemoteTerminal = function (divid) {
376
}
377
// ###END###{Terminal-Enumation-All}
378
416
- // ###BEGIN###{Terminal-Enumation-UTF8}
417
- // VT100 - UTF-8 emulation
418
- var fallout = true;
419
- if ((ch & 0x80) == 0) {
420
- // Sub 127 char.
421
- _utf8accumulator = ch;
422
- _utf8accumulatorCount = 0;
423
- fallout = false;
424
- }
425
- else if ((ch & 0xE0) == 0xC0) {
426
- // 2 byte char
427
- _utf8accumulator = (ch & 0x1F);
428
- _utf8accumulatorCount = 1;
429
- fallout = true;
430
- }
431
- else if ((ch & 0xF0) == 0xE0) {
432
- // 3 byte char
433
- _utf8accumulator = (ch & 0x0F);
434
- _utf8accumulatorCount = 2;
435
- fallout = true;
436
- }
437
- else if ((ch & 0xC0) == 0x80) {
438
- if (_utf8accumulatorCount > 0) {
439
- _utf8accumulator = (_utf8accumulator << 6);
440
- _utf8accumulator += (ch & 0x3F);
441
- _utf8accumulatorCount--;
442
- fallout = (_utf8accumulatorCount != 0);
443
- }
444
- else {
445
- _utf8accumulator = 0;
446
- _utf8accumulatorCount = 0;
447
- fallout = true;
448
- }
449
- }
450
- if (fallout == true) return;
451
- c = String.fromCharCode(_utf8accumulator);
452
- // ###END###{Terminal-Enumation-UTF8}
453
-
379
// ###BEGIN###{Terminal-Enumation-ASCII}
380
// ANSI - Extended ASCII emulation.
456
- if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicode[ch & 0x7F]); }
381
+ //if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicode[ch & 0x7F]); }
382
// ###END###{Terminal-Enumation-ASCII}
383
384
// ###BEGIN###{Terminal-Enumation-Intel}
385
// ANSI - Intel Extended ASCII emulation.
461
- if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicodeIntel[ch & 0x7F]); }
386
+ //if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicodeIntel[ch & 0x7F]); }
387
// ###END###{Terminal-Enumation-Intel}
388
389
//if (ch < 32 && ch != 10 && ch != 13) alert(ch);
views/default.handlebars
+16
-14
@@ -2,7 +2,7 @@
2
<html dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
3
<head>
4
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
5
- <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
5
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
6
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
7
<meta name="apple-mobile-web-app-capable" content="yes" />
8
<meta name="format-detection" content="telephone=no" />
@@ -3767,6 +3767,7 @@
3767
terminal.onStateChanged = onTerminalStateChange;
3768
terminal.Start(terminalNode._id, 16994, '*', '*', 0);
3769
terminal.contype = 2;
3770
+ Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
3771
} else {
3772
// Setup a mesh agent terminal
3773
terminal = CreateAgentRedirect(meshserver, CreateAmtRemoteTerminal('Term'), serverPublicNamePort);
@@ -3777,6 +3778,8 @@
3778
terminal.onStateChanged = onTerminalStateChange;
3779
terminal.Start(terminalNode._id);
3780
terminal.contype = 1;
3781
+ terminal.m.terminalEmulation = 0;
3782
+ Q('id_ttypebutton').value = terminalEmulations[0];
3783
}
3784
} else {
3785
//QH('Term', '');
@@ -3860,7 +3863,7 @@
3863
break;
3864
case 3:
3865
p13targetpath = '';
3863
- files.send(JSON.stringify({ action: 'ls', reqid: 1, path: '' }));
3866
+ files.sendText({ action: 'ls', reqid: 1, path: '' });
3867
break;
3868
}
3869
}
@@ -3901,10 +3904,9 @@
3904
var p13filetreelocation = [];
3905
3906
function p13gotFiles(data) {
3904
- //console.log('p13gotFiles', data);
3907
if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p13gotDownloadBinaryData(data); return; }
3908
//console.log('p13gotFiles', data);
3907
- data = JSON.parse(data);
3909
+ data = JSON.parse(decode_utf8(data));
3910
if (data.action == 'download') { p13gotDownloadCommand(data); return; }
3911
data.path = data.path.replace(/\//g, "\\");
3912
if ((p13filetree != null) && (data.path == p13filetree.path)) {
@@ -3990,13 +3992,13 @@
3992
3993
function p13folderset(x) {
3994
p13targetpath = joinPaths(p13filetree.path, p13filetree.dir[x].n).split('\\').join('/');
3993
- files.send(JSON.stringify({ action: 'ls', reqid: 1, path: p13targetpath }));
3995
+ files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
3996
}
3997
3998
function p13folderup(x) {
3999
if (x == null) { p13filetreelocation.pop(); } else { while (p13filetreelocation.length > x) { p13filetreelocation.pop(); } }
4000
p13targetpath = p13filetreelocation.join('/');
3999
- files.send(JSON.stringify({ action: 'ls', reqid: 1, path: p13targetpath }));
4001
+ files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
4002
}
4003
4004
var p13sortorder;
@@ -4047,11 +4049,11 @@
4049
function p13getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
4050
function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
4051
function p13createfolder() { setDialogMode(2, "New Folder", 3, p13createfolderEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />'); focusTextBox('p13renameinput'); p13fileNameCheck(); }
4050
- function p13createfolderEx() { files.send(JSON.stringify({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value })); p13folderup(999); }
4052
+ function p13createfolderEx() { files.sendText({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value }); p13folderup(999); }
4053
function p13deletefile() { var cc = getFileSelCount(); setDialogMode(2, "Delete", 3, p13deletefileEx, (cc > 1)?('Delete ' + cc + ' selected items?'):('Delete selected item?')); }
4052
- 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.send(JSON.stringify({ action: 'rm', reqid: 1, path: p13filetreelocation.join('/'), delfiles: delfiles })); p13folderup(999); }
4054
+ 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 }); p13folderup(999); }
4055
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, "Rename", 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(); }
4054
- function p13renamefileEx(b, t) { t.newname = Q('p13renameinput').value; files.send(JSON.stringify(t)); p13folderup(999); }
4056
+ function p13renamefileEx(b, t) { t.newname = Q('p13renameinput').value; files.sendText(t); p13folderup(999); }
4057
function p13fileNameCheck(e) { var x = isFilenameValid(Q('p13renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e != null) && (e.keyCode == 13)) { dialogclose(1); } }
4058
function p13uploadFile() { setDialogMode(2, "Upload File", 3, p13uploadFileEx, '<input type=file name=files id=p13uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p13uploadinput\')" />'); updateUploadDialogOk('p13uploadinput'); }
4059
function p13uploadFileEx() { p13doUploadFiles(Q('p13uploadinput').files); }
@@ -4059,7 +4061,7 @@
4061
var p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0;
4062
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(); }
4063
function p13pasteFile() { var x = ''; if ((p13clipboard != null) && (p13clipboard.length > 0)) { x = 'Confim ' + (p13clipboardCut == 0?'copy':'move') + ' of ' + p13clipboard.length + ' entrie' + ((p13clipboard.length > 1)?'s':'') + ' to this location?' } setDialogMode(2, "Paste", 3, p13pasteFileEx, x); }
4062
- function p13pasteFileEx() { files.send(JSON.stringify({ 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(); } }
4064
+ 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(); } }
4065
function p13updateClipview() { var x = ''; if ((p13clipboard != null) && (p13clipboard.length > 0)) { x = 'Holding ' + p13clipboard.length + ' entrie' + ((p13clipboard.length > 1)?'s':'') + ' for ' + (p13clipboardCut == 0?'copy':'move') + ', <a onclick=p13clearClip() style=cursor:pointer>Clear</a>.' } QH('p13bottomstatus', x); p13setActions(); }
4066
function p13clearClip() { p13clipboard = null; p13clipboardFolder = null; p13clipboardCut = 0; p13updateClipview(); }
4067
@@ -4101,18 +4103,18 @@
4103
if (xxdialogMode || downloadFile || !files) return;
4104
downloadFile = { path: decodeURIComponent(x), file: decodeURIComponent(y), size: z, tsize: 0, data: '', state: 0, id: Math.random() }
4105
//console.log('p13downloadFileCancel', downloadFile);
4104
- files.send(JSON.stringify({ action: 'download', sub: 'start', id: downloadFile.id, path: downloadFile.path }));
4106
+ files.sendText({ action: 'download', sub: 'start', id: downloadFile.id, path: downloadFile.path });
4107
setDialogMode(2, "Download File", 10, p13downloadFileCancel, '<div>' + downloadFile.file + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
4108
}
4109
4110
// Called by the html page to cancel the download
4109
- function p13downloadFileCancel() { setDialogMode(0); files.send(JSON.stringify({ action: 'download', sub: 'cancel', id: downloadFile.id })); downloadFile = null; }
4111
+ function p13downloadFileCancel() { setDialogMode(0); files.sendText({ action: 'download', sub: 'cancel', id: downloadFile.id }); downloadFile = null; }
4112
4113
// Called by the transport when download control command is received
4114
function p13gotDownloadCommand(cmd) {
4115
//console.log('p13gotDownloadCommand', cmd);
4116
if ((downloadFile == null) || (cmd.id != downloadFile.id)) return;
4115
- if (cmd.sub == 'start') { downloadFile.state = 1; files.send(JSON.stringify({ action: 'download', sub: 'startack', id: downloadFile.id })); }
4117
+ if (cmd.sub == 'start') { downloadFile.state = 1; files.sendText({ action: 'download', sub: 'startack', id: downloadFile.id }); }
4118
else if (cmd.sub == 'cancel') { downloadFile = null; setDialogMode(0); }
4119
}
4120
@@ -4127,7 +4129,7 @@
4129
if ((ReadInt(data, 0) & 1) != 0) { // Check end flag
4130
saveAs(data2blob(downloadFile.data), downloadFile.file); downloadFile = null; setDialogMode(0); // Save the file
4131
} else {
4130
- files.send(JSON.stringify({ action: 'download', sub: 'ack', id: downloadFile.id })); // Send the ACK
4132
+ files.sendText({ action: 'download', sub: 'ack', id: downloadFile.id }); // Send the ACK
4133
}
4134
}
4135