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("<");
- break;
- case '>':
- result.append(">");
- break;
- case '&':
- result.append("&");
- break;
- case '"':
- result.append(""");
- 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("<");
+ break;
+ case '>':
+ result.append(">");
+ break;
+ case '&':
+ result.append("&");
+ break;
+ case '"':
+ result.append(""");
+ 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]