Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,12 @@ public boolean isValid(final String value) {
return false;
}
final String authority = uri.getRawAuthority();
if ("file".equals(scheme) && GenericValidator.isBlankOrNull(authority)) { // Special case - file: allows an empty authority
return true; // this is a local file - nothing more to do here
}
// Special case - file: allows an empty authority, so only the authority check is skipped for it;
// the path, query and fragment below are validated as they are for any other scheme
final boolean emptyFileAuthority = "file".equals(scheme) && GenericValidator.isBlankOrNull(authority);
// Validate the authority
if ("file".equals(scheme) && authority != null && authority.contains(":") || !isValidAuthority(authority)) {
if (!emptyFileAuthority
&& ("file".equals(scheme) && authority != null && authority.contains(":") || !isValidAuthority(authority))) {
return false;
}
if (!isValidPath(uri.getRawPath()) || !isValidQuery(uri.getRawQuery()) || !isValidFragment(uri.getRawFragment())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,45 @@ public void setUp() {
}
}

@Test
void testFileSchemePath() {
final String[] schemes = { "file" };
final UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS);

// an authority-less file: URL gets the same path check as one carrying an authority
assertFalse(urlValidator.isValid("file:///../../etc/passwd"));
assertFalse(urlValidator.isValid("file:/../../etc/passwd"));
assertFalse(urlValidator.isValid("file://localhost/../../etc/passwd"));

// percent-encoded form of the same, as covered for http in testValidator383
assertFalse(urlValidator.isValid("file:///..%2f..%2fetc/passwd"));
assertFalse(urlValidator.isValid("file:///%2e%2e/etc/passwd"));

// an opaque file: URI has no path at all, just as http:example.com has none
assertFalse(urlValidator.isValid("file:etc/passwd"));

assertTrue(urlValidator.isValid("file:///etc/hosts"));
assertTrue(urlValidator.isValid("file:/C:/path/to/dir/"));
}

@Test
void testFileSchemePathOptions() {
final String[] schemes = { "file" };

final UrlValidator noDoubleSlashes = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS);
assertFalse(noDoubleSlashes.isValid("file:///tmp/a//b"));
assertFalse(noDoubleSlashes.isValid("file://localhost/tmp/a//b"));

final UrlValidator allowDoubleSlashes = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS | UrlValidator.ALLOW_2_SLASHES);
assertTrue(allowDoubleSlashes.isValid("file:///tmp/a//b"));

final UrlValidator noFragments = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS | UrlValidator.NO_FRAGMENTS);
assertFalse(noFragments.isValid("file:///tmp/x#frag"));
assertFalse(noFragments.isValid("file://localhost/tmp/x#frag"));

assertTrue(noDoubleSlashes.isValid("file:///tmp/x#frag"));
}

@Test
void testFragments() {
final String[] schemes = { "http", "https" };
Expand Down
Loading