title: XSS Filter to enctype="multipart/form-data" forms
body: <p>I found the next code that prevent xss atacks. But it has a problem. It works fine with forms that have <code>enctype="application/x-www-form-urlencoded"</code>, but not with forms that have <code>enctype="multipart/form-data"</code>. I observe that <code>getParameterValues()</code> and rest of methods are not called.</p>
  
  <p>//--- XSS Filter ---//</p>
  
  <pre><code>import java.io.IOException;
  import javax.servlet.Filter;
  import javax.servlet.FilterChain;
  import javax.servlet.FilterConfig;
  import javax.servlet.ServletException;
  import javax.servlet.ServletRequest;
  import javax.servlet.ServletResponse;
  import javax.servlet.http.HttpServletRequest;
  
  /**
   * Servlet Filter implementation class XSSFilter
   */
  public class XSSFilter implements Filter {
  
  @SuppressWarnings("unused")
  private FilterConfig filterConfig;
  
  /**
   * Default constructor. 
   */
  public XSSFilter() {
  
  }
  
  public void init(FilterConfig filterConfig) throws ServletException {
      this.filterConfig = filterConfig;        
  }
  
  public void destroy() {
      this.filterConfig = null;
  }
  
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {      
      chain.doFilter(new RequestWrapperXSS((HttpServletRequest) request), response);
  }
  
  }
  </code></pre>
  
  <p>//--- RequestWrapperXSS ---//</p>
  
  <pre><code>import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletRequestWrapper;
  
  public final class RequestWrapperXSS extends HttpServletRequestWrapper {
  public RequestWrapperXSS(HttpServletRequest servletRequest) {       
      super(servletRequest);
  }
  
  public String[] getParameterValues(String parameter) {
      System.out.println("entra parameterValues");
      String[] values = super.getParameterValues(parameter);
      if (values == null) {
          return null;
      }
      int count = values.length;
      String[] encodedValues = new String[count];
      for (int i = 0; i &lt; count; i++) {
          encodedValues[i] = cleanXSS(values[i]);
      }
      return encodedValues;
  }
  
  public String getParameter(String parameter) {
      System.out.println("entra getParameter");
      String value = super.getParameter(parameter);
      if (value == null) {
          return null;
      }
      return cleanXSS(value);
  }
  
  public String getHeader(String name) {
      System.out.println("entra header");
      String value = super.getHeader(name);
      if (value == null)
          return null;
      return cleanXSS(value);
  }
  
  private String cleanXSS(String cadena) {
      System.out.println("entra claean XSS");
       StringBuffer sb = new StringBuffer(cadena.length());
          // true if last char was blank
          boolean lastWasBlankChar = false;
          int len = cadena.length();
          char c;
  
          for (int i = 0; i &lt; len; i++)
              {
              c = cadena.charAt(i);
              if (c == ' ') {
                  // blank gets extra work,
                  // this solves the problem you get if you replace all
                  // blanks with &amp;nbsp;, if you do that you loss 
                  // word breaking
                  if (lastWasBlankChar) {
                      lastWasBlankChar = false;
                      sb.append("&amp;nbsp;");
                      }
                  else {
                      lastWasBlankChar = true;
                      sb.append(' ');
                      }
                  }
              else {
                  lastWasBlankChar = false;
                  //
                  // HTML Special Chars
                  if (c == '"')
                      sb.append("&amp;quot;");
                  else if (c == '&amp;')
                      sb.append("&amp;amp;");
                  else if (c == '&lt;')
                      sb.append("&amp;lt;");
                  else if (c == '&gt;')
                      sb.append("&amp;gt;");
                  else if (c == '\n')
                      // Handle Newline
                      sb.append("&amp;lt;br/&amp;gt;");
                  else {
                      int ci = 0xffff &amp; c;
                      if (ci &lt; 160 )
                          // nothing special only 7 Bit
                          sb.append(c);
                      else {
                          // Not 7 Bit use the unicode system
                          sb.append("&amp;#");
                          sb.append(new Integer(ci).toString());
                          sb.append(';');
                          }
                      }
                  }
              }
          return sb.toString();
  
  
  }
  }
  </code></pre>