topical media & game development
lib-js-terminal-sample-remote-terminal.htm / htm
<html>
<head>
<title>termlib Remote Terminal</title>
<script language="JavaScript" type="text/javascript" src="lib-js-terminal-termlib.js"></script>
<script language="JavaScript" type="text/javascript" src="lib-js-terminal-termlib-socket.js"></script>
<script type="text/javascript">
<!--
// *** remote terminal sample ***
// mass:werk, N.Landsteiner 2007
// path to server script goes here
var remotePath = '/cgi-bin/termbackend.pl';
// a var to stor the last transfered content
var lastResponse = '';
var term;
var help = [
'%+r **** remote terminal sample **** %-r',
' ',
'* use "exit" to quit.',
'* use "rlogin <username>" for remote login.',
'* use "rlogout" to clear any rlogin data.',
'* use "clear" to clear the screen.',
'* use "help" to see this page.',
'* any other command will be executed on the remote host.',
' '
];
function termOpen() {
if ((!term) || (term.closed)) {
term = new Terminal(
{
x: 220,
y: 70,
termDiv: 'termDiv',
bgColor: '#232e45',
greeting: help.join('\n'),
handler: termHandler,
exitHandler: termExitHandler
}
);
// set up some instance properties for server-client communication
// we use the private namespace "env" of our Terminal instance
term.env.myHistPtr = 0;
term.env.dir = '';
term.env.userid = '';
term.env.password = '';
// and open the terminal
term.open();
// some UI tasks
var lastResponseLink = (document.getElementById)?
document.getElementById('lastResponseLink') : document.all.lastResponseLink;
if (lastResponseLink) lastResponseLink.style.display = 'inline';
var mainPane = (document.getElementById)?
document.getElementById('mainPane') : document.all.mainPane;
if (mainPane) mainPane.className = 'lh15 dimmed';
}
}
function termExitHandler() {
// reset the UI
var lastResponseLink = (document.getElementById)?
document.getElementById('lastResponseLink') : document.all.lastResponseLink;
if (lastResponseLink) lastResponseLink.style.display = 'none';
var mainPane = (document.getElementById)?
document.getElementById('mainPane') : document.all.mainPane;
if (mainPane) mainPane.className = 'lh15';
}
// terminal main loop
function termHandler() {
this.newLine();
// check for raw mode first
if (this.rawMode) {
this.rawMode = false;
if (this.env.getPassword) {
// we just recieved the password of "rlogin"
// first store password
this.env.password = this.lineBuffer;
this.env.getPassword = false;
// store the local terminal history position for later
term.env.myHistPtr = this.histPtr;
// send an initial request to verify and get the working dir
this.send(
{
url: remotePath,
method: 'post',
callback: socketCallback,
data: {
command: 'echo "connection up and ready."',
dir: '',
user: this.env.userid,
pass: this.env.password
}
}
);
// done, leave without prompt (this will come from the callback)
return;
}
// we shouldn't end here
this.prompt(); return;
}
// clear heading white space from input line
this.lineBuffer = this.lineBuffer.replace(/^\s+/, '');
// evaluate commands (split to words first)
var argv = this.lineBuffer.split(/\s+/);
var cmd = argv[0];
switch (cmd) {
case 'rlogin':
if (argv.length<2 || argv[1]=='') {
this.type('usage: rlogin <username>');
}
else {
this.env.getPassword = true;
this.env.userid = argv[1];
this.type('Password: ');
// exit in raw mode for password (blind input)
this.rawMode = true;
this.lock = false;
return;
}
break;
case 'rlogout':
// just forget username and password, reset prompt-string
this.env.dir = '';
this.env.userid = '';
this.env.password = '';
this.ps = '>';
// reset the local terminal's history to login-state
this.histPtr = this.env.myHistPtr;
this.history.length = this.histPtr;
// clear stored last response
lastResponse='';
break;
case 'clear':
this.clear();
break;
case 'help':
this.clear();
this.write(help);
break;
case 'exit':
this.env.dir = '';
this.env.userid = '';
this.env.password = '';
this.close();
lastResponse='';
return;
default:
// no local command
if (this.lineBuffer != '') {
if (!this.env.userid) {
this.write('Not logged in, sorry.'); // not logged in
}
else {
// send (unparsed) line to server-backend
this.send(
{
url: remotePath,
method: 'post',
callback: socketCallback,
data: {
command: this.lineBuffer,
dir: this.env.dir,
user: this.env.userid,
pass: this.env.password
}
}
);
// leave without prompt (this will come from the callback)
return;
}
}
}
this.prompt();
}
// callback for server-client communication
function socketCallback() {
var response = this.socket;
if (response.success) {
// split the responseText to lines
var lines = response.responseText.split('\n');
// get the last valid line and check it
if (lines.length > 1 && lines[lines.length-1] == '') lines.length--;
var lastline = lines[lines.length-1];
if (lastline.indexOf('dir:') == 0) {
// if last line starts with "dir:", store this as working dir
this.env.dir = lastline.substring(4);
// shorten output
lines.length--;
if (lines[lines.length-1] == '') lines.length--;
// and set the prompt-string of the terminal
this.ps = '[' + this.env.dir + '] termbackend.pl
sample backend for the termlib.js remote terminal sample
example only, do not use for real!
use strict;
use CGI;
use IPC::Open3;
use Symbol qw(gensym);
username and password here
my userid = 'user';
my q = new CGI;
my q->param('user');
my q->param('pass');
my q->param('command') || '';
my q->param('dir') || user eq pass eq cmd .= ';echo "";echo "dir:cmd =~ s/^[\\;\s]+//;
# change dir and return command output ...
chdir(cmd`) won't catch STDERR
# so we'll use open3 and mix STDOUT and STDERR ...
my cmd);
while( <CATCH> ) {
print pid, 0);
}
else {
# authorization failed, return Sorry.
print "Sorry.";
}
eof
</pre>
<p> </p>
<p>A script like this must be installed on your web-server (probably in the cgi-bin directory) with sufficient execute permissions in order to make this sample work. Since this is not installed on the <a href="http://www.masswerk.at/" target="_blank">mass:werk</a> server, this page won't be functional on this site.</p>
<p>Be sure to understand that installing a script like this on a public server will mean to welcome hackers with open doors ...</p>
<p> </p>
<p>Disclaimer<br>
This piece of software is published as an example only and AS IS. No warranty of any kind is granted, not even the implied warranty of fitness for a particular purpose. You are advised to <span style="letter-spacing: 1px;">NOT</span> use this script for real. Be aware that using this script or any interface alike bears the risk of serious damage and loss of data. Be also aware that there is no guarantee of any kind for the correctness of the data displayed or transfered.</p>
</td>
</tr>
</table>
<div id="termDiv" style="position:absolute; visibility: hidden; z-index:1;"></div>
</body>
</html>
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.