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

org.springframework.web.filter.EncodingFilter Maven / Gradle / Ivy

package org.springframework.web.filter;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.Ordered;
import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

public class EncodingFilter extends OncePerRequestFilter implements Ordered {
  private static final Set CHARSETS = Collections.newSetFromMap(new LinkedCaseInsensitiveMap(5, Locale.ENGLISH));
  private static final Map ESCAPES = new LinkedHashMap();

  private int order = Ordered.HIGHEST_PRECEDENCE + 50;

  private Charset charset;

  static {
    CHARSETS.add(StandardCharsets.ISO_8859_1.name());
    CHARSETS.add(StandardCharsets.UTF_16.name());
    CHARSETS.add(StandardCharsets.UTF_16BE.name());
    CHARSETS.add(StandardCharsets.UTF_16LE.name());
    CHARSETS.add(StandardCharsets.US_ASCII.name());

    ESCAPES.put("|", "%7C");
    ESCAPES.put(" ", "%20");
    ESCAPES.put("^", "%5E");
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    String encoding = request.getCharacterEncoding();

    if (encoding == null) {
      Charset charset = getCharset();
      if (charset == null) {
        charset = Charset.defaultCharset();
      }
      encoding = charset.name();
    }

    Assert.notNull(encoding, "'encoding' must not be null");

    filterChain.doFilter(new CharsetEscapeRequestWrapper(request, encoding), response);
  }

  @Override
  public int getOrder() {
    return order;
  }

  public void setOrder(int order) {
    this.order = order;
  }

  public Charset getCharset() {
    return charset;
  }

  public void setCharset(Charset charset) {
    this.charset = charset;
  }

  private static class CharsetEscapeRequestWrapper extends HttpServletRequestWrapper {
    private final StringBuffer requestURL;
    private final String requestURI;
    private final String queryString;

    public CharsetEscapeRequestWrapper(HttpServletRequest request, String encoding) {
      super(request);
      String requestURL, requestURI, queryString;

      if (request.getRequestURL() != null && StringUtils.hasText(requestURL = new String(request.getRequestURL()))) {
        requestURL = replace(requestURL);
        try {
          URI.create(requestURL).toASCIIString();
        }
        catch (IllegalArgumentException e) {
          requestURL = convert(requestURL, encoding);
        }
        this.requestURL = new StringBuffer(requestURL);
      }
      else {
        this.requestURL = request.getRequestURL();
      }

      if (StringUtils.hasText(requestURI = request.getRequestURI())) {
        requestURI = replace(requestURI);
        try {
          URI.create(requestURI).toASCIIString();
        }
        catch (IllegalArgumentException e) {
          requestURI = convert(requestURI, encoding);
        }
        this.requestURI = requestURI;
      }
      else {
        this.requestURI = requestURI;
      }

      if (StringUtils.hasText(queryString = request.getQueryString())) {
        queryString = replace(queryString);
        try {
          URI.create(queryString).toASCIIString();
        }
        catch (IllegalArgumentException e) {
          queryString = convert(queryString, encoding);
        }
        this.queryString = queryString;
      }
      else {
        this.queryString = queryString;
      }
    }

    private String replace(String string) {
      for (Entry entry : ESCAPES.entrySet()) {
        string = string.replace(entry.getKey(), entry.getValue());
      }
      return string;
    }

    private String convert(String string, String characterEncoding) {
      for (String charset : CHARSETS) {
        try {
          return convert(string, charset, characterEncoding);
        }
        catch (Exception e) {
          continue;
        }
      }
      return string;
    }

    private String convert(String string, String charsetName, String characterEncoding) throws Exception {
      try {
        return URI.create(new String(string.getBytes(charsetName), characterEncoding)).toASCIIString();
      }
      catch (IOException | IllegalArgumentException e) {
        throw e;
      }
    }

    @Override
    public String getRequestURI() {
      return this.requestURI;
    }

    @Override
    public StringBuffer getRequestURL() {
      return this.requestURL;
    }

    @Override
    public String getQueryString() {
      return this.queryString;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy