/**
* Copyright 2005-2016 hdiv.org
*
* 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.hdiv.filter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequestWrapper;
import org.hdiv.context.RequestContextHolder;
import org.hdiv.session.ISession;
import org.hdiv.util.Constants;
/**
* A wrapper for HTTP servlet request.
*
* @author Roberto Velasco
* @author Gorka Vicente
* @see javax.servlet.http.HttpServletRequestWrapper
*/
public class RequestWrapper extends HttpServletRequestWrapper {
/**
* HTTP header to sent cookies.
*/
protected static final String COOKIE = "cookie";
/**
* Set with editable parameters.
*/
protected Set<String> editableParameters = new HashSet<String>();
/**
* Map with request parameters
*/
protected Map<String, String[]> parameters = new HashMap<String, String[]>();
/**
* The file request parameters.
*/
protected Map<String, Object> elementsFile = new HashMap<String, Object>();
/**
* The text request parameters.
*/
protected Map<String, Object> elementsText = new HashMap<String, Object>();
/**
* Determines whether this request is multipart.
*/
protected boolean isMultipart = false;
/**
* Confidentiality indicator to know if information is accessible only for those who are authorized.
*/
protected boolean confidentiality = true;
/**
* Indicates if cookie confidentiality is applied or not. If the value is <code>true</code> cookie values must not be replaced by
* relative values. If it is <code>false</code> they must be replaced by relative values to provide confidentiality.
*/
protected boolean cookiesConfidentiality;
/**
* Session object wrapper.
*/
protected ISession session;
/**
* Request context data.
*/
protected final RequestContextHolder requestContext;
/**
* Constructs a request object wrapping the given request.
*
* @param requestContext request context
*/
@SuppressWarnings("deprecation")
public RequestWrapper(final RequestContextHolder requestContext) {
super(requestContext.getRequest());
this.requestContext = requestContext;
}
/**
* Returns an array of String objects containing all of the values the given request parameter has. If the parameter has a single value,
* the array has a length of 1.
*
* @param parameter the name of the parameter whose value is requested
*/
@Override
public String[] getParameterValues(final String parameter) {
// non validated parameters are obtained from the original request
if (!parameters.containsKey(parameter)) {
return super.getParameterValues(parameter);
}
Object data = parameters.get(parameter);
if (data.getClass().isArray()) {
return (String[]) data;
}
else {
return parameters.get(parameter);
}
}
/**
* Returns the value of a request parameter as a String. Request parameters are extra information sent with the request. For HTTP
* servlets, parameters are contained in the query string or posted form data.
*
* @param parameter name of the parameter
*/
@Override
public String getParameter(final String parameter) {
// non validated parameters are obtained from the original request
if (!parameters.containsKey(parameter)) {
return super.getParameter(parameter);
}
Object data = parameters.get(parameter);
if (data.getClass().isArray()) {
String[] array = (String[]) data;
return array[0];
}
else {
String[] values = parameters.get(parameter);
return values.length > 0 ? values[0] : null;
}
}
/**
* Returns the names of the parameters for this request. The enumeration consists of the normal request parameter names plus the
* parameters read from the multipart request.
*/
@Override
public Enumeration<String> getParameterNames() {
Enumeration<String> baseParams = super.getParameterNames();
if (!isMultipart) {
return baseParams;
}
List<String> list = new ArrayList<String>(Collections.list(baseParams));
list.addAll(parameters.keySet());
return Collections.enumeration(list);
}
/**
* Returns the value of the specified request header as a String.
*
* @param name header name
* @return a String containing the value of the requested header, or null if the request does not have a header of that name
* @since HDIV 1.1.1
*/
@Override
@SuppressWarnings("unchecked")
public String getHeader(final String name) {
String cookieHeader = super.getHeader(name);
if (name.equalsIgnoreCase(COOKIE) && confidentiality && cookiesConfidentiality) {
Map<String, SavedCookie> sessionCookies = session.getAttribute(requestContext, Constants.HDIV_COOKIES_KEY, Map.class);
if (sessionCookies != null) {
return replaceCookieString(cookieHeader, sessionCookies);
}
}
return cookieHeader;
}
/**
* Returns all the values of the specified request header as an Enumeration of String objects.
*
* @param name a String specifying the header name
* @return an Enumeration containing the values of the requested header. If the request does not have any headers of that name return an
* empty enumeration. If the container does not allow access to header information, return null.
* @since HDIV 1.1.1
*/
@Override
@SuppressWarnings("unchecked")
public Enumeration<String> getHeaders(final String name) {
Enumeration<String> headerValues = super.getHeaders(name);
if (name.equalsIgnoreCase(COOKIE) && confidentiality && cookiesConfidentiality) {
Map<String, SavedCookie> sessionCookies = session.getAttribute(requestContext, Constants.HDIV_COOKIES_KEY, Map.class);
if (sessionCookies == null) {
return headerValues;
}
else {
List<String> values = new ArrayList<String>();
while (headerValues.hasMoreElements()) {
String element = headerValues.nextElement();
String replaced = replaceCookieString(element, sessionCookies);
values.add(replaced);
}
return Collections.enumeration(values);
}
}
return headerValues;
}
/**
* Parses an http cookie request header and replace values if confidentiality is activated.
*
* @param cookieHeader value assigned to cookie header
* @param sessionCookies cookies stored in user session
* @return cookie request header with replaced values
* @since HDIV 1.1.1
*/
protected String replaceCookieString(final String cookieHeader, final Map<String, SavedCookie> sessionCookies) {
String header = cookieHeader.trim();
// Cookie fields are separated by ';'
StringTokenizer tokens = new StringTokenizer(cookieHeader, ";");
while (tokens.hasMoreTokens()) {
// field name is separated from value by '='
StringTokenizer t = new StringTokenizer(tokens.nextToken(), "=");
String name = t.nextToken().trim();
if (name.equals(Constants.JSESSIONID)) {
continue;
}
if (sessionCookies.containsKey(name) && t.hasMoreTokens()) {
String value = t.nextToken().trim();
SavedCookie savedCookie = sessionCookies.get(name);
header = header.replaceFirst("=" + value, "=" + savedCookie.getValue());
}
}
return header;
}
/**
* Add a single value for the specified HTTP parameter <code>name</code>.
*
* @param name parameter name
* @param value value
*/
public void addParameter(final String name, final String[] value) {
parameters.put(name, value);
if (isMultipart) {
addTextParameter(name, value);
}
}
/**
* Combines the parameters stored here with those in the underlying request. If parameter values in the underlying request take
* precedence over those stored here.
*
* @since HDIV 1.3
*/
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> map = new HashMap<String, String[]>(super.getRequest().getParameterMap());
map.putAll(parameters);
return map;
}
/**
* Returns a map containing the text (that is, non-file) request parameters.
*
* @return The text request parameters.
*/
public Map<String, Object> getTextElements() {
return elementsText;
}
/**
* Returns a map containing the file (that is, non-text) request parameters.
*
* @return The file request parameters.
*/
public Map<String, Object> getFileElements() {
return elementsFile;
}
/**
* Adds a regular text parameter to the set of text parameters for this request.
*
* @param name text parameter name
* @param value text parameter value
*/
public void addTextParameter(final String name, final Object value) {
elementsText.put(name, value);
}
/**
* Adds a file parameter to the set of file parameters for this request.
*
* @param name file name
* @param values file values
*/
public void addFileItem(final String name, final Object values) {
elementsFile.put(name, values);
}
/**
* Add editable parameter.
*
* @param parameter new parameter name
*/
public void addEditableParameter(final String parameter) {
editableParameters.add(parameter);
}
/**
* Return true if parameter is editable.
*
* @param parameter parameter name
* @return boolean
*/
public boolean isEditableParameter(final String parameter) {
return editableParameters.contains(parameter);
}
/**
* Determines whether this request is multipart.
*
* @param isMultipart true if it is multipart
*/
public void setMultipart(final boolean isMultipart) {
this.isMultipart = isMultipart;
}
/**
* @param cookiesConfidentiality The cookiesConfidentiality to set.
*/
public void setCookiesConfidentiality(final boolean cookiesConfidentiality) {
this.cookiesConfidentiality = cookiesConfidentiality;
}
/**
* @param confidentiality The confidentiality to set.
*/
public void setConfidentiality(final boolean confidentiality) {
this.confidentiality = confidentiality;
}
/**
* @param session the session to set
*/
public void setSession(final ISession session) {
this.session = session;
}
}