Browse Source

Refactored URI parsing to detect wrong URIs

There where quite some bugs regarding wrong URI parsing. In order
to solve them the parsing has to be refactored. We now have
specialized regexps for 'scheme://host/...', scp URIs and local
file names. Now we can detect problems while parsing 'git://host:/abc' which
was previously not possible.

Bug: 315571
Bug: 292897
Bug: 307017
Bug: 323571
Bug: 317388
Change-Id: If72576576ebb6b9d9dc8b7e51ddd87c9909e8b62
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
stable-0.10
Christian Halstrick 14 years ago committed by Matthias Sohn
parent
commit
2160c09dd4
  1. 6
      org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java
  2. 102
      org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java

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

@ -447,4 +447,10 @@ public class URIishTest extends TestCase {
assertEquals("secret@pass", u.getPass()); assertEquals("secret@pass", u.getPass());
assertEquals(u, new URIish(str)); assertEquals(u, new URIish(str));
} }
public void testMissingPort() throws URISyntaxException {
final String incorrectSshUrl = "ssh://some-host:/path/to/repository.git";
URIish u = new URIish(incorrectSshUrl);
assertFalse(TransportGitSsh.canHandle(u));
}
} }

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

@ -78,10 +78,10 @@ public class URIish implements Serializable {
private static final String OPT_USER_PWD_P = "(?:([^/:@]+)(?::([^/]+))?@)?"; private static final String OPT_USER_PWD_P = "(?:([^/:@]+)(?::([^/]+))?@)?";
/** /**
* Part of a pattern which matches the optional host part of URIs. Defines * Part of a pattern which matches the host part of URIs. Defines one
* one capturing group containing the host name. * capturing group containing the host name.
*/ */
private static final String OPT_HOST_P = "(?:([^/]+?))?"; private static final String HOST_P = "([^/:]+)";
/** /**
* Part of a pattern which matches the optional port part of URIs. Defines * Part of a pattern which matches the optional port part of URIs. Defines
@ -89,6 +89,12 @@ public class URIish implements Serializable {
*/ */
private static final String OPT_PORT_P = "(?::(\\d+))?"; private static final String OPT_PORT_P = "(?::(\\d+))?";
/**
* Part of a pattern which matches the ~username part (e.g. /~root in
* git://host.xyz/~root/a.git) of URIs. Defines no capturing group.
*/
private static final String USER_HOME_P = "(?:/~(?:[^/]+))";
/** /**
* Part of a pattern which matches the optional drive letter in paths (e.g. * Part of a pattern which matches the optional drive letter in paths (e.g.
* D: in file:///D:/a.txt). Defines no capturing group. * D: in file:///D:/a.txt). Defines no capturing group.
@ -99,7 +105,14 @@ public class URIish implements Serializable {
* Part of a pattern which matches a relative path. Relative paths don't * Part of a pattern which matches a relative path. Relative paths don't
* start with slash or drive letters. Defines no capturing group. * start with slash or drive letters. Defines no capturing group.
*/ */
private static final String OPT_RELATIVE_PATH_P = "(?:\\.\\.)?"; private static final String RELATIVE_PATH_P = "(?:(?:[^/]+/)*[^/]+/?)";
/**
* Part of a pattern which matches a relative or absolute path. Defines no
* capturing group.
*/
private static final String PATH_P = "(" + OPT_DRIVE_LETTER_P + "/?"
+ RELATIVE_PATH_P + ")";
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -108,24 +121,37 @@ public class URIish implements Serializable {
* <code>scheme "://" user_password? hostname? portnumber? path</code> * <code>scheme "://" user_password? hostname? portnumber? path</code>
*/ */
private static final Pattern FULL_URI = Pattern.compile("^" // private static final Pattern FULL_URI = Pattern.compile("^" //
+ "(?:" //
+ SCHEME_P // + SCHEME_P //
+ "(?:" // start a group containing hostname and all options only
// availabe when a hostname is there
+ OPT_USER_PWD_P // + OPT_USER_PWD_P //
+ OPT_HOST_P // + HOST_P //
+ OPT_PORT_P // + OPT_PORT_P //
+ ")?" // + "(" // open a catpuring group the the user-home-dir part
+ "(" + OPT_DRIVE_LETTER_P + OPT_RELATIVE_PATH_P + "/.+" // + (USER_HOME_P + "?") //
+ ")$"); // /anything + "/)" //
+ ")?" // close the optional group containing hostname
+ "(.+)?" //
+ "$");
/**
* A pattern matching the reference to a local file. This may be an absolute
* path (maybe even containing windows drive-letters) or a relative path.
*/
private static final Pattern LOCAL_FILE = Pattern.compile("^" //
+ "(/?" + PATH_P + ")" //
+ "$");
/** /**
* A pattern matching SCP URI's of the form user@host:path/to/repo.git * A pattern matching SCP URI's of the form user@host:path/to/repo.git
*/ */
private static final Pattern SCP_URI = Pattern.compile("^" // private static final Pattern SCP_URI = Pattern.compile("^" //
+ "(?:([^@]+?)@)?" // + OPT_USER_PWD_P //
+ "([^:]+?)" // + HOST_P //
+ ":" // + ":(" //
+ "(.+)" // + ("(?:" + USER_HOME_P + "/)?") //
+ "$"); // + RELATIVE_PATH_P //
+ ")$");
private String scheme; private String scheme;
@ -155,27 +181,49 @@ public class URIish implements Serializable {
host = matcher.group(4); host = 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 = matcher.group(6); path = cleanLeadingSlashes(
if (path.length() >= 3 n2e(matcher.group(6)) + n2e(matcher.group(7)), scheme);
&& path.charAt(0) == '/'
&& path.charAt(2) == ':'
&& (path.charAt(1) >= 'A' && path.charAt(1) <= 'Z'
|| path.charAt(1) >= 'a' && path.charAt(1) <= 'z'))
path = path.substring(1);
else if (scheme != null && path.length() >= 2
&& path.charAt(0) == '/' && path.charAt(1) == '~')
path = path.substring(1);
} else { } else {
matcher = SCP_URI.matcher(s); matcher = SCP_URI.matcher(s);
if (matcher.matches()) { if (matcher.matches()) {
user = matcher.group(1); user = matcher.group(1);
host = matcher.group(2); pass = matcher.group(2);
path = matcher.group(3); host = matcher.group(3);
path = matcher.group(4);
} else {
matcher = LOCAL_FILE.matcher(s);
if (matcher.matches()) {
path = matcher.group(1);
} else } else
throw new URISyntaxException(s, JGitText.get().cannotParseGitURIish); throw new URISyntaxException(s,
JGitText.get().cannotParseGitURIish);
}
} }
} }
private String n2e(String s) {
if (s == null)
return "";
else
return s;
}
// takes care to cut of a leading slash if a windows drive letter or a
// user-home-dir specifications are
private String cleanLeadingSlashes(String p, String s) {
if (p.length() >= 3
&& p.charAt(0) == '/'
&& p.charAt(2) == ':'
&& (p.charAt(1) >= 'A' && p.charAt(1) <= 'Z' || p.charAt(1) >= 'a'
&& p.charAt(1) <= 'z'))
return p.substring(1);
else if (s != null && p.length() >= 2 && p.charAt(0) == '/'
&& p.charAt(1) == '~')
return p.substring(1);
else
return p;
}
/** /**
* Construct a URIish from a standard URL. * Construct a URIish from a standard URL.
* *

Loading…
Cancel
Save