package com.cftech.sys.filter;

import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.jsoup.nodes.Document.OutputSettings;
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.errors.ValidationException;
import org.owasp.esapi.filters.ESAPIFilter;
import org.owasp.validator.html.AntiSamy;
import org.owasp.validator.html.CleanResults;
import org.owasp.validator.html.Policy;
import org.owasp.validator.html.PolicyException;
import org.springframework.web.util.HtmlUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.regex.Pattern;

/**
 *  EASPI 针对XSS 侵入
 * Created by Jasper Huang on 2018/6/1.
 */
public class SecurityRequestWrapper extends HttpServletRequestWrapper {
    private final static Whitelist WHITELIST = Whitelist.relaxed();
    private static AntiSamy antiSamy = new AntiSamy();
    private static Policy ebaypolicy ;
    private static Policy simplePolcy ;
    private static Policy esapiPolicy;
    private final static OutputSettings OUTPUTSETTINGS = new OutputSettings().prettyPrint( false );

    static {
        WHITELIST.addTags( "embed", "object", "param", "span", "div", "img" );
        WHITELIST.addAttributes( ":all", "style", "class", "id", "name" );
        WHITELIST.addAttributes( "object", "width", "height", "classid", "codebase" );
        WHITELIST.addAttributes( "param", "name", "value" );
        WHITELIST.addAttributes( "embed", "src", "quality", "width", "height", "allowFullScreen",
                "allowScriptAccess", "flashvars", "name", "type", "pluginspage" );

        try {
            ebaypolicy = Policy.getInstance(SecurityRequestWrapper.class.getClassLoader().getResourceAsStream("antisamy/antisamy-ebay.xml"));
        } catch (PolicyException e) {
            e.printStackTrace();
        }

        try {
            simplePolcy = Policy.getInstance(SecurityRequestWrapper.class.getClassLoader().getResourceAsStream("antisamy/antisamy-schaffler-tinymce.xml"));
        } catch (PolicyException e) {
            e.printStackTrace();
        }

        try {
            esapiPolicy = Policy.getInstance(SecurityRequestWrapper.class.getClassLoader().getResourceAsStream("esapi/antisamy-esapi.xml"));
        } catch (PolicyException e) {
            e.printStackTrace();
        }

    }

    public SecurityRequestWrapper( HttpServletRequest servletRequest ) {
        super( servletRequest );
    }

    @Override
    public String[] getParameterValues( String parameter ) {
        boolean flag = true;

        String[] values = super.getParameterValues( parameter );
        if( null == values ) {
            return null;
        }
        if(parameter.contains("content"))
        {
            flag = false;
        }
        int count = values.length;
        String[] encodedValues = new String[ count ];
        for( int i = 0; i < count; i++ ) {
                encodedValues[ i ] = filterValue( values[ i ],flag );
        }
        return encodedValues;
    }

    @Override
    public String getParameter( String parameter ) {
        String value = super.getParameter( parameter );
        return filterValue( value,true );
    }

    @Override
    public String getHeader( String name ) {
        String value = super.getHeader( name );
        return filterValue(value, true );
    }

    private String filterValue( String value,boolean flag ) {
        if( null != value ) {

            try
            {

                //CleanResults cr = antiSamy.scan(dirtyInput, policyFilePath);
                CleanResults cr = null;
                if(!flag)
                {
//                     cr = antiSamy.scan(value, ebaypolicy);
                     value  =  ESAPI.encoder().encodeForHTML(value);
                }else
                {
                   //  value =  ESAPI.encoder().canonicalize(value);//进行标准化
                     cr = antiSamy.scan(value, simplePolcy);
                    //安全的HTML输出
                    value  =  cr.getCleanHTML();

                    value = HtmlUtils.htmlEscape(HtmlUtils.htmlUnescape(value),"UTF-8");
                }


            }catch (Exception e)
            {
                e.printStackTrace();
            }

            // avoid encoded attacks.
//                 value = ESAPI.encoder().canonicalize(value);

//                value = ESAPI.encoder().encodeForHTML( value );

//                try {
//                    value = ESAPI.validator(). //getValidSafeHTML("richtext",value,value.length()+10,true);
//                } catch (ValidationException e) {
//                    value = ESAPI.encoder().encodeForHTML( value );
//                    e.printStackTrace();
//                }




            // Avoid null characters
//            value = value.replaceAll( "\0", "" );
//            value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
//            value = value.replaceAll("eval\\((.*)\\)", "");
//            value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
//            value =alue.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
//            value = value.replaceAll("'", "& #39;");
//            value = v value.replaceAll("script", "");
            // Clean out HTML


            // Avoid null characters
//            value = value.replaceAll("", "");
//
//            // Avoid anything between script tags
//            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Avoid anything in a src='...' type of expression
//            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Remove any lonesome </script> tag
//            scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Remove any lonesome <script ...> tag
//            scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Avoid eval(...) expressions
//            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Avoid expression(...) expressions
//            scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Avoid javascript:... expressions
//            scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Avoid vbscript:... expressions
//            scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
//            value = scriptPattern.matcher(value).replaceAll("");
//
//            // Avoid onload= expressions
//            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
//            value = scriptPattern.matcher(value).replaceAll("");


          //  value = Jsoup.clean( value, "", WHITELIST, OUTPUTSETTINGS );
        }
        return value;
    }
}
