
* fix `npm run build` fixes #125 - update font-awesome fonts to 5.6.3 - update webpack and dependancies - update xterm to 3.8.0
243 lines
7.1 KiB
JavaScript
243 lines
7.1 KiB
JavaScript
'use strict'
|
|
|
|
import * as io from 'socket.io-client'
|
|
import * as Terminal from 'xterm/dist/xterm'
|
|
import * as fit from 'xterm/dist/addons/fit/fit'
|
|
import { library, dom } from '@fortawesome/fontawesome-svg-core'
|
|
import { faBars, faClipboard, faDownload, faKey, faCog } from '@fortawesome/free-solid-svg-icons'
|
|
library.add(faBars, faClipboard, faDownload, faKey, faCog)
|
|
dom.watch()
|
|
|
|
require('xterm/dist/xterm.css')
|
|
require('../css/style.css')
|
|
|
|
Terminal.applyAddon(fit)
|
|
|
|
/* global Blob, logBtn, credentialsBtn, reauthBtn, downloadLogBtn */
|
|
var sessionLogEnable = false
|
|
var loggedData = false
|
|
var allowreplay = false
|
|
var allowreauth = false
|
|
var sessionLog, sessionFooter, logDate, currentDate, myFile, errorExists
|
|
var socket, termid // eslint-disable-line
|
|
var term = new Terminal()
|
|
// DOM properties
|
|
var status = document.getElementById('status')
|
|
var header = document.getElementById('header')
|
|
var dropupContent = document.getElementById('dropupContent')
|
|
var footer = document.getElementById('footer')
|
|
var terminalContainer = document.getElementById('terminal-container')
|
|
term.open(terminalContainer)
|
|
term.focus()
|
|
term.fit()
|
|
|
|
window.addEventListener('resize', resizeScreen, false)
|
|
|
|
function resizeScreen () {
|
|
term.fit()
|
|
socket.emit('resize', { cols: term.cols, rows: term.rows })
|
|
}
|
|
|
|
if (document.location.pathname) {
|
|
var parts = document.location.pathname.split('/')
|
|
var base = parts.slice(0, parts.length - 1).join('/') + '/'
|
|
var resource = base.substring(1) + 'socket.io'
|
|
socket = io.connect(null, {
|
|
resource: resource
|
|
})
|
|
} else {
|
|
socket = io.connect()
|
|
}
|
|
|
|
term.on('data', function (data) {
|
|
socket.emit('data', data)
|
|
})
|
|
|
|
socket.on('data', function (data) {
|
|
term.write(data)
|
|
if (sessionLogEnable) {
|
|
sessionLog = sessionLog + data
|
|
}
|
|
})
|
|
|
|
socket.on('connect', function () {
|
|
socket.emit('geometry', term.cols, term.rows)
|
|
})
|
|
|
|
socket.on('setTerminalOpts', function (data) {
|
|
term.setOption('cursorBlink', data.cursorBlink)
|
|
term.setOption('scrollback', data.scrollback)
|
|
term.setOption('tabStopWidth', data.tabStopWidth)
|
|
term.setOption('bellStyle', data.bellStyle)
|
|
})
|
|
|
|
socket.on('title', function (data) {
|
|
document.title = data
|
|
})
|
|
|
|
socket.on('menu', function (data) {
|
|
drawMenu(data)
|
|
})
|
|
|
|
socket.on('status', function (data) {
|
|
status.innerHTML = data
|
|
})
|
|
|
|
socket.on('ssherror', function (data) {
|
|
status.innerHTML = data
|
|
status.style.backgroundColor = 'red'
|
|
errorExists = true
|
|
})
|
|
|
|
socket.on('headerBackground', function (data) {
|
|
header.style.backgroundColor = data
|
|
})
|
|
|
|
socket.on('header', function (data) {
|
|
if (data) {
|
|
header.innerHTML = data
|
|
header.style.display = 'block'
|
|
// header is 19px and footer is 19px, recaculate new terminal-container and resize
|
|
terminalContainer.style.height = 'calc(100% - 38px)'
|
|
resizeScreen()
|
|
}
|
|
})
|
|
|
|
socket.on('footer', function (data) {
|
|
sessionFooter = data
|
|
footer.innerHTML = data
|
|
})
|
|
|
|
socket.on('statusBackground', function (data) {
|
|
status.style.backgroundColor = data
|
|
})
|
|
|
|
socket.on('allowreplay', function (data) {
|
|
if (data === true) {
|
|
console.log('allowreplay: ' + data)
|
|
allowreplay = true
|
|
drawMenu(dropupContent.innerHTML + '<a id="credentialsBtn"><i class="fas fa-key fa-fw"></i> Credentials</a>')
|
|
} else {
|
|
allowreplay = false
|
|
console.log('allowreplay: ' + data)
|
|
}
|
|
})
|
|
|
|
socket.on('allowreauth', function (data) {
|
|
if (data === true) {
|
|
console.log('allowreauth: ' + data)
|
|
allowreauth = true
|
|
drawMenu(dropupContent.innerHTML + '<a id="reauthBtn"><i class="fas fa-key fa-fw"></i> Switch User</a>')
|
|
} else {
|
|
allowreauth = false
|
|
console.log('allowreauth: ' + data)
|
|
}
|
|
})
|
|
|
|
socket.on('disconnect', function (err) {
|
|
if (!errorExists) {
|
|
status.style.backgroundColor = 'red'
|
|
status.innerHTML =
|
|
'WEBSOCKET SERVER DISCONNECTED: ' + err
|
|
}
|
|
socket.io.reconnection(false)
|
|
})
|
|
|
|
socket.on('error', function (err) {
|
|
if (!errorExists) {
|
|
status.style.backgroundColor = 'red'
|
|
status.innerHTML = 'ERROR: ' + err
|
|
}
|
|
})
|
|
|
|
socket.on('reauth', function () {
|
|
(allowreauth) && reauthSession()
|
|
})
|
|
|
|
term.on('title', function (title) {
|
|
document.title = title
|
|
})
|
|
|
|
// draw/re-draw menu and reattach listeners
|
|
// when dom is changed, listeners are abandonded
|
|
function drawMenu (data) {
|
|
dropupContent.innerHTML = data
|
|
logBtn.addEventListener('click', toggleLog)
|
|
allowreauth && reauthBtn.addEventListener('click', reauthSession)
|
|
allowreplay && credentialsBtn.addEventListener('click', replayCredentials)
|
|
loggedData && downloadLogBtn.addEventListener('click', downloadLog)
|
|
}
|
|
|
|
// reauthenticate
|
|
function reauthSession () { // eslint-disable-line
|
|
console.log('re-authenticating')
|
|
window.location.href = '/reauth'
|
|
return false
|
|
}
|
|
|
|
// replay password to server, requires
|
|
function replayCredentials () { // eslint-disable-line
|
|
socket.emit('control', 'replayCredentials')
|
|
console.log('replaying credentials')
|
|
term.focus()
|
|
return false
|
|
}
|
|
|
|
// Set variable to toggle log data from client/server to a varialble
|
|
// for later download
|
|
function toggleLog () { // eslint-disable-line
|
|
if (sessionLogEnable === true) {
|
|
sessionLogEnable = false
|
|
loggedData = true
|
|
logBtn.innerHTML = '<i class="fas fa-clipboard fa-fw"></i> Start Log'
|
|
console.log('stopping log, ' + sessionLogEnable)
|
|
currentDate = new Date()
|
|
sessionLog = sessionLog + '\r\n\r\nLog End for ' + sessionFooter + ': ' +
|
|
currentDate.getFullYear() + '/' + (currentDate.getMonth() + 1) + '/' +
|
|
currentDate.getDate() + ' @ ' + currentDate.getHours() + ':' +
|
|
currentDate.getMinutes() + ':' + currentDate.getSeconds() + '\r\n'
|
|
logDate = currentDate
|
|
term.focus()
|
|
return false
|
|
} else {
|
|
sessionLogEnable = true
|
|
loggedData = true
|
|
logBtn.innerHTML = '<i class="fas fa-cog fa-spin fa-fw"></i> Stop Log'
|
|
downloadLogBtn.style.color = '#000'
|
|
downloadLogBtn.addEventListener('click', downloadLog)
|
|
console.log('starting log, ' + sessionLogEnable)
|
|
currentDate = new Date()
|
|
sessionLog = 'Log Start for ' + sessionFooter + ': ' +
|
|
currentDate.getFullYear() + '/' + (currentDate.getMonth() + 1) + '/' +
|
|
currentDate.getDate() + ' @ ' + currentDate.getHours() + ':' +
|
|
currentDate.getMinutes() + ':' + currentDate.getSeconds() + '\r\n\r\n'
|
|
logDate = currentDate
|
|
term.focus()
|
|
return false
|
|
}
|
|
}
|
|
|
|
// cross browser method to "download" an element to the local system
|
|
// used for our client-side logging feature
|
|
function downloadLog () { // eslint-disable-line
|
|
if (loggedData === true) {
|
|
myFile = 'WebSSH2-' + logDate.getFullYear() + (logDate.getMonth() + 1) +
|
|
logDate.getDate() + '_' + logDate.getHours() + logDate.getMinutes() +
|
|
logDate.getSeconds() + '.log'
|
|
// regex should eliminate escape sequences from being logged.
|
|
var blob = new Blob([sessionLog.replace(/[\u001b\u009b][[\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><;]/g, '')], { // eslint-disable-line no-control-regex
|
|
type: 'text/plain'
|
|
})
|
|
if (window.navigator.msSaveOrOpenBlob) {
|
|
window.navigator.msSaveBlob(blob, myFile)
|
|
} else {
|
|
var elem = window.document.createElement('a')
|
|
elem.href = window.URL.createObjectURL(blob)
|
|
elem.download = myFile
|
|
document.body.appendChild(elem)
|
|
elem.click()
|
|
document.body.removeChild(elem)
|
|
}
|
|
}
|
|
term.focus()
|
|
}
|