added boolean conversion from url strings, continuing browser resize additions
This commit is contained in:
parent
15945f0d16
commit
d456a180d9
8 changed files with 66 additions and 12 deletions
|
@ -5,6 +5,10 @@ Mostly client (browser) related changes in this release
|
||||||
### Added
|
### Added
|
||||||
- Menu system
|
- Menu system
|
||||||
- Fontawesome icons
|
- Fontawesome icons
|
||||||
|
- Resizing browser window sends resize events to terminal container as well as SSH session (pty)
|
||||||
|
- Adding terminal options
|
||||||
|
- New serverside (nodejs) terminal configuration options (cursorBlink, scrollback, tabStopWidth)
|
||||||
|
- Logging of MRH session (unassigned if not present)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Updated xterm.js to 3.0.2
|
- Updated xterm.js to 3.0.2
|
||||||
|
|
|
@ -80,6 +80,12 @@ docker run --name webssh2 -d -p 2222:2222 webssh2
|
||||||
|
|
||||||
* **ssh.keepaliveCountMax** - _integer_ - How many consecutive, unanswered SSH-level keepalive packets that can be sent to the server before disconnection (similar to OpenSSH's ServerAliveCountMax config option). **Default:** 10.
|
* **ssh.keepaliveCountMax** - _integer_ - How many consecutive, unanswered SSH-level keepalive packets that can be sent to the server before disconnection (similar to OpenSSH's ServerAliveCountMax config option). **Default:** 10.
|
||||||
|
|
||||||
|
* **terminal.cursorBlink** - _boolean_ - Cursor blinks (true), does not (false) **Default:** true.
|
||||||
|
|
||||||
|
* **terminal.scrollback** - _integer_ - Lines in the scrollback buffer. **Default:** 10000.
|
||||||
|
|
||||||
|
* **terminal.tabStopWidth** - _integer_ - Tab stops at _n_ characters **Default:** 8.
|
||||||
|
|
||||||
* **useminified** - _boolean_ - Choose between ./public/client-full.htm (false/non-minified) or ./public/client-min.htm (true/minified js), defaults to false (non-minified version)
|
* **useminified** - _boolean_ - Choose between ./public/client-full.htm (false/non-minified) or ./public/client-min.htm (true/minified js), defaults to false (non-minified version)
|
||||||
|
|
||||||
* **header.text** - _string_ - Specify header text, defaults to `My Header` but may also be set to `null`. When set to `null` no header bar will be displayed on the client.
|
* **header.text** - _string_ - Specify header text, defaults to `My Header` but may also be set to `null`. When set to `null` no header bar will be displayed on the client.
|
||||||
|
|
9
app.js
9
app.js
|
@ -48,8 +48,13 @@ app.get('/ssh/host/:host?', function (req, res, next) {
|
||||||
keepaliveCountMax: config.ssh.keepaliveCountMax,
|
keepaliveCountMax: config.ssh.keepaliveCountMax,
|
||||||
term: (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) &&
|
term: (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) &&
|
||||||
req.query.sshterm) || config.ssh.term,
|
req.query.sshterm) || config.ssh.term,
|
||||||
allowreplay: validator.isBoolean(req.headers.allowreplay + '') || false,
|
terminal: {
|
||||||
sessionID: validator.isAlphanumeric(req.headers.sessionID + '') || false,
|
cursorBlink: (validator.isBoolean(req.query.cursorBlink + '') ? myutil.parseBool(req.query.cursorBlink) : config.terminal.cursorBlink),
|
||||||
|
scrollback: config.terminal.scrollback,
|
||||||
|
tabStopWidth: config.terminal.tabStopWidth
|
||||||
|
},
|
||||||
|
allowreplay: (validator.isBoolean(req.headers.allowreplay + '') ? myutil.parseBool(req.headers.allowreplay) : false),
|
||||||
|
MRH_Session: validator.isAlphanumeric(req.headers.lastMRH_Session + '') && req.headers.lastMRH_Session || 'none',
|
||||||
serverlog: {
|
serverlog: {
|
||||||
client: config.serverlog.client || false,
|
client: config.serverlog.client || false,
|
||||||
server: config.serverlog.server || false
|
server: config.serverlog.server || false
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
"keepaliveInterval": 120000,
|
"keepaliveInterval": 120000,
|
||||||
"keepaliveCountMax": 10
|
"keepaliveCountMax": 10
|
||||||
},
|
},
|
||||||
|
"terminal": {
|
||||||
|
"cursorBlink": true,
|
||||||
|
"scrollback": 10000,
|
||||||
|
"tabStopWidth": 8
|
||||||
|
},
|
||||||
"useminified": false,
|
"useminified": false,
|
||||||
"header": {
|
"header": {
|
||||||
"text": null,
|
"text": null,
|
||||||
|
|
|
@ -125,15 +125,20 @@ logBtn.addEventListener('click', toggleLog)
|
||||||
logBtn.style.color = '#000'
|
logBtn.style.color = '#000'
|
||||||
|
|
||||||
var terminalContainer = document.getElementById('terminal-container')
|
var terminalContainer = document.getElementById('terminal-container')
|
||||||
|
|
||||||
var term = new __WEBPACK_IMPORTED_MODULE_1__node_modules_xterm_dist_xterm__({
|
|
||||||
cursorBlink: true
|
|
||||||
})
|
|
||||||
var socket, termid // eslint-disable-line
|
var socket, termid // eslint-disable-line
|
||||||
|
var term = new __WEBPACK_IMPORTED_MODULE_1__node_modules_xterm_dist_xterm__()
|
||||||
term.open(terminalContainer)
|
term.open(terminalContainer)
|
||||||
term.focus()
|
term.focus()
|
||||||
term.fit()
|
term.fit()
|
||||||
|
|
||||||
|
document.body.onresize = function () {
|
||||||
|
term.fit()
|
||||||
|
term.resize(term.cols, term.rows)
|
||||||
|
console.log('document resize...')
|
||||||
|
console.log('geometry cols: ' + term.cols + ' rows: ' + term.rows)
|
||||||
|
socket.emit('resize', {cols: term.cols, rows: term.rows})
|
||||||
|
}
|
||||||
|
|
||||||
if (document.location.pathname) {
|
if (document.location.pathname) {
|
||||||
var parts = document.location.pathname.split('/')
|
var parts = document.location.pathname.split('/')
|
||||||
var base = parts.slice(0, parts.length - 1).join('/') + '/'
|
var base = parts.slice(0, parts.length - 1).join('/') + '/'
|
||||||
|
@ -149,6 +154,12 @@ socket.on('connect', function () {
|
||||||
socket.emit('geometry', term.cols, term.rows)
|
socket.emit('geometry', term.cols, term.rows)
|
||||||
console.log('geometry cols: ' + term.cols + ' rows: ' + term.rows)
|
console.log('geometry cols: ' + term.cols + ' rows: ' + term.rows)
|
||||||
})
|
})
|
||||||
|
socket.on('setTerminalOpts', function (data) {
|
||||||
|
console.log('terminalOpts: ' + JSON.stringify(data))
|
||||||
|
term.setOption('cursorBlink', data.cursorBlink)
|
||||||
|
term.setOption('scrollback', data.scrollback)
|
||||||
|
term.setOption('tabStopWidth', data.tabStopWidth)
|
||||||
|
})
|
||||||
term.on('data', function (data) {
|
term.on('data', function (data) {
|
||||||
socket.emit('data', data)
|
socket.emit('data', data)
|
||||||
})
|
})
|
||||||
|
|
11
socket.js
11
socket.js
|
@ -29,8 +29,10 @@ module.exports = function socket (socket) {
|
||||||
})
|
})
|
||||||
|
|
||||||
conn.on('ready', function connOnReady () {
|
conn.on('ready', function connOnReady () {
|
||||||
console.log('WebSSH2 Login: user=' + socket.request.session.username + ' from=' + socket.handshake.address + ' host=' + socket.request.session.ssh.host + ' port=' + socket.request.session.ssh.port + ' sessionID=' + socket.request.sessionID + '/' + socket.id + ' allowreplay=' + socket.request.session.ssh.allowreplay + ' term=' + socket.request.session.ssh.term)
|
console.log('WebSSH2 Login: user=' + socket.request.session.username + ' from=' + socket.handshake.address + ' host=' + socket.request.session.ssh.host + ' port=' + socket.request.session.ssh.port + ' sessionID=' + socket.request.sessionID + '/' + socket.id + ' MRH_Session=' + socket.request.session.ssh.MRH_Session + ' allowreplay=' + socket.request.session.ssh.allowreplay + ' term=' + socket.request.session.ssh.term)
|
||||||
|
socket.emit('setTerminalOpts', socket.request.session.ssh.terminal)
|
||||||
socket.emit('title', 'ssh://' + socket.request.session.ssh.host)
|
socket.emit('title', 'ssh://' + socket.request.session.ssh.host)
|
||||||
|
console.log('terminal: ' + JSON.stringify(socket.request.session.ssh.terminal))
|
||||||
if (socket.request.session.ssh.header.background) socket.emit('headerBackground', socket.request.session.ssh.header.background)
|
if (socket.request.session.ssh.header.background) socket.emit('headerBackground', socket.request.session.ssh.header.background)
|
||||||
if (socket.request.session.ssh.header.name) socket.emit('header', socket.request.session.ssh.header.name)
|
if (socket.request.session.ssh.header.name) socket.emit('header', socket.request.session.ssh.header.name)
|
||||||
socket.emit('footer', 'ssh://' + socket.request.session.username + '@' + socket.request.session.ssh.host + ':' + socket.request.session.ssh.port)
|
socket.emit('footer', 'ssh://' + socket.request.session.username + '@' + socket.request.session.ssh.host + ':' + socket.request.session.ssh.port)
|
||||||
|
@ -64,12 +66,17 @@ module.exports = function socket (socket) {
|
||||||
socket.on('control', function socketOnControl (controlData) {
|
socket.on('control', function socketOnControl (controlData) {
|
||||||
switch (controlData) {
|
switch (controlData) {
|
||||||
case 'replayCredentials':
|
case 'replayCredentials':
|
||||||
stream.write(socket.request.session.userpassword + '\n')
|
if (socket.request.session.ssh.allowreplay) {
|
||||||
|
stream.write(socket.request.session.userpassword + '\n')
|
||||||
|
}
|
||||||
/* falls through */
|
/* falls through */
|
||||||
default:
|
default:
|
||||||
console.log('controlData: ' + controlData)
|
console.log('controlData: ' + controlData)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
socket.on('resize', function socketOnResize (data) {
|
||||||
|
stream.setWindow(data.rows, data.cols)
|
||||||
|
})
|
||||||
socket.on('disconnecting', function socketOnDisconnecting (reason) { debugWebSSH2('SOCKET DISCONNECTING: ' + reason) })
|
socket.on('disconnecting', function socketOnDisconnecting (reason) { debugWebSSH2('SOCKET DISCONNECTING: ' + reason) })
|
||||||
socket.on('disconnect', function socketOnDisconnect (reason) {
|
socket.on('disconnect', function socketOnDisconnect (reason) {
|
||||||
debugWebSSH2('SOCKET DISCONNECT: ' + reason)
|
debugWebSSH2('SOCKET DISCONNECT: ' + reason)
|
||||||
|
|
|
@ -37,15 +37,20 @@ logBtn.addEventListener('click', toggleLog)
|
||||||
logBtn.style.color = '#000'
|
logBtn.style.color = '#000'
|
||||||
|
|
||||||
var terminalContainer = document.getElementById('terminal-container')
|
var terminalContainer = document.getElementById('terminal-container')
|
||||||
|
|
||||||
var term = new Terminal({
|
|
||||||
cursorBlink: true
|
|
||||||
})
|
|
||||||
var socket, termid // eslint-disable-line
|
var socket, termid // eslint-disable-line
|
||||||
|
var term = new Terminal()
|
||||||
term.open(terminalContainer)
|
term.open(terminalContainer)
|
||||||
term.focus()
|
term.focus()
|
||||||
term.fit()
|
term.fit()
|
||||||
|
|
||||||
|
document.body.onresize = function () {
|
||||||
|
term.fit()
|
||||||
|
term.resize(term.cols, term.rows)
|
||||||
|
console.log('document resize...')
|
||||||
|
console.log('geometry cols: ' + term.cols + ' rows: ' + term.rows)
|
||||||
|
socket.emit('resize', {cols: term.cols, rows: term.rows})
|
||||||
|
}
|
||||||
|
|
||||||
if (document.location.pathname) {
|
if (document.location.pathname) {
|
||||||
var parts = document.location.pathname.split('/')
|
var parts = document.location.pathname.split('/')
|
||||||
var base = parts.slice(0, parts.length - 1).join('/') + '/'
|
var base = parts.slice(0, parts.length - 1).join('/') + '/'
|
||||||
|
@ -61,6 +66,12 @@ socket.on('connect', function () {
|
||||||
socket.emit('geometry', term.cols, term.rows)
|
socket.emit('geometry', term.cols, term.rows)
|
||||||
console.log('geometry cols: ' + term.cols + ' rows: ' + term.rows)
|
console.log('geometry cols: ' + term.cols + ' rows: ' + term.rows)
|
||||||
})
|
})
|
||||||
|
socket.on('setTerminalOpts', function (data) {
|
||||||
|
console.log('terminalOpts: ' + JSON.stringify(data))
|
||||||
|
term.setOption('cursorBlink', data.cursorBlink)
|
||||||
|
term.setOption('scrollback', data.scrollback)
|
||||||
|
term.setOption('tabStopWidth', data.tabStopWidth)
|
||||||
|
})
|
||||||
term.on('data', function (data) {
|
term.on('data', function (data) {
|
||||||
socket.emit('data', data)
|
socket.emit('data', data)
|
||||||
})
|
})
|
||||||
|
|
5
util.js
5
util.js
|
@ -21,3 +21,8 @@ exports.basicAuth = function basicAuth (req, res, next) {
|
||||||
res.end('Username and password required for web SSH service.')
|
res.end('Username and password required for web SSH service.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// takes a string, makes it boolean (true if the string is true, false otherwise)
|
||||||
|
exports.parseBool = function parseBool (str) {
|
||||||
|
return (str.toLowerCase() === 'true')
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue