Skip to content
Snippets Groups Projects
Commit a9ec1449 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Handled special characters and illegal characters on node paths

parent 5a20bd0a
No related branches found
No related tags found
No related merge requests found
Pipeline #1009 passed
package it.inaf.oats.vospace.datamodel;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import net.ivoa.xml.vospace.v2.Node;
public class NodeUtils {
/**
* Forbidden path chars are non printable characters and some symbols that
* could create issues to scripts that manipulates files. Other UTF-8
* characters are allowed. Front end needs to pay attention to other allowed
* characters like & and parenthesis in any case, also to avoid XSS attacks.
*/
private static final Pattern FORBIDDEN_CHARS = Pattern.compile("[\\x00\\x08\\x0B\\x0C\\x0E-\\x1F" + Pattern.quote("<>?\":\\|'*") + "]");
/**
* Slash is a special character in defining REST endpoints and trying to
* define a PathVariable containing slashes doesn't work, so the endpoint
* has been defined using "/nodes/**" instead of "/nodes/{path}" and the
* path is extracted manually parsing the request URL.
* path is extracted manually parsing the request URL. Proper URL encoding
* handling is needed, considering also that slashes mustn't be escaped.
*/
public static String getPathFromRequestURLString(String requestUrlString) {
return getPathFromRequestURLString(requestUrlString, "/nodes/");
}
String[] split = requestUrlString.split("/nodes/");
public static String getPathFromRequestURLString(String requestUrlString, String prefix) {
String[] split = requestUrlString.split(prefix);
String path = "/";
if (split.length == 2) {
path += split[1];
String[] parts = split[1].split("/");
path += String.join("/", Arrays.stream(parts)
.map(p -> {
String decoded = URLDecoder.decode(p, StandardCharsets.UTF_8);
if (FORBIDDEN_CHARS.matcher(decoded).find()) {
throw new IllegalArgumentException("Path segment " + decoded + " contains an illegal character");
}
return decoded;
})
.collect(Collectors.toList()));
}
return path;
}
public static String urlEncodePath(String path) {
String[] parts = path.split("/");
return String.join("/", Arrays.stream(parts)
.map(p -> URLEncoder.encode(p, StandardCharsets.UTF_8))
.collect(Collectors.toList()));
}
// This method assumes that URL is in the format /node1/node2/...
// multiple slashes as a single separator are allowed
// But the output has only single slash separators
......
package it.inaf.oats.vospace.datamodel;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
public class NodeUtilsTest {
@Test
public void testGetPathFromRequestURLString() {
String requestUrl = "http://localhost/vospace/nodes/a/b/c/";
assertEquals("/a/b/c", NodeUtils.getPathFromRequestURLString(requestUrl));
}
@Test
public void testGetPathWithSpacesFromRequestURLString() {
String requestUrl = "http://localhost/vospace/nodes/a/b/c%20d%20%C3%A4.pdf";
assertEquals("/a/b/c d ä.pdf", NodeUtils.getPathFromRequestURLString(requestUrl));
}
@Test
public void testEncodePathSpecialChars() {
String specialChars = "ä è#+ /other/+-ò@";
assertEquals("%C3%A4+%C3%A8%23%2B+/other/%2B-%C3%B2%40", NodeUtils.urlEncodePath(specialChars));
}
@Test
public void testIllegalBrakets() {
testIllegalChars("<no>.pdf");
}
@Test
public void testIllegalQuestionMark() {
testIllegalChars("???.pdf");
}
@Test
public void testIllegalQuotes() {
testIllegalChars("\"'.pdf");
}
private void testIllegalChars(String illegalString) {
boolean exception = false;
try {
NodeUtils.getPathFromRequestURLString("http://localhost/vospace/nodes/path/to/" + illegalString);
} catch (IllegalArgumentException ex) {
exception = true;
}
assertTrue(exception);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment