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

Reply via email to