mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-422: Merge support for forwarding client timezone at Guacamole protocol level.
This commit is contained in:
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.protocol;
|
package org.apache.guacamole.protocol;
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
@@ -56,6 +55,15 @@ public class ConfiguredGuacamoleSocket implements GuacamoleSocket {
|
|||||||
*/
|
*/
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The protocol version that will be used to communicate with guacd. The
|
||||||
|
* default is 1.0.0, and, if the server does not provide a specific version
|
||||||
|
* it will be assumed that it operates at this version and certain features
|
||||||
|
* may be unavailable.
|
||||||
|
*/
|
||||||
|
private GuacamoleProtocolVersion protocol =
|
||||||
|
GuacamoleProtocolVersion.VERSION_1_0_0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for the instruction having the given opcode, returning that
|
* Waits for the instruction having the given opcode, returning that
|
||||||
* instruction once it has been read. If the instruction is never read,
|
* instruction once it has been read. If the instruction is never read,
|
||||||
@@ -142,6 +150,13 @@ public class ConfiguredGuacamoleSocket implements GuacamoleSocket {
|
|||||||
|
|
||||||
// Retrieve argument name
|
// Retrieve argument name
|
||||||
String arg_name = arg_names.get(i);
|
String arg_name = arg_names.get(i);
|
||||||
|
|
||||||
|
// Check for protocol version as first argument
|
||||||
|
if (i == 0 && arg_name.startsWith("VERSION_")) {
|
||||||
|
protocol = GuacamoleProtocolVersion.getVersion(arg_name);
|
||||||
|
arg_values[i] = protocol.toString();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get defined value for name
|
// Get defined value for name
|
||||||
String value = config.getParameter(arg_name);
|
String value = config.getParameter(arg_name);
|
||||||
@@ -184,6 +199,19 @@ public class ConfiguredGuacamoleSocket implements GuacamoleSocket {
|
|||||||
"image",
|
"image",
|
||||||
info.getImageMimetypes().toArray(new String[0])
|
info.getImageMimetypes().toArray(new String[0])
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Check for support for timezone handshake
|
||||||
|
if (protocol.isSupported(GuacamoleProtocolCapability.TIMEZONE_HANDSHAKE)) {
|
||||||
|
// Send client timezone, if available
|
||||||
|
String timezone = info.getTimezone();
|
||||||
|
if (timezone != null) {
|
||||||
|
writer.writeInstruction(
|
||||||
|
new GuacamoleInstruction(
|
||||||
|
"timezone",
|
||||||
|
info.getTimezone()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Send args
|
// Send args
|
||||||
writer.writeInstruction(new GuacamoleInstruction("connect", arg_values));
|
writer.writeInstruction(new GuacamoleInstruction("connect", arg_values));
|
||||||
|
@@ -58,6 +58,11 @@ public class GuacamoleClientInformation {
|
|||||||
* The list of image mimetypes reported by the client to be supported.
|
* The list of image mimetypes reported by the client to be supported.
|
||||||
*/
|
*/
|
||||||
private final List<String> imageMimetypes = new ArrayList<String>();
|
private final List<String> imageMimetypes = new ArrayList<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timezone reported by the client.
|
||||||
|
*/
|
||||||
|
private String timezone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the optimal screen width requested by the client, in pixels.
|
* Returns the optimal screen width requested by the client, in pixels.
|
||||||
@@ -144,5 +149,31 @@ public class GuacamoleClientInformation {
|
|||||||
public List<String> getImageMimetypes() {
|
public List<String> getImageMimetypes() {
|
||||||
return imageMimetypes;
|
return imageMimetypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the timezone as reported by the client, or null if the timezone
|
||||||
|
* is not set. Valid timezones are specified in IANA zone key format,
|
||||||
|
* also known as Olson time zone database or TZ Database.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A string value of the timezone reported by the client.
|
||||||
|
*/
|
||||||
|
public String getTimezone() {
|
||||||
|
return timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the string value of the timezone, or null if the timezone will not
|
||||||
|
* be provided by the client. Valid timezones are specified in IANA zone
|
||||||
|
* key format (aka Olson time zone database or tz database).
|
||||||
|
*
|
||||||
|
* @param timezone
|
||||||
|
* The string value of the timezone reported by the client, in tz
|
||||||
|
* database format, or null if the timezone is not provided by the
|
||||||
|
* client.
|
||||||
|
*/
|
||||||
|
public void setTimezone(String timezone) {
|
||||||
|
this.timezone = timezone;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enum that specifies protocol capabilities that can be used to help
|
||||||
|
* detect whether or not a particular protocol version contains a capability.
|
||||||
|
*/
|
||||||
|
public enum GuacamoleProtocolCapability {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the protocol supports arbitrary ordering of the
|
||||||
|
* handshake instructions. This was introduced in VERSION_1_1_0.
|
||||||
|
*/
|
||||||
|
ARBITRARY_HANDSHAKE_ORDER(GuacamoleProtocolVersion.VERSION_1_1_0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the protocol supports the ability to dynamically
|
||||||
|
* detect the version client and server are running in order to allow
|
||||||
|
* compatibility between differing client and server versions. This
|
||||||
|
* was introduced in VERSION_1_1_0.
|
||||||
|
*/
|
||||||
|
PROTOCOL_VERSION_DETECTION(GuacamoleProtocolVersion.VERSION_1_1_0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the protocol supports the timezone instruction during
|
||||||
|
* the Client-Server handshake phase. This was introduced in
|
||||||
|
* VERSION_1_1_0.
|
||||||
|
*/
|
||||||
|
TIMEZONE_HANDSHAKE(GuacamoleProtocolVersion.VERSION_1_1_0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum protocol version required to support this capability.
|
||||||
|
*/
|
||||||
|
private final GuacamoleProtocolVersion version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new enum value with the given protocol version as the minimum
|
||||||
|
* required to support the capability.
|
||||||
|
*
|
||||||
|
* @param version
|
||||||
|
* The minimum required protocol version for supporting the
|
||||||
|
* capability.
|
||||||
|
*/
|
||||||
|
GuacamoleProtocolCapability(GuacamoleProtocolVersion version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum protocol version required to support this
|
||||||
|
* capability.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The minimum protocol version required to support this capability.
|
||||||
|
*/
|
||||||
|
public GuacamoleProtocolVersion getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.protocol;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enum that defines the available Guacamole protocol versions that can be
|
||||||
|
* used between guacd and clients, and provides convenience methods for parsing
|
||||||
|
* and comparing versions.
|
||||||
|
*/
|
||||||
|
public enum GuacamoleProtocolVersion {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol version 1.0.0 and older. Any client that doesn't explicitly
|
||||||
|
* set the protocol version will negotiate down to this protocol version.
|
||||||
|
* This requires that handshake instructions be ordered correctly, and
|
||||||
|
* lacks support for certain protocol-related features introduced in later
|
||||||
|
* versions.
|
||||||
|
*/
|
||||||
|
VERSION_1_0_0(1, 0, 0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol version 1.1.0, which introduces Client-Server version
|
||||||
|
* detection, arbitrary handshake instruction order, and support
|
||||||
|
* for passing the client timezone to the server during the handshake.
|
||||||
|
*/
|
||||||
|
VERSION_1_1_0(1, 1, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A regular expression that matches the VERSION_X_Y_Z pattern, where
|
||||||
|
* X is the major version component, Y is the minor version component,
|
||||||
|
* and Z is the patch version component. This expression puts each of
|
||||||
|
* the version components in their own group so that they can be easily
|
||||||
|
* used later.
|
||||||
|
*/
|
||||||
|
private static final Pattern VERSION_PATTERN =
|
||||||
|
Pattern.compile("^VERSION_([0-9]+)_([0-9]+)_([0-9]+)$");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The major version component of the protocol version.
|
||||||
|
*/
|
||||||
|
private final int major;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minor version component of the protocol version.
|
||||||
|
*/
|
||||||
|
private final int minor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The patch version component of the protocol version.
|
||||||
|
*/
|
||||||
|
private final int patch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new GuacamoleProtocolVersion object with the given
|
||||||
|
* major version, minor version, and patch version.
|
||||||
|
*
|
||||||
|
* @param major
|
||||||
|
* The integer representation of the major version component.
|
||||||
|
*
|
||||||
|
* @param minor
|
||||||
|
* The integer representation of the minor version component.
|
||||||
|
*
|
||||||
|
* @param patch
|
||||||
|
* The integer representation of the patch version component.
|
||||||
|
*/
|
||||||
|
GuacamoleProtocolVersion(int major, int minor, int patch) {
|
||||||
|
this.major = major;
|
||||||
|
this.minor = minor;
|
||||||
|
this.patch = patch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the major version component of the protocol version.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The integer major version component.
|
||||||
|
*/
|
||||||
|
public int getMajor() {
|
||||||
|
return major;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the minor version component of the protocol version.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The integer minor version component.
|
||||||
|
*/
|
||||||
|
public int getMinor() {
|
||||||
|
return minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the patch version component of the protocol version.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The integer patch version component.
|
||||||
|
*/
|
||||||
|
public int getPatch() {
|
||||||
|
return patch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not this object is greater than or equal to the
|
||||||
|
* the version passed in to the method. Returns a boolean true if the
|
||||||
|
* version is the same as or greater than the other version, otherwise
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param otherVersion
|
||||||
|
* The version to which this object should be compared.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* True if this object is greater than or equal to the other version.
|
||||||
|
*/
|
||||||
|
private boolean atLeast(GuacamoleProtocolVersion otherVersion) {
|
||||||
|
|
||||||
|
// If major is not the same, return inequality
|
||||||
|
if (major != otherVersion.getMajor())
|
||||||
|
return this.major > major;
|
||||||
|
|
||||||
|
// Major is the same, but minor is not, return minor inequality
|
||||||
|
if (minor != otherVersion.getMinor())
|
||||||
|
return this.minor > minor;
|
||||||
|
|
||||||
|
// Major and minor are equal, so return patch inequality
|
||||||
|
return patch >= otherVersion.getPatch();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare this version with the major, minor, and patch components
|
||||||
|
* provided to the method, and determine if this version is compatible
|
||||||
|
* with the provided version, returning a boolean true if it is compatible,
|
||||||
|
* otherwise false. This version is compatible with the version specified
|
||||||
|
* by the provided components if the major, minor, and patch components
|
||||||
|
* are equivalent or less than those provided.
|
||||||
|
*
|
||||||
|
* @param major
|
||||||
|
* The major version component to compare for compatibility.
|
||||||
|
*
|
||||||
|
* @param minor
|
||||||
|
* The minor version component to compare for compatibility.
|
||||||
|
*
|
||||||
|
* @param patch
|
||||||
|
* The patch version component to compare for compatibility.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* True if this version is compatibility with the version components
|
||||||
|
* provided, otherwise false.
|
||||||
|
*/
|
||||||
|
private boolean isCompatible(int major, int minor, int patch) {
|
||||||
|
|
||||||
|
if (this.major != major)
|
||||||
|
return this.major < major;
|
||||||
|
|
||||||
|
if (this.minor != minor)
|
||||||
|
return this.minor < minor;
|
||||||
|
|
||||||
|
return this.patch <= patch;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the String format of the version provided and return the
|
||||||
|
* the enum value matching that version. If no value is provided, return
|
||||||
|
* null.
|
||||||
|
*
|
||||||
|
* @param version
|
||||||
|
* The String format of the version to parse.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The enum value that matches the specified version, VERSION_1_0_0
|
||||||
|
* if no match is found, or null if no comparison version is provided.
|
||||||
|
*/
|
||||||
|
public static GuacamoleProtocolVersion getVersion(String version) {
|
||||||
|
|
||||||
|
// If nothing is passed in, return null
|
||||||
|
if (version == null || version.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Check the string against the pattern matcher
|
||||||
|
Matcher versionMatcher = VERSION_PATTERN.matcher(version);
|
||||||
|
|
||||||
|
// If there is no RegEx match, return null
|
||||||
|
if (!versionMatcher.matches())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try the valueOf function
|
||||||
|
return valueOf(version);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing matches, find the closest compatible version.
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
int myMajor = Integer.parseInt(versionMatcher.group(1));
|
||||||
|
int myMinor = Integer.parseInt(versionMatcher.group(2));
|
||||||
|
int myPatch = Integer.parseInt(versionMatcher.group(3));
|
||||||
|
|
||||||
|
GuacamoleProtocolVersion myVersion = VERSION_1_0_0;
|
||||||
|
|
||||||
|
// Loop through possible versions, grabbing the latest compatible
|
||||||
|
for (GuacamoleProtocolVersion v : values()) {
|
||||||
|
if (v.isCompatible(myMajor, myMinor, myPatch))
|
||||||
|
myVersion = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return myVersion;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the specified capability is supported in the current
|
||||||
|
* protocol version, otherwise false.
|
||||||
|
*
|
||||||
|
* @param capability
|
||||||
|
* The protocol capability that is being checked for support.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* True if the capability is supported in the current version,
|
||||||
|
* otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean isSupported(GuacamoleProtocolCapability capability) {
|
||||||
|
|
||||||
|
return atLeast(capability.getVersion());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -199,6 +199,10 @@
|
|||||||
{
|
{
|
||||||
"name" : "static-channels",
|
"name" : "static-channels",
|
||||||
"type" : "TEXT"
|
"type" : "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "timezone",
|
||||||
|
"type" : "TIMEZONE"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@@ -97,9 +97,13 @@
|
|||||||
"options" : [ "", "127", "8" ]
|
"options" : [ "", "127", "8" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name" : "terminal-type",
|
"name" : "terminal-type",
|
||||||
"type" : "ENUM",
|
"type" : "ENUM",
|
||||||
"options" : [ "", "xterm", "xterm-256color", "vt220", "vt100", "ansi", "linux" ]
|
"options" : [ "", "xterm", "xterm-256color", "vt220", "vt100", "ansi", "linux" ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "timezone",
|
||||||
|
"type" : "TIMEZONE"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@@ -493,6 +493,13 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JSTZ for TimeZone Detection -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.webjars.npm</groupId>
|
||||||
|
<artifactId>jstz</artifactId>
|
||||||
|
<version>1.0.10</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@@ -605,6 +605,36 @@ licenses; we recommend you read them, as their terms may differ from the
|
|||||||
terms above.
|
terms above.
|
||||||
|
|
||||||
|
|
||||||
|
JSTZ (https://pellepim.bitbucket.io/jstz/)
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
Version: 1.0.10
|
||||||
|
From: 'Jon Nylander' (https://pellepim.bitbucket.io/jstz/)
|
||||||
|
License(s):
|
||||||
|
MIT (bundled/jstz-1.0.10/LICENSE)
|
||||||
|
|
||||||
|
Copyright (c) 2012 Jon Nylander, project maintained at
|
||||||
|
https://bitbucket.org/pellepim/jstimezonedetect
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
Logback (http://logback.qos.ch/)
|
Logback (http://logback.qos.ch/)
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
|
22
guacamole/src/licenses/bundled/jstz-1.0.10/LICENSE
Normal file
22
guacamole/src/licenses/bundled/jstz-1.0.10/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2012 Jon Nylander, project maintained at
|
||||||
|
https://bitbucket.org/pellepim/jstimezonedetect
|
||||||
|
|
||||||
|
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.
|
@@ -95,6 +95,11 @@ public abstract class TunnelRequest {
|
|||||||
* once for each mimetype.
|
* once for each mimetype.
|
||||||
*/
|
*/
|
||||||
public static final String IMAGE_PARAMETER = "GUAC_IMAGE";
|
public static final String IMAGE_PARAMETER = "GUAC_IMAGE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the parameter specifying the timezone of the client.
|
||||||
|
*/
|
||||||
|
public static final String TIMEZONE_PARAMETER = "GUAC_TIMEZONE";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All supported object types that can be used as the destination of a
|
* All supported object types that can be used as the destination of a
|
||||||
@@ -365,5 +370,16 @@ public abstract class TunnelRequest {
|
|||||||
public List<String> getImageMimetypes() {
|
public List<String> getImageMimetypes() {
|
||||||
return getParameterValues(IMAGE_PARAMETER);
|
return getParameterValues(IMAGE_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tz database value of the timezone declared by the client
|
||||||
|
* within the tunnel request.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The tz database value of the timezone parameter as reported by
|
||||||
|
* the client.
|
||||||
|
*/
|
||||||
|
public String getTimezone() {
|
||||||
|
return getParameter(TIMEZONE_PARAMETER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -166,6 +166,11 @@ public class TunnelRequestService {
|
|||||||
List<String> imageMimetypes = request.getImageMimetypes();
|
List<String> imageMimetypes = request.getImageMimetypes();
|
||||||
if (imageMimetypes != null)
|
if (imageMimetypes != null)
|
||||||
info.getImageMimetypes().addAll(imageMimetypes);
|
info.getImageMimetypes().addAll(imageMimetypes);
|
||||||
|
|
||||||
|
// Get the timezone value
|
||||||
|
String timezone = request.getTimezone();
|
||||||
|
if (timezone != null & !timezone.isEmpty())
|
||||||
|
info.setTimezone(timezone);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
|||||||
var authenticationService = $injector.get('authenticationService');
|
var authenticationService = $injector.get('authenticationService');
|
||||||
var connectionGroupService = $injector.get('connectionGroupService');
|
var connectionGroupService = $injector.get('connectionGroupService');
|
||||||
var connectionService = $injector.get('connectionService');
|
var connectionService = $injector.get('connectionService');
|
||||||
|
var preferenceService = $injector.get('preferenceService');
|
||||||
var requestService = $injector.get('requestService');
|
var requestService = $injector.get('requestService');
|
||||||
var tunnelService = $injector.get('tunnelService');
|
var tunnelService = $injector.get('tunnelService');
|
||||||
var guacAudio = $injector.get('guacAudio');
|
var guacAudio = $injector.get('guacAudio');
|
||||||
@@ -225,6 +226,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
|||||||
+ "&GUAC_WIDTH=" + Math.floor(optimal_width)
|
+ "&GUAC_WIDTH=" + Math.floor(optimal_width)
|
||||||
+ "&GUAC_HEIGHT=" + Math.floor(optimal_height)
|
+ "&GUAC_HEIGHT=" + Math.floor(optimal_height)
|
||||||
+ "&GUAC_DPI=" + Math.floor(optimal_dpi)
|
+ "&GUAC_DPI=" + Math.floor(optimal_dpi)
|
||||||
|
+ "&GUAC_TIMEZONE=" + encodeURIComponent(preferenceService.preferences.timezone)
|
||||||
+ (connectionParameters ? '&' + connectionParameters : '');
|
+ (connectionParameters ? '&' + connectionParameters : '');
|
||||||
|
|
||||||
// Add audio mimetypes to connect string
|
// Add audio mimetypes to connect string
|
||||||
|
@@ -98,6 +98,18 @@ angular.module('settings').provider('preferenceService', ['$injector',
|
|||||||
return language.replace(/-/g, '_');
|
return language.replace(/-/g, '_');
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the timezone detected for the current browser session
|
||||||
|
* by the JSTZ timezone library.
|
||||||
|
*
|
||||||
|
* @returns String
|
||||||
|
* The name of the currently-detected timezone in IANA zone key
|
||||||
|
* format (Olson time zone database).
|
||||||
|
*/
|
||||||
|
var getDetectedTimezone = function getDetectedTimezone() {
|
||||||
|
return jstz.determine().name();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All currently-set preferences, as name/value pairs. Each property name
|
* All currently-set preferences, as name/value pairs. Each property name
|
||||||
@@ -128,7 +140,15 @@ angular.module('settings').provider('preferenceService', ['$injector',
|
|||||||
*
|
*
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
language : getDefaultLanguageKey()
|
language : getDefaultLanguageKey(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timezone set by the user, in IANA zone key format (Olson time
|
||||||
|
* zone database).
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
timezone : getDetectedTimezone()
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.preferences .update-password .form,
|
.preferences .update-password .form,
|
||||||
.preferences .language .form {
|
.preferences .locale .form {
|
||||||
padding-left: 0.5em;
|
padding-left: 0.5em;
|
||||||
border-left: 3px solid rgba(0, 0, 0, 0.125);
|
border-left: 3px solid rgba(0, 0, 0, 0.125);
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
<div class="preferences" ng-class="{loading: !isLoaded()}">
|
<div class="preferences" ng-class="{loading: !isLoaded()}">
|
||||||
|
|
||||||
<!-- Language settings -->
|
<!-- Locale settings -->
|
||||||
<div class="settings section language">
|
<div class="settings section locale">
|
||||||
<p>{{'SETTINGS_PREFERENCES.HELP_LANGUAGE' | translate}}</p>
|
<p>{{'SETTINGS_PREFERENCES.HELP_LOCALE' | translate}}</p>
|
||||||
|
|
||||||
<!-- Language selection -->
|
<!-- Language selection -->
|
||||||
<div class="form">
|
<div class="form">
|
||||||
@@ -13,6 +13,15 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Timezone selection -->
|
||||||
|
<div class="form">
|
||||||
|
<guac-form-field
|
||||||
|
field="{ 'type' : 'TIMEZONE', 'name' : 'timezone' }"
|
||||||
|
model="preferences.timezone"
|
||||||
|
namespace="'SETTINGS_PREFERENCES'">
|
||||||
|
</guac-form-field>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Password update -->
|
<!-- Password update -->
|
||||||
|
@@ -85,6 +85,9 @@
|
|||||||
<script type="text/javascript" src="webjars/angular-translate-interpolation-messageformat/2.16.0/angular-translate-interpolation-messageformat.min.js"></script>
|
<script type="text/javascript" src="webjars/angular-translate-interpolation-messageformat/2.16.0/angular-translate-interpolation-messageformat.min.js"></script>
|
||||||
<script type="text/javascript" src="webjars/angular-translate-loader-static-files/2.16.0/angular-translate-loader-static-files.min.js"></script>
|
<script type="text/javascript" src="webjars/angular-translate-loader-static-files/2.16.0/angular-translate-loader-static-files.min.js"></script>
|
||||||
|
|
||||||
|
<!-- JSTZ -->
|
||||||
|
<script type="text/javascript" src="webjars/jstz/1.0.10/dist/jstz.min.js"></script>
|
||||||
|
|
||||||
<!-- Polyfills for the "datalist" element, Blob and the FileSaver API -->
|
<!-- Polyfills for the "datalist" element, Blob and the FileSaver API -->
|
||||||
<script type="text/javascript" src="webjars/blob-polyfill/1.0.20150320/Blob.js"></script>
|
<script type="text/javascript" src="webjars/blob-polyfill/1.0.20150320/Blob.js"></script>
|
||||||
<script type="text/javascript" src="webjars/datalist-polyfill/1.14.0/datalist-polyfill.min.js"></script>
|
<script type="text/javascript" src="webjars/datalist-polyfill/1.14.0/datalist-polyfill.min.js"></script>
|
||||||
|
@@ -415,6 +415,7 @@
|
|||||||
"FIELD_HEADER_REMOTE_APP_ARGS" : "Parameters:",
|
"FIELD_HEADER_REMOTE_APP_ARGS" : "Parameters:",
|
||||||
"FIELD_HEADER_REMOTE_APP_DIR" : "Working directory:",
|
"FIELD_HEADER_REMOTE_APP_DIR" : "Working directory:",
|
||||||
"FIELD_HEADER_REMOTE_APP" : "Program:",
|
"FIELD_HEADER_REMOTE_APP" : "Program:",
|
||||||
|
"FIELD_HEADER_TIMEZONE" : "Timezone:",
|
||||||
"FIELD_HEADER_SECURITY" : "Security mode:",
|
"FIELD_HEADER_SECURITY" : "Security mode:",
|
||||||
"FIELD_HEADER_SERVER_LAYOUT" : "Keyboard layout:",
|
"FIELD_HEADER_SERVER_LAYOUT" : "Keyboard layout:",
|
||||||
"FIELD_HEADER_SFTP_DIRECTORY" : "Default upload directory:",
|
"FIELD_HEADER_SFTP_DIRECTORY" : "Default upload directory:",
|
||||||
@@ -757,6 +758,7 @@
|
|||||||
"FIELD_HEADER_PASSWORD_OLD" : "Current Password:",
|
"FIELD_HEADER_PASSWORD_OLD" : "Current Password:",
|
||||||
"FIELD_HEADER_PASSWORD_NEW" : "New Password:",
|
"FIELD_HEADER_PASSWORD_NEW" : "New Password:",
|
||||||
"FIELD_HEADER_PASSWORD_NEW_AGAIN" : "Confirm New Password:",
|
"FIELD_HEADER_PASSWORD_NEW_AGAIN" : "Confirm New Password:",
|
||||||
|
"FIELD_HEADER_TIMEZONE" : "Timezone:",
|
||||||
"FIELD_HEADER_USERNAME" : "Username:",
|
"FIELD_HEADER_USERNAME" : "Username:",
|
||||||
|
|
||||||
"HELP_DEFAULT_INPUT_METHOD" : "The default input method determines how keyboard events are received by Guacamole. Changing this setting may be necessary when using a mobile device, or when typing through an IME. This setting can be overridden on a per-connection basis within the Guacamole menu.",
|
"HELP_DEFAULT_INPUT_METHOD" : "The default input method determines how keyboard events are received by Guacamole. Changing this setting may be necessary when using a mobile device, or when typing through an IME. This setting can be overridden on a per-connection basis within the Guacamole menu.",
|
||||||
@@ -764,7 +766,7 @@
|
|||||||
"HELP_INPUT_METHOD_NONE" : "@:CLIENT.HELP_INPUT_METHOD_NONE",
|
"HELP_INPUT_METHOD_NONE" : "@:CLIENT.HELP_INPUT_METHOD_NONE",
|
||||||
"HELP_INPUT_METHOD_OSK" : "@:CLIENT.HELP_INPUT_METHOD_OSK",
|
"HELP_INPUT_METHOD_OSK" : "@:CLIENT.HELP_INPUT_METHOD_OSK",
|
||||||
"HELP_INPUT_METHOD_TEXT" : "@:CLIENT.HELP_INPUT_METHOD_TEXT",
|
"HELP_INPUT_METHOD_TEXT" : "@:CLIENT.HELP_INPUT_METHOD_TEXT",
|
||||||
"HELP_LANGUAGE" : "Select a different language below to change the language of all text within Guacamole. Available choices will depend on which languages are installed.",
|
"HELP_LOCALE" : "Options below are related to the locale of the user and will impact how various parts of the interface are displayed.",
|
||||||
"HELP_MOUSE_MODE_ABSOLUTE" : "@:CLIENT.HELP_MOUSE_MODE_ABSOLUTE",
|
"HELP_MOUSE_MODE_ABSOLUTE" : "@:CLIENT.HELP_MOUSE_MODE_ABSOLUTE",
|
||||||
"HELP_MOUSE_MODE_RELATIVE" : "@:CLIENT.HELP_MOUSE_MODE_RELATIVE",
|
"HELP_MOUSE_MODE_RELATIVE" : "@:CLIENT.HELP_MOUSE_MODE_RELATIVE",
|
||||||
"HELP_UPDATE_PASSWORD" : "If you wish to change your password, enter your current password and the desired new password below, and click \"Update Password\". The change will take effect immediately.",
|
"HELP_UPDATE_PASSWORD" : "If you wish to change your password, enter your current password and the desired new password below, and click \"Update Password\". The change will take effect immediately.",
|
||||||
|
Reference in New Issue
Block a user