GUAC-340: Expose available protocols within Environment.

This commit is contained in:
Michael Jumper
2014-11-23 17:39:48 -08:00
parent ff286264e4
commit 49b91ebe56
23 changed files with 222 additions and 155 deletions

View File

@@ -23,11 +23,13 @@
package org.glyptodon.guacamole.environment;
import java.io.File;
import java.util.Map;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.properties.BooleanGuacamoleProperty;
import org.glyptodon.guacamole.properties.GuacamoleProperty;
import org.glyptodon.guacamole.properties.IntegerGuacamoleProperty;
import org.glyptodon.guacamole.properties.StringGuacamoleProperty;
import org.glyptodon.guacamole.protocols.ProtocolInfo;
/**
* The environment of an arbitrary Guacamole instance, describing available
@@ -80,6 +82,24 @@ public interface Environment {
*/
public File getGuacamoleHome();
/**
* Returns a map of all available protocols, where each key is the name of
* that protocol as would be passed to guacd during connection.
*
* @return A map of all available protocols.
*/
public Map<String, ProtocolInfo> getProtocols();
/**
* Returns the protocol having the given name. The name must be the
* protocol name as would be passed to guacd during connection.
*
* @param name The name of the protocol.
* @return The protocol having the given name, or null if no such
* protocol is registered.
*/
public ProtocolInfo getProtocol(String name);
/**
* Given a GuacamoleProperty, parses and returns the value set for that
* property in guacamole.properties, if any.

View File

@@ -22,14 +22,27 @@
package org.glyptodon.guacamole.environment;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.properties.GuacamoleProperty;
import org.glyptodon.guacamole.protocols.ProtocolInfo;
import org.glyptodon.guacamole.xml.DocumentHandler;
import org.glyptodon.guacamole.xml.protocol.ProtocolTagHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* The environment of the locally-running Guacamole instance, describing
@@ -40,6 +53,17 @@ import org.glyptodon.guacamole.properties.GuacamoleProperty;
*/
public class LocalEnvironment implements Environment {
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(LocalEnvironment.class);
/**
* Array of all known protocol names.
*/
private static final String[] KNOWN_PROTOCOLS = new String[]{
"vnc", "rdp", "ssh", "telnet"};
/**
* All properties read from guacamole.properties.
*/
@@ -50,6 +74,11 @@ public class LocalEnvironment implements Environment {
*/
private final File guacHome;
/**
* The map of all available protocols.
*/
private final Map<String, ProtocolInfo> availableProtocols;
/**
* Creates a new Environment, initializing that environment based on the
* location of GUACAMOLE_HOME and the contents of guacamole.properties.
@@ -59,9 +88,11 @@ public class LocalEnvironment implements Environment {
*/
public LocalEnvironment() throws GuacamoleException {
properties = new Properties();
// Determine location of GUACAMOLE_HOME
guacHome = findGuacamoleHome();
// Read properties
properties = new Properties();
try {
InputStream stream;
@@ -92,6 +123,9 @@ public class LocalEnvironment implements Environment {
throw new GuacamoleServerException("Error reading guacamole.properties", e);
}
// Read all protocols
availableProtocols = readProtocols();
}
/**
@@ -127,6 +161,130 @@ public class LocalEnvironment implements Environment {
}
/**
* Parses the given XML file, returning the parsed ProtocolInfo.
*
* @param input An input stream containing XML describing the parameters
* associated with a protocol supported by Guacamole.
* @return A new ProtocolInfo object which contains the parameters described
* by the XML file parsed.
* @throws GuacamoleException If an error occurs while parsing the XML file.
*/
private ProtocolInfo readProtocol(InputStream input)
throws GuacamoleException {
// Parse document
try {
// Get handler for root element
ProtocolTagHandler protocolTagHandler =
new ProtocolTagHandler();
// Set up document handler
DocumentHandler contentHandler = new DocumentHandler(
"protocol", protocolTagHandler);
// Set up XML parser
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(contentHandler);
// Read and parse file
InputStream xml = new BufferedInputStream(input);
parser.parse(new InputSource(xml));
xml.close();
// Return parsed protocol
return protocolTagHandler.asProtocolInfo();
}
catch (IOException e) {
throw new GuacamoleException("Error reading basic user mapping file.", e);
}
catch (SAXException e) {
throw new GuacamoleException("Error parsing basic user mapping XML.", e);
}
}
/**
* Reads through all pre-defined protocols and any protocols within the
* "protocols" subdirectory of GUACAMOLE_HOME, returning a map containing
* each of these protocols. The key of each entry will be the name of that
* protocol, as would be passed to guacd during connection.
*
* @return A map of all available protocols.
* @throws GuacamoleException If an error occurs while reading the various
* protocol XML files.
*/
private Map<String, ProtocolInfo> readProtocols() throws GuacamoleException {
// Map of all available protocols
Map<String, ProtocolInfo> protocols = new HashMap<String, ProtocolInfo>();
// Get protcols directory
File protocol_directory = new File(getGuacamoleHome(), "protocols");
// Read protocols from directory if it exists
if (protocol_directory.isDirectory()) {
// Get all XML files
File[] files = protocol_directory.listFiles(
new FilenameFilter() {
@Override
public boolean accept(File file, String string) {
return string.endsWith(".xml");
}
}
);
// Load each protocol from each file
for (File file : files) {
try {
// Parse protocol
FileInputStream stream = new FileInputStream(file);
ProtocolInfo protocol = readProtocol(stream);
stream.close();
// Store protocol
protocols.put(protocol.getName(), protocol);
}
catch (IOException e) {
logger.error("Unable to read connection parameter information from \"{}\": {}", file.getAbsolutePath(), e.getMessage());
logger.debug("Error reading protocol XML.", e);
}
}
}
// If known protocols are not already defined, read from classpath
for (String protocol : KNOWN_PROTOCOLS) {
// If protocol not defined yet, attempt to load from classpath
if (!protocols.containsKey(protocol)) {
InputStream stream = LocalEnvironment.class.getResourceAsStream(
"/org/glyptodon/guacamole/protocols/"
+ protocol + ".xml");
// Parse XML if available
if (stream != null)
protocols.put(protocol, readProtocol(stream));
}
}
// Protocols map now fully populated
return protocols;
}
@Override
public File getGuacamoleHome() {
return guacHome;
@@ -161,4 +319,14 @@ public class LocalEnvironment implements Environment {
}
@Override
public Map<String, ProtocolInfo> getProtocols() {
return availableProtocols;
}
@Override
public ProtocolInfo getProtocol(String name) {
return availableProtocols.get(name);
}
}

View File

@@ -0,0 +1,102 @@
/*
* 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.
*/
package org.glyptodon.guacamole.protocols;
import java.util.ArrayList;
import java.util.Collection;
/**
* Describes a protocol and all parameters associated with it, as required by
* a protocol plugin for guacd. This class allows known parameters for a
* protocol to be exposed to the user as friendly fields.
*
* @author Michael Jumper
*/
public class ProtocolInfo {
/**
* The human-readable title associated with this protocol.
*/
private String title;
/**
* The unique name associated with this protocol.
*/
private String name;
/**
* A collection of all associated protocol parameters.
*/
private Collection<ProtocolParameter> parameters =
new ArrayList<ProtocolParameter>();
/**
* Returns the human-readable title associated with this protocol.
*
* @return The human-readable title associated with this protocol.
*/
public String getTitle() {
return title;
}
/**
* Sets the human-readable title associated with this protocol.
*
* @param title The human-readable title to associate with this protocol.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Returns the unique name of this protocol. The protocol name is the
* value required by the corresponding protocol plugin for guacd.
*
* @return The unique name of this protocol.
*/
public String getName() {
return name;
}
/**
* Sets the unique name of this protocol. The protocol name is the value
* required by the corresponding protocol plugin for guacd.
*
* @param name The unique name of this protocol.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns a mutable collection of the protocol parameters associated with
* this protocol. Changes to this collection affect the parameters exposed
* to the user.
*
* @return A mutable collection of protocol parameters.
*/
public Collection<ProtocolParameter> getParameters() {
return parameters;
}
}

View File

@@ -0,0 +1,192 @@
/*
* 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.
*/
package org.glyptodon.guacamole.protocols;
import java.util.ArrayList;
import java.util.Collection;
/**
* Represents a parameter of a protocol.
*
* @author Michael Jumper
*/
public class ProtocolParameter {
/**
* All possible types of protocol parameter.
*/
public enum Type {
/**
* A text parameter, accepting arbitrary values.
*/
TEXT,
/**
* A username parameter. This parameter type generally behaves
* identically to arbitrary text parameters, but has semantic
* differences. If credential pass-through is in use, the value for this
* parameter may be automatically provided using the credentials
* originally used by the user to authenticate.
*/
USERNAME,
/**
* A password parameter, whose value is sensitive and must be hidden. If
* credential pass-through is in use, the value for this parameter may
* be automatically provided using the credentials originally used by
* the user to authenticate.
*/
PASSWORD,
/**
* A numeric parameter, whose value must contain only digits.
*/
NUMERIC,
/**
* A boolean parameter, whose value is either blank or "true".
*/
BOOLEAN,
/**
* An enumerated parameter, whose legal values are fully enumerated
* by a provided, finite list.
*/
ENUM,
/**
* A text parameter that can span more than one line.
*/
MULTILINE
}
/**
* The unique name that identifies this parameter to the protocol plugin.
*/
private String name;
/**
* A human-readable name to be presented to the user.
*/
private String title;
/**
* The type of this field.
*/
private Type type;
/**
* The value of this parameter, for boolean parameters.
*/
private String value;
/**
* A collection of all associated parameter options.
*/
private Collection<ProtocolParameterOption> options =
new ArrayList<ProtocolParameterOption>();
/**
* Returns the name associated with this protocol parameter.
* @return The name associated with this protocol parameter.
*/
public String getName() {
return name;
}
/**
* Sets the name associated with this protocol parameter. This name must
* uniquely identify this parameter among the others accepted by the
* corresponding protocol.
*
* @param name The name to assign to this protocol parameter.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the title associated with this protocol parameter.
* @return The title associated with this protocol parameter.
*/
public String getTitle() {
return title;
}
/**
* Sets the title associated with this protocol parameter. The title must
* be a human-readable string which describes accurately this parameter.
*
* @param title A human-readable string describing this parameter.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Returns the value associated with this protocol parameter.
* @return The value associated with this protocol parameter.
*/
public String getValue() {
return value;
}
/**
* Sets the value associated with this protocol parameter. The value must
* be a human-readable string which describes accurately this parameter.
*
* @param value A human-readable string describing this parameter.
*/
public void setValue(String value) {
this.value = value;
}
/**
* Returns the type of this parameter.
* @return The type of this parameter.
*/
public Type getType() {
return type;
}
/**
* Sets the type of this parameter.
* @param type The type of this parameter.
*/
public void setType(Type type) {
this.type = type;
}
/**
* Returns a mutable collection of protocol parameter options. Changes to
* this collection directly affect the available options.
*
* @return A mutable collection of parameter options.
*/
public Collection<ProtocolParameterOption> getOptions() {
return options;
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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.
*/
package org.glyptodon.guacamole.protocols;
/**
* Describes an available legal value for an enumerated protocol parameter.
*
* @author Michael Jumper
*/
public class ProtocolParameterOption {
/**
* The value that will be sent to the client plugin if this option is
* chosen.
*/
private String value;
/**
* A human-readable title describing the effect of the value.
*/
private String title;
/**
* Returns the value that will be sent to the client plugin if this option
* is chosen.
*
* @return The value that will be sent if this option is chosen.
*/
public String getValue() {
return value;
}
/**
* Sets the value that will be sent to the client plugin if this option is
* chosen.
*
* @param value The value to send if this option is chosen.
*/
public void setValue(String value) {
this.value = value;
}
/**
* Returns the human-readable title describing the effect of this option.
* @return The human-readable title describing the effect of this option.
*/
public String getTitle() {
return title;
}
/**
* Sets the human-readable title describing the effect of this option.
* @param title A human-readable title describing the effect of this option.
*/
public void setTitle(String title) {
this.title = title;
}
}

View File

@@ -0,0 +1,200 @@
/*
* 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.
*/
package org.glyptodon.guacamole.xml;
import java.util.Deque;
import java.util.LinkedList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* A simple ContentHandler implementation which digests SAX document events and
* produces simpler tag-level events, maintaining its own stack for the
* convenience of the tag handlers.
*
* @author Mike Jumper
*/
public class DocumentHandler extends DefaultHandler {
/**
* The name of the root element of the document.
*/
private String rootElementName;
/**
* The handler which will be used to handle element events for the root
* element of the document.
*/
private TagHandler root;
/**
* The stack of all states applicable to the current parser state. Each
* element of the stack references the TagHandler for the element being
* parsed at that level of the document, where the current element is
* last in the stack, and the root element is first.
*/
private Deque<DocumentHandlerState> stack =
new LinkedList<DocumentHandlerState>();
/**
* Creates a new DocumentHandler which will use the given TagHandler
* to handle the root element.
*
* @param rootElementName The name of the root element of the document
* being handled.
* @param root The TagHandler to use for the root element.
*/
public DocumentHandler(String rootElementName, TagHandler root) {
this.root = root;
this.rootElementName = rootElementName;
}
/**
* Returns the current element state. The current element state is the
* state of the element the parser is currently within.
*
* @return The current element state.
*/
private DocumentHandlerState getCurrentState() {
// If no state, return null
if (stack.isEmpty())
return null;
return stack.getLast();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// Get current state
DocumentHandlerState current = getCurrentState();
// Handler for tag just read
TagHandler handler;
// If no stack, use root handler
if (current == null) {
// Validate element name
if (!localName.equals(rootElementName))
throw new SAXException("Root element must be '" + rootElementName + "'");
handler = root;
}
// Otherwise, get handler from parent
else {
TagHandler parent_handler = current.getTagHandler();
handler = parent_handler.childElement(localName);
}
// If no handler returned, the element was not expected
if (handler == null)
throw new SAXException("Unexpected element: '" + localName + "'");
// Initialize handler
handler.init(attributes);
// Append new element state to stack
stack.addLast(new DocumentHandlerState(handler));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// Pop last element from stack
DocumentHandlerState completed = stack.removeLast();
// Finish element by sending text content
completed.getTagHandler().complete(
completed.getTextContent().toString());
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// Append received chunk to text content
getCurrentState().getTextContent().append(ch, start, length);
}
/**
* The current state of the DocumentHandler.
*/
private static class DocumentHandlerState {
/**
* The current text content of the current element being parsed.
*/
private StringBuilder textContent = new StringBuilder();
/**
* The TagHandler which must handle document events related to the
* element currently being parsed.
*/
private TagHandler tagHandler;
/**
* Creates a new DocumentHandlerState which will maintain the state
* of parsing of the current element, as well as contain the TagHandler
* which will receive events related to that element.
*
* @param tagHandler The TagHandler which should receive any events
* related to the element being parsed.
*/
public DocumentHandlerState(TagHandler tagHandler) {
this.tagHandler = tagHandler;
}
/**
* Returns the mutable StringBuilder which contains the current text
* content of the element being parsed.
*
* @return The mutable StringBuilder which contains the current text
* content of the element being parsed.
*/
public StringBuilder getTextContent() {
return textContent;
}
/**
* Returns the TagHandler which must handle any events relating to the
* element being parsed.
*
* @return The TagHandler which must handle any events relating to the
* element being parsed.
*/
public TagHandler getTagHandler() {
return tagHandler;
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.
*/
package org.glyptodon.guacamole.xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* A simple element-level event handler for events triggered by the
* SAX-driven DocumentHandler parser.
*
* @author Mike Jumper
*/
public interface TagHandler {
/**
* Called when a child element of the current element is parsed.
*
* @param localName The local name of the child element seen.
* @return The TagHandler which should handle all element-level events
* related to the child element.
* @throws SAXException If the child element being parsed was not expected,
* or some other error prevents a proper TagHandler
* from being constructed for the child element.
*/
public TagHandler childElement(String localName)
throws SAXException;
/**
* Called when the element corresponding to this TagHandler is first seen,
* just after an instance is created.
*
* @param attributes The attributes of the element seen.
* @throws SAXException If an error prevents a the TagHandler from being
* from being initialized.
*/
public void init(Attributes attributes) throws SAXException;
/**
* Called when this element, and all child elements, have been fully parsed,
* and the entire text content of this element (if any) is available.
*
* @param textContent The full text content of this element, if any.
* @throws SAXException If the text content received is not valid for any
* reason, or the child elements parsed are not
* correct.
*/
public void complete(String textContent) throws SAXException;
}

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
/**
* Classes driving the SAX-based XML parser used by the Guacamole web
* application.
*/
package org.glyptodon.guacamole.xml;

View File

@@ -0,0 +1,65 @@
/*
* 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.
*/
package org.glyptodon.guacamole.xml.protocol;
import org.glyptodon.guacamole.protocols.ProtocolParameterOption;
import org.glyptodon.guacamole.xml.TagHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* TagHandler for the "option" element.
*
* @author Mike Jumper
*/
public class OptionTagHandler implements TagHandler {
/**
* The option backing this option tag.
*/
private ProtocolParameterOption option = new ProtocolParameterOption();
@Override
public void init(Attributes attributes) throws SAXException {
option.setValue(attributes.getValue("value"));
}
@Override
public TagHandler childElement(String localName) throws SAXException {
throw new SAXException("The 'param' tag can contain no elements.");
}
@Override
public void complete(String textContent) throws SAXException {
option.setTitle(textContent);
}
/**
* Returns the ProtocolParameterOption backing this tag.
* @return The ProtocolParameterOption backing this tag.
*/
public ProtocolParameterOption asProtocolParameterOption() {
return option;
}
}

View File

@@ -0,0 +1,124 @@
/*
* 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.
*/
package org.glyptodon.guacamole.xml.protocol;
import org.glyptodon.guacamole.protocols.ProtocolParameter;
import org.glyptodon.guacamole.xml.TagHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* TagHandler for the "param" element.
*
* @author Mike Jumper
*/
public class ParamTagHandler implements TagHandler {
/**
* The ProtocolParameter backing this tag handler.
*/
private ProtocolParameter protocolParameter = new ProtocolParameter();
@Override
public void init(Attributes attributes) throws SAXException {
protocolParameter.setName(attributes.getValue("name"));
protocolParameter.setTitle(attributes.getValue("title"));
protocolParameter.setValue(attributes.getValue("value"));
// Parse type
String type = attributes.getValue("type");
// Text field
if ("text".equals(type))
protocolParameter.setType(ProtocolParameter.Type.TEXT);
// Numeric field
else if ("numeric".equals(type))
protocolParameter.setType(ProtocolParameter.Type.NUMERIC);
// Username field
else if ("username".equals(type))
protocolParameter.setType(ProtocolParameter.Type.USERNAME);
// Password field
else if ("password".equals(type))
protocolParameter.setType(ProtocolParameter.Type.PASSWORD);
// Enumerated field
else if ("enum".equals(type))
protocolParameter.setType(ProtocolParameter.Type.ENUM);
// Multiline field
else if ("multiline".equals(type))
protocolParameter.setType(ProtocolParameter.Type.MULTILINE);
// Boolean field
else if ("boolean".equals(type)) {
protocolParameter.setType(ProtocolParameter.Type.BOOLEAN);
if(protocolParameter.getValue() == null)
throw new SAXException
("A value is required for the boolean parameter type.");
}
// Otherwise, fail with unrecognized type
else
throw new SAXException("Invalid parameter type: " + type);
}
@Override
public TagHandler childElement(String localName) throws SAXException {
// Start parsing of option tags
if (localName.equals("option")) {
// Get tag handler for option tag
OptionTagHandler tagHandler = new OptionTagHandler();
// Store stub in options collection
protocolParameter.getOptions().add(
tagHandler.asProtocolParameterOption());
return tagHandler;
}
return null;
}
@Override
public void complete(String textContent) throws SAXException {
// Do nothing
}
/**
* Returns the ProtocolParameter backing this tag.
* @return The ProtocolParameter backing this tag.
*/
public ProtocolParameter asProtocolParameter() {
return protocolParameter;
}
}

View File

@@ -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.
*/
package org.glyptodon.guacamole.xml.protocol;
import org.glyptodon.guacamole.protocols.ProtocolInfo;
import org.glyptodon.guacamole.xml.TagHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* TagHandler for the "protocol" element.
*
* @author Mike Jumper
*/
public class ProtocolTagHandler implements TagHandler {
/**
* The ProtocolInfo object which will contain all data parsed by this tag
* handler.
*/
private ProtocolInfo info = new ProtocolInfo();
@Override
public void init(Attributes attributes) throws SAXException {
info.setName(attributes.getValue("name"));
info.setTitle(attributes.getValue("title"));
}
@Override
public TagHandler childElement(String localName) throws SAXException {
// Start parsing of param tags, add to list of all parameters
if (localName.equals("param")) {
// Get tag handler for param tag
ParamTagHandler tagHandler = new ParamTagHandler();
// Store stub in parameters collection
info.getParameters().add(tagHandler.asProtocolParameter());
return tagHandler;
}
return null;
}
@Override
public void complete(String textContent) throws SAXException {
// Do nothing
}
/**
* Returns the ProtocolInfo backing this tag.
* @return The ProtocolInfo backing this tag.
*/
public ProtocolInfo asProtocolInfo() {
return info;
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
/**
* Classes related to parsing XML files which describe the parameters of a
* protocol.
*/
package org.glyptodon.guacamole.xml.protocol;

View File

@@ -0,0 +1,53 @@
<protocol name="rdp" title="RDP">
<param name="hostname" type="text" title="Hostname"/>
<param name="port" type="numeric" title="Port"/>
<param name="username" type="username" title="Username"/>
<param name="password" type="password" title="Password"/>
<param name="domain" type="text" title="Domain"/>
<param name="initial-program" type="text" title="Initial program"/>
<param name="width" type="numeric" title="Display width"/>
<param name="height" type="numeric" title="Display height"/>
<param name="dpi" type="numeric" title="Display resolution (DPI)"/>
<param name="color-depth" type="enum" title="Color depth">
<option value="8">256 color</option>
<option value="16">Low color (16-bit)</option>
<option value="24">True color (24-bit)</option>
<option value="32">True color (32-bit)</option>
</param>
<param name="server-layout" type="enum" title="Keyboard layout">
<option value="">(default)</option>
<option value="en-us-qwerty">US English (Qwerty)</option>
<option value="fr-fr-azerty">French (Azerty)</option>
<option value="de-de-qwertz">German (Qwertz)</option>
<option value="failsafe">Unicode</option>
</param>
<param name="console" type="boolean" title="Administrator console" value="true"/>
<param name="console-audio" type="boolean" title="Support audio in console" value="true"/>
<param name="disable-audio" type="boolean" title="Disable audio" value="true"/>
<param name="enable-printing" type="boolean" title="Enable printing" value="true"/>
<param name="enable-drive" type="boolean" title="Enable drive" value="true"/>
<param name="drive-path" type="text" title="Drive path"/>
<param name="security" type="enum" title="Security mode">
<option value="">(default)</option>
<option value="rdp">RDP encryption</option>
<option value="tls">TLS encryption</option>
<option value="nla">NLA (Network Level Authentication)</option>
<option value="any">Any</option>
</param>
<param name="disable-auth" type="boolean" title="Disable authentication" value="true"/>
<param name="ignore-cert" type="boolean" title="Ignore server certificate" value="true"/>
<param name="remote-app" type="text" title="RemoteApp program"/>
<param name="remote-app-dir" type="text" title="RemoteApp working directory"/>
<param name="remote-app-args" type="text" title="RemoteApp parameters"/>
<param name="static-channels" type="text" title="Static channel names"/>
</protocol>

View File

@@ -0,0 +1,33 @@
<protocol name="ssh" title="SSH">
<param name="hostname" title="Hostname" type="text"/>
<param name="port" title="Port" type="numeric"/>
<param name="username" title="Username" type="username"/>
<param name="password" title="Password" type="password"/>
<param name="font-name" title="Font name" type="text"/>
<param name="font-size" title="Font size" type="enum">
<option value=""></option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="14">14</option>
<option value="18">18</option>
<option value="24">24</option>
<option value="30">30</option>
<option value="36">36</option>
<option value="48">48</option>
<option value="60">60</option>
<option value="72">72</option>
<option value="96">96</option>
</param>
<param name="enable-sftp" type="boolean" title="Enable SFTP" value="true"/>
<param name="private-key" type="multiline" title="Private key"/>
<param name="passphrase" type="password" title="Passphrase"/>
</protocol>

View File

@@ -0,0 +1,31 @@
<protocol name="telnet" title="Telnet">
<param name="hostname" title="Hostname" type="text"/>
<param name="port" title="Port" type="numeric"/>
<param name="username" title="Username" type="username"/>
<param name="password" title="Password" type="password"/>
<param name="password-regex"
title="Password regular expression" type="text"/>
<param name="font-name" title="Font name" type="text"/>
<param name="font-size" title="Font size" type="enum">
<option value=""></option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="14">14</option>
<option value="18">18</option>
<option value="24">24</option>
<option value="30">30</option>
<option value="36">36</option>
<option value="48">48</option>
<option value="60">60</option>
<option value="72">72</option>
<option value="96">96</option>
</param>
</protocol>

View File

@@ -0,0 +1,28 @@
<protocol name="vnc" title="VNC">
<param name="hostname" type="text" title="Hostname"/>
<param name="port" type="numeric" title="Port"/>
<param name="password" type="password" title="Password"/>
<param name="read-only" type="boolean" title="Read-only" value="true"/>
<param name="swap-red-blue" type="boolean" title="Swap red/blue components" value="true"/>
<param name="cursor" type="enum" title="Cursor">
<option value="local">Local</option>
<option value="remote">Remote</option>
</param>
<param name="color-depth" type="enum" title="Color depth">
<option value="8">256 color</option>
<option value="16">Low color (16-bit)</option>
<option value="24">True color (24-bit)</option>
<option value="32">True color (32-bit)</option>
</param>
<param name="dest-host" type="text" title="Repeater destination host"/>
<param name="dest-port" type="numeric" title="Repeater destination port"/>
<param name="enable-audio" type="boolean" title="Enable audio" value="true"/>
<param name="audio-servername" type="text" title="Audio server name"/>
</protocol>