Fix most of things

This commit is contained in:
Florian Mounier
2016-08-19 17:41:26 +02:00
parent fe258f44f8
commit 3c2bf35b09
8 changed files with 155 additions and 217 deletions

View File

@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__version__ = '2.0.3'
__version__ = '2.1.0'
import os

View File

@@ -119,7 +119,6 @@ class TermCtlWebSocket(Route, tornado.websocket.WebSocketHandler):
sessions_secure_users = {}
def open(self, session):
self.set_nodelay(True)
self.session = session
self.closed = False
self.log.info('Websocket /ctl opened %r' % self)
@@ -145,18 +144,24 @@ class TermCtlWebSocket(Route, tornado.websocket.WebSocketHandler):
# Certificate authed user
secure_user = user
elif socket.local and socket.user == utils.User():
elif socket.local and socket.user == utils.User() and not user:
# Local to local returning browser user
secure_user = socket.user
elif user:
try:
user = utils.User(name=user)
except LookupError:
raise Exception('Invalid user')
if secure_user:
user = secure_user.name
if self.session in self.sessions:
if user != self.sessions_secure_users[self.session]:
user = secure_user
if self.session in self.sessions and self.session in (
self.sessions_secure_users):
if user.name != self.sessions_secure_users[self.session]:
# Restrict to authorized users
raise tornado.web.HTTPError(403)
else:
self.sessions_secure_users[self.session] = user
self.sessions_secure_users[self.session] = user.name
self.sessions[self.session].append(self)
@@ -192,7 +197,11 @@ class TermCtlWebSocket(Route, tornado.websocket.WebSocketHandler):
if cmd['cmd'] == 'open':
self.create_terminal()
else:
try:
Terminal.sessions[self.session].ctl(cmd)
except Exception:
# FF strange bug
pass
self.broadcast(self.session, message, self)
def on_close(self):
@@ -203,6 +212,14 @@ class TermCtlWebSocket(Route, tornado.websocket.WebSocketHandler):
if self in self.sessions[self.session]:
self.sessions[self.session].remove(self)
opts = tornado.options.options
if opts.one_shot or (
self.application.systemd and
not sum([
len(wsockets)
for session, wsockets in self.sessions.items()])):
sys.exit(0)
@url(r'/ws/session/(?P<session>[^/]+)')
class TermWebSocket(Route, tornado.websocket.WebSocketHandler):
@@ -259,14 +276,6 @@ class TermWebSocket(Route, tornado.websocket.WebSocketHandler):
self.log.info('Websocket /ws closed %r' % self)
self.sessions[self.session].remove(self)
opts = tornado.options.options
if opts.one_shot or (
self.application.systemd and
not sum([
len(wsockets)
for session, wsockets in self.sessions.items()])):
sys.exit(0)
@url(r'/sessions/list.json')
class SessionsList(Route):

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,5 @@
(function() {
var $, State, Terminal, cancel, cols, cutMessage, openTs, quit, rows, s, uuid, ws,
slice = [].slice,
var $, State, Terminal, cancel, cols, openTs, quit, rows, s, uuid, ws,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
cols = rows = null;
@@ -9,11 +8,9 @@
openTs = (new Date()).getTime();
cutMessage = '\r\nCutting...... 8< ...... 8< ...... ' + '\r\nYou can release when there is no more output.' + '\r\nCutting...... 8< ...... 8< ......' + '\r\nCutting...... 8< ...... 8< ......';
ws = {
shell: null,
termctl: null
ctl: null
};
$ = document.querySelectorAll.bind(document);
@@ -28,22 +25,8 @@
};
document.addEventListener('DOMContentLoaded', function() {
var close, ctl, error, open, path, rootPath, send, term, wsUrl;
var close, ctl, error, init_ctl_ws, init_shell_ws, open, path, reopenOnClose, rootPath, term, write, write_request, wsUrl;
term = null;
send = function(data) {
return ws.shell.send(data);
};
ctl = function() {
var args, type;
type = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
if (type === 'Resize') {
return ws.termctl.send(JSON.stringify({
cmd: 'size',
cols: args[0],
rows: args[1]
}));
}
};
if (location.protocol === 'https:') {
wsUrl = 'wss://';
} else {
@@ -60,104 +43,88 @@
}
path += location.search;
ws.shell = new WebSocket(wsUrl + '/ws' + path);
ws.termctl = new WebSocket(wsUrl + '/ctl' + path);
ws.ctl = new WebSocket(wsUrl + '/ctl' + path);
open = function() {
console.log("WebSocket open", arguments);
if (ws.shell.readyState === WebSocket.OPEN && ws.termctl.readyState === WebSocket.OPEN) {
term = new Terminal(document.body, send, ctl);
if (term) {
term.body.classList.remove('stopped');
term.out = ws.shell.send.bind(ws.shell);
term.out('\x03\n');
return;
}
if (ws.shell.readyState === WebSocket.OPEN && ws.ctl.readyState === WebSocket.OPEN) {
term = new Terminal(document.body, ws.shell.send.bind(ws.shell), ws.ctl.send.bind(ws.ctl));
term.ws = ws;
window.butterfly = term;
ws.termctl.send(JSON.stringify({
ws.ctl.send(JSON.stringify({
cmd: 'open'
}));
ws.termctl.send(JSON.stringify({
ws.ctl.send(JSON.stringify({
cmd: 'size',
cols: term.cols,
rows: term.rows
}));
return openTs = (new Date()).getTime();
openTs = (new Date()).getTime();
}
return console.log("WebSocket open end", arguments);
};
error = function() {
return console.log("WebSocket error", arguments);
return console.error("WebSocket error", arguments);
};
close = function() {
console.log("WebSocket closed", arguments);
if (quit) {
return;
}
setTimeout(function() {
quit = true;
term.write('Closed');
term.skipNextKey = true;
term.body.classList.add('dead');
if ((new Date()).getTime() - openTs > 60 * 1000) {
return window.open('', '_self').close();
}
}, 1);
return quit = true;
};
ws.shell.addEventListener('open', open);
ws.termctl.addEventListener('open', open);
ws.shell.addEventListener('error', error);
ws.termctl.addEventListener('error', error);
ws.shell.addEventListener('close', close);
ws.termctl.addEventListener('close', close);
ws.shell.addEventListener('message', function(e) {
var letter;
if (term.stop == null) {
return term.write(e.data);
} else {
if (term.stop < cutMessage.length) {
letter = cutMessage[term.stop++];
} else {
letter = '.';
reopenOnClose = function() {
if (quit) {
return;
}
return term.write(letter);
ws.shell = new WebSocket(wsUrl + '/ws' + path);
return init_shell_ws();
};
write = function(data) {
if (term) {
return term.write(data);
}
});
ws.termctl.addEventListener('message', function(e) {
};
write_request = function(e) {
return setTimeout(write, 1, e.data);
};
ctl = function() {
var cmd;
cmd = JSON.parse(e.data);
if (cmd.cmd === 'size') {
return term.resize(cmd.cols, cmd.rows, true);
}
});
addEventListener('beforeunload', function() {
};
init_shell_ws = function() {
ws.shell.addEventListener('open', open);
ws.shell.addEventListener('message', write_request);
ws.shell.addEventListener('error', error);
return ws.shell.addEventListener('close', reopenOnClose);
};
init_ctl_ws = function() {
ws.ctl.addEventListener('open', open);
ws.ctl.addEventListener('message', ctl);
ws.ctl.addEventListener('error', error);
return ws.ctl.addEventListener('close', close);
};
init_shell_ws();
init_ctl_ws();
return addEventListener('beforeunload', function() {
if (!quit) {
return 'This will exit the terminal session';
}
});
window.bench = function(n) {
var rnd;
if (n == null) {
n = 100000000;
}
rnd = '';
while (rnd.length < n) {
rnd += Math.random().toString(36).substring(2);
}
console.time('bench');
console.profile('bench');
term.write(rnd);
console.profileEnd();
return console.timeEnd('bench');
};
return window.cbench = function(n) {
var rnd;
if (n == null) {
n = 100000000;
}
rnd = '';
while (rnd.length < n) {
rnd += "\x1b[" + (30 + parseInt(Math.random() * 20)) + "m";
rnd += Math.random().toString(36).substring(2);
}
console.time('cbench');
console.profile('cbench');
term.write(rnd);
console.profileEnd();
return console.timeEnd('cbench');
};
});
cancel = function(ev) {
@@ -217,7 +184,6 @@
this.focus();
this.startBlink();
addEventListener('keydown', this.keyDown.bind(this));
addEventListener('keyup', this.keyUp.bind(this));
addEventListener('keypress', this.keyPress.bind(this));
addEventListener('focus', this.focus.bind(this));
addEventListener('blur', this.blur.bind(this));
@@ -559,7 +525,7 @@
};
Terminal.prototype.refresh = function(force) {
var active, attr, ch, classes, cursor, data, fg, group, i, j, k, len, len1, len2, len3, len4, line, lines, m, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, x, z;
var active, attr, ch, classes, cursor, data, fg, group, i, j, k, len, len1, len2, len3, len4, line, lines, m, n, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, x;
if (force == null) {
force = false;
}
@@ -575,7 +541,7 @@
}
newOut = '';
ref2 = this.screen;
for (j = o = 0, len2 = ref2.length; o < len2; j = ++o) {
for (j = n = 0, len2 = ref2.length; n < len2; j = ++n) {
line = ref2[j];
if (!(line.dirty || force)) {
continue;
@@ -588,7 +554,7 @@
}
attr = this.cloneAttr(this.defAttr);
skipnext = false;
for (i = q = 0, ref3 = this.cols - 1; 0 <= ref3 ? q <= ref3 : q >= ref3; i = 0 <= ref3 ? ++q : --q) {
for (i = o = 0, ref3 = this.cols - 1; 0 <= ref3 ? o <= ref3 : o >= ref3; i = 0 <= ref3 ? ++o : --o) {
data = line.chars[i];
if (data.html) {
out += data.html;
@@ -724,13 +690,13 @@
lines = document.querySelectorAll('.line');
if (lines.length > this.scrollback) {
ref4 = Array.prototype.slice.call(lines, 0, lines.length - this.scrollback);
for (u = 0, len3 = ref4.length; u < len3; u++) {
line = ref4[u];
for (q = 0, len3 = ref4.length; q < len3; q++) {
line = ref4[q];
line.remove();
}
ref5 = document.querySelectorAll('.group:empty');
for (z = 0, len4 = ref5.length; z < len4; z++) {
group = ref5[z];
for (u = 0, len4 = ref5.length; u < len4; u++) {
group = ref5[u];
group.remove();
}
lines = document.querySelectorAll('.line');
@@ -1407,29 +1373,15 @@
return this.write(data + "\r\n");
};
Terminal.prototype.keyUp = function(ev) {
if (ev.keyCode === 19) {
if (this.stop == null) {
return;
}
this.body.classList.remove('stopped');
this.stop = null;
return this.out('\x03\n');
}
};
Terminal.prototype.keyDown = function(ev) {
var key, ref;
if (ev.keyCode > 15 && ev.keyCode < 19) {
return true;
}
if (ev.keyCode === 19) {
if (this.stop != null) {
return;
}
this.body.classList.add('stopped');
this.stop = 0;
this.out('\x03');
this.ws.shell.close();
return false;
}
if ((ev.shiftKey || ev.ctrlKey) && ev.keyCode === 45) {
@@ -1728,7 +1680,11 @@
return;
}
if (!notif) {
this.ctl('Resize', this.cols, this.rows);
this.ctl(JSON.stringify({
cmd: 'size',
cols: this.cols,
rows: this.rows
}));
}
if (oldCols < this.cols) {
i = this.screen.length;

File diff suppressed because one or more lines are too long

View File

@@ -73,7 +73,7 @@ class Terminal(object):
if tornado.options.options.unsecure:
if self.user:
try:
self.callee = utils.User(name=self.user)
self.callee = self.user
except LookupError:
log.debug(
"Can't switch to user %s" % self.user, exc_info=True)
@@ -198,7 +198,7 @@ class Terminal(object):
self.socket.local and
self.caller == self.callee and
server == self.callee
) or not tornado.options.options.login:
) and not tornado.options.options.login:
# User has been auth with ssl or is the same user as server
# or login is explicitly turned off
if (

View File

@@ -10,7 +10,7 @@
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# GNU General Public License for more details.s
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -18,13 +18,10 @@
cols = rows = null
quit = false
openTs = (new Date()).getTime()
cutMessage = '\r\nCutting...... 8< ...... 8< ...... ' +
'\r\nYou can release when there is no more output.' +
'\r\nCutting...... 8< ...... 8< ......' +
'\r\nCutting...... 8< ...... 8< ......'
ws =
shell: null
termctl: null
ctl: null
$ = document.querySelectorAll.bind(document)
@@ -36,13 +33,6 @@ uuid = ->
document.addEventListener 'DOMContentLoaded', ->
term = null
send = (data) ->
ws.shell.send data
ctl = (type, args...) ->
if type == 'Resize'
ws.termctl.send JSON.stringify(
cmd: 'size', cols: args[0], rows: args[1])
if location.protocol == 'https:'
wsUrl = 'wss://'
@@ -61,29 +51,38 @@ document.addEventListener 'DOMContentLoaded', ->
path += location.search
ws.shell = new WebSocket wsUrl + '/ws' + path
ws.termctl = new WebSocket wsUrl + '/ctl' + path
ws.ctl = new WebSocket wsUrl + '/ctl' + path
open = ->
console.log "WebSocket open", arguments
if (ws.shell.readyState is WebSocket.OPEN and
ws.termctl.readyState is WebSocket.OPEN)
term = new Terminal document.body, send, ctl
if term
term.body.classList.remove 'stopped'
term.out = ws.shell.send.bind(ws.shell)
term.out '\x03\n'
return
if (ws.shell.readyState is WebSocket.OPEN and
ws.ctl.readyState is WebSocket.OPEN)
term = new Terminal(
document.body, ws.shell.send.bind(ws.shell), ws.ctl.send.bind(ws.ctl))
term.ws = ws
window.butterfly = term
ws.termctl.send JSON.stringify(cmd: 'open')
ws.termctl.send JSON.stringify(
ws.ctl.send JSON.stringify(cmd: 'open')
ws.ctl.send JSON.stringify(
cmd: 'size', cols: term.cols, rows: term.rows)
openTs = (new Date()).getTime()
console.log "WebSocket open end", arguments
error = ->
console.log "WebSocket error", arguments
console.error "WebSocket error", arguments
close = ->
console.log "WebSocket closed", arguments
return if quit
quit = true
setTimeout ->
term.write 'Closed'
# Allow quick reload
term.skipNextKey = true
@@ -91,57 +90,39 @@ document.addEventListener 'DOMContentLoaded', ->
# Don't autoclose if websocket didn't last 1 minute
if (new Date()).getTime() - openTs > 60 * 1000
window.open('','_self').close()
, 1
quit = true
ws.shell.addEventListener 'open', open
ws.termctl.addEventListener 'open', open
reopenOnClose = ->
return if quit
ws.shell = new WebSocket wsUrl + '/ws' + path
init_shell_ws()
ws.shell.addEventListener 'error', error
ws.termctl.addEventListener 'error', error
write = (data) ->
if term
term.write data
ws.shell.addEventListener 'close', close
ws.termctl.addEventListener 'close', close
write_request = (e) ->
setTimeout write, 1, e.data
ws.shell.addEventListener 'message', (e) ->
unless term.stop?
term.write e.data
else
if term.stop < cutMessage.length
letter = cutMessage[term.stop++]
else
letter = '.'
term.write letter
ws.termctl.addEventListener 'message', (e) ->
ctl = ->
cmd = JSON.parse(e.data)
if cmd.cmd is 'size'
term.resize cmd.cols, cmd.rows, true
init_shell_ws = ->
ws.shell.addEventListener 'open', open
ws.shell.addEventListener 'message', write_request
ws.shell.addEventListener 'error', error
ws.shell.addEventListener 'close', reopenOnClose
init_ctl_ws = ->
ws.ctl.addEventListener 'open', open
ws.ctl.addEventListener 'message', ctl
ws.ctl.addEventListener 'error', error
ws.ctl.addEventListener 'close', close
init_shell_ws()
init_ctl_ws()
addEventListener 'beforeunload', ->
if not quit
'This will exit the terminal session'
window.bench = (n=100000000) ->
rnd = ''
while rnd.length < n
rnd += Math.random().toString(36).substring(2)
console.time('bench')
console.profile('bench')
term.write rnd
console.profileEnd()
console.timeEnd('bench')
window.cbench = (n=100000000) ->
rnd = ''
while rnd.length < n
rnd += "\x1b[#{30 + parseInt(Math.random() * 20)}m"
rnd += Math.random().toString(36).substring(2)
console.time('cbench')
console.profile('cbench')
term.write rnd
console.profileEnd()
console.timeEnd('cbench')

View File

@@ -87,7 +87,6 @@ class Terminal
@startBlink()
addEventListener 'keydown', @keyDown.bind(@)
addEventListener 'keyup', @keyUp.bind(@)
addEventListener 'keypress', @keyPress.bind(@)
addEventListener 'focus', @focus.bind(@)
addEventListener 'blur', @blur.bind(@)
@@ -1258,13 +1257,6 @@ class Terminal
writeln: (data) ->
@write "#{data}\r\n"
keyUp: (ev) ->
if ev.keyCode is 19 # Pause break
return unless @stop?
@body.classList.remove 'stopped'
@stop = null
@out '\x03\n'
keyDown: (ev) ->
# Key Resources:
# https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent
@@ -1272,10 +1264,9 @@ class Terminal
return true if ev.keyCode > 15 and ev.keyCode < 19
if ev.keyCode is 19 # Pause break
return if @stop?
@body.classList.add 'stopped'
@stop = 0
@out '\x03'
@ws.shell.close()
return false
# Handle shift insert and ctrl insert
@@ -1574,7 +1565,8 @@ class Terminal
if (not x and not y) and oldCols == @cols and oldRows == @rows
return
@ctl 'Resize', @cols, @rows unless notif
@ctl(JSON.stringify(
cmd: 'size', cols: @cols, rows: @rows)) unless notif
# resize cols
if oldCols < @cols