Skip to content

Commit

Permalink
Terminal cursor navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
veniware committed May 9, 2024
1 parent b0440b4 commit 0b44728
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Protest/Front/deviceview.js
Original file line number Diff line number Diff line change
Expand Up @@ -2454,7 +2454,7 @@ class DeviceView extends View {
snmpCheckBox.checked = false;
snmpCheckBox.disabled = true; //TODO:
grid.appendChild(snmpCheckBox);
this.AddCheckBoxLabel(grid, snmpCheckBox, "SNMP").style.gridArea = "3 / 2";;
this.AddCheckBoxLabel(grid, snmpCheckBox, "SNMP").style.gridArea = "3 / 2";

const snmpInput = document.createElement("select");
snmpInput.style.marginLeft = "0";
Expand Down
1 change: 1 addition & 0 deletions Protest/Front/terminal.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 3px;
height: 20px;
border-radius: 1px;
Expand Down
123 changes: 103 additions & 20 deletions Protest/Front/terminal.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ class Terminal extends Window {
};

this.ws.onmessage = event=> {
console.log("received", event.data)
this.HandleMessage(event.data);
};

Expand All @@ -107,6 +106,7 @@ class Terminal extends Window {
case "Enter" : this.ws.send("\n\r"); break;
case "Tab" : this.ws.send("\t"); break;
case "Backspace" : this.ws.send("\x08"); break;
case "Delete" : this.ws.send("\x1b[3~"); break;
case "ArrowLeft" : this.ws.send("\x1b[D"); break;
case "ArrowRight": this.ws.send("\x1b[C"); break;
case "ArrowUp" : this.ws.send("\x1b[A"); break;
Expand All @@ -122,10 +122,7 @@ class Terminal extends Window {
for (let i=0; i<data.length; i++) {
let char = this.chars[`${this.cursor.x},${this.cursor.y}`];

if (char) {
//
}
else {
if (!char) {
char = document.createElement("span");
char.style.left = `${this.cursor.x * Terminal.CURSOR_WIDTH}px`;
char.style.top = `${this.cursor.y * Terminal.CURSOR_HEIGHT}px`;
Expand All @@ -147,22 +144,22 @@ class Terminal extends Window {
this.cursor.x = Math.max(0, this.cursor.x - 1);
break;

case "\x09": break; //tab
//case "\x09": break; //tab
case "\x0a": //lf
char.innerHTML = "<br>";
this.cursor.x = 0;
this.cursor.y++;
break;

case "\x0b": break; //vertical tab
case "\x0c": break; //new page
case "\x0d": break; //cr
//case "\x0b": break; //vertical tab
//case "\x0c": break; //new page
//case "\x0d": break; //cr

case "\x1b": //esc
i += this.HandleEscSequence(data, i);
i += this.HandleEscSequence(data, i)-1;
break;

case "\x7f": break; //delete
//case "\x7f": break; //delete

default:
char.textContent = data[i];
Expand All @@ -179,15 +176,17 @@ class Terminal extends Window {
if (data[index+1] === "[" || data[index+1] === "\x9b") {
return this.HandleCSI(data, index);
}
else if (data[index+1] === "P" || data[index+1] === "\x90") {

if (data[index+1] === "P" || data[index+1] === "\x90") {
return this.HandleDCS(data, index);
}
else if (data[index+1] === "]" || data[index+1] === "\x9d") {

if (data[index+1] === "]" || data[index+1] === "\x9d") {
return this.HandleOSC(data, index);
}
else {
return 1;
}

console.warn("Unknown escape sequence: " + data[index+1]);
return 1;
}

HandleCSI(data, index) { //Control Sequence Introducer
Expand Down Expand Up @@ -224,6 +223,52 @@ class Terminal extends Window {
else if (data[i] === "G") { //moves cursor to column n
this.cursor.x = n;
}
else if (data[i] === "P") { //delete n chars and shift the following chars left
let i = this.cursor.x+n;
let sequence = "";
while (this.chars[`${i++},${this.cursor.y}`]) {
sequence += this.chars[`${i-1},${this.cursor.y}`].textContent;
}

i = this.cursor.x;
let key = `${i},${this.cursor.y}`;
while (this.chars[key]) {
this.content.removeChild(this.chars[key]);
delete this.chars[key];

key = `${++i},${this.cursor.y}`;
}

for (i=0; i<sequence.length; i++) {
const char = document.createElement("span");
char.style.left = `${(this.cursor.x + i) * Terminal.CURSOR_WIDTH}px`;
char.style.top = `${this.cursor.y * Terminal.CURSOR_HEIGHT}px`;
this.content.appendChild(char);
this.chars[`${this.cursor.x + i},${this.cursor.y}`] = char;
}
}
else if (data[i] === "J") { //erase screen
if (n === 0) { //erase from cursor until end
console.warn(`Unknown CSI: 0J`);
return 4;
}
else if (n === 1) { //erase from cursor to beginning of screen
console.warn(`Unknown CSI: 1J`);
return 4;
}
else if (n === 2) { //clear entire screen
console.log("clear screen");
this.ClearScreen();
return 4;
}
else if (n === 3) { //erase saved lines
console.warn(`Unknown CSI: 3J`);
return 4;
}
}
else {
console.warn(`Unknown CSI: ${data[i]} with n=${n}`);
}

return i - index + 1;
}
Expand All @@ -234,21 +279,59 @@ class Terminal extends Window {
return 3;
}

if (data[index+2] === "K") { //erase in line
this.cursor.x = Math.max(0, this.cursor.x-1);
let char = this.chars[`${this.cursor.x},${this.cursor.y}`];
if (char) char.textContent = "";
if (data[index+2] === "K") {
this.ClearLineFromCursorToEnd();
return 3;
}

console.warn("Unknown CSI: " + data[index+2]);
return 2;
}

HandleDCS(data, index) { //Device Control String
if (index >= data.length) return 2;

console.warn("Unknown DCS: " + data[index+2]);
return 2;
}

HandleOSC(data, index) { //Operating System Command
if (index >= data.length) return 2;

console.warn("Unknown OCS: " + data[index+2]);
return 2;
}

ClearLine() {
const w = this.GetScreenWidth();
for (let i=0; i<w; i++) {
const key = `${i},${this.cursor.y}`;
if (!this.chars[key]) continue;
this.content.removeChild(this.chars[key]);
delete this.chars[key];
}

this.cursor = {x:0, y:this.cursor.y};
}

ClearLineFromCursorToEnd() {
const w = this.GetScreenWidth();
for (let i=this.cursor.x; i<w; i++) {
const key = `${i},${this.cursor.y}`;
if (!this.chars[key]) continue;
console.log(this.chars[key]);
this.content.removeChild(this.chars[key]);
delete this.chars[key];
}

this.cursor = {x:0, y:this.cursor.y};
}

ClearScreen() {
this.chars = {};
this.content.innerHTML = "";
this.content.appendChild(this.cursorElement);
//this.cursor = {x:0, y:0};
}

GetScreenWidth() {
Expand Down
2 changes: 1 addition & 1 deletion Protest/Misc/Update.cs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ public static byte[] TorFormDataHandler(HttpListenerContext ctx) {
}

//private static string GetFieldName(string part) {
// return part[(part.IndexOf("name=\"") + 6)..].Split('"')[0]; ;
// return part[(part.IndexOf("name=\"") + 6)..].Split('"')[0];
//}

private static readonly string[] separator = new[] { "\r\n\r\n" };
Expand Down
9 changes: 4 additions & 5 deletions Protest/Protocols/Telnet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,13 @@ public static async void WebSocketHandler2(HttpListenerContext ctx) {
_ = int.TryParse(split[1], out port);
}

TcpClient telnet = new TcpClient(host, port); ;
TcpClient telnet = new TcpClient(host, port);
NetworkStream stream = telnet.GetStream();

Logger.Action(username, $"Establish telnet connection to {host}:{port}");

//await WsWriteText(ws, $"connected to {host}:{port}\n\r");

await Task.Delay(400);

Task daemon = new Task(async ()=>{
while (ws.State == WebSocketState.Open && telnet.Connected) { //host read loop
byte[] buffer = new byte[2048];
Expand All @@ -73,6 +71,9 @@ public static async void WebSocketHandler2(HttpListenerContext ctx) {
responseData = Encoding.UTF8.GetString(buffer, 0, bytes);
Console.Write(responseData);
}
catch (System.IO.IOException) {
return;
}
catch {
return;
}
Expand All @@ -89,7 +90,6 @@ public static async void WebSocketHandler2(HttpListenerContext ctx) {
daemon.Start();

while (ws.State == WebSocketState.Open && telnet.Connected) { //host write loop
await Task.Delay(400);
byte[] buff = new byte[2048];

WebSocketReceiveResult receiveResult = await ws.ReceiveAsync(new ArraySegment<byte>(buff), CancellationToken.None);
Expand Down Expand Up @@ -190,7 +190,6 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {
NetworkStream stream = telnet.GetStream();

wsToServer = new Thread(async () => {
await Task.Delay(500);
while (ws.State == WebSocketState.Open) { //ws to server loop

byte[] buff = new byte[2048];
Expand Down
33 changes: 25 additions & 8 deletions Protest/Tasks/Lifeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,16 @@ private static bool DoPing(string host) {
pingMutexes[host] = mutex;
}

//Console.WriteLine($"{host} \t - {mutex.GetHashCode()}");

lock (mutex) {
using FileStream stream = new FileStream($"{dir}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);
using BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, false);
writer.Write(((DateTimeOffset)now).ToUnixTimeMilliseconds()); //8 bytes
writer.Write(rtt); //2 bytes

writer.Dispose();
stream.Dispose();
}
return rtt >= 0;
}
Expand Down Expand Up @@ -276,50 +281,59 @@ private static void DoWmi(string file, string host) {
if (cpuUsage != 255) {
string dirCpu = $"{Data.DIR_LIFELINE}{Data.DELIMITER}cpu{Data.DELIMITER}{file}";
if (!Directory.Exists(dirCpu)) Directory.CreateDirectory(dirCpu);
using FileStream cpuStream = new FileStream($"{dirCpu}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);

try {
using BinaryWriter writer = new BinaryWriter(cpuStream, Encoding.UTF8, false);
using FileStream stream = new FileStream($"{dirCpu}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);
using BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, false);
writer.Write(((DateTimeOffset)now).ToUnixTimeMilliseconds()); //8 bytes
writer.Write((byte)(100 - cpuUsage)); //1 byte

writer.Dispose();
stream.Dispose();
}
catch { }
}

if (diskUsage != 255) {
string dirDiskUsage = $"{Data.DIR_LIFELINE}{Data.DELIMITER}diskusage{Data.DELIMITER}{file}";
if (!Directory.Exists(dirDiskUsage)) Directory.CreateDirectory(dirDiskUsage);
using FileStream diskStream = new FileStream($"{dirDiskUsage}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);

try {
using BinaryWriter writer = new BinaryWriter(diskStream, Encoding.UTF8, false);
using FileStream stream = new FileStream($"{dirDiskUsage}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);
using BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, false);
writer.Write(((DateTimeOffset)now).ToUnixTimeMilliseconds()); //8 bytes
writer.Write((byte)(100 - diskUsage)); //1 byte

writer.Dispose();
stream.Dispose();
}
catch { }
}

if (memoryTotal > 0) {
string dirMemory = $"{Data.DIR_LIFELINE}{Data.DELIMITER}memory{Data.DELIMITER}{file}";
if (!Directory.Exists(dirMemory)) Directory.CreateDirectory(dirMemory);
using FileStream memoryStream = new FileStream($"{dirMemory}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);

try {
using BinaryWriter writer = new BinaryWriter(memoryStream, Encoding.UTF8, false);
using FileStream stream = new FileStream($"{dirMemory}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);
using BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, false);
writer.Write(((DateTimeOffset)now).ToUnixTimeMilliseconds()); //8 bytes
writer.Write(memoryTotal - memoryFree); //8 bytes
writer.Write(memoryTotal); //8 bytes

writer.Dispose();
stream.Dispose();
}
catch { }
}

if (diskCaption.Count > 0) {
string dirDisk = $"{Data.DIR_LIFELINE}{Data.DELIMITER}disk{Data.DELIMITER}{file}";
if (!Directory.Exists(dirDisk)) Directory.CreateDirectory(dirDisk);
using FileStream diskStream = new FileStream($"{dirDisk}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);

try {
using BinaryWriter writer = new BinaryWriter(diskStream, Encoding.UTF8, false);
using FileStream stream = new FileStream($"{dirDisk}{Data.DELIMITER}{now:yyyyMM}", FileMode.Append);
using BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, false);
writer.Write(((DateTimeOffset)now).ToUnixTimeMilliseconds()); //8 bytes
writer.Write(diskCaption.Count); //4 bytes

Expand All @@ -328,6 +342,9 @@ private static void DoWmi(string file, string host) {
writer.Write(diskTotal[i] - diskFree[i]); //8 bytes
writer.Write(diskTotal[i]); //8 bytes
}

writer.Dispose();
stream.Dispose();
}
catch { }
}
Expand Down

0 comments on commit 0b44728

Please sign in to comment.