Author: maartenc Date: Wed Oct 1 14:52:11 2008 New Revision: 700941 URL: http://svn.apache.org/viewvc?rev=700941&view=rev Log: FIX: Can't download files containing space or + in their names by HTTP (IVY-923)
Modified: ant/ivy/core/trunk/CHANGES.txt ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/AbstractURLHandler.java ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/BasicURLHandler.java ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/HttpClientHandler.java Modified: ant/ivy/core/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=700941&r1=700940&r2=700941&view=diff ============================================================================== --- ant/ivy/core/trunk/CHANGES.txt (original) +++ ant/ivy/core/trunk/CHANGES.txt Wed Oct 1 14:52:11 2008 @@ -98,6 +98,7 @@ - FIX: Maven Pom reader doesn't handle optional dependencies correctly in some instances (IVY-926) (thanks to Phil Messenger) - FIX: ivy:settings doesn't work if id is a property (IVY-925) - FIX: HttpClientHandler hanging in certain cases (IVY-930) (thanks to Scott Hebert) +- FIX: Can't download files containing space or + in their names by HTTP (IVY-923) 2.0.0-rc1 ===================================== Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/AbstractURLHandler.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/AbstractURLHandler.java?rev=700941&r1=700940&r2=700941&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/AbstractURLHandler.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/AbstractURLHandler.java Wed Oct 1 14:52:11 2008 @@ -17,12 +17,18 @@ */ package org.apache.ivy.util.url; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.net.HttpURLConnection; +import java.util.regex.Pattern; import java.io.IOException; public abstract class AbstractURLHandler implements URLHandler { + private static final Pattern ESCAPE_PATTERN = Pattern.compile("%25([0-9a-fA-F][0-9a-fA-F])"); + // the request method to use. TODO: don't use a static here private static int requestMethod = REQUEST_METHOD_HEAD; @@ -79,4 +85,38 @@ public int getRequestMethod() { return requestMethod; } + + protected String normalizeToString(URL url) throws IOException { + if (!"http".equals(url.getProtocol()) && !"https".equals(url.getProtocol())) { + return url.toExternalForm(); + } + + try { + URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), + url.getPort(), url.getPath(), url.getQuery(), url.getRef()); + + // it is possible that the original url was already (partial) escaped, + // so we must unescape all '%' followed by 2 hexadecimals... + String uriString = uri.toString(); + + // manually escape the '+' character + uriString = uriString.replaceAll("\\+", "%2B"); + + return ESCAPE_PATTERN.matcher(uriString).replaceAll("%$1"); + } catch (URISyntaxException e) { + IOException ioe = new MalformedURLException("Couldn't convert '" + + url.toString() + "' to a valid URI"); + ioe.initCause(e); + throw ioe; + } + } + + protected URL normalizeToURL(URL url) throws IOException { + if (!"http".equals(url.getProtocol()) && !"https".equals(url.getProtocol())) { + return url; + } + + return new URL(normalizeToString(url)); + } + } Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/BasicURLHandler.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/BasicURLHandler.java?rev=700941&r1=700940&r2=700941&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/BasicURLHandler.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/BasicURLHandler.java Wed Oct 1 14:52:11 2008 @@ -25,13 +25,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; -import java.util.regex.Pattern; import org.apache.ivy.Ivy; import org.apache.ivy.util.CopyProgressListener; @@ -42,8 +38,6 @@ * */ public class BasicURLHandler extends AbstractURLHandler { - - private static final Pattern ESCAPE_PATTERN = Pattern.compile("%25([0-9a-fA-F][0-9a-fA-F])"); private static final int BUFFER_SIZE = 64 * 1024; @@ -70,7 +64,7 @@ public URLInfo getURLInfo(URL url, int timeout) { URLConnection con = null; try { - url = normalize(url); + url = normalizeToURL(url); con = url.openConnection(); con.setRequestProperty("User-Agent", "Apache Ivy/" + Ivy.getIvyVersion()); if (con instanceof HttpURLConnection) { @@ -101,26 +95,6 @@ return UNAVAILABLE; } - private URL normalize(URL url) throws IOException { - if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) { - try { - URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), - url.getPort(), url.getPath(), url.getQuery(), url.getRef()); - - // it is possible that the original url was already (partial) escaped, - // so we must unescape all '%' followed by 2 hexadecimals... - String uriString = uri.toString(); - url = new URL(ESCAPE_PATTERN.matcher(uriString).replaceAll("%$1")); - } catch (URISyntaxException e) { - IOException ioe = new MalformedURLException("Couldn't convert '" - + url.toString() + "' to a valid URI"); - ioe.initCause(e); - throw ioe; - } - } - return url; - } - private boolean checkStatusCode(URL url, HttpURLConnection con) throws IOException { int status = con.getResponseCode(); if (status == HttpStatus.SC_OK) { @@ -143,7 +117,7 @@ URLConnection conn = null; InputStream inStream = null; try { - url = normalize(url); + url = normalizeToURL(url); conn = url.openConnection(); conn.setRequestProperty("User-Agent", "Apache Ivy/" + Ivy.getIvyVersion()); if (conn instanceof HttpURLConnection) { @@ -175,7 +149,7 @@ public void download(URL src, File dest, CopyProgressListener l) throws IOException { URLConnection srcConn = null; try { - src = normalize(src); + src = normalizeToURL(src); srcConn = src.openConnection(); srcConn.setRequestProperty("User-Agent", "Apache Ivy/" + Ivy.getIvyVersion()); if (srcConn instanceof HttpURLConnection) { @@ -211,7 +185,7 @@ HttpURLConnection conn = null; try { - dest = normalize(dest); + dest = normalizeToURL(dest); conn = (HttpURLConnection) dest.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("PUT"); Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/HttpClientHandler.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/HttpClientHandler.java?rev=700941&r1=700940&r2=700941&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/HttpClientHandler.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/url/HttpClientHandler.java Wed Oct 1 14:52:11 2008 @@ -121,7 +121,7 @@ public void upload(File src, URL dest, CopyProgressListener l) throws IOException { HttpClient client = getClient(dest); - PutMethod put = new PutMethod(dest.toExternalForm()); + PutMethod put = new PutMethod(normalizeToString(dest)); put.setDoAuthentication(useAuthentication(dest) || useProxyAuthentication()); FileInputStream fileStream = null; try { @@ -243,7 +243,7 @@ HttpClient client = getClient(url); client.setTimeout(timeout); - GetMethod get = new GetMethod(url.toExternalForm()); + GetMethod get = new GetMethod(normalizeToString(url)); get.setDoAuthentication(useAuthentication(url) || useProxyAuthentication()); client.executeMethod(get); return get; @@ -253,7 +253,7 @@ HttpClient client = getClient(url); client.setTimeout(timeout); - HeadMethod head = new HeadMethod(url.toExternalForm()); + HeadMethod head = new HeadMethod(normalizeToString(url)); head.setDoAuthentication(useAuthentication(url) || useProxyAuthentication()); client.executeMethod(head); return head;