All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.catalina.util.RequestUtil Maven / Gradle / Ivy

There is a newer version: 11.0.0-M26
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.catalina.util;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Map;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.B2CConverter;
import org.apache.tomcat.util.res.StringManager;


/**
 * General purpose request parsing and encoding utility methods.
 *
 * @author Craig R. McClanahan
 * @author Tim Tye
 * @version $Id: RequestUtil.java 1500934 2013-07-08 20:32:53Z markt $
 */
public final class RequestUtil {


    private static final Log log = LogFactory.getLog(RequestUtil.class);

    /**
     * The string resources for this package.
     */
    private static final StringManager sm =
        StringManager.getManager("org.apache.catalina.util");


    /**
     * 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);
        StringBuilder result = new StringBuilder(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());

    }


    /**
     * 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.
     * 

* IMPLEMENTATION NOTE: 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 * @param encoding The encoding to use; encoding must not be null. * If an unsupported encoding is specified the parameters will not be * parsed and the map will not be modified */ public static void parseParameters(Map map, String data, String encoding) { 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. byte[] bytes = null; try { bytes = data.getBytes(B2CConverter.getCharset(encoding)); parseParameters(map, bytes, encoding); } catch (UnsupportedEncodingException uee) { if (log.isDebugEnabled()) { log.debug(sm.getString("requestUtil.parseParameters.uee", encoding), uee); } } } } /** * Convert a byte character value to hexadecimal 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); throw new IllegalArgumentException( sm.getString("requestUtil.convertHexDigit.notHex", Character.valueOf((char)b))); } /** * 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 = 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. *

* IMPLEMENTATION NOTE: 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 The encoding to use; if null, the default encoding is * used * * @exception UnsupportedEncodingException if the requested encoding is not * supported. */ public static void parseParameters(Map map, byte[] data, String encoding) throws UnsupportedEncodingException { Charset charset = B2CConverter.getCharset(encoding); if (data != null && data.length > 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, charset); if (key != null) { putMapEntry(map, key, value); key = null; } ox = 0; break; case '=': if (key == null) { key = new String(data, 0, ox, charset); 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, charset); putMapEntry(map, key, value); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy