Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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 @@ -103,7 +103,7 @@ public UriBuilderImpl(URI uri) throws IllegalArgumentException {

@Override
public URI build(Object... values) throws IllegalArgumentException, UriBuilderException {
return doBuild(false, true, values);
return build(values, true);
}

private static Map<String, Object> getResolvedTemplates(Map<String, Object> rtemplates) {
Expand Down Expand Up @@ -185,13 +185,16 @@ private UriParts doBuildUriParts(boolean fromEncoded, boolean encodePathSlash,

private URI buildURI(boolean fromEncoded, String thePath, String theQuery, String theFragment)
throws URISyntaxException {

// Always include the leading slash in order to prevent host overrides
if ((scheme != null || host != null || userInfo != null)
&& thePath.length() != 0 && !(thePath.startsWith("/") || !needsLeadingSlash(thePath))) {
thePath = "/" + thePath;
}

if (fromEncoded) {
return buildURIFromEncoded(thePath, theQuery, theFragment);
} else if (!isSchemeOpaque()) {
if ((scheme != null || host != null || userInfo != null)
&& thePath.length() != 0 && !(thePath.startsWith("/") || thePath.startsWith(";"))) {
thePath = "/" + thePath;
}
try {
return buildURIFromEncoded(thePath, theQuery, theFragment);
} catch (Exception ex) {
Expand Down Expand Up @@ -235,8 +238,8 @@ private String buildUriString(String thePath, String theQuery, String theFragmen
b.append(':').append(port);
}
if (thePath != null && thePath.length() > 0) {
b.append(thePath.startsWith("/") || b.length() == 0 || originalPathEmpty
? thePath : '/' + thePath);
b.append(thePath.startsWith("/") || b.length() == 0
|| (originalPathEmpty && !needsLeadingSlash(thePath)) ? thePath : '/' + thePath);
}
if (theQuery != null && theQuery.length() != 0) {
b.append('?').append(theQuery);
Expand All @@ -249,6 +252,28 @@ private String buildUriString(String thePath, String theQuery, String theFragmen
}
return b.toString();
}

/**
* The URI parsing logic seems to be flawed and treats everything after @
* symbol as the host name, for example:
*
* URI.create("http://foo.com;@evil.com").getHost() -> "evil.com"
* URI.create("http://foo.com&@evil.com").getHost() -> "evil.com"
* URI.create("http://foo.com+@evil.com").getHost() -> "evil.com"
*
* The straightforward encoding of @ -> %40 does not work either:
*
* URI.create("http://foo.com;%40evil.com").getHost() -> null
*
* It does not even matter if the userinfo part is already provided:
*
* URI.create("http://a:b@foo.com;%40evil.com").getHost() -> null
*
* To workaround the issue, we have to include leading path slash all the time.
*/
private boolean needsLeadingSlash(String path) {
return !path.startsWith(";") || path.indexOf('@') >= 0; /* check if @ is present */
}

private boolean isSchemeOpaque() {
return schemeSpecificPart != null;
Expand All @@ -262,7 +287,7 @@ public URI buildFromEncoded(Object... values) throws IllegalArgumentException, U
@Override
public URI buildFromMap(Map<String, ?> map) throws IllegalArgumentException,
UriBuilderException {
return doBuildFromMap(map, false, true);
return buildFromMap(map, true);
}

private URI doBuildFromMap(Map<String, ? extends Object> map, boolean fromEncoded,
Expand Down Expand Up @@ -548,7 +573,9 @@ private UriBuilder doPath(String path, boolean checkSegments) {
if (path == null) {
throw new IllegalArgumentException("path is null");
}
if (isAbsoluteUriPath(path)) {
Comment thread
coheigea marked this conversation as resolved.
// Only set uri when path is absolute and the current URI's is not set
// (scheme and host are all null).
if (isAbsoluteUriPath(path) && scheme == null && host == null) {
try {
URI uri = URI.create(path);
this.originalPathEmpty = StringUtils.isEmpty(uri.getPath());
Expand Down Expand Up @@ -778,7 +805,9 @@ public UriBuilder replaceMatrixParam(String name, Object... values) throws Illeg
public UriBuilder replacePath(String path) {
if (path == null) {
clearPathAndMatrix();
} else if (isAbsoluteUriPath(path)) {
} else if (isAbsoluteUriPath(path) && scheme == null && host == null) {
// Only set uri when path is absolute and the current URI's is not set
// (scheme and host are all null).
clearPathAndMatrix();
uri(URI.create(path));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@

import org.junit.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
Expand Down Expand Up @@ -134,7 +137,257 @@ public void testBuildWithNonEncodedSubstitutionValue8() {
assertEquals("/?a=%25&a2=%7B%7D", uri.toString());
}

@Test
public void testReplaceFullPath() {
UriBuilder ub = UriBuilder.fromPath("");
URI uri = ub.build();
assertEquals("", uri.toString());
uri = ub.replacePath("http://foo.com").build();
assertEquals("http://foo.com", uri.toString());

uri = ub.buildFromEncoded();
assertEquals("http://foo.com", uri.toString());
}

@Test
public void testReplaceFullPathWhenUriIsSet() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.replacePath("http://bar.com/").build();
assertThat(uri.toString(), startsWith("http://foo.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), startsWith("http://foo.com"));
assertThat(uri.getHost(), equalTo("foo.com"));
}

@Test
public void testBuildAndSetFullPath() {
UriBuilder ub = UriBuilder.fromPath("");
URI uri = ub.build();
assertEquals("", uri.toString());
uri = ub.path("http://foo.com").build();
assertEquals("http://foo.com", uri.toString());

uri = ub.buildFromEncoded();
assertThat(uri.toString(), startsWith("http://foo.com"));
assertThat(uri.getHost(), equalTo("foo.com"));
}

@Test
public void testBuildAndSetFullPathWhenUriIsSet() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.path("http://bar.com/").build();
assertThat(uri.toString(), startsWith("http://foo.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), startsWith("http://foo.com"));
assertThat(uri.getHost(), equalTo("foo.com"));
}

@Test
public void testPathDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());

uri = ub.path(".org").build();
assertThat(uri.toString(), equalTo("http://foo.com/.org"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://foo.com/.org"));
assertThat(uri.getHost(), equalTo("foo.com"));
}

@Test
public void testReplacePathDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.replacePath(".org").build();
assertThat(uri.toString(), equalTo("http://foo.com/.org"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://foo.com/.org"));
assertThat(uri.getHost(), equalTo("foo.com"));
}

@Test
public void testUserInfoAndUriWithMatrix() {
// The URI will treat `evil.com` as the host name
UriBuilder ub = UriBuilder.fromUri("http://foo.com;@evil.com");
URI uri = ub.build();
assertEquals("http://foo.com;@evil.com", uri.toString());
assertThat(uri.getHost(), equalTo("evil.com"));
Comment thread
coheigea marked this conversation as resolved.
}

@Test
public void testUserInfoAndPathWithMatrix() {
// The URI will treat `evil.com` as the host name
UriBuilder ub = UriBuilder.fromPath("http://foo.com;@evil.com");
URI uri = ub.build();
assertEquals("http://foo.com;@evil.com", uri.toString());
assertThat(uri.getHost(), equalTo("evil.com"));
}

@Test
public void testPathWithUserInfoDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://a:b@foo.com");
URI uri = ub.build();
assertEquals("http://a:b@foo.com", uri.toString());
uri = ub.path(";@evil.com").build();
assertThat(uri.toString(), equalTo("http://a:b@foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://a:b@foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

String template = ub.toTemplate();
assertThat(template, equalTo("http://a:b@foo.com/;@evil.com"));
}

@Test
public void testUriWithUserInfoDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromUri("http://a:b@foo.com");
URI uri = ub.build();
assertEquals("http://a:b@foo.com", uri.toString());
uri = ub.path(";@evil.com").build();
assertThat(uri.toString(), equalTo("http://a:b@foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://a:b@foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

String template = ub.toTemplate();
assertThat(template, equalTo("http://a:b@foo.com/;@evil.com"));
}

@Test
public void testUserInfoAndPathDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.path(";@evil.com").build();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

String template = ub.toTemplate();
assertThat(template, equalTo("http://foo.com/;@evil.com"));
}

@Test
public void testUserInfoAndReplacePathDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.replacePath(";@evil.com").build();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

String template = ub.toTemplate();
assertThat(template, equalTo("http://foo.com/;@evil.com"));
}

@Test
public void testUserInfoAndReplaceMatrixDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.replaceMatrix("@evil.com").build();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

String template = ub.toTemplate();
assertThat(template, equalTo("http://foo.com/;@evil.com"));
}

@Test
public void testUserInfoAndMatrixDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.matrixParam("@evil.com").build();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded();
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

String template = ub.toTemplate();
assertThat(template, equalTo("http://foo.com/;@evil.com"));
}

@Test
public void testUserInfoAndTemplatedPathDoesNotChangeHost() {
UriBuilder ub = UriBuilder.fromPath("http://foo.com");
URI uri = ub.build();
assertEquals("http://foo.com", uri.toString());
uri = ub.path("{x}").build(";@evil.com");
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));

uri = ub.buildFromEncoded(";@evil.com");
assertThat(uri.toString(), equalTo("http://foo.com/;@evil.com"));
assertThat(uri.getHost(), equalTo("foo.com"));
}

@Test
public void testTemplateUriDoesNotChangeHost() {
final String template = UriBuilder
.fromUri("http://foo.com")
.path(".org")
.toTemplate();
assertEquals("http://foo.com/.org", template);
}

@Test
public void testTemplatePathDoesNotChangeHost() {
final String template = UriBuilder
.fromPath("http://foo.com")
.path(".org")
.toTemplate();
assertEquals("http://foo.com/.org", template);
}

@Test
public void testTemplateWithPathDoesNotChangeHost() {
final String template = UriBuilder
.fromPath("http://foo.com/aaa")
.path(".org")
.toTemplate();
assertEquals("http://foo.com/aaa/.org", template);
}

@Test
public void testTemplatePathDoesNotReplaceUri() {
final String template = UriBuilder
.fromPath("http://foo.com/")
.path("http://bar.com")
.toTemplate();
assertThat(template, startsWith("http://foo.com/"));
}

@Test
public void testResolveTemplate() {
Expand Down
Loading
Loading