Re: 4523159: suggestion for a bugfix for 13 year old "jars in path with !"
Hi Daniel, Thanks for looking at this old bug. I'm concerned about the approach of looking in the filesystem to determine how to parse the URL. If that's the case, then it's no longer possible to look at just the URL string and determine what it represents. Instead, it's possible that different systems will parse the URL differently depending upon the contents of their filesystems, or that the same system will parse the same URL differently at different times if the contents of its filesystem has changed. That leads toward another, different class of errors. There is clearly a bug here, which is that the '!' character is ambiguous: either it's the separator between the jar filename and the path to the entry within the jar file, or it's part of the jar filename. The solution suggested in the bug report by Michael McMahon (cc'd) is to allow for a quoting or escape mechanism to disambiguate the meaning of the '!' character. Would it be possible to pursue that solution? s'marks On 9/15/15 5:27 AM, Daniel Wilhlem wrote: Hi, Our download manager http://jdownloader.org/ has millions of customers. Some of them also suffered from the 13 year old bug http://bugs.java.com/view_bug.do?bug_id=4523159. The issue happens because '!/' is used as seperator between a jar file and its content in URLStreamHandler and JarURLConnection. I hereby want to suggest our bugfix. It consists of a modified sun.net.www.protocol.jar.Handler and sun.net.www.protocol.jar.JarURLConnection. Instead of searching for '!/' and using the first hit, our customized sun.net.www.protocol.jar.Handler loops through URL.getFile() via indexof and substring and tests if it specifies the actual jar file on disk. In case the path contains '!/' we return a customized sun.net.www.protocol.jar.JarURLConnection that overrides getJarFileURL(),getJarEntry(),getEntryName() to provide the correct information. The one disadvantage of this bugfix is the additional IO introduced by File.exits(), but that can be considered//neglectable/./ Please find attached our customized classes. Best Regards Daniel Wilhelm PS: sean.cof...@oracle.com/sean.cof...@oracle.com told me to post this to net-dev -- --- Daniel Wilhelm CTO, Co-Founder Appwork GmbH T: +49 (911)97923112 (Mo-Fr 9:00 - 17:00 CET) Schwabacherstraße 117, 90763 Fürth, Germany
4523159: suggestion for a bugfix for 13 year old "jars in path with !"
Hi, Our download manager http://jdownloader.org/ has millions of customers. Some of them also suffered from the 13 year old bug http://bugs.java.com/view_bug.do?bug_id=4523159. The issue happens because '!/' is used as seperator between a jar file and its content in URLStreamHandler and JarURLConnection. I hereby want to suggest our bugfix. It consists of a modified sun.net.www.protocol.jar.Handler and sun.net.www.protocol.jar.JarURLConnection. Instead of searching for '!/' and using the first hit, our customized sun.net.www.protocol.jar.Handler loops through URL.getFile() via indexof and substring and tests if it specifies the actual jar file on disk. In case the path contains '!/' we return a customized sun.net.www.protocol.jar.JarURLConnection that overrides getJarFileURL(),getJarEntry(),getEntryName() to provide the correct information. The one disadvantage of this bugfix is the additional IO introduced by File.exits(), but that can be considered//neglectable/./ Please find attached our customized classes. Best Regards Daniel Wilhelm PS: sean.cof...@oracle.com/sean.cof...@oracle.com told me to post this to net-dev -- --- Daniel Wilhelm CTO, Co-Founder Appwork GmbH T: +49 (911)97923112 (Mo-Fr 9:00 - 17:00 CET) Schwabacherstraße 117, 90763 Fürth, Germany public class OracleWorkaroundJarHandler extends sun.net.www.protocol.jar.Handler { @Override protected URLConnection openConnection(final URL url) throws IOException { try { // System.out.println("openConnection:" + url); final String path = url.getFile(); URL jarFileURL = null; int lastIndex = 0; if (path.startsWith("file:")) { while (true) { final int indexOf = path.indexOf(".jar", lastIndex); if (indexOf > 0) { final int index = indexOf + 4; lastIndex = index; final String jarFileName = path.substring(0, index); if (jarFileName.contains("!/")) { final File jarFile; final URL jarURL; try { jarURL = new URL(jarFileName); jarFile = new File(jarURL.toURI()); } catch (Exception e) { e.printStackTrace(); continue; } if (jarFile.exists() && jarFile.isFile()) { jarFileURL = jarURL; break; } } } else { break; } } } if (jarFileURL != null) { lastIndex++;// skip ! final URL finalJarFileURL = jarFileURL; final String entryName; if (++lastIndex != path.length()) { final String tempEntryName = path.substring(lastIndex, path.length()); entryName = sun.net.www.ParseUtil.decode(tempEntryName); } else { entryName = null; } System.out.println("Workaround for URL.openConnection:" + finalJarFileURL + " Entry:" + entryName); return new sun.net.www.protocol.jar.JarURLConnection(url, this) { @Override public URL getJarFileURL() { return finalJarFileURL; } @Override public JarEntry getJarEntry() throws IOException { return getJarFile().getJarEntry(getEntryName()); } @Override public String getEntryName() { return entryName; } }; } } catch (final Throwable e) { e.printStackTrace(); } return super.openConnection(url); } }