Index: src/main/java/java/net/URLStreamHandler.java =================================================================== --- src/main/java/java/net/URLStreamHandler.java (revision 512320) +++ src/main/java/java/net/URLStreamHandler.java (working copy) @@ -20,6 +20,7 @@ import java.io.IOException; import org.apache.harmony.luni.util.Msg; +import org.apache.harmony.luni.util.URLUtil; /** * The abstract superclass of all classes that implement Protocol Handler. @@ -227,27 +228,7 @@ if (canonicalize) { // modify file if there's any relative referencing - int dirIndex; - while ((dirIndex = file.indexOf("/./")) >= 0) { //$NON-NLS-1$ - file = file.substring(0, dirIndex + 1) - + file.substring(dirIndex + 3); - } - if (file.endsWith("/.")) { //$NON-NLS-1$ - file = file.substring(0, file.length() - 1); - } - while ((dirIndex = file.indexOf("/../")) >= 0) { //$NON-NLS-1$ - if (dirIndex != 0) { - file = file.substring(0, file - .lastIndexOf('/', dirIndex - 1)) - + file.substring(dirIndex + 3); - } else { - file = file.substring(dirIndex + 3); - } - } - if (file.endsWith("/..") && file.length() > 3) { //$NON-NLS-1$ - file = file.substring(0, file.lastIndexOf('/', - file.length() - 4) + 1); - } + file = URLUtil.canonicalizePath(file); } setURL(u, u.getProtocol(), host, port, authority, userInfo, file, Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java =================================================================== --- src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java (revision 512320) +++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java (working copy) @@ -24,6 +24,7 @@ import java.net.URLStreamHandler; import org.apache.harmony.luni.util.Msg; +import org.apache.harmony.luni.util.URLUtil; public class Handler extends URLStreamHandler { /** @@ -68,10 +69,15 @@ if (spec.indexOf("!/") == -1 && (file.indexOf("!/") == -1)) { //$NON-NLS-1$ //$NON-NLS-2$ throw new NullPointerException(Msg.getString("K01b6")); //$NON-NLS-1$ } - if (spec.charAt(0) == '/') { + if (file.equals("")) { + file = spec; + } else if (spec.charAt(0) == '/') { file = file.substring(0, file.indexOf('!') + 1) + spec; } else { - file = file.substring(0, file.lastIndexOf('/') + 1) + spec; + int idx = file.indexOf('!'); + String tmpFile = file.substring(idx + 1, file.lastIndexOf('/') + 1) + spec; + tmpFile = URLUtil.canonicalizePath(tmpFile); + file = file.substring(0, idx + 1) + tmpFile; } try { // check that the embedded url is valid Index: src/main/java/org/apache/harmony/luni/util/URLUtil.java =================================================================== --- src/main/java/org/apache/harmony/luni/util/URLUtil.java (revision 0) +++ src/main/java/org/apache/harmony/luni/util/URLUtil.java (revision 0) @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.luni.util; + +public final class URLUtil { + + /** + * Canonicalize the path, i.e. remove ".." and "." occurences. + * + * @param path the path to be canonicalized + * @return the canonicalized path + */ + public static String canonicalizePath(String path) { + int dirIndex; + + while ((dirIndex = path.indexOf("/./")) >= 0) { //$NON-NLS-1$ + path = path.substring(0, dirIndex + 1) + + path.substring(dirIndex + 3); + } + + if (path.endsWith("/.")) { //$NON-NLS-1$ + path = path.substring(0, path.length() - 1); + } + + while ((dirIndex = path.indexOf("/../")) >= 0) { //$NON-NLS-1$ + if (dirIndex != 0) { + path = path.substring(0, path + .lastIndexOf('/', dirIndex - 1)) + + path.substring(dirIndex + 3); + } else { + path = path.substring(dirIndex + 3); + } + } + + if (path.endsWith("/..") && path.length() > 3) { //$NON-NLS-1$ + path = path.substring(0, path.lastIndexOf('/', + path.length() - 4) + 1); + } + return path; + } +} Index: src/test/java/tests/api/java/net/URLTest.java =================================================================== --- src/test/java/tests/api/java/net/URLTest.java (revision 512320) +++ src/test/java/tests/api/java/net/URLTest.java (working copy) @@ -326,6 +326,17 @@ } catch (MalformedURLException e) { fail("5 Did not expect the exception " + e); } + + // testing jar protocol with relative path + // to make sure it's not canonicalized + try { + String file = "file:/a!/b/../d"; + u = new URL("jar:" + file); + assertEquals("Wrong file (jar protocol, relative path)", + file, u.getFile()); + } catch (MalformedURLException e) { + fail("Did not expect the exception (jar protocol, relative path)" + e); + } } /** @@ -577,6 +588,45 @@ fail("2 Exception during tests : " + e.getMessage()); } fail("didn't throw the expected MalFormedURLException"); + + // Regression test for HARMONY-3258 + // testing jar context url with relative file + try { + // check that relative path with null context is not canonicalized + String spec = "jar:file:/a!/b/../d"; + URL ctx = null; + u = new URL(ctx, spec); + assertEquals("1 Wrong file (jar protocol, relative path)", + spec, u.getFile()); + + spec = "../d"; + ctx = new URL("jar:file:/a!/b"); + u = new URL(ctx, spec); + assertEquals("2 Wrong file (jar protocol, relative path)", + "file:/a!/d", u.getFile()); + + spec = "../d"; + ctx = new URL("jar:file:/a!/b/c"); + u = new URL(ctx, spec); + assertEquals("3 Wrong file (jar protocol, relative path)", + "file:/a!/d", u.getFile()); + + spec = "../d"; + ctx = new URL("jar:file:/a!/b/c/d"); + u = new URL(ctx, spec); + assertEquals("4 Wrong file (jar protocol, relative path)", + "file:/a!/b/d", u.getFile()); + + // added the real example + spec = "../pdf/PDF.settings"; + ctx = new URL("jar:file:/C:/Program%20Files/Netbeans-5.5/ide7/modules/org-netbeans-modules-utilities.jar!/org/netbeans/modules/utilities/Layer.xml"); + u = new URL(ctx, spec); + assertEquals("5 Wrong file (jar protocol, relative path)", + "file:/C:/Program%20Files/Netbeans-5.5/ide7/modules/org-netbeans-modules-utilities.jar!/org/netbeans/modules/pdf/PDF.settings", + u.getFile()); + } catch (MalformedURLException e) { + fail("Testing jar protocol, relative path failed: " + e); + } } /**