mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-641: Provide strict filtering mode for TokenFilter which disallows undefined tokens.
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.token;
|
||||
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
|
||||
/**
|
||||
* An exception thrown when a token cannot be substituted because it has no
|
||||
* corresponding value. Additional information describing the undefined token
|
||||
* is provided.
|
||||
*/
|
||||
public class GuacamoleTokenUndefinedException extends GuacamoleServerException {
|
||||
|
||||
/**
|
||||
* The name of the token that is undefined.
|
||||
*/
|
||||
private final String tokenName;
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleTokenUndefinedException with the given message,
|
||||
* cause, and associated undefined token name.
|
||||
*
|
||||
* @param message
|
||||
* A human readable description of the exception that occurred.
|
||||
*
|
||||
* @param cause
|
||||
* The cause of this exception.
|
||||
*
|
||||
* @param tokenName
|
||||
* The name of the token which has no defined value.
|
||||
*/
|
||||
public GuacamoleTokenUndefinedException(String message, Throwable cause,
|
||||
String tokenName) {
|
||||
super(message, cause);
|
||||
this.tokenName = tokenName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleTokenUndefinedException with the given
|
||||
* message and associated undefined token name.
|
||||
*
|
||||
* @param message
|
||||
* A human readable description of the exception that occurred.
|
||||
*
|
||||
* @param tokenName
|
||||
* The name of the token which has no defined value.
|
||||
*/
|
||||
public GuacamoleTokenUndefinedException(String message, String tokenName) {
|
||||
super(message);
|
||||
this.tokenName = tokenName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleTokenUndefinedException with the given cause
|
||||
* and associated undefined token name.
|
||||
*
|
||||
* @param cause
|
||||
* The cause of this exception.
|
||||
*
|
||||
* @param tokenName
|
||||
* The name of the token which has no defined value.
|
||||
*/
|
||||
public GuacamoleTokenUndefinedException(Throwable cause, String tokenName) {
|
||||
super(cause);
|
||||
this.tokenName = tokenName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the token which has no defined value, causing this
|
||||
* exception to be thrown.
|
||||
*
|
||||
* @return
|
||||
* The name of the token which has no defined value.
|
||||
*/
|
||||
public String getTokenName() {
|
||||
return tokenName;
|
||||
}
|
||||
|
||||
}
|
@@ -162,19 +162,31 @@ public class TokenFilter {
|
||||
tokenValues.clear();
|
||||
tokenValues.putAll(tokens);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the given string, replacing any tokens with their corresponding
|
||||
* values.
|
||||
* values. Handling of undefined tokens depends on the value given for the
|
||||
* strict flag.
|
||||
*
|
||||
* @param input
|
||||
* The string to filter.
|
||||
*
|
||||
* @param strict
|
||||
* Whether to disallow tokens which lack values from existing in the
|
||||
* string. If true, an exception will be thrown if any tokens in the
|
||||
* string lack corresponding values. If false, tokens which lack values
|
||||
* will be interpreted as literals.
|
||||
*
|
||||
* @return
|
||||
* A copy of the input string, with any tokens replaced with their
|
||||
* corresponding values.
|
||||
*
|
||||
* @throws GuacamoleTokenUndefinedException
|
||||
* If the strict flag is set to true and at least one token in the
|
||||
* given string has no corresponding value.
|
||||
*/
|
||||
public String filter(String input) {
|
||||
private String filter(String input, boolean strict)
|
||||
throws GuacamoleTokenUndefinedException {
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
Matcher tokenMatcher = tokenPattern.matcher(input);
|
||||
@@ -209,10 +221,20 @@ public class TokenFilter {
|
||||
String tokenName = tokenMatcher.group(TOKEN_NAME_GROUP);
|
||||
String tokenValue = getToken(tokenName);
|
||||
|
||||
// If token is unknown, interpret as literal
|
||||
// If token is unknown, interpretation depends on whether
|
||||
// strict mode is enabled
|
||||
if (tokenValue == null) {
|
||||
|
||||
// Fail outright if strict mode is enabled
|
||||
if (strict)
|
||||
throw new GuacamoleTokenUndefinedException("Token "
|
||||
+ "has no defined value.", tokenName);
|
||||
|
||||
// If strict mode is NOT enabled, simply interpret as
|
||||
// a literal
|
||||
String notToken = tokenMatcher.group(TOKEN_GROUP);
|
||||
output.append(notToken);
|
||||
|
||||
}
|
||||
|
||||
// Otherwise, check for modifiers and substitute value appropriately
|
||||
@@ -247,19 +269,71 @@ public class TokenFilter {
|
||||
|
||||
// Update last regex match
|
||||
endOfLastMatch = tokenMatcher.end();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Append any remaining non-token text
|
||||
output.append(input.substring(endOfLastMatch));
|
||||
|
||||
|
||||
return output.toString();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the given string, replacing any tokens with their corresponding
|
||||
* values. Any tokens present in the given string which lack values will
|
||||
* be interpreted as literals.
|
||||
*
|
||||
* @param input
|
||||
* The string to filter.
|
||||
*
|
||||
* @return
|
||||
* A copy of the input string, with any tokens replaced with their
|
||||
* corresponding values.
|
||||
*/
|
||||
public String filter(String input) {
|
||||
|
||||
// Filter with strict mode disabled (should always succeed)
|
||||
try {
|
||||
return filter(input, false);
|
||||
}
|
||||
|
||||
// GuacamoleTokenUndefinedException cannot be thrown when strict mode
|
||||
// is disabled
|
||||
catch (GuacamoleTokenUndefinedException e) {
|
||||
throw new IllegalStateException("filter() threw "
|
||||
+ "GuacamoleTokenUndefinedException despite strict mode "
|
||||
+ "being disabled.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the given string, replacing any tokens with their corresponding
|
||||
* values. If any token in the given string has no defined value within
|
||||
* this TokenFilter, a GuacamoleTokenUndefinedException will be thrown.
|
||||
*
|
||||
* @param input
|
||||
* The string to filter.
|
||||
*
|
||||
* @return
|
||||
* A copy of the input string, with any tokens replaced with their
|
||||
* corresponding values.
|
||||
*
|
||||
* @throws GuacamoleTokenUndefinedException
|
||||
* If at least one token in the given string has no corresponding
|
||||
* value.
|
||||
*/
|
||||
public String filterStrict(String input)
|
||||
throws GuacamoleTokenUndefinedException {
|
||||
return filter(input, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an arbitrary map containing String values, replace each non-null
|
||||
* value with the corresponding filtered value.
|
||||
* value with the corresponding filtered value. Any tokens present in the
|
||||
* values of the given map which lack defined values within this
|
||||
* TokenFilter will be interpreted as literals.
|
||||
*
|
||||
* @param map
|
||||
* The map whose values should be filtered.
|
||||
@@ -273,6 +347,34 @@ public class TokenFilter {
|
||||
String value = entry.getValue();
|
||||
if (value != null)
|
||||
entry.setValue(filter(value));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an arbitrary map containing String values, replace each non-null
|
||||
* value with the corresponding filtered value. If any token in any string
|
||||
* has no defined value within this TokenFilter, a
|
||||
* GuacamoleTokenUndefinedException will be thrown.
|
||||
*
|
||||
* @param map
|
||||
* The map whose values should be filtered.
|
||||
*
|
||||
* @throws GuacamoleTokenUndefinedException
|
||||
* If at least one token in at least one string has no corresponding
|
||||
* value.
|
||||
*/
|
||||
public void filterValuesStrict(Map<?, String> map)
|
||||
throws GuacamoleTokenUndefinedException {
|
||||
|
||||
// For each map entry
|
||||
for (Map.Entry<?, String> entry : map.entrySet()) {
|
||||
|
||||
// If value is non-null, filter value through this TokenFilter
|
||||
String value = entry.getValue();
|
||||
if (value != null)
|
||||
entry.setValue(filterStrict(value));
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user