Changeset 13065


Ignore:
Timestamp:
11/29/10 08:51:04 (13 years ago)
Author:
Mark Evenson
Message:

[backport r13056] Fix problems with #\Space characters in JAR pathnames.

Location:
branches/0.23.x/abcl/src/org/armedbear/lisp
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/0.23.x/abcl/src/org/armedbear/lisp/Load.java

    r12760 r13065  
    154154        if (Utilities.checkZipFile(truename)) {
    155155            String n = truename.getNamestring();
     156            n = Pathname.uriEncode(n);
    156157            if (n.startsWith("jar:")) {
    157158                n = "jar:" + n + "!/" + truename.name.getStringValue() + "."
  • branches/0.23.x/abcl/src/org/armedbear/lisp/Pathname.java

    r13033 r13065  
    3939import java.io.InputStream;
    4040import java.io.FileInputStream;
     41import java.io.UnsupportedEncodingException;
    4142import java.net.MalformedURLException;
    4243import java.net.URI;
     
    4546import java.net.URLDecoder;
    4647import java.net.URLConnection;
     48import java.net.URLEncoder;
    4749import java.util.Enumeration;
    4850import java.util.StringTokenizer;
     
    196198
    197199    public Pathname(URL url) {
    198         if ("file".equals(url.getProtocol())) {
    199             String s = url.getPath();
    200             if (s != null) {
    201                 if (Utilities.isPlatformWindows) {
    202                     //  Workaround for Java's idea of URLs
    203                     //  new (URL"file:///c:/a/b").getPath() --> "/c:/a/b"
    204                     //  whereas we need "c" to be the DEVICE.
    205                     if (s.length() > 2
    206                         && s.charAt(0) == '/'
    207                         && s.charAt(2) == ':') {
    208                         s = s.substring(1);
    209                     }
    210                 }
    211                 init(s);
    212                 return;
    213             }
    214         } else {
    215             init(url.toString());
    216             return;
    217         }
    218         error(new LispError("Failed to construct Pathname from URL: "
    219                             + "'" + url.toString() + "'"));
     200         // URL handling is now buried in init(String), as the URI
     201         // escaping mechanism didn't interact well with '+' and other
     202         // characters.
     203        init(url.toString());
    220204    }
    221205
     
    280264            }
    281265            if (jar.startsWith("jar:file:")) {
    282                 String jarString
    283                     = jar.substring("jar:".length(),
     266                String file
     267                    = jar.substring("jar:file:".length(),
    284268                                    jar.length() - jarSeparator.length());
    285                 // Use URL constructor to normalize Windows' use of device
    286                 URL url = null;
    287                 try {
    288                     url = new URL(jarString);
    289                 } catch (MalformedURLException e) {
    290                     error(new LispError("Failed to parse '" + jarString + "'"
    291                             + " as URL:"
    292                             + e.getMessage()));
    293                 }
    294                 Pathname jarPathname = new Pathname(url);
     269                Pathname jarPathname;
     270                if (file.length() > 0) {
     271                    // Instead of "use URL constructor to normalize Windows' use of device"
     272                    // attempt to shorten the URL to pass through the normal constructor.
     273                    if (Utilities.isPlatformWindows
     274                        && file.charAt(0) == '/'
     275                        && file.charAt(2) == ':'
     276                        && Character.isLetter(file.charAt(1)))
     277                        {
     278                            file = file.substring(1);
     279                        }
     280                    URL url = null;
     281                    URI uri = null;
     282                    try {
     283                        url = new URL("file:" + file);
     284                        uri = url.toURI();
     285                    } catch (MalformedURLException e1) {
     286                        error(new FileError("Failed to create URI from "
     287                                            + "'" + file + "'"
     288                                            + ": " + e1.getMessage()));
     289                    } catch (URISyntaxException e2) {
     290                        error(new FileError("Failed to create URI from "
     291                                            + "'" + file + "'"
     292                                            + ": " + e2.getMessage()));
     293                    }
     294                    String path = uri.getPath();
     295                    if (path == null) {
     296                        // We allow "jar:file:baz.jar!/" to construct a relative
     297                        // path for jar files, so MERGE-PATHNAMES means something.
     298                        jarPathname = new Pathname(uri.getSchemeSpecificPart());
     299                    } else {
     300                        jarPathname = new Pathname(path);
     301                    }
     302                } else {
     303                    jarPathname = new Pathname("");
     304                }
    295305                jars = jars.push(jarPathname);
    296306            } else {
     
    316326        if (separatorIndex > 0 && s.startsWith("jar:")) {
    317327            final String jarURL = s.substring(0, separatorIndex + jarSeparator.length());
    318             Pathname d = new Pathname(jarURL);
     328            URL url = null;
     329            try {
     330                url = new URL(jarURL);
     331            } catch (MalformedURLException ex) {
     332                error(new FileError("Failed to parse URL "
     333                                    + "'" + jarURL + "'"
     334                                    + ex.getMessage()));
     335            }
     336            Pathname d = new Pathname(url);
    319337            if (device instanceof Cons) {
    320338                LispObject[] jars = d.copyToArray();
     
    343361            String scheme = url.getProtocol();
    344362            if (scheme.equals("file")) {
    345                 Pathname p = new Pathname(url.getFile());
     363                URI uri = null;
     364                try {
     365                    uri = url.toURI();
     366                } catch (URISyntaxException ex) {
     367                    error(new FileError("Improper URI syntax for "
     368                                    + "'" + url.toString() + "'"
     369                                    + ": " + ex.toString()));
     370                }
     371                Pathname p = new Pathname(uri.getPath());
    346372                this.host = p.host;
    347373                this.device = p.device;
     
    597623            }
    598624        }
     625        boolean uriEncoded = false;
    599626        if (device == NIL) {
    600627        } else if (device == Keyword.UNSPECIFIC) {
     
    606633                if (!((Pathname)jars[i]).isURL() && i == 0) {
    607634                    sb.append("file:");
    608                 }
    609                 sb.append(((Pathname) jars[i]).getNamestring());
     635                    uriEncoded = true;
     636                }
     637                Pathname jar = (Pathname) jars[i];
     638                String encodedNamestring;
     639                if (uriEncoded) {
     640                    encodedNamestring = uriEncode(jar.getNamestring());
     641                } else {
     642                    encodedNamestring = jar.getNamestring();
     643                }
     644                sb.append(encodedNamestring);
    610645                sb.append("!/");
    611646            }
     
    621656        }
    622657        String directoryNamestring = getDirectoryNamestring();
     658        if (uriEncoded) {
     659            directoryNamestring = uriEncode(directoryNamestring);
     660        }
    623661        if (isJar()) {
    624662            if (directoryNamestring.startsWith("/")) {
     
    636674                return null;
    637675            }
    638             sb.append(n);
     676            if (uriEncoded) {
     677                sb.append(uriEncode(n));
     678            } else {
     679                sb.append(n);
     680            }
    639681        } else if (name == Keyword.WILD) {
    640682            sb.append('*');
     
    651693                    }
    652694                }
    653                 sb.append(t);
     695                if (uriEncoded) {
     696                    sb.append(uriEncode(t));
     697                } else {
     698                    sb.append(t);
     699                }
    654700            } else if (type == Keyword.WILD) {
    655701                sb.append('*');
     
    19712017                if (truename != null
    19722018                    && truename instanceof Pathname) {
    1973                     jars.car = (Pathname)truename;
     2019                    Pathname truePathname = (Pathname)truename;
     2020                    // A jar that is a directory makes no sense, so exit
     2021                    if (truePathname.getNamestring().endsWith("/")) {
     2022                        break jarfile;
     2023                    }
     2024                    jars.car = truePathname;
    19742025                } else {
    19752026                    break jarfile;
     
    19842035            // 3.  JAR with Entry
    19852036            // 4.  JAR in JAR with Entry
     2037
    19862038            ZipFile jarFile = ZipCache.get((Pathname)jars.car());
    19872039            String entryPath = pathname.asEntryPath();
     
    23402392    }
    23412393
     2394    static String uriDecode(String s) {
     2395        try {
     2396            URI uri = new URI(null, null, null, s, null);
     2397            return uri.toASCIIString().substring(1);
     2398        } catch (URISyntaxException e) {}
     2399        return null;  // Error
     2400    }
     2401
     2402    static String uriEncode(String s) {
     2403        // The constructor we use here only allows absolute paths, so
     2404        // we manipulate the input and output correspondingly.
     2405        String u;
     2406        if (!s.startsWith("/")) {
     2407            u = "/" + s;
     2408        } else {
     2409            u = new String(s);
     2410        }
     2411        try {
     2412            URI uri = new URI("file", "", u, "");
     2413            String result = uri.getRawPath();
     2414            if (!s.startsWith("/")) {
     2415                return result.substring(1);
     2416            }
     2417            return result;
     2418        } catch (URISyntaxException e) {
     2419            Debug.assertTrue(false);
     2420        }
     2421        return null; // Error
     2422    }
    23422423}
    23432424
  • branches/0.23.x/abcl/src/org/armedbear/lisp/Utilities.java

    r12612 r13065  
    255255    }
    256256
    257     static String uriEncode(String s) {
    258         try {
    259             URI uri = new URI("?" + s);
    260             return uri.getQuery();
    261         } catch (URISyntaxException e) {}
    262         return null;
    263     }
    264 
    265     static String uriDecode(String s) {
    266         try {
    267             URI uri = new URI(null, null, null, s, null);
    268             return uri.toASCIIString().substring(1);
    269         } catch (URISyntaxException e) {}
    270         return null;  // Error
    271     }
    272    
    273257    static String escapeFormat(String s) {
    274258        return s.replace("~", "~~");
Note: See TracChangeset for help on using the changeset viewer.