Add .gitignore and .ratignore files for various directories
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
gyurix
2025-04-29 21:43:12 +02:00
parent 983ecbfc53
commit be9f66dee9
2167 changed files with 254128 additions and 0 deletions

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-quickconnect</artifactId>
<packaging>jar</packaging>
<version>1.6.0</version>
<name>guacamole-auth-quickconnect</name>
<url>http://guacamole.apache.org/</url>
<parent>
<groupId>org.apache.guacamole</groupId>
<artifactId>extensions</artifactId>
<version>1.6.0</version>
<relativePath>../</relativePath>
</parent>
<build>
<plugins>
<!-- JS/CSS Minification Plugin -->
<plugin>
<groupId>com.github.buckelieg</groupId>
<artifactId>minify-maven-plugin</artifactId>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<charset>UTF-8</charset>
<webappSourceDir>${basedir}/src/main/resources</webappSourceDir>
<webappTargetDir>${project.build.directory}/classes</webappTargetDir>
<cssSourceDir>/</cssSourceDir>
<cssTargetDir>/</cssTargetDir>
<cssFinalFile>quickconnect.css</cssFinalFile>
<cssSourceIncludes>
<cssSourceInclude>**/*.css</cssSourceInclude>
</cssSourceIncludes>
<jsSourceDir>/</jsSourceDir>
<jsTargetDir>/</jsTargetDir>
<jsFinalFile>quickconnect.js</jsFinalFile>
<jsSourceIncludes>
<jsSourceInclude>**/*.js</jsSourceInclude>
</jsSourceIncludes>
<!-- Do not minify and include tests -->
<jsSourceExcludes>
<jsSourceExclude>**/*.test.js</jsSourceExclude>
</jsSourceExcludes>
<jsEngine>CLOSURE</jsEngine>
<!-- Disable warnings for JSDoc annotations -->
<closureWarningLevels>
<misplacedTypeAnnotation>OFF</misplacedTypeAnnotation>
<nonStandardJsDocs>OFF</nonStandardJsDocs>
</closureWarningLevels>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>1.6.0</version>
<scope>provided</scope>
</dependency>
<!-- Guice -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<!-- Jersey - JAX-RS Implementation -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>dist</id>
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
<!-- Output tar.gz -->
<formats>
<format>tar.gz</format>
</formats>
<!-- Include licenses and extension .jar -->
<fileSets>
<!-- Include licenses -->
<fileSet>
<outputDirectory></outputDirectory>
<directory>target/licenses</directory>
</fileSet>
<!-- Include extension .jar -->
<fileSet>
<directory>target</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,68 @@
/*
* 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.auth.quickconnect;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
import org.apache.guacamole.net.auth.UserContext;
/**
* This class provides the necessary hooks into the Guacamole Client authentication
* process so that the QuickConnect functionality can be initialized and used
* throughout the web client.
*/
public class QuickConnectAuthenticationProvider extends AbstractAuthenticationProvider {
/**
* Injector which will manage the object graph of this authentication
* provider.
*/
private final Injector injector;
public QuickConnectAuthenticationProvider() throws GuacamoleException {
// Set up Guice injector.
injector = Guice.createInjector(
new QuickConnectAuthenticationProviderModule(this)
);
}
@Override
public String getIdentifier() {
return "quickconnect";
}
@Override
public UserContext getUserContext(AuthenticatedUser authenticatedUser)
throws GuacamoleException {
QuickConnectUserContext userContext =
injector.getInstance(QuickConnectUserContext.class);
userContext.init(authenticatedUser.getIdentifier());
return userContext;
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.auth.quickconnect;
import com.google.inject.AbstractModule;
import org.apache.guacamole.auth.quickconnect.conf.ConfigurationService;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.auth.AuthenticationProvider;
/**
* Guice module which configures QuickConnect-specific injections.
*/
public class QuickConnectAuthenticationProviderModule extends AbstractModule {
/**
* Guacamole server environment.
*/
private final Environment environment;
/**
* A reference to the QuickConnectAuthenticationProvider on behalf of which
* this module has configured injection.
*/
private final AuthenticationProvider authProvider;
/**
* Creates a new QuickConnect authentication provider module which
* configures injection for the QuickConnectAuthenticationProvider.
*
* @param authProvider
* The AuthenticationProvider for which injection is being configured.
*
* @throws GuacamoleException
* If an error occurs while retrieving the Guacamole server
* environment.
*/
public QuickConnectAuthenticationProviderModule(
AuthenticationProvider authProvider) throws GuacamoleException {
// Get local environment
this.environment = LocalEnvironment.getInstance();
// Store associated auth provider
this.authProvider = authProvider;
}
@Override
protected void configure() {
// Bind core implementations of guacamole-ext classes
bind(AuthenticationProvider.class).toInstance(authProvider);
bind(Environment.class).toInstance(environment);
// Bind QuickConnect-specific services
bind(ConfigurationService.class);
bind(QuickConnectUserContext.class);
bind(QuickConnectDirectory.class);
}
}

View File

@@ -0,0 +1,138 @@
/*
* 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.auth.quickconnect;
import com.google.inject.Inject;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.quickconnect.utility.QCParser;
import org.apache.guacamole.auth.quickconnect.conf.ConfigurationService;
import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.simple.SimpleConnection;
import org.apache.guacamole.net.auth.simple.SimpleDirectory;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
/**
* Implementation of a directory to store Connection objects
* completely in memory.
*/
public class QuickConnectDirectory extends SimpleDirectory<Connection> {
/**
* The configuration service for the QuickConnect module.
*/
@Inject
private ConfigurationService confService;
/**
* The connections to store.
*/
private final Map<String, Connection> connections =
new ConcurrentHashMap<>();
/**
* The root connection group for this directory.
*/
private QuickConnectionGroup rootGroup;
/**
* The internal counter for connection IDs.
*/
private AtomicInteger connectionId;
/**
* Initialize the QuickConnectDirectory with the default empty Map for
* Connection objects, and the specified ConnectionGroup at the root of
* the directory.
*
* @param rootGroup
* A group that should be at the root of this directory.
*/
public void init(ConnectionGroup rootGroup) {
this.rootGroup = (QuickConnectionGroup)rootGroup;
this.connectionId = new AtomicInteger();
super.setObjects(this.connections);
}
/**
* Returns the current connection identifier counter and then increments it.
*
* @return
* An int representing the next available connection
* identifier to be used when adding connections.
*/
private int getNextConnectionID() {
return connectionId.getAndIncrement();
}
@Override
public void add(Connection connection) throws GuacamoleException {
connections.put(connection.getIdentifier(), connection);
}
/**
* Taking a URI, parse the URI into a GuacamoleConfiguration object and
* then use the configuration to create a SimpleConnection object, obtain
* an identifier, and place it on the tree, returning the identifier value
* of the new connection.
*
* @param uri
* The URI to parse into a GuacamoleConfiguration, which will then be
* used to generate the SimpleConnection.
*
* @return
* The identifier of the connection created in the directory.
*
* @throws GuacamoleException
* If an error occurs adding the object to the tree.
*/
public String create(String uri) throws GuacamoleException {
// Get the next available connection identifier.
String newConnectionId = Integer.toString(getNextConnectionID());
// Get a new QCParser
QCParser parser = new QCParser(confService.getAllowedParameters(),
confService.getDeniedParameters());
// Parse the URI into a configuration
GuacamoleConfiguration config = parser.getConfiguration(uri);
// Generate a name for the configuration.
String name = parser.getName(config);
// Create a new connection and set the parent identifier.
Connection connection = new SimpleConnection(name, newConnectionId, config, true);
connection.setParentIdentifier(QuickConnectUserContext.ROOT_IDENTIFIER);
// Place the object in this directory.
add(connection);
// Add connection to the tree.
rootGroup.addConnectionIdentifier(newConnectionId);
return newConnectionId;
}
}

View File

@@ -0,0 +1,136 @@
/*
* 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.auth.quickconnect;
import com.google.inject.Inject;
import java.util.Collections;
import org.apache.guacamole.auth.quickconnect.rest.QuickConnectREST;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AbstractUserContext;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.simple.SimpleObjectPermissionSet;
import org.apache.guacamole.net.auth.simple.SimpleUser;
/**
* A simple implementation of UserContext to support this
* extension, used for storing connections the user has created
* with the QuickConnect bar in the webapp.
*/
public class QuickConnectUserContext extends AbstractUserContext {
/**
* The unique identifier of the root connection group.
*/
public static final String ROOT_IDENTIFIER = DEFAULT_ROOT_CONNECTION_GROUP;
/**
* The AuthenticationProvider that created this UserContext.
*/
@Inject
private AuthenticationProvider authProvider;
/**
* Reference to the user whose permissions dictate the configurations
* accessible within this UserContext.
*/
private User self;
/**
* The Directory with access to all connections within the root group
* associated with this UserContext.
*/
@Inject
private QuickConnectDirectory connectionDirectory;
/**
* The root connection group.
*/
private ConnectionGroup rootGroup;
/**
* Initialize a QuickConnectUserContext using the provided username.
*
* @param username
* The name of the user logging in that will be associated
* with this UserContext.
*
* @throws GuacamoleException
* If errors occur initializing the ConnectionGroup,
* ConnectionDirectory, or User.
*/
public void init(String username) throws GuacamoleException {
// Initialize the rootGroup to a QuickConnectionGroup with a
// single root identifier.
this.rootGroup = new QuickConnectionGroup(
ROOT_IDENTIFIER,
ROOT_IDENTIFIER
);
// Initialize the connection directory
this.connectionDirectory.init(this.rootGroup);
// Initialize the user to a SimpleUser with the provided username,
// no connections, and the single root group.
this.self = new SimpleUser(username) {
@Override
public ObjectPermissionSet getConnectionPermissions() throws GuacamoleException {
return new SimpleObjectPermissionSet(connectionDirectory.getIdentifiers());
}
@Override
public ObjectPermissionSet getConnectionGroupPermissions() throws GuacamoleException {
return new SimpleObjectPermissionSet(Collections.singleton(ROOT_IDENTIFIER));
}
};
}
@Override
public QuickConnectDirectory getConnectionDirectory() {
return connectionDirectory;
}
@Override
public User self() {
return self;
}
@Override
public Object getResource() throws GuacamoleException {
return new QuickConnectREST(connectionDirectory);
}
@Override
public AuthenticationProvider getAuthenticationProvider() {
return authProvider;
}
@Override
public ConnectionGroup getRootConnectionGroup() throws GuacamoleException {
return rootGroup;
}
}

View File

@@ -0,0 +1,117 @@
/*
* 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.auth.quickconnect;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.auth.AbstractConnectionGroup;
import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.protocol.GuacamoleClientInformation;
/**
* Provides a simple, single-level connection group used for
* temporarily storing the Connection objects created by users.
*/
public class QuickConnectionGroup extends AbstractConnectionGroup {
/**
* A set that will store the Connection identifiers for this group.
*/
private final Set<String> connectionIdentifiers =
new HashSet<String>(Collections.<String>emptyList());
/**
* Set up a QuickConnectionGroup with the provided name and
* identifier.
*
* @param name
* The name of the QuickConnectionGroup.
*
* @param identifier
* The identifier of the QuickConnectionGroup.
*/
public QuickConnectionGroup(String name, String identifier) {
super();
super.setName(name);
super.setIdentifier(identifier);
super.setType(ConnectionGroup.Type.ORGANIZATIONAL);
}
/**
* Add a connection identifier to this connection group, and
* return the identifier if the add succeeds, otherwise
* return null.
*
* @param identifier
* The identifier of the connection to add to the group.
*
* @return
* The String identifier of the connection if the add
* operation was successful; otherwise null.
*/
public String addConnectionIdentifier(String identifier) {
if (connectionIdentifiers.add(identifier))
return identifier;
return null;
}
@Override
public int getActiveConnections() {
// This group does not track active connections.
return 0;
}
@Override
public Set<String> getConnectionIdentifiers() {
return connectionIdentifiers;
}
@Override
public Set<String> getConnectionGroupIdentifiers() {
// This group contains only connections, not other groups.
return Collections.<String>emptySet();
}
@Override
public Map<String, String> getAttributes() {
// There are no attributes associated with this group.
return Collections.<String, String>emptyMap();
}
@Override
public void setAttributes(Map<String, String> attributes) {
// Do nothing - there are no attributes
}
@Override
public GuacamoleTunnel connect(GuacamoleClientInformation info,
Map<String, String> tokens) throws GuacamoleException {
// This group does not support connections
throw new GuacamoleSecurityException("Permission denied.");
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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.auth.quickconnect.conf;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.StringGuacamoleProperty;
/**
* Configuration options to control the QuickConnect module.
*/
public class ConfigurationService {
/**
* The environment of the Guacamole Server.
*/
@Inject
private Environment environment;
/**
* A list of parameters that, if set, will limit the parameters allowed to
* be defined by connections created using the QuickConnect module to only
* the parameters defined in this list. Defaults to null (all parameters
* are allowed).
*/
public static final StringGuacamoleProperty QUICKCONNECT_ALLOWED_PARAMETERS = new StringGuacamoleProperty() {
@Override
public String getName() { return "quickconnect-allowed-parameters"; }
};
/**
* A list of parameters that, if set, will limit the parameters allowed to
* be defined by connections created using the QuickConnect module to any
* except the ones defined in this list. Defaults to null (all parameters
* are allowed).
*/
public static final StringGuacamoleProperty QUICKCONNECT_DENIED_PARAMETERS = new StringGuacamoleProperty() {
@Override
public String getName() { return "quickconnect-denied-parameters"; }
};
/**
* Return the list of allowed parameters to be set by connections created
* using the QuickConnect module, or null if none are defined (thereby
* allowing all parameters to be set).
*
* @return
* The list of allowed parameters to be set by connections crated using
* the QuickConnect module.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public Collection<String> getAllowedParameters() throws GuacamoleException {
return environment.getPropertyCollection(QUICKCONNECT_ALLOWED_PARAMETERS);
}
/**
* Return the list of denied parameters for connections created using the
* QuickConnect module, or null if none are defined (thereby allowing all
* parameters to be set).
*
* @return
* The list of parameters that cannot be set by connections created
* using the QuickConnect module.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public Collection<String> getDeniedParameters() throws GuacamoleException {
return environment.getPropertyCollection(QUICKCONNECT_DENIED_PARAMETERS);
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.auth.quickconnect.rest;
import java.util.Collections;
import java.util.Map;
import javax.ws.rs.FormParam;
import javax.ws.rs.Path;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.quickconnect.QuickConnectDirectory;
import org.apache.guacamole.auth.quickconnect.utility.QCParser;
/**
* A class that implements REST endpoints for the QuickConnect
* extension.
*/
@Produces(MediaType.APPLICATION_JSON)
public class QuickConnectREST {
/**
* The connection directory for this REST endpoint.
*/
private final QuickConnectDirectory directory;
/**
* Construct a new QuickConnectREST class, taking in a
* QuickConnectDirectory for use with this class.
*
* @param directory
* The QuickConnectDirectory object to associate with this
* REST endpoint class.
*/
public QuickConnectREST(QuickConnectDirectory directory) {
this.directory = directory;
}
/**
* Parse the URI read from the POST input, add the connection
* to the directory, and return a Map containing a single key,
* identifier, and the identifier of the new connection.
*
* @param uri
* The URI to parse into a connection.
*
* @return
* A Map containing a single key, identifier, and the
* identifier of the new connection.
*
* @throws GuacamoleException
* If an error is encountered parsing the URI.
*/
@POST
@Path("create")
public Map<String, String> create(@FormParam("uri") String uri)
throws GuacamoleException {
return Collections.singletonMap("identifier", directory.create(uri));
}
}

View File

@@ -0,0 +1,331 @@
/*
* 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.auth.quickconnect.utility;
import java.io.UnsupportedEncodingException;
import java.lang.StringBuilder;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.language.TranslatableGuacamoleClientException;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
/**
* A utility class to parse out a URI into the settings necessary
* to generate a GuacamoleConfiguration object.
*/
public class QCParser {
/**
* The regex to use to split username and password.
*/
private static final Pattern userinfoPattern = Pattern.compile("(^[^:]+):?(.*)");
/**
* The regex group of the username.
*/
private static final int USERNAME_GROUP = 1;
/**
* THe regex group of the password.
*/
private static final int PASSWORD_GROUP = 2;
/**
* The list of parameters that are allowed to be placed into a configuration
* by this parser. If not defined, all parameters will be allowed unless
* explicitly denied.
*/
private final Collection<String> allowedParams;
/**
* The list of parameters that are explicitly denied from being placed into
* a configuration by this parser.
*/
private final Collection<String> deniedParams;
/**
* Create a new instance of the QCParser class, with the provided allowed
* and denied parameter lists, if any.
*
* @param allowedParams
* A list of parameters that are allowed to be parsed and placed into
* a connection configuration, or null or empty if all parameters are
* allowed.
*
* @param deniedParams
* A list of parameters, if any, that should be explicitly denied from
* being placed into a connection configuration.
*/
public QCParser(Collection<String> allowedParams, Collection<String> deniedParams) {
this.allowedParams = allowedParams;
this.deniedParams = deniedParams;
}
/**
* Create a new instance of the QCParser class, initializing the allowed
* and denied parameter lists to empty lists, which means all parameters
* will be allowed and none will be denied.
*/
public QCParser() {
this.allowedParams = Collections.emptyList();
this.deniedParams = Collections.emptyList();
}
/**
* Parse out a URI string and get a GuacamoleConfiguration
* from that string, or an exception if the parsing fails.
*
* @param uri
* The string form of the URI to be parsed.
*
* @return
* A GuacamoleConfiguration generated using the information
* provided by the user in the URI.
*
* @throws GuacamoleException
* If an error occurs parsing the URI.
*/
public GuacamoleConfiguration getConfiguration(String uri)
throws GuacamoleException {
// Parse the provided String into a URI object.
URI qcUri;
try {
qcUri = new URI(uri);
if (!qcUri.isAbsolute())
throw new TranslatableGuacamoleClientException("URI must be absolute.",
"QUICKCONNECT.ERROR_NOT_ABSOLUTE_URI");
}
catch (URISyntaxException e) {
throw new TranslatableGuacamoleClientException("Invalid URI Syntax",
"QUICKCONNECT.ERROR_INVALID_URI");
}
// Break out individual components of the URI.
String protocol = qcUri.getScheme();
String host = qcUri.getHost();
int port = qcUri.getPort();
String userInfo = qcUri.getUserInfo();
String query = qcUri.getQuery();
// Generate a new GuacamoleConfiguration
GuacamoleConfiguration qcConfig = new GuacamoleConfiguration();
// Check for protocol and set it, or throw an error if not present
if (protocol != null && !protocol.isEmpty())
qcConfig.setProtocol(protocol);
else
throw new TranslatableGuacamoleClientException("No protocol specified.",
"QUICKCONNECT.ERROR_NO_PROTOCOL");
// Check for provided port number
if (port > 0 && paramIsAllowed("port"))
qcConfig.setParameter("port", Integer.toString(port));
// Check for provided host, or throw an error if not present
if (host != null && !host.isEmpty() && paramIsAllowed("hostname"))
qcConfig.setParameter("hostname", host);
else
throw new TranslatableGuacamoleClientException("No host specified.",
"QUICKCONNECT.ERROR_NO_HOST");
// Look for extra query parameters and parse them out.
if (query != null && !query.isEmpty())
parseQueryString(query, qcConfig);
// Look for the username and password and parse them out.
if (userInfo != null && !userInfo.isEmpty())
parseUserInfo(userInfo, qcConfig);
return qcConfig;
}
/**
* Parse the given string for parameter key/value pairs and update the
* provided GuacamoleConfiguration object with the parsed values, checking
* to make sure that the parser is allowed to provide the requested
* parameters.
*
* @param queryStr
* The query string to parse for key/value pairs.
*
* @param config
* The GuacamoleConfiguration object that should be updated with the
* parsed parameters.
*
* @throws GuacamoleException
* If Java unexpectedly lacks UTF-8 support.
*/
private void parseQueryString(String queryStr, GuacamoleConfiguration config)
throws GuacamoleException {
// Split the query string into the pairs
List<String> paramList = Arrays.asList(queryStr.split("&"));
// Loop through key/value pairs and put them in the Map.
for (String param : paramList) {
String[] paramArray = param.split("=", 2);
try {
String paramName = URLDecoder.decode(paramArray[0], "UTF-8");
String paramValue = URLDecoder.decode(paramArray[1], "UTF-8");
if (paramIsAllowed(paramName))
config.setParameter(paramName, paramValue);
}
catch (UnsupportedEncodingException e) {
throw new GuacamoleServerException("Unexpected lack of UTF-8 encoding support.", e);
}
}
}
/**
* Parse the given string for username and password values, and, if values
* are present and allowed by the configuration, decode them and set them in
* the provided GuacamoleConfiguration object.
*
* @param userInfo
* The string to parse for username/password values.
*
* @param config
* The GuacamoleConfiguration object to store the username
* and password in.
*
* @throws GuacamoleException
* If Java unexpectedly lacks UTF-8 support.
*/
private void parseUserInfo(String userInfo,
GuacamoleConfiguration config)
throws GuacamoleException {
Matcher userinfoMatcher = userinfoPattern.matcher(userInfo);
if (userinfoMatcher.matches()) {
String username = userinfoMatcher.group(USERNAME_GROUP);
String password = userinfoMatcher.group(PASSWORD_GROUP);
if (username != null && !username.isEmpty() && paramIsAllowed("username")) {
try {
config.setParameter("username",
URLDecoder.decode(username, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
throw new GuacamoleServerException("Unexpected lack of UTF-8 encoding support.", e);
}
}
if (password != null && !password.isEmpty() && paramIsAllowed("password")) {
try {
config.setParameter("password",
URLDecoder.decode(password, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
throw new GuacamoleServerException("Unexpected lack of UTF-8 encoding support.", e);
}
}
}
}
/**
* Given a GuacamoleConfiguration object, generate a name
* for the configuration based on the protocol, host, user
* and port in the configuration, and return the string value.
*
* @param config
* The GuacamoleConfiguration object to use to generate
* the name.
*
* @return
* The String value of the name that is generated.
*
* @throws GuacamoleException
* If an error occurs getting items in the configuration.
*/
public String getName(GuacamoleConfiguration config)
throws GuacamoleException {
if (config == null)
return null;
String protocol = config.getProtocol();
String host = config.getParameter("hostname");
String port = config.getParameter("port");
String user = config.getParameter("username");
StringBuilder name = new StringBuilder();
if (protocol != null && !protocol.isEmpty())
name.append(protocol).append("://");
if (user != null && !user.isEmpty())
name.append(user).append("@");
if (host != null && !host.isEmpty())
name.append(host);
if (port != null && !port.isEmpty())
name.append(":").append(port);
name.append("/");
return name.toString();
}
/**
* For a given parameter, check to make sure the parameter is allowed to be
* used in the connection configuration, first by checking to see if
* allowed parameters are defined and the given parameter is present, then
* by checking for explicitly denied parameters. Returns false if the
* configuration prevents the parameter from being used, otherwise true.
*
* @param param
* The name of the parameter to check.
*
* @return
* False if the configuration prevents the parameter from being used,
* otherwise true.
*/
private boolean paramIsAllowed(String param) {
// If allowed parameters are defined and not empty,
// check to see if this parameter is allowed.
if (allowedParams != null && !allowedParams.isEmpty() && !allowedParams.contains(param))
return false;
// If denied parameters are defined and not empty,
// check to see if this parameter is denied.
if (deniedParams != null && !deniedParams.isEmpty() && deniedParams.contains(param))
return false;
// By default, the parameter is allowed.
return true;
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.
*/
/**
* The controller for making ad-hoc (quick) connections
*/
angular.module('guacQuickConnect').controller('quickconnectController', ['$scope', '$injector',
function manageConnectionController($scope, $injector) {
// Required types
var ClientIdentifier = $injector.get('ClientIdentifier');
// Required services
var $location = $injector.get('$location');
var guacNotification = $injector.get('guacNotification');
var quickConnectService = $injector.get('quickConnectService');
/**
* The URI that will be passed in to the extension to create
* the connection.
*/
$scope.uri = null;
/**
* Saves the connection, creating a new connection or updating the existing
* connection.
*/
$scope.quickConnect = function quickConnect() {
quickConnectService.createConnection($scope.uri)
.then(function createdConnection(connectionId) {
$location.url('/client/' + ClientIdentifier.toString({
dataSource : 'quickconnect',
type : ClientIdentifier.Types.CONNECTION,
id : connectionId
}));
}, guacNotification.SHOW_REQUEST_ERROR);
return;
};
}]);

View File

@@ -0,0 +1,40 @@
{
"guacamoleVersion" : "1.6.0",
"name" : "Adhoc Guacamole Connections",
"namespace" : "quickconnect",
"authProviders" : [
"org.apache.guacamole.auth.quickconnect.QuickConnectAuthenticationProvider"
],
"js" : [
"quickconnect.min.js"
],
"css" : [
"quickconnect.min.css"
],
"html" : [
"templates/quickconnectField.html"
],
"translations" : [
"translations/ca.json",
"translations/de.json",
"translations/en.json",
"translations/fr.json",
"translations/ja.json",
"translations/ko.json",
"translations/pl.json",
"translations/pt.json",
"translations/ru.json",
"translations/zh.json"
],
"resources" : {
"templates/quickconnectField.html" : "text/html"
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
/**
* Module which provides QuickConnect capability
*/
angular.module('guacQuickConnect', [
'form'
]);
// Ensure the guacQuickConnect module is loaded along with the rest of the app
angular.module('index').requires.push('guacQuickConnect');

View File

@@ -0,0 +1,69 @@
/*
* 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.
*/
/**
* Service for managing quickConnect extension.
*/
angular.module('guacQuickConnect').factory('quickConnectService', ['$injector',
function quickConnectService($injector) {
// Required services
var authenticationService = $injector.get('authenticationService');
var cacheService = $injector.get('cacheService');
var requestService = $injector.get('requestService');
var service = {};
/**
* Makes a request to the REST API to create a connection, returning a
* promise that can be used for processing the results of the call.
*
* @param {uri} The URI of the connection to create.
*
* @returns {Promise}
* A promise for the HTTP call which will succeed if and only if the
* save operation is successful.
*/
service.createConnection = function createConnection(uri) {
// Build HTTP parameters set
var httpParameters = {
token : authenticationService.getCurrentToken()
};
return requestService({
method : 'POST',
url : 'api/session/ext/quickconnect/create',
params : httpParameters,
data : $.param({uri: uri}),
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(function connectionCreated(connectionId) {
// Clear connections and users from cache.
cacheService.connections.removeAll();
cacheService.users.removeAll();
// Pass on the connection identifier
return connectionId.identifier;
});
};
return service;
}]);

View File

@@ -0,0 +1,53 @@
/*
* 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.
*/
.quickconnect-container {
margin: 0.25em 0;
width: 100%;
margin-left: 0.50em;
}
.quickconnect-container .quickconnect-field {
background-image: url('images/protocol-icons/guac-text.png');
background-repeat: no-repeat;
background-size: 1.50em;
background-position: 0.25em center;
background-color: transparent;
padding: 0.25em;
padding-left: 2.50em;
width: 100%;
max-width: none;
border: 0;
box-sizing: border-box;
}
.quickconnect-button {
clear: both;
float: right;
margin-right: 0.75em;
font-size: 0.75em;
padding: 0.25em;
}
.quickconnect-list-item {
vertical-align: middle;
align-content: center;
display: flex
}

View File

@@ -0,0 +1,11 @@
<meta name="before" content=".all-connections">
<div class="quickconnect-list-item list-item" ng-controller="quickconnectController">
<div class="quickconnect-container">
<form ng-submit="quickConnect()">
<input type=text class="quickconnect-field" placeholder="{{'QUICKCONNECT.FIELD_PLACEHOLDER_URI' |translate}}" ng-model="uri">
</form>
</div>
<div class="action-buttons">
<button class="quickconnect-button" ng-click="quickConnect()">{{'QUICKCONNECT.ACTION_CONNECT' | translate}}</button>
</div>
</div>

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Connectat",
"ERROR_INVALID_URI" : "Especificació URI no vàlida",
"ERROR_NO_HOST" : "No s'ha especificat l'amfitrió",
"ERROR_NO_PROTOCOL" : "No s'ha especificat protocol",
"ERROR_NOT_ABSOLUTE_URI" : "L'URI no és absolut",
"FIELD_PLACEHOLDER_URI" : "Introduïu l'URI de connexió"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Verbinden",
"ERROR_INVALID_URI" : "Ungültige URI angegeben",
"ERROR_NO_HOST" : "Keinen Host angegeben",
"ERROR_NO_PROTOCOL" : "Kein Protokoll angegeben",
"ERROR_NOT_ABSOLUTE_URI" : "URI ist nicht absolut",
"FIELD_PLACEHOLDER_URI" : "URI der Verbindung eingeben"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Connect",
"ERROR_INVALID_URI" : "Invalid URI Specified",
"ERROR_NO_HOST" : "No host specified",
"ERROR_NO_PROTOCOL" : "No protocol specified",
"ERROR_NOT_ABSOLUTE_URI" : "URI is not absolute",
"FIELD_PLACEHOLDER_URI" : "Enter Connection URI"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Connecter",
"ERROR_INVALID_URI" : "L'URI spécifiée est invalide",
"ERROR_NO_HOST" : "Pas d'hôte spécifié",
"ERROR_NO_PROTOCOL" : "Pas de protocole spécifié",
"ERROR_NOT_ABSOLUTE_URI" : "L'URI n'est pas absolue",
"FIELD_PLACEHOLDER_URI" : "Entrez l'URI de connexion"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Collegare",
"ERROR_INVALID_URI" : "URI specificato non valido",
"ERROR_NO_HOST" : "Nessun host specificato",
"ERROR_NO_PROTOCOL" : "Nessun protocollo specificato",
"ERROR_NOT_ABSOLUTE_URI" : "L'URI non è assoluto",
"FIELD_PLACEHOLDER_URI" : "Immettere l'URI di connessione"
}
}

View File

@@ -0,0 +1,14 @@
{
"QUICKCONNECT" : {
"ACTION_CONNECT" : "接続",
"ERROR_INVALID_URI" : "URIが無効です",
"ERROR_NO_HOST" : "ホストが指定されていません",
"ERROR_NO_PROTOCOL" : "プロトコルが指定されていません",
"ERROR_NOT_ABSOLUTE_URI" : "絶対URIで指定してください",
"FIELD_PLACEHOLDER_URI" : "接続するURIを入力"
}
}

View File

@@ -0,0 +1,13 @@
{
"QUICKCONNECT" : {
"ACTION_CONNECT" : "연결",
"ERROR_INVALID_URI" : "잘못된 URI 지정",
"ERROR_NO_HOST" : "지정된 호스트 없음",
"ERROR_NO_PROTOCOL" : "지정된 프로토콜 없음",
"ERROR_NOT_ABSOLUTE_URI" : "URL이 절대 경로가 아님",
"FIELD_PLACEHOLDER_URI" : "연결 URI 입력"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Połącz",
"ERROR_INVALID_URI" : "Podano nieprawidłowy URI",
"ERROR_NO_HOST" : "Nie podano hosta",
"ERROR_NO_PROTOCOL" : "Nie podano protokołu",
"ERROR_NOT_ABSOLUTE_URI" : "Adres URI nie jest absolutny",
"FIELD_PLACEHOLDER_URI" : "Podaj URI Połączenia"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Conectar",
"ERROR_INVALID_URI" : "URI especificada é inválida",
"ERROR_NO_HOST" : "Nenhum host especificado",
"ERROR_NO_PROTOCOL" : "Nenhum protocol especificado",
"ERROR_NOT_ABSOLUTE_URI" : "URI não é absoluta",
"FIELD_PLACEHOLDER_URI" : "Digite a conexão URI"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "QuickConnect"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "Подключиться",
"ERROR_INVALID_URI" : "Указан неверный адрес URI",
"ERROR_NO_HOST" : "Не указан сервер",
"ERROR_NO_PROTOCOL" : "Не указан протокол",
"ERROR_NOT_ABSOLUTE_URI" : "Адрес URI не является абсолютным",
"FIELD_PLACEHOLDER_URI" : "Введите адрес URI для подключения"
}
}

View File

@@ -0,0 +1,18 @@
{
"DATA_SOURCE_QUICKCONNECT" : {
"NAME" : "快速连接"
},
"QUICKCONNECT" : {
"ACTION_CONNECT" : "连接",
"ERROR_INVALID_URI" : "指定的URI无效",
"ERROR_NO_HOST" : "未指定主机",
"ERROR_NO_PROTOCOL" : "未指定协议",
"ERROR_NOT_ABSOLUTE_URI" : "不是绝对URI地址",
"FIELD_PLACEHOLDER_URI" : "输入连接URI"
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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.auth.quickconnect.utility;
import java.util.Arrays;
import java.util.Collections;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
* Class to test methods in the QCParser utility class.
*/
public class QCParserTest {
/**
* Verify that the getConfiguration() method returns the expected
* GuacamoleConfiguration object.
*
* @throws GuacamoleException
* If the configuration cannot be parsed from the given URI or Java
* unexpectedly lacks UTF-8 support.
*/
@Test
public void testGetConfiguration() throws GuacamoleException {
// Initialize the parser, first with no lists so all parameters are allowed
QCParser parser = new QCParser();
// Create some empty objects to test
GuacamoleConfiguration guacConfig;
String uri;
// Test a standard SSH URI, with username and password, and parameters and values
uri = "ssh://guacuser:guacpassword@hostname1.domain.local/?param1=value1&param2=value2";
guacConfig = parser.getConfiguration(uri);
assertEquals("ssh", guacConfig.getProtocol());
assertEquals("hostname1.domain.local", guacConfig.getParameter("hostname"));
assertEquals("guacuser", guacConfig.getParameter("username"));
assertEquals("guacpassword", guacConfig.getParameter("password"));
assertEquals("value1", guacConfig.getParameter("param1"));
assertEquals("value2", guacConfig.getParameter("param2"));
// Test a standard RDP URI, with username/password and a parameter/value pair.
uri = "rdp://domain%5cguacuser:adPassword123@windows1.domain.tld/?enable-sftp=true";
guacConfig = parser.getConfiguration(uri);
assertEquals("rdp", guacConfig.getProtocol());
assertEquals("windows1.domain.tld", guacConfig.getParameter("hostname"));
assertEquals("domain\\guacuser", guacConfig.getParameter("username"));
assertEquals("adPassword123", guacConfig.getParameter("password"));
assertEquals("true", guacConfig.getParameter("enable-sftp"));
// Test a VNC URI with no parameters/values
uri = "vnc://mirror1.example.com:5910/";
guacConfig = parser.getConfiguration(uri);
assertEquals("vnc", guacConfig.getProtocol());
assertEquals("mirror1.example.com", guacConfig.getParameter("hostname"));
assertEquals("5910", guacConfig.getParameter("port"));
// Test a telnet URI with no parameters/values
uri = "telnet://old1.example.com:23/";
guacConfig = parser.getConfiguration(uri);
assertEquals("telnet", guacConfig.getProtocol());
assertEquals("old1.example.com", guacConfig.getParameter("hostname"));
assertEquals("23", guacConfig.getParameter("port"));
// Re-initialize parser with only allowed parameters, and test
parser = new QCParser(Arrays.asList("hostname", "username", "password", "port"), Collections.emptyList());
uri = "rdp://domain%5cguacuser:adPassword123@windows1.domain.tld/?enable-sftp=true";
guacConfig = parser.getConfiguration(uri);
assertEquals("rdp", guacConfig.getProtocol());
assertEquals("windows1.domain.tld", guacConfig.getParameter("hostname"));
assertEquals("domain\\guacuser", guacConfig.getParameter("username"));
assertEquals("adPassword123", guacConfig.getParameter("password"));
assertNull(guacConfig.getParameter("enable-sftp"));
// Re-initialize parser with denied parameters, and test
parser = new QCParser(Collections.emptyList(), Arrays.asList("password"));
uri = "rdp://domain%5cguacuser:adPassword123@windows1.domain.tld/?enable-sftp=true";
guacConfig = parser.getConfiguration(uri);
assertEquals("rdp", guacConfig.getProtocol());
assertEquals("windows1.domain.tld", guacConfig.getParameter("hostname"));
assertEquals("domain\\guacuser", guacConfig.getParameter("username"));
assertNull(guacConfig.getParameter("password"));
assertEquals("true", guacConfig.getParameter("enable-sftp"));
// Re-initialize parser with both allowed and denied parameters, and test
parser = new QCParser(Arrays.asList("hostname", "username", "password", "port"), Arrays.asList("password"));
uri = "rdp://domain%5cguacuser:adPassword123@windows1.domain.tld/?enable-sftp=true";
guacConfig = parser.getConfiguration(uri);
assertEquals("rdp", guacConfig.getProtocol());
assertEquals("windows1.domain.tld", guacConfig.getParameter("hostname"));
assertEquals("domain\\guacuser", guacConfig.getParameter("username"));
assertNull(guacConfig.getParameter("password"));
assertNull(guacConfig.getParameter("enable-sftp"));
}
}