mbecke      2003/06/19 16:28:20

  Modified:    httpclient/src/java/org/apache/commons/httpclient URI.java
               httpclient/src/test/org/apache/commons/httpclient
                        TestURI.java
               httpclient release_notes.txt
  Log:
  Updated URI path resolution to conform to 
http://www.apache.org/~fielding/uri/rev-2002/issues.html.
  PR: 20665
  Reviewed by: Adrian Sutton and Oleg Kalnichevski
  
  Revision  Changes    Path
  1.35      +64 -54    
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/URI.java
  
  Index: URI.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/URI.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- URI.java  5 Mar 2003 03:47:25 -0000       1.34
  +++ URI.java  19 Jun 2003 23:28:19 -0000      1.35
  @@ -2923,7 +2923,7 @@
           if (relPath == null || relPath.length == 0) {
               return normalize(basePath);
           } else if (relPath[0] == '/') {
  -            return relPath;
  +            return normalize(relPath);
           } else {
               StringBuffer buff = new StringBuffer(base.length() 
                   + relPath.length);
  @@ -3401,6 +3401,9 @@
   
       /**
        * Normalize the given hier path part.
  +     * 
  +     * <p>Algorithm taken from URI reference parser at 
  +     * http://www.apache.org/~fielding/uri/rev-2002/issues.html.
        *
        * @param path the path to normalize
        * @return the normalized path
  @@ -3413,62 +3416,69 @@
           }
   
           String normalized = new String(path);
  -        boolean endsWithSlash = true;
  -        // precondition
  -        if (!normalized.endsWith("/")) {
  -            normalized += '/';
  -            endsWithSlash = false;
  -        }
  -        if (normalized.endsWith("/./") || normalized.endsWith("/../")) {
  -            endsWithSlash = true;
  -        }
  -        // Resolve occurrences of "/./" in the normalized path
  -        while (true) {
  -            int at = normalized.indexOf("/./");
  -            if (at == -1) {
  -                break;
  +
  +        // If the buffer begins with "./" or "../", the "." or ".." is removed.
  +        if (normalized.startsWith("./")) {
  +            normalized = normalized.substring(1);
  +        } else if (normalized.startsWith("../")) {
  +            normalized = normalized.substring(2);
  +        } else if (normalized.startsWith("..")) {
  +            normalized = normalized.substring(2);
  +        }
  +
  +        // All occurrences of "/./" in the buffer are replaced with "/"
  +        int index = -1;
  +        while ((index = normalized.indexOf("/./")) != -1) {
  +            normalized = normalized.substring(0, index) + 
normalized.substring(index + 2);
  +        }
  +
  +        // If the buffer ends with "/.", the "." is removed.
  +        if (normalized.endsWith("/.")) {
  +            normalized = normalized.substring(0, normalized.length() - 1);
  +        }
  +
  +        int startIndex = 0;
  +
  +        // All occurrences of "/<segment>/../" in the buffer, where ".."
  +        // and <segment> are complete path segments, are iteratively replaced
  +        // with "/" in order from left to right until no matching pattern remains.
  +        // If the buffer ends with "/<segment>/..", that is also replaced
  +        // with "/".  Note that <segment> may be empty.
  +        while ((index = normalized.indexOf("/../", startIndex)) != -1) {
  +            int slashIndex = normalized.lastIndexOf('/', index - 1);
  +            if (slashIndex >= 0) {
  +                normalized = normalized.substring(0, slashIndex) + 
normalized.substring(index + 3);
  +            } else {
  +                startIndex = index + 3;   
               }
  -            normalized = normalized.substring(0, at) 
  -                + normalized.substring(at + 2);
           }
  -        while (true) {
  -            // Resolve occurrences of "//" in the normalized path
  -            int at = normalized.indexOf("//");
  -            if (at != -1) {
  -                normalized = normalized.substring(0, at) 
  -                    + normalized.substring(at + 1);
  -                continue;
  +        if (normalized.endsWith("/..")) {
  +            int slashIndex = normalized.lastIndexOf('/', normalized.length() - 4);
  +            if (slashIndex >= 0) {
  +                normalized = normalized.substring(0, slashIndex + 1);
               }
  -            // Resolve occurrences of "/../" in the normalized path
  -            at = normalized.indexOf("/../");
  -            if (at == -1) {
  +        }
  +
  +        // All prefixes of "<segment>/../" in the buffer, where ".."
  +        // and <segment> are complete path segments, are iteratively replaced
  +        // with "/" in order from left to right until no matching pattern remains.
  +        // If the buffer ends with "<segment>/..", that is also replaced
  +        // with "/".  Note that <segment> may be empty.
  +        while ((index = normalized.indexOf("/../")) != -1) {
  +            int slashIndex = normalized.lastIndexOf('/', index - 1);
  +            if (slashIndex >= 0) {
                   break;
  -            }
  -            if (at == 0) {
  -                // no more higher path level to be normalized
  -                if (!endsWithSlash && normalized.endsWith("/")) {
  -                    normalized =
  -                        normalized.substring(0, normalized.length() - 1);
  -                } else if (endsWithSlash && !normalized.endsWith("/")) {
  -                    normalized = normalized + "/";
  -                }
  -                throw new URIException(URIException.PARSING, new String(path));
  -            }
  -            int backward = normalized.lastIndexOf('/', at - 1);
  -            if (backward == -1) {
  -                // consider the rel_path
  -                normalized = normalized.substring(at + 4);
               } else {
  -                normalized = normalized.substring(0, backward) 
  -                    + normalized.substring(at + 3);
  +                normalized = normalized.substring(index + 3);
               }
           }
  -        if (!endsWithSlash && normalized.endsWith("/")) {
  -            normalized = normalized.substring(0, normalized.length() - 1);
  -        } else if (endsWithSlash && !normalized.endsWith("/")) {
  -            normalized = normalized + "/";
  +        if (normalized.endsWith("/..")) {
  +            int slashIndex = normalized.lastIndexOf('/', normalized.length() - 4);
  +            if (slashIndex < 0) {
  +                normalized = "/";
  +            }
           }
  -        // Set the normalized path that we have completed
  +
           return normalized.toCharArray();
       }
   
  
  
  
  1.4       +8 -10     
jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestURI.java
  
  Index: TestURI.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestURI.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TestURI.java      30 Jan 2003 21:44:56 -0000      1.3
  +++ TestURI.java      19 Jun 2003 23:28:20 -0000      1.4
  @@ -130,12 +130,10 @@
               { "../..", "http", "a", "/", null, null, "http://a/"; },
               { "../../", "http", "a", "/", null, null, "http://a/"; },
               { "../../g", "http", "a", "/g", null, null, "http://a/g"; },
  -            // Abnormal examples
  -            // exception thrown the right below two
  -            // { "../../../g", "http", "a", being-normalized path?, null, null, 
"http://a/../g?"; },
  -            // { "../../../../g", "http", "a", being-normalied path?, null, null, 
"http://a/../../g?"; },
  -            { "/./g", "http", "a", "/./g", null, null, "http://a/./g"; },
  -            { "/../g", "http", "a", "/../g", null, null, "http://a/../g"; },
  +            { "../../../g", "http", "a", "/g", null, null, "http://a/g"; },
  +            { "../../../../g", "http", "a", "/g", null, null, "http://a/g"; },
  +            { "/./g", "http", "a", "/g", null, null, "http://a/g"; },
  +            { "/../g", "http", "a", "/g", null, null, "http://a/g"; },
               { "g.", "http", "a", "/b/c/g.", null, null, "http://a/b/c/g."; },
               { ".g", "http", "a", "/b/c/.g", null, null, "http://a/b/c/.g"; },
               { "g..", "http", "a", "/b/c/g..", null, null, "http://a/b/c/g.."; },
  @@ -152,12 +150,12 @@
               { "g#s/../x", "http", "a", "/b/c/g", null, "s/../x", 
"http://a/b/c/g#s/../x"; }
           };
           for (int i = 0; i < testRelativeURIs.length; i++) {
  -            
               URI testURI = null;
               
               try {
                   testURI = new URI( baseURI, testRelativeURIs[i][0] );
               } catch ( URIException e ) {
  +                e.printStackTrace();
                   fail( 
                       "unable to create URI with relative value(" 
                       + testRelativeURIs[i][0] + "): " + e 
  
  
  
  1.6       +4 -0      jakarta-commons/httpclient/release_notes.txt
  
  Index: release_notes.txt
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/release_notes.txt,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- release_notes.txt 19 Jun 2003 21:09:19 -0000      1.5
  +++ release_notes.txt 19 Jun 2003 23:28:20 -0000      1.6
  @@ -1,5 +1,9 @@
   Changes since Release 2.0 Beta 1:
   
  + * Changed URI to correctly handle path resolution according to 
  +   http://www.apache.org/~fielding/uri/rev-2002/issues.html.  In 
  +   particular dot-segments are removed when not necessary.
  +
    * POST method correctly applies 'application/x-www-form-urlencoded'
      encoding
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to