]> source.dussan.org Git - jgit.git/commitdiff
Refactored URI parsing to detect wrong URIs 90/1690/5
authorChristian Halstrick <christian.halstrick@sap.com>
Wed, 6 Oct 2010 15:29:25 +0000 (17:29 +0200)
committerMatthias Sohn <matthias.sohn@sap.com>
Fri, 8 Oct 2010 09:12:09 +0000 (11:12 +0200)
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>
org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java

index 88651b75e6973ff1988e8a013956f1d3a13915d5..6a53810d0790af46ce3af024c0b0e6ffb05a50f3 100644 (file)
@@ -447,4 +447,10 @@ public class URIishTest extends TestCase {
                assertEquals("secret@pass", u.getPass());
                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));
+       }
 }
index 3c044fe6759b94f58e49faba5d7d28c3423fbadb..82f80c547e5bd0ccc4ff35f66bfbdf71802ffb78 100644 (file)
@@ -78,10 +78,10 @@ public class URIish implements Serializable {
        private static final String OPT_USER_PWD_P = "(?:([^/:@]+)(?::([^/]+))?@)?";
 
        /**
-        * Part of a pattern which matches the optional host part of URIs. Defines
-        * one capturing group containing the host name.
+        * Part of a pattern which matches the host part of URIs. Defines one
+        * 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
@@ -89,6 +89,12 @@ public class URIish implements Serializable {
         */
        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.
         * 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
         * 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;
 
@@ -108,24 +121,37 @@ public class URIish implements Serializable {
         * <code>scheme "://" user_password? hostname? portnumber? path</code>
         */
        private static final Pattern FULL_URI = Pattern.compile("^" //
-                       + "(?:" //
                        + SCHEME_P //
+                       + "(?:" // start a group containing hostname and all options only
+                                       // availabe when a hostname is there
                        + OPT_USER_PWD_P //
-                       + OPT_HOST_P //
+                       + HOST_P //
                        + OPT_PORT_P //
-                       + ")?" //
-                       + "(" + OPT_DRIVE_LETTER_P + OPT_RELATIVE_PATH_P + "/.+" //
-                       + ")$"); // /anything
+                       + "(" // open a catpuring group the the user-home-dir part
+                       + (USER_HOME_P + "?") //
+                       + "/)" //
+                       + ")?" // 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
         */
        private static final Pattern SCP_URI = Pattern.compile("^" //
-                       + "(?:([^@]+?)@)?" //
-                       + "([^:]+?)" //
-                       + ":" //
-                       + "(.+)" //
-                       + "$"); //
+                       + OPT_USER_PWD_P //
+                       + HOST_P //
+                       + ":(" //
+                       + ("(?:" + USER_HOME_P + "/)?") //
+                       + RELATIVE_PATH_P //
+                       + ")$");
 
        private String scheme;
 
@@ -155,27 +181,49 @@ public class URIish implements Serializable {
                        host = matcher.group(4);
                        if (matcher.group(5) != null)
                                port = Integer.parseInt(matcher.group(5));
-                       path = matcher.group(6);
-                       if (path.length() >= 3
-                       && 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);
+                       path = cleanLeadingSlashes(
+                                       n2e(matcher.group(6)) + n2e(matcher.group(7)), scheme);
                } else {
                        matcher = SCP_URI.matcher(s);
                        if (matcher.matches()) {
                                user = matcher.group(1);
-                               host = matcher.group(2);
-                               path = matcher.group(3);
-                       } else
-                               throw new URISyntaxException(s, JGitText.get().cannotParseGitURIish);
+                               pass = matcher.group(2);
+                               host = matcher.group(3);
+                               path = matcher.group(4);
+                       } else {
+                               matcher = LOCAL_FILE.matcher(s);
+                               if (matcher.matches()) {
+                                       path = matcher.group(1);
+                               } else
+                                       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.
         *