<?php
class Webscan {
	/**
	 * 安全检测
	 */
	public function run() {
		// get拦截规则
		$getfilter = "<[^>]*?=[^>]*?&#[^>]*?>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\()|<[^>]*?\\b(onerror|onmousemove|onload|onclick|onmouseover)\\b[^>]*?>|^\\+\\/v(8|9)|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
		// post拦截规则
		$postfilter = "<[^>]*?=[^>]*?&#[^>]*?>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\()|<[^>]*?\\b(onerror|onmousemove|onload|onclick|onmouseover)\\b[^>]*?>|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
		// cookie拦截规则
		$cookiefilter = "\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
		if (C('WEBSCAN_GET', 1)) {
			foreach($_GET as $key => $value) {
				self :: stopAttack($key, $value, $getfilter, "GET");
			}
		}
		if (C('WEBSCAN_POST', 1)) {
			foreach($_POST as $key => $value) {
				self :: stopAttack($key, $value, $postfilter, "POST");
			}
		}
		if (C('WEBSCAN_COOKIE', 1)) {
			foreach($_COOKIE as $key => $value) {
				self :: stopAttack($key, $value, $cookiefilter, "COOKIE");
			}
		}
		if (C('WEBSCAN_REFERRER', 1)) {
			foreach($webscan_referer as $key => $value) {
				self :: stopAttack($key, $value, $postfilter, "REFERRER");
			}
		}
	}
	/**
	 * 攻击检查拦截
	 */
	private function stopAttack($StrFiltKey, $StrFiltValue, $ArrFiltReq, $method) {
		$StrFiltValue = self :: arrToStr($StrFiltValue);
		if (preg_match("/" . $ArrFiltReq . "/is", $StrFiltValue) == 1) {
			self :: slog(array('ip' => IP, 'time' => TIME, 'page' => $_SERVER['PHP_SELF'], 'method' => $method, 'rkey' => $StrFiltKey, 'rdata' => $StrFiltValue, 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'request_url' => $_SERVER['REQUEST_URI'], 'hash' => md5($StrFiltValue)));
			show_error(L('ATTACK_NOTICE', 'scan'));
		}
		if (preg_match("/" . $ArrFiltReq . "/is", $StrFiltKey) == 1) {
			self :: slog(array('ip' => IP, 'time' => TIME, 'page' => $_SERVER['PHP_SELF'], 'method' => $method, 'rkey' => $StrFiltKey, 'rdata' => $StrFiltKey, 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'request_url' => $_SERVER["REQUEST_URI"], 'hash' => md5($StrFiltKey)));
			show_error(L('ATTACK_NOTICE', 'scan'));
		}
	}
	/**
	 * 数组转换成字符串
	 */
	private function arrToStr($arr) {
		if (is_array($arr)) {
			$str = '';
			foreach ($arr as $val) {
				$str .= is_array($val)?arrToStr($val):$val;
			}
		} else $str = $arr;
		return $str;
	}
	/**
	 * 攻击记录入库
	 */
	private function slog($arr) {
		if (C('WEBSCAN_LOG', 1)) {
			$obj = M('webscan');
			if (!$obj -> where('hash=' . $arr['hash']) -> find()) {
				$obj -> create($arr) -> add();
				if ($obj -> count() > 1000) {
					$obj -> order('id ASC') -> limit(500) -> delete();
				}
			}
		}
	}
}