271 lines
5.1 KiB
JavaScript
271 lines
5.1 KiB
JavaScript
if (! window.$D) {
|
|
window.$D = function (id) {
|
|
return document.getElementById(id);
|
|
};
|
|
}
|
|
|
|
function Telnet(target, connect_callback, disconnect_callback, initscr) {
|
|
var that = {}, // Public API interface
|
|
vd, ws, sQ = [];
|
|
|
|
termType = "Viewdata";
|
|
|
|
Array.prototype.pushStr = function (str) {
|
|
var n = str.length;
|
|
|
|
for (var i=0; i<n; i++) {
|
|
this.push(str.charCodeAt(i));
|
|
}
|
|
}
|
|
|
|
function do_send() {
|
|
Log.Debug('>> do_send');
|
|
|
|
if (sQ.length > 0) {
|
|
ws.send(sQ);
|
|
sQ = [];
|
|
}
|
|
}
|
|
|
|
function do_recv() {
|
|
Log.Debug('>> do_recv');
|
|
|
|
vd.write(ws.rQshiftStr(ws.rQlen()));
|
|
}
|
|
|
|
that.addEvent = function(obj, evType, fn) {
|
|
if (obj.attachEvent) {
|
|
var r = obj.attachEvent("on"+evType, fn);
|
|
return r;
|
|
|
|
} else if (obj.addEventListener){
|
|
obj.addEventListener(evType, fn, false);
|
|
return true;
|
|
|
|
} else {
|
|
throw("Handler could not be attached");
|
|
}
|
|
};
|
|
|
|
that.removeEvent = function(obj, evType, fn){
|
|
if (obj.detachEvent) {
|
|
var r = obj.detachEvent("on"+evType, fn);
|
|
return r;
|
|
|
|
} else if (obj.removeEventListener) {
|
|
obj.removeEventListener(evType, fn, false);
|
|
return true;
|
|
|
|
} else {
|
|
throw("Handler could not be removed");
|
|
}
|
|
};
|
|
|
|
that.stopEvent = function(e) {
|
|
if (e.stopPropagation) {
|
|
e.stopPropagation();
|
|
|
|
} else {
|
|
e.cancelBubble = true;
|
|
}
|
|
|
|
if (e.preventDefault) {
|
|
e.preventDefault();
|
|
} else {
|
|
e.returnValue = false;
|
|
}
|
|
};
|
|
|
|
that.connect = function(host, port, encrypt, url) {
|
|
Log.Debug('>> connect');
|
|
|
|
var host = host,
|
|
port = port,
|
|
scheme = "ws://", uri;
|
|
|
|
if ((!host) || (!port)) {
|
|
console.log("must set host and port");
|
|
return;
|
|
}
|
|
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
|
|
if (encrypt) {
|
|
scheme = "wss://";
|
|
}
|
|
|
|
uri = scheme + host + ":" + port + url;
|
|
|
|
ws.open(uri);
|
|
|
|
//vd.write("\x1e\x11Connecting, hang tight...");
|
|
vd.write("\x0c"+vd.txthash('#0:QIECBAgQIECBAgQIECBAgQIECBAgQIECBAgQIECBAgQIECA0XboW7V61ete7Fuh1oWr1q3QoECBAgQIECBAgQIECBAgQIDRfqw6tWrVq16sOrDUgatWvVqwYMGCBAgQIECBAgQIECBAg')+' '.repeat(40));
|
|
}
|
|
|
|
that.disconnect = function() {
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
|
|
disconnect_callback();
|
|
}
|
|
|
|
function constructor() {
|
|
/* Initialize Websock object */
|
|
ws = new Websock();
|
|
|
|
ws.on('message', do_recv);
|
|
ws.on('open', function(e) {
|
|
vd.curs_set(true, true);
|
|
connect_callback();
|
|
});
|
|
ws.on('close', function(e) {
|
|
that.disconnect();
|
|
});
|
|
ws.on('error', function(e) {
|
|
that.disconnect();
|
|
});
|
|
|
|
/* Initialize the terminal emulator/renderer */
|
|
vd = new VD(40,24,target,initscr);
|
|
|
|
// Override VD I/O routines
|
|
// Set handler for sending characters
|
|
vd.getch(
|
|
function send_chr(chr, vt) {
|
|
var i;
|
|
for (i = 0; i < chr.length; i++) {
|
|
sQ.push(chr.charCodeAt(i));
|
|
}
|
|
do_send();
|
|
vd.getch(send_chr);
|
|
}
|
|
);
|
|
|
|
vd.curs_set = function(vis, grab, eventist) {
|
|
if (vis !== undefined)
|
|
this.cursor_vis_ = (vis > 0);
|
|
|
|
if (eventist === undefined)
|
|
eventist = window;
|
|
|
|
if (grab === true || grab === false) {
|
|
if (grab === this.grab_events_)
|
|
return;
|
|
|
|
if (grab) {
|
|
this.grab_events_ = true;
|
|
VD.the_vt_ = this;
|
|
that.addEvent(eventist, 'keydown', vd.key_down);
|
|
that.addEvent(eventist, 'keyup', vd.key_up);
|
|
} else {
|
|
that.removeEvent(eventist, 'keydown', vd.key_down);
|
|
that.removeEvent(eventist, 'keyup', vd.key_up);
|
|
this.grab_events_ = false;
|
|
VD.the_vt_ = undefined;
|
|
}
|
|
}
|
|
}
|
|
|
|
vd.key_down = function(e) {
|
|
var vt = VD.the_vt_, keysym, ch, str = '';
|
|
|
|
if (vt === undefined)
|
|
return true;
|
|
|
|
keysym = getKeysym(e);
|
|
|
|
if (keysym < 128) {
|
|
if (e.ctrlKey) {
|
|
if (keysym == 64) {
|
|
// control 0
|
|
ch = 0;
|
|
|
|
} else if ((keysym >= 97) && (keysym <= 122)) {
|
|
// control codes 1-26
|
|
ch = keysym - 96;
|
|
|
|
} else if ((keysym >= 91) && (keysym <= 95)) {
|
|
// control codes 27-31
|
|
ch = keysym - 64;
|
|
}
|
|
|
|
} else {
|
|
ch = keysym;
|
|
|
|
switch (ch) {
|
|
case 34:
|
|
ch = 126; break;
|
|
case 126:
|
|
ch = 0x40; break;
|
|
case 64:
|
|
ch = 0x22; break;
|
|
case 39:
|
|
ch = 0x5f; break;
|
|
case 95:
|
|
ch = 0x23; break;
|
|
case 96:
|
|
ch = 0x27; break;
|
|
}
|
|
}
|
|
|
|
str = String.fromCharCode(ch);
|
|
|
|
} else {
|
|
switch (keysym) {
|
|
case 65505: // Shift, do not send directly
|
|
break;
|
|
case 65507: // Ctrl, do not send directly
|
|
break;
|
|
case 65293: // Carriage return, line feed
|
|
str = '_'; break;
|
|
case 65288: // Backspace
|
|
str = '\b'; break;
|
|
case 65307: // Escape
|
|
str = '\x1b'; break;
|
|
case 65361: // Left arrow
|
|
str = '\x08'; break;
|
|
case 65362: // Up arrow
|
|
str = '\x0b'; break;
|
|
case 65363: // Right arrow
|
|
str = '\x09'; break;
|
|
case 65364: // Down arrow
|
|
str = '\x0a'; break;
|
|
|
|
case 0xffc0: // f3
|
|
vd.reveal_ ^= 1;
|
|
vd.refresh();
|
|
break;
|
|
|
|
case 0xffc4: // f7
|
|
str = '\x1b'; break
|
|
}
|
|
}
|
|
|
|
if (str) {
|
|
vt.key_buf_.push(str);
|
|
setTimeout(VD.go_getch_,0);
|
|
}
|
|
|
|
that.stopEvent(e);
|
|
return false;
|
|
}
|
|
|
|
vd.key_up = function(e) {
|
|
var vt = VD.the_vt_;
|
|
|
|
if (vt === undefined)
|
|
return true;
|
|
|
|
that.stopEvent(e);
|
|
return false;
|
|
}
|
|
|
|
return that;
|
|
}
|
|
|
|
return constructor(); // Return the public API interface
|
|
}
|