From 10b398d5d74d7e14a943316d05aaa52819665e45 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 12 Jan 2014 00:34:09 -0800 Subject: [PATCH] Massive reorganization. Separate all objects into individual files. Remove duplicate namespace declarations. --- .../modules/{audio.js => AudioChannel.js} | 6 - .../modules/{guacamole.js => Client.js} | 363 ------------------ .../src/main/resources/modules/InputStream.js | 135 +++++++ .../src/main/resources/modules/IntegerPool.js | 75 ++++ .../modules/{keyboard.js => Keyboard.js} | 6 - .../resources/modules/{layer.js => Layer.js} | 6 - .../resources/modules/{mouse.js => Mouse.js} | 220 ++++++----- .../{oskeyboard.js => OnScreenKeyboard.js} | 6 - .../main/resources/modules/OutputStream.js | 81 ++++ .../src/main/resources/modules/Parser.js | 159 ++++++++ .../modules/{tunnel.js => Tunnel.js} | 6 - .../src/main/resources/modules/namespace.js | 6 - 12 files changed, 557 insertions(+), 512 deletions(-) rename guacamole-common-js/src/main/resources/modules/{audio.js => AudioChannel.js} (98%) rename guacamole-common-js/src/main/resources/modules/{guacamole.js => Client.js} (82%) create mode 100644 guacamole-common-js/src/main/resources/modules/InputStream.js create mode 100644 guacamole-common-js/src/main/resources/modules/IntegerPool.js rename guacamole-common-js/src/main/resources/modules/{keyboard.js => Keyboard.js} (99%) rename guacamole-common-js/src/main/resources/modules/{layer.js => Layer.js} (99%) rename guacamole-common-js/src/main/resources/modules/{mouse.js => Mouse.js} (99%) rename guacamole-common-js/src/main/resources/modules/{oskeyboard.js => OnScreenKeyboard.js} (99%) create mode 100644 guacamole-common-js/src/main/resources/modules/OutputStream.js create mode 100644 guacamole-common-js/src/main/resources/modules/Parser.js rename guacamole-common-js/src/main/resources/modules/{tunnel.js => Tunnel.js} (99%) delete mode 100644 guacamole-common-js/src/main/resources/modules/namespace.js diff --git a/guacamole-common-js/src/main/resources/modules/audio.js b/guacamole-common-js/src/main/resources/modules/AudioChannel.js similarity index 98% rename from guacamole-common-js/src/main/resources/modules/audio.js rename to guacamole-common-js/src/main/resources/modules/AudioChannel.js index dc7518831..cb89d045c 100644 --- a/guacamole-common-js/src/main/resources/modules/audio.js +++ b/guacamole-common-js/src/main/resources/modules/AudioChannel.js @@ -20,12 +20,6 @@ * THE SOFTWARE. */ - -/** - * Namespace for all Guacamole JavaScript objects. - * @ignore - * @namespace - */ var Guacamole = Guacamole || {}; /** diff --git a/guacamole-common-js/src/main/resources/modules/guacamole.js b/guacamole-common-js/src/main/resources/modules/Client.js similarity index 82% rename from guacamole-common-js/src/main/resources/modules/guacamole.js rename to guacamole-common-js/src/main/resources/modules/Client.js index 342395579..dfc646536 100644 --- a/guacamole-common-js/src/main/resources/modules/guacamole.js +++ b/guacamole-common-js/src/main/resources/modules/Client.js @@ -20,371 +20,8 @@ * THE SOFTWARE. */ - -/** - * Namespace for all Guacamole JavaScript objects. - * @namespace - */ var Guacamole = Guacamole || {}; -/** - * Simple Guacamole protocol parser that invokes an oninstruction event when - * full instructions are available from data received via receive(). - * - * @constructor - */ -Guacamole.Parser = function() { - - /** - * Reference to this parser. - * @private - */ - var parser = this; - - /** - * Current buffer of received data. This buffer grows until a full - * element is available. After a full element is available, that element - * is flushed into the element buffer. - * - * @private - */ - var buffer = ""; - - /** - * Buffer of all received, complete elements. After an entire instruction - * is read, this buffer is flushed, and a new instruction begins. - * - * @private - */ - var element_buffer = []; - - // The location of the last element's terminator - var element_end = -1; - - // Where to start the next length search or the next element - var start_index = 0; - - /** - * Appends the given instruction data packet to the internal buffer of - * this Guacamole.Parser, executing all completed instructions at - * the beginning of this buffer, if any. - * - * @param {String} packet The instruction data to receive. - */ - this.receive = function(packet) { - - // Truncate buffer as necessary - if (start_index > 4096 && element_end >= start_index) { - - buffer = buffer.substring(start_index); - - // Reset parse relative to truncation - element_end -= start_index; - start_index = 0; - - } - - // Append data to buffer - buffer += packet; - - // While search is within currently received data - while (element_end < buffer.length) { - - // If we are waiting for element data - if (element_end >= start_index) { - - // We now have enough data for the element. Parse. - var element = buffer.substring(start_index, element_end); - var terminator = buffer.substring(element_end, element_end+1); - - // Add element to array - element_buffer.push(element); - - // If last element, handle instruction - if (terminator == ";") { - - // Get opcode - var opcode = element_buffer.shift(); - - // Call instruction handler. - if (parser.oninstruction != null) - parser.oninstruction(opcode, element_buffer); - - // Clear elements - element_buffer.length = 0; - - } - else if (terminator != ',') - throw new Error("Illegal terminator."); - - // Start searching for length at character after - // element terminator - start_index = element_end + 1; - - } - - // Search for end of length - var length_end = buffer.indexOf(".", start_index); - if (length_end != -1) { - - // Parse length - var length = parseInt(buffer.substring(element_end+1, length_end)); - if (length == NaN) - throw new Error("Non-numeric character in element length."); - - // Calculate start of element - start_index = length_end + 1; - - // Calculate location of element terminator - element_end = start_index + length; - - } - - // If no period yet, continue search when more data - // is received - else { - start_index = buffer.length; - break; - } - - } // end parse loop - - }; - - /** - * Fired once for every complete Guacamole instruction received, in order. - * - * @event - * @param {String} opcode The Guacamole instruction opcode. - * @param {Array} parameters The parameters provided for the instruction, - * if any. - */ - this.oninstruction = null; - -}; - -/** - * An input stream abstraction used by the Guacamole client to facilitate - * transfer of files or other binary data. - * - * @constructor - * @param {String} mimetype The mimetype of the data this stream will receive. - */ -Guacamole.InputStream = function(mimetype) { - - /** - * Reference to this Guacamole.InputStream. - * @private - */ - var guac_stream = this; - - /** - * The length of this Guacamole.InputStream in bytes. - * @private - */ - var length = 0; - - /** - * The mimetype of the data contained within this blob. - */ - this.mimetype = mimetype; - - // Get blob builder - var blob_builder; - if (window.BlobBuilder) blob_builder = new BlobBuilder(); - else if (window.WebKitBlobBuilder) blob_builder = new WebKitBlobBuilder(); - else if (window.MozBlobBuilder) blob_builder = new MozBlobBuilder(); - else - blob_builder = new (function() { - - var blobs = []; - - /** @ignore */ - this.append = function(data) { - blobs.push(new Blob([data], {"type": mimetype})); - }; - - /** @ignore */ - this.getBlob = function() { - return new Blob(blobs, {"type": mimetype}); - }; - - })(); - - /** - * Receives the given ArrayBuffer, storing its data within this - * Guacamole.InputStream. - * - * @param {ArrayBuffer} buffer An ArrayBuffer containing the data to be - * received. - */ - this.receive = function(buffer) { - - blob_builder.append(buffer); - length += buffer.byteLength; - - // Call handler, if present - if (guac_stream.onreceive) - guac_stream.onreceive(buffer.byteLength); - - }; - - /** - * Closes this Guacamole.InputStream such that no further data will be - * written. - */ - this.close = function() { - - // Call handler, if present - if (guac_stream.onclose) - guac_stream.onclose(); - - // NOTE: Currently not enforced. - - }; - - /** - * Returns the current length of this Guacamole.InputStream, in bytes. - * @return {Number} The current length of this Guacamole.InputStream. - */ - this.getLength = function() { - return length; - }; - - /** - * Returns the contents of this Guacamole.InputStream as a Blob. - * @return {Blob} The contents of this Guacamole.InputStream. - */ - this.getBlob = function() { - return blob_builder.getBlob(); - }; - - /** - * Fired once for every blob of data received. - * - * @event - * @param {Number} length The number of bytes received. - */ - this.onreceive = null; - - /** - * Fired once this stream is finished and no further data will be written. - * @event - */ - this.onclose = null; - -}; - -/** - * Integer pool which returns consistently increasing integers while integers - * are in use, and previously-used integers when possible. - * @constructor - */ -Guacamole.IntegerPool = function() { - - /** - * Reference to this integer pool. - */ - var guac_pool = this; - - /** - * Array of available integers. - * @type Number[] - */ - var pool = []; - - /** - * The next integer to return if no more integers remain. - * @type Number - */ - this.next_int = 0; - - /** - * Returns the next available integer in the pool. If possible, a previously - * used integer will be returned. - * - * @return {Number} The next available integer. - */ - this.next = function() { - - // If free'd integers exist, return one of those - if (pool.length > 0) - return pool.shift(); - - // Otherwise, return a new integer - return guac_pool.next_int++; - - }; - - /** - * Frees the given integer, allowing it to be reused. - * - * @param {Number} integer The integer to free. - */ - this.free = function(integer) { - pool.push(integer); - }; - -}; - -/** - * Abstract stream which can receive data. - * - * @constructor - * @param {Guacamole.Client} client The client owning this stream. - * @param {Number} index The index of this stream. - */ -Guacamole.OutputStream = function(client, index) { - - /** - * Reference to this stream. - * @private - */ - var guac_stream = this; - - /** - * The index of this stream. - * @type Number - */ - this.index = index; - - /** - * Fired when the stream is being closed due to an error. - * - * @param {String} reason A human-readable reason describing the error. - * @param {Number} code The error code associated with the error. - */ - this.onerror = null; - - /** - * Fired whenever an acknowledgement is received from the server, indicating - * that a stream operation has completed. - * - * @event - * @param {String} message A human-readable status message related to the - * operation performed. - * @param {Number} code The error code associated with the operation. - */ - this.onack = null; - - /** - * Writes the given base64-encoded data to this stream as a blob. - * - * @param {String} data The base64-encoded data to send. - */ - this.write = function(data) { - client.sendBlob(guac_stream.index, data); - }; - - /** - * Closes this stream. - */ - this.close = function() { - client.endStream(guac_stream.index); - }; - -}; - /** * Guacamole protocol client. Given a display element and {@link Guacamole.Tunnel}, * automatically handles incoming and outgoing Guacamole instructions via the diff --git a/guacamole-common-js/src/main/resources/modules/InputStream.js b/guacamole-common-js/src/main/resources/modules/InputStream.js new file mode 100644 index 000000000..7f2e7a254 --- /dev/null +++ b/guacamole-common-js/src/main/resources/modules/InputStream.js @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +var Guacamole = Guacamole || {}; + +/** + * An input stream abstraction used by the Guacamole client to facilitate + * transfer of files or other binary data. + * + * @constructor + * @param {String} mimetype The mimetype of the data this stream will receive. + */ +Guacamole.InputStream = function(mimetype) { + + /** + * Reference to this Guacamole.InputStream. + * @private + */ + var guac_stream = this; + + /** + * The length of this Guacamole.InputStream in bytes. + * @private + */ + var length = 0; + + /** + * The mimetype of the data contained within this blob. + */ + this.mimetype = mimetype; + + // Get blob builder + var blob_builder; + if (window.BlobBuilder) blob_builder = new BlobBuilder(); + else if (window.WebKitBlobBuilder) blob_builder = new WebKitBlobBuilder(); + else if (window.MozBlobBuilder) blob_builder = new MozBlobBuilder(); + else + blob_builder = new (function() { + + var blobs = []; + + /** @ignore */ + this.append = function(data) { + blobs.push(new Blob([data], {"type": mimetype})); + }; + + /** @ignore */ + this.getBlob = function() { + return new Blob(blobs, {"type": mimetype}); + }; + + })(); + + /** + * Receives the given ArrayBuffer, storing its data within this + * Guacamole.InputStream. + * + * @param {ArrayBuffer} buffer An ArrayBuffer containing the data to be + * received. + */ + this.receive = function(buffer) { + + blob_builder.append(buffer); + length += buffer.byteLength; + + // Call handler, if present + if (guac_stream.onreceive) + guac_stream.onreceive(buffer.byteLength); + + }; + + /** + * Closes this Guacamole.InputStream such that no further data will be + * written. + */ + this.close = function() { + + // Call handler, if present + if (guac_stream.onclose) + guac_stream.onclose(); + + // NOTE: Currently not enforced. + + }; + + /** + * Returns the current length of this Guacamole.InputStream, in bytes. + * @return {Number} The current length of this Guacamole.InputStream. + */ + this.getLength = function() { + return length; + }; + + /** + * Returns the contents of this Guacamole.InputStream as a Blob. + * @return {Blob} The contents of this Guacamole.InputStream. + */ + this.getBlob = function() { + return blob_builder.getBlob(); + }; + + /** + * Fired once for every blob of data received. + * + * @event + * @param {Number} length The number of bytes received. + */ + this.onreceive = null; + + /** + * Fired once this stream is finished and no further data will be written. + * @event + */ + this.onclose = null; + +}; diff --git a/guacamole-common-js/src/main/resources/modules/IntegerPool.js b/guacamole-common-js/src/main/resources/modules/IntegerPool.js new file mode 100644 index 000000000..41aef3021 --- /dev/null +++ b/guacamole-common-js/src/main/resources/modules/IntegerPool.js @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2013 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +var Guacamole = Guacamole || {}; + +/** + * Integer pool which returns consistently increasing integers while integers + * are in use, and previously-used integers when possible. + * @constructor + */ +Guacamole.IntegerPool = function() { + + /** + * Reference to this integer pool. + */ + var guac_pool = this; + + /** + * Array of available integers. + * @type Number[] + */ + var pool = []; + + /** + * The next integer to return if no more integers remain. + * @type Number + */ + this.next_int = 0; + + /** + * Returns the next available integer in the pool. If possible, a previously + * used integer will be returned. + * + * @return {Number} The next available integer. + */ + this.next = function() { + + // If free'd integers exist, return one of those + if (pool.length > 0) + return pool.shift(); + + // Otherwise, return a new integer + return guac_pool.next_int++; + + }; + + /** + * Frees the given integer, allowing it to be reused. + * + * @param {Number} integer The integer to free. + */ + this.free = function(integer) { + pool.push(integer); + }; + +}; diff --git a/guacamole-common-js/src/main/resources/modules/keyboard.js b/guacamole-common-js/src/main/resources/modules/Keyboard.js similarity index 99% rename from guacamole-common-js/src/main/resources/modules/keyboard.js rename to guacamole-common-js/src/main/resources/modules/Keyboard.js index 28fa1e6c4..c2ce79e9f 100644 --- a/guacamole-common-js/src/main/resources/modules/keyboard.js +++ b/guacamole-common-js/src/main/resources/modules/Keyboard.js @@ -20,12 +20,6 @@ * THE SOFTWARE. */ - -/** - * Namespace for all Guacamole JavaScript objects. - * @ignore - * @namespace - */ var Guacamole = Guacamole || {}; /** diff --git a/guacamole-common-js/src/main/resources/modules/layer.js b/guacamole-common-js/src/main/resources/modules/Layer.js similarity index 99% rename from guacamole-common-js/src/main/resources/modules/layer.js rename to guacamole-common-js/src/main/resources/modules/Layer.js index 379a1a1f3..d01c453d8 100644 --- a/guacamole-common-js/src/main/resources/modules/layer.js +++ b/guacamole-common-js/src/main/resources/modules/Layer.js @@ -20,12 +20,6 @@ * THE SOFTWARE. */ - -/** - * Namespace for all Guacamole JavaScript objects. - * @ignore - * @namespace - */ var Guacamole = Guacamole || {}; /** diff --git a/guacamole-common-js/src/main/resources/modules/mouse.js b/guacamole-common-js/src/main/resources/modules/Mouse.js similarity index 99% rename from guacamole-common-js/src/main/resources/modules/mouse.js rename to guacamole-common-js/src/main/resources/modules/Mouse.js index 53560b9f6..f2ece49fa 100644 --- a/guacamole-common-js/src/main/resources/modules/mouse.js +++ b/guacamole-common-js/src/main/resources/modules/Mouse.js @@ -20,12 +20,6 @@ * THE SOFTWARE. */ - -/** - * Namespace for all Guacamole JavaScript objects. - * @ignore - * @namespace - */ var Guacamole = Guacamole || {}; /** @@ -311,6 +305,113 @@ Guacamole.Mouse = function(element) { }; +/** + * Simple container for properties describing the state of a mouse. + * + * @constructor + * @param {Number} x The X position of the mouse pointer in pixels. + * @param {Number} y The Y position of the mouse pointer in pixels. + * @param {Boolean} left Whether the left mouse button is pressed. + * @param {Boolean} middle Whether the middle mouse button is pressed. + * @param {Boolean} right Whether the right mouse button is pressed. + * @param {Boolean} up Whether the up mouse button is pressed (the fourth + * button, usually part of a scroll wheel). + * @param {Boolean} down Whether the down mouse button is pressed (the fifth + * button, usually part of a scroll wheel). + */ +Guacamole.Mouse.State = function(x, y, left, middle, right, up, down) { + + /** + * Reference to this Guacamole.Mouse.State. + * @private + */ + var guac_state = this; + + /** + * The current X position of the mouse pointer. + * @type Number + */ + this.x = x; + + /** + * The current Y position of the mouse pointer. + * @type Number + */ + this.y = y; + + /** + * Whether the left mouse button is currently pressed. + * @type Boolean + */ + this.left = left; + + /** + * Whether the middle mouse button is currently pressed. + * @type Boolean + */ + this.middle = middle + + /** + * Whether the right mouse button is currently pressed. + * @type Boolean + */ + this.right = right; + + /** + * Whether the up mouse button is currently pressed. This is the fourth + * mouse button, associated with upward scrolling of the mouse scroll + * wheel. + * @type Boolean + */ + this.up = up; + + /** + * Whether the down mouse button is currently pressed. This is the fifth + * mouse button, associated with downward scrolling of the mouse scroll + * wheel. + * @type Boolean + */ + this.down = down; + + /** + * Updates the position represented within this state object by the given + * element and clientX/clientY coordinates (commonly available within event + * objects). Position is translated from clientX/clientY (relative to + * viewport) to element-relative coordinates. + * + * @param {Element} element The element the coordinates should be relative + * to. + * @param {Number} clientX The X coordinate to translate, viewport-relative. + * @param {Number} clientY The Y coordinate to translate, viewport-relative. + */ + this.fromClientPosition = function(element, clientX, clientY) { + + guac_state.x = clientX - element.offsetLeft; + guac_state.y = clientY - element.offsetTop; + + // This is all JUST so we can get the mouse position within the element + var parent = element.offsetParent; + while (parent && !(parent === document.body)) { + guac_state.x -= parent.offsetLeft - parent.scrollLeft; + guac_state.y -= parent.offsetTop - parent.scrollTop; + + parent = parent.offsetParent; + } + + // Element ultimately depends on positioning within document body, + // take document scroll into account. + if (parent) { + var documentScrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft; + var documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop; + + guac_state.x -= parent.offsetLeft - documentScrollLeft; + guac_state.y -= parent.offsetTop - documentScrollTop; + } + + }; + +}; + /** * Provides cross-browser relative touch event translation for a given element. * @@ -712,110 +813,3 @@ Guacamole.Mouse.Touchscreen = function(element) { }; -/** - * Simple container for properties describing the state of a mouse. - * - * @constructor - * @param {Number} x The X position of the mouse pointer in pixels. - * @param {Number} y The Y position of the mouse pointer in pixels. - * @param {Boolean} left Whether the left mouse button is pressed. - * @param {Boolean} middle Whether the middle mouse button is pressed. - * @param {Boolean} right Whether the right mouse button is pressed. - * @param {Boolean} up Whether the up mouse button is pressed (the fourth - * button, usually part of a scroll wheel). - * @param {Boolean} down Whether the down mouse button is pressed (the fifth - * button, usually part of a scroll wheel). - */ -Guacamole.Mouse.State = function(x, y, left, middle, right, up, down) { - - /** - * Reference to this Guacamole.Mouse.State. - * @private - */ - var guac_state = this; - - /** - * The current X position of the mouse pointer. - * @type Number - */ - this.x = x; - - /** - * The current Y position of the mouse pointer. - * @type Number - */ - this.y = y; - - /** - * Whether the left mouse button is currently pressed. - * @type Boolean - */ - this.left = left; - - /** - * Whether the middle mouse button is currently pressed. - * @type Boolean - */ - this.middle = middle - - /** - * Whether the right mouse button is currently pressed. - * @type Boolean - */ - this.right = right; - - /** - * Whether the up mouse button is currently pressed. This is the fourth - * mouse button, associated with upward scrolling of the mouse scroll - * wheel. - * @type Boolean - */ - this.up = up; - - /** - * Whether the down mouse button is currently pressed. This is the fifth - * mouse button, associated with downward scrolling of the mouse scroll - * wheel. - * @type Boolean - */ - this.down = down; - - /** - * Updates the position represented within this state object by the given - * element and clientX/clientY coordinates (commonly available within event - * objects). Position is translated from clientX/clientY (relative to - * viewport) to element-relative coordinates. - * - * @param {Element} element The element the coordinates should be relative - * to. - * @param {Number} clientX The X coordinate to translate, viewport-relative. - * @param {Number} clientY The Y coordinate to translate, viewport-relative. - */ - this.fromClientPosition = function(element, clientX, clientY) { - - guac_state.x = clientX - element.offsetLeft; - guac_state.y = clientY - element.offsetTop; - - // This is all JUST so we can get the mouse position within the element - var parent = element.offsetParent; - while (parent && !(parent === document.body)) { - guac_state.x -= parent.offsetLeft - parent.scrollLeft; - guac_state.y -= parent.offsetTop - parent.scrollTop; - - parent = parent.offsetParent; - } - - // Element ultimately depends on positioning within document body, - // take document scroll into account. - if (parent) { - var documentScrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft; - var documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop; - - guac_state.x -= parent.offsetLeft - documentScrollLeft; - guac_state.y -= parent.offsetTop - documentScrollTop; - } - - }; - -}; - diff --git a/guacamole-common-js/src/main/resources/modules/oskeyboard.js b/guacamole-common-js/src/main/resources/modules/OnScreenKeyboard.js similarity index 99% rename from guacamole-common-js/src/main/resources/modules/oskeyboard.js rename to guacamole-common-js/src/main/resources/modules/OnScreenKeyboard.js index 446b622de..b98fa6ad2 100644 --- a/guacamole-common-js/src/main/resources/modules/oskeyboard.js +++ b/guacamole-common-js/src/main/resources/modules/OnScreenKeyboard.js @@ -20,12 +20,6 @@ * THE SOFTWARE. */ - -/** - * Namespace for all Guacamole JavaScript objects. - * @ignore - * @namespace - */ var Guacamole = Guacamole || {}; /** diff --git a/guacamole-common-js/src/main/resources/modules/OutputStream.js b/guacamole-common-js/src/main/resources/modules/OutputStream.js new file mode 100644 index 000000000..3abe503b9 --- /dev/null +++ b/guacamole-common-js/src/main/resources/modules/OutputStream.js @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2013 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +var Guacamole = Guacamole || {}; + +/** + * Abstract stream which can receive data. + * + * @constructor + * @param {Guacamole.Client} client The client owning this stream. + * @param {Number} index The index of this stream. + */ +Guacamole.OutputStream = function(client, index) { + + /** + * Reference to this stream. + * @private + */ + var guac_stream = this; + + /** + * The index of this stream. + * @type Number + */ + this.index = index; + + /** + * Fired when the stream is being closed due to an error. + * + * @param {String} reason A human-readable reason describing the error. + * @param {Number} code The error code associated with the error. + */ + this.onerror = null; + + /** + * Fired whenever an acknowledgement is received from the server, indicating + * that a stream operation has completed. + * + * @event + * @param {String} message A human-readable status message related to the + * operation performed. + * @param {Number} code The error code associated with the operation. + */ + this.onack = null; + + /** + * Writes the given base64-encoded data to this stream as a blob. + * + * @param {String} data The base64-encoded data to send. + */ + this.write = function(data) { + client.sendBlob(guac_stream.index, data); + }; + + /** + * Closes this stream. + */ + this.close = function() { + client.endStream(guac_stream.index); + }; + +}; diff --git a/guacamole-common-js/src/main/resources/modules/Parser.js b/guacamole-common-js/src/main/resources/modules/Parser.js new file mode 100644 index 000000000..ff0304673 --- /dev/null +++ b/guacamole-common-js/src/main/resources/modules/Parser.js @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +var Guacamole = Guacamole || {}; + +/** + * Simple Guacamole protocol parser that invokes an oninstruction event when + * full instructions are available from data received via receive(). + * + * @constructor + */ +Guacamole.Parser = function() { + + /** + * Reference to this parser. + * @private + */ + var parser = this; + + /** + * Current buffer of received data. This buffer grows until a full + * element is available. After a full element is available, that element + * is flushed into the element buffer. + * + * @private + */ + var buffer = ""; + + /** + * Buffer of all received, complete elements. After an entire instruction + * is read, this buffer is flushed, and a new instruction begins. + * + * @private + */ + var element_buffer = []; + + // The location of the last element's terminator + var element_end = -1; + + // Where to start the next length search or the next element + var start_index = 0; + + /** + * Appends the given instruction data packet to the internal buffer of + * this Guacamole.Parser, executing all completed instructions at + * the beginning of this buffer, if any. + * + * @param {String} packet The instruction data to receive. + */ + this.receive = function(packet) { + + // Truncate buffer as necessary + if (start_index > 4096 && element_end >= start_index) { + + buffer = buffer.substring(start_index); + + // Reset parse relative to truncation + element_end -= start_index; + start_index = 0; + + } + + // Append data to buffer + buffer += packet; + + // While search is within currently received data + while (element_end < buffer.length) { + + // If we are waiting for element data + if (element_end >= start_index) { + + // We now have enough data for the element. Parse. + var element = buffer.substring(start_index, element_end); + var terminator = buffer.substring(element_end, element_end+1); + + // Add element to array + element_buffer.push(element); + + // If last element, handle instruction + if (terminator == ";") { + + // Get opcode + var opcode = element_buffer.shift(); + + // Call instruction handler. + if (parser.oninstruction != null) + parser.oninstruction(opcode, element_buffer); + + // Clear elements + element_buffer.length = 0; + + } + else if (terminator != ',') + throw new Error("Illegal terminator."); + + // Start searching for length at character after + // element terminator + start_index = element_end + 1; + + } + + // Search for end of length + var length_end = buffer.indexOf(".", start_index); + if (length_end != -1) { + + // Parse length + var length = parseInt(buffer.substring(element_end+1, length_end)); + if (length == NaN) + throw new Error("Non-numeric character in element length."); + + // Calculate start of element + start_index = length_end + 1; + + // Calculate location of element terminator + element_end = start_index + length; + + } + + // If no period yet, continue search when more data + // is received + else { + start_index = buffer.length; + break; + } + + } // end parse loop + + }; + + /** + * Fired once for every complete Guacamole instruction received, in order. + * + * @event + * @param {String} opcode The Guacamole instruction opcode. + * @param {Array} parameters The parameters provided for the instruction, + * if any. + */ + this.oninstruction = null; + +}; diff --git a/guacamole-common-js/src/main/resources/modules/tunnel.js b/guacamole-common-js/src/main/resources/modules/Tunnel.js similarity index 99% rename from guacamole-common-js/src/main/resources/modules/tunnel.js rename to guacamole-common-js/src/main/resources/modules/Tunnel.js index d4b83685b..596c4cbf2 100644 --- a/guacamole-common-js/src/main/resources/modules/tunnel.js +++ b/guacamole-common-js/src/main/resources/modules/Tunnel.js @@ -20,12 +20,6 @@ * THE SOFTWARE. */ - -/** - * Namespace for all Guacamole JavaScript objects. - * @ignore - * @namespace - */ var Guacamole = Guacamole || {}; /** diff --git a/guacamole-common-js/src/main/resources/modules/namespace.js b/guacamole-common-js/src/main/resources/modules/namespace.js deleted file mode 100644 index 4e722e389..000000000 --- a/guacamole-common-js/src/main/resources/modules/namespace.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Namespace for all Guacamole JavaScript objects. - * @ignore - * @namespace - */ -var Guacamole = Guacamole || {}; \ No newline at end of file