Author: markt Date: Thu Aug 2 14:26:40 2018 New Revision: 1837319 URL: http://svn.apache.org/viewvc?rev=1837319&view=rev Log: Back-port static URL decode methods.
Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/LocalStrings.properties tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/LocalStrings.properties?rev=1837319&r1=1837318&r2=1837319&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/LocalStrings.properties (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/LocalStrings.properties Thu Aug 2 14:26:40 2018 @@ -15,3 +15,7 @@ b2cConverter.unknownEncoding=The character encoding [{0}] is not supported c2bConverter.recycleFailed=Failed to recycle the C2B Converter. Creating new BufferedWriter, WriteConvertor and IntermediateOutputStream. + +uDecoder.urlDecode.conversionError=Failed to decode [{0}] using character set [{1}] +uDecoder.urlDecode.missingDigit=Failed to decode [{0}] because the % character must be followed by two hexademical digits +uDecoder.convertHexDigit.notHex=[{0}] is not a hexadecimal digit Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java?rev=1837319&r1=1837318&r2=1837319&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java Thu Aug 2 14:26:40 2018 @@ -16,8 +16,13 @@ */ package org.apache.tomcat.util.buf; +import java.io.ByteArrayOutputStream; import java.io.CharConversionException; import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; + +import org.apache.tomcat.util.res.StringManager; /** * All URL decoding happens here. This way we can reuse, review, optimize @@ -29,6 +34,8 @@ import java.io.IOException; */ public final class UDecoder { + private static final StringManager sm = StringManager.getManager(UDecoder.class); + public static final boolean ALLOW_ENCODED_SLASH = Boolean.parseBoolean(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false")); @@ -324,6 +331,100 @@ public final class UDecoder { } + /** + * Decode and return the specified URL-encoded String. + * When the byte array is converted to a string, UTF-8 is used. This may + * be different than some other servers. It is assumed the string is not a + * query string. + * + * @param str The url-encoded string + * @return the decoded string + * @exception IllegalArgumentException if a '%' character is not followed + * by a valid 2-digit hexadecimal number + */ + public static String URLDecode(String str) { + return URLDecode(str, B2CConverter.UTF_8); + } + + + /** + * Decode and return the specified URL-encoded String. It is assumed the + * string is not a query string. + * + * @param str The url-encoded string + * @param charset The character encoding to use; if null, UTF-8 is used. + * @return the decoded string + * @exception IllegalArgumentException if a '%' character is not followed + * by a valid 2-digit hexadecimal number + */ + public static String URLDecode(String str, Charset charset) { + if (str == null) { + return null; + } + + if (str.indexOf('%') == -1) { + // No %nn sequences, so return string unchanged + return str; + } + + if (charset == null) { + charset = B2CConverter.UTF_8; + } + + /* + * Decoding is required. + * + * Potential complications: + * - The source String may be partially decoded so it is not valid to + * assume that the source String is ASCII. + * - Have to process as characters since there is no guarantee that the + * byte sequence for '%' is going to be the same in all character + * sets. + * - We don't know how many '%nn' sequences are required for a single + * character. It varies between character sets and some use a variable + * length. + */ + + // This isn't perfect but it is a reasonable guess for the size of the + // array required + ByteArrayOutputStream baos = new ByteArrayOutputStream(str.length() * 2); + + OutputStreamWriter osw = new OutputStreamWriter(baos, charset); + + char[] sourceChars = str.toCharArray(); + int len = sourceChars.length; + int ix = 0; + + try { + while (ix < len) { + char c = sourceChars[ix++]; + if (c == '%') { + osw.flush(); + if (ix + 2 > len) { + throw new IllegalArgumentException( + sm.getString("uDecoder.urlDecode.missingDigit", str)); + } + char c1 = sourceChars[ix++]; + char c2 = sourceChars[ix++]; + if (isHexDigit(c1) && isHexDigit(c2)) { + baos.write(x2c(c1, c2)); + } else { + throw new IllegalArgumentException( + sm.getString("uDecoder.urlDecode.missingDigit", str)); + } + } else { + osw.append(c); + } + } + osw.flush(); + + return baos.toString(charset.name()); + } catch (IOException ioe) { + throw new IllegalArgumentException( + sm.getString("uDecoder.urlDecode.conversionError", str, charset.name()), ioe); + } + } + private static boolean isHexDigit( int c ) { return ( ( c>='0' && c<='9' ) || --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org