JDK-4273532 : toURL() method in File class needs to escape excluded URL characters
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version:
    s8u6,solaris_8u1,1.2.0,1.2.1,1.2.1_04,1.2.2,1.3.0,1.3.1 s8u6,solaris_8u1,1.2.0,1.2.1,1.2.1_04,1.2.2,1.3.0,1.3.1
  • Priority: P2
  • Status: Closed
  • Resolution: Won't Fix
  • OS:
    generic,solaris_2.6,solaris_8,windows_98,windows_nt generic,solaris_2.6,solaris_8,windows_98,windows_nt
  • CPU: generic,x86,sparc
  • Submitted: 1999-09-20
  • Updated: 2004-10-15
  • Resolved: 2002-07-19
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
The File class toURL() method does not escape "excluded" URL
characters when mapping a file path to a file: URL. For example, space
characters or '#' characters etc. should be escaped with a '%' followed by the
hexidecimal encoding of the character.

	See RFC 2396 section 2.4.3.

Name: rlT66838			Date: 02/15/2000


java version "1.2.2"
HotSpot VM (1.0.1, mixed mode, build g)

1. Make directory, which name containts "!" sign and go to it.
2. Create java file like:
import java.net.*;
import java.io.*;
public class q
{
    public q()
    {
        try {
            URL u = getClass().getResource("myresources");
            System.out.println("" + u);
            InputStream in = u.openStream();
            System.out.println("" + in);
            InputStreamReader inr = new InputStreamReader(in);
         } catch (Throwable t)
        {
            t.printStackTrace();
        }
    }
    
    public static void main(String args[])
    {
        q qq = new q();
    }
}

3. Create file named "myresources"
4. Place q.class and myresources to JAR file, by example "test.jar"
5. Run java -classpath test.jar q
6. Look at console:
jar:file:/M:/test/!/test.jar!/myresources
java.util.zip.ZipException: error in opening zip file
        at java.util.zip.ZipFile.open(Native Method)
        at java.util.zip.ZipFile.<init>(ZipFile.java:69)
        at java.util.jar.JarFile.<init>(JarFile.java:71)
        at java.util.jar.JarFile.<init>(JarFile.java:58)
        at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:76)
        at sun.net.www.protocol.jar.JarURLConnection.connect
(JarURLConnection.java:92)
        at sun.net.www.protocol.jar.JarURLConnection.getInputStream
(JarURLConnection.java:
112)
        at java.net.URL.openStream(URL.java:818)
        at q.<init>(q.java:10)
        at q.main(q.java:21)

7. Place all files in, by example, "test" directory.
Run again. All is OK.

Problem occurs because "!" is Jar resource delimiter sign, and I think
that either "!" must not be resource delimiter sign, or
JarURLConnection::getResource() needed to be changed.
(Review ID: 101275)
======================================================================
###@###.### 10/15/04 18:46 GMT

Comments
SUGGESTED FIX src/share/classes/java/io/File.java: public URL toURL() throws MalformedURLException { String path = getAbsolutePath(); path = ParseUtil.encodePath(path, isDirectory()); return new URL("file", "", path); } src/share/classes/sun/net/www/ParseUtil.java: static BitSet encodedInPath; static { encodedInPath = new BitSet(256); // Set the bits corresponding to characters that are encoded in the // path component of a URI. // These characters are reserved in the path segment as described in // RFC2396 section 3.3. encodedInPath.set('='); encodedInPath.set(';'); encodedInPath.set('?'); encodedInPath.set('/'); // These characters are defined as excluded in RFC2396 section 2.4.3 // and must be escaped if they occur in the data part of a URI. encodedInPath.set('#'); encodedInPath.set(' '); encodedInPath.set('<'); encodedInPath.set('>'); encodedInPath.set('%'); encodedInPath.set('"'); encodedInPath.set('{'); encodedInPath.set('}'); encodedInPath.set('|'); encodedInPath.set('\\'); encodedInPath.set('^'); encodedInPath.set('['); encodedInPath.set(']'); encodedInPath.set('`'); // US ASCII control characters 00-1F and 7F. for (int i=0; i<32; i++) encodedInPath.set(i); encodedInPath.set(127); } /** * Constructs an encoded version of the specified path string suitable * for use in the construction of a URL. * * If the path does not start with a '/' then a '/' is prepended. If * <tt>directory</tt> is <tt>true</tt> then a '/' is appended to the * specified path. * * A path separator is replaced by a forward slash. The string is UTF8 * encoded. The % escape sequence is used for characters that are above * 0x7F or those defined in RFC2396 as reserved or excluded in the path * component of a URL. */ public static String encodePath(String path, boolean directory) { StringBuffer sb = new StringBuffer(); int n = path.length(); for (int i=0; i<n; i++) { char c = path.charAt(i); if (c == File.separatorChar) sb.append('/'); else { if (c <= 0x007F) { if (encodedInPath.get(c)) escape(sb, c); else sb.append(c); } else if (c > 0x07FF) { escape(sb, (char)(0xE0 | ((c >> 12) & 0x0F))); escape(sb, (char)(0x80 | ((c >> 6) & 0x3F))); escape(sb, (char)(0x80 | ((c >> 0) & 0x3F))); } else { escape(sb, (char)(0xC0 | ((c >> 6) & 0x1F))); escape(sb, (char)(0x80 | ((c >> 0) & 0x3F))); } } } path = sb.toString(); if (!path.startsWith("/")) { path = "/" + path; } if (!path.endsWith("/") && directory) { path = path + "/"; } return path; } /** * Appends the URL escape sequence for the specified char to the * specified StringBuffer. */ private static void escape(StringBuffer s, char c) { s.append('%'); s.append(Character.forDigit((c >> 4) & 0xF, 16)); s.append(Character.forDigit(c & 0xF, 16)); }
11-06-2004

PUBLIC COMMENTS The File class toURL() method does not escape illegal URL characters when mapping a file path to a file: URL.
10-06-2004

WORK AROUND Use file.toURI().toURL(). ###@###.### 2002-07-19
19-07-2002

EVALUATION File.toURL now uses code in sun.net.www.ParseUtil to escape reserved and excluded characters in the path. The path is UTF-8 encoded as well. michael.mccloskey@eng 2000-02-24 We could not go ahead with this fix because of compatibility. Use File.toURI().toURL(). ###@###.### 2002-07-19
24-02-2000