/** * Copyright 2005-2010 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.util; import java.util.Hashtable; import java.util.Iterator; import java.util.Map.Entry; import java.util.StringTokenizer; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hdiv.config.HDIVConfig; import org.hdiv.dataComposer.IDataComposer; /** * General purpose utility methods related to processing a servlet request. * * @author Gorka Vicente */ public class RequestUtilsHDIV { private static Log log = LogFactory.getLog(RequestUtilsHDIV.class); /** * Devuelve true solo si la url que se le pasa es externa, esto es, no hay * que a�adirle el estado de HDIV * Returns true only if it is an external url, that is, HDIV state must not be added. * * @param request * request object * @param url * the url * @return boolean value */ public static boolean isInternalUrl(HttpServletRequest request, String url) { if (RequestUtilsHDIV.isPathUrl(url)) { if (url.startsWith(request.getContextPath() + "/") || url.equals(request.getContextPath())) { // url of type /hdiv-jsf-1.0/... or /hdiv-jsf-1.0 return true; } else if (url.startsWith("/")) { // url of type /anotherApplication/... return false; } else { // url of type section/action... return true; } } else { // URL is absolute: http://... String urlWithoutServer = removeServerFromUrl(url); if (urlWithoutServer.startsWith(request.getContextPath() + "/") || urlWithoutServer.equals(request.getContextPath())) { // http://localhost:8080/hdiv-jsf-1.0/... or // http://localhost:8080/hdiv-jsf-1.0 return true; } // http://localhost:8080/anotherApplication... or http://www.google.com return false; } } /** * Returns true only if url points to a resource that does not require * a HDIV state, as an image or pdf file. * Before calling this method verify that it is an internal url * * @param url * @return */ public static boolean isResourceUrl(HDIVConfig hdivConfig, String url) { // Remove parameters if (url.indexOf("?") > 0) { url = url.substring(0, url.indexOf("?")); } // Remove anchor if (url.indexOf("#") > 0) { url = url.substring(0, url.indexOf("#")); } if (url.endsWith("/")) { return false; } Hashtable protectedExtensions = hdivConfig.getProtectedURLPatterns(); Iterator it = protectedExtensions.entrySet().iterator(); while (it.hasNext()) { Entry valor = (Entry) it.next(); Pattern allowedExtension = (Pattern) valor.getValue(); if (allowedExtension.matcher(url).matches()) { return false; } } // If url ends with .../module verify that has no dot (.) on it. // If contains a dot it may be a type of file extension .../mod.gif String suffix = ""; if (url.indexOf("/") > 0) { suffix = url.substring(url.lastIndexOf("/") + 1); } else { suffix = url; } if (suffix.indexOf(".") < 0) { return false; } return true; } /** * Checks if <code>url</code> contains any scheme. * * @param url * URL * @return if the url <code>url</code> contains a scheme. False otherwise. */ private static boolean isPathUrl(String url) { return (url.indexOf(':') == -1);// Si contiene http://.... devuelve // false } /** * It creates a new state to store all the parameters and values of the * <code>request</code> and it generates a new encoded values for the * <code>request</code> parameters and adds the HDIV parameter. * * @param request * HTTP request * @param finalLocation * the location to redirect to * @return URL with encoded parameters and HDIV parameter */ public static String composeURL(HttpServletRequest request, IDataComposer dataComposer, String url) { String encodedURL = url; // IDataComposer dataComposer = (IDataComposer) // request.getAttribute("dataComposer"); // IDataComposer dataComposer = HDIVUtil.getDataComposer(); String actionMappingName = RequestUtilsHDIV.getActionMappingName(request, url); dataComposer.beginRequest(actionMappingName); int question = url.indexOf("?"); if (question > 0) { // generate a new encoded values for the url parameters encodedURL = RequestUtilsHDIV.composeAction(url, question, Constants.ENCODING_UTF_8, dataComposer); } return encodedURL; } /** * Gets action identifier from url. Action identifier is composed by * application and action names <code>/application/action</code> * * @param request * @param url * @return */ private static String getActionMappingName(HttpServletRequest request, String url) { String actionMappingName = null; if (!isPathUrl(url)) { // http://.... // Remove the part related with the server side String urlSimple = removeServerFromUrl(url); actionMappingName = HDIVUtil.getActionMappingName(urlSimple); } else if (url.startsWith("/")) { // url= /aplicacion/action // Already has the context path actionMappingName = HDIVUtil.getActionMappingName(url); } else { String uri = request.getRequestURI(); String contextAndFolder = uri.substring(0, uri.lastIndexOf("/")); // url= action actionMappingName = HDIVUtil.getActionMappingName(contextAndFolder + "/" + url); } return actionMappingName; } /** * <p> * It generates a new encoded values for the <code>url</code> parameters. * </p> * <p> * The returned values guarantees the confidentiality in the encoded and * memory strategies if confidentiality indicator defined by user is true. * </p> * * @param url * request url * @param questionIndex * index of the first question occurrence in <code>url</code> * string * @param charEncoding * character encoding * @return url with encoded values */ public static String composeAction(String url, int questionIndex, String charEncoding, IDataComposer dataComposer) { String value = url; value = value.substring(questionIndex + 1); value = value.replaceAll("&", "&"); String token = null; String urlAction = HDIVUtil.getActionMappingName(url); StringTokenizer st = new StringTokenizer(value, "&"); while (st.hasMoreTokens()) { token = st.nextToken(); String param = token.substring(0, token.indexOf("=")); String val = token.substring(token.indexOf("=") + 1); String encodedValue = dataComposer.compose(urlAction, param, val, false, true, charEncoding); value = value.replaceFirst(HDIVUtil.protectCharacters(token), param + "=" + encodedValue); } return url.substring(0, questionIndex + 1) + value; } /** * Add Hdiv state to the url * * @param hdivParameter * hdiv parameter name * @param hdivRequestId * hdiv parameter value * @param encodedURL * url to appent the hdiv state * @param anchor * url anchor * @return url with state */ public static String addHDIVState(String hdivParameter, String hdivRequestId, String encodedURL, String anchor) { String separator = ""; if ((hdivRequestId.length() <= 0) || (encodedURL.startsWith("javascript:"))) { return encodedURL; } // we ask if the link has an anchor. If so, we must remove it to be // added // later on, once the hdivParameter has been added. this way we get a // link // like this: ../action.do?parameters&hdivParameter=2-5#anchor boolean isAnchor = (anchor != null) && (!anchor.equals("")); if (isAnchor) { encodedURL = encodedURL.replaceFirst("#" + anchor, ""); } // we check if the url contains parameters separator = (encodedURL.indexOf("?") > 0) ? "&" : "?"; hdivParameter = separator + hdivParameter + "=" + hdivRequestId; return encodedURL + hdivParameter + ((isAnchor) ? "#" + anchor : ""); } /** * Removes from url the part related with the server side * * @param url * url a modificar * @return url modificada */ public static String removeServerFromUrl(String url) { String urlSimple = url.replaceFirst("://", ""); int posicion = urlSimple.indexOf("/"); if (posicion > 0) { urlSimple = urlSimple.substring(posicion); } else { urlSimple = ""; } return urlSimple; } }