aboutsummaryrefslogtreecommitdiff
path: root/third_party/websockify/include
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/websockify/include')
-rw-r--r--third_party/websockify/include/VT100.js919
-rw-r--r--third_party/websockify/include/base64.js147
-rw-r--r--third_party/websockify/include/keysym.js99
-rw-r--r--third_party/websockify/include/util.js303
-rw-r--r--third_party/websockify/include/web-socket-js/README.txt109
-rw-r--r--third_party/websockify/include/web-socket-js/WebSocketMain.swfbin0 -> 177114 bytes
-rw-r--r--third_party/websockify/include/web-socket-js/swfobject.js4
-rwxr-xr-xthird_party/websockify/include/web-socket-js/web_socket.js391
-rw-r--r--third_party/websockify/include/websock.js427
-rw-r--r--third_party/websockify/include/webutil.js148
-rw-r--r--third_party/websockify/include/wsirc.js235
-rw-r--r--third_party/websockify/include/wstelnet.js335
12 files changed, 3117 insertions, 0 deletions
diff --git a/third_party/websockify/include/VT100.js b/third_party/websockify/include/VT100.js
new file mode 100644
index 00000000..6a325e13
--- /dev/null
+++ b/third_party/websockify/include/VT100.js
@@ -0,0 +1,919 @@
+// VT100.js -- a text terminal emulator in JavaScript with a ncurses-like
+// interface and a POSIX-like interface. (The POSIX-like calls are
+// implemented on top of the ncurses-like calls, not the other way round.)
+//
+// Released under the GNU LGPL v2.1, by Frank Bi <bi@zompower.tk>
+//
+// 2007-08-12 - refresh():
+// - factor out colour code to html_colours_()
+// - fix handling of A_REVERSE | A_DIM
+// - simplify initial <br /> output code
+// - fix underlining colour
+// - fix attron() not to turn off attributes
+// - decouple A_STANDOUT and A_BOLD
+// 2007-08-11 - getch() now calls refresh()
+// 2007-08-06 - Safari compat fix -- turn '\r' into '\n' for onkeypress
+// 2007-08-05 - Opera compat fixes for onkeypress
+// 2007-07-30 - IE compat fixes:
+// - change key handling code
+// - add <br />...<br />&nbsp; so that 1st and last lines align
+// 2007-07-28 - change wrapping behaviour -- writing at the right edge no
+// longer causes the cursor to immediately wrap around
+// - add <b>...</b> to output to make A_STANDOUT stand out more
+// - add handling of backspace, tab, return keys
+// - fix doc. of VT100() constructor
+// - change from GPL to LGPL
+// 2007-07-09 - initial release
+//
+// class VT100
+// A_NORMAL, A_UNDERLINE, A_REVERSE, A_BLINK, A_DIM, A_BOLD, A_STANDOUT
+// =class constants=
+// Attribute constants.
+// VT100(wd, ht, scr_id) =constructor=
+// Creates a virtual terminal with width `wd', and
+// height `ht'. The terminal will be displayed between
+// <pre>...</pre> tags which have element ID `scr_id'.
+// addch(ch [, attr])
+// Writes out the character `ch'. If `attr' is given,
+// it specifies the attributes for the character,
+// otherwise the current attributes are used.
+// addstr(stuff) Writes out the string `stuff' using the current
+// attributes.
+// attroff(mode) Turns off any current options given in mode.
+// attron(mode) Turns on any options given in mode.
+// attrset(mode) Sets the current options to mode.
+// bkgdset(attr) Sets the background attributes to attr.
+// clear() Clears the terminal using the background attributes,
+// and homes the cursor.
+// clrtobol() Clears the portion of the terminal from the cursor
+// to the bottom.
+// clrtoeol() Clears the portion of the current line after the
+// cursor.
+// curs_set(vis [, grab])
+// If `vis' is 0, makes the cursor invisible; otherwise
+// make it visible. If `grab' is given and true, starts
+// capturing keyboard events (for `getch()'); if given
+// and false, stops capturing events.
+// echo() Causes key strokes to be automatically echoed on the
+// terminal.
+// erase() Same as `clear()'.
+// getch(isr) Arranges to call `isr' when a key stroke is
+// received. The received character and the terminal
+// object are passed as arguments to `isr'.
+// getmaxyx() Returns an associative array with the maximum row
+// (`y') and column (`x') numbers for the terminal.
+// getyx() Returns an associative array with the current row
+// (`y') and column (`x') of the cursor.
+// move(r, c) Moves the cursor to row `r', column `c'.
+// noecho() Stops automatically echoing key strokes.
+// refresh() Updates the display.
+// scroll() Scrolls the terminal up one line.
+// standend() Same as `attrset(VT100.A_NORMAL)'.
+// standout() Same as `attron(VT100.A_STANDOUT)'.
+// write(stuff) Writes `stuff' to the terminal and immediately
+// updates the display; (some) escape sequences are
+// interpreted and acted on.
+
+// constructor
+function VT100(wd, ht, scr_id)
+{
+ var r;
+ var c;
+ var scr = document.getElementById(scr_id);
+ this.wd_ = wd;
+ this.ht_ = ht;
+ this.scrolled_ = 0;
+ this.bkgd_ = {
+ mode: VT100.A_NORMAL,
+ fg: VT100.COLOR_WHITE,
+ bg: VT100.COLOR_BLACK
+ };
+ this.c_attr_ = {
+ mode: VT100.A_NORMAL,
+ fg: VT100.COLOR_WHITE,
+ bg: VT100.COLOR_BLACK
+ };
+ this.text_ = new Array(ht);
+ this.attr_ = new Array(ht);
+ for (r = 0; r < ht; ++r) {
+ this.text_[r] = new Array(wd);
+ this.attr_[r] = new Array(wd);
+ }
+ this.scr_ = scr;
+ this.cursor_vis_ = true;
+ this.grab_events_ = false;
+ this.getch_isr_ = undefined;
+ this.key_buf_ = [];
+ this.echo_ = true;
+ this.esc_state_ = 0;
+ // Internal debug setting.
+ this.debug_ = 0;
+ this.clear();
+ this.refresh();
+}
+
+// public constants -- colours and colour pairs
+VT100.COLOR_BLACK = 0;
+VT100.COLOR_BLUE = 1;
+VT100.COLOR_GREEN = 2;
+VT100.COLOR_CYAN = 3;
+VT100.COLOR_RED = 4;
+VT100.COLOR_MAGENTA = 5;
+VT100.COLOR_YELLOW = 6;
+VT100.COLOR_WHITE = 7;
+VT100.COLOR_PAIRS = 256;
+VT100.COLORS = 8;
+// public constants -- attributes
+VT100.A_NORMAL = 0;
+VT100.A_UNDERLINE = 1;
+VT100.A_REVERSE = 2;
+VT100.A_BLINK = 4;
+VT100.A_DIM = 8;
+VT100.A_BOLD = 16;
+VT100.A_STANDOUT = 32;
+VT100.A_PROTECT = VT100.A_INVIS = 0; // ?
+// other public constants
+VT100.TABSIZE = 8;
+// private constants
+VT100.ATTR_FLAGS_ = VT100.A_UNDERLINE | VT100.A_REVERSE | VT100.A_BLINK |
+ VT100.A_DIM | VT100.A_BOLD | VT100.A_STANDOUT |
+ VT100.A_PROTECT | VT100.A_INVIS;
+VT100.COLOR_SHIFT_ = 6;
+VT100.browser_ie_ = (navigator.appName.indexOf("Microsoft") != -1);
+VT100.browser_opera_ = (navigator.appName.indexOf("Opera") != -1);
+// class variables
+VT100.the_vt_ = undefined;
+
+// class methods
+
+// this is actually an event handler
+VT100.handle_onkeypress_ = function VT100_handle_onkeypress(event)
+{
+ var vt = VT100.the_vt_, ch;
+ if (vt === undefined)
+ return true;
+ if (VT100.browser_ie_ || VT100.browser_opera_) {
+ ch = event.keyCode;
+ if (ch == 13)
+ ch = 10;
+ else if (ch > 255 || (ch < 32 && ch != 8))
+ return true;
+ ch = String.fromCharCode(ch);
+ } else {
+ ch = event.charCode;
+ //dump("ch: " + ch + "\n");
+ //dump("ctrl?: " + event.ctrlKey + "\n");
+ vt.debug("onkeypress:: keyCode: " + event.keyCode + ", ch: " + event.charCode);
+ if (ch) {
+ if (ch > 255)
+ return true;
+ if (event.ctrlKey && event.shiftKey) {
+ // Don't send the copy/paste commands.
+ var charStr = String.fromCharCode(ch);
+ if (charStr == 'C' || charStr == 'V') {
+ return false;
+ }
+ }
+ if (event.ctrlKey) {
+ ch = String.fromCharCode(ch - 96);
+ } else {
+ ch = String.fromCharCode(ch);
+ if (ch == '\r')
+ ch = '\n';
+ }
+ } else {
+ switch (event.keyCode) {
+ case event.DOM_VK_BACK_SPACE:
+ ch = '\b';
+ break;
+ case event.DOM_VK_TAB:
+ ch = '\t';
+ // Stop tab from moving to another element.
+ event.preventDefault();
+ break;
+ case event.DOM_VK_RETURN:
+ case event.DOM_VK_ENTER:
+ ch = '\n';
+ break;
+ case event.DOM_VK_UP:
+ ch = '\x1b[A';
+ break;
+ case event.DOM_VK_DOWN:
+ ch = '\x1b[B';
+ break;
+ case event.DOM_VK_RIGHT:
+ ch = '\x1b[C';
+ break;
+ case event.DOM_VK_LEFT:
+ ch = '\x1b[D';
+ break;
+ case event.DOM_VK_DELETE:
+ ch = '\x1b[3~';
+ break;
+ case event.DOM_VK_HOME:
+ ch = '\x1b[H';
+ break;
+ case event.DOM_VK_ESCAPE:
+ ch = '\x1bc';
+ break;
+ default:
+ return true;
+ }
+ }
+ }
+ vt.key_buf_.push(ch);
+ setTimeout(VT100.go_getch_, 0);
+ return false;
+}
+
+// this is actually an event handler
+VT100.handle_onkeydown_ = function VT100_handle_onkeydown()
+{
+ var vt = VT100.the_vt_, ch;
+ switch (event.keyCode) {
+ case 8:
+ ch = '\b'; break;
+ default:
+ return true;
+ }
+ vt.key_buf_.push(ch);
+ setTimeout(VT100.go_getch_, 0);
+ return false;
+}
+
+VT100.go_getch_ = function VT100_go_getch()
+{
+ var vt = VT100.the_vt_;
+ if (vt === undefined)
+ return;
+ var isr = vt.getch_isr_;
+ vt.getch_isr_ = undefined;
+ if (isr === undefined)
+ return;
+ var ch = vt.key_buf_.shift();
+ if (ch === undefined) {
+ vt.getch_isr_ = isr;
+ return;
+ }
+ if (vt.echo_)
+ vt.addch(ch);
+ isr(ch, vt);
+}
+
+// object methods
+
+VT100.prototype.may_scroll_ = function()
+{
+ var ht = this.ht_, cr = this.row_;
+ while (cr >= ht) {
+ this.scroll();
+ --cr;
+ }
+ this.row_ = cr;
+}
+
+VT100.prototype.html_colours_ = function(attr)
+{
+ var fg, bg, co0, co1;
+ fg = attr.fg;
+ bg = attr.bg;
+ switch (attr.mode & (VT100.A_REVERSE | VT100.A_DIM | VT100.A_BOLD)) {
+ case 0:
+ case VT100.A_DIM | VT100.A_BOLD:
+ co0 = '00'; co1 = 'c0';
+ break;
+ case VT100.A_BOLD:
+ co0 = '00'; co1 = 'ff';
+ break;
+ case VT100.A_DIM:
+ if (fg == VT100.COLOR_BLACK)
+ co0 = '40';
+ else
+ co0 = '00';
+ co1 = '40';
+ break;
+ case VT100.A_REVERSE:
+ case VT100.A_REVERSE | VT100.A_DIM | VT100.A_BOLD:
+ co0 = 'c0'; co1 = '40';
+ break;
+ case VT100.A_REVERSE | VT100.A_BOLD:
+ co0 = 'c0'; co1 = '00';
+ break;
+ default:
+ if (fg == VT100.COLOR_BLACK)
+ co0 = '80';
+ else
+ co0 = 'c0';
+ co1 = 'c0';
+ }
+ return {
+ f: '#' + (fg & 4 ? co1 : co0) +
+ (fg & 2 ? co1 : co0) +
+ (fg & 1 ? co1 : co0),
+ b: '#' + (bg & 4 ? co1 : co0) +
+ (bg & 2 ? co1 : co0) +
+ (bg & 1 ? co1 : co0)
+ };
+}
+
+VT100.prototype.addch = function(ch, attr)
+{
+ var cc = this.col_;
+ this.debug("addch:: ch: " + ch + ", attr: " + attr);
+ switch (ch) {
+ case '\b':
+ if (cc != 0)
+ --cc;
+ break;
+ case '\n':
+ ++this.row_;
+ cc = 0;
+ this.clrtoeol();
+ this.may_scroll_();
+ break;
+ case '\r':
+ this.may_scroll_();
+ cc = 0;
+ break;
+ case '\t':
+ this.may_scroll_();
+ cc += VT100.TABSIZE - cc % VT100.TABSIZE;
+ if (cc >= this.wd_) {
+ ++this.row_;
+ cc -= this.wd_;
+ }
+ break;
+ default:
+ if (attr === undefined)
+ attr = this._cloneAttr(this.c_attr_);
+ if (cc >= this.wd_) {
+ ++this.row_;
+ cc = 0;
+ }
+ this.may_scroll_();
+ this.text_[this.row_][cc] = ch;
+ this.attr_[this.row_][cc] = attr;
+ ++cc;
+ }
+ this.col_ = cc;
+}
+
+VT100.prototype.addstr = function(stuff)
+{
+ for (var i = 0; i < stuff.length; ++i)
+ this.addch(stuff.charAt(i));
+}
+
+VT100.prototype._cloneAttr = function VT100_cloneAttr(a)
+{
+ return {
+ mode: a.mode,
+ fg: a.fg,
+ bg: a.bg
+ };
+}
+
+VT100.prototype.attroff = function(a)
+{
+ //dump("attroff: " + a + "\n");
+ a &= VT100.ATTR_FLAGS_;
+ this.c_attr_.mode &= ~a;
+}
+
+VT100.prototype.attron = function(a)
+{
+ //dump("attron: " + a + "\n");
+ a &= VT100.ATTR_FLAGS_;
+ this.c_attr_.mode |= a;
+}
+
+VT100.prototype.attrset = function(a)
+{
+ //dump("attrset: " + a + "\n");
+ this.c_attr_.mode = a;
+}
+
+VT100.prototype.fgset = function(fg)
+{
+ //dump("fgset: " + fg + "\n");
+ this.c_attr_.fg = fg;
+}
+
+VT100.prototype.bgset = function(bg)
+{
+ //dump("bgset: " + bg + "\n");
+ if (bg !== 0) {
+ this.warn("bgset: " + bg + "\n");
+ }
+ this.c_attr_.bg = bg;
+}
+
+VT100.prototype.bkgdset = function(a)
+{
+ this.bkgd_ = a;
+}
+
+VT100.prototype.clear = function()
+{
+ this.debug("clear");
+ this.row_ = this.col_ = 0;
+ this.scrolled_ = 0;
+ for (r = 0; r < this.ht_; ++r) {
+ for (c = 0; c < this.wd_; ++c) {
+ this.text_[r][c] = ' ';
+ this.attr_[r][c] = this._cloneAttr(this.bkgd_);
+ }
+ }
+}
+
+VT100.prototype.clrtobot = function()
+{
+ this.debug("clrtobot, row: " + this.row_);
+ var ht = this.ht_;
+ var wd = this.wd_;
+ this.clrtoeol();
+ for (var r = this.row_ + 1; r < ht; ++r) {
+ for (var c = 0; c < wd; ++c) {
+ this.text_[r][c] = ' ';
+ this.attr_[r][c] = this.bkgd_;
+ }
+ }
+}
+
+VT100.prototype.clrtoeol = function()
+{
+ this.debug("clrtoeol, col: " + this.col_);
+ var r = this.row_;
+ if (r >= this.ht_)
+ return;
+ for (var c = this.col_; c < this.wd_; ++c) {
+ this.text_[r][c] = ' ';
+ this.attr_[r][c] = this.bkgd_;
+ }
+}
+
+VT100.prototype.clearpos = function(row, col)
+{
+ this.debug("clearpos (" + row + ", " + col + ")");
+ if (row < 0 || row >= this.ht_)
+ return;
+ if (col < 0 || col >= this.wd_)
+ return;
+ this.text_[row][col] = ' ';
+ this.attr_[row][col] = this.bkgd_;
+}
+
+VT100.prototype.curs_set = function(vis, grab, eventist)
+{
+ this.debug("curs_set:: vis: " + vis + ", grab: " + grab);
+ 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;
+ VT100.the_vt_ = this;
+ eventist.addEventListener("keypress", VT100.handle_onkeypress_, false);
+ if (VT100.browser_ie_)
+ document.onkeydown = VT100.handle_onkeydown_;
+ } else {
+ eventist.removeEventListener("keypress", VT100.handle_onkeypress_, false);
+ if (VT100.browser_ie_)
+ document.onkeydown = VT100.handle_onkeydown_;
+ this.grab_events_ = false;
+ VT100.the_vt_ = undefined;
+ }
+ }
+}
+
+VT100.prototype.echo = function()
+{
+ this.debug("echo on");
+ this.echo_ = true;
+}
+
+VT100.prototype.erase = VT100.prototype.clear;
+
+VT100.prototype.getch = function(isr)
+{
+ this.debug("getch");
+ this.refresh();
+ this.getch_isr_ = isr;
+ setTimeout(VT100.go_getch_, 0);
+}
+
+VT100.prototype.getmaxyx = function()
+{
+ return { y: this.ht_ - 1, x: this.wd_ - 1 };
+}
+
+VT100.prototype.getyx = function()
+{
+ return { y: this.row_, x: this.col_ };
+}
+
+VT100.prototype.move = function(r, c)
+{
+ this.debug("move: (" + r + ", " + c + ")");
+ if (r < 0)
+ r = 0;
+ else if (r >= this.ht_)
+ r = this.ht_ - 1;
+ if (c < 0)
+ c = 0;
+ else if (c >= this.wd_)
+ c = this.wd_ - 1;
+ this.row_ = r;
+ this.col_ = c;
+}
+
+VT100.prototype.noecho = function()
+{
+ this.debug("echo off");
+ this.echo_ = false;
+}
+
+VT100.prototype.refresh = function()
+{
+ this.debug("refresh");
+ var r, c, stuff = "", start_tag = "", end_tag = "", at = -1, n_at, ch,
+ pair, cr, cc, ht, wd, cv, added_end_tag;
+ ht = this.ht_;
+ wd = this.wd_;
+ cr = this.row_;
+ cc = this.col_;
+ cv = this.cursor_vis_;
+ var innerHTML = this.scr_.innerHTML;
+ if (cc >= wd)
+ cc = wd - 1;
+ for (r = 0; r < ht; ++r) {
+ if (r > 0) {
+ stuff += '\n';
+ }
+ for (c = 0; c < wd; ++c) {
+ added_end_tag = false;
+ n_at = this.attr_[r][c];
+ if (cv && r == cr && c == cc) {
+ // Draw the cursor here.
+ n_at = this._cloneAttr(n_at);
+ n_at.mode ^= VT100.A_REVERSE;
+ }
+ // If the attributes changed, make a new span.
+ if (n_at.mode != at.mode || n_at.fg != at.fg || n_at.bg != at.bg) {
+ if (c > 0) {
+ stuff += end_tag;
+ }
+ start_tag = "";
+ end_tag = "";
+ if (n_at.mode & VT100.A_BLINK) {
+ start_tag = "<blink>";
+ end_tag = "</blink>" + end_tag;
+ }
+ if (n_at.mode & VT100.A_STANDOUT)
+ n_at.mode |= VT100.A_BOLD;
+ pair = this.html_colours_(n_at);
+ start_tag += '<span style="color:' + pair.f +
+ ';background-color:' + pair.b;
+ if (n_at.mode & VT100.A_UNDERLINE)
+ start_tag += ';text-decoration:underline';
+ start_tag += ';">';
+ stuff += start_tag;
+ end_tag = "</span>" + end_tag;
+ at = n_at;
+ added_end_tag = true;
+ } else if (c == 0) {
+ stuff += start_tag;
+ }
+ ch = this.text_[r][c];
+ switch (ch) {
+ case '&':
+ stuff += '&amp;'; break;
+ case '<':
+ stuff += '&lt;'; break;
+ case '>':
+ stuff += '&gt;'; break;
+ case ' ':
+ //stuff += '&nbsp;'; break;
+ stuff += ' '; break;
+ default:
+ stuff += ch;
+ }
+ }
+ if (!added_end_tag)
+ stuff += end_tag;
+ }
+ this.scr_.innerHTML = "<b>" + stuff + "</b>\n";
+}
+
+VT100.prototype.scroll = function()
+{
+ this.scrolled_ += 1;
+ this.debug("scrolled: " + this.scrolled_);
+ var n_text = this.text_[0], n_attr = this.attr_[0],
+ ht = this.ht_, wd = this.wd_;
+ for (var r = 1; r < ht; ++r) {
+ this.text_[r - 1] = this.text_[r];
+ this.attr_[r - 1] = this.attr_[r];
+ }
+ this.text_[ht - 1] = n_text;
+ this.attr_[ht - 1] = n_attr;
+ for (var c = 0; c < wd; ++c) {
+ n_text[c] = ' ';
+ n_attr[c] = this.bkgd_;
+ }
+}
+
+VT100.prototype.standend = function()
+{
+ //this.debug("standend");
+ this.attrset(0);
+}
+
+VT100.prototype.standout = function()
+{
+ //this.debug("standout");
+ this.attron(VT100.A_STANDOUT);
+}
+
+VT100.prototype.write = function(stuff)
+{
+ var ch, x, r, c, i, j, yx, myx;
+ for (i = 0; i < stuff.length; ++i) {
+ ch = stuff.charAt(i);
+ if (ch == '\x0D') {
+ this.debug("write:: ch: " + ch.charCodeAt(0) + ", '\\x0D'");
+ } else {
+ this.debug("write:: ch: " + ch.charCodeAt(0) + ", '" + (ch == '\x1b' ? "ESC" : ch) + "'");
+ }
+ //dump("ch: " + ch.charCodeAt(0) + ", '" + (ch == '\x1b' ? "ESC" : ch) + "'\n");
+ switch (ch) {
+ case '\x00':
+ case '\x7f':
+ case '\x07': /* bell, ignore it */
+ this.debug("write:: ignoring bell character: " + ch);
+ continue;
+ case '\a':
+ case '\b':
+ case '\t':
+ case '\r':
+ this.addch(ch);
+ continue;
+ case '\n':
+ case '\v':
+ case '\f': // what a mess
+ yx = this.getyx();
+ myx = this.getmaxyx();
+ if (yx.y >= myx.y) {
+ this.scroll();
+ this.move(myx.y, 0);
+ } else
+ this.move(yx.y + 1, 0);
+ continue;
+ case '\x18':
+ case '\x1a':
+ this.esc_state_ = 0;
+ this.debug("write:: set escape state: 0");
+ continue;
+ case '\x1b':
+ this.esc_state_ = 1;
+ this.debug("write:: set escape state: 1");
+ continue;
+ case '\x9b':
+ this.esc_state_ = 2;
+ this.debug("write:: set escape state: 2");
+ continue;
+ }
+ // not a recognized control character
+ switch (this.esc_state_) {
+ case 0: // not in escape sequence
+ this.addch(ch);
+ break;
+ case 1: // just saw ESC
+ switch (ch) {
+ case '[':
+ this.esc_state_ = 2;
+ this.debug("write:: set escape state: 2");
+ break;
+ case '=':
+ /* Set keypade mode (ignored) */
+ this.debug("write:: set keypade mode: ignored");
+ this.esc_state_ = 0;
+ break;
+ case '>':
+ /* Reset keypade mode (ignored) */
+ this.debug("write:: reset keypade mode: ignored");
+ this.esc_state_ = 0;
+ break;
+ case 'H':
+ /* Set tab at cursor column (ignored) */
+ this.debug("write:: set tab cursor column: ignored");
+ this.esc_state_ = 0;
+ break;
+ }
+ break;
+ case 2: // just saw CSI
+ switch (ch) {
+ case 'K':
+ /* Erase in Line */
+ this.esc_state_ = 0;
+ this.clrtoeol();
+ continue;
+ case 'H':
+ /* Move to (0,0). */
+ this.esc_state_ = 0;
+ this.move(0, 0);
+ continue;
+ case 'J':
+ /* Clear to the bottom. */
+ this.esc_state_ = 0;
+ this.clrtobot();
+ continue;
+ case '?':
+ /* Special VT100 mode handling. */
+ this.esc_state_ = 5;
+ this.debug("write:: special vt100 mode");
+ continue;
+ }
+ // Drop through to next case.
+ this.csi_parms_ = [0];
+ this.debug("write:: set escape state: 3");
+ this.esc_state_ = 3;
+ case 3: // saw CSI and parameters
+ switch (ch) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ x = this.csi_parms_.pop();
+ this.csi_parms_.push(x * 10 + ch * 1);
+ this.debug("csi_parms_: " + this.csi_parms_);
+ continue;
+ case ';':
+ if (this.csi_parms_.length < 17)
+ this.csi_parms_.push(0);
+ continue;
+ }
+ this.esc_state_ = 0;
+ switch (ch) {
+ case 'A':
+ // Cursor Up <ESC>[{COUNT}A
+ this.move(this.row_ - Math.max(1, this.csi_parms_[0]),
+ this.col_);
+ break;
+ case 'B':
+ // Cursor Down <ESC>[{COUNT}B
+ this.move(this.row_ + Math.max(1, this.csi_parms_[0]),
+ this.col_);
+ break;
+ case 'C':
+ // Cursor Forward <ESC>[{COUNT}C
+ this.move(this.row_,
+ this.col_ + Math.max(1, this.csi_parms_[0]));
+ break;
+ case 'c':
+ this.warn("write:: got TERM query");
+ break;
+ case 'D':
+ // Cursor Backward <ESC>[{COUNT}D
+ this.move(this.row_,
+ this.col_ - Math.max(1, this.csi_parms_[0]));
+ break;
+ case 'f':
+ case 'H':
+ // Cursor Home <ESC>[{ROW};{COLUMN}H
+ this.csi_parms_.push(0);
+ this.move(this.csi_parms_[0] - 1,
+ this.csi_parms_[1] - 1);
+ break;
+ case 'J':
+ switch (this.csi_parms_[0]) {
+ case 0:
+ this.clrtobot();
+ break;
+ case 2:
+ this.clear();
+ this.move(0, 0);
+ }
+ break;
+ case 'm':
+ for (j=0; j<this.csi_parms_.length; ++j) {
+ x = this.csi_parms_[j];
+ switch (x) {
+ case 0:
+ this.standend();
+ this.fgset(this.bkgd_.fg);
+ this.bgset(this.bkgd_.bg);
+ break;
+ case 1:
+ this.attron(VT100.A_BOLD);
+ break;
+ case 30:
+ this.fgset(VT100.COLOR_BLACK);
+ break;
+ case 31:
+ this.fgset(VT100.COLOR_RED);
+ break;
+ case 32:
+ this.fgset(VT100.COLOR_GREEN);
+ break;
+ case 33:
+ this.fgset(VT100.COLOR_YELLOW);
+ break;
+ case 34:
+ this.fgset(VT100.COLOR_BLUE);
+ break;
+ case 35:
+ this.fgset(VT100.COLOR_MAGENTA);
+ break;
+ case 36:
+ this.fgset(VT100.COLOR_CYAN);
+ break;
+ case 37:
+ this.fgset(VT100.COLOR_WHITE);
+ break;
+ case 40:
+ this.bgset(VT100.COLOR_BLACK);
+ break;
+ case 41:
+ this.bgset(VT100.COLOR_RED);
+ break;
+ case 42:
+ this.bgset(VT100.COLOR_GREEN);
+ break;
+ case 44:
+ this.bgset(VT100.COLOR_YELLOW);
+ break;
+ case 44:
+ this.bgset(VT100.COLOR_BLUE);
+ break;
+ case 45:
+ this.bgset(VT100.COLOR_MAGENTA);
+ break;
+ case 46:
+ this.bgset(VT100.COLOR_CYAN);
+ break;
+ case 47:
+ this.bgset(VT100.COLOR_WHITE);
+ break;
+ }
+ }
+ break;
+ case 'r':
+ // 1,24r - set scrolling region (ignored)
+ break;
+ case '[':
+ this.debug("write:: set escape state: 4");
+ this.esc_state_ = 4;
+ break;
+ case 'g':
+ // 0g: clear tab at cursor (ignored)
+ // 3g: clear all tabs (ignored)
+ break;
+ default:
+ this.warn("write:: unknown command: " + ch);
+ this.csi_parms_ = [];
+ break;
+ }
+ break;
+ case 4: // saw CSI [
+ this.esc_state_ = 0; // gobble char.
+ break;
+ case 5: // Special mode handling, saw <ESC>[?
+ // Expect a number - the reset type
+ this.csi_parms_ = [ch];
+ this.esc_state_ = 6;
+ break;
+ case 6: // Reset mode handling, saw <ESC>[?1
+ // Expect a letter - the mode target, example:
+ // <ESC>[?1l : cursor key mode = cursor
+ // <ESC>[?1h : save current screen, create new empty
+ // screen and position at 0,0
+ // <ESC>[?5l : White on blk
+ // XXX: Ignored for now.
+ //dump("Saw reset mode: <ESC>[?" + this.csi_parms_[0] + ch + "\n");
+ this.esc_state_ = 0;
+ this.debug("write:: set escape state: 0");
+ break;
+ }
+ }
+ this.refresh();
+}
+
+VT100.prototype.debug = function(message) {
+ if (this.debug_) {
+ dump(message + "\n");
+ }
+}
+
+VT100.prototype.warn = function(message) {
+ dump(message + "\n");
+}
diff --git a/third_party/websockify/include/base64.js b/third_party/websockify/include/base64.js
new file mode 100644
index 00000000..e9b3c522
--- /dev/null
+++ b/third_party/websockify/include/base64.js
@@ -0,0 +1,147 @@
+/*
+ * Modified from:
+ * http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956
+ */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XML-RPC Client component.
+ *
+ * The Initial Developer of the Original Code is
+ * Digital Creations 2, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Martijn Pieters <mj@digicool.com> (original author)
+ * Samuel Sieb <samuel@sieb.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*jslint white: false, bitwise: false, plusplus: false */
+/*global console */
+
+var Base64 = {
+
+/* Convert data (an array of integers) to a Base64 string. */
+toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+base64Pad : '=',
+
+encode: function (data) {
+ "use strict";
+ var result = '',
+ chrTable = Base64.toBase64Table.split(''),
+ pad = Base64.base64Pad,
+ length = data.length,
+ i;
+ // Convert every three bytes to 4 ascii characters.
+ for (i = 0; i < (length - 2); i += 3) {
+ result += chrTable[data[i] >> 2];
+ result += chrTable[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
+ result += chrTable[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
+ result += chrTable[data[i+2] & 0x3f];
+ }
+
+ // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
+ if (length%3) {
+ i = length - (length%3);
+ result += chrTable[data[i] >> 2];
+ if ((length%3) === 2) {
+ result += chrTable[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
+ result += chrTable[(data[i+1] & 0x0f) << 2];
+ result += pad;
+ } else {
+ result += chrTable[(data[i] & 0x03) << 4];
+ result += pad + pad;
+ }
+ }
+
+ return result;
+},
+
+/* Convert Base64 data to a string */
+toBinaryTable : [
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+ 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
+ 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+ -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+ 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+],
+
+decode: function (data, offset) {
+ "use strict";
+ offset = typeof(offset) !== 'undefined' ? offset : 0;
+ var binTable = Base64.toBinaryTable,
+ pad = Base64.base64Pad,
+ result, result_length, idx, i, c, padding,
+ leftbits = 0, // number of bits decoded, but yet to be appended
+ leftdata = 0, // bits decoded, but yet to be appended
+ data_length = data.indexOf('=') - offset;
+
+ if (data_length < 0) { data_length = data.length - offset; }
+
+ /* Every four characters is 3 resulting numbers */
+ result_length = (data_length >> 2) * 3 + Math.floor((data_length%4)/1.5);
+ result = new Array(result_length);
+
+ // Convert one by one.
+ for (idx = 0, i = offset; i < data.length; i++) {
+ c = binTable[data.charCodeAt(i) & 0x7f];
+ padding = (data.charAt(i) === pad);
+ // Skip illegal characters and whitespace
+ if (c === -1) {
+ console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
+ continue;
+ }
+
+ // Collect data into leftdata, update bitcount
+ leftdata = (leftdata << 6) | c;
+ leftbits += 6;
+
+ // If we have 8 or more bits, append 8 bits to the result
+ if (leftbits >= 8) {
+ leftbits -= 8;
+ // Append if not padding.
+ if (!padding) {
+ result[idx++] = (leftdata >> leftbits) & 0xff;
+ }
+ leftdata &= (1 << leftbits) - 1;
+ }
+ }
+
+ // If there are any bits left, the base64 string was corrupted
+ if (leftbits) {
+ throw {name: 'Base64-Error',
+ message: 'Corrupted base64 string'};
+ }
+
+ return result;
+}
+
+}; /* End of Base64 namespace */
diff --git a/third_party/websockify/include/keysym.js b/third_party/websockify/include/keysym.js
new file mode 100644
index 00000000..b24ac889
--- /dev/null
+++ b/third_party/websockify/include/keysym.js
@@ -0,0 +1,99 @@
+/*
+ * from noVNC: HTML5 VNC client
+ * Copyright (C) 2010 Joel Martin
+ * Licensed under LGPL-3 (see LICENSE.txt)
+ */
+
+/* Translate DOM key down/up event to keysym value */
+function getKeysym(e) {
+ var evt, keysym;
+ evt = (e ? e : window.event);
+
+ /* Remap modifier and special keys */
+ switch ( evt.keyCode ) {
+ case 8 : keysym = 0xFF08; break; // BACKSPACE
+ case 9 : keysym = 0xFF09; break; // TAB
+ case 13 : keysym = 0xFF0D; break; // ENTER
+ case 27 : keysym = 0xFF1B; break; // ESCAPE