diff --git a/public/js/lib/jailed/_JailedSite.js b/public/js/lib/jailed/_JailedSite.js
deleted file mode 100644
index 54fba0fdbd..0000000000
--- a/public/js/lib/jailed/_JailedSite.js
+++ /dev/null
@@ -1,432 +0,0 @@
-
-/**
- * Contains the JailedSite object used both by the application
- * site, and by each plugin
- */
-
-(function(){
-
- /**
- * JailedSite object represents a single site in the
- * communication protocol between the application and the plugin
- *
- * @param {Object} connection a special object allowing to send
- * and receive messages from the opposite site (basically it
- * should only provide send() and onMessage() methods)
- */
- JailedSite = function(connection) {
- this._interface = {};
- this._remote = null;
- this._remoteUpdateHandler = function(){};
- this._getInterfaceHandler = function(){};
- this._interfaceSetAsRemoteHandler = function(){};
- this._disconnectHandler = function(){};
- this._store = new ReferenceStore;
-
- var me = this;
- this._connection = connection;
- this._connection.onMessage(
- function(data){ me._processMessage(data); }
- );
-
- this._connection.onDisconnect(
- function(m){
- me._disconnectHandler(m);
- }
- );
- }
-
-
- /**
- * Set a handler to be called when the remote site updates its
- * interface
- *
- * @param {Function} handler
- */
- JailedSite.prototype.onRemoteUpdate = function(handler) {
- this._remoteUpdateHandler = handler;
- }
-
-
- /**
- * Set a handler to be called when received a responce from the
- * remote site reporting that the previously provided interface
- * has been succesfully set as remote for that site
- *
- * @param {Function} handler
- */
- JailedSite.prototype.onInterfaceSetAsRemote = function(handler) {
- this._interfaceSetAsRemoteHandler = handler;
- }
-
-
- /**
- * Set a handler to be called when the remote site requests to
- * (re)send the interface. Used to detect an initialzation
- * completion without sending additional request, since in fact
- * 'getInterface' request is only sent by application at the last
- * step of the plugin initialization
- *
- * @param {Function} handler
- */
- JailedSite.prototype.onGetInterface = function(handler) {
- this._getInterfaceHandler = handler;
- }
-
-
- /**
- * @returns {Object} set of remote interface methods
- */
- JailedSite.prototype.getRemote = function() {
- return this._remote;
- }
-
-
- /**
- * Sets the interface of this site making it available to the
- * remote site by sending a message with a set of methods names
- *
- * @param {Object} _interface to set
- */
- JailedSite.prototype.setInterface = function(_interface) {
- this._interface = _interface;
- this._sendInterface();
- }
-
-
- /**
- * Sends the actual interface to the remote site upon it was
- * updated or by a special request of the remote site
- */
- JailedSite.prototype._sendInterface = function() {
- var names = [];
- for (var name in this._interface) {
- if (this._interface.hasOwnProperty(name)) {
- names.push(name);
- }
- }
-
- this._connection.send({type:'setInterface', api: names});
- }
-
-
- /**
- * Handles a message from the remote site
- */
- JailedSite.prototype._processMessage = function(data) {
- switch(data.type) {
- case 'method':
- var method = this._interface[data.name];
- var args = this._unwrap(data.args);
- method.apply(null, args);
- break;
- case 'callback':
- var method = this._store.fetch(data.id)[data.num];
- var args = this._unwrap(data.args);
- method.apply(null, args);
- break;
- case 'setInterface':
- this._setRemote(data.api);
- break;
- case 'getInterface':
- this._sendInterface();
- this._getInterfaceHandler();
- break;
- case 'interfaceSetAsRemote':
- this._interfaceSetAsRemoteHandler();
- break;
- case 'disconnect':
- this._disconnectHandler();
- this._connection.disconnect();
- break;
- }
- }
-
-
- /**
- * Sends a requests to the remote site asking it to provide its
- * current interface
- */
- JailedSite.prototype.requestRemote = function() {
- this._connection.send({type:'getInterface'});
- }
-
-
- /**
- * Sets the new remote interface provided by the other site
- *
- * @param {Array} names list of function names
- */
- JailedSite.prototype._setRemote = function(names) {
- this._remote = {};
- var i, name;
- for (i = 0; i < names.length; i++) {
- name = names[i];
- this._remote[name] = this._genRemoteMethod(name);
- }
-
- this._remoteUpdateHandler();
- this._reportRemoteSet();
- }
-
-
- /**
- * Generates the wrapped function corresponding to a single remote
- * method. When the generated function is called, it will send the
- * corresponding message to the remote site asking it to execute
- * the particular method of its interface
- *
- * @param {String} name of the remote method
- *
- * @returns {Function} wrapped remote method
- */
- JailedSite.prototype._genRemoteMethod = function(name) {
- var me = this;
- var remoteMethod = function() {
- me._connection.send({
- type: 'method',
- name: name,
- args: me._wrap(arguments)
- });
- };
-
- return remoteMethod;
- }
-
-
- /**
- * Sends a responce reporting that interface just provided by the
- * remote site was sucessfully set by this site as remote
- */
- JailedSite.prototype._reportRemoteSet = function() {
- this._connection.send({type:'interfaceSetAsRemote'});
- }
-
-
- /**
- * Prepares the provided set of remote method arguments for
- * sending to the remote site, replaces all the callbacks with
- * identifiers
- *
- * @param {Array} args to wrap
- *
- * @returns {Array} wrapped arguments
- */
- JailedSite.prototype._wrap = function(args) {
- var wrapped = [];
- var callbacks = {};
- var callbacksPresent = false;
- for (var i = 0; i < args.length; i++) {
- if (typeof args[i] == 'function') {
- callbacks[i] = args[i];
- wrapped[i] = {type: 'callback', num : i};
- callbacksPresent = true;
- } else {
- wrapped[i] = {type: 'argument', value : args[i]};
- }
- }
-
- var result = {args: wrapped};
-
- if (callbacksPresent) {
- result.callbackId = this._store.put(callbacks);
- }
-
- return result;
- }
-
-
- /**
- * Unwraps the set of arguments delivered from the remote site,
- * replaces all callback identifiers with a function which will
- * initiate sending that callback identifier back to other site
- *
- * @param {Object} args to unwrap
- *
- * @returns {Array} unwrapped args
- */
- JailedSite.prototype._unwrap = function(args) {
- var called = false;
-
- // wraps each callback so that the only one could be called
- var once = function(cb) {
- return function() {
- if (!called) {
- called = true;
- cb.apply(this, arguments);
- } else {
- var msg =
- 'A callback from this set has already been executed';
- throw new Error(msg);
- }
- };
- }
-
- var result = [];
- var i, arg, cb, me = this;
- for (i = 0; i < args.args.length; i++) {
- arg = args.args[i];
- if (arg.type == 'argument') {
- result.push(arg.value);
- } else {
- cb = once(
- this._genRemoteCallback(args.callbackId, i)
- );
- result.push(cb);
- }
- }
-
- return result;
- }
-
-
- /**
- * Generates the wrapped function corresponding to a single remote
- * callback. When the generated function is called, it will send
- * the corresponding message to the remote site asking it to
- * execute the particular callback previously saved during a call
- * by the remote site a method from the interface of this site
- *
- * @param {Number} id of the remote callback to execute
- * @param {Number} argNum argument index of the callback
- *
- * @returns {Function} wrapped remote callback
- */
- JailedSite.prototype._genRemoteCallback = function(id, argNum) {
- var me = this;
- var remoteCallback = function() {
- me._connection.send({
- type : 'callback',
- id : id,
- num : argNum,
- args : me._wrap(arguments)
- });
- };
-
- return remoteCallback;
- }
-
-
- /**
- * Sends the notification message and breaks the connection
- */
- JailedSite.prototype.disconnect = function() {
- this._connection.send({type: 'disconnect'});
- this._connection.disconnect();
- }
-
-
- /**
- * Set a handler to be called when received a disconnect message
- * from the remote site
- *
- * @param {Function} handler
- */
- JailedSite.prototype.onDisconnect = function(handler) {
- this._disconnectHandler = handler;
- }
-
-
-
-
- /**
- * ReferenceStore is a special object which stores other objects
- * and provides the references (number) instead. This reference
- * may then be sent over a json-based communication channel (IPC
- * to another Node.js process or a message to the Worker). Other
- * site may then provide the reference in the responce message
- * implying the given object should be activated.
- *
- * Primary usage for the ReferenceStore is a storage for the
- * callbacks, which therefore makes it possible to initiate a
- * callback execution by the opposite site (which normally cannot
- * directly execute functions over the communication channel).
- *
- * Each stored object can only be fetched once and is not
- * available for the second time. Each stored object must be
- * fetched, since otherwise it will remain stored forever and
- * consume memory.
- *
- * Stored object indeces are simply the numbers, which are however
- * released along with the objects, and are later reused again (in
- * order to postpone the overflow, which should not likely happen,
- * but anyway).
- */
- var ReferenceStore = function() {
- this._store = {}; // stored object
- this._indices = [0]; // smallest available indices
- }
-
-
- /**
- * @function _genId() generates the new reference id
- *
- * @returns {Number} smallest available id and reserves it
- */
- ReferenceStore.prototype._genId = function() {
- var id;
- if (this._indices.length == 1) {
- id = this._indices[0]++;
- } else {
- id = this._indices.shift();
- }
-
- return id;
- }
-
-
- /**
- * Releases the given reference id so that it will be available by
- * another object stored
- *
- * @param {Number} id to release
- */
- ReferenceStore.prototype._releaseId = function(id) {
- for (var i = 0; i < this._indices.length; i++) {
- if (id < this._indices[i]) {
- this._indices.splice(i, 0, id);
- break;
- }
- }
-
- // cleaning-up the sequence tail
- for (i = this._indices.length-1; i >= 0; i--) {
- if (this._indices[i]-1 == this._indices[i-1]) {
- this._indices.pop();
- } else {
- break;
- }
- }
- }
-
-
- /**
- * Stores the given object and returns the refernce id instead
- *
- * @param {Object} obj to store
- *
- * @returns {Number} reference id of the stored object
- */
- ReferenceStore.prototype.put = function(obj) {
- var id = this._genId();
- this._store[id] = obj;
- return id;
- }
-
-
- /**
- * Retrieves previously stored object and releases its reference
- *
- * @param {Number} id of an object to retrieve
- */
- ReferenceStore.prototype.fetch = function(id) {
- var obj = this._store[id];
- this._store[id] = null;
- delete this._store[id];
- this._releaseId(id);
- return obj;
- }
-
-
-})();
-
diff --git a/public/js/lib/jailed/_frame.html b/public/js/lib/jailed/_frame.html
deleted file mode 100644
index 68b300d6e3..0000000000
--- a/public/js/lib/jailed/_frame.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/js/lib/jailed/_frame.js b/public/js/lib/jailed/_frame.js
deleted file mode 100644
index f9e28d641e..0000000000
--- a/public/js/lib/jailed/_frame.js
+++ /dev/null
@@ -1,56 +0,0 @@
-
-/**
- * Contains the code executed in the sandboxed frame under web-browser
- *
- * Creates a Web-Worker inside the frame, sets up the communication
- * between the worker and the parent window
- */
-
-
-var scripts = document.getElementsByTagName('script');
-var __jailed__path__ = scripts[scripts.length-1].src
- .split('?')[0]
- .split('/')
- .slice(0, -1)
- .join('/') + '/';
-
-// creating worker as a blob enables import of local files
-var blobCode = [
- ' self.addEventListener("message", function(m){ ',
- ' if (m.data.type == "initImport") { ',
- ' importScripts(m.data.url); ',
- ' self.postMessage({type: "initialized"}); ',
- ' } ',
- ' }); '
-].join('\n');
-
-var blobUrl;
-try {
- blobUrl = new Blob([blobCode], {type: 'application/javascript'});
-} catch (e) {
- window.BlobBuilder = window.BlobBuilder
- || window.WebKitBlobBuilder
- || window.MozBlobBuilder;
- blobUrl = new BlobBuilder();
- blobUrl.append(blobCode);
- blobUrl = blobUrl.getBlob();
-}
-
-var worker = new Worker(URL.createObjectURL(blobUrl));
-
-// telling worker to load _pluginWeb.js (see blob code above)
-worker.postMessage({
- type: 'initImport',
- url: __jailed__path__ + '_pluginWeb.js'
-});
-
-
-// forwarding messages between the worker and parent window
-worker.addEventListener('message', function(m) {
- parent.postMessage(m.data, '*');
-});
-
-window.addEventListener('message', function(m) {
- worker.postMessage(m.data);
-});
-
diff --git a/public/js/lib/jailed/_pluginCore.js b/public/js/lib/jailed/_pluginCore.js
deleted file mode 100644
index 184113a124..0000000000
--- a/public/js/lib/jailed/_pluginCore.js
+++ /dev/null
@@ -1,95 +0,0 @@
-
-/**
- * Core plugin script loaded into the plugin process/thread.
- *
- * Initializes the plugin-site API global methods.
- */
-
-(function(){
-
- // localize
- var site = new JailedSite(connection);
- delete JailedSite;
- delete connection;
-
- site.onGetInterface(function(){
- launchConnected();
- });
-
- site.onRemoteUpdate(function(){
- application.remote = site.getRemote();
- });
-
-
-
- /**
- * Simplified clone of Whenable instance (the object can not be
- * placed into a shared script, because the main library needs it
- * before the additional scripts may load)
- */
- var connected = false;
- var connectedHandlers = [];
-
- var launchConnected = function() {
- if (!connected) {
- connected = true;
-
- var handler;
- while(handler = connectedHandlers.pop()) {
- handler();
- }
- }
- }
-
- var checkHandler = function(handler){
- var type = typeof handler;
- if (type != 'function') {
- var msg =
- 'A function may only be subsribed to the event, '
- + type
- + ' was provided instead'
- throw new Error(msg);
- }
-
- return handler;
- }
-
-
- /**
- * Sets a function executed after the connection to the
- * application is estaplished, and the initial interface-exchange
- * messaging is completed
- *
- * @param {Function} handler to be called upon initialization
- */
- application.whenConnected = function(handler) {
- handler = checkHandler(handler);
- if (connected) {
- handler();
- } else {
- connectedHandlers.push(handler);
- }
- }
-
-
- /**
- * Sets the plugin interface available to the application
- *
- * @param {Object} _interface to set
- */
- application.setInterface = function(_interface) {
- site.setInterface(_interface);
- }
-
-
-
- /**
- * Disconnects the plugin from the application (sending
- * notification message) and destroys itself
- */
- application.disconnect = function(_interface) {
- site.disconnect();
- }
-
-})();
-
diff --git a/public/js/lib/jailed/_pluginNode.js b/public/js/lib/jailed/_pluginNode.js
deleted file mode 100644
index ee9d49469b..0000000000
--- a/public/js/lib/jailed/_pluginNode.js
+++ /dev/null
@@ -1,267 +0,0 @@
-
-/**
- * Contains the routines loaded by the plugin process under Node.js
- *
- * Initializes the Node.js environment version of the
- * platform-dependent connection object for the plugin site
- */
-
-application = {};
-connection = {};
-
-
-/**
- * Prints error message and its stack
- *
- * @param {Object} msg stack provided by error.stack or a message
- */
-var printError = function(msg) {
- console.error();
- console.error(msg);
-}
-
-
-/**
- * Event lisener for the plugin message
- */
-process.on('message', function(m) {
- switch(m.type){
- case 'import':
- importScript(m.url);
- break;
- case 'importJailed':
- importScriptJailed(m.url);
- break;
- case 'execute':
- execute(m.code);
- break;
- case 'message':
- // unhandled exception would break the IPC channel
- try {
- conn._messageHandler(m.data);
- } catch(e) {
- printError(e.stack);
- }
- break;
- }
-});
-
-
-/**
- * Checks if the given path is remote
- *
- * @param {String} path to check
- * @returns {Boolean} true if path is remote
- */
-var isRemote = function(path) {
- return (path.substr(0,7).toLowerCase() == 'http://' ||
- path.substr(0,8).toLowerCase() == 'https://');
-}
-
-
-/**
- * Loads and executes the JavaScript file with the given url
- *
- * @param {String} url of the script to load
- */
-var importScript = function(url) {
- var sCb = function() {
- process.send({type: 'importSuccess', url: url});
- }
-
- var fCb = function() {
- process.send({type: 'importFailure', url: url});
- }
-
- var run = function(code) {
- executeNormal(code, url, sCb, fCb);
- }
-
- if (isRemote(url)) {
- loadRemote(url, run, fCb);
- } else {
- try {
- run(loadLocal(url));
- } catch(e) {
- printError(e.stack);
- fCb();
- }
- }
-
-}
-
-
-/**
- * Loads and executes the JavaScript file with the given url in a
- * jailed environment
- *
- * @param {String} url of the script to load
- */
-var importScriptJailed = function(url) {
- var sCb = function() {
- process.send({type: 'importSuccess', url: url});
- }
-
- var fCb = function() {
- process.send({type: 'importFailure', url: url});
- }
-
- var run = function(code) {
- executeJailed(code, url, sCb, fCb);
- }
-
- if (isRemote(url)) {
- loadRemote(url, run, fCb);
- } else {
- try {
- run(loadLocal(url));
- } catch (e) {
- printError(e.stack);
- fCb();
- }
-
- }
-
-}
-
-
-/**
- * Executes the given code in the jailed environment, sends the
- * corresponding message to the application site when succeeded/failed
- *
- * @param {String} code to execute
- */
-var execute = function(code) {
- var sCb = function() {
- process.send({type: 'executeSuccess'});
- }
-
- var fCb = function() {
- process.send({type: 'executeFailure'});
- }
-
- executeJailed(code, 'DYNAMIC PLUGIN', sCb, fCb);
-}
-
-
-/**
- * Executes the given code in the current environment / scope, runs
- * the corresponding callback when done
- *
- * @param {String} code to execute
- * @param {String} url of the script (for displaying the stack)
- * @param {Function} sCb
- * @param {Function} fCb
- */
-var executeNormal = function(code, url, sCb, fCb) {
- var err = null;
- try {
- require('vm').runInThisContext(code, url);
- sCb();
- } catch (e) {
- printError(e.stack);
- fCb();
- }
-}
-
-
-/**
- * Executes the given code in a jailed environment, runs the
- * corresponding callback when done
- *
- * @param {String} code to execute
- * @param {String} url of the script (for displaying the stack)
- * @param {Function} sCb
- * @param {Function} fCb
- */
-var executeJailed = function(code, url, sCb, fCb) {
- var vm = require('vm');
- var sandbox = {};
- var expose = [
- 'application',
- 'setTimeout',
- 'setInterval',
- 'clearTimeout',
- 'clearInterval'
- ];
-
- for (var i = 0; i < expose.length; i++) {
- sandbox[expose[i]] = global[expose[i]];
- }
-
- code = '"use strict";\n'+code;
- try {
- vm.runInNewContext(code, vm.createContext(sandbox), url);
- sCb();
- } catch (e) {
- printError(e.stack);
- fCb();
- }
-}
-
-
-/**
- * Loads local file and
- *
- * @param {String} path of the file to read
- *
- * @returns {String} file contents
- */
-var loadLocal = function(path) {
- return require("fs").readFileSync(path).toString();
-}
-
-
-/**
- * Downloads the script by remote url and provides its content as a
- * string to the callback
- *
- * @param {String} url of the remote module to load
- * @param {Function} sCb success callback
- * @param {Function} fCb failure callback
- */
-var loadRemote = function(url, sCb, fCb) {
- var receive = function(res) {
- if (res.statusCode != 200) {
- var msg = 'Failed to load ' + url + '\n' +
- 'HTTP responce status code: ' + res.statusCode;
- printError(msg);
- fCb();
- } else {
- var content = '';
- res.on('end', function(){ sCb(content); });
- res.on(
- 'readable',
- function() {
- var chunk = res.read();
- content += chunk.toString();
- }
- );
- }
- }
-
- try {
- require('http').get(url, receive).on('error', fCb);
- } catch (e) {
- printError(e.stack);
- fCb();
- }
-}
-
-
-/**
- * Connection object provided to the SandboxedSite constructor, plugin
- * site implementation for the Node.js environment
- */
-var conn = {
- disconnect: function(){ process.exit(); },
- send: function(data) {
- process.send({type: 'message', data: data});
- },
- onMessage: function(h){ conn._messageHandler = h; },
- _messageHandler: function(){},
- onDisconnect: function() {}
-};
-
-connection = conn;
-
diff --git a/public/js/lib/jailed/_pluginWeb.js b/public/js/lib/jailed/_pluginWeb.js
deleted file mode 100644
index bb250de36c..0000000000
--- a/public/js/lib/jailed/_pluginWeb.js
+++ /dev/null
@@ -1,96 +0,0 @@
-
-/**
- * Contains the routines loaded by the plugin Worker under web-browser.
- *
- * Initializes the web environment version of the platform-dependent
- * connection object for the plugin site
- */
-
-self.application = {};
-self.connection = {};
-
-
-(function(){
-
- /**
- * Event lisener for the plugin message
- */
- self.addEventListener('message', function(e){
- var m = e.data.data;
- switch (m.type) {
- case 'import':
- case 'importJailed': // already jailed in the Worker
- importScript(m.url);
- break;
- case 'execute':
- execute(m.code);
- break;
- case 'message':
- conn._messageHandler(m.data);
- break;
- }
- });
-
-
- /**
- * Loads and executes the JavaScript file with the given url
- *
- * @param {String} url to load
- */
- var importScript = function(url) {
- var error = null;
- try {
- importScripts(url);
- } catch (e) {
- error = e;
- }
-
- if (error) {
- self.postMessage({type: 'importFailure', url: url});
- throw error;
- } else {
- self.postMessage({type: 'importSuccess', url: url});
- }
-
- }
-
-
- /**
- * Executes the given code in a jailed environment. For web
- * implementation, we're already jailed in the worker, so simply
- * eval()
- *
- * @param {String} code code to execute
- */
- var execute = function(code) {
- try {
- eval(code);
- } catch (e) {
- self.postMessage({type: 'executeFailure'});
- throw e;
- }
-
- self.postMessage({type: 'executeSuccess'});
- }
-
-
- /**
- * Connection object provided to the JailedSite constructor,
- * plugin site implementation for the web-based environment.
- * Global will be then cleared to prevent exposure into the
- * Worker, so we put this local connection object into a closure
- */
- var conn = {
- disconnect: function(){ self.close(); },
- send: function(data) {
- self.postMessage({type: 'message', data: data});
- },
- onMessage: function(h){ conn._messageHandler = h; },
- _messageHandler: function(){},
- onDisconnect: function() {}
- };
-
- connection = conn;
-
-})();
-
diff --git a/public/js/lib/jailed/jailed.js b/public/js/lib/jailed/jailed.js
deleted file mode 100644
index e4525068ea..0000000000
--- a/public/js/lib/jailed/jailed.js
+++ /dev/null
@@ -1,780 +0,0 @@
-/**
- * @fileoverview Jailed - safe yet flexible sandbox
- * @version 0.2.0
- *
- * @license MIT, see http://github.com/asvd/jailed
- * Copyright (c) 2014 asvd
- *
- * Main library script, the only one to be loaded by a developer into
- * the application. Other scrips shipped along will be loaded by the
- * library either here (application site), or into the plugin site
- * (Worker/child process):
- *
- * _JailedSite.js loaded into both applicaiton and plugin sites
- * _frame.html sandboxed frame (web)
- * _frame.js sandboxed frame code (web)
- * _pluginWeb.js platform-dependent plugin routines (web)
- * _pluginNode.js platform-dependent plugin routines (Node.js)
- * _pluginCore.js common plugin site protocol implementation
- */
-
-
-var __jailed__path__;
-if (typeof window == 'undefined') {
- // Node.js
- __jailed__path__ = __dirname + '/';
-} else {
- // web
- var scripts = document.getElementsByTagName('script');
- __jailed__path__ = scripts[scripts.length-1].src
- .split('?')[0]
- .split('/')
- .slice(0, -1)
- .join('/')+'/';
-}
-
-
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define(['exports'], factory);
- } else if (typeof exports !== 'undefined') {
- factory(exports);
- } else {
- factory((root.jailed = {}));
- }
-}(this, function (exports) {
- var isNode = typeof window == 'undefined';
-
-
- /**
- * A special kind of event:
- * - which can only be emitted once;
- * - executes a set of subscribed handlers upon emission;
- * - if a handler is subscribed after the event was emitted, it
- * will be invoked immideately.
- *
- * Used for the events which only happen once (or do not happen at
- * all) during a single plugin lifecycle - connect, disconnect and
- * connection failure
- */
- var Whenable = function() {
- this._emitted = false;
- this._handlers = [];
- }
-
-
- /**
- * Emits the Whenable event, calls all the handlers already
- * subscribed, switches the object to the 'emitted' state (when
- * all future subscibed listeners will be immideately issued
- * instead of being stored)
- */
- Whenable.prototype.emit = function(){
- if (!this._emitted) {
- this._emitted = true;
-
- var handler;
- while(handler = this._handlers.pop()) {
- setTimeout(handler,0);
- }
- }
- }
-
-
- /**
- * Saves the provided function as a handler for the Whenable
- * event. This handler will then be called upon the event emission
- * (if it has not been emitted yet), or will be scheduled for
- * immediate issue (if the event has already been emmitted before)
- *
- * @param {Function} handler to subscribe for the event
- */
- Whenable.prototype.whenEmitted = function(handler){
- handler = this._checkHandler(handler);
- if (this._emitted) {
- setTimeout(handler, 0);
- } else {
- this._handlers.push(handler);
- }
- }
-
-
- /**
- * Checks if the provided object is suitable for being subscribed
- * to the event (= is a function), throws an exception if not
- *
- * @param {Object} obj to check for being subscribable
- *
- * @throws {Exception} if object is not suitable for subscription
- *
- * @returns {Object} the provided object if yes
- */
- Whenable.prototype._checkHandler = function(handler){
- var type = typeof handler;
- if (type != 'function') {
- var msg =
- 'A function may only be subsribed to the event, '
- + type
- + ' was provided instead'
- throw new Error(msg);
- }
-
- return handler;
- }
-
-
-
- /**
- * Initializes the library site for Node.js environment (loads
- * _JailedSite.js)
- */
- var initNode = function() {
- require('./_JailedSite.js');
- }
-
-
- /**
- * Initializes the library site for web environment (loads
- * _JailedSite.js)
- */
- var platformInit;
- var initWeb = function() {
- // loads additional script to the application environment
- var load = function(path, cb) {
- var script = document.createElement('script');
- script.src = path;
-
- var clear = function() {
- script.onload = null;
- script.onerror = null;
- script.onreadystatechange = null;
- script.parentNode.removeChild(script);
- }
-
- var success = function() {
- clear();
- cb();
- }
-
- script.onerror = clear;
- script.onload = success;
- script.onreadystatechange = function() {
- var state = script.readyState;
- if (state==='loaded' || state==='complete') {
- success();
- }
- }
-
- document.body.appendChild(script);
- }
-
- platformInit = new Whenable;
- var origOnload = window.onload || function(){};
-
- window.onload = function(){
- origOnload();
- load(
- __jailed__path__+'_JailedSite.js',
- function(){ platformInit.emit(); }
- );
- }
- }
-
-
- var BasicConnection;
-
- /**
- * Creates the platform-dependent BasicConnection object in the
- * Node.js environment
- */
- var basicConnectionNode = function() {
- var childProcess = require('child_process');
-
- /**
- * Platform-dependent implementation of the BasicConnection
- * object, initializes the plugin site and provides the basic
- * messaging-based connection with it
- *
- * For Node.js the plugin is created as a forked process
- */
- BasicConnection = function() {
- this._disconnected = false;
- this._messageHandler = function(){};
- this._disconnectHandler = function(){};
- this._process = childProcess.fork(
- __jailed__path__+'_pluginNode.js'
- );
-
- var me = this;
- this._process.on('message', function(m){
- me._messageHandler(m);
- });
-
- this._process.on('exit', function(m){
- me._disconnected = true;
- me._disconnectHandler(m);
- });
- }
-
-
- /**
- * Sets-up the handler to be called upon the BasicConnection
- * initialization is completed.
- *
- * For Node.js the connection is fully initialized within the
- * constructor, so simply calls the provided handler.
- *
- * @param {Function} handler to be called upon connection init
- */
- BasicConnection.prototype.whenInit = function(handler) {
- handler();
- }
-
-
- /**
- * Sends a message to the plugin site
- *
- * @param {Object} data to send
- */
- BasicConnection.prototype.send = function(data) {
- if (!this._disconnected) {
- this._process.send(data);
- }
- }
-
-
- /**
- * Adds a handler for a message received from the plugin site
- *
- * @param {Function} handler to call upon a message
- */
- BasicConnection.prototype.onMessage = function(handler) {
- this._messageHandler = function(data) {
- // broken stack would break the IPC in Node.js
- try {
- handler(data);
- } catch (e) {
- console.error();
- console.error(e.stack);
- }
- }
- }
-
-
- /**
- * Adds a handler for the event of plugin disconnection
- * (= plugin process exit)
- *
- * @param {Function} handler to call upon a disconnect
- */
- BasicConnection.prototype.onDisconnect = function(handler) {
- this._disconnectHandler = handler;
- }
-
-
- /**
- * Disconnects the plugin (= kills the forked process)
- */
- BasicConnection.prototype.disconnect = function() {
- this._process.kill('SIGKILL');
- this._disconnected = true;
- }
-
- }
-
-
- /**
- * Creates the platform-dependent BasicConnection object in the
- * web-browser environment
- */
- var basicConnectionWeb = function() {
- var perm = ['allow-scripts'];
-
- if (__jailed__path__.substr(0,7).toLowerCase() == 'file://') {
- // local instance requires extra permission
- perm.push('allow-same-origin');
- }
-
- // frame element to be cloned
- var sample = document.createElement('iframe');
- sample.src = __jailed__path__ + '_frame.html';
- sample.sandbox = perm.join(' ');
- sample.style.display = 'none';
-
-
- /**
- * Platform-dependent implementation of the BasicConnection
- * object, initializes the plugin site and provides the basic
- * messaging-based connection with it
- *
- * For the web-browser environment, the plugin is created as a
- * Worker in a sandbaxed frame
- */
- BasicConnection = function() {
- this._init = new Whenable;
- this._disconnected = false;
-
- var me = this;
- platformInit.whenEmitted(function() {
- if (!me._disconnected) {
- me._frame = sample.cloneNode(false);
- document.body.appendChild(me._frame);
-
- window.addEventListener('message', function (e) {
- if (e.origin === "null" &&
- e.source === me._frame.contentWindow) {
- if (e.data.type == 'initialized') {
- me._init.emit();
- } else {
- me._messageHandler(e.data);
- }
- }
- });
- }
- });
- }
-
-
- /**
- * Sets-up the handler to be called upon the BasicConnection
- * initialization is completed.
- *
- * For the web-browser environment, the handler is issued when
- * the plugin worker successfully imported and executed the
- * _pluginWeb.js, and replied to the application site with the
- * initImprotSuccess message.
- *
- * @param {Function} handler to be called upon connection init
- */
- BasicConnection.prototype.whenInit = function(handler) {
- this._init.whenEmitted(handler);
- }
-
-
- /**
- * Sends a message to the plugin site
- *
- * @param {Object} data to send
- */
- BasicConnection.prototype.send = function(data) {
- this._frame.contentWindow.postMessage(
- {type: 'message', data: data}, '*'
- );
- }
-
-
- /**
- * Adds a handler for a message received from the plugin site
- *
- * @param {Function} handler to call upon a message
- */
- BasicConnection.prototype.onMessage = function(handler) {
- this._messageHandler = handler;
- }
-
-
- /**
- * Adds a handler for the event of plugin disconnection
- * (not used in case of Worker)
- *
- * @param {Function} handler to call upon a disconnect
- */
- BasicConnection.prototype.onDisconnect = function(){};
-
-
- /**
- * Disconnects the plugin (= kills the frame)
- */
- BasicConnection.prototype.disconnect = function() {
- if (!this._disconnected) {
- this._disconnected = true;
- if (typeof this._frame != 'undefined') {
- this._frame.parentNode.removeChild(this._frame);
- } // otherwise farme is not yet created
- }
- }
-
- }
-
-
- if (isNode) {
- initNode();
- basicConnectionNode();
- } else {
- initWeb();
- basicConnectionWeb();
- }
-
-
-
- /**
- * Application-site Connection object constructon, reuses the
- * platform-dependent BasicConnection declared above in order to
- * communicate with the plugin environment, implements the
- * application-site protocol of the interraction: provides some
- * methods for loading scripts and executing the given code in the
- * plugin
- */
- var Connection = function(){
- this._platformConnection = new BasicConnection;
-
- this._importCallbacks = {};
- this._executeSCb = function(){};
- this._executeFCb = function(){};
- this._messageHandler = function(){};
-
- var me = this;
- this.whenInit = function(cb){
- me._platformConnection.whenInit(cb);
- };
-
- this._platformConnection.onMessage(function(m) {
- switch(m.type) {
- case 'message':
- me._messageHandler(m.data);
- break;
- case 'importSuccess':
- me._handleImportSuccess(m.url);
- break;
- case 'importFailure':
- me._handleImportFailure(m.url);
- break;
- case 'executeSuccess':
- me._executeSCb();
- break;
- case 'executeFailure':
- me._executeFCb();
- break;
- }
- });
- }
-
-
- /**
- * Tells the plugin to load a script with the given path, and to
- * execute it. Callbacks executed upon the corresponding responce
- * message from the plugin site
- *
- * @param {String} path of a script to load
- * @param {Function} sCb to call upon success
- * @param {Function} fCb to call upon failure
- */
- Connection.prototype.importScript = function(path, sCb, fCb) {
- var f = function(){};
- this._importCallbacks[path] = {sCb: sCb||f, fCb: fCb||f};
- this._platformConnection.send({type: 'import', url: path});
- }
-
-
- /**
- * Tells the plugin to load a script with the given path, and to
- * execute it in the JAILED environment. Callbacks executed upon
- * the corresponding responce message from the plugin site
- *
- * @param {String} path of a script to load
- * @param {Function} sCb to call upon success
- * @param {Function} fCb to call upon failure
- */
- Connection.prototype.importJailedScript = function(path, sCb, fCb) {
- var f = function(){};
- this._importCallbacks[path] = {sCb: sCb||f, fCb: fCb||f};
- this._platformConnection.send({type: 'importJailed', url: path});
- }
-
-
- /**
- * Sends the code to the plugin site in order to have it executed
- * in the JAILED enviroment. Assuming the execution may only be
- * requested once by the Plugin object, which means a single set
- * of callbacks is enough (unlike importing additional scripts)
- *
- * @param {String} code code to execute
- * @param {Function} sCb to call upon success
- * @param {Function} fCb to call upon failure
- */
- Connection.prototype.execute = function(code, sCb, fCb) {
- this._executeSCb = sCb||function(){};
- this._executeFCb = fCb||function(){};
- this._platformConnection.send({type: 'execute', code: code});
- }
-
-
- /**
- * Adds a handler for a message received from the plugin site
- *
- * @param {Function} handler to call upon a message
- */
- Connection.prototype.onMessage = function(handler) {
- this._messageHandler = handler;
- }
-
-
- /**
- * Adds a handler for a disconnect message received from the
- * plugin site
- *
- * @param {Function} handler to call upon disconnect
- */
- Connection.prototype.onDisconnect = function(handler) {
- this._platformConnection.onDisconnect(handler);
- }
-
-
- /**
- * Sends a message to the plugin
- *
- * @param {Object} data of the message to send
- */
- Connection.prototype.send = function(data) {
- this._platformConnection.send({
- type: 'message',
- data: data
- });
- }
-
-
- /**
- * Handles import succeeded message from the plugin
- *
- * @param {String} url of a script loaded by the plugin
- */
- Connection.prototype._handleImportSuccess = function(url) {
- var sCb = this._importCallbacks[url].sCb;
- this._importCallbacks[url] = null;
- delete this._importCallbacks[url];
- sCb();
- }
-
-
- /**
- * Handles import failure message from the plugin
- *
- * @param {String} url of a script loaded by the plugin
- */
- Connection.prototype._handleImportFailure = function(url) {
- var fCb = this._importCallbacks[url].fCb;
- this._importCallbacks[url] = null;
- delete this._importCallbacks[url];
- fCb();
- }
-
-
- /**
- * Disconnects the plugin when it is not needed anymore
- */
- Connection.prototype.disconnect = function() {
- this._platformConnection.disconnect();
- }
-
-
-
-
- /**
- * Plugin constructor, represents a plugin initialized by a script
- * with the given path
- *
- * @param {String} url of a plugin source
- * @param {Object} _interface to provide for the plugin
- */
- var Plugin = function(url, _interface) {
- this._path = url;
- this._initialInterface = _interface||{};
- this._connect();
- }
-
-
- /**
- * DynamicPlugin constructor, represents a plugin initialized by a
- * string containing the code to be executed
- *
- * @param {String} code of the plugin
- * @param {Object} _interface to provide to the plugin
- */
- var DynamicPlugin = function(code, _interface) {
- this._code = code;
- this._initialInterface = _interface||{};
- this._connect();
- }
-
-
- /**
- * Creates the connection to the plugin site
- */
- DynamicPlugin.prototype._connect =
- Plugin.prototype._connect = function() {
- this.remote = null;
-
- this._connect = new Whenable;
- this._fail = new Whenable;
- this._disconnect = new Whenable;
-
- var me = this;
-
- // binded failure callback
- this._fCb = function(){
- me._fail.emit();
- me.disconnect();
- }
-
- this._connection = new Connection;
- this._connection.whenInit(function(){
- me._init();
- });
- }
-
-
- /**
- * Creates the Site object for the plugin, and then loads the
- * common routines (_JailedSite.js)
- */
- DynamicPlugin.prototype._init =
- Plugin.prototype._init = function() {
- this._site = new JailedSite(this._connection);
-
- var me = this;
- this._site.onDisconnect(function() {
- me._disconnect.emit();
- });
-
- var sCb = function() {
- me._loadCore();
- }
-
- this._connection.importScript(
- __jailed__path__+'_JailedSite.js', sCb, this._fCb
- );
- }
-
-
- /**
- * Loads the core scirpt into the plugin
- */
- DynamicPlugin.prototype._loadCore =
- Plugin.prototype._loadCore = function() {
- var me = this;
- var sCb = function() {
- me._sendInterface();
- }
-
- this._connection.importScript(
- __jailed__path__+'_pluginCore.js', sCb, this._fCb
- );
- }
-
-
- /**
- * Sends to the remote site a signature of the interface provided
- * upon the Plugin creation
- */
- DynamicPlugin.prototype._sendInterface =
- Plugin.prototype._sendInterface = function() {
- var me = this;
- this._site.onInterfaceSetAsRemote(function() {
- if (!me._connected) {
- me._loadPlugin();
- }
- });
-
- this._site.setInterface(this._initialInterface);
- }
-
-
- /**
- * Loads the plugin body (loads the plugin url in case of the
- * Plugin)
- */
- Plugin.prototype._loadPlugin = function() {
- var me = this;
- var sCb = function() {
- me._requestRemote();
- }
-
- this._connection.importJailedScript(this._path, sCb, this._fCb);
- }
-
-
- /**
- * Loads the plugin body (executes the code in case of the
- * DynamicPlugin)
- */
- DynamicPlugin.prototype._loadPlugin = function() {
- var me = this;
- var sCb = function() {
- me._requestRemote();
- }
-
- this._connection.execute(this._code, sCb, this._fCb);
- }
-
-
- /**
- * Requests the remote interface from the plugin (which was
- * probably set by the plugin during its initialization), emits
- * the connect event when done, then the plugin is fully usable
- * (meaning both the plugin and the application can use the
- * interfaces provided to each other)
- */
- DynamicPlugin.prototype._requestRemote =
- Plugin.prototype._requestRemote = function() {
- var me = this;
- this._site.onRemoteUpdate(function(){
- me.remote = me._site.getRemote();
- me._connect.emit();
- });
-
- this._site.requestRemote();
- }
-
-
- /**
- * Disconnects the plugin immideately
- */
- DynamicPlugin.prototype.disconnect =
- Plugin.prototype.disconnect = function() {
- this._connection.disconnect();
- this._disconnect.emit();
- }
-
-
- /**
- * Saves the provided function as a handler for the connection
- * failure Whenable event
- *
- * @param {Function} handler to be issued upon disconnect
- */
- DynamicPlugin.prototype.whenFailed =
- Plugin.prototype.whenFailed = function(handler) {
- this._fail.whenEmitted(handler);
- }
-
-
- /**
- * Saves the provided function as a handler for the connection
- * success Whenable event
- *
- * @param {Function} handler to be issued upon connection
- */
- DynamicPlugin.prototype.whenConnected =
- Plugin.prototype.whenConnected = function(handler) {
- this._connect.whenEmitted(handler);
- }
-
-
- /**
- * Saves the provided function as a handler for the connection
- * failure Whenable event
- *
- * @param {Function} handler to be issued upon connection failure
- */
- DynamicPlugin.prototype.whenDisconnected =
- Plugin.prototype.whenDisconnected = function(handler) {
- this._disconnect.whenEmitted(handler);
- }
-
-
-
- exports.Plugin = Plugin;
- exports.DynamicPlugin = DynamicPlugin;
-
-}));
-
diff --git a/server/views/partials/challenge-footer.jade b/server/views/partials/challenge-footer.jade
index 732c9dadb6..2112eae1ba 100644
--- a/server/views/partials/challenge-footer.jade
+++ b/server/views/partials/challenge-footer.jade
@@ -1,4 +1,3 @@
-script(type='text/javascript', src='/js/lib/jailed/jailed.js')
script(src=rev('/js', 'vendor-challenges.js'))
script(src=rev('/js', 'commonFramework.js'))
script.