<commit_before><?php

/**
 * 安全相关类
 * 包括内容：XSS，CSRF，密码安全
 * 
 * @author ShuangYa
 * @package SYFramework
 * @category Library
 * @link http://www.sylingd.com/
 * @copyright Copyright (c) 2015 ShuangYa
 * @license http://lab.sylingd.com/go.php?name=framework&type=license
 */

namespace sy\lib;
use \Sy;
use \sy\lib\YCookie;
use \sy\base\SYException;

class YSecurity {
	protected static $csrf_config = ['tokenName' => '_csrf_token', 'cookieName' => '_csrf_token'];
	protected static $csrf_hash = NULL;
	/**
	 * csrf验证
	 * @param boolean $show_error 验证不通过时，是否直接报错
	 * @return boolean
	 */
	public static function csrfVerify($show_error = TRUE, $requestId = NULL) {
		//仅POST需要验证csrf
		if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') {
			static::csrfSetCookie($requestId);
			return TRUE;
		}
		if (NULL !== $requestId) {
			if (!isset(Sy::$httpRequest[$requestId]->post[static::$csrf_config['tokenName']]) || YCookie::get(static::$csrf_config['cookieName'], $requestId) === NULL || (Sy::$httpRequest[$requestId]->post[static::$csrf_config['tokenName']] !== YCookie::get(static::$csrf_config['cookieName'], $requestId))) {
				if ($show_error) {
					Sy::$httpResponse[$requestId]->status(403);
					Sy::$httpResponse[$requestId]->end();
					return;
				} else {
					return FALSE;
				}
			}
			unset(Sy::$httpRequest[$requestId]->post[static::$csrf_config['tokenName']]);
		} else {
			if (!isset($_POST[static::$csrf_config['tokenName']]) || YCookie::get(static::$csrf_config['cookieName']) === NULL || ($_POST[static::$csrf_config['tokenName']] !== YCookie::get(static::$csrf_config['cookieName']))) {
				if ($show_error) {
					header(Sy::getHttpStatus('403'));
					exit;
				} else {
					return FALSE;
				}
			}
			unset($_POST[static::$csrf_config['tokenName']]);
		}
		return TRUE;
	}
	/**
	 * 生成/获取csrf_hash
	 * @return string
	 */
	public static function csrfGetHash() {
		if (static::$csrf_hash === NULL) {
			$cookie_hash = YCookie::get(static::$csrf_config['cookieName']);
			if ($cookie_hash !== NULL && preg_match('/^[0-9a-f]{32}$/iS', $cookie_hash)) {
				return static::$csrf_hash = $cookie_hash;
			}
			static::$csrf_hash = md5(uniqid(mt_rand(), TRUE));
		}
		return static::$csrf_hash;
	}
	/**
	 * 设置CSRF-Cookie
	 * @access public
	 */
	public static function csrfSetCookie($requestId = NULL) {
		$param = ['name' => static::$csrf_config['cookieName'], 'value' => static::csrfGetHash(), 'httponly' => TRUE];
		if ($requestId !== NULL) {
			$param['requestId'] = $requestId;
		}
		YCookie::set($param);
	}
	/**
	 * 进行可逆加密
	 * @access public
	 * @param string $string 需要加密/解密的字符串
	 * @param string $operation 类型，加密为ENCODE，解密为DECODE
	 * @param string $key 加密/解密Key。默认从config读取
	 * @param int $expire 过期时间，单位：秒。0为不过期
	 * @return string
	 */
	public static function securityCode($string, $operation = 'ENCODE', $key = '', $expire = 0) {
		$ckey_length = 4;<commit_msg>Fix. csrf not work well on swoole<commit_after><?php

/**
 * 安全相关类
 * 包括内容：XSS，CSRF，密码安全
 * 
 * @author ShuangYa
 * @package SYFramework
 * @category Library
 * @link http://www.sylingd.com/
 * @copyright Copyright (c) 2015 ShuangYa
 * @license http://lab.sylingd.com/go.php?name=framework&type=license
 */

namespace sy\lib;
use \Sy;
use \sy\lib\YCookie;
use \sy\base\SYException;

class YSecurity {
	protected static $csrf_config = ['tokenName' => '_csrf_token', 'cookieName' => '_csrf_token'];
	protected static $csrf_hash = NULL;
	/**
	 * csrf验证
	 * @param boolean $show_error 验证不通过时，是否直接报错
	 * @return boolean
	 */
	public static function csrfVerify($show_error = TRUE, $requestId = NULL) {
		//仅POST需要验证csrf
		$REQUEST_METHOD = ($requestId === NULL ? $_SERVER['REQUEST_METHOD'] : Sy::$httpRequest[$requestId]->server['request_method']);
		if (strtoupper($REQUEST_METHOD) !== 'POST') {
			static::csrfSetCookie($requestId);
			return TRUE;
		}
		if (NULL !== $requestId) {
			if (!isset(Sy::$httpRequest[$requestId]->post[static::$csrf_config['tokenName']]) || YCookie::get(static::$csrf_config['cookieName'], $requestId) === NULL || (Sy::$httpRequest[$requestId]->post[static::$csrf_config['tokenName']] !== YCookie::get(static::$csrf_config['cookieName'], $requestId))) {
				if ($show_error) {
					Sy::$httpResponse[$requestId]->status(403);
					Sy::$httpResponse[$requestId]->end();
					return;
				} else {
					return FALSE;
				}
			}
			unset(Sy::$httpRequest[$requestId]->post[static::$csrf_config['tokenName']]);
		} else {
			if (!isset($_POST[static::$csrf_config['tokenName']]) || YCookie::get(static::$csrf_config['cookieName']) === NULL || ($_POST[static::$csrf_config['tokenName']] !== YCookie::get(static::$csrf_config['cookieName']))) {
				if ($show_error) {
					header(Sy::getHttpStatus('403'));
					exit;
				} else {
					return FALSE;
				}
			}
			unset($_POST[static::$csrf_config['tokenName']]);
		}
		return TRUE;
	}
	/**
	 * 生成/获取csrf_hash
	 * @return string
	 */
	public static function csrfGetHash($requestId = NULL) {
		if (static::$csrf_hash === NULL) {
			$cookie_hash = YCookie::get(static::$csrf_config['cookieName'], $requestId);
			if ($cookie_hash !== NULL && preg_match('/^[0-9a-f]{32}$/iS', $cookie_hash)) {
				return static::$csrf_hash = $cookie_hash;
			}
			static::$csrf_hash = md5(uniqid(microtime(), TRUE));
		}
		return static::$csrf_hash;
	}
	/**
	 * 设置CSRF-Cookie
	 * @access public
	 */
	public static function csrfSetCookie($requestId = NULL) {
		$param = ['name' => static::$csrf_config['cookieName'], 'value' => static::csrfGetHash($requestId), 'httponly' => TRUE];
		if ($requestId !== NULL) {
			$param['requestId'] = $requestId;
		}
		YCookie::set($param);
	}
	/**
	 * 进行可逆加密
	 * @access public
	 * @param string $string 需要加密/解密的字符串
	 * @param string $operation 类型，加密为ENCODE，解密为DECODE
	 * @param string $key 加密/解密Key。默认从config读取
	 * @param int $expire 过期时间，单位：秒。0为不过期
	 * @return string
	 */
	public static function securityCode($string, $operation = 'ENCODE', $key = '', $expire = 0) {
		$ckey_length = 4;
{'fraction_non_alphanumeric': 0.1933970169264287, 'fraction_numerical': 0.006033182503770739, 'mean_word_length': 4.700095510983763, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1850984', 'n_tokens_mistral': 2412, 'n_tokens_neox': 2276, 'n_words': 362}