Index: src/java/org/apache/commons/httpclient/URI.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/URI.java,v
retrieving revision 1.34
diff -u -r1.34 URI.java
--- src/java/org/apache/commons/httpclient/URI.java 5 Mar 2003 03:47:25 -0000 1.34
+++ src/java/org/apache/commons/httpclient/URI.java 10 Jun 2003 22:44:14 -0000
@@ -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.
+ *
+ *
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 "//../" in the buffer, where ".."
+ // and are complete path segments, are iteratively replaced
+ // with "/" in order from left to right until no matching pattern remains.
+ // If the buffer ends with "//..", that is also replaced
+ // with "/". Note that 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 "/../" in the buffer, where ".."
+ // and are complete path segments, are iteratively replaced
+ // with "/" in order from left to right until no matching pattern remains.
+ // If the buffer ends with "/..", that is also replaced
+ // with "/". Note that 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();
}
Index: src/test/org/apache/commons/httpclient/TestURI.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestURI.java,v
retrieving revision 1.3
diff -u -r1.3 TestURI.java
--- src/test/org/apache/commons/httpclient/TestURI.java 30 Jan 2003 21:44:56 -0000 1.3
+++ src/test/org/apache/commons/httpclient/TestURI.java 10 Jun 2003 22:44:17 -0000
@@ -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