Browse Source

Add percent-encoding of reserved characters in URIish

We do this for the the names that have an explicit scheme and
do it both ways. The URIish is parsed before decoding. Only
a few special characters are encoded for the path part of the
URI, i.e. space, non-ASCII and control characters. The percent
encoding is assumed to be a stream encoding so we interpret it
as UTF-8.

Change-Id: I82d1910df9472e21d7212a2b984ff7d8fb2cbf0f
stable-1.3
Robin Rosenberg 13 years ago
parent
commit
00514bde50
  1. 230
      org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java
  2. 174
      org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java

230
org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java

@ -88,8 +88,10 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals(str, u.getRawPath());
assertEquals(str, u.getPath()); assertEquals(str, u.getPath());
assertEquals(str, u.toString()); assertEquals(str, u.toString());
assertEquals(str, u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -99,8 +101,10 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals(str, u.getRawPath());
assertEquals(str, u.getPath()); assertEquals(str, u.getPath());
assertEquals(str, u.toString()); assertEquals(str, u.toString());
assertEquals(str, u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -110,8 +114,10 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals("D:\\m y", u.getRawPath());
assertEquals("D:\\m y", u.getPath()); assertEquals("D:\\m y", u.getPath());
assertEquals("D:\\m y", u.toString()); assertEquals("D:\\m y", u.toString());
assertEquals("D:\\m y", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -121,8 +127,10 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals(str, u.getRawPath());
assertEquals(str, u.getPath()); assertEquals(str, u.getPath());
assertEquals(str, u.toString()); assertEquals(str, u.toString());
assertEquals(str, u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -132,8 +140,10 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals("\\\\some\\place", u.getRawPath());
assertEquals("\\\\some\\place", u.getPath()); assertEquals("\\\\some\\place", u.getPath());
assertEquals("\\\\some\\place", u.toString()); assertEquals("\\\\some\\place", u.toString());
assertEquals("\\\\some\\place", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -143,8 +153,49 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("file", u.getScheme()); assertEquals("file", u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals("/home/m y", u.getRawPath());
assertEquals("/home/m y", u.getPath()); assertEquals("/home/m y", u.getPath());
assertEquals(str, u.toString()); assertEquals("file:///home/m y", u.toString());
assertEquals("file:///home/m%20y", u.toASCIIString());
assertEquals(u, new URIish(str));
}
@Test
public void testURIEncode_00() throws Exception {
final String str = "file:///home/m%00y";
URIish u = new URIish(str);
assertEquals("file", u.getScheme());
assertFalse(u.isRemote());
assertEquals("/home/m%00y", u.getRawPath());
assertEquals("/home/m\u0000y", u.getPath());
assertEquals("file:///home/m%00y", u.toString());
assertEquals("file:///home/m%00y", u.toASCIIString());
assertEquals(u, new URIish(str));
}
@Test
public void testURIEncode_0a() throws Exception {
final String str = "file:///home/m%0ay";
URIish u = new URIish(str);
assertEquals("file", u.getScheme());
assertFalse(u.isRemote());
assertEquals("/home/m%0ay", u.getRawPath());
assertEquals("/home/m\ny", u.getPath());
assertEquals("file:///home/m%0ay", u.toString());
assertEquals("file:///home/m%0ay", u.toASCIIString());
assertEquals(u, new URIish(str));
}
@Test
public void testURIEncode_unicode() throws Exception {
final String str = "file:///home/m%c3%a5y";
URIish u = new URIish(str);
assertEquals("file", u.getScheme());
assertFalse(u.isRemote());
assertEquals("/home/m%c3%a5y", u.getRawPath());
assertEquals("/home/m\u00e5y", u.getPath());
assertEquals("file:///home/m%c3%a5y", u.toString());
assertEquals("file:///home/m%c3%a5y", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -154,8 +205,10 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("file", u.getScheme()); assertEquals("file", u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals("D:/m y", u.getRawPath());
assertEquals("D:/m y", u.getPath()); assertEquals("D:/m y", u.getPath());
assertEquals(str, u.toString()); assertEquals("file:///D:/m y", u.toString());
assertEquals("file:///D:/m%20y", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -166,8 +219,10 @@ public class URIishTest {
assertEquals("git", u.getScheme()); assertEquals("git", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals("/home/m y", u.getRawPath());
assertEquals("/home/m y", u.getPath()); assertEquals("/home/m y", u.getPath());
assertEquals(str, u.toString()); assertEquals("git://example.com/home/m y", u.toString());
assertEquals("git://example.com/home/m%20y", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -178,9 +233,11 @@ public class URIishTest {
assertEquals("git", u.getScheme()); assertEquals("git", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals("/home/m y", u.getRawPath());
assertEquals("/home/m y", u.getPath()); assertEquals("/home/m y", u.getPath());
assertEquals(333, u.getPort()); assertEquals(333, u.getPort());
assertEquals(str, u.toString()); assertEquals("git://example.com:333/home/m y", u.toString());
assertEquals("git://example.com:333/home/m%20y", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -190,10 +247,12 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("git", u.getScheme()); assertEquals("git", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("D:/m y", u.getRawPath());
assertEquals("D:/m y", u.getPath()); assertEquals("D:/m y", u.getPath());
assertEquals(338, u.getPort()); assertEquals(338, u.getPort());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(str, u.toString()); assertEquals("git://example.com:338/D:/m y", u.toString());
assertEquals("git://example.com:338/D:/m%20y", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -203,10 +262,27 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("git", u.getScheme()); assertEquals("git", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("D:/m y", u.getRawPath());
assertEquals("D:/m y", u.getPath()); assertEquals("D:/m y", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals("git://example.com/D:/m y", u.toString());
assertEquals("git://example.com/D:/m%20y", u.toASCIIString());
assertEquals(u, new URIish(str));
}
@Test
public void testScpStyleNoURIDecoding() throws Exception {
final String str = "example.com:some/p%20ath";
URIish u = new URIish(str);
assertNull(u.getScheme());
assertTrue(u.isRemote());
assertEquals("some/p%20ath", u.getRawPath());
assertEquals("some/p%20ath", u.getPath());
assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort());
assertEquals(str, u.toString()); assertEquals(str, u.toString());
assertEquals(str, u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -216,10 +292,12 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("some/p ath", u.getRawPath());
assertEquals("some/p ath", u.getPath()); assertEquals("some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toString()); assertEquals(str, u.toString());
assertEquals(str, u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -229,10 +307,12 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath()); assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toString()); assertEquals(str, u.toString());
assertEquals(str, u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -242,11 +322,13 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("some/p ath", u.getRawPath());
assertEquals("some/p ath", u.getPath()); assertEquals("some/p ath", u.getPath());
assertEquals("user", u.getUser()); assertEquals("user", u.getUser());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toString()); assertEquals(str, u.toString());
assertEquals(str, u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -256,10 +338,12 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("git+ssh", u.getScheme()); assertEquals("git+ssh", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath()); assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toString()); assertEquals("git+ssh://example.com/some/p ath", u.toString());
assertEquals("git+ssh://example.com/some/p%20ath", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -269,10 +353,12 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("ssh+git", u.getScheme()); assertEquals("ssh+git", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath()); assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toString()); assertEquals("ssh+git://example.com/some/p ath", u.toString());
assertEquals("ssh+git://example.com/some/p%20ath", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -282,10 +368,12 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("ssh", u.getScheme()); assertEquals("ssh", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath()); assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toString()); assertEquals("ssh://example.com/some/p ath", u.toString());
assertEquals("ssh://example.com/some/p%20ath", u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -295,12 +383,15 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("ssh", u.getScheme()); assertEquals("ssh", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath()); assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals("user", u.getUser()); assertEquals("user", u.getUser());
assertNull(u.getPass()); assertNull(u.getPass());
assertEquals(33, u.getPort()); assertEquals(33, u.getPort());
assertEquals(str, u.toString()); assertEquals("ssh://user@example.com:33/some/p ath", u.toString());
assertEquals("ssh://user@example.com:33/some/p%20ath",
u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -310,13 +401,18 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("ssh", u.getScheme()); assertEquals("ssh", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath()); assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals("user", u.getUser()); assertEquals("user", u.getUser());
assertEquals("pass", u.getPass()); assertEquals("pass", u.getPass());
assertEquals(33, u.getPort()); assertEquals(33, u.getPort());
assertEquals(str, u.toPrivateString()); assertEquals("ssh://user:pass@example.com:33/some/p ath",
u.toPrivateString());
assertEquals("ssh://user:pass@example.com:33/some/p%20ath",
u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString()); assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -326,13 +422,62 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("ssh", u.getScheme()); assertEquals("ssh", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath()); assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertEquals("DOMAIN\\user", u.getUser()); assertEquals("DOMAIN\\user", u.getUser());
assertEquals("pass", u.getPass()); assertEquals("pass", u.getPass());
assertEquals(33, u.getPort()); assertEquals(33, u.getPort());
assertEquals(str, u.toPrivateString()); assertEquals("ssh://DOMAIN\\user:pass@example.com:33/some/p ath",
u.toPrivateString());
assertEquals("ssh://DOMAIN\\user:pass@example.com:33/some/p%20ath",
u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str));
}
@Test
public void testSshProtoWithEscapedADUserPassAndPort() throws Exception {
final String str = "ssh://DOMAIN%5c\u00fcser:pass@example.com:33/some/p ath";
URIish u = new URIish(str);
assertEquals("ssh", u.getScheme());
assertTrue(u.isRemote());
assertEquals("/some/p ath", u.getRawPath());
assertEquals("/some/p ath", u.getPath());
assertEquals("example.com", u.getHost());
assertEquals("DOMAIN\\\u00fcser", u.getUser());
assertEquals("pass", u.getPass());
assertEquals(33, u.getPort());
assertEquals("ssh://DOMAIN\\\u00fcser:pass@example.com:33/some/p ath",
u.toPrivateString());
assertEquals(
"ssh://DOMAIN\\%c3%bcser:pass@example.com:33/some/p%20ath",
u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str));
}
@Test
public void testURIEncodeDecode() throws Exception {
final String str = "ssh://%3ax%25:%40%41x@example.com:33/some%c3%a5/p%20a th";
URIish u = new URIish(str);
assertEquals("ssh", u.getScheme());
assertTrue(u.isRemote());
assertEquals("/some%c3%a5/p%20a th", u.getRawPath());
assertEquals("/some\u00e5/p a th", u.getPath());
assertEquals("example.com", u.getHost());
assertEquals(":x%", u.getUser());
assertEquals("@Ax", u.getPass());
assertEquals(33, u.getPort());
assertEquals("ssh://%3ax%25:%40Ax@example.com:33/some%c3%a5/p%20a th",
u.toPrivateString());
assertEquals(
"ssh://%3ax%25:%40Ax@example.com:33/some%c3%a5/p%20a%20th",
u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString()); assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -342,13 +487,17 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("git", u.getScheme()); assertEquals("git", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("~some/p ath", u.getRawPath());
assertEquals("~some/p ath", u.getPath()); assertEquals("~some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertNull(u.getUser()); assertNull(u.getUser());
assertNull(u.getPass()); assertNull(u.getPass());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toPrivateString()); assertEquals("git://example.com/~some/p ath", u.toPrivateString());
assertEquals("git://example.com/~some/p%20ath",
u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString()); assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -359,13 +508,16 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("git", u.getScheme()); assertEquals("git", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("~some/p ath", u.getRawPath());
assertEquals("~some/p ath", u.getPath()); assertEquals("~some/p ath", u.getPath());
assertEquals("example.com", u.getHost()); assertEquals("example.com", u.getHost());
assertNull(u.getUser()); assertNull(u.getUser());
assertNull(u.getPass()); assertNull(u.getPass());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toPrivateString()); assertEquals(str, u.toPrivateString());
assertEquals(str, u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString()); assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -375,13 +527,16 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertNull(u.getScheme()); assertNull(u.getScheme());
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertEquals("/~some/p ath", u.getRawPath());
assertEquals("/~some/p ath", u.getPath()); assertEquals("/~some/p ath", u.getPath());
assertNull(u.getHost()); assertNull(u.getHost());
assertNull(u.getUser()); assertNull(u.getUser());
assertNull(u.getPass()); assertNull(u.getPass());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertEquals(str, u.toPrivateString()); assertEquals(str, u.toPrivateString());
assertEquals(str, u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString()); assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
@ -415,6 +570,33 @@ public class URIishTest {
} }
} }
@Test
public void testGetSet() throws Exception {
final String str = "ssh://DOMAIN\\user:pass@example.com:33/some/p ath%20";
URIish u = new URIish(str);
u = u.setHost(u.getHost());
u = u.setPass(u.getPass());
u = u.setPort(u.getPort());
assertEquals("ssh", u.getScheme());
assertTrue(u.isRemote());
u = u.setRawPath(u.getRawPath());
assertEquals("/some/p ath%20", u.getRawPath());
u = u.setPath(u.getPath());
assertEquals("/some/p ath ", u.getRawPath());
assertEquals("/some/p ath ", u.getPath());
assertEquals("example.com", u.getHost());
assertEquals("DOMAIN\\user", u.getUser());
assertEquals("pass", u.getPass());
assertEquals(33, u.getPort());
assertEquals("ssh://DOMAIN\\user:pass@example.com:33/some/p ath ",
u.toPrivateString());
assertEquals("ssh://DOMAIN\\user:pass@example.com:33/some/p%20ath%20",
u.toPrivateASCIIString());
assertEquals(u.setPass(null).toPrivateString(), u.toString());
assertEquals(u.setPass(null).toPrivateASCIIString(), u.toASCIIString());
assertEquals(u, new URIish(str));
}
@Test @Test
public void testGetValidWithEmptySlashDotGitHumanishName() public void testGetValidWithEmptySlashDotGitHumanishName()
throws IllegalArgumentException, URISyntaxException { throws IllegalArgumentException, URISyntaxException {
@ -537,6 +719,7 @@ public class URIishTest {
URIish u = new URIish(str); URIish u = new URIish(str);
assertEquals("http", u.getScheme()); assertEquals("http", u.getScheme());
assertTrue(u.isRemote()); assertTrue(u.isRemote());
assertEquals("/some/path", u.getRawPath());
assertEquals("/some/path", u.getPath()); assertEquals("/some/path", u.getPath());
assertEquals("host.xy", u.getHost()); assertEquals("host.xy", u.getHost());
assertEquals(80, u.getPort()); assertEquals(80, u.getPort());
@ -556,6 +739,27 @@ public class URIishTest {
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
/**
* Exemplify what happens with the special case of encoding '/' as %2F. Web
* services in general parse path components before decoding the characters.
*
* @throws URISyntaxException
*/
@Test
public void testPathSeparator() throws URISyntaxException {
String str = "http://user:secret@host.xy:80/some%2Fpath";
URIish u = new URIish(str);
assertEquals("http", u.getScheme());
assertTrue(u.isRemote());
assertEquals("/some%2Fpath", u.getRawPath());
assertEquals("/some/path", u.getPath());
assertEquals("host.xy", u.getHost());
assertEquals(80, u.getPort());
assertEquals("user", u.getUser());
assertEquals("secret", u.getPass());
assertEquals(u, new URIish(str));
}
@Test @Test
public void testFileProtocol() throws IllegalArgumentException, public void testFileProtocol() throws IllegalArgumentException,
URISyntaxException, IOException { URISyntaxException, IOException {
@ -565,6 +769,7 @@ public class URIishTest {
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertNull(u.getHost()); assertNull(u.getHost());
assertNull(u.getPass()); assertNull(u.getPass());
assertEquals("/a/b.txt", u.getRawPath());
assertEquals("/a/b.txt", u.getPath()); assertEquals("/a/b.txt", u.getPath());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertNull(u.getUser()); assertNull(u.getUser());
@ -586,6 +791,7 @@ public class URIishTest {
assertFalse(u.isRemote()); assertFalse(u.isRemote());
assertNull(u.getHost()); assertNull(u.getHost());
assertNull(u.getPass()); assertNull(u.getPass());
assertEquals("/a/b.txt", u.getRawPath());
assertEquals("/a/b.txt", u.getPath()); assertEquals("/a/b.txt", u.getPath());
assertEquals(-1, u.getPort()); assertEquals(-1, u.getPort());
assertNull(u.getUser()); assertNull(u.getUser());

174
org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java

@ -46,22 +46,26 @@
package org.eclipse.jgit.transport; package org.eclipse.jgit.transport;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.Serializable; import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.BitSet;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.eclipse.jgit.JGitText; import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils; import org.eclipse.jgit.util.StringUtils;
/** /**
* This URI like construct used for referencing Git archives over the net, as * This URI like construct used for referencing Git archives over the net, as
* well as locally stored archives. The most important difference compared to * well as locally stored archives. It is similar to RFC 2396 URI's, but also
* RFC 2396 URI's is that no URI encoding/decoding ever takes place. A space or * support SCP and the malformed file://<path> syntax (as opposed to the correct
* any special character is written as-is. * file:<path> syntax.
*/ */
public class URIish implements Serializable { public class URIish implements Serializable {
/** /**
@ -179,6 +183,8 @@ public class URIish implements Serializable {
private String path; private String path;
private String rawPath;
private String user; private String user;
private String pass; private String pass;
@ -201,19 +207,21 @@ public class URIish implements Serializable {
Matcher matcher = SINGLE_SLASH_FILE_URI.matcher(s); Matcher matcher = SINGLE_SLASH_FILE_URI.matcher(s);
if (matcher.matches()) { if (matcher.matches()) {
scheme = matcher.group(1); scheme = matcher.group(1);
path = cleanLeadingSlashes(matcher.group(2), scheme); rawPath = cleanLeadingSlashes(matcher.group(2), scheme);
path = unescape(rawPath);
return; return;
} }
matcher = FULL_URI.matcher(s); matcher = FULL_URI.matcher(s);
if (matcher.matches()) { if (matcher.matches()) {
scheme = matcher.group(1); scheme = matcher.group(1);
user = matcher.group(2); user = unescape(matcher.group(2));
pass = matcher.group(3); pass = unescape(matcher.group(3));
host = matcher.group(4); host = unescape(matcher.group(4));
if (matcher.group(5) != null) if (matcher.group(5) != null)
port = Integer.parseInt(matcher.group(5)); port = Integer.parseInt(matcher.group(5));
path = cleanLeadingSlashes( rawPath = cleanLeadingSlashes(
n2e(matcher.group(6)) + n2e(matcher.group(7)), scheme); n2e(matcher.group(6)) + n2e(matcher.group(7)), scheme);
path = unescape(rawPath);
return; return;
} }
matcher = RELATIVE_SCP_URI.matcher(s); matcher = RELATIVE_SCP_URI.matcher(s);
@ -221,7 +229,8 @@ public class URIish implements Serializable {
user = matcher.group(1); user = matcher.group(1);
pass = matcher.group(2); pass = matcher.group(2);
host = matcher.group(3); host = matcher.group(3);
path = matcher.group(4); rawPath = matcher.group(4);
path = rawPath;
return; return;
} }
matcher = ABSOLUTE_SCP_URI.matcher(s); matcher = ABSOLUTE_SCP_URI.matcher(s);
@ -229,17 +238,95 @@ public class URIish implements Serializable {
user = matcher.group(1); user = matcher.group(1);
pass = matcher.group(2); pass = matcher.group(2);
host = matcher.group(3); host = matcher.group(3);
path = matcher.group(4); rawPath = matcher.group(4);
path = rawPath;
return; return;
} }
matcher = LOCAL_FILE.matcher(s); matcher = LOCAL_FILE.matcher(s);
if (matcher.matches()) { if (matcher.matches()) {
path = matcher.group(1); rawPath = matcher.group(1);
path = rawPath;
return; return;
} }
throw new URISyntaxException(s, JGitText.get().cannotParseGitURIish); throw new URISyntaxException(s, JGitText.get().cannotParseGitURIish);
} }
private static String unescape(String s) throws URISyntaxException {
if (s == null)
return null;
if (s.indexOf('%') < 0)
return s;
byte[] bytes;
try {
bytes = s.getBytes(Constants.CHARACTER_ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e); // can't happen
}
byte[] os = new byte[bytes.length];
int j = 0;
for (int i = 0; i < bytes.length; ++i) {
byte c = bytes[i];
if (c == '%') {
if (i + 2 >= bytes.length)
throw new URISyntaxException(s, JGitText.get().cannotParseGitURIish);
int val = (RawParseUtils.parseHexInt4(bytes[i + 1]) << 4)
| RawParseUtils.parseHexInt4(bytes[i + 2]);
os[j++] = (byte) val;
i += 2;
} else
os[j++] = c;
}
return RawParseUtils.decode(os, 0, j);
}
private static final BitSet reservedChars = new BitSet(127);
static {
for (byte b : Constants.encodeASCII("!*'();:@&=+$,/?#[]"))
reservedChars.set(b);
}
/**
* Escape unprintable characters optionally URI-reserved characters
*
* @param s
* The Java String to encode (may contain any character)
* @param escapeReservedChars
* true to escape URI reserved characters
* @param encodeNonAscii
* encode any non-ASCII characters
* @return a URI-encoded string
*/
private static String escape(String s, boolean escapeReservedChars,
boolean encodeNonAscii) {
if (s == null)
return null;
ByteArrayOutputStream os = new ByteArrayOutputStream(s.length());
byte[] bytes;
try {
bytes = s.getBytes(Constants.CHARACTER_ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e); // cannot happen
}
for (int i = 0; i < bytes.length; ++i) {
int b = bytes[i] & 0xFF;
if (b <= 32 || (encodeNonAscii && b > 127) || b == '%'
|| (escapeReservedChars && reservedChars.get(b))) {
os.write('%');
byte[] tmp = Constants.encodeASCII(String.format("%02x",
Integer.valueOf(b)));
os.write(tmp[0]);
os.write(tmp[1]);
} else {
os.write(b);
}
}
byte[] buf = os.toByteArray();
return RawParseUtils.decode(buf, 0, buf.length);
}
private String n2e(String s) { private String n2e(String s) {
if (s == null) if (s == null)
return ""; return "";
@ -272,6 +359,11 @@ public class URIish implements Serializable {
public URIish(final URL u) { public URIish(final URL u) {
scheme = u.getProtocol(); scheme = u.getProtocol();
path = u.getPath(); path = u.getPath();
try {
rawPath = u.toURI().getRawPath();
} catch (URISyntaxException e) {
throw new RuntimeException(e); // Impossible
}
final String ui = u.getUserInfo(); final String ui = u.getUserInfo();
if (ui != null) { if (ui != null) {
@ -291,6 +383,7 @@ public class URIish implements Serializable {
private URIish(final URIish u) { private URIish(final URIish u) {
this.scheme = u.scheme; this.scheme = u.scheme;
this.rawPath = u.rawPath;
this.path = u.path; this.path = u.path;
this.user = u.user; this.user = u.user;
this.pass = u.pass; this.pass = u.pass;
@ -352,6 +445,13 @@ public class URIish implements Serializable {
return path; return path;
} }
/**
* @return path name component
*/
public String getRawPath() {
return rawPath;
}
/** /**
* Return a new URI matching this one, but with a different path. * Return a new URI matching this one, but with a different path.
* *
@ -362,6 +462,22 @@ public class URIish implements Serializable {
public URIish setPath(final String n) { public URIish setPath(final String n) {
final URIish r = new URIish(this); final URIish r = new URIish(this);
r.path = n; r.path = n;
r.rawPath = n;
return r;
}
/**
* Return a new URI matching this one, but with a different (raw) path.
*
* @param n
* the new value for path.
* @return a new URI with the updated value.
* @throws URISyntaxException
*/
public URIish setRawPath(final String n) throws URISyntaxException {
final URIish r = new URIish(this);
r.path = unescape(n);
r.rawPath = n;
return r; return r;
} }
@ -475,14 +591,15 @@ public class URIish implements Serializable {
* @return the URI, including its password field, if any. * @return the URI, including its password field, if any.
*/ */
public String toPrivateString() { public String toPrivateString() {
return format(true); return format(true, false, false);
} }
public String toString() { public String toString() {
return format(false); return format(false, false, false);
} }
private String format(final boolean includePassword) { private String format(final boolean includePassword, boolean escape,
boolean escapeNonAscii) {
final StringBuilder r = new StringBuilder(); final StringBuilder r = new StringBuilder();
if (getScheme() != null) { if (getScheme() != null) {
r.append(getScheme()); r.append(getScheme());
@ -490,17 +607,17 @@ public class URIish implements Serializable {
} }
if (getUser() != null) { if (getUser() != null) {
r.append(getUser()); r.append(escape(getUser(), true, escapeNonAscii));
if (includePassword && getPass() != null) { if (includePassword && getPass() != null) {
r.append(':'); r.append(':');
r.append(getPass()); r.append(escape(getPass(), true, escapeNonAscii));
} }
} }
if (getHost() != null) { if (getHost() != null) {
if (getUser() != null) if (getUser() != null)
r.append('@'); r.append('@');
r.append(getHost()); r.append(escape(getHost(), false, escapeNonAscii));
if (getScheme() != null && getPort() > 0) { if (getScheme() != null && getPort() > 0) {
r.append(':'); r.append(':');
r.append(getPort()); r.append(getPort());
@ -513,12 +630,33 @@ public class URIish implements Serializable {
r.append('/'); r.append('/');
} else if (getHost() != null) } else if (getHost() != null)
r.append(':'); r.append(':');
r.append(getPath()); if (getScheme() != null)
if (escapeNonAscii)
r.append(escape(getPath(), false, escapeNonAscii));
else
r.append(getRawPath());
else
r.append(getPath());
} }
return r.toString(); return r.toString();
} }
/**
* @return the URI as an ASCII string. Password is not included.
*/
public String toASCIIString() {
return format(false, true, true);
}
/**
* @return the URI including password, formatted with only ASCII characters
* such that it will be valid for use over the network.
*/
public String toPrivateASCIIString() {
return format(true, true, true);
}
/** /**
* Get the "humanish" part of the path. Some examples of a 'humanish' part * Get the "humanish" part of the path. Some examples of a 'humanish' part
* for a full path: * for a full path:

Loading…
Cancel
Save