/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.pluginmanager; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import freenet.pluginmanager.PluginManager.PluginProgress; import freenet.support.Logger; public class PluginDownLoaderURL extends PluginDownLoader<URL> { @Override public URL checkSource(String source) throws PluginNotFoundException { try { return new URL(source); } catch (MalformedURLException e) { // Generate a meaningful error message when file not found falls back to a URL. // Maybe it's a file? // If we've reached this point then it doesn't exist. File[] roots = File.listRoots(); for(File f : roots) { if(source.startsWith(f.getName()) && !new File(source).exists()) { throw new PluginNotFoundException("File not found: "+source); } } Logger.error(this, "could not build plugin url for " + source, e); throw new PluginNotFoundException("could not build plugin url for " + source, e); } } @Override InputStream getInputStream(PluginProgress progress) throws IOException { URLConnection urlConnection = getSource().openConnection(); urlConnection.setUseCaches(false); urlConnection.setAllowUserInteraction(false); //urlConnection.connect(); return openConnectionCheckRedirects(urlConnection); } @Override String getPluginName(String source) throws PluginNotFoundException { String name = source.substring(source.lastIndexOf('/') + 1); if (name.endsWith(".url")) { name = name.substring(0, name.length() - 4); } return name; } @Override String getSHA1sum() throws PluginNotFoundException { return null; } @Override String getSHA256sum() throws PluginNotFoundException { return null; } static InputStream openConnectionCheckRedirects(URLConnection c) throws IOException { boolean redir; int redirects = 0; InputStream in = null; do { if (c instanceof HttpURLConnection) { ((HttpURLConnection) c).setInstanceFollowRedirects(false); } // We want to open the input stream before getting headers // because getHeaderField() et al swallow IOExceptions. in = c.getInputStream(); redir = false; if (c instanceof HttpURLConnection) { HttpURLConnection http = (HttpURLConnection) c; int stat = http.getResponseCode(); if (stat >= 300 && stat <= 307 && stat != 306 && stat != HttpURLConnection.HTTP_NOT_MODIFIED) { URL base = http.getURL(); String loc = http.getHeaderField("Location"); URL target = null; if (loc != null) { target = new URL(base, loc); } http.disconnect(); // Redirection should be allowed only for HTTP and HTTPS // and should be limited to 5 redirections at most. if (target == null || !(target.getProtocol().equals("http") || target.getProtocol().equals("https") || target.getProtocol().equals("ftp")) || redirects >= 5) { throw new SecurityException("illegal URL redirect"); } redir = true; c = target.openConnection(); redirects++; in.close(); } } } while (redir); return in; } @Override void tryCancel() { // Do nothing, not supported. } }