package com.skr.mdm.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
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.core.io.ClassPathResource;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

/**
 * @author nfq
 * @date 2020/7/21 19:10
 */
@Slf4j
public class XssHttpRequestWrapper extends HttpServletRequestWrapper {

	private static Policy policy = null;


	static {
		//初始化策略
		/**
		 * antisamy-anythinggoes.xml    非常危险，允许HTML、CSS、Javascript通过
		 * antisamy-ebay.xml    相对安全，对内容进行过滤。适用于电子商务网站，允许用户输入HTML脚本作为页面的一部分
		 * antisamy-myspace.xml 相对危险，适用于社交网站，允许用户输入作为整个页面
		 * antisamy-slashdot.xml    适用于新闻网站的评论过滤
		 * antisamy-tinymce.xml 相对安全，只允许文本格式通过
		 */

		ClassPathResource classPathResource = new ClassPathResource("xss/antisamy-tinymce.xml");
		try {
			try {
				policy = Policy.getInstance(classPathResource.getInputStream());
			} catch (PolicyException e) {
				log.error("加载Antisamy策略文件时异常", e);
			}
		} catch (IOException e) {
			log.error("加载Antisamy策略文件时异常", e);
		}
	}


	public XssHttpRequestWrapper(HttpServletRequest request) {
		super(request);
	}

	@Override
	public String getParameter(String paramString) {
		String str = super.getParameter(paramString);
		return StringUtils.isBlank(str) ? null : xssClean(str);
	}

	@Override
	public String getHeader(String paramString) {
		String str = super.getHeader(paramString);
		return StringUtils.isBlank(str) ? null : xssClean(str);
	}

	@Override
	@SuppressWarnings("rawtypes")
	public Map<String, String[]> getParameterMap() {
		Map<String, String[]> requestMap = super.getParameterMap();
		Iterator iterator = requestMap.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry me = (Map.Entry) iterator.next();
			String[] values = (String[]) me.getValue();
			for (int i = 0; i < values.length; i++) {
				values[i] = xssClean(values[i]);
			}
		}
		return requestMap;
	}

	@Override
	public String[] getParameterValues(String paramString) {
		String[] arrayOfString1 = super.getParameterValues(paramString);
		if (arrayOfString1 == null) {
			return null;
		}
		int i = arrayOfString1.length;
		String[] arrayOfString2 = new String[i];
		for (int j = 0; j < i; j++) {
			arrayOfString2[j] = xssClean(arrayOfString1[j]);
		}
		return arrayOfString2;
	}

	private static String xssClean(String value) {
		AntiSamy antiSamy = new AntiSamy();
		try {
			if (policy == null) {
				log.error("Antisamy配置文件加载失败==============" + value);
				return value;
			}
			final CleanResults cr = antiSamy.scan(value, policy);
			// 安全的HTML输出
			String resultValue = cr.getCleanHTML();
			//对转义的html特殊字符进行反转义，如 <、>、" 等
			return StringEscapeUtils.unescapeHtml4(resultValue);
		} catch (Exception e) {
			log.error("Antisamy过滤特殊字符异常==============" + value, e);
		}
		return value;
	}
}
