From 551b204c245d4861589a0be50f453507e3c72e81 Mon Sep 17 00:00:00 2001 From: Antoine Levy-Lambert Date: Wed, 30 Nov 2005 22:13:24 +0000 Subject: [PATCH] percent encode the relative paths in ManifestClassPath git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@350061 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/tools/ant/launch/Locator.java | 92 ++++++++++++++++++- .../tools/ant/taskdefs/ManifestClassPath.java | 11 ++- .../org/apache/tools/ant/util/FileUtils.java | 86 +---------------- 3 files changed, 104 insertions(+), 85 deletions(-) diff --git a/src/main/org/apache/tools/ant/launch/Locator.java b/src/main/org/apache/tools/ant/launch/Locator.java index eec938ec9..e0632a0dd 100644 --- a/src/main/org/apache/tools/ant/launch/Locator.java +++ b/src/main/org/apache/tools/ant/launch/Locator.java @@ -38,6 +38,37 @@ public final class Locator { * encoding used to represent URIs */ public static String URI_ENCODING = "UTF-8"; + // stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir() + // of the Xerces-J team + // which ASCII characters need to be escaped + private static boolean gNeedEscaping[] = new boolean[128]; + // the first hex character if a character needs to be escaped + private static char gAfterEscaping1[] = new char[128]; + // the second hex character if a character needs to be escaped + private static char gAfterEscaping2[] = new char[128]; + private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + // initialize the above 3 arrays + static { + for (int i = 0; i <= 0x1f; i++) { + gNeedEscaping[i] = true; + gAfterEscaping1[i] = gHexChs[i >> 4]; + gAfterEscaping2[i] = gHexChs[i & 0xf]; + } + gNeedEscaping[0x7f] = true; + gAfterEscaping1[0x7f] = '7'; + gAfterEscaping2[0x7f] = 'F'; + char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', + '|', '\\', '^', '~', '[', ']', '`'}; + int len = escChs.length; + char ch; + for (int i = 0; i < len; i++) { + ch = escChs[i]; + gNeedEscaping[ch] = true; + gAfterEscaping1[ch] = gHexChs[ch >> 4]; + gAfterEscaping2[ch] = gHexChs[ch & 0xf]; + } + } /** * Not instantiable */ @@ -176,7 +207,66 @@ public final class Locator { sb.write(c); } } - return sb.toString("UTF-8"); + return sb.toString(URI_ENCODING); + } + /** + * Encodes an Uri with % characters. + * The URI is escaped + * @param path String to encode. + * @return The encoded string, according to URI norms + * @throws UnsupportedEncodingException if UTF-8 is not available + * @since Ant 1.7 + */ + public static String encodeUri(String path) throws UnsupportedEncodingException { + int i = 0; + int len = path.length(); + int ch = 0; + StringBuffer sb = new StringBuffer(len); + for (; i < len; i++) { + ch = path.charAt(i); + // if it's not an ASCII character, break here, and use UTF-8 encoding + if (ch >= 128) + break; + if (gNeedEscaping[ch]) { + sb.append('%'); + sb.append(gAfterEscaping1[ch]); + sb.append(gAfterEscaping2[ch]); + // record the fact that it's escaped + } + else { + sb.append((char)ch); + } + } + + // we saw some non-ascii character + if (i < len) { + // get UTF-8 bytes for the remaining sub-string + byte[] bytes = null; + byte b; + bytes = path.substring(i).getBytes(URI_ENCODING); + len = bytes.length; + + // for each byte + for (i = 0; i < len; i++) { + b = bytes[i]; + // for non-ascii character: make it positive, then escape + if (b < 0) { + ch = b + 256; + sb.append('%'); + sb.append(gHexChs[ch >> 4]); + sb.append(gHexChs[ch & 0xf]); + } + else if (gNeedEscaping[b]) { + sb.append('%'); + sb.append(gAfterEscaping1[b]); + sb.append(gAfterEscaping2[b]); + } + else { + sb.append((char)b); + } + } + } + return sb.toString(); } /** diff --git a/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java b/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java index 8337b943e..303d19d2a 100644 --- a/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java +++ b/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java @@ -17,10 +17,12 @@ package org.apache.tools.ant.taskdefs; import java.io.File; +import java.io.UnsupportedEncodingException; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.launch.Locator; import org.apache.tools.ant.util.FileUtils; /** @@ -123,10 +125,15 @@ public class ManifestClassPath if (File.separatorChar != '/') { relPath = relPath.replace(File.separatorChar, '/'); } - buffer.append(relPath); if (pathEntry.isDirectory()) { - buffer.append('/'); + relPath = relPath + '/'; + } + try { + relPath = Locator.encodeUri(relPath); + } catch (UnsupportedEncodingException exc) { + throw new BuildException(exc); } + buffer.append(relPath); buffer.append(' '); } diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index 897b5b3cf..dc28b00a4 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -59,37 +59,6 @@ public class FileUtils { static final int BUF_SIZE = 8192; - // stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir() - // of the Xerces-J team - // which ASCII characters need to be escaped - private static boolean gNeedEscaping[] = new boolean[128]; - // the first hex character if a character needs to be escaped - private static char gAfterEscaping1[] = new char[128]; - // the second hex character if a character needs to be escaped - private static char gAfterEscaping2[] = new char[128]; - private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - // initialize the above 3 arrays - static { - for (int i = 0; i <= 0x1f; i++) { - gNeedEscaping[i] = true; - gAfterEscaping1[i] = gHexChs[i >> 4]; - gAfterEscaping2[i] = gHexChs[i & 0xf]; - } - gNeedEscaping[0x7f] = true; - gAfterEscaping1[0x7f] = '7'; - gAfterEscaping2[0x7f] = 'F'; - char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', - '|', '\\', '^', '~', '[', ']', '`'}; - int len = escChs.length; - char ch; - for (int i = 0; i < len; i++) { - ch = escChs[i]; - gNeedEscaping[ch] = true; - gAfterEscaping1[ch] = gHexChs[ch >> 4]; - gAfterEscaping2[ch] = gHexChs[ch & 0xf]; - } - } /** * The granularity of timestamps under FAT. @@ -1048,58 +1017,11 @@ public class FileUtils { sb.append("/"); } path = path.replace('\\', '/'); - - int i = 0; - for (; i < len; i++) { - ch = path.charAt(i); - // if it's not an ASCII character, break here, and use UTF-8 encoding - if (ch >= 128) - break; - if (gNeedEscaping[ch]) { - sb.append('%'); - sb.append(gAfterEscaping1[ch]); - sb.append(gAfterEscaping2[ch]); - // record the fact that it's escaped - } - else { - sb.append((char)ch); - } - } - - // we saw some non-ascii character - if (i < len) { - // get UTF-8 bytes for the remaining sub-string - byte[] bytes = null; - byte b; - try { - bytes = path.substring(i).getBytes(Locator.URI_ENCODING); - } catch (java.io.UnsupportedEncodingException e) { - // should never happen - throw new BuildException(e); - } - len = bytes.length; - - // for each byte - for (i = 0; i < len; i++) { - b = bytes[i]; - // for non-ascii character: make it positive, then escape - if (b < 0) { - ch = b + 256; - sb.append('%'); - sb.append(gHexChs[ch >> 4]); - sb.append(gHexChs[ch & 0xf]); - } - else if (gNeedEscaping[b]) { - sb.append('%'); - sb.append(gAfterEscaping1[b]); - sb.append(gAfterEscaping2[b]); - } - else { - sb.append((char)b); - } - } + try { + sb.append(Locator.encodeUri(path)); + } catch (UnsupportedEncodingException exc) { + throw new BuildException(exc); } - if (isDir && !path.endsWith("/")) { sb.append('/'); }