From f57a40eeb30606864fc71856cd813046af9cebd5 Mon Sep 17 00:00:00 2001 From: Paris Date: Fri, 5 Aug 2016 08:46:49 +0000 Subject: [PATCH 1/3] First batch of improvements to demo - Used fetch tentatively - Implemented resize endpoint - Create terminals with the appropriate size --- demo/app.js | 54 +++++++++++++++++++++++++++++++++++++++++----------- demo/main.js | 32 ++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/demo/app.js b/demo/app.js index 8661cc62..83195e62 100644 --- a/demo/app.js +++ b/demo/app.js @@ -4,6 +4,9 @@ var expressWs = require('express-ws')(app); var os = require('os'); var pty = require('pty.js'); +var terminals = {}, + logs = {}; + app.use('/src', express.static(__dirname + '/../src')); app.use('/addons', express.static(__dirname + '/../addons')); @@ -19,17 +22,43 @@ app.get('/main.js', function(req, res){ res.sendFile(__dirname + '/main.js'); }); -app.ws('/bash', function(ws, req) { - /** - * Open bash terminal and attach it - */ - var term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], { - name: 'xterm-color', - cols: 80, - rows: 24, - cwd: process.env.PWD, - env: process.env +app.post('/terminals', function (req, res) { + var cols = parseInt(req.query.cols), + rows = parseInt(req.query.rows), + term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], { + name: 'xterm-color', + cols: cols || 80, + rows: rows || 24, + cwd: process.env.PWD, + env: process.env + }); + + console.log('Created terminal with PID: ' + term.pid); + terminals[term.pid] = term; + logs[term.pid] = ''; + term.on('data', function(data) { + logs[term.pid] += data; }); + res.send(term.pid.toString()); + res.end(); +}); + +app.post('/terminals/:pid/size', function (req, res) { + var pid = parseInt(req.params.pid), + cols = parseInt(req.query.cols), + rows = parseInt(req.query.rows), + term = terminals[pid]; + + term.resize(cols, rows); + console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.'); + res.end(); +}); + +app.ws('/terminals/:pid', function (ws, req) { + var term = terminals[parseInt(req.params.pid)]; + console.log('Connected to terminal ' + term.pid); + ws.send(logs[term.pid]); + term.on('data', function(data) { try { ws.send(data); @@ -41,8 +70,11 @@ app.ws('/bash', function(ws, req) { term.write(msg); }); ws.on('close', function () { - console.log('close'); process.kill(term.pid); + console.log('Closed terminal ' + term.pid); + // Clean things up + delete terminals[term.pid]; + delete logs[term.pid]; }); }); diff --git a/demo/main.js b/demo/main.js index 59bdacdd..b46716bf 100644 --- a/demo/main.js +++ b/demo/main.js @@ -1,7 +1,8 @@ var term, protocol, socketURL, - socket; + socket, + pid; var terminalContainer = document.getElementById('terminal-container'); var optionElements = { @@ -13,22 +14,39 @@ optionElements.cursorBlink.addEventListener('change', createTerminal); createTerminal(); function createTerminal() { + // Clean terminal while (terminalContainer.children.length) { terminalContainer.removeChild(terminalContainer.children[0]); } term = new Terminal({ cursorBlink: optionElements.cursorBlink.checked }); + term.on('resize', function (size) { + if (!pid) { + return; + } + }); protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; - socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/bash'; - socket = new WebSocket(socketURL); + socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/'; term.open(terminalContainer); - term.fit(); - socket.onopen = runRealTerminal; - socket.onclose = runFakeTerminal; - socket.onerror = runFakeTerminal; + var initialGeometry = term.proposeGeometry(), + cols = initialGeometry.cols, + rows = initialGeometry.rows; + + fetch('/terminals?cols=' + cols + '&rows=' + rows, {method: 'POST'}).then(function (res) { + res.text().then(function (pid) { + window.pid = pid; + socketURL += pid; + socket = new WebSocket(socketURL); + socket.onopen = runRealTerminal; + socket.onclose = runFakeTerminal; + socket.onerror = runFakeTerminal; + }); + }); + + term.fit(); } From 0f8fc63a5e5a27a83101ba9bea3f127b0465a7f6 Mon Sep 17 00:00:00 2001 From: Paris Date: Fri, 5 Aug 2016 12:28:22 +0300 Subject: [PATCH 2/3] First functional resizing demo Fix #211 --- demo/index.html | 14 ++++++++++++++ demo/main.js | 47 +++++++++++++++++++++++++++++++++++++---------- demo/style.css | 4 ++-- 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/demo/index.html b/demo/index.html index ff10a5cb..74c954d6 100644 --- a/demo/index.html +++ b/demo/index.html @@ -5,6 +5,7 @@ + @@ -18,6 +19,19 @@

Options

+
+

Size

+
+
+ + +
+
+ + +
+
+
diff --git a/demo/main.js b/demo/main.js index b46716bf..86fbd314 100644 --- a/demo/main.js +++ b/demo/main.js @@ -2,12 +2,30 @@ var term, protocol, socketURL, socket, - pid; + pid, + charWidth, + charHeight; -var terminalContainer = document.getElementById('terminal-container'); -var optionElements = { - cursorBlink: document.querySelector('#option-cursor-blink') -}; +var terminalContainer = document.getElementById('terminal-container'), + optionElements = { + cursorBlink: document.querySelector('#option-cursor-blink') + }, + colsElement = document.getElementById('cols'), + rowsElement = document.getElementById('rows'); + +function setTerminalSize () { + var cols = parseInt(colsElement.value), + rows = parseInt(rowsElement.value), + width = (cols * charWidth).toString() + 'px', + height = (rows * charHeight).toString() + 'px'; + + terminalContainer.style.width = width; + terminalContainer.style.height = height; + term.resize(cols, rows); +} + +colsElement.addEventListener('change', setTerminalSize); +rowsElement.addEventListener('change', setTerminalSize); optionElements.cursorBlink.addEventListener('change', createTerminal); @@ -25,17 +43,30 @@ function createTerminal() { if (!pid) { return; } + var cols = size.cols, + rows = size.rows, + url = '/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows; + + fetch(url, {method: 'POST'}); }); protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/'; term.open(terminalContainer); + term.fit(); var initialGeometry = term.proposeGeometry(), cols = initialGeometry.cols, rows = initialGeometry.rows; + colsElement.value = cols; + rowsElement.value = rows; + fetch('/terminals?cols=' + cols + '&rows=' + rows, {method: 'POST'}).then(function (res) { + + charWidth = Math.ceil(term.element.offsetWidth / cols); + charHeight = Math.ceil(term.element.offsetHeight / rows); + res.text().then(function (pid) { window.pid = pid; socketURL += pid; @@ -45,8 +76,6 @@ function createTerminal() { socket.onerror = runFakeTerminal; }); }); - - term.fit(); } @@ -82,9 +111,7 @@ function runFakeTerminal() { if (ev.keyCode == 13) { term.prompt(); } else if (ev.keyCode == 8) { - /* - * Do not delete the prompt - */ + // Do not delete the prompt if (term.x > 2) { term.write('\b \b'); } diff --git a/demo/style.css b/demo/style.css index c93ca74f..2f05e309 100644 --- a/demo/style.css +++ b/demo/style.css @@ -9,8 +9,8 @@ h1 { } #terminal-container { - width: 960px; - height: 600px; + width: 800px; + height: 450px; margin: 0 auto; padding: 2px; } From 5ce012bdac100631657f5cf3d9b4a8b6f7e74a00 Mon Sep 17 00:00:00 2001 From: Paris Date: Mon, 8 Aug 2016 16:28:29 +0300 Subject: [PATCH 3/3] Add notice about security risks --- demo/index.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/demo/index.html b/demo/index.html index 74c954d6..1d9a2189 100644 --- a/demo/index.html +++ b/demo/index.html @@ -12,9 +12,7 @@ -

- xterm.js: xterm, in the browser -

+

xterm.js: xterm, in the browser

Options

@@ -33,6 +31,7 @@
+

Attention: The demo should be used only for evaluation of xterm.js and not be exposed or shared to public, as this will introduce security risks for the host.