Modified: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/util/RequestUtil.java
URL: 
http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/util/RequestUtil.java?rev=641160&r1=641159&r2=641160&view=diff
==============================================================================
--- 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/util/RequestUtil.java
 (original)
+++ 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/util/RequestUtil.java
 Tue Mar 25 22:36:01 2008
@@ -1,509 +1,509 @@
-/*
- * Copyright 1999,2004 The Apache Software Foundation.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.tomcat.servlets.util;
-
-import java.io.UnsupportedEncodingException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.TimeZone;
-
-import javax.servlet.http.Cookie;
-
-
-/**
- * General purpose request parsing and encoding utility methods.
- *
- * @author Craig R. McClanahan
- * @author Tim Tye
- * @version $Revision: 302905 $ $Date: 2004-05-26 18:41:54 +0200 (mer., 26 mai 
2004) $
- */
-
-public final class RequestUtil {
-
-
-    /**
-     * The DateFormat to use for generating readable dates in cookies.
-     */
-    private static SimpleDateFormat format =
-        new SimpleDateFormat(" EEEE, dd-MMM-yy kk:mm:ss zz");
-
-    static {
-        format.setTimeZone(TimeZone.getTimeZone("GMT"));
-    }
-
-
-    /**
-     * Encode a cookie as per RFC 2109.  The resulting string can be used
-     * as the value for a <code>Set-Cookie</code> header.
-     *
-     * @param cookie The cookie to encode.
-     * @return A string following RFC 2109.
-     */
-    public static String encodeCookie(Cookie cookie) {
-
-        StringBuffer buf = new StringBuffer( cookie.getName() );
-        buf.append("=");
-        buf.append(cookie.getValue());
-
-        if (cookie.getComment() != null) {
-            buf.append("; Comment=\"");
-            buf.append(cookie.getComment());
-            buf.append("\"");
-        }
-
-        if (cookie.getDomain() != null) {
-            buf.append("; Domain=\"");
-            buf.append(cookie.getDomain());
-            buf.append("\"");
-        }
-
-        long age = cookie.getMaxAge();
-        if (cookie.getMaxAge() >= 0) {
-            buf.append("; Max-Age=\"");
-            buf.append(cookie.getMaxAge());
-            buf.append("\"");
-        }
-
-        if (cookie.getPath() != null) {
-            buf.append("; Path=\"");
-            buf.append(cookie.getPath());
-            buf.append("\"");
-        }
-
-        if (cookie.getSecure()) {
-            buf.append("; Secure");
-        }
-
-        if (cookie.getVersion() > 0) {
-            buf.append("; Version=\"");
-            buf.append(cookie.getVersion());
-            buf.append("\"");
-        }
-
-        return (buf.toString());
-    }
-
-
-    /**
-     * Filter the specified message string for characters that are sensitive
-     * in HTML.  This avoids potential attacks caused by including JavaScript
-     * codes in the request URL that is often reported in error messages.
-     *
-     * @param message The message string to be filtered
-     */
-    public static String filter(String message) {
-
-        if (message == null)
-            return (null);
-
-        char content[] = new char[message.length()];
-        message.getChars(0, message.length(), content, 0);
-        StringBuffer result = new StringBuffer(content.length + 50);
-        for (int i = 0; i < content.length; i++) {
-            switch (content[i]) {
-            case '<':
-                result.append("&lt;");
-                break;
-            case '>':
-                result.append("&gt;");
-                break;
-            case '&':
-                result.append("&amp;");
-                break;
-            case '"':
-                result.append("&quot;");
-                break;
-            default:
-                result.append(content[i]);
-            }
-        }
-        return (result.toString());
-
-    }
-
-
-    /**
-     * Normalize a relative URI path that may have relative values ("/./",
-     * "/../", and so on ) it it.  <strong>WARNING</strong> - This method is
-     * useful only for normalizing application-generated paths.  It does not
-     * try to perform security checks for malicious input.
-     *
-     * @param path Relative path to be normalized
-     */
-    public static String normalize(String path) {
-
-        if (path == null)
-            return null;
-
-        // Create a place for the normalized path
-        String normalized = path;
-
-        if (normalized.equals("/."))
-            return "/";
-
-        // Add a leading "/" if necessary
-        if (!normalized.startsWith("/"))
-            normalized = "/" + normalized;
-
-        // Resolve occurrences of "//" in the normalized path
-        while (true) {
-            int index = normalized.indexOf("//");
-            if (index < 0)
-                break;
-            normalized = normalized.substring(0, index) +
-                normalized.substring(index + 1);
-        }
-
-        // Resolve occurrences of "/./" in the normalized path
-        while (true) {
-            int index = normalized.indexOf("/./");
-            if (index < 0)
-                break;
-            normalized = normalized.substring(0, index) +
-                normalized.substring(index + 2);
-        }
-
-        // Resolve occurrences of "/../" in the normalized path
-        while (true) {
-            int index = normalized.indexOf("/../");
-            if (index < 0)
-                break;
-            if (index == 0)
-                return (null);  // Trying to go outside our context
-            int index2 = normalized.lastIndexOf('/', index - 1);
-            normalized = normalized.substring(0, index2) +
-                normalized.substring(index + 3);
-        }
-
-        // Return the normalized path that we have completed
-        return (normalized);
-
-    }
-
-
-    /**
-     * Parse the character encoding from the specified content type header.
-     * If the content type is null, or there is no explicit character encoding,
-     * <code>null</code> is returned.
-     *
-     * @param contentType a content type header
-     */
-    public static String parseCharacterEncoding(String contentType) {
-
-        if (contentType == null)
-            return (null);
-        int start = contentType.indexOf("charset=");
-        if (start < 0)
-            return (null);
-        String encoding = contentType.substring(start + 8);
-        int end = encoding.indexOf(';');
-        if (end >= 0)
-            encoding = encoding.substring(0, end);
-        encoding = encoding.trim();
-        if ((encoding.length() > 2) && (encoding.startsWith("\""))
-            && (encoding.endsWith("\"")))
-            encoding = encoding.substring(1, encoding.length() - 1);
-        return (encoding.trim());
-
-    }
-
-
-    /**
-     * Parse a cookie header into an array of cookies according to RFC 2109.
-     *
-     * @param header Value of an HTTP "Cookie" header
-     */
-    public static Cookie[] parseCookieHeader(String header) {
-
-        if ((header == null) || (header.length() < 1))
-            return (new Cookie[0]);
-
-        ArrayList cookies = new ArrayList();
-        while (header.length() > 0) {
-            int semicolon = header.indexOf(';');
-            if (semicolon < 0)
-                semicolon = header.length();
-            if (semicolon == 0)
-                break;
-            String token = header.substring(0, semicolon);
-            if (semicolon < header.length())
-                header = header.substring(semicolon + 1);
-            else
-                header = "";
-            try {
-                int equals = token.indexOf('=');
-                if (equals > 0) {
-                    String name = token.substring(0, equals).trim();
-                    String value = token.substring(equals+1).trim();
-                    cookies.add(new Cookie(name, value));
-                }
-            } catch (Throwable e) {
-                ;
-            }
-        }
-
-        return ((Cookie[]) cookies.toArray(new Cookie[cookies.size()]));
-
-    }
-
-
-    /**
-     * Append request parameters from the specified String to the specified
-     * Map.  It is presumed that the specified Map is not accessed from any
-     * other thread, so no synchronization is performed.
-     * <p>
-     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
-     * individually on the parsed name and value elements, rather than on
-     * the entire query string ahead of time, to properly deal with the case
-     * where the name or value includes an encoded "=" or "&" character
-     * that would otherwise be interpreted as a delimiter.
-     *
-     * @param map Map that accumulates the resulting parameters
-     * @param data Input string containing request parameters
-     *
-     * @exception IllegalArgumentException if the data is malformed
-     */
-    public static void parseParameters(Map map, String data, String encoding)
-        throws UnsupportedEncodingException {
-
-        if ((data != null) && (data.length() > 0)) {
-
-            // use the specified encoding to extract bytes out of the
-            // given string so that the encoding is not lost. If an
-            // encoding is not specified, let it use platform default
-            byte[] bytes = null;
-            try {
-                if (encoding == null) {
-                    bytes = data.getBytes();
-                } else {
-                    bytes = data.getBytes(encoding);
-                }
-            } catch (UnsupportedEncodingException uee) {
-            }
-
-            parseParameters(map, bytes, encoding);
-        }
-
-    }
-
-
-    /**
-     * Decode and return the specified URL-encoded String.
-     * When the byte array is converted to a string, the system default
-     * character encoding is used...  This may be different than some other
-     * servers.
-     *
-     * @param str The url-encoded 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, null);
-
-    }
-
-
-    /**
-     * Decode and return the specified URL-encoded String.
-     *
-     * @param str The url-encoded string
-     * @param enc The encoding to use; if null, the default encoding is used
-     * @exception IllegalArgumentException if a '%' character is not followed
-     * by a valid 2-digit hexadecimal number
-     */
-    public static String URLDecode(String str, String enc) {
-
-        if (str == null)
-            return (null);
-
-        // use the specified encoding to extract bytes out of the
-        // given string so that the encoding is not lost. If an
-        // encoding is not specified, let it use platform default
-        byte[] bytes = null;
-        try {
-            if (enc == null) {
-                bytes = str.getBytes();
-            } else {
-                bytes = str.getBytes(enc);
-            }
-        } catch (UnsupportedEncodingException uee) {}
-
-        return URLDecode(bytes, enc);
-
-    }
-
-
-    /**
-     * Decode and return the specified URL-encoded byte array.
-     *
-     * @param bytes The url-encoded byte array
-     * @exception IllegalArgumentException if a '%' character is not followed
-     * by a valid 2-digit hexadecimal number
-     */
-    public static String URLDecode(byte[] bytes) {
-        return URLDecode(bytes, null);
-    }
-
-
-    /**
-     * Decode and return the specified URL-encoded byte array.
-     *
-     * @param bytes The url-encoded byte array
-     * @param enc The encoding to use; if null, the default encoding is used
-     * @exception IllegalArgumentException if a '%' character is not followed
-     * by a valid 2-digit hexadecimal number
-     */
-    public static String URLDecode(byte[] bytes, String enc) {
-
-        if (bytes == null)
-            return (null);
-
-        int len = bytes.length;
-        int ix = 0;
-        int ox = 0;
-        while (ix < len) {
-            byte b = bytes[ix++];     // Get byte to test
-            if (b == '+') {
-                b = (byte)' ';
-            } else if (b == '%') {
-                b = (byte) ((convertHexDigit(bytes[ix++]) << 4)
-                            + convertHexDigit(bytes[ix++]));
-            }
-            bytes[ox++] = b;
-        }
-        if (enc != null) {
-            try {
-                return new String(bytes, 0, ox, enc);
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-        return new String(bytes, 0, ox);
-
-    }
-
-
-    /**
-     * Convert a byte character value to hexidecimal digit value.
-     *
-     * @param b the character value byte
-     */
-    private static byte convertHexDigit( byte b ) {
-        if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
-        if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
-        if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
-        return 0;
-    }
-
-
-    /**
-     * Put name and value pair in map.  When name already exist, add value
-     * to array of values.
-     *
-     * @param map The map to populate
-     * @param name The parameter name
-     * @param value The parameter value
-     */
-    private static void putMapEntry( Map map, String name, String value) {
-        String[] newValues = null;
-        String[] oldValues = (String[]) map.get(name);
-        if (oldValues == null) {
-            newValues = new String[1];
-            newValues[0] = value;
-        } else {
-            newValues = new String[oldValues.length + 1];
-            System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
-            newValues[oldValues.length] = value;
-        }
-        map.put(name, newValues);
-    }
-
-
-    /**
-     * Append request parameters from the specified String to the specified
-     * Map.  It is presumed that the specified Map is not accessed from any
-     * other thread, so no synchronization is performed.
-     * <p>
-     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
-     * individually on the parsed name and value elements, rather than on
-     * the entire query string ahead of time, to properly deal with the case
-     * where the name or value includes an encoded "=" or "&" character
-     * that would otherwise be interpreted as a delimiter.
-     *
-     * NOTE: byte array data is modified by this method.  Caller beware.
-     *
-     * @param map Map that accumulates the resulting parameters
-     * @param data Input string containing request parameters
-     * @param encoding Encoding to use for converting hex
-     *
-     * @exception UnsupportedEncodingException if the data is malformed
-     */
-    public static void parseParameters(Map map, byte[] data, String encoding)
-        throws UnsupportedEncodingException {
-
-        if (data != null && data.length > 0) {
-            int    pos = 0;
-            int    ix = 0;
-            int    ox = 0;
-            String key = null;
-            String value = null;
-            while (ix < data.length) {
-                byte c = data[ix++];
-                switch ((char) c) {
-                case '&':
-                    value = new String(data, 0, ox, encoding);
-                    if (key != null) {
-                        putMapEntry(map, key, value);
-                        key = null;
-                    }
-                    ox = 0;
-                    break;
-                case '=':
-                    if (key == null) {
-                        key = new String(data, 0, ox, encoding);
-                        ox = 0;
-                    } else {
-                        data[ox++] = c;
-                    }                   
-                    break;  
-                case '+':
-                    data[ox++] = (byte)' ';
-                    break;
-                case '%':
-                    data[ox++] = (byte)((convertHexDigit(data[ix++]) << 4)
-                                    + convertHexDigit(data[ix++]));
-                    break;
-                default:
-                    data[ox++] = c;
-                }
-            }
-            //The last value does not end in '&'.  So save it now.
-            if (key != null) {
-                value = new String(data, 0, ox, encoding);
-                putMapEntry(map, key, value);
-            }
-        }
-
-    }
-
-
-
-}
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.servlets.util;
+
+import java.io.UnsupportedEncodingException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.TimeZone;
+
+import javax.servlet.http.Cookie;
+
+
+/**
+ * General purpose request parsing and encoding utility methods.
+ *
+ * @author Craig R. McClanahan
+ * @author Tim Tye
+ * @version $Revision: 302905 $ $Date: 2004-05-26 18:41:54 +0200 (mer., 26 mai 
2004) $
+ */
+
+public final class RequestUtil {
+
+
+    /**
+     * The DateFormat to use for generating readable dates in cookies.
+     */
+    private static SimpleDateFormat format =
+        new SimpleDateFormat(" EEEE, dd-MMM-yy kk:mm:ss zz");
+
+    static {
+        format.setTimeZone(TimeZone.getTimeZone("GMT"));
+    }
+
+
+    /**
+     * Encode a cookie as per RFC 2109.  The resulting string can be used
+     * as the value for a <code>Set-Cookie</code> header.
+     *
+     * @param cookie The cookie to encode.
+     * @return A string following RFC 2109.
+     */
+    public static String encodeCookie(Cookie cookie) {
+
+        StringBuffer buf = new StringBuffer( cookie.getName() );
+        buf.append("=");
+        buf.append(cookie.getValue());
+
+        if (cookie.getComment() != null) {
+            buf.append("; Comment=\"");
+            buf.append(cookie.getComment());
+            buf.append("\"");
+        }
+
+        if (cookie.getDomain() != null) {
+            buf.append("; Domain=\"");
+            buf.append(cookie.getDomain());
+            buf.append("\"");
+        }
+
+        long age = cookie.getMaxAge();
+        if (cookie.getMaxAge() >= 0) {
+            buf.append("; Max-Age=\"");
+            buf.append(cookie.getMaxAge());
+            buf.append("\"");
+        }
+
+        if (cookie.getPath() != null) {
+            buf.append("; Path=\"");
+            buf.append(cookie.getPath());
+            buf.append("\"");
+        }
+
+        if (cookie.getSecure()) {
+            buf.append("; Secure");
+        }
+
+        if (cookie.getVersion() > 0) {
+            buf.append("; Version=\"");
+            buf.append(cookie.getVersion());
+            buf.append("\"");
+        }
+
+        return (buf.toString());
+    }
+
+
+    /**
+     * Filter the specified message string for characters that are sensitive
+     * in HTML.  This avoids potential attacks caused by including JavaScript
+     * codes in the request URL that is often reported in error messages.
+     *
+     * @param message The message string to be filtered
+     */
+    public static String filter(String message) {
+
+        if (message == null)
+            return (null);
+
+        char content[] = new char[message.length()];
+        message.getChars(0, message.length(), content, 0);
+        StringBuffer result = new StringBuffer(content.length + 50);
+        for (int i = 0; i < content.length; i++) {
+            switch (content[i]) {
+            case '<':
+                result.append("&lt;");
+                break;
+            case '>':
+                result.append("&gt;");
+                break;
+            case '&':
+                result.append("&amp;");
+                break;
+            case '"':
+                result.append("&quot;");
+                break;
+            default:
+                result.append(content[i]);
+            }
+        }
+        return (result.toString());
+
+    }
+
+
+    /**
+     * Normalize a relative URI path that may have relative values ("/./",
+     * "/../", and so on ) it it.  <strong>WARNING</strong> - This method is
+     * useful only for normalizing application-generated paths.  It does not
+     * try to perform security checks for malicious input.
+     *
+     * @param path Relative path to be normalized
+     */
+    public static String normalize(String path) {
+
+        if (path == null)
+            return null;
+
+        // Create a place for the normalized path
+        String normalized = path;
+
+        if (normalized.equals("/."))
+            return "/";
+
+        // Add a leading "/" if necessary
+        if (!normalized.startsWith("/"))
+            normalized = "/" + normalized;
+
+        // Resolve occurrences of "//" in the normalized path
+        while (true) {
+            int index = normalized.indexOf("//");
+            if (index < 0)
+                break;
+            normalized = normalized.substring(0, index) +
+                normalized.substring(index + 1);
+        }
+
+        // Resolve occurrences of "/./" in the normalized path
+        while (true) {
+            int index = normalized.indexOf("/./");
+            if (index < 0)
+                break;
+            normalized = normalized.substring(0, index) +
+                normalized.substring(index + 2);
+        }
+
+        // Resolve occurrences of "/../" in the normalized path
+        while (true) {
+            int index = normalized.indexOf("/../");
+            if (index < 0)
+                break;
+            if (index == 0)
+                return (null);  // Trying to go outside our context
+            int index2 = normalized.lastIndexOf('/', index - 1);
+            normalized = normalized.substring(0, index2) +
+                normalized.substring(index + 3);
+        }
+
+        // Return the normalized path that we have completed
+        return (normalized);
+
+    }
+
+
+    /**
+     * Parse the character encoding from the specified content type header.
+     * If the content type is null, or there is no explicit character encoding,
+     * <code>null</code> is returned.
+     *
+     * @param contentType a content type header
+     */
+    public static String parseCharacterEncoding(String contentType) {
+
+        if (contentType == null)
+            return (null);
+        int start = contentType.indexOf("charset=");
+        if (start < 0)
+            return (null);
+        String encoding = contentType.substring(start + 8);
+        int end = encoding.indexOf(';');
+        if (end >= 0)
+            encoding = encoding.substring(0, end);
+        encoding = encoding.trim();
+        if ((encoding.length() > 2) && (encoding.startsWith("\""))
+            && (encoding.endsWith("\"")))
+            encoding = encoding.substring(1, encoding.length() - 1);
+        return (encoding.trim());
+
+    }
+
+
+    /**
+     * Parse a cookie header into an array of cookies according to RFC 2109.
+     *
+     * @param header Value of an HTTP "Cookie" header
+     */
+    public static Cookie[] parseCookieHeader(String header) {
+
+        if ((header == null) || (header.length() < 1))
+            return (new Cookie[0]);
+
+        ArrayList cookies = new ArrayList();
+        while (header.length() > 0) {
+            int semicolon = header.indexOf(';');
+            if (semicolon < 0)
+                semicolon = header.length();
+            if (semicolon == 0)
+                break;
+            String token = header.substring(0, semicolon);
+            if (semicolon < header.length())
+                header = header.substring(semicolon + 1);
+            else
+                header = "";
+            try {
+                int equals = token.indexOf('=');
+                if (equals > 0) {
+                    String name = token.substring(0, equals).trim();
+                    String value = token.substring(equals+1).trim();
+                    cookies.add(new Cookie(name, value));
+                }
+            } catch (Throwable e) {
+                ;
+            }
+        }
+
+        return ((Cookie[]) cookies.toArray(new Cookie[cookies.size()]));
+
+    }
+
+
+    /**
+     * Append request parameters from the specified String to the specified
+     * Map.  It is presumed that the specified Map is not accessed from any
+     * other thread, so no synchronization is performed.
+     * <p>
+     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
+     * individually on the parsed name and value elements, rather than on
+     * the entire query string ahead of time, to properly deal with the case
+     * where the name or value includes an encoded "=" or "&" character
+     * that would otherwise be interpreted as a delimiter.
+     *
+     * @param map Map that accumulates the resulting parameters
+     * @param data Input string containing request parameters
+     *
+     * @exception IllegalArgumentException if the data is malformed
+     */
+    public static void parseParameters(Map map, String data, String encoding)
+        throws UnsupportedEncodingException {
+
+        if ((data != null) && (data.length() > 0)) {
+
+            // use the specified encoding to extract bytes out of the
+            // given string so that the encoding is not lost. If an
+            // encoding is not specified, let it use platform default
+            byte[] bytes = null;
+            try {
+                if (encoding == null) {
+                    bytes = data.getBytes();
+                } else {
+                    bytes = data.getBytes(encoding);
+                }
+            } catch (UnsupportedEncodingException uee) {
+            }
+
+            parseParameters(map, bytes, encoding);
+        }
+
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded String.
+     * When the byte array is converted to a string, the system default
+     * character encoding is used...  This may be different than some other
+     * servers.
+     *
+     * @param str The url-encoded 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, null);
+
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded String.
+     *
+     * @param str The url-encoded string
+     * @param enc The encoding to use; if null, the default encoding is used
+     * @exception IllegalArgumentException if a '%' character is not followed
+     * by a valid 2-digit hexadecimal number
+     */
+    public static String URLDecode(String str, String enc) {
+
+        if (str == null)
+            return (null);
+
+        // use the specified encoding to extract bytes out of the
+        // given string so that the encoding is not lost. If an
+        // encoding is not specified, let it use platform default
+        byte[] bytes = null;
+        try {
+            if (enc == null) {
+                bytes = str.getBytes();
+            } else {
+                bytes = str.getBytes(enc);
+            }
+        } catch (UnsupportedEncodingException uee) {}
+
+        return URLDecode(bytes, enc);
+
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded byte array.
+     *
+     * @param bytes The url-encoded byte array
+     * @exception IllegalArgumentException if a '%' character is not followed
+     * by a valid 2-digit hexadecimal number
+     */
+    public static String URLDecode(byte[] bytes) {
+        return URLDecode(bytes, null);
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded byte array.
+     *
+     * @param bytes The url-encoded byte array
+     * @param enc The encoding to use; if null, the default encoding is used
+     * @exception IllegalArgumentException if a '%' character is not followed
+     * by a valid 2-digit hexadecimal number
+     */
+    public static String URLDecode(byte[] bytes, String enc) {
+
+        if (bytes == null)
+            return (null);
+
+        int len = bytes.length;
+        int ix = 0;
+        int ox = 0;
+        while (ix < len) {
+            byte b = bytes[ix++];     // Get byte to test
+            if (b == '+') {
+                b = (byte)' ';
+            } else if (b == '%') {
+                b = (byte) ((convertHexDigit(bytes[ix++]) << 4)
+                            + convertHexDigit(bytes[ix++]));
+            }
+            bytes[ox++] = b;
+        }
+        if (enc != null) {
+            try {
+                return new String(bytes, 0, ox, enc);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return new String(bytes, 0, ox);
+
+    }
+
+
+    /**
+     * Convert a byte character value to hexidecimal digit value.
+     *
+     * @param b the character value byte
+     */
+    private static byte convertHexDigit( byte b ) {
+        if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
+        if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
+        if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
+        return 0;
+    }
+
+
+    /**
+     * Put name and value pair in map.  When name already exist, add value
+     * to array of values.
+     *
+     * @param map The map to populate
+     * @param name The parameter name
+     * @param value The parameter value
+     */
+    private static void putMapEntry( Map map, String name, String value) {
+        String[] newValues = null;
+        String[] oldValues = (String[]) map.get(name);
+        if (oldValues == null) {
+            newValues = new String[1];
+            newValues[0] = value;
+        } else {
+            newValues = new String[oldValues.length + 1];
+            System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
+            newValues[oldValues.length] = value;
+        }
+        map.put(name, newValues);
+    }
+
+
+    /**
+     * Append request parameters from the specified String to the specified
+     * Map.  It is presumed that the specified Map is not accessed from any
+     * other thread, so no synchronization is performed.
+     * <p>
+     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
+     * individually on the parsed name and value elements, rather than on
+     * the entire query string ahead of time, to properly deal with the case
+     * where the name or value includes an encoded "=" or "&" character
+     * that would otherwise be interpreted as a delimiter.
+     *
+     * NOTE: byte array data is modified by this method.  Caller beware.
+     *
+     * @param map Map that accumulates the resulting parameters
+     * @param data Input string containing request parameters
+     * @param encoding Encoding to use for converting hex
+     *
+     * @exception UnsupportedEncodingException if the data is malformed
+     */
+    public static void parseParameters(Map map, byte[] data, String encoding)
+        throws UnsupportedEncodingException {
+
+        if (data != null && data.length > 0) {
+            int    pos = 0;
+            int    ix = 0;
+            int    ox = 0;
+            String key = null;
+            String value = null;
+            while (ix < data.length) {
+                byte c = data[ix++];
+                switch ((char) c) {
+                case '&':
+                    value = new String(data, 0, ox, encoding);
+                    if (key != null) {
+                        putMapEntry(map, key, value);
+                        key = null;
+                    }
+                    ox = 0;
+                    break;
+                case '=':
+                    if (key == null) {
+                        key = new String(data, 0, ox, encoding);
+                        ox = 0;
+                    } else {
+                        data[ox++] = c;
+                    }                   
+                    break;  
+                case '+':
+                    data[ox++] = (byte)' ';
+                    break;
+                case '%':
+                    data[ox++] = (byte)((convertHexDigit(data[ix++]) << 4)
+                                    + convertHexDigit(data[ix++]));
+                    break;
+                default:
+                    data[ox++] = c;
+                }
+            }
+            //The last value does not end in '&'.  So save it now.
+            if (key != null) {
+                value = new String(data, 0, ox, encoding);
+                putMapEntry(map, key, value);
+            }
+        }
+
+    }
+
+
+
+}

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/util/RequestUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/util/UrlUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/res/LocalStrings.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/res/LocalStrings_es.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/res/LocalStrings_fr.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/res/LocalStrings_ja.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/threads/res/LocalStrings.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/threads/res/LocalStrings_es.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/threads/res/LocalStrings_fr.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/threads/res/LocalStrings_ja.properties
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to