diff --git a/jetty-core/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java b/jetty-core/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java index 9e6b6d71d887..4efdd1e0f822 100644 --- a/jetty-core/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java +++ b/jetty-core/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java @@ -36,7 +36,6 @@ import org.eclipse.jetty.util.FileID; import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.component.Environment; @@ -481,7 +480,7 @@ protected void initializeContextPath(ContextHandler context, Path path) // special case of archive (or dir) named "root" is / context if (contextPath.equalsIgnoreCase("root")) { - contextPath = URIUtil.SLASH; + contextPath = "/"; } // handle root with virtual host form else if (StringUtil.startsWithIgnoreCase(contextPath, "root-")) @@ -489,7 +488,7 @@ else if (StringUtil.startsWithIgnoreCase(contextPath, "root-")) int dash = contextPath.indexOf('-'); String virtual = contextPath.substring(dash + 1); context.setVirtualHosts(Arrays.asList(virtual.split(","))); - contextPath = URIUtil.SLASH; + contextPath = "/"; } // Ensure "/" is Prepended to all context paths. diff --git a/jetty-core/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/MockAppProvider.java b/jetty-core/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/MockAppProvider.java index 989cc15ac908..bd76e5f24361 100644 --- a/jetty-core/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/MockAppProvider.java +++ b/jetty-core/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/MockAppProvider.java @@ -18,7 +18,6 @@ import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.FileID; -import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.Environment; @@ -71,7 +70,7 @@ public ContextHandler createContextHandler(App app) // special case of archive (or dir) named "root" is / context if (path.equalsIgnoreCase("root") || path.equalsIgnoreCase("root/")) - path = URIUtil.SLASH; + path = "/"; // Ensure "/" is Prepended to all context paths. if (path.charAt(0) != '/') diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java index e50f077e2a44..7eafc547ac30 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java @@ -177,15 +177,15 @@ public static String relativePath(String base, if (info.startsWith("./")) info = info.substring(2); - if (base.endsWith(URIUtil.SLASH)) - if (info.startsWith(URIUtil.SLASH)) + if (base.endsWith("/")) + if (info.startsWith("/")) path = base + info.substring(1); else path = base + info; - else if (info.startsWith(URIUtil.SLASH)) + else if (info.startsWith("/")) path = base + info; else - path = base + URIUtil.SLASH + info; + path = base + "/" + info; return path; } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceListing.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceListing.java index 3e61300f3183..993177e37527 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceListing.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceListing.java @@ -225,7 +225,7 @@ public static String getAsXHTML(Resource resource, String base, boolean parent, // Ensure name has a slash if it's a directory if (item.isDirectory() && !name.endsWith("/")) - name += URIUtil.SLASH; + name += "/"; // Name buf.append(" reqRanges = request.getHeaders().getValuesList(HttpHeader.RANGE.asString()); - boolean endsWithSlash = pathInContext.endsWith(URIUtil.SLASH); + boolean endsWithSlash = pathInContext.endsWith("/"); boolean checkPrecompressedVariants = _precompressedFormats.size() > 0 && !endsWithSlash && reqRanges.isEmpty(); try @@ -552,7 +552,7 @@ private void sendDirectory(Request request, Response response, HttpContent httpC return; } - String base = URIUtil.addEncodedPaths(request.getHttpURI().getPath(), URIUtil.SLASH); + String base = URIUtil.addEncodedPaths(request.getHttpURI().getPath(), "/"); String listing = ResourceListing.getAsXHTML(httpContent.getResource(), base, pathInContext.length() > 1, request.getHttpURI().getQuery()); if (listing == null) { diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index ce4540d0aa60..be9e28f6a2fc 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -18,7 +18,6 @@ import java.net.URI; import java.net.URL; import java.net.URLClassLoader; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -55,17 +54,10 @@ public final class URIUtil .with("jar:") .build(); - public static final String SLASH = "/"; - public static final String HTTP = "http"; - public static final String HTTPS = "https"; - - // Use UTF-8 as per http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars - public static final Charset __CHARSET = StandardCharsets.UTF_8; - /** * The characters that are supported by the URI class and that can be decoded by {@link #canonicalPath(String)} */ - public static final boolean[] __uriSupportedCharacters = new boolean[] + private static final boolean[] URI_SUPPORTED_CHARACTERS = new boolean[] { false, // 0x00 is illegal false, // 0x01 is illegal @@ -197,242 +189,102 @@ public final class URIUtil false, // 0x7f DEL is illegal }; + private static final boolean[] ENCODE_PATH_NEEDS_ENCODING; + private URIUtil() { } + static + { + ENCODE_PATH_NEEDS_ENCODING = new boolean[128]; + // Special characters + for (char c: "%?;#\"'<> [\\]^`{|}".toCharArray()) + ENCODE_PATH_NEEDS_ENCODING[c] = true; + // control characters + ENCODE_PATH_NEEDS_ENCODING[0x7f] = true; + for (int i = 0; i < 0x20; i++) + ENCODE_PATH_NEEDS_ENCODING[i] = true; + } + /** * Encode a URI path. * This is the same encoding offered by URLEncoder, except that - * the '/' character is not encoded. + * the '{@code /}' character is not encoded. * - * @param path The path the encode + * @param path The path to encode * @return The encoded path */ public static String encodePath(String path) { - if (path == null || path.length() == 0) + if (StringUtil.isEmpty(path)) return path; - StringBuilder buf = encodePath(null, path, 0); - return buf == null ? path : buf.toString(); - } - - /** - * Encode a URI path. - * - * @param path The path the encode - * @param buf StringBuilder to encode path into (or null) - * @return The StringBuilder or null if no substitutions required. - */ - public static StringBuilder encodePath(StringBuilder buf, String path) - { - return encodePath(buf, path, 0); - } - - /** - * Encode a URI path. - * - * @param path The path the encode - * @param buf StringBuilder to encode path into (or null) - * @return The StringBuilder or null if no substitutions required. - */ - private static StringBuilder encodePath(StringBuilder buf, String path, int offset) - { - byte[] bytes = null; - if (buf == null) + // byte encoding always wins and, if encountered, should be used. + boolean needsByteEncoding = false; + // string (char-by-char) encoding, but it could be followed by a need for byte encoding instead + boolean needsEncoding = false; + int length = path.length(); + for (int i = 0; i < length; i++) { - loop: - for (int i = offset; i < path.length(); i++) + char c = path.charAt(i); + if (c > 0x7F) // 8-bit + { - char c = path.charAt(i); - switch (c) - { - case '%': - case '?': - case ';': - case '#': - case '"': - case '\'': - case '<': - case '>': - case ' ': - case '[': - case '\\': - case ']': - case '^': - case '`': - case '{': - case '|': - case '}': - buf = new StringBuilder(path.length() * 2); - break loop; - default: - if (c < 0x20 || c >= 0x7f) - { - bytes = path.getBytes(URIUtil.__CHARSET); - buf = new StringBuilder(path.length() * 2); - break loop; - } - } + needsByteEncoding = true; + break; // have to encode byte by byte now + } + if (ENCODE_PATH_NEEDS_ENCODING[c]) + { + // could be followed by a byte encoding, so no break + needsEncoding = true; } - if (buf == null) - return null; } - int i; + if (needsByteEncoding) + return encodePathBytes(path); + else if (needsEncoding) + return encodePathString(path); + else + return path; + } - loop: - for (i = offset; i < path.length(); i++) + private static String encodePathString(String path) + { + StringBuilder buf = new StringBuilder(path.length() * 2); + int length = path.length(); + for (int i = 0; i < length; i++) { char c = path.charAt(i); - switch (c) + if (ENCODE_PATH_NEEDS_ENCODING[c]) { - case '%': - buf.append("%25"); - continue; - case '?': - buf.append("%3F"); - continue; - case ';': - buf.append("%3B"); - continue; - case '#': - buf.append("%23"); - continue; - case '"': - buf.append("%22"); - continue; - case '\'': - buf.append("%27"); - continue; - case '<': - buf.append("%3C"); - continue; - case '>': - buf.append("%3E"); - continue; - case ' ': - buf.append("%20"); - continue; - case '[': - buf.append("%5B"); - continue; - case '\\': - buf.append("%5C"); - continue; - case ']': - buf.append("%5D"); - continue; - case '^': - buf.append("%5E"); - continue; - case '`': - buf.append("%60"); - continue; - case '{': - buf.append("%7B"); - continue; - case '|': - buf.append("%7C"); - continue; - case '}': - buf.append("%7D"); - continue; - - default: - if (c < 0x20 || c >= 0x7f) - { - bytes = path.getBytes(URIUtil.__CHARSET); - break loop; - } - buf.append(c); + buf.append('%'); + TypeUtil.toHex((byte)c, buf); } - } - - if (bytes != null) - { - for (; i < bytes.length; i++) + else { - byte c = bytes[i]; - switch (c) - { - case '%': - buf.append("%25"); - continue; - case '?': - buf.append("%3F"); - continue; - case ';': - buf.append("%3B"); - continue; - case '#': - buf.append("%23"); - continue; - case '"': - buf.append("%22"); - continue; - case '\'': - buf.append("%27"); - continue; - case '<': - buf.append("%3C"); - continue; - case '>': - buf.append("%3E"); - continue; - case ' ': - buf.append("%20"); - continue; - case '[': - buf.append("%5B"); - continue; - case '\\': - buf.append("%5C"); - continue; - case ']': - buf.append("%5D"); - continue; - case '^': - buf.append("%5E"); - continue; - case '`': - buf.append("%60"); - continue; - case '{': - buf.append("%7B"); - continue; - case '|': - buf.append("%7C"); - continue; - case '}': - buf.append("%7D"); - continue; - default: - if (c < 0x20 || c >= 0x7f) - { - buf.append('%'); - TypeUtil.toHex(c, buf); - } - else - buf.append((char)c); - } + buf.append(c); } } - - return buf; + return buf.toString(); } - /** - * Encode a raw URI String and convert any raw spaces to - * their "%20" equivalent. - * - * @param str input raw string - * @return output with spaces converted to "%20" - */ - public static String encodeSpaces(String str) + private static String encodePathBytes(String path) { - return StringUtil.replace(str, " ", "%20"); + StringBuilder buf = new StringBuilder(path.length() * 2); + byte[] pathBytes = path.getBytes(StandardCharsets.UTF_8); + for (byte b : pathBytes) + { + if (b < 0 || ENCODE_PATH_NEEDS_ENCODING[b]) + { + buf.append('%'); + TypeUtil.toHex(b, buf); + } + else + { + buf.append((char)b); + } + } + return buf.toString(); } /** @@ -483,7 +335,7 @@ public static String encodeSpecific(String str, String charsToEncode) * Decode a raw String and convert any specific URI encoded sequences into characters. * * @param str input raw string - * @param charsToDecode the list of raw characters that need to be decoded (if encountered), leaving all other encoded sequences alone. + * @param charsToDecode the list of raw characters that need to be decoded (if encountered), leaving all the other encoded sequences alone. * @return output with specified characters decoded. */ @SuppressWarnings("Duplicates") @@ -510,41 +362,40 @@ public static String decodeSpecific(String str, String charsToDecode) for (int i = idx; i < len; i++) { char c = str.charAt(i); - switch (c) + if (c == '%') { - case '%': - if ((i + 2) < len) + if ((i + 2) < len) + { + char u = str.charAt(i + 1); + char l = str.charAt(i + 2); + char result = (char)(0xff & (TypeUtil.convertHexDigit(u) * 16 + TypeUtil.convertHexDigit(l))); + boolean decoded = false; + for (char f : find) { - char u = str.charAt(i + 1); - char l = str.charAt(i + 2); - char result = (char)(0xff & (TypeUtil.convertHexDigit(u) * 16 + TypeUtil.convertHexDigit(l))); - boolean decoded = false; - for (char f : find) - { - if (f == result) - { - ret.append(result); - decoded = true; - break; - } - } - if (decoded) + if (f == result) { - i += 2; - } - else - { - ret.append(c); + ret.append(result); + decoded = true; + break; } } + if (decoded) + { + i += 2; + } else { - throw new IllegalArgumentException("Bad URI % encoding"); + ret.append(c); } - break; - default: - ret.append(c); - break; + } + else + { + throw new IllegalArgumentException("Bad URI % encoding"); + } + } + else + { + ret.append(c); } } return ret.toString(); @@ -553,11 +404,12 @@ public static String decodeSpecific(String str, String charsToDecode) /** * Encode a URI path. * - * @param path The path the encode + * @param path The path to encode * @param buf StringBuilder to encode path into (or null) - * @param encode String of characters to encode. % is always encoded. + * @param encode String of characters to encode. '{@code %}' is always encoded. * @return The StringBuilder or null if no substitutions required. */ + // TODO: remove, only used in URIUtilTest? public static StringBuilder encodeString(StringBuilder buf, String path, String encode) @@ -730,7 +582,7 @@ private static boolean isSafe(int code) { // Allow any 8-bit character (as it's likely unicode). // or any character labeled with true in __uriSupportedCharacters static - return (code >= __uriSupportedCharacters.length || __uriSupportedCharacters[code]); + return (code >= URI_SUPPORTED_CHARACTERS.length || URI_SUPPORTED_CHARACTERS[code]); } /** @@ -784,11 +636,11 @@ private static void appendHexValue(Utf8StringBuilder builder, byte value) *

* Decode only the safe characters in a URI path and strip parameters of UTF-8 path. * Safe characters are ones that are not special delimiters and that can be passed to the JVM {@link URI} class. - * Unsafe characters, other than '/' will be encoded. Encodings will be uppercase hex. + * Unsafe characters, other than '{@code /}' will be encoded. Encodings will be uppercase hex. * Canonical paths are also normalized and may be used in string comparisons with other canonical paths. *

- * For example the path /fo %2fo/b%61r will be normalized to /fo%20%2Fo/bar, - * whilst {@link #decodePath(String)} would result in the ambiguous and URI illegal /fo /o/bar. + * For example the path {@code /fo %2fo/b%61r} will be normalized to {@code /fo%20%2Fo/bar}, + * whilst {@link #decodePath(String)} would result in the ambiguous and URI illegal {@code /fo /o/bar}. * @return the canonical path or null if it is non-normal * @see #decodePath(String) * @see #normalizePath(String) @@ -917,7 +769,8 @@ public static String canonicalPath(String path) } } - /* Decode a URI path and strip parameters of ISO-8859-1 path + /** + * Decode a URI path and strip parameters of ISO-8859-1 path */ private static String decodeISO88591Path(String path, int offset, int length) { @@ -989,7 +842,7 @@ private static String decodeISO88591Path(String path, int offset, int length) /** * Add two encoded URI path segments. * Handles null and empty paths, path and query params - * (eg ?a=b or ;JSESSIONID=xxx) and avoids duplicate '/' + * (e.g. {@code ?a=b} or {@code ;JSESSIONID=xxx}) and avoids duplicate '{@code /}' * * @param p1 URI path segment (should be encoded) * @param p2 URI path segment (should be encoded) @@ -1019,7 +872,7 @@ public static String addEncodedPaths(String p1, String p2) if (buf.charAt(split - 1) == '/') { - if (p2.startsWith(URIUtil.SLASH)) + if (p2.startsWith("/")) { buf.deleteCharAt(split - 1); buf.insert(split - 1, p2); @@ -1029,7 +882,7 @@ public static String addEncodedPaths(String p1, String p2) } else { - if (p2.startsWith(URIUtil.SLASH)) + if (p2.startsWith("/")) buf.insert(split, p2); else { @@ -1043,8 +896,10 @@ public static String addEncodedPaths(String p1, String p2) /** * Add two Decoded URI path segments. - * Handles null and empty paths. Path and query params (eg ?a=b or - * ;JSESSIONID=xxx) are not handled + *

+ * Handles null and empty paths. + * Path and query params (e.g. {@code ?a=b} or {@code ;JSESSIONID=xxx}) are not handled + *

* * @param p1 URI path segment (should be decoded) * @param p2 URI path segment (should be decoded) @@ -1061,8 +916,8 @@ public static String addPaths(String p1, String p2) if (p2 == null || p2.length() == 0) return p1; - boolean p1EndsWithSlash = p1.endsWith(SLASH); - boolean p2StartsWithSlash = p2.startsWith(SLASH); + boolean p1EndsWithSlash = p1.endsWith("/"); + boolean p2StartsWithSlash = p2.startsWith("/"); if (p1EndsWithSlash && p2StartsWithSlash) { @@ -1075,25 +930,27 @@ public static String addPaths(String p1, String p2) StringBuilder buf = new StringBuilder(p1.length() + p2.length() + 2); buf.append(p1); - if (p1.endsWith(SLASH)) + if (p1.endsWith("/")) { - if (p2.startsWith(SLASH)) + if (p2.startsWith("/")) buf.setLength(buf.length() - 1); } else { - if (!p2.startsWith(SLASH)) - buf.append(SLASH); + if (!p2.startsWith("/")) + buf.append("/"); } buf.append(p2); return buf.toString(); } - /** Add a path and a query string + /** + * Add a path and a query string + * * @param path The path which may already contain a query * @param query The query string to add (if blank, no query is added) - * @return The path with any non-blank query added after a '?' or '&' as appropriate. + * @return The path with any non-blank query added after a '{@code ?}' or '{@code &}' as appropriate. */ public static String addPathQuery(String path, String query) { @@ -1142,14 +999,16 @@ public static String getUriLastPathSegment(URI uri) /** * Return the parent Path. + *

* Treat a URI like a directory path and return the parent directory. + *

* * @param p the path to return a parent reference to * @return the parent path of the URI */ public static String parentPath(String p) { - if (p == null || URIUtil.SLASH.equals(p)) + if (p == null || "/".equals(p)) return null; int slash = p.lastIndexOf('/', p.length() - 2); if (slash >= 0) @@ -1158,7 +1017,8 @@ public static String parentPath(String p) } /** - *

Normalize a URI path and query by factoring out all segments of "." and ".." + *

+ * Normalize a URI path and query by factoring out all segments of '{@code .}' and '{@code ..}' * up until any query or fragment. * Null is returned if the path is normalized above its root. *

@@ -1189,7 +1049,6 @@ public static String normalizePathQuery(String pathQuery) case '.': if (slash) break loop; - slash = false; break; case '?': @@ -1267,8 +1126,8 @@ else if (slash) /** *

Check if a path would be normalized within itself. For example, - * /foo/../../bar is normalized above its root and would - * thus return false, whilst /foo/./bar/.. is normal within itself + * {@code /foo/../../bar} is normalized above its root and would + * thus return false, whilst {@code /foo/./bar/..} is normal within itself * and would return true. * @param path The path to check * @return True if the normal form of the path is within the root of the path. @@ -1280,11 +1139,11 @@ public static boolean isNotNormalWithinSelf(String path) } /** - *

Normalize a URI path by factoring out all segments of "." and "..". + *

Normalize a URI path by factoring out all segments of {@code .} and {@code ..}. * Null is returned if the path is normalized above its root. *

* - * @param path the decoded URI path to convert. Any special characters (e.g. '?', "#") are assumed to be part of + * @param path the decoded URI path to convert. Any special characters (e.g. {@code ?}, {@code #}) are assumed to be part of * the path segments. * @return the normalized path, or null if path traversal above root. * @see #normalizePathQuery(String) @@ -1306,18 +1165,13 @@ public static String normalizePath(String path) char c = path.charAt(i); switch (c) { - case '/': - slash = true; - break; - - case '.': + case '/' -> slash = true; + case '.' -> + { if (slash) break loop; - slash = false; - break; - - default: - slash = false; + } + default -> slash = false; } i++; @@ -1339,14 +1193,15 @@ public static String normalizePath(String path) char c = path.charAt(i); switch (c) { - case '/': + case '/' -> + { if (doDotsSlash(canonical, dots)) return null; slash = true; dots = 0; - break; - - case '.': + } + case '.' -> + { // Count dots only if they are leading in the segment if (dots > 0) dots++; @@ -1355,15 +1210,16 @@ else if (slash) else canonical.append('.'); slash = false; - break; - - default: + } + default -> + { // Add leading dots to the path while (dots-- > 0) canonical.append('.'); canonical.append(c); dots = 0; slash = false; + } } i++; } @@ -1420,7 +1276,7 @@ private static boolean doDotsSlash(StringBuilder canonical, int dots) /** * Convert a path to a compact form. - * All instances of "//" and "///" etc. are factored out to single "/" + * All instances of {@code //} and {@code ///} etc. are factored out to single {@code /} * * @param path the path to compact * @return the compacted path @@ -1582,47 +1438,36 @@ public static void appendSchemeHostPort(StringBuilder url, String scheme, String */ public static void appendSchemeHostPort(StringBuffer url, String scheme, String server, int port) { - synchronized (url) - { - url.append(scheme).append("://").append(HostPort.normalizeHost(server)); + url.append(scheme).append("://").append(HostPort.normalizeHost(server)); - if (port > 0) + if (port > 0) + { + switch (scheme) { - switch (scheme) - { - case "http": - if (port != 80) - url.append(':').append(port); - break; - - case "https": - if (port != 443) - url.append(':').append(port); - break; + case "http": + if (port != 80) + url.append(':').append(port); + break; - default: + case "https": + if (port != 443) url.append(':').append(port); - } - } - } - } + break; - // Only URIUtil is using this method - static boolean equalsIgnoreEncodings(String uriA, String uriB) - { - try - { - String safeDecodedUriA = ensureSafeEncoding(uriA); - String safeDecodedUriB = ensureSafeEncoding(uriB); - return safeDecodedUriA.equals(safeDecodedUriB); - } - catch (IllegalArgumentException e) - { - return false; + default: + url.append(':').append(port); + } } } - static String ensureSafeEncoding(String path) + /** + * Encode characters in a path to ensure they only contain safe encodings suitable for both + * {@link URI} and {@link Paths#get(URI)} usage. + * + * @param path the path to encode + * @return the returned path with only safe encodings + */ + public static String encodePathSafeEncoding(String path) { if (path == null) return null; @@ -1762,42 +1607,6 @@ private static boolean mustBeEncoded(int codepoint) return ((codepoint == '?') || (codepoint == '#')); } - public static boolean equalsIgnoreEncodings(URI uriA, URI uriB) - { - if (uriA.equals(uriB)) - return true; - - if (uriA.toASCIIString().equals(uriB.toASCIIString())) - return true; - - // TODO: this check occurs in uriA.equals(uriB) - if (uriA.getScheme() == null) - { - if (uriB.getScheme() != null) - return false; - } - else if (!uriA.getScheme().equalsIgnoreCase(uriB.getScheme())) - return false; - - if ("jar".equalsIgnoreCase(uriA.getScheme())) - { - // at this point we know that both uri's are "jar:" - URI uriAssp = URI.create(uriA.getRawSchemeSpecificPart()); - URI uriBssp = URI.create(uriB.getRawSchemeSpecificPart()); - return equalsIgnoreEncodings(uriAssp, uriBssp); - } - - if (uriA.getAuthority() == null) - { - if (uriB.getAuthority() != null) - return false; - } - else if (!uriA.getAuthority().equals(uriB.getAuthority())) - return false; - - return equalsIgnoreEncodings(uriA.getRawPath(), uriB.getRawPath()); - } - /** * Add a sub path to an existing URI. * @@ -1828,7 +1637,7 @@ public static URI addPath(URI uri, String path) // ensure that the base has a safe encoding suitable for both // URI and Paths.get(URI) later usage - path = ensureSafeEncoding(path); + path = encodePathSafeEncoding(path); pathLen = path.length(); if (base.length() == 0) @@ -1847,8 +1656,8 @@ public static URI addPath(URI uri, String path) } /** - * Combine two query strings into one. Each query string should not contain the beginning '?' character, but - * may contain multiple parameters separated by the '{@literal &}' character. + * Combine two query strings into one. Each query string should not contain the beginning '{@code ?}' character, but + * may contain multiple parameters separated by the '{@code &}' character. * @param query1 the first query string. * @param query2 the second query string. * @return the combination of the two query strings. @@ -1911,12 +1720,12 @@ public static URI correctFileURI(URI uri) } /** - * Split a string of references, that may be split with {@code ,}, or {@code ;}, or {@code |} into URIs. + * Split a string of references, that may be split with '{@code ,}', or '{@code ;}', or '{@code |}' into URIs. *

* Each part of the input string could be path references (unix or windows style), or string URI references. *

*

- * If the result of processing the input segment is a java archive, then its resulting URI will be a mountable URI as `jar:file:...!/`. + * If the result of processing the input segment is a java archive, then its resulting URI will be a mountable URI as {@code jar:file:...!/} *

* * @param str the input string of references @@ -1973,12 +1782,15 @@ public static List split(String str) } /** + *

* Take an arbitrary URI and provide a URI that is suitable for mounting the URI as a Java FileSystem. - * + *

+ *

* The resulting URI will point to the {@code jar:file://foo.jar!/} said Java Archive (jar, war, or zip) + *

* * @param uri the URI to mutate to a {@code jar:file:...} URI. - * @return the jar:${uri_to_java_archive}!/${internal-reference} URI or the unchanged URI if not a Java Archive. + * @return the {@code jar:${uri_to_java_archive}!/${internal-reference}} URI or the unchanged URI if not a Java Archive. * @see FileID#isArchive(URI) */ public static URI toJarFileUri(URI uri) @@ -2034,9 +1846,13 @@ public static URI toURI(String resource) } /** + *

* Unwrap a URI to expose its container path reference. + *

* + *

* Take out the container archive name URI from a {@code jar:file:${container-name}!/} URI. + *

* * @param uri the input URI * @return the container String if a {@code jar} scheme, or just the URI untouched. diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/CombinedResource.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/CombinedResource.java index 896f18fbe3b6..e264e06d9d17 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/CombinedResource.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/CombinedResource.java @@ -131,7 +131,7 @@ public Resource resolve(String subUriPath) if (URIUtil.isNotNormalWithinSelf(subUriPath)) throw new IllegalArgumentException(subUriPath); - if (subUriPath.length() == 0 || URIUtil.SLASH.equals(subUriPath)) + if (subUriPath.length() == 0 || "/".equals(subUriPath)) { return this; } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java index dfeb444212d6..f334d2077294 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java @@ -182,8 +182,8 @@ public static boolean isSameName(Path pathA, Path pathB) if (Files.isDirectory(path)) { String uriString = uri.toASCIIString(); - if (!uriString.endsWith(URIUtil.SLASH)) - uri = URIUtil.correctFileURI(URI.create(uriString + URIUtil.SLASH)); + if (!uriString.endsWith("/")) + uri = URIUtil.correctFileURI(URI.create(uriString + "/")); } this.path = path; @@ -282,7 +282,7 @@ public Resource resolve(String subUriPath) if (URIUtil.isNotNormalWithinSelf(subUriPath)) throw new IllegalArgumentException(subUriPath); - if (URIUtil.SLASH.equals(subUriPath)) + if ("/".equals(subUriPath)) return this; URI uri = getURI(); diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java index 5dc2cbbd9355..dfba8cb54eca 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java @@ -66,7 +66,9 @@ public static Stream encodePathSource() Arguments.of("/context/'list'/\"me\"/;", "/context/%27list%27/%22me%22/%3B%3Cscript%3Ewindow.alert(%27xss%27)%3B%3C/script%3E"), Arguments.of("test\u00f6?\u00f6:\u00df", "test%C3%B6%3F%C3%B6:%C3%9F"), - Arguments.of("test?\u00f6?\u00f6:\u00df", "test%3F%C3%B6%3F%C3%B6:%C3%9F") + Arguments.of("test?\u00f6?\u00f6:\u00df", "test%3F%C3%B6%3F%C3%B6:%C3%9F"), + Arguments.of("/test space/", "/test%20space/"), + Arguments.of("/test\u007fdel/", "/test%7Fdel/") ); } @@ -75,10 +77,8 @@ public static Stream encodePathSource() public void testEncodePath(String rawPath, String expectedEncoded) { // test basic encode/decode - StringBuilder buf = new StringBuilder(); - buf.setLength(0); - URIUtil.encodePath(buf, rawPath); - assertEquals(expectedEncoded, buf.toString()); + String result = URIUtil.encodePath(rawPath); + assertEquals(expectedEncoded, result); } @Test @@ -565,7 +565,7 @@ public void testAddPathQuery(String path, String query, String expected) assertThat(actual, is(expected)); } - public static Stream ensureSafeEncodingSource() + public static Stream encodePathSafeEncodingSource() { return Stream.of( Arguments.of("/foo", "/foo"), @@ -589,10 +589,10 @@ public static Stream ensureSafeEncodingSource() } @ParameterizedTest - @MethodSource("ensureSafeEncodingSource") - public void testEnsureSafeEncoding(String input, String expected) + @MethodSource("encodePathSafeEncodingSource") + public void testEncodePathSafeEncoding(String input, String expected) { - assertThat(URIUtil.ensureSafeEncoding(input), is(expected)); + assertThat(URIUtil.encodePathSafeEncoding(input), is(expected)); } public static Stream compactPathSource() @@ -637,139 +637,6 @@ public void testParentPath(String path, String expectedPath) assertEquals(expectedPath, actual, String.format("parent %s", path)); } - public static Stream equalsIgnoreEncodingStringTrueSource() - { - return Stream.of( - Arguments.of("http://example.com/foo/bar", "http://example.com/foo/bar"), - Arguments.of("/barry%27s", "/barry%27s"), - Arguments.of("/b rry%27s", "/b%20rry%27s"), - Arguments.of("/barry's", "/barry%27s"), - Arguments.of("/barry%27s", "/barry's"), - Arguments.of("/b rry's", "/b%20rry%27s"), - Arguments.of("/b rry%27s", "/b%20rry's"), - Arguments.of("/re bar", "/re%20bar"), - - Arguments.of("/foo%2fbar", "/foo%2fbar"), - Arguments.of("/foo%2fbar", "/foo%2Fbar"), - - // encoded vs not-encode ("%" symbol is encoded as "%25") - Arguments.of("/abc%25xyz", "/abc%xyz"), - Arguments.of("/abc%25xy", "/abc%xy"), - Arguments.of("/abc%25x", "/abc%x"), - Arguments.of("/zzz%25", "/zzz%"), - - // unicode encoded vs not-encoded - Arguments.of("/path/to/bä€ãm/", "/path/to/b%C3%A4%E2%82%AC%C3%A3m/") - ); - } - - @ParameterizedTest - @MethodSource("equalsIgnoreEncodingStringTrueSource") - public void testEqualsIgnoreEncodingStringTrue(String uriA, String uriB) - { - assertTrue(URIUtil.equalsIgnoreEncodings(uriA, uriB)); - } - - public static Stream equalsIgnoreEncodingStringFalseSource() - { - return Stream.of( - // case difference - Arguments.of("ABC", "abc"), - // Encoding difference ("'" is "%27") - Arguments.of("/barry's", "/barry%26s"), - // Never match on "%2f" differences - only intested in filename / directory name differences - // This could be a directory called "foo" with a file called "bar" on the left, and just a file "foo%2fbar" on the right - Arguments.of("/foo/bar", "/foo%2fbar"), - // not actually encoded - Arguments.of("/foo2fbar", "/foo/bar"), - // path params - Arguments.of("/path;a=b/to;x=y/foo/", "/path/to/foo"), - // encoded vs not-encode ("%" symbol is encoded as "%25") - Arguments.of("/yyy%25zzz", "/aaa%xxx"), - Arguments.of("/zzz%25", "/aaa%"), - // %2F then multi-byte unicode - Arguments.of("/path/to/bãm/", "/path%2Fto/b%C3%A3m/"), - // multi-byte unicode then %2F - Arguments.of("/path/bãm/or/bust", "/path/b%C3%A3m/or%2Fbust"), - // mix of %2F and multiple consecutive multi-byte unicode - Arguments.of("/path/to/bä€ãm/", "/path%2Fto/b%C3%A4%E2%82%AC%C3%A3m/") - ); - } - - @ParameterizedTest - @MethodSource("equalsIgnoreEncodingStringFalseSource") - public void testEqualsIgnoreEncodingStringFalse(String uriA, String uriB) - { - assertFalse(URIUtil.equalsIgnoreEncodings(uriA, uriB)); - } - - public static Stream equalsIgnoreEncodingURITrueSource() - { - return Stream.of( - Arguments.of( - URI.create("HTTP:/foo/b%61r"), - URI.create("http:/f%6Fo/bar") - ), - Arguments.of( - URI.create("jar:file:/path/to/main.jar!/META-INF/versions/"), - URI.create("jar:file:/path/to/main.jar!/META-INF/%76ersions/") - ), - Arguments.of( - URI.create("JAR:FILE:/path/to/main.jar!/META-INF/versions/"), - URI.create("jar:file:/path/to/main.jar!/META-INF/versions/") - ), - // unicode in opaque jar:file: URI - Arguments.of( - URI.create("jar:file:///path/to/test.jar!/bãm/"), - URI.create("jar:file:///path/to/test.jar!/b%C3%A3m/") - ), - // multiple consecutive unicode - Arguments.of( - URI.create("file:///path/to/bä€ãm/"), - URI.create("file:///path/to/b%C3%A4%E2%82%AC%C3%A3m/") - ) - ); - } - - @ParameterizedTest - @MethodSource("equalsIgnoreEncodingURITrueSource") - public void testEqualsIgnoreEncodingURITrue(URI uriA, URI uriB) - { - assertTrue(URIUtil.equalsIgnoreEncodings(uriA, uriB)); - } - - public static Stream equalsIgnoreEncodingURIFalseSource() - { - return Stream.of( - Arguments.of( - URI.create("/foo%2Fbar"), - URI.create("/foo/bar") - ), - // %2F then unicode - Arguments.of( - URI.create("file:///path/to/bãm/"), - URI.create("file:///path%2Fto/b%C3%A3m/") - ), - // unicode then %2F - Arguments.of( - URI.create("file:///path/bãm/or/bust"), - URI.create("file:///path/b%C3%A3m/or%2Fbust") - ), - // mix of %2F and multiple consecutive unicode - Arguments.of( - URI.create("file:///path/to/bä€ãm/"), - URI.create("file:///path%2Fto/b%C3%A4%E2%82%AC%C3%A3m/") - ) - ); - } - - @ParameterizedTest - @MethodSource("equalsIgnoreEncodingURIFalseSource") - public void testEqualsIgnoreEncodingURIFalse(URI uriA, URI uriB) - { - assertFalse(URIUtil.equalsIgnoreEncodings(uriA, uriB)); - } - public static Stream correctBadFileURICases() { return Stream.of( @@ -811,17 +678,18 @@ public void testCorrectFileURI(String input, String expected) } @Test - public void testCorrectBadFileURIActualFile() throws Exception + public void testCorrectBadFileURIActualFile(WorkDir workDir) throws Exception { - File file = MavenTestingUtils.getTargetFile("testCorrectBadFileURIActualFile.txt"); - FS.touch(file); + Path testfile = workDir.getEmptyPathDir().resolve("testCorrectBadFileURIActualFile.txt"); + FS.touch(testfile); - URI expectedUri = file.toPath().toUri(); + URI expectedUri = testfile.toUri(); // correct URI with `://` assertThat(expectedUri.toASCIIString(), containsString("://")); - URI fileUri = file.toURI(); - URI fileUrlUri = file.toURL().toURI(); + File file = testfile.toFile(); + URI fileUri = file.toURI(); // java produced bad format with only `:/` (not `://`) + URI fileUrlUri = file.toURL().toURI(); // java produced bad format with only `:/` (not `://`) // If these 2 tests start failing, that means Java itself has been fixed assertThat(fileUri.toASCIIString(), not(containsString("://"))); @@ -831,29 +699,6 @@ public void testCorrectBadFileURIActualFile() throws Exception assertThat(URIUtil.correctFileURI(fileUrlUri).toASCIIString(), is(expectedUri.toASCIIString())); } - public static Stream encodeSpacesSource() - { - return Stream.of( - // null - Arguments.of(null, null), - - // no spaces - Arguments.of("abc", "abc"), - - // match - Arguments.of("a c", "a%20c"), - Arguments.of(" ", "%20%20%20"), - Arguments.of("a%20space", "a%20space") - ); - } - - @ParameterizedTest - @MethodSource("encodeSpacesSource") - public void testEncodeSpaces(String raw, String expected) - { - assertThat(URIUtil.encodeSpaces(raw), is(expected)); - } - public static Stream encodeSpecific() { return Stream.of( @@ -1040,12 +885,12 @@ public void testEncodeDecodeVisibleOnly() builder.append(i); String path = builder.toString(); String encoded = URIUtil.encodePath(path); - // Check endoded is visible + // Check encoded is visible for (char c : encoded.toCharArray()) { - assertTrue(c > 0x20 && c < 0x80); + assertTrue(c > 0x20 && c < 0x7f); assertFalse(Character.isWhitespace(c)); - assertFalse(Character.isISOControl(c)); + assertFalse(Character.isISOControl(c), "isISOControl(0x%2x)".formatted((byte)c)); } // check decode to original String decoded = URIUtil.decodePath(encoded); diff --git a/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java b/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java index 22dd8d1cd32d..e34e8111b61c 100644 --- a/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java +++ b/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java @@ -389,7 +389,7 @@ public Authentication validateRequest(Request req, Response res, Callback cb, bo String uri = request.getRequestURI(); if (uri == null) - uri = URIUtil.SLASH; + uri = "/"; mandatory |= isJSecurityCheck(uri); if (!mandatory) diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java index 30a32c7e9316..a124d5c083b4 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java @@ -786,7 +786,7 @@ public Map getLocaleEncodings() */ public Resource getResource(String pathInContext) throws MalformedURLException { - if (pathInContext == null || !pathInContext.startsWith(URIUtil.SLASH)) + if (pathInContext == null || !pathInContext.startsWith("/")) throw new MalformedURLException(pathInContext); Resource baseResource = getBaseResource(); @@ -838,8 +838,8 @@ public Set getResourcePaths(String path) { Resource resource = getResource(path); - if (!path.endsWith(URIUtil.SLASH)) - path = path + URIUtil.SLASH; + if (!path.endsWith("/")) + path = path + "/"; HashSet set = new HashSet<>(); for (Resource item: resource.list()) @@ -2889,9 +2889,9 @@ public String getRealPath(String path) if (path == null) return null; if (path.length() == 0) - path = URIUtil.SLASH; + path = "/"; else if (path.charAt(0) != '/') - path = URIUtil.SLASH + path; + path = "/" + path; try { diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java index 6b10a2f03cd2..8ae24f46a722 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java @@ -253,7 +253,7 @@ public Authentication validateRequest(Request req, Response res, Callback callba { nuri = servletApiRequest.getContextPath(); if (nuri.length() == 0) - nuri = URIUtil.SLASH; + nuri = "/"; } else nuri = savedURI.asString(); diff --git a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java index 7ac59b85dbc1..f881706aaddc 100644 --- a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java +++ b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java @@ -378,7 +378,7 @@ public ResourceFactory getResourceFactory() @Override public Resource getResource(String pathInContext) throws MalformedURLException { - if (pathInContext == null || !pathInContext.startsWith(URIUtil.SLASH)) + if (pathInContext == null || !pathInContext.startsWith("/")) throw new MalformedURLException(pathInContext); MalformedURLException mue = null; diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java index 02ad570627da..54aa0096935d 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java @@ -1384,7 +1384,7 @@ public Map getLocaleEncodings() */ public Resource getResource(String pathInContext) throws MalformedURLException { - if (pathInContext == null || !pathInContext.startsWith(URIUtil.SLASH)) + if (pathInContext == null || !pathInContext.startsWith("/")) throw new MalformedURLException(pathInContext); Resource baseResource = _coreContextHandler.getBaseResource(); @@ -1476,8 +1476,8 @@ public Set getResourcePaths(String path) { Resource resource = getResource(path); - if (!path.endsWith(URIUtil.SLASH)) - path = path + URIUtil.SLASH; + if (!path.endsWith("/")) + path = path + "/"; HashSet set = new HashSet<>(); @@ -1814,9 +1814,9 @@ public String getRealPath(String path) if (path == null) return null; if (path.length() == 0) - path = URIUtil.SLASH; + path = "/"; else if (path.charAt(0) != '/') - path = URIUtil.SLASH + path; + path = "/" + path; try { diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceService.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceService.java index 6a6b97e39aef..9cbc5a23e266 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceService.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceService.java @@ -233,7 +233,7 @@ public boolean doGet(HttpServletRequest request, HttpServletResponse response) String pathInContext = URIUtil.addPaths(servletPath, pathInfo); - boolean endsWithSlash = (pathInfo == null ? (_pathInfoOnly ? "" : servletPath) : pathInfo).endsWith(URIUtil.SLASH); + boolean endsWithSlash = (pathInfo == null ? (_pathInfoOnly ? "" : servletPath) : pathInfo).endsWith("/"); boolean checkPrecompressedVariants = _precompressedFormats.length > 0 && !endsWithSlash && !included && reqRanges == null; HttpContent content = null; @@ -650,7 +650,7 @@ protected void sendDirectory(HttpServletRequest request, } byte[] data = null; - String base = URIUtil.addEncodedPaths(request.getRequestURI(), URIUtil.SLASH); + String base = URIUtil.addEncodedPaths(request.getRequestURI(), "/"); String dir = ResourceListing.getAsXHTML(resource, base, pathInContext.length() > 1, request.getQueryString()); if (dir == null) { diff --git a/jetty-ee9/jetty-ee9-openid/src/main/java/org/eclipse/jetty/ee9/security/openid/OpenIdAuthenticator.java b/jetty-ee9/jetty-ee9-openid/src/main/java/org/eclipse/jetty/ee9/security/openid/OpenIdAuthenticator.java index dfcc778a6dc5..2852d0f3212f 100644 --- a/jetty-ee9/jetty-ee9-openid/src/main/java/org/eclipse/jetty/ee9/security/openid/OpenIdAuthenticator.java +++ b/jetty-ee9/jetty-ee9-openid/src/main/java/org/eclipse/jetty/ee9/security/openid/OpenIdAuthenticator.java @@ -378,7 +378,7 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b String uri = request.getRequestURI(); if (uri == null) - uri = URIUtil.SLASH; + uri = "/"; mandatory |= isJSecurityCheck(uri); if (!mandatory) diff --git a/jetty-ee9/jetty-ee9-security/src/main/java/org/eclipse/jetty/ee9/security/authentication/FormAuthenticator.java b/jetty-ee9/jetty-ee9-security/src/main/java/org/eclipse/jetty/ee9/security/authentication/FormAuthenticator.java index 5b058821a0a9..45ea2f4ad35f 100644 --- a/jetty-ee9/jetty-ee9-security/src/main/java/org/eclipse/jetty/ee9/security/authentication/FormAuthenticator.java +++ b/jetty-ee9/jetty-ee9-security/src/main/java/org/eclipse/jetty/ee9/security/authentication/FormAuthenticator.java @@ -242,7 +242,7 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b String uri = request.getRequestURI(); if (uri == null) - uri = URIUtil.SLASH; + uri = "/"; mandatory |= isJSecurityCheck(uri); if (!mandatory) @@ -275,7 +275,7 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b { nuri = request.getContextPath(); if (nuri.length() == 0) - nuri = URIUtil.SLASH; + nuri = "/"; } formAuth = new FormAuthentication(getAuthMethod(), user); } diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java index 06c5a80b501e..9d7afbded2d7 100644 --- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java +++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java @@ -387,7 +387,7 @@ public ResourceFactory getResourceFactory() @Override public Resource getResource(String pathInContext) throws MalformedURLException { - if (pathInContext == null || !pathInContext.startsWith(URIUtil.SLASH)) + if (pathInContext == null || !pathInContext.startsWith("/")) throw new MalformedURLException(pathInContext); MalformedURLException mue = null;