mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
Fixed added by Gliphtodown backported to 2.1
This commit is contained in:
parent
8cbfcbb104
commit
e067f09958
13
guacamole-tunnel/.gitignore
vendored
Normal file
13
guacamole-tunnel/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Backup files
|
||||
*~
|
||||
|
||||
# Generated files
|
||||
src/main/webapp/META-INF/
|
||||
src/main/webapp/generated/
|
||||
target/
|
||||
|
||||
# IDE-specific configuration
|
||||
nb-configuration.xml
|
||||
.classpath
|
||||
.project
|
||||
|
@ -7,7 +7,7 @@
|
||||
<groupId>org.openuds.server</groupId>
|
||||
<artifactId>transport</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.1.0</version>
|
||||
<version>2.5.0</version>
|
||||
<name>Guacamole Transport</name>
|
||||
<url>https://github.com/dkmstr/openuds</url>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2013 Glyptodon LLC
|
||||
Copyright (C) 2017 Glyptodon, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -147,30 +147,12 @@
|
||||
|
||||
<!-- guacamole-default-webapp scripts -->
|
||||
<script type="text/javascript" src="scripts/session.js"></script>
|
||||
<script type="text/javascript" src="scripts/history.js"></script>
|
||||
<script type="text/javascript" src="scripts/service.js"></script>
|
||||
<script type="text/javascript" src="scripts/guac-ui.js"></script>
|
||||
<script type="text/javascript" src="scripts/client-ui.js"></script>
|
||||
|
||||
<!-- Init -->
|
||||
<script type="text/javascript"> /* <![CDATA[ */
|
||||
|
||||
/*function getQueryParams(qs) {
|
||||
qs = qs.split("+").join(" ");
|
||||
|
||||
var params = {}, tokens,
|
||||
re = /[?&]?([^=]+)=([^&]*)/g;
|
||||
|
||||
while (tokens = re.exec(qs)) {
|
||||
params[decodeURIComponent(tokens[1])]
|
||||
= decodeURIComponent(tokens[2]);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
window.query = getQueryParams(document.location.search);*/
|
||||
|
||||
// Adapted to 1.5
|
||||
function getQueryParams(qs) {
|
||||
qs = qs.split("+").join(" ");
|
||||
@ -187,16 +169,11 @@
|
||||
|
||||
window.query = getQueryParams(document.location.href);
|
||||
|
||||
// Sanity check Guacamole JavaScript API version
|
||||
// if (Guacamole.API_VERSION !== "0.9.1")
|
||||
// GuacUI.Client.showStatus("Clear Your Cache", "An older version of Guacamole has been cached by your browser. Please clear your browser's cache and try again.");
|
||||
|
||||
// Start connect after control returns from onload (allow browser
|
||||
// to consider the page loaded).
|
||||
//else
|
||||
window.onload = function() {
|
||||
window.setTimeout(GuacUI.Client.connect, 10);
|
||||
};
|
||||
window.onload = function() {
|
||||
window.setTimeout(GuacUI.Client.connect, 10);
|
||||
};
|
||||
|
||||
/* ]]> */ </script>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -746,48 +746,6 @@ GuacUI.Client.Pinch = function(element) {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Flattens the attached Guacamole.Client, storing the result within the
|
||||
* connection history.
|
||||
*/
|
||||
GuacUI.Client.updateThumbnail = function() {
|
||||
|
||||
var guac = GuacUI.Client.attachedClient;
|
||||
if (!guac)
|
||||
return;
|
||||
|
||||
// Do not create empty thumbnails
|
||||
if (guac.getDisplay().getWidth() <= 0 || guac.getDisplay().getHeight() <= 0)
|
||||
return;
|
||||
|
||||
// Get screenshot
|
||||
var canvas = guac.getDisplay().flatten();
|
||||
|
||||
// Calculate scale of thumbnail (max 320x240, max zoom 100%)
|
||||
var scale = Math.min(
|
||||
320 / canvas.width,
|
||||
240 / canvas.height,
|
||||
1
|
||||
);
|
||||
|
||||
// Create thumbnail canvas
|
||||
var thumbnail = document.createElement("canvas");
|
||||
thumbnail.width = canvas.width*scale;
|
||||
thumbnail.height = canvas.height*scale;
|
||||
|
||||
// Scale screenshot to thumbnail
|
||||
var context = thumbnail.getContext("2d");
|
||||
context.drawImage(canvas,
|
||||
0, 0, canvas.width, canvas.height,
|
||||
0, 0, thumbnail.width, thumbnail.height
|
||||
);
|
||||
|
||||
// Save thumbnail to history
|
||||
var id = decodeURIComponent(window.location.search.substring(4));
|
||||
GuacamoleHistory.update(id, thumbnail.toDataURL());
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current display scale to the given value, where 1 is 100% (1:1
|
||||
* pixel ratio). Out-of-range values will be clamped in-range.
|
||||
@ -1588,15 +1546,11 @@ GuacUI.Client.attach = function(guac) {
|
||||
}, false);
|
||||
|
||||
/*
|
||||
* Disconnect and update thumbnail on close
|
||||
* Disconnect on close
|
||||
*/
|
||||
window.onunload = function() {
|
||||
|
||||
GuacUI.Client.updateThumbnail();
|
||||
|
||||
if (GuacUI.Client.attachedClient)
|
||||
GuacUI.Client.attachedClient.disconnect();
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -45,23 +45,6 @@ GuacUI.createChildElement = function(parent, tagname, classname) {
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new row within the given table having a single header cell
|
||||
* with the given title, and a single value cell. The value cell is returned.
|
||||
*/
|
||||
GuacUI.createTabulatedContainer = function(table, title) {
|
||||
|
||||
// Create elements
|
||||
var row = GuacUI.createChildElement(table, "tr");
|
||||
var header = GuacUI.createChildElement(row, "th");
|
||||
var cell = GuacUI.createChildElement(row, "td");
|
||||
|
||||
// Set title, return cell
|
||||
header.textContent = title;
|
||||
return cell;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given CSS class to the given element.
|
||||
*/
|
||||
@ -107,55 +90,6 @@ GuacUI.removeClass = function(element, classname) {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Opens the connection group having the given ID in a new tab/window.
|
||||
*
|
||||
* @param {String} id The ID of the connection group to open.
|
||||
* @param {String} parameters Any parameters that should be added to the URL,
|
||||
* for sake of authentication.
|
||||
*/
|
||||
GuacUI.openConnectionGroup = function(id, parameters) {
|
||||
GuacUI.openObject("g/" + id, parameters);
|
||||
};
|
||||
|
||||
/**
|
||||
* Opens the connection having the given ID in a new tab/window.
|
||||
*
|
||||
* @param {String} id The ID of the connection to open.
|
||||
* @param {String} parameters Any parameters that should be added to the URL,
|
||||
* for sake of authentication.
|
||||
*/
|
||||
GuacUI.openConnection = function(id, parameters) {
|
||||
GuacUI.openObject("c/" + id, parameters);
|
||||
};
|
||||
|
||||
/**
|
||||
* Opens the object having the given ID in a new tab/window. The ID must
|
||||
* include the relevant prefix.
|
||||
*
|
||||
* @param {String} id The ID of the object to open, including prefix.
|
||||
* @param {String} parameters Any parameters that should be added to the URL,
|
||||
* for sake of authentication.
|
||||
*/
|
||||
GuacUI.openObject = function(id, parameters) {
|
||||
|
||||
// Get URL
|
||||
var url = "client.xhtml?id=" + encodeURIComponent(id);
|
||||
|
||||
// Add parameters, if given
|
||||
if (parameters)
|
||||
url += "&" + parameters;
|
||||
|
||||
// Attempt to focus existing window
|
||||
var current = window.open(null, id);
|
||||
|
||||
// If window did not already exist, set up as
|
||||
// Guacamole client
|
||||
if (!current.GuacUI)
|
||||
window.open(url, id);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Object describing the UI's level of audio support. If the user has request
|
||||
* that audio be disabled, this object will pretend that audio is not
|
||||
@ -262,237 +196,6 @@ GuacUI.Video = new (function() {
|
||||
|
||||
})();
|
||||
|
||||
/**
|
||||
* A connection UI object which can be easily added to a list of connections
|
||||
* for sake of display.
|
||||
*/
|
||||
GuacUI.ListConnection = function(connection) {
|
||||
|
||||
/**
|
||||
* Reference to this connection.
|
||||
* @private
|
||||
*/
|
||||
var guac_connection = this;
|
||||
|
||||
/**
|
||||
* The actual connection associated with this connection UI element.
|
||||
*/
|
||||
this.connection = connection;
|
||||
|
||||
/**
|
||||
* Fired when this connection is clicked.
|
||||
* @event
|
||||
*/
|
||||
this.onclick = null;
|
||||
|
||||
// Create connection display elements
|
||||
var element = GuacUI.createElement("div", "connection");
|
||||
var caption = GuacUI.createChildElement(element, "div", "caption");
|
||||
var protocol = GuacUI.createChildElement(caption, "div", "protocol");
|
||||
var name = GuacUI.createChildElement(caption, "span", "name");
|
||||
GuacUI.createChildElement(protocol, "div", "icon " + connection.protocol);
|
||||
|
||||
element.addEventListener("click", function(e) {
|
||||
|
||||
// Prevent click from affecting parent
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
// Fire event if defined
|
||||
if (guac_connection.onclick)
|
||||
guac_connection.onclick();
|
||||
|
||||
}, false);
|
||||
|
||||
// Set name
|
||||
name.textContent = connection.name;
|
||||
|
||||
// Add active usages (if any)
|
||||
var active_users = connection.currentUsage();
|
||||
if (active_users > 0) {
|
||||
var usage = GuacUI.createChildElement(caption, "span", "usage");
|
||||
usage.textContent = "Currently in use by " + active_users + " user(s)";
|
||||
GuacUI.addClass(element, "in-use");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DOM element representing this connection.
|
||||
*/
|
||||
this.getElement = function() {
|
||||
return element;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A paging component. Elements can be added via the addElement() function,
|
||||
* and will only be shown if they are on the current page, set via setPage().
|
||||
*
|
||||
* Beware that all elements will be added to the given container element, and
|
||||
* all children of the container element will be removed when the page is
|
||||
* changed.
|
||||
*/
|
||||
GuacUI.Pager = function(container) {
|
||||
|
||||
var guac_pager = this;
|
||||
|
||||
/**
|
||||
* A container for all pager control buttons.
|
||||
*/
|
||||
var element = GuacUI.createElement("div", "pager");
|
||||
|
||||
/**
|
||||
* All displayable elements.
|
||||
*/
|
||||
var elements = [];
|
||||
|
||||
/**
|
||||
* The number of elements to display per page.
|
||||
*/
|
||||
this.page_capacity = 10;
|
||||
|
||||
/**
|
||||
* The number of pages to generate a window for.
|
||||
*/
|
||||
this.window_size = 11;
|
||||
|
||||
/**
|
||||
* The current page, where 0 is the first page.
|
||||
*/
|
||||
this.current_page = 0;
|
||||
|
||||
/**
|
||||
* The last existing page.
|
||||
*/
|
||||
this.last_page = 0;
|
||||
|
||||
function update_display() {
|
||||
|
||||
var i;
|
||||
|
||||
// Calculate first and last elements of page (where the last element
|
||||
// is actually the first element of the next page)
|
||||
var first_element = guac_pager.current_page * guac_pager.page_capacity;
|
||||
var last_element = Math.min(elements.length,
|
||||
first_element + guac_pager.page_capacity);
|
||||
|
||||
// Clear contents, add elements
|
||||
container.innerHTML = "";
|
||||
for (i=first_element; i < last_element; i++)
|
||||
container.appendChild(elements[i]);
|
||||
|
||||
// Update buttons
|
||||
element.innerHTML = "";
|
||||
|
||||
// Create first and prev buttons
|
||||
var first = GuacUI.createChildElement(element, "div", "first-page icon");
|
||||
var prev = GuacUI.createChildElement(element, "div", "prev-page icon");
|
||||
|
||||
// Handle prev/first
|
||||
if (guac_pager.current_page > 0) {
|
||||
first.onclick = function() {
|
||||
guac_pager.setPage(0);
|
||||
};
|
||||
|
||||
prev.onclick = function() {
|
||||
guac_pager.setPage(guac_pager.current_page - 1);
|
||||
};
|
||||
}
|
||||
else {
|
||||
GuacUI.addClass(first, "disabled");
|
||||
GuacUI.addClass(prev, "disabled");
|
||||
}
|
||||
|
||||
// Calculate page jump window start/end
|
||||
var window_start = guac_pager.current_page - (guac_pager.window_size - 1) / 2;
|
||||
var window_end = window_start + guac_pager.window_size - 1;
|
||||
|
||||
// Shift window as necessary
|
||||
if (window_start < 0) {
|
||||
window_end = Math.min(guac_pager.last_page, window_end - window_start);
|
||||
window_start = 0;
|
||||
}
|
||||
else if (window_end > guac_pager.last_page) {
|
||||
window_start = Math.max(0, window_start - window_end + guac_pager.last_page);
|
||||
window_end = guac_pager.last_page;
|
||||
}
|
||||
|
||||
// Add ellipsis if window after beginning
|
||||
if (window_start != 0)
|
||||
GuacUI.createChildElement(element, "div", "more-pages").textContent = "...";
|
||||
|
||||
// Add page jumps
|
||||
for (i=window_start; i<=window_end; i++) {
|
||||
|
||||
// Create clickable element containing page number
|
||||
var jump = GuacUI.createChildElement(element, "div", "set-page");
|
||||
jump.textContent = i+1;
|
||||
|
||||
// Mark current page
|
||||
if (i == guac_pager.current_page)
|
||||
GuacUI.addClass(jump, "current");
|
||||
|
||||
// If not current, add click event
|
||||
else
|
||||
(function(page_number) {
|
||||
jump.onclick = function() {
|
||||
guac_pager.setPage(page_number);
|
||||
};
|
||||
})(i);
|
||||
|
||||
}
|
||||
|
||||
// Add ellipsis if window before end
|
||||
if (window_end != guac_pager.last_page)
|
||||
GuacUI.createChildElement(element, "div", "more-pages").textContent = "...";
|
||||
|
||||
// Create next and last buttons
|
||||
var next = GuacUI.createChildElement(element, "div", "next-page icon");
|
||||
var last = GuacUI.createChildElement(element, "div", "last-page icon");
|
||||
|
||||
// Handle next/last
|
||||
if (guac_pager.current_page < guac_pager.last_page) {
|
||||
next.onclick = function() {
|
||||
guac_pager.setPage(guac_pager.current_page + 1);
|
||||
};
|
||||
|
||||
last.onclick = function() {
|
||||
guac_pager.setPage(guac_pager.last_page);
|
||||
};
|
||||
}
|
||||
else {
|
||||
GuacUI.addClass(next, "disabled");
|
||||
GuacUI.addClass(last, "disabled");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given element to the set of displayable elements.
|
||||
*/
|
||||
this.addElement = function(element) {
|
||||
elements.push(element);
|
||||
guac_pager.last_page = Math.max(0,
|
||||
Math.floor((elements.length - 1) / guac_pager.page_capacity));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current page, where 0 is the first page.
|
||||
*/
|
||||
this.setPage = function(number) {
|
||||
guac_pager.current_page = number;
|
||||
update_display();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the element representing the buttons of this pager.
|
||||
*/
|
||||
this.getElement = function() {
|
||||
return element;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface object which displays the progress of a download, ultimately
|
||||
* becoming a download link once complete.
|
||||
@ -706,639 +409,3 @@ GuacUI.Upload = function(filename) {
|
||||
this.onclose = null;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A grouping component. Child elements can be added via the addElement()
|
||||
* function. By default, groups display as collapsed.
|
||||
*/
|
||||
GuacUI.ListGroup = function(caption) {
|
||||
|
||||
/**
|
||||
* Reference to this group.
|
||||
* @private
|
||||
*/
|
||||
var guac_group = this;
|
||||
|
||||
/**
|
||||
* Whether this group is empty.
|
||||
* @private
|
||||
*/
|
||||
var empty = true;
|
||||
|
||||
/**
|
||||
* A container for for the list group itself.
|
||||
*/
|
||||
var element = GuacUI.createElement("div", "group empty");
|
||||
|
||||
// Create connection display elements
|
||||
var caption_element = GuacUI.createChildElement(element, "div", "caption");
|
||||
var caption_icon = GuacUI.createChildElement(caption_element, "div", "icon group");
|
||||
GuacUI.createChildElement(caption_element, "div", "icon type");
|
||||
GuacUI.createChildElement(caption_element, "span", "name").textContent = caption;
|
||||
|
||||
/**
|
||||
* A container for all children of this list group.
|
||||
*/
|
||||
var elements = GuacUI.createChildElement(element, "div", "children");
|
||||
|
||||
/**
|
||||
* Whether this group is expanded.
|
||||
*
|
||||
* @type Boolean
|
||||
*/
|
||||
this.expanded = false;
|
||||
|
||||
/**
|
||||
* Fired when this group is clicked.
|
||||
* @event
|
||||
*/
|
||||
this.onclick = null;
|
||||
|
||||
/**
|
||||
* Returns the element representing this notification.
|
||||
*/
|
||||
this.getElement = function() {
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds an element as a child of this group.
|
||||
*/
|
||||
this.addElement = function(child) {
|
||||
|
||||
// Mark as non-empty
|
||||
if (empty) {
|
||||
GuacUI.removeClass(element, "empty");
|
||||
empty = false;
|
||||
}
|
||||
|
||||
elements.appendChild(child);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Expands the list group, revealing all children of the group. This
|
||||
* functionality requires supporting CSS.
|
||||
*/
|
||||
this.expand = function() {
|
||||
GuacUI.addClass(element, "expanded");
|
||||
guac_group.expanded = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Collapses the list group, hiding all children of the group. This
|
||||
* functionality requires supporting CSS.
|
||||
*/
|
||||
this.collapse = function() {
|
||||
GuacUI.removeClass(element, "expanded");
|
||||
guac_group.expanded = false;
|
||||
};
|
||||
|
||||
// Toggle when icon is clicked
|
||||
caption_icon.addEventListener("click", function(e) {
|
||||
|
||||
// Prevent click from affecting parent
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
if (guac_group.expanded)
|
||||
guac_group.collapse();
|
||||
else
|
||||
guac_group.expand();
|
||||
|
||||
}, false);
|
||||
|
||||
// Fire event when any other part is clicked
|
||||
element.addEventListener("click", function(e) {
|
||||
|
||||
// Prevent click from affecting parent
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
// Fire event if defined
|
||||
if (guac_group.onclick)
|
||||
guac_group.onclick();
|
||||
|
||||
}, false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Component which displays a paginated tree view of all groups and their
|
||||
* connections.
|
||||
*
|
||||
* @constructor
|
||||
* @param {GuacamoleService.ConnectionGroup} root_group The group to display
|
||||
* within the view.
|
||||
* @param {Number} flags Any flags (such as MULTISELECT or SHOW_CONNECTIONS)
|
||||
* for modifying the behavior of this group view.
|
||||
* @param {Function} group_filter Function which returns true if the given
|
||||
* group should be displayed and false otherwise.
|
||||
* @param {Function} connection_filter Function which returns true if the given
|
||||
* connection should be displayed and false
|
||||
* otherwise.
|
||||
*/
|
||||
GuacUI.GroupView = function(root_group, flags,
|
||||
group_filter, connection_filter) {
|
||||
|
||||
/**
|
||||
* Reference to this GroupView.
|
||||
* @private
|
||||
*/
|
||||
var group_view = this;
|
||||
|
||||
// Group view components
|
||||
var element = GuacUI.createElement("div", "group-view");
|
||||
var list = GuacUI.createChildElement(element, "div", "list");
|
||||
|
||||
/**
|
||||
* Whether multiselect is enabled.
|
||||
*/
|
||||
var multiselect = flags & GuacUI.GroupView.MULTISELECT;
|
||||
|
||||
/**
|
||||
* Whether connections should be included in the view.
|
||||
*/
|
||||
var show_connections = flags & GuacUI.GroupView.SHOW_CONNECTIONS;
|
||||
|
||||
/**
|
||||
* Whether the root group should be included in the view.
|
||||
*/
|
||||
var show_root = flags & GuacUI.GroupView.SHOW_ROOT_GROUP;
|
||||
|
||||
/**
|
||||
* Set of all group checkboxes, indexed by ID. Only applicable when
|
||||
* multiselect is enabled.
|
||||
* @private
|
||||
*/
|
||||
var group_checkboxes = {};
|
||||
|
||||
/**
|
||||
* Set of all connection checkboxes, indexed by ID. Only applicable when
|
||||
* multiselect is enabled.
|
||||
* @private
|
||||
*/
|
||||
var connection_checkboxes = {};
|
||||
|
||||
/**
|
||||
* Set of all list groups, indexed by associated group ID.
|
||||
* @private
|
||||
*/
|
||||
var list_groups = {};
|
||||
|
||||
/**
|
||||
* Set of all connection groups, indexed by ID.
|
||||
*/
|
||||
this.groups = {};
|
||||
|
||||
/**
|
||||
* Set of all connections, indexed by ID.
|
||||
*/
|
||||
this.connections = {};
|
||||
|
||||
/**
|
||||
* Fired when a connection is clicked.
|
||||
*
|
||||
* @event
|
||||
* @param {GuacamolService.Connection} connection The connection which was
|
||||
* clicked.
|
||||
*/
|
||||
this.onconnectionclick = null;
|
||||
|
||||
/**
|
||||
* Fired when a connection group is clicked.
|
||||
*
|
||||
* @event
|
||||
* @param {GuacamolService.ConnectionGroup} group The connection group which
|
||||
* was clicked.
|
||||
*/
|
||||
this.ongroupclick = null;
|
||||
|
||||
/**
|
||||
* Fired when a connection's selected status changes.
|
||||
*
|
||||
* @event
|
||||
* @param {GuacamolService.Connection} connection The connection whose
|
||||
* status changed.
|
||||
* @param {Boolean} selected The new status of the connection.
|
||||
*/
|
||||
this.onconnectionchange = null;
|
||||
|
||||
/**
|
||||
* Fired when a connection group's selected status changes.
|
||||
*
|
||||
* @event
|
||||
* @param {GuacamolService.ConnectionGroup} group The connection group whose
|
||||
* status changed.
|
||||
* @param {Boolean} selected The new status of the connection group.
|
||||
*/
|
||||
this.ongroupchange = null;
|
||||
|
||||
/**
|
||||
* Returns the element representing this group view.
|
||||
*/
|
||||
this.getElement = function() {
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets whether the group with the given ID can be selected. This function
|
||||
* only has an effect when multiselect is enabled.
|
||||
*
|
||||
* @param {String} id The ID of the group to alter.
|
||||
* @param {Boolean} value Whether the group should be selected.
|
||||
*/
|
||||
this.setGroupEnabled = function(id, value) {
|
||||
|
||||
var checkbox = group_checkboxes[id];
|
||||
if (!checkbox)
|
||||
return;
|
||||
|
||||
// If enabled, show checkbox, allow select
|
||||
if (value) {
|
||||
checkbox.style.visibility = "";
|
||||
checkbox.disabled = false;
|
||||
}
|
||||
|
||||
// Otherwise, hide checkbox
|
||||
else {
|
||||
checkbox.style.visibility = "hidden";
|
||||
checkbox.disabled = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets whether the connection with the given ID can be selected. This
|
||||
* function only has an effect when multiselect is enabled.
|
||||
*
|
||||
* @param {String} id The ID of the connection to alter.
|
||||
* @param {Boolean} value Whether the connection can be selected.
|
||||
*/
|
||||
this.setConnectionEnabled = function(id, value) {
|
||||
|
||||
var checkbox = connection_checkboxes[id];
|
||||
if (!checkbox)
|
||||
return;
|
||||
|
||||
// If enabled, show checkbox, allow select
|
||||
if (value) {
|
||||
checkbox.style.visibility = "";
|
||||
checkbox.disabled = false;
|
||||
}
|
||||
|
||||
// Otherwise, hide checkbox
|
||||
else {
|
||||
checkbox.style.visibility = "hidden";
|
||||
checkbox.disabled = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current value of the group with the given ID. This function
|
||||
* only has an effect when multiselect is enabled.
|
||||
*
|
||||
* @param {String} id The ID of the group to change.
|
||||
* @param {Boolean} value Whether the group should be selected.
|
||||
*/
|
||||
this.setGroupValue = function(id, value) {
|
||||
|
||||
var checkbox = group_checkboxes[id];
|
||||
if (!checkbox)
|
||||
return;
|
||||
|
||||
checkbox.checked = value;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current value of the connection with the given ID. This function
|
||||
* only has an effect when multiselect is enabled.
|
||||
*
|
||||
* @param {String} id The ID of the connection to change.
|
||||
* @param {Boolean} value Whether the connection should be selected.
|
||||
*/
|
||||
this.setConnectionValue = function(id, value) {
|
||||
|
||||
var checkbox = connection_checkboxes[id];
|
||||
if (!checkbox)
|
||||
return;
|
||||
|
||||
checkbox.checked = value;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Expands the given group and all parent groups all the way up to root.
|
||||
*
|
||||
* @param {GuacamoleService.ConnectionGroup} group The group that should
|
||||
* be expanded.
|
||||
*/
|
||||
this.expand = function(group) {
|
||||
|
||||
// Skip current group - only need to expand parents
|
||||
group = group.parent;
|
||||
|
||||
// For each group all the way to root
|
||||
while (group !== null) {
|
||||
|
||||
// If list group exists, expand it
|
||||
var list_group = list_groups[group.id];
|
||||
if (list_group)
|
||||
list_group.expand();
|
||||
|
||||
group = group.parent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create pager for contents
|
||||
var pager = new GuacUI.Pager(list);
|
||||
pager.page_capacity = 20;
|
||||
|
||||
/**
|
||||
* Adds the contents of the given group via the given appendChild()
|
||||
* function, but not the given group itself.
|
||||
*
|
||||
* @param {GuacamoleService.ConnectionGroup} group The group whose contents
|
||||
* should be added.
|
||||
* @param {Function} appendChild A function which, given an element, will
|
||||
* add that element the the display as
|
||||
* desired.
|
||||
*/
|
||||
function addGroupContents(group, appendChild) {
|
||||
|
||||
var i;
|
||||
|
||||
// Add all contained connections
|
||||
if (show_connections) {
|
||||
for (i=0; i<group.connections.length; i++)
|
||||
addConnection(group.connections[i], appendChild);
|
||||
}
|
||||
|
||||
// Add all contained groups
|
||||
for (i=0; i<group.groups.length; i++)
|
||||
addGroup(group.groups[i], appendChild);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given connection via the given appendChild() function.
|
||||
*
|
||||
* @param {GuacamoleService.Connection} connection The connection to add.
|
||||
* @param {Function} appendChild A function which, given an element, will
|
||||
* add that element the the display as
|
||||
* desired.
|
||||
*/
|
||||
function addConnection(connection, appendChild) {
|
||||
|
||||
// Do not add connection if filter says "no"
|
||||
if (connection_filter && !connection_filter(connection))
|
||||
return;
|
||||
|
||||
group_view.connections[connection.id] = connection;
|
||||
|
||||
// Add connection to connection list or parent group
|
||||
var guacui_connection = new GuacUI.ListConnection(connection);
|
||||
GuacUI.addClass(guacui_connection.getElement(), "list-item");
|
||||
|
||||
// If multiselect, add checkbox for each connection
|
||||
if (multiselect) {
|
||||
|
||||
var connection_choice = GuacUI.createElement("div", "choice");
|
||||
var connection_checkbox = GuacUI.createChildElement(connection_choice, "input");
|
||||
connection_checkbox.setAttribute("type", "checkbox");
|
||||
|
||||
connection_choice.appendChild(guacui_connection.getElement());
|
||||
appendChild(connection_choice);
|
||||
|
||||
function fire_connection_change(e) {
|
||||
|
||||
// Prevent click from affecting parent
|
||||
e.stopPropagation();
|
||||
|
||||
// Fire event if handler defined
|
||||
if (group_view.onconnectionchange)
|
||||
group_view.onconnectionchange(connection, this.checked);
|
||||
|
||||
}
|
||||
|
||||
// Fire change events when checkbox modified
|
||||
connection_checkbox.addEventListener("click", fire_connection_change, false);
|
||||
connection_checkbox.addEventListener("change", fire_connection_change, false);
|
||||
|
||||
// Add checbox to set of connection checkboxes
|
||||
connection_checkboxes[connection.id] = connection_checkbox;
|
||||
|
||||
}
|
||||
else
|
||||
appendChild(guacui_connection.getElement());
|
||||
|
||||
// Fire click events when connection clicked
|
||||
guacui_connection.onclick = function() {
|
||||
if (group_view.onconnectionclick)
|
||||
group_view.onconnectionclick(connection);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given group via the given appendChild() function.
|
||||
*
|
||||
* @param {GuacamoleService.ConnectionGroup} group The group to add.
|
||||
* @param {Function} appendChild A function which, given an element, will
|
||||
* add that element the the display as
|
||||
* desired.
|
||||
*/
|
||||
function addGroup(group, appendChild) {
|
||||
|
||||
// Do not add group if filter says "no"
|
||||
if (group_filter && !group_filter(group))
|
||||
return;
|
||||
|
||||
// Add group to groups collection
|
||||
group_view.groups[group.id] = group;
|
||||
|
||||
// Create element for group
|
||||
var list_group = new GuacUI.ListGroup(group.name);
|
||||
list_groups[group.id] = list_group;
|
||||
GuacUI.addClass(list_group.getElement(), "list-item");
|
||||
|
||||
// Mark group as balancer if appropriate
|
||||
if (group.type === GuacamoleService.ConnectionGroup.Type.BALANCING)
|
||||
GuacUI.addClass(list_group.getElement(), "balancer");
|
||||
|
||||
// Recursively add all children to the new element
|
||||
addGroupContents(group, list_group.addElement);
|
||||
|
||||
// If multiselect, add checkbox for each group
|
||||
if (multiselect) {
|
||||
|
||||
var group_choice = GuacUI.createElement("div", "choice");
|
||||
var group_checkbox = GuacUI.createChildElement(group_choice, "input");
|
||||
group_checkbox.setAttribute("type", "checkbox");
|
||||
|
||||
group_choice.appendChild(list_group.getElement());
|
||||
appendChild(group_choice);
|
||||
|
||||
function fire_group_change(e) {
|
||||
|
||||
// Prevent click from affecting parent
|
||||
e.stopPropagation();
|
||||
|
||||
// Fire event if handler defined
|
||||
if (group_view.ongroupchange)
|
||||
group_view.ongroupchange(group, this.checked);
|
||||
|
||||
}
|
||||
|
||||
// Fire change events when checkbox modified
|
||||
group_checkbox.addEventListener("click", fire_group_change, false);
|
||||
group_checkbox.addEventListener("change", fire_group_change, false);
|
||||
|
||||
// Add checbox to set of group checkboxes
|
||||
group_checkboxes[group.id] = group_checkbox;
|
||||
|
||||
}
|
||||
else
|
||||
appendChild(list_group.getElement());
|
||||
|
||||
// Fire click events when group clicked
|
||||
list_group.onclick = function() {
|
||||
if (group_view.ongroupclick)
|
||||
group_view.ongroupclick(group);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// If requested, include the root group as an item
|
||||
if (show_root) {
|
||||
addGroup(root_group, pager.addElement);
|
||||
list_groups[root_group.id].expand();
|
||||
}
|
||||
|
||||
// Otherwise, only add contents of root group
|
||||
else
|
||||
addGroupContents(root_group, pager.addElement);
|
||||
|
||||
// Add buttons if more than one page
|
||||
if (pager.last_page !== 0) {
|
||||
var list_buttons = GuacUI.createChildElement(element, "div", "buttons");
|
||||
list_buttons.appendChild(pager.getElement());
|
||||
}
|
||||
|
||||
// Start at page 0
|
||||
pager.setPage(0);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* When set, allows multiple groups (or connections to be selected).
|
||||
*/
|
||||
GuacUI.GroupView.MULTISELECT = 0x1;
|
||||
|
||||
/**
|
||||
* When set, also displays connections within the visible groups.
|
||||
*/
|
||||
GuacUI.GroupView.SHOW_CONNECTIONS = 0x2;
|
||||
|
||||
/**
|
||||
* When set, also displays the root group. By default the root group is hidden.
|
||||
*/
|
||||
GuacUI.GroupView.SHOW_ROOT_GROUP = 0x4;
|
||||
|
||||
/**
|
||||
* Simple modal dialog providing a header, body, and footer. No other
|
||||
* functionality is provided other than a reasonable hierarchy of divs and
|
||||
* easy access to their corresponding elements.
|
||||
*/
|
||||
GuacUI.Dialog = function() {
|
||||
|
||||
/**
|
||||
* The container of the entire dialog. Adding this element to the DOM
|
||||
* displays the dialog, while removing this element hides the dialog.
|
||||
*
|
||||
* @private
|
||||
* @type Element
|
||||
*/
|
||||
var element = GuacUI.createElement("div", "dialog-container");
|
||||
|
||||
/**
|
||||
* The dialog itself. This element is not exposed outside this object,
|
||||
* but rather contains the header, body, and footer sections which are
|
||||
* exposed.
|
||||
*
|
||||
* @private
|
||||
* @type Element
|
||||
*/
|
||||
var dialog = GuacUI.createChildElement(element, "div", "dialog");
|
||||
|
||||
/**
|
||||
* The header section of the dialog. This section would normally contain
|
||||
* the title.
|
||||
*
|
||||
* @private
|
||||
* @type Element
|
||||
*/
|
||||
var header = GuacUI.createChildElement(dialog, "div", "header");
|
||||
|
||||
/**
|
||||
* The body section of the dialog. This section would normally contain any
|
||||
* form fields and content.
|
||||
*
|
||||
* @private
|
||||
* @type Element
|
||||
*/
|
||||
var body = GuacUI.createChildElement(dialog, "div", "body");
|
||||
|
||||
/**
|
||||
* The footer section of the dialog. This section would normally contain
|
||||
* the buttons.
|
||||
*
|
||||
* @private
|
||||
* @type Element
|
||||
*/
|
||||
var footer = GuacUI.createChildElement(dialog, "div", "footer");
|
||||
|
||||
/**
|
||||
* Returns the header section of this dialog. This section normally
|
||||
* contains the title of the dialog.
|
||||
*
|
||||
* @return {Element} The header section of this dialog.
|
||||
*/
|
||||
this.getHeader = function() {
|
||||
return header;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the body section of this dialog. This section normally contains
|
||||
* the form fields, etc. of a dialog.
|
||||
*
|
||||
* @return {Element} The body section of this dialog.
|
||||
*/
|
||||
this.getBody = function() {
|
||||
return body;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the footer section of this dialog. This section is normally
|
||||
* used to contain the buttons of the dialog.
|
||||
*
|
||||
* @return {Element} The footer section of this dialog.
|
||||
*/
|
||||
this.getFooter = function() {
|
||||
return footer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the element representing this dialog. Adding this element to
|
||||
* the DOM shows the dialog, while removing this element hides the dialog.
|
||||
*
|
||||
* @return {Element} The element representing this dialog.
|
||||
*/
|
||||
this.getElement = function() {
|
||||
return element;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -1,212 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set of thumbnails for each connection, indexed by ID.
|
||||
*/
|
||||
GuacamoleHistory = new (function() {
|
||||
|
||||
/**
|
||||
* Reference to this GuacamoleHistory.
|
||||
*/
|
||||
var guac_history = this;
|
||||
|
||||
/**
|
||||
* The number of entries to allow before removing old entries based on the
|
||||
* cutoff.
|
||||
*/
|
||||
var IDEAL_LENGTH = 6;
|
||||
|
||||
/**
|
||||
* The maximum age of a history entry before it is removed, in
|
||||
* milliseconds.
|
||||
*/
|
||||
var CUTOFF_AGE = 900000;
|
||||
|
||||
var history = {};
|
||||
|
||||
function truncate() {
|
||||
|
||||
// Build list of entries
|
||||
var entries = [];
|
||||
for (var old_id in history)
|
||||
entries.push(history[old_id]);
|
||||
|
||||
// Avoid history growth beyond defined number of entries
|
||||
if (entries.length > IDEAL_LENGTH) {
|
||||
|
||||
// Sort list
|
||||
entries.sort(GuacamoleHistory.Entry.compare);
|
||||
|
||||
// Remove entries until length is ideal or all are recent
|
||||
var now = new Date().getTime();
|
||||
while (entries.length > IDEAL_LENGTH
|
||||
&& now - entries[0].accessed > CUTOFF_AGE) {
|
||||
|
||||
// Remove entry
|
||||
var removed = entries.shift();
|
||||
delete history[removed.id];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL for the thumbnail of the connection with the given ID,
|
||||
* or undefined if no thumbnail is associated with that connection.
|
||||
*/
|
||||
this.get = function(id) {
|
||||
return history[id] || new GuacamoleHistory.Entry();
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the thumbnail and access time of the history entry for the
|
||||
* connection with the given ID.
|
||||
*/
|
||||
this.update = function(id, thumbnail) {
|
||||
|
||||
/* Do nothing if localStorage not present */
|
||||
if (!localStorage)
|
||||
return;
|
||||
|
||||
// Create updated entry
|
||||
var entry = new GuacamoleHistory.Entry(
|
||||
id,
|
||||
thumbnail,
|
||||
new Date().getTime()
|
||||
);
|
||||
|
||||
// Store entry in history
|
||||
history[id] = entry;
|
||||
truncate();
|
||||
|
||||
// Save updated history, ignore inability to use localStorage
|
||||
try {
|
||||
localStorage.setItem("GUAC_HISTORY", JSON.stringify(history));
|
||||
}
|
||||
catch (ignore) {}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Reloads all history data.
|
||||
*/
|
||||
this.reload = function() {
|
||||
|
||||
/* Do nothing if localStorage not present */
|
||||
if (!localStorage)
|
||||
return;
|
||||
|
||||
// Get old and new for comparison, ignore inability to use localStorage
|
||||
var old_history = history;
|
||||
try {
|
||||
var new_history = JSON.parse(localStorage.getItem("GUAC_HISTORY") || "{}");
|
||||
}
|
||||
catch (ignore) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update history
|
||||
history = new_history;
|
||||
|
||||
// Call onchange handler as necessary
|
||||
if (guac_history.onchange) {
|
||||
|
||||
// Produce union of all known IDs
|
||||
var known_ids = {};
|
||||
for (var new_id in new_history) known_ids[new_id] = true;
|
||||
for (var old_id in old_history) known_ids[old_id] = true;
|
||||
|
||||
// For each known ID
|
||||
for (var id in known_ids) {
|
||||
|
||||
// Get entries
|
||||
var old_entry = old_history[id];
|
||||
var new_entry = new_history[id];
|
||||
|
||||
// Call handler for all changed
|
||||
if (!old_entry || !new_entry
|
||||
|| old_entry.accessed != new_entry.accessed)
|
||||
guac_history.onchange(id, old_entry, new_entry);
|
||||
|
||||
}
|
||||
|
||||
} // end onchange
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler called whenever a history entry is changed.
|
||||
*
|
||||
* @event
|
||||
* @param {String} id The ID of the connection whose history entry is
|
||||
* changing.
|
||||
* @param {GuacamoleHistory.Entry} old_entry The old value of the entry, if
|
||||
* any.
|
||||
* @param {GuacamoleHistory.Entry} new_entry The new value of the entry, if
|
||||
* any.
|
||||
*/
|
||||
this.onchange = null;
|
||||
|
||||
// Reload when modified
|
||||
window.addEventListener("storage", guac_history.reload, false);
|
||||
|
||||
// Initial load
|
||||
guac_history.reload();
|
||||
|
||||
})();
|
||||
|
||||
/**
|
||||
* A single entry in the indexed connection usage history.
|
||||
*
|
||||
* @constructor
|
||||
* @param {String} id The ID of this connection.
|
||||
* @param {String} thumbnail The URL of the thumbnail to use to represent this
|
||||
* connection.
|
||||
* @param {Number} last_access The time this connection was last accessed, in
|
||||
* seconds.
|
||||
*/
|
||||
GuacamoleHistory.Entry = function(id, thumbnail, last_access) {
|
||||
|
||||
/**
|
||||
* The ID of the connection associated with this history entry.
|
||||
*/
|
||||
this.id = id;
|
||||
|
||||
/**
|
||||
* The thumbnail associated with the connection associated with this history
|
||||
* entry.
|
||||
*/
|
||||
this.thumbnail = thumbnail;
|
||||
|
||||
/**
|
||||
* The time the connection associated with this entry was last accessed.
|
||||
*/
|
||||
this.accessed = last_access;
|
||||
|
||||
};
|
||||
|
||||
GuacamoleHistory.Entry.compare = function(a, b) {
|
||||
return a.accessed - b.accessed;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -23,7 +23,7 @@
|
||||
/**
|
||||
* Global storage for Guacamole pages.
|
||||
*/
|
||||
GuacamoleSessionStorage = (opener && opener.GuacamoleSessionStorage) || new (function() {
|
||||
GuacamoleSessionStorage = (window.opener && opener.GuacamoleSessionStorage) || new (function() {
|
||||
|
||||
/**
|
||||
* The contents of storage, as a JSON string containing name/value pairs as
|
||||
@ -71,7 +71,7 @@ GuacamoleSessionStorage = (opener && opener.GuacamoleSessionStorage) || new (fun
|
||||
|
||||
// Attempt to read JSON from localStorage, default to local variable
|
||||
var json = stored_json;
|
||||
if (localStorage) {
|
||||
if (window.localStorage) {
|
||||
try {
|
||||
json = localStorage.getItem("GUACAMOLE_STATE") || "{}";
|
||||
}
|
||||
@ -96,7 +96,7 @@ GuacamoleSessionStorage = (opener && opener.GuacamoleSessionStorage) || new (fun
|
||||
|
||||
// Attempt to read JSON from localStorage, default to local variable
|
||||
var json = stored_json;
|
||||
if (localStorage) {
|
||||
if (window.localStorage) {
|
||||
try {
|
||||
json = localStorage.getItem("GUACAMOLE_STATE") || "{}";
|
||||
}
|
||||
@ -114,7 +114,7 @@ GuacamoleSessionStorage = (opener && opener.GuacamoleSessionStorage) || new (fun
|
||||
|
||||
// Attempt to set JSON within localStorage, default to local variable
|
||||
stored_json = JSON.stringify(obj);
|
||||
if (localStorage) {
|
||||
if (window.localStorage) {
|
||||
try {
|
||||
localStorage.setItem("GUACAMOLE_STATE", stored_json);
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
button#back {
|
||||
|
||||
background-image: url('../images/action-icons/guac-back.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1em;
|
||||
background-position: 0.5em 0.45em;
|
||||
|
||||
padding-left: 1.8em;
|
||||
|
||||
}
|
||||
|
||||
button#add-user {
|
||||
|
||||
background-image: url('../images/action-icons/guac-user-add.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1em;
|
||||
background-position: 0.5em 0.45em;
|
||||
|
||||
padding-left: 1.8em;
|
||||
|
||||
}
|
||||
|
||||
button#add-connection {
|
||||
|
||||
background-image: url('../images/action-icons/guac-monitor-add.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1em;
|
||||
background-position: 0.5em 0.45em;
|
||||
|
||||
padding-left: 1.8em;
|
||||
|
||||
}
|
||||
|
||||
button#add-connection-group {
|
||||
|
||||
background-image: url('../images/action-icons/guac-group-add.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1em;
|
||||
background-position: 0.5em 0.45em;
|
||||
|
||||
padding-left: 1.8em;
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,364 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* {
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
input[type=checkbox], input[type=text], textarea {
|
||||
-webkit-tap-highlight-color: rgba(128,192,128,0.5);
|
||||
}
|
||||
|
||||
input[type=submit], button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #EEE;
|
||||
font-family: FreeSans, Helvetica, Arial, sans-serif;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#manage {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.admin #manage {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button#manage {
|
||||
|
||||
background-image: url('../images/action-icons/guac-config.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1em;
|
||||
background-position: 0.5em 0.45em;
|
||||
|
||||
padding-left: 1.8em;
|
||||
|
||||
}
|
||||
|
||||
div#login-ui {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: table;
|
||||
}
|
||||
|
||||
@keyframes shake-head {
|
||||
0% { margin-left: 0.25em; margin-right: -0.25em; }
|
||||
25% { margin-left: -0.25em; margin-right: 0.25em; }
|
||||
50% { margin-left: 0.25em; margin-right: -0.25em; }
|
||||
75% { margin-left: -0.25em; margin-right: 0.25em; }
|
||||
100% { margin-left: 0.00em; margin-right: 0.00em; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes shake-head {
|
||||
0% { margin-left: 0.25em; margin-right: -0.25em; }
|
||||
25% { margin-left: -0.25em; margin-right: 0.25em; }
|
||||
50% { margin-left: 0.25em; margin-right: -0.25em; }
|
||||
75% { margin-left: -0.25em; margin-right: 0.25em; }
|
||||
100% { margin-left: 0.00em; margin-right: 0.00em; }
|
||||
}
|
||||
|
||||
p#login-error {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.error p#login-error {
|
||||
display: block;
|
||||
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
padding: 1em;
|
||||
margin: 0.2em;
|
||||
|
||||
background: #FDD;
|
||||
border: 1px solid #964040;
|
||||
-moz-border-radius: 0.25em;
|
||||
-webkit-border-radius: 0.25em;
|
||||
-khtml-border-radius: 0.25em;
|
||||
text-align: center;
|
||||
color: #964040;
|
||||
}
|
||||
|
||||
.error #login-form {
|
||||
animation-name: shake-head;
|
||||
animation-duration: 0.25s;
|
||||
animation-timing-function: linear;
|
||||
-webkit-animation-name: shake-head;
|
||||
-webkit-animation-duration: 0.25s;
|
||||
-webkit-animation-timing-function: linear;
|
||||
}
|
||||
|
||||
div#login-logo {
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div#login-dialog-middle {
|
||||
width: 100%;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div#login-dialog {
|
||||
|
||||
max-width: 75%;
|
||||
text-align: left;
|
||||
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div#login-dialog h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div#login-dialog #buttons {
|
||||
padding-top: 0.5em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input[type="submit"]#login, button#login {
|
||||
|
||||
background-image: url('../images/guacamole-logo-64.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5em;
|
||||
background-position: 0.5em 0.25em;
|
||||
|
||||
padding-left: 2.5em;
|
||||
|
||||
}
|
||||
|
||||
div#login-dialog #login-fields {
|
||||
|
||||
vertical-align: middle;
|
||||
|
||||
padding: 1em;
|
||||
border-top: 1px solid #999;
|
||||
border-bottom: 1px solid #999;
|
||||
|
||||
}
|
||||
|
||||
div#login-dialog th {
|
||||
text-shadow: 1px 1px white;
|
||||
}
|
||||
|
||||
div#login-dialog #login-fields input {
|
||||
border: 1px solid #777;
|
||||
-moz-border-radius: 0.2em;
|
||||
-webkit-border-radius: 0.2em;
|
||||
-khtml-border-radius: 0.2em;
|
||||
border-radius: 0.2em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div#login-dialog #login-fields img.logo {
|
||||
position: fixed;
|
||||
margin: 10px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
opacity: 0.1;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
div#version {
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
font-size: 0.75em;
|
||||
color: black;
|
||||
opacity: 0.5;
|
||||
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
img#license {
|
||||
float: right;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
div#connection-list-ui h1 {
|
||||
|
||||
margin: 0;
|
||||
padding: 0.5em;
|
||||
|
||||
font-size: 2em;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
div#connection-list-ui h2 {
|
||||
|
||||
padding: 0.5em;
|
||||
margin: 0;
|
||||
font-size: 1.5em;
|
||||
|
||||
font-weight: lighter;
|
||||
text-shadow: 1px 1px white;
|
||||
|
||||
border-top: 1px solid #AAA;
|
||||
border-bottom: 1px solid #AAA;
|
||||
background: #DDD;
|
||||
|
||||
}
|
||||
|
||||
div#connection-list-ui img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div#logout-panel {
|
||||
padding: 0.45em;
|
||||
text-align: right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.history-unavailable div#recent-connections {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div#recent-connections,
|
||||
div#clipboardDiv,
|
||||
div#settings,
|
||||
div#all-connections {
|
||||
margin: 1em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#all-connections .list-buttons {
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div#recent-connections {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#no-recent {
|
||||
|
||||
color: black;
|
||||
text-shadow: 1px 1px white;
|
||||
opacity: 0.5;
|
||||
|
||||
font-size: 2em;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
div#recent-connections div.connection {
|
||||
-moz-border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
-khtml-border-radius: 0.5em;
|
||||
border-radius: 0.5em;
|
||||
display: inline-block;
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
text-align: center;
|
||||
max-width: 75%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.group,
|
||||
.connection {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.connection:hover {
|
||||
background: #CDA;
|
||||
}
|
||||
|
||||
.group,
|
||||
.connection .name {
|
||||
color: black;
|
||||
font-weight: normal;
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
.connection .thumbnail {
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
.connection .thumbnail img {
|
||||
border: 1px solid black;
|
||||
box-shadow: 1px 1px 5px black;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
div#all-connections .connection {
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div#recent-connections .connection .thumbnail {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div#all-connections .connection {
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
div#recent-connections .protocol {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.caption * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.caption .name {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
#clipboardDiv textarea {
|
||||
width: 100%;
|
||||
border: 1px solid #AAA;
|
||||
-moz-border-radius: 0.25em;
|
||||
-webkit-border-radius: 0.25em;
|
||||
-khtml-border-radius: 0.25em;
|
||||
border-radius: 0.25em;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#settings dt {
|
||||
border-bottom: 1px dotted #AAA;
|
||||
padding-bottom: 0.25em;
|
||||
}
|
||||
|
||||
#settings dd {
|
||||
margin: 1.5em;
|
||||
margin-left: 2.5em;
|
||||
font-size: 0.75em;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
Loading…
Reference in New Issue
Block a user