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: [email protected]
For additional commands, e-mail: [email protected]