fixed auto fit and column/row settings for SSH, added experimental client-side logging
line wrapping should work correctly now. experimental client side logging.
This commit is contained in:
parent
3b8182fb3f
commit
17233f11de
4 changed files with 103 additions and 23 deletions
14
index.js
14
index.js
|
@ -12,10 +12,12 @@ var io = require('socket.io')(server);
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
var basicAuth = require('basic-auth');
|
var basicAuth = require('basic-auth');
|
||||||
var ssh = require('ssh2');
|
var ssh = require('ssh2').Client;
|
||||||
var readConfig = require('read-config'),
|
var readConfig = require('read-config'),
|
||||||
config = readConfig(__dirname + '/config.json');
|
config = readConfig(__dirname + '/config.json');
|
||||||
var myError = " - ";
|
var myError = " - ";
|
||||||
|
var termCols;
|
||||||
|
var termRows;
|
||||||
|
|
||||||
function logErrors(err, req, res, next) {
|
function logErrors(err, req, res, next) {
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
|
@ -64,6 +66,10 @@ app.use(express.static(__dirname + '/public')).use(function(req, res, next) {
|
||||||
|
|
||||||
io.on('connection', function(socket) {
|
io.on('connection', function(socket) {
|
||||||
var conn = new ssh();
|
var conn = new ssh();
|
||||||
|
socket.on('geometry', function (cols, rows) {
|
||||||
|
termCols = cols;
|
||||||
|
termRows = rows;
|
||||||
|
});
|
||||||
conn.on('banner', function(d) {
|
conn.on('banner', function(d) {
|
||||||
//need to convert to cr/lf for proper formatting
|
//need to convert to cr/lf for proper formatting
|
||||||
d = d.replace(/\r?\n/g, "\r\n");
|
d = d.replace(/\r?\n/g, "\r\n");
|
||||||
|
@ -76,7 +82,8 @@ io.on('connection', function(socket) {
|
||||||
socket.emit('status', 'SSH CONNECTION ESTABLISHED');
|
socket.emit('status', 'SSH CONNECTION ESTABLISHED');
|
||||||
socket.emit('statusBackground', 'green');
|
socket.emit('statusBackground', 'green');
|
||||||
socket.emit('allowreplay', config.options.allowreplay);
|
socket.emit('allowreplay', config.options.allowreplay);
|
||||||
conn.shell( { term: config.ssh.term }, function(err, stream) {
|
|
||||||
|
conn.shell( { term: config.ssh.term, cols: termCols, rows: termRows }, function(err, stream) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log (err.message);
|
console.log (err.message);
|
||||||
myError = myError + err.message;
|
myError = myError + err.message;
|
||||||
|
@ -99,6 +106,7 @@ io.on('connection', function(socket) {
|
||||||
}).on('close', function(code, signal) {
|
}).on('close', function(code, signal) {
|
||||||
console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
|
console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
|
||||||
conn.end();
|
conn.end();
|
||||||
|
socket.disconnect();
|
||||||
}).stderr.on('data', function(data) {
|
}).stderr.on('data', function(data) {
|
||||||
console.log('STDERR: ' + data);
|
console.log('STDERR: ' + data);
|
||||||
});
|
});
|
||||||
|
@ -106,9 +114,11 @@ io.on('connection', function(socket) {
|
||||||
}).on('end', function() {
|
}).on('end', function() {
|
||||||
socket.emit('status', 'SSH CONNECTION CLOSED BY HOST' + myError);
|
socket.emit('status', 'SSH CONNECTION CLOSED BY HOST' + myError);
|
||||||
socket.emit('statusBackground', 'red');
|
socket.emit('statusBackground', 'red');
|
||||||
|
socket.disconnect();
|
||||||
}).on('close', function() {
|
}).on('close', function() {
|
||||||
socket.emit('status', 'SSH CONNECTION CLOSE' + myError);
|
socket.emit('status', 'SSH CONNECTION CLOSE' + myError);
|
||||||
socket.emit('statusBackground', 'red');
|
socket.emit('statusBackground', 'red');
|
||||||
|
socket.disconnect();
|
||||||
}).on('error', function(err) {
|
}).on('error', function(err) {
|
||||||
myError = myError + err;
|
myError = myError + err;
|
||||||
socket.emit('status', 'SSH CONNECTION ERROR' + myError);
|
socket.emit('status', 'SSH CONNECTION ERROR' + myError);
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
<div id="bottomdiv">
|
<div id="bottomdiv">
|
||||||
<div id="footer"></div>
|
<div id="footer"></div>
|
||||||
<div id="status"></div>
|
<div id="status"></div>
|
||||||
<div id="credentials"><a class="credentials" href="" onclick="return false;">CREDENTIALS</a></div>
|
<div id="credentials"><a class="credentials" href="javascript:void(0);" onclick="replayCredentials()">CREDENTIALS</a></div>
|
||||||
|
<div id="downloadLog"><a class="downloadLog" href="javascript:void(0);" onclick="downloadLog()">Download Log</a></div>
|
||||||
|
<div id="startLog"><a class="startLog" href="javascript:void(0);" onclick="startLog();">Start Log</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
|
var sessionLog,
|
||||||
|
sessionLogEnable = false,
|
||||||
|
sessionFooter,
|
||||||
|
logDate;
|
||||||
|
document.getElementById('downloadLog').style.display = 'none';
|
||||||
var terminalContainer = document.getElementById('terminal-container'),
|
var terminalContainer = document.getElementById('terminal-container'),
|
||||||
term = new Terminal({
|
term = new Terminal({
|
||||||
cursorBlink: true
|
cursorBlink: true
|
||||||
}),
|
}),
|
||||||
socket,
|
socket,
|
||||||
termid;
|
termid;
|
||||||
term.open(terminalContainer);
|
term.open(terminalContainer);
|
||||||
term.fit();
|
term.fit();
|
||||||
var 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('/'),
|
||||||
base = parts.slice(0, parts.length - 1).join('/') + '/',
|
base = parts.slice(0, parts.length - 1).join('/') + '/',
|
||||||
|
@ -18,22 +22,52 @@ if (document.location.pathname) {
|
||||||
} else {
|
} else {
|
||||||
socket = io.connect();
|
socket = io.connect();
|
||||||
}
|
}
|
||||||
var credentialReplay = document.getElementById('credentials')
|
|
||||||
credentialReplay.onclick = replayCredentials;
|
|
||||||
|
|
||||||
function replayCredentials() {
|
function replayCredentials() {
|
||||||
socket.emit('control', 'replayCredentials');
|
socket.emit('control', 'replayCredentials');
|
||||||
//term.writeln('sending credentials');
|
console.log("replaying credentials");
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startLog() {
|
||||||
|
if (sessionLogEnable == true) {
|
||||||
|
sessionLogEnable = false;
|
||||||
|
document.getElementById('startLog').innerHTML = '<a class="startLog" href="javascript:void(0);" onclick="startLog();">Start Log</a>';
|
||||||
|
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;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
sessionLogEnable = true;
|
||||||
|
document.getElementById('startLog').innerHTML = '<a class="startLog" href="javascript:void(0)" onclick="startLog();">Logging - STOP LOG</a>';
|
||||||
|
document.getElementById('downloadLog').style.display = 'inline';
|
||||||
|
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;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadLog() {
|
||||||
|
myFile = "WebSSH2-" + logDate.getFullYear() + (logDate.getMonth() + 1) + logDate.getDate() + "_" + logDate.getHours() + logDate.getMinutes() + logDate.getSeconds() + ".log";
|
||||||
|
var blob = new Blob([sessionLog], {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
socket.emit('create', term.cols, term.rows, function(err, data) {
|
|
||||||
if (err) return self._destroy();
|
|
||||||
self.pty = data.pty;
|
|
||||||
self.id = data.id;
|
|
||||||
termid = self.id;
|
|
||||||
term.emit('open tab', self);
|
|
||||||
});
|
|
||||||
socket.on('connect', function() {
|
socket.on('connect', function() {
|
||||||
|
socket.emit('geometry', term.cols, term.rows);
|
||||||
term.on('data', function(data) {
|
term.on('data', function(data) {
|
||||||
socket.emit('data', data);
|
socket.emit('data', data);
|
||||||
});
|
});
|
||||||
|
@ -46,26 +80,28 @@ socket.on('connect', function() {
|
||||||
}).on('header', function(data) {
|
}).on('header', function(data) {
|
||||||
document.getElementById('header').innerHTML = data;
|
document.getElementById('header').innerHTML = data;
|
||||||
}).on('footer', function(data) {
|
}).on('footer', function(data) {
|
||||||
|
sessionFooter = data;
|
||||||
document.getElementById('footer').innerHTML = data;
|
document.getElementById('footer').innerHTML = data;
|
||||||
}).on('statusBackground', function(data) {
|
}).on('statusBackground', function(data) {
|
||||||
document.getElementById('status').style.backgroundColor = data;
|
document.getElementById('status').style.backgroundColor = data;
|
||||||
}).on('allowreplay', function(data) {
|
}).on('allowreplay', function(data) {
|
||||||
console.log ('allowreplay: ' + data);
|
|
||||||
if (data == 'true') {
|
if (data == 'true') {
|
||||||
|
console.log('allowreplay: ' + data);
|
||||||
document.getElementById('credentials').style.display = 'inline';
|
document.getElementById('credentials').style.display = 'inline';
|
||||||
console.log ('display: block');
|
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('credentials').style.display = 'none';
|
document.getElementById('credentials').style.display = 'none';
|
||||||
console.log ('display: none');
|
|
||||||
}
|
}
|
||||||
}).on('data', function(data) {
|
}).on('data', function(data) {
|
||||||
term.write(data);
|
term.write(data);
|
||||||
|
if (sessionLogEnable) {
|
||||||
|
sessionLog = sessionLog + data;
|
||||||
|
}
|
||||||
}).on('disconnect', function() {
|
}).on('disconnect', function() {
|
||||||
document.getElementById('status').style.backgroundColor = 'red';
|
document.getElementById('status').style.backgroundColor = 'red';
|
||||||
document.getElementById('status').innerHTML = 'WEBSOCKET SERVER DISCONNECTED';
|
document.getElementById('status').innerHTML = 'WEBSOCKET SERVER DISCONNECTED' + err;
|
||||||
socket.io.reconnection(false);
|
socket.io.reconnection(false);
|
||||||
}).on('error', function(err) {
|
}).on('error', function(err) {
|
||||||
document.getElementById('status').style.backgroundColor = 'red';
|
document.getElementById('status').style.backgroundColor = 'red';
|
||||||
document.getElementById('status').innerHTML = 'ERROR ' + err;
|
document.getElementById('status').innerHTML = 'ERROR ' + err;
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -89,4 +89,36 @@ body {
|
||||||
a.credentials {
|
a.credentials {
|
||||||
color: rgb(51, 51, 51);
|
color: rgb(51, 51, 51);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
#downloadLog {
|
||||||
|
display: inline-block;
|
||||||
|
color: rgb(240, 240, 240);
|
||||||
|
background-color: rgb(255, 127, 0);
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
border-color: white;
|
||||||
|
border-style: none solid none none;
|
||||||
|
border-width: 1px;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
a.downloadLog {
|
||||||
|
color: rgb(240, 240, 240);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
#startLog {
|
||||||
|
display: inline-block;
|
||||||
|
color: rgb(240, 240, 240);
|
||||||
|
background-color: rgb(0, 127, 0);
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
border-color: white;
|
||||||
|
border-style: none solid none none;
|
||||||
|
border-width: 1px;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
a.startLog {
|
||||||
|
color: rgb(240, 240, 240);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue