gateone.js:  Added GateOne.terminals.count() which simply returns the number of open terminals.
gateone.js:  Instead of loading the accept_certificate.html page in the current window (so the user can accept Gate One's SSL certificate when embedding) a new window will be opened to accept_certificate.html instead.  This window will be checked at an interval and the <Gate One URL>/combined_js will be reloaded when it is closed.  This should allow the user to accept Gate One's SSL certificate without having to leave the current web page.
accept_certificate.html:  Instead of redirecting the user to the previous page in the browser's history the JavaScript will simply call window.close().  This works well in conjunction with the new SSL error logic inside of gateone.js (see previous note).
gateone.py:  Changed how the api_keys option is determined so that you can override it on the command line if you want.
gateone.py:  Added 'command' to the Application settings dict so that plugins can more easily access that option.
gateone.py:  Fixed a bug in API authentication where self._current_user wasn't getting set after successful authentication.
setup.py:  Gate One will now require Tornado 2.4+.
gateone.js:  Fixed a bug where the *callback* passed to GateOne.init() wasn't getting called when the WebSocket was connected successfully.
gateone.js:  Removed and unnecessary getEmDimensions() call in GateOne.Terminal.termUpdateFromWorker().
gateone.js:  The window.onresize function is now assigned to GateOne.onResizeEvent() so it can be overridden.
gateone.js:  The code that attaches the window.onresize event has been changed to use window.addEventListener() so as to avoid conflicts when embedding.
gateone.js:  Fixed a bug where the top of the terminal could get cut off when you resized it (to a larger size).
gateone.js:  Added a new event:  "connection_error".  It gets triggered when the WebSocket is disconnected (inside of GateOne.Net.connectionError()).  The primary purpose of this event is so that developers that embed Gate One will have a way to automatically grab a new 'auth' object so the user won't have to reload the page to get reconnected (without encountering an authentication error).
auth.py:  Modified APIAuthHandler slightly:  It will now delete the "gateone_user" cookie every time it is called (just a security precaution).
gateone.js:  Added a "connected" event that gets triggered after the WebSocket connection is established successfully (gets called before GateOne.initialize()).
gateone.js:  Added a "initialized" event that gets triggered at the end of GateOne.initialize().
gateone.js:  Added a "term_updated" event that deprecates GateOne.Terminal.updateTermCallbacks.
gateone.js:  Added a "term_closed" event that deprecates GateOne.Terminal.closeTermCallbacks.
gateone.js:  Made it so that the callback that can be passed to GateOne.init() will be called after GateOne.initialize() instead of after the connection is opened.  I may remove this in the future since you can now use GateOne.Events.on("initialized", yourFunc) instead.
gateone.py:  The JSPluginsHandler has been modified to store combined_plugins.js in the session_dir instead of the static_dir.  This should work around the problem where the static dir is read-only.
setup.py:  Removed the combined_js logic since it is no longer necessary (Gate One re-creates that file every time it starts).
gateone.py:  Added a new plugin hook type:  PLUGIN_ENV_HOOKS.  It will allow plugins to set or override the environment variables that get set before the 'command' is executed.  This should allow things like: command = "/path/to/some_script.sh $PLUGIN_VAR1 $PLUGIN_VAR2".  To take advantage of this just add an 'Environment' dict to the 'hooks' dict in your plugin.  e.g. hooks = {'Environment': {'PLUGIN_VAR1': 'whatever you want'}}
Example Plugin:  An example of the new 'Environment' hook has been added.
gateone.js:  Added a new event:  "term_reattach".  It gets called inside of GateOne.Terminal.reattachTerminalsAction(), deprecating GateOne.Terminal.reattachTerminalsCallbacks.
gateone.js:  Added a new event:  "user_login".  It gets called inside of GateOne.User.setUsername(), deprecating GateOne.User.userLoginCallbacks.
gateone.js:  Added a new event:  "user_logout".  It gets called inside of GateOne.User.logout() with the user's username as the only argument.
gateone.js:  Changed the location of a few calls to GateOne.Logging.deprecated() so these warning messages will only get called once instead of inside of loops.
Bookmarks Plugin:  Updated to use the "user_login" event instead of GateOne.User.userLoginCallbacks.
Playback Plugin:  Updated to use the "new_terminal", "term_updated", and "save_prefs" events instead of their deprecated <whatever>Callbacks equivalents.
SSH Plugin:  Updated to use the "new_terminal" event just like the Playback plugin.
SSH Plugin:  Added some validation to the logic that lets you load an ssh:// or telnet:// URL via a query string (e.g. https://gateone/?ssh=ssh://foo@bar:22)
auth.py:  Added an 'ip_address' attribute to all user objects so that it can be used by the forthcoming authorization framework.
gateone.js:  Added some extra conditionals inside of GateOne.Input.onMouseUp() and GateOne.Input.onMouseDown() to prevent some benign exceptions that can occur if the user clicks on #gateone before it has a terminal present.
gateone.js:  When setting the default for 'selectedTerminal' in localStorage it will now include GateOne.location in the prefix.
gateone.js:  GateOne.Utils.getEmDimensions() and GateOne.Utils.getRowsAndColumns() have been modified to return undefined if the goDiv is not visible.
hello_embedded:  Changed the parts of the code that call GateOne.Net.setTerminal() to use GateOne.Terminal.switchTerminal() instead to make things more consistent with how I'm expecting folks to use that function.
Added a new module:  gopam.py.  It is a modified version of the pam-0.1.3 module by Chris AtLee <chris@atlee.ca> that adds support for setting PAM_TTY.  Why not continue using PyPAM?  PyPAM is not portable...  You get it in Linux distributions based on Debian and Red Hat but nothing else.  This module should work on any platform that uses PAM.  Also, PyPAM appears to be abandoned--the original download URL is inaccessible.  All we have left is the source packages from Debian and Red Hat.  One less thing to install too.
authpam.py:  Modified to use the new (much simpler) gopam.py instead of PyPAM (aka "PAM" in all caps).
auth.py:  Added some information about the APIAuthHandler to the docstring.
LICENSE.txt:  Added information about the gopam.py module being MIT licensed.
gateone.js:  fixed a bug with the recent change I made that sets the selectedTerminal in localStorage (was missing an underscore).
SSH Plugin:  From now on user's SSH directories will start with a dot (.) to better emulate how OpenSSH works.  This will also allow you to use a regular home directory without having to worry about keeping 'ssh' in sync with '.ssh'.  The SSH plugin will automatically rename existing directories to .ssh (if a directory with that name doesn't already exist--don't worry, it's safe :).
gateone.py:  Added a new plugin hook:  'Command'.  It gives plugins the ability to transform the configured 'command' (e.g. in server.conf) before it is executed.  So you can make your own replacement variables (like %USER%) if you like.
Example plugin:  Added an example of the new 'Command' hook.
gateone.py:  Replaces all ownership/uid checks with os.access().  It is a more appropriate test of whether or not we can write to the file/directory in question.
gateone.py:  When the user executing gateone.py doesn't have permission to write to the static_dir it will now print a warning instead of an error.  Also, it will no longer exit.  The only thing Gate One needs write access to the static_dir for is to create the symbolic links to the plugins/<plugin>/static directories.  If the user creates those links then it will work just fine without needing that write access.
gateone.py:  Swapped the use of os.getlogin() with pwd.getpwuid(os.geteuid())[0] since os.getlogin() just plain doesn't work on some systems due to the lack of utmp.
utils.py:  Just like gateone.py, the use of os.getlogin() was swapped out with pwd.getpwuid(os.geteuid())[0] everywhere.
terminal.py:  Added a note/tip about installing Pillow instead of PIL (it's a "friendly fork" that also happens to work in Python 3).
gateone.py:  Instead of creating symbolic links to each plugin's respective 'static' dir Gate One will simply add routes with their own StaticFileHandlers.
gateone.py:  combined_plugins.js will be automatically removed when Gate One is closed to ensure it gets regenerated automatically when Gate One is started.
gateone.py:  Made some changes to how combined_plugins.js is created so that it will work without the symbolic links to plugin static directories.
utils.py:  Removed the create_plugin_links() function since it is no longer being used.
utils.py:  Modified killall() to use the pid_file when killing the gateone.py process.  The two calls to this function inside gateone.py have been updated to use the new pid_file argument as well.
Various Plugin JS files:  Just a bit of housekeeping.
auth.py:  Instead of setting user['ip_address'] in the each login function 'ip_address' will simply be added to the user dict whenever get_current_user() is called.  This is to prevent the IP address from being written to the user's session file (since the session is meant to work no matter where the user is logging in from).
gateone.py:  Made a few changes here to use self.current_user instead of self.get_current_user() since it is slightly more efficient.
gateone.py:  Changed all get_current_user() functions to add the ip_address attribute to the user dict whenever it is created.
gateone.py:  Fixed a bug where the new combined_plugins.js logic was loading the .js files of plugins that were not enabled.
gateone.js:  Made a minor modification to GateOne.Terminal.termUpdateFromWorker() to avoid a benign TypeError exception that can happen if the underlying terminal gets closed while a screen update was still being processed by the Web Worker (go_process.js).
gateone.js:  Added a new function:  GateOne.Utils.loadScriptError().  It gets called when loadScript() times out trying to load a .js file.  Previously this was just an anonymous function inside loadScript()...  I made it separate so it would be easier to override (display your own error when embedding).
gateone.js:  Added a new kind of keyboard shortcut:  Global.  These shortcuts will work even if #gateone is hidden or GateOne.Input.disableCapture() has been called.  You can register them using the new GateOne.Input.registerGlobalShortcut() function.  It works identically to GateOne.Input.registerShortcut() except it creates global shortcuts (duh).  NOTE: In the event of conflicts between global shortcuts and regular ones the global shortcut will take precedence--overriding the regular shortcut.
SSH Plugin:  Updated/improved the log messages that talk about renaming/moving user's 'ssh' directories to '.ssh'.
SSH Plugin:  Replaced the use of panelToggleCallbacks with GateOne.Events.on('panel_toggle:in', func) and GateOne.Events.on('panel_toggle:out', func).
Logging Plugin:  Replaced the use of panelToggleCallbacks with GateOne.Events.on('panel_toggle:in', func) and GateOne.Events.on('panel_toggle:out', func).
Bookmarks Plugin:  Replaced the use of panelToggleCallbacks with GateOne.Events.on('panel_toggle:in', func) and GateOne.Events.on('panel_toggle:out', func).
Themes:  Added 'outline: none;' to {{container}} (aka #gateone) in all the themes since it looks better this way (we already have an overlay to indicate whether or not Gate One has focus so the outline-when-selected feature of browsers isn't necessary).
gateone.py:  Added a check to make sure that combined_plugins.js exists before we try to remove it.  This will prevent a benign OSError exception from showing up in the logs when you remove that file before stopping gateone.py.
gateone.py:  Cleaned up some leftover debugging print statements.
gateone.py:  You can now pass the 'timestamp' as an integer value (JSON) when performing API authentication; it will automatically be converted to a string before calculating the HMAC signature.
gateone.py:  API-based authentication will now fail and report an error if the api_version is not provided or is set to anything other than 1.0.
gateone.py:  When using API-based authentication any additional parameters that are provides in the 'auth' object will be attached to the 'user' dict.  This will allow applications embedding Gate One to provide their own unique values as user attributes which can be later used by plugins, access restrictions, and whatnot.
gateone.py:  Modified TerminalWebSocket.debug_terminal() to be a bit more generic and useful for debugging things other than the terminal emulator itself.
gateone.py:  Uncommented and started modifying TerminalWebSocket.get_js() since I will soon have a use for it.  Still a work-in-progress.
gateone.py:  Uncommented and renamed GateOne.Utils.loadJS() to be GateOne.Utils.loadJSAction().  Also in the process of modifying it to make it more useful.
Example Plugin:  Added a new function to the client-side JavaScript:  GateOne.Example.generateAuthObject(api_key, secret, upn).  It will return an valid 'auth' object that can be used with Gate One's API authentication mode.  Essentially it just takes care of the timestamp, api_version, signature_method and generates the 'signature' automatically using CryptoJS.HmacSHA1() (which is now included in the plugins/example/static dir).
gateone.js:  Renamed GateOne.Utils.loadStyle() to GateOne.Utils.loadStyleAction() (keeping in line with convention).  Also updated the name in the docs.
gateone.js:  Made a minor change to GateOne.Visual.displayTermInfo() so that it won't throw a benign exception if the terminal has been removed before it does its thing.
gateone.py:  When starting up Gate One will now output the version of Tornado that's installed.
gateone.py:  Fixed a broken path to combined_plugins.js in __main__.  All the logic surrounding combined_plugins.js will be replaced soon but in the mean time I'd like to keep things tidy.
gateone.py:  Changed the default path to the `pid_file` and `unix_socket_path` options from '/var/run' to '/tmp'.  This is to prevent non-root users from encountering errors when they start up Gate One for the first time.
gateone.py:  Replaced the use of os.access() with check_write_permissions() (see below).  The reason for this change is that it will allow us to correct the permissions on certain directories *before* we drop privileges.
utils.py:  Added a new function:  check_write_permissions(user, path).  It will return True if the given user has write permission for the given path.  The given 'user' can be a username/UPN or a UID.
Playback Plugin:  Removed some unused variable assignments in addPlaybackControls() that could cause benign exceptions in the JS console in certain (embedded) situations.
gateone.py:  Added an informational warning message that will be displayed when Gate One starts if auth='pam' and Gate One is running as a non-root user.
gateone.py:  Made some changes to the various failure messages that can occur when API-based authentication fails.  For most situations the client will now be sent a 'reautenticate' response.
auth.py:  Fixed a bug in require() where you could get an exception in the logs instead of a proper log message when an unauthenticated user attempted to perform an action they're not allowed to do.
gateone.js:  Modified GateOne.Net.reauthenticate() slightly:  It now clears the timeout that tells Gate One to reconnect.  There's no reason why the dialog needs to appear more than once.
MAJOR CHANGES/IMPROVEMENTS in this commit.  New settings format, new application support, relocated plugins, new functionality, etc etc.  See below for the details.
NEW GATE ONE APPLICATION:  Terminal.  Actually, it's the same terminal from before but it now exists in its own directory in the applications dir.  It even has its own plugins!  Some work still needs to be done to migrate terminal-specific stuff out of gateone.py but the hardest part is now done.
NEW SETTINGS FORMAT:  See all the new stuff in the 'settings' directory.  10server.conf will replace the usual server.conf and there's all sorts of new authentication and authorization options available as well.  More stuff like this is coming!  The whole point of this architecture change is to provide more fine-grained control over what users can do, when they can do it, how often, etc.  The change to an 'applications' directory also paves the way to supporting SFTP, X11, and more capabilities.
utils.py:  Renamed load_plugins() to load_modules().  This more accurately reflects what it does (it can load any Python module in the given list).
utils.py:  Added a new function:  get_settings(path).  It will read all files ending in .conf at a given *path* that contain JSON and return an RUDict object with the respective .conf file settings.  It will automatically strip JavaScript-style comments before decoding the JSON.
utils.py:  Added a new function:  minify(path_or_fileobj, kind).  It will minify JavaScript and CSS files using slimit and/or cssmin if they're available.  It just returns the files as-is if those modules aren't available; giving the user a message indicating they should install those modules.
utils.py:  Added a new function:  settings_template(path, **kwargs).  It will render settings templates like 'templates/settings/10server.conf' using the given *kwargs*, automatically remove blank lines (so they look nice/easy to read).
utils.py:  Added a new function:  bind(function, self).  It's just a convenience returns partial(function, self).  This allows us to write functions for things like WebSocket actions in a more natural fashion.  The code for functions like that will be outside of a class but will be written as if it were inside of it:  def foo(self)
gateone.py:  Changed the name of load_plugins to load_modules everywhere.
gateone.py:  Added a new class:  GOApplication.  It will be the base from which all Gate One applications are built.
gateone.py:  TerminalWebSocket has been renamed ApplicationWebSocket.  This is because the 'terminal' part of Gate One will soon become just another 'application' that can be run via that WebSocket.
gateone.py:  Renamed a few variables here and there to clarify their purpose (nothing interesting).
gateone.py:  Relocated some terminal-specific logic to occur that the end of various functions inside of ApplicationWebSocket.  This is to make it easier to move them into a separate GOApplication later.
gateone.py:  Changed the default command to use '.ssh' for the path to known_hosts.  Also added a warning message and convenient auto-fix if the old location is detected.
gateone.py:  Added a new method to ApplicationWebSocket:  send_js(path).  It uses the 'load_js' WebSocket action to send a JavaScript file to the client (to be loaded dynamically).
gateone.py:  Added four new methods to ApplicationWebSocket to handle various events and eventually replace the various PLUGIN_HOOKS: on(), once(), off(), and trigger().  They work similarly to the functions of the same name in gateone.js (GateOne.Events.on, once, off, trigger).  Calls to trigger() have been strewn throughout the code so that plugins and applications can take advantage of them.
gateone.js:  Modified GateOne.Utils.runPostInit() slightly:  It will now check if a module has already had its init() function called and will neglect to call it in that situation.  This will allow for running GateOne.Utils.runPostInit() at-will whenever a new plugin is loaded without having to worry about calling _every_ plugin's init() or postInit() functions.  Essentially, this makes it so I can be lazy about late-loading scripts and just call runPostInit() whenever a new script is added to the page.
gateone.js:  Removed postOnLoad() backwards-compatibility support from GateOne.Utils.runPostInit().  It has been deprecated for long enough--time to let it go.
SSH Plugin:  Fixed a bug where the KnownHostsHandler was still looking for the old 'ssh' directory path.
SSH Plugin:  Fixed a few places where ssh_connect.py was still using 'ssh' instead of '.ssh'.
SSH Plugin:  Fixed a bug where duplicate session sometimes wouldn't work because it took a little longer than expected for the new terminal to come up.
Themes:  Added '#{{container}}' before all the SVG-specific classes to ensure there's no conflicts when embedding.
Themes:  The #{{container}} style now has the background color set to match the '.terminal pre' style.  This should make playback exports look better.
app_terminal.py:  Initial public version.  Many changes in regards to how plugins are initialized and how their functions are initialized...  The use of the 'tws' argument for WebSockets has been replaced with the use of the utils.bind() method.
setup.py:  Added logic to move existing terminal-specific plugins into the applications/terminal/plugins directory (before they're updated with the latest code).
Mobile Plugin:  Removed mobile.py and moved the <head> bits to Gate One's index.html.  There's realy no reason that needs its own Python module.
Documentation:  Started updating various docs to reflect all the above changes.
gateone.py:  Removed a bunch of TODO comments that have been done.
Added some missing templates.
Added a number of .example files to the settings directory to demonstrate some of the new ways Gate One can be configured.
utils.py:  Changed how get_applications() works...  It will now use the new settings format instead of the applications.conf file.  It also requires the path to the settings directory as the second argument.
gateone.py:  Changed how applications are imported slightly to make sure we use the appropriate settings_dir.
Added the missing app_terminal.py