You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

filter.php 7.3 KiB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. namespace Kuxin;
  3. /**
  4. * Class Filter
  5. *
  6. * @package Kuxin
  7. * @author Pakey <pakey@qq.com>
  8. */
  9. class Filter
  10. {
  11. /**
  12. * 默认验证规则
  13. *
  14. * @var array
  15. */
  16. protected static $validate = [
  17. //必填
  18. 'require' => '/.+/',
  19. 'required' => '/.+/',
  20. 'string' => '/.+/',
  21. 'str' => '/.+/',
  22. 'mix' => '/.+/',
  23. 'mixed' => '/.+/',
  24. //邮箱
  25. 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',
  26. //链接
  27. 'url' => '/^https?:\/\/[a-zA-Z0-9]+\.[a-zA-Z0-9]+[\/=\?%\-&_~`@\[\]\':+!]*([^<>\"\"])*$/',
  28. 'path' => '/^\/[\w\.\/]+?$/',
  29. //货币
  30. 'currency' => '/^\d+(\.\d+)?$/',
  31. //数字
  32. 'number' => '/^\d+$/',
  33. //邮编
  34. 'zip' => '/^[0-9]\d{5}$/',
  35. //电话
  36. 'mobile' => '/^1[\d]{10}$/',
  37. //整型
  38. 'integer' => '/^[-\+]?\d+$/',
  39. 'int' => '/^[-\+]?\d+$/',
  40. //带小数点
  41. 'double' => '/^[-\+]?\d+(\.\d+)?$/',
  42. 'float' => '/^[-\+]?\d+(\.\d+)?$/',
  43. //英文字母
  44. 'english' => '/^[a-zA-Z]+$/',
  45. //
  46. 'key' => '/^[\w\-\#]+$/',
  47. //中文汉字
  48. 'chinese' => '/^[\x{4e00}-\x{9fa5}]+$/u',
  49. //拼音
  50. 'pinyin' => '/^[a-zA-Z0-9\-\_]+$/',
  51. //用户名
  52. 'username' => '/^(?!_)(?!.*?_$)[a-zA-Z0-9_\x{4e00}-\x{9fa5}]{3,15}$/u',
  53. //英文字符
  54. 'en' => '/^[a-zA-Z0-9_\s\-\.]+$/',
  55. //中文字符
  56. 'cn' => '/^[\w\s\-\x{4e00}-\x{9fa5}]+$/u',
  57. //安全字符串
  58. 'safestring' => '/^[^\$\?]+$/',
  59. ];
  60. /**
  61. * 校验变量
  62. *
  63. * @param $value
  64. * @param $rule
  65. * @return mixed
  66. */
  67. public static function check($value, $rule)
  68. {
  69. switch ($rule) {
  70. case 'mixed':
  71. case 'mix':
  72. break;
  73. case 'int':
  74. $value = (int)$value;
  75. break;
  76. case 'float':
  77. $value = (float)$value;
  78. break;
  79. case 'str':
  80. case 'string':
  81. $value = (string)$value;
  82. break;
  83. case 'arr':
  84. case 'array':
  85. $value = (array)$value;
  86. break;
  87. case 'time':
  88. $value = strtotime($value) ? $value : '0';
  89. break;
  90. default:
  91. if (is_array($rule)) {
  92. if (!in_array($value, $rule)) {
  93. $value = null;
  94. }
  95. } elseif (false === Filter::regex($value, $rule)) {
  96. $value = null;
  97. };
  98. }
  99. return $value;
  100. }
  101. /**
  102. * 判断是否符合正则
  103. *
  104. * @param $value
  105. * @param $rule
  106. * @return bool
  107. */
  108. public static function regex($value, string $rule): bool
  109. {
  110. if (strpos($rule, '|')) {
  111. $rules = explode('|', $rule);
  112. } else {
  113. $rules = [$rule];
  114. }
  115. foreach ($rules as $rule) {
  116. if (in_array($rule, ['unique', 'ignore'])) {
  117. continue;
  118. }
  119. if (isset(self::$validate[$rule])) {
  120. $rule = self::$validate[$rule];
  121. }
  122. if (preg_match($rule, strval($value)) !== 1) {
  123. return false;
  124. }
  125. }
  126. return true;
  127. }
  128. /**
  129. * 安全的剔除字符 单行等 用于搜索 链接等地方
  130. *
  131. * @param $str
  132. * @return mixed|string
  133. */
  134. public static function safeWord(string $str): string
  135. {
  136. if (strlen($str) == 0) {
  137. return '';
  138. }
  139. $str = strip_tags($str);
  140. $badString = '~!@#$%^&*()+|=\\{}[];\'"/<>?';
  141. $length = strlen($badString);
  142. $pos = 0;
  143. while ($pos < $length) {
  144. $str = str_replace($badString{$pos}, '', $str);
  145. $pos++;
  146. }
  147. return preg_replace('/([\:\r\n\t]+)/', '', $str);
  148. }
  149. /**
  150. * 过滤掉html字符
  151. *
  152. * @param string $text
  153. * @param string $tags 允许的html标签
  154. * @return mixed|string
  155. */
  156. public static function safetext(string $text, string $tags = 'br'): string
  157. {
  158. $text = trim($text);
  159. //完全过滤注释
  160. $text = preg_replace('/<!--?.*-->/', '', $text);
  161. //完全过滤动态代码
  162. $text = preg_replace('/<\?|\?' . '>/', '', $text);
  163. //完全过滤js
  164. $text = preg_replace('/<script?.*\/script>/', '', $text);
  165. $text = preg_replace('/\&#\d+;/', '', $text);
  166. $text = preg_replace('/\&#\w{4}/', '', $text);
  167. $text = str_replace('[', '&#091;', $text);
  168. $text = str_replace(']', '&#093;', $text);
  169. $text = str_replace('|', '&#124;', $text);
  170. //br
  171. $text = preg_replace('/<br(\s\/)?' . '>/i', '[br]', $text);
  172. $text = preg_replace('/<p(\s\/)?' . '>/i', '[br]', $text);
  173. $text = preg_replace('/(\[br\]\s*){10,}/i', '[br]', $text);
  174. //过滤危险的属性,如:过滤on事件lang js
  175. while (preg_match('/(<[^><]+)( lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i', $text, $mat)) {
  176. $text = str_replace($mat[0], $mat[1], $text);
  177. }
  178. while (preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i', $text, $mat)) {
  179. $text = str_replace($mat[0], $mat[1] . $mat[3], $text);
  180. }
  181. //允许的HTML标签
  182. $text = preg_replace('/<(' . $tags . ')( [^><\[\]]*)>/i', '[\1\2]', $text);
  183. $text = preg_replace('/<\/(' . $tags . ')>/Ui', '[/\1]', $text);
  184. //过滤多余html
  185. $text = preg_replace('/<\/?(html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml|table|td|th|tr|i|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a|b|strong)[^><]*>/i', '', $text);
  186. //过滤合法的html标签
  187. while (preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i', $text, $mat)) {
  188. $text = str_replace($mat[0], str_replace('>', ']', str_replace('<', '[', $mat[0])), $text);
  189. }
  190. //转换引号
  191. while (preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i', $text, $mat)) {
  192. $text = str_replace($mat[0], $mat[1] . '|' . $mat[3] . '|' . $mat[4], $text);
  193. }
  194. //过滤错误的单个引号
  195. while (preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i', $text, $mat)) {
  196. $text = str_replace($mat[0], str_replace($mat[1], '', $mat[0]), $text);
  197. }
  198. //转换其它所有不合法的 < >
  199. $text = str_replace('<', '&lt;', $text);
  200. $text = str_replace('>', '&gt;', $text);
  201. $text = str_replace('"', '&quot;', $text);
  202. //反转换
  203. $text = str_replace('[', '<', $text);
  204. $text = str_replace(']', '>', $text);
  205. $text = str_replace('|', '"', $text);
  206. //过滤多余空格
  207. $text = str_replace(' ', ' ', $text);
  208. return $text;
  209. }
  210. /**
  211. * 深度过滤 去掉url
  212. * @param $text
  213. * @return string|string[]|null
  214. */
  215. public static function clearUrl($text)
  216. {
  217. $text = self::safetext($text);
  218. return $text = preg_replace(self::$validate['ur;'], '', $text);
  219. }
  220. }