Skip to content

Commit

Permalink
gateone.js: You can now set GateOne.prefs.pingTimeout to 0/null/false…
Browse files Browse the repository at this point in the history
… to disable that feature.

gateone.js:  You can now set GateOne.prefs.keepaliveInterval to 0/null/false to disable keepalive pings.
gateone.js:  The default `GateOne.prefs.keepalive` ping has been modified from 15s to 60s.
gateone.js:  The default `GateOne.prefs.pingTimeout` has been increased from 5s to 10s.
gateone.js:  `GateOne.Base.dependencyTimeout` has been increased from 15s to 30s.
gateone.js:  `GateOne.restoreDefaults()` is much more explicit now and shouldn't mess up the hello_embedded tutorial anymore.
terminal_input.js:  Changed `GateOne.Terminal.Input.capture()` and `GateOne.Terminal.Input.disableCapture()` to attach keydown and keyup events to the IME node instead of just attaching them to the `GateOne.node` (aka `GateOne.prefs.goDiv`).  Also changed these functions to place the ✈IME textarea on the document.body.  These changes were necessary to handle the situation where terminals are created somewhere other than inside the `GateOne.node` (e.g. #gateone).  So if you create a terminal somewhere else on the page keyboard input should continue working now.
terminal_input.js:  Modified `GateOne.Terminal.Input.emulateKey()` slightly so that it handles Shift-Insert instead of relying on the global key combo event (which doesn't appear to work anymore thanks to the aforementioned changes).
Removed the 256colors2.pl and xterm-colortest.pl scripts from the tests directory since test_term_renditions.py covers all those bases.
tests/hello_embedded/static/index.html:  Revamped the whole hello_embedded tutorial.  Everything works again.  Not done yet though...  It needs a complete overhaul!  I *did* add an example of how to embed terminals outside of the #gateone element though.  This should close issue #459 (#459) and issue #441 (#441).
Themes:  Set the 'color' of `.✈new_workspace_workspace_title` in all themes so it doesn't get overridden by (generic) external CSS.
core/log.py:  Fixed a bug in `JSONAdapter.process()` that could result in lost connections if certain non-ascii characters were passed to that kind of logger.
applications/terminal/plugins/ssh/scripts/timeout.sh: Removed the -e switch that gets passed to echo.  It isn't supported on a lot of systems and isn't needed in most cases.
core/server.py:  Added a new CLI command and associated function:  install_license (e.g. gateone install_license).  It is not quite complete but it was created at the request of a (paying) customer that wanted an easy way to track Gate One licenses.  It is completely inapplicable to those adhering to the AGPLv3.
core/server.py:  Added a new WebSocket action that can be used to query the license information:  go:license_info
  • Loading branch information
liftoff committed Aug 28, 2014
1 parent ba9c247 commit cdd2d8f
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 502 deletions.
1 change: 0 additions & 1 deletion docker/Dockerfile
Expand Up @@ -45,7 +45,6 @@ RUN apt-get -y upgrade
# Install dependencies
RUN apt-get -y \
install python-pip \
python-xpyb \
python-imaging \
python-setuptools \
python-mutagen \
Expand Down
2 changes: 1 addition & 1 deletion gateone/__init__.py
Expand Up @@ -3,7 +3,7 @@
__version_info__ = (1, 2, 0)
__license__ = "AGPLv3" # ...or proprietary (see LICENSE.txt)
__author__ = 'Dan McDougall <daniel.mcdougall@liftoffsoftware.com>'
__commit__ = "20140823210437" # Gets replaced by git (holds the date/time)
__commit__ = "20140825193132" # Gets replaced by git (holds the date/time)

import os
GATEONE_DIR = os.path.dirname(os.path.abspath(__file__))
Expand Down
4 changes: 2 additions & 2 deletions gateone/applications/terminal/plugins/ssh/scripts/timeout.sh
@@ -1,7 +1,7 @@
#!/bin/sh

echo -e "\n\n\033[1mTimedout due to lack of activity.\033[0m"
echo -e "\033]_;notice|Timedout due to lack of activity.\007"
echo "\n\n\033[1mTimedout due to lack of activity.\033[0m"
echo "\033]_;notice|Timedout due to lack of activity.\007"
echo '[Press Ctrl-C to close this terminal]'
read whatever
exit 1
4 changes: 2 additions & 2 deletions gateone/applications/terminal/static/terminal.js
Expand Up @@ -497,7 +497,7 @@ go.Base.update(GateOne.Terminal, {
});
E.on("terminal:term_closed", function(term) {
// Check if the closed terminal belonged to someone else (shared) and tell the server to detach it if necessary
console.log("term_closed: " + term);
logDebug("term_closed: " + term);
});
// Open/Create our terminal database
S.openDB('terminal', go.Terminal.setDBReady, go.Terminal.terminalDBModel, go.Terminal.dbVersion);
Expand Down Expand Up @@ -1532,7 +1532,7 @@ go.Base.update(GateOne.Terminal, {
count = 0,
X = e.clientX,
Y = e.clientY,
timeout = 500;
timeout = 50;
if (pastearea.style.display != 'none') {
u.hideElement(pastearea);
go.Terminal.Input.pasteareaTemp = pastearea.onmousemove;
Expand Down
27 changes: 17 additions & 10 deletions gateone/applications/terminal/static/terminal_input.js
Expand Up @@ -326,6 +326,7 @@ GateOne.Base.update(GateOne.Terminal.Input, {
return;
} else {
go.Terminal.unHighlight();
// go.Terminal.Input.capture();
}
if (document.activeElement.tagName == "INPUT" || document.activeElement.tagName == "TEXTAREA" || document.activeElement.tagName == "SELECT" || document.activeElement.tagName == "BUTTON") {
if (document.activeElement.classList && !document.activeElement.classList.contains('✈IME')) {
Expand Down Expand Up @@ -414,7 +415,7 @@ GateOne.Base.update(GateOne.Terminal.Input, {
selectedText = u.getSelText();
if (!t.Input.inputNode) {
t.Input.inputNode = u.createElement('textarea', {'class': '✈IME', 'style': {'position': 'fixed', 'z-index': 99999, 'top': '0px', 'autocapitalize': 'off', 'autocomplete': 'off', 'autocorrect': 'off', 'spellcheck': 'false'}});
go.node.appendChild(t.Input.inputNode);
document.body.appendChild(t.Input.inputNode);
t.Input.inputNode.addEventListener('compositionstart', t.Input.onCompositionStart, true);
t.Input.inputNode.addEventListener('compositionupdate', t.Input.onCompositionUpdate, true);
t.Input.inputNode.addEventListener('compositionend', t.Input.onCompositionEnd, true);
Expand All @@ -423,9 +424,10 @@ GateOne.Base.update(GateOne.Terminal.Input, {
if (!t.Input.addedEventListeners) {
t.Input.inputNode.addEventListener('input', t.Input.onInput, false);
t.Input.inputNode.tabIndex = 1; // Just in case--this is necessary to set focus
go.node.addEventListener('keydown', t.Input.onKeyDown, true);
go.node.addEventListener('keyup', t.Input.onKeyUp, true);
t.Input.inputNode.addEventListener('paste', t.Input.onPaste, false);
t.Input.inputNode.addEventListener('blur', t.Input.disableCapture, true);
t.Input.inputNode.addEventListener('keydown', t.Input.onKeyDown, true);
t.Input.inputNode.addEventListener('keyup', t.Input.onKeyUp, true);
terms.forEach(function(termNode) {
termNode.addEventListener('copy', t.Input.onCopy, false);
termNode.addEventListener('paste', t.Input.onPaste, false);
Expand Down Expand Up @@ -472,11 +474,12 @@ GateOne.Base.update(GateOne.Terminal.Input, {
if (t.Input.InputNode) {
t.Input.inputNode.removeEventListener('input', t.Input.onInput, false);
t.Input.inputNode.tabIndex = null;
t.Input.inputNode.removeEventListener('paste', t.Input.onPaste, false);
t.Input.inputNode.removeEventListener('blur', t.Input.disableCapture, true);
t.Input.inputNode.removeEventListener('keydown', t.Input.onKeyDown, true);
t.Input.inputNode.removeEventListener('keyup', t.Input.onKeyUp, true);
u.hideElement(t.Input.inputNode);
}
go.node.removeEventListener('keydown', t.Input.onKeyDown, true);
go.node.removeEventListener('keyup', t.Input.onKeyUp, true);
terms.forEach(function(termNode) {
termNode.removeEventListener('copy', t.Input.onCopy, false);
termNode.removeEventListener('paste', t.Input.onPaste, false);
Expand All @@ -497,8 +500,7 @@ GateOne.Base.update(GateOne.Terminal.Input, {
Attached to the 'paste' event on the terminal application container; converts pasted text to plaintext and sends it to the selected terminal.
*/
var goDiv = go.node;
logDebug("go.Terminal.Input.onPaste() goDiv registered paste event.");
logDebug("go.Terminal.Input.onPaste() registered paste event.");
if (document.activeElement.tagName == "INPUT" || document.activeElement.tagName == "TEXTAREA" || document.activeElement.tagName == "SELECT" || document.activeElement.tagName == "BUTTON") {
return; // Don't do anything if the user is editing text in an input/textarea or is using a select element (so the up/down arrows work)
}
Expand Down Expand Up @@ -748,7 +750,9 @@ GateOne.Base.update(GateOne.Terminal.Input, {
}
}
} else { // Shift was held down
if (t.Input.keyTable[key.string]['shift']) {
if (key.string == 'KEY_INSERT') {
t.paste(e);
} else if (t.Input.keyTable[key.string]['shift']) {
q(t.Input.keyTable[key.string]['shift']);
// This allows the browser's native pgup and pgdown to scroll up and down when the shift key is held:
} else if (key.string == 'KEY_PAGE_UP') {
Expand Down Expand Up @@ -927,11 +931,14 @@ GateOne.Base.update(GateOne.Terminal.Input, {
}
},
handleVisibility: function(e) {
// Calls GateOne.Terminal.Input.capture() when the page becomes visible again *if* goDiv had focus before the document went invisible
/**:GateOne.Terminal.handleVisibility(e)
Calls GateOne.Terminal.Input.capture() when the page becomes visible again *if* a terminal had focus before the document went invisible.
*/
if (!u.isPageHidden()) {
// Page has become visibile again
logDebug("Ninja Mode disabled.");
if (document.activeElement == go.node) {
if (document.activeElement.classList.contains('✈terminal')) {
// Gate One was active when the page became hidden
t.Input.capture(); // Resume keyboard input
}
Expand Down
6 changes: 5 additions & 1 deletion gateone/core/log.py
Expand Up @@ -85,7 +85,11 @@ def process(self, msg, kwargs):
extra.update(kwargs.pop('metadata'))
if extra:
json_data = json.dumps(extra, sort_keys=True, ensure_ascii=False)
line = u'{json_data} {msg}'.format(json_data=json_data, msg=msg)
try:
line = u'{json_data} {msg}'.format(json_data=json_data, msg=msg)
except UnicodeDecodeError:
line = u'{json_data} {msg}'.format(
json_data=json_data, msg=repr(msg))
else:
line = msg
return (line, kwargs)
Expand Down
62 changes: 59 additions & 3 deletions gateone/core/server.py
Expand Up @@ -9,8 +9,13 @@
__version__ = '1.2.0'
__version_info__ = (1, 2, 0)
__license__ = "AGPLv3" # ...or proprietary (see LICENSE.txt)
__license_info__ = {
"license": "AGPLv3",
"users": 0, # 0 being unlimited
"version": __version__
}
__author__ = 'Dan McDougall <daniel.mcdougall@liftoffsoftware.com>'
__commit__ = "20140823210437" # Gets replaced by git (holds the date/time)
__commit__ = "20140825193132" # Gets replaced by git (holds the date/time)

# NOTE: Docstring includes reStructuredText markup for use with Sphinx.
__doc__ = '''\
Expand Down Expand Up @@ -1389,6 +1394,7 @@ def __init__(self, application, request, **kwargs):
'go:set_location': self.set_location,
'go:set_locale': self.set_locale,
'go:set_dimensions': self.set_dimensions,
'go:license_info': self.license_info,
'go:debug': self.debug,
}
# Setup some instance-specific loggers that we can later update with
Expand Down Expand Up @@ -3633,6 +3639,13 @@ def _list_connected_users(cls):
continue
return tuple(out)

def license_info(self):
"""
Returns the contents of the `__license_info__` dict to the client as
a JSON-encoded message.
"""
self.write_message(__license_info__)

@require(authenticated(), policies('gateone'))
def debug(self):
"""
Expand Down Expand Up @@ -3927,10 +3940,41 @@ def set_license():
license_path = os.path.join(GATEONE_DIR, '.license')
if os.path.exists(license_path):
with io.open(license_path, 'r', encoding='utf-8') as f:
license = f.read()
license = f.read().strip()
if license:
import json
global __license__
__license__ = license.strip()
global __license_info__
try:
license_info = json.loads(license)
except ValueError:
pass # Invalid license
__license__ = "Commercial"
__license_info__ = license_info

# TODO: Make this install in the settings_dir instead of the GATEONE_DIR so it persists after installation or re-installation
def install_license(args=sys.argv):
"""
Handles the 'install_license' CLI command. Just installs the license at the
path given via `sys.argv[1]` (first argument after the 'install_license'
command).
"""
install_path = os.path.join(GATEONE_DIR, '.license')
if len(args) < 1:
print("Usage: {0} /path/to/license.txt".format(sys.argv[0]))
sys.exit(1)
import shutil
license_path = os.path.expanduser(args[0]) # In case ~
license_path = os.path.expandvars(license_path) # In case $HOME (or similar)
if os.path.exists(install_path):
yesno = raw_input(_(
"A license file is already installed. Are you sure you want to "
"replace it? (y/n) "))
if yesno not in ('yes', 'y', 'YES', 'Y'):
sys.exit(1)
shutil.copy(license_path, install_path)
print("{0} has been installed ({1})".format(license_path, install_path))
sys.exit(0)

def main(installed=True):
global _
Expand Down Expand Up @@ -3961,6 +4005,7 @@ def main(installed=True):
enabled_applications = []
cli_commands = {} # Holds CLI commands provided by plugins/applications
cli_commands['broadcast'] = broadcast_message
cli_commands['install_license'] = install_license
go_settings = {}
log_fail_msg = _(
"You probably want to provide a different destination via "
Expand Down Expand Up @@ -4132,6 +4177,17 @@ def main(installed=True):
else:
cli_commands[command](commands[1:])
sys.exit(0)
if __license__ == "AGPLv3":
agplv3_url = 'http://www.gnu.org/licenses/agpl-3.0.html'
logging.info("Gate One License: {0} ({1})".format(
__license__, agplv3_url))
else:
logging.info(
"Gate One License: {license} (Max Users: {users}, "
"Version: {version})".format(
license=__license_info__['license'],
users=__license_info__['users'],
version=__license_info__['license']))
logging.info(_("Imported applications: {0}".format(
', '.join([a.info['name'] for a in APPLICATIONS]))))
# Change the uid/gid strings into integers
Expand Down

0 comments on commit cdd2d8f

Please sign in to comment.