/* * 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.wicket.protocol.http; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.wicket.Application; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.mapper.parameter.INamedParameters; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.util.encoding.UrlDecoder; import org.apache.wicket.util.string.Strings; /** * Wicket Http specific utilities class. */ public final class RequestUtils { /** * Decode the provided queryString as a series of key/ value pairs and set them in the provided * value map. * * @param queryString * string to decode, uses '&' to separate parameters and '=' to separate key from * value * @param params * parameters map to write the found key/ value pairs to */ public static void decodeParameters(String queryString, PageParameters params) { decodeParameters(queryString, params, getCurrentCharset()); } /** * Decode the provided queryString as a series of key/ value pairs and set them in the provided * value map. * * @param queryString * string to decode, uses '&' to separate parameters and '=' to separate key from * value * @param params * parameters map to write the found key/ value pairs to * @param currentCharset * charset resolved via current requestCycle */ static void decodeParameters(String queryString, PageParameters params, Charset currentCharset) { if (Strings.indexOf(queryString, '?') == 0) { queryString = queryString.substring(1); } for (String paramTuple : Strings.split(queryString, '&')) { final String[] bits = Strings.split(paramTuple, '='); if (bits.length == 2) { params.add(UrlDecoder.QUERY_INSTANCE.decode(bits[0], currentCharset), UrlDecoder.QUERY_INSTANCE.decode(bits[1], currentCharset), INamedParameters.Type.QUERY_STRING); } else { params.add(UrlDecoder.QUERY_INSTANCE.decode(bits[0], currentCharset), "", INamedParameters.Type.QUERY_STRING); } } } /** * Remove occurrences of ".." from the path * * @param path * @return path string with double dots removed */ public static String removeDoubleDots(String path) { String[] segments = Strings.split(path, '/'); List<String> newcomponents = new ArrayList<>(Arrays.asList(segments)); for (int i = 0; i < newcomponents.size(); i++) { if (i < newcomponents.size() - 1) { // Verify for a ".." component at next iteration if ((newcomponents.get(i)).length() > 0 && newcomponents.get(i + 1).equals("..")) { newcomponents.remove(i); newcomponents.remove(i); i = i - 2; if (i < -1) { i = -1; } } } } String newpath = Strings.join("/", newcomponents); if (path.endsWith("/")) { return newpath + "/"; } return newpath; } /** * Hidden utility class constructor. */ private RequestUtils() { } /** * Calculates absolute path to url relative to another absolute url. * * @param requestPath * absolute path. * @param relativePagePath * path, relative to requestPath * @return absolute path for given url */ public static String toAbsolutePath(final String requestPath, String relativePagePath) { final StringBuilder result; if (requestPath.endsWith("/")) { result = new StringBuilder(requestPath); } else { // Remove everything after last slash (but not slash itself) result = new StringBuilder(requestPath.substring(0, requestPath.lastIndexOf('/') + 1)); } if (relativePagePath.startsWith("./")) { relativePagePath = relativePagePath.substring(2); } if (relativePagePath.startsWith("../")) { StringBuilder tempRelative = new StringBuilder(relativePagePath); // Go up through hierarchy until we find most common directory for both pathes. while (tempRelative.indexOf("../") == 0) { // Delete ../ from relative path tempRelative.delete(0, 3); // Delete last slash from result result.setLength(result.length() - 1); // Delete everyting up to last slash result.delete(result.lastIndexOf("/") + 1, result.length()); } result.append(tempRelative); } else { // Pages are in the same directory result.append(relativePagePath); } return result.toString(); } private static Charset getDefaultCharset() { String charsetName = null; if (Application.exists()) { charsetName = Application.get().getRequestCycleSettings().getResponseRequestEncoding(); } if (Strings.isEmpty(charsetName)) { charsetName = "UTF-8"; } return Charset.forName(charsetName); } private static Charset getCurrentCharset() { return RequestCycle.get().getRequest().getCharset(); } /** * @param request * the http servlet request to extract the charset from * @return the request's charset or a default it request is {@code null} or has an unsupported * character encoding * * @see org.apache.wicket.settings.RequestCycleSettings#getResponseRequestEncoding() */ public static Charset getCharset(HttpServletRequest request) { Charset charset = null; if (request != null) { String charsetName = request.getCharacterEncoding(); if (charsetName != null) { try { charset = Charset.forName(charsetName); } catch (UnsupportedCharsetException useDefault) { } } } if (charset == null) { charset = getDefaultCharset(); } return charset; } }