filter.class.php 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409
  1. <?php
  2. /**
  3. * ZenTaoPHP的验证和过滤类。
  4. * The validater and fixer class file of ZenTaoPHP framework.
  5. *
  6. * The author disclaims copyright to this source code. In place of
  7. * a legal notice, here is a blessing:
  8. *
  9. * May you do good and not evil.
  10. * May you find forgiveness for yourself and forgive others.
  11. * May you share freely, never taking more than you give.
  12. */
  13. /**
  14. * validater类,检查数据是否符合规则。
  15. * The validater class, checking data by rules.
  16. *
  17. * @package framework
  18. */
  19. class baseValidater
  20. {
  21. /**
  22. * 最大参数个数。
  23. * The max count of args.
  24. */
  25. const MAX_ARGS = 3;
  26. /**
  27. * 是否是Bool类型。
  28. * Bool checking.
  29. *
  30. * @param bool $var
  31. * @static
  32. * @access public
  33. * @return bool
  34. */
  35. public static function checkBool($var)
  36. {
  37. return filter_var($var, FILTER_VALIDATE_BOOLEAN);
  38. }
  39. /**
  40. * 是否是Int类型。
  41. * Int checking.
  42. *
  43. * @param int $var
  44. * @static
  45. * @access public
  46. * @return bool
  47. */
  48. public static function checkInt($var)
  49. {
  50. $args = func_get_args();
  51. if($var != 0) $var = ltrim($var, 0); // 去掉变量左边的0,00不是Int类型
  52. // Remove the left 0, filter don't think 00 is an int.
  53. /* 如果设置了最小的整数。 Min is setted. */
  54. if(isset($args[1]))
  55. {
  56. /* 如果最大的整数也设置了。 And Max is setted. */
  57. if(isset($args[2]))
  58. {
  59. $options = array('options' => array('min_range' => $args[1], 'max_range' => $args[2]));
  60. }
  61. else
  62. {
  63. $options = array('options' => array('min_range' => $args[1]));
  64. }
  65. return filter_var($var, FILTER_VALIDATE_INT, $options);
  66. }
  67. else
  68. {
  69. return filter_var($var, FILTER_VALIDATE_INT);
  70. }
  71. }
  72. /**
  73. * 检查不是Int类型。
  74. * Not int checking.
  75. *
  76. * @param int $var
  77. * @static
  78. * @access public
  79. * @return bool
  80. */
  81. public static function checkNotInt($var)
  82. {
  83. return !self::checkInt($var);
  84. }
  85. /**
  86. * 检查Float类型。
  87. * Float checking.
  88. *
  89. * @param float $var
  90. * @param string $decimal
  91. * @static
  92. * @access public
  93. * @return bool
  94. */
  95. public static function checkFloat($var, $decimal = '.')
  96. {
  97. return filter_var($var, FILTER_VALIDATE_FLOAT, array('options' => array('decimal' => $decimal)));
  98. }
  99. /**
  100. * 检查Email。
  101. * Email checking.
  102. *
  103. * @param string $var
  104. * @static
  105. * @access public
  106. * @return bool
  107. */
  108. public static function checkEmail($var)
  109. {
  110. return filter_var($var, FILTER_VALIDATE_EMAIL);
  111. }
  112. /**
  113. * 检查电话或手机号码
  114. * Check phone number.
  115. *
  116. * @param string $var
  117. * @static
  118. * @access public
  119. * @return void
  120. */
  121. public static function checkPhone($var)
  122. {
  123. return (validater::checkTel($var) or validater::checkMobile($var));
  124. }
  125. /**
  126. * 检查电话号码
  127. * Check tel number.
  128. *
  129. * @param int $var
  130. * @static
  131. * @access public
  132. * @return void
  133. */
  134. public static function checkTel($var)
  135. {
  136. return preg_match("/^([0-9]{3,4}-?)?[0-9]{7,8}$/", $var) ? true : false;
  137. }
  138. /**
  139. * 检查手机号码
  140. * Check mobile number.
  141. *
  142. * @param string $var
  143. * @static
  144. * @access public
  145. * @return void
  146. */
  147. public static function checkMobile($var)
  148. {
  149. return preg_match("/^1[3-9]{1}[0-9]{9}$/", $var) ? true : false;
  150. }
  151. /**
  152. * 检查网址。
  153. * 该规则不支持中文字符的网址。
  154. *
  155. * URL checking.
  156. * The check rule of filter don't support chinese.
  157. *
  158. * @param string $var
  159. * @static
  160. * @access public
  161. * @return bool
  162. */
  163. public static function checkURL($var)
  164. {
  165. return filter_var($var, FILTER_VALIDATE_URL);
  166. }
  167. /**
  168. * 检查域名,不支持中文。
  169. * Domain checking.
  170. *
  171. * The check rule of filter don't support chinese.
  172. *
  173. * @param string $var
  174. * @static
  175. * @access public
  176. * @return bool
  177. */
  178. public static function checkDomain($var)
  179. {
  180. return preg_match('/^([a-z0-9-]+\.)+[a-z]{2,15}$/', $var) ? true : false;
  181. }
  182. /**
  183. * 检查IP地址。
  184. * IP checking.
  185. *
  186. * @param ip $var
  187. * @param string $range all|public|static|private
  188. * @static
  189. * @access public
  190. * @return bool
  191. */
  192. public static function checkIP($var, $range = 'all')
  193. {
  194. if($range == 'all') return filter_var($var, FILTER_VALIDATE_IP);
  195. if($range == 'public static') return filter_var($var, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
  196. if($range == 'private')
  197. {
  198. if($var == '127.0.0.1' or filter_var($var, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false) return true;
  199. return false;
  200. }
  201. }
  202. /**
  203. * 身份证号检查。
  204. * Idcard checking.
  205. *
  206. * @access public
  207. * @return void
  208. */
  209. public static function checkIdcard($idcard)
  210. {
  211. if(strlen($idcard) != 18) return false;
  212. $idcard = strtoupper($idcard);
  213. $cityList = array(
  214. '11', '12', '13', '14', '15', '21', '22',
  215. '23', '31', '32', '33', '34', '35', '36',
  216. '37', '41', '42', '43', '44', '45', '46',
  217. '50', '51', '52', '53', '54', '61', '62',
  218. '63', '64', '65', '71', '81', '82', '91'
  219. );
  220. if(!preg_match('/^([\d]{17}[xX\d]|[\d]{15})$/', $idcard)) return false;
  221. if(!in_array(substr($idcard, 0, 2), $cityList)) return false;
  222. $baseCode = substr($idcard, 0, 17);
  223. $verifyCode = substr($idcard, 17, 1);
  224. $interference = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
  225. $verifyConfig = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
  226. $total = 0;
  227. for($i = 0; $i < 17; $i++) $total += substr($baseCode, $i, 1) * $interference[$i];
  228. $mod = $total % 11;
  229. return $verifyCode == $verifyConfig[$mod];
  230. }
  231. /**
  232. * 日期检查。注意,2009-09-31是一个合法日期,系统会将它转换为2009-10-01。
  233. * Date checking. Note: 2009-09-31 will be an valid date, because strtotime auto fixed it to 10-01.
  234. *
  235. * @param date $date
  236. * @static
  237. * @access public
  238. * @return bool
  239. */
  240. public static function checkDate($date)
  241. {
  242. if(empty($date)) return true;
  243. if($date == '0000-00-00') return true;
  244. if(preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $parts)) return checkdate($parts[2], $parts[3], $parts[1]);
  245. return false;
  246. }
  247. /**
  248. * Check datetime.
  249. *
  250. * @param string $datetime
  251. * @static
  252. * @access public
  253. * @return bool
  254. */
  255. public static function checkDatetime($datetime)
  256. {
  257. if(empty($datetime)) return true;
  258. if($datetime == '0000-00-00') return true;
  259. if($datetime == '0000-00-00 00:00:00') return true;
  260. $date = substr($datetime, 0, 10);
  261. if(preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $parts)) return checkdate($parts[2], $parts[3], $parts[1]);
  262. return false;
  263. }
  264. /**
  265. * 检查正则表达式。
  266. * REG checking.
  267. *
  268. * @param string $var
  269. * @param string $reg
  270. * @static
  271. * @access public
  272. * @return bool
  273. */
  274. public static function checkREG($var, $reg)
  275. {
  276. return filter_var($var, FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => $reg)));
  277. }
  278. /**
  279. * 检查长度。
  280. * Length checking.
  281. *
  282. * @param string $var
  283. * @param string $max
  284. * @param int $min
  285. * @static
  286. * @access public
  287. * @return bool
  288. */
  289. public static function checkLength($var, $max, $min = 0)
  290. {
  291. $length = function_exists('mb_strlen') ? mb_strlen($var, 'utf-8') : strlen($var);
  292. return self::checkInt($length, $min, $max);
  293. }
  294. /**
  295. * 检查不为空。
  296. * Not empty checking.
  297. *
  298. * @param mixed $var
  299. * @static
  300. * @access public
  301. * @return bool
  302. */
  303. public static function checkNotEmpty($var)
  304. {
  305. return !empty($var);
  306. }
  307. /**
  308. * 检查为空。
  309. * Empty checking.
  310. *
  311. * @param mixed $var
  312. * @static
  313. * @access public
  314. * @return bool
  315. */
  316. public static function checkEmpty($var)
  317. {
  318. if(is_null($var)) return true;
  319. return strlen(trim($var)) == 0;
  320. }
  321. /**
  322. * 检查用户名。
  323. * Account checking.
  324. *
  325. * @param string $var
  326. * @static
  327. * @access public
  328. * @return bool
  329. */
  330. public static function checkAccount($var)
  331. {
  332. global $config;
  333. $accountRule = empty($config->accountRule) ? '|^[a-zA-Z0-9_]{1}[a-zA-Z0-9_\.]{1,}[a-zA-Z0-9_]{1}$|' : $config->accountRule;
  334. return self::checkREG($var, $accountRule);
  335. }
  336. /**
  337. * 检查Code。
  338. * Check code.
  339. *
  340. * @param string $var
  341. * @static
  342. * @access public
  343. * @return bool
  344. */
  345. public static function checkCode($var)
  346. {
  347. return self::checkREG($var, '|^[A-Za-z0-9_]+$|');
  348. }
  349. /**
  350. * 检查验证码。
  351. * Check captcha.
  352. *
  353. * @param mixed $var
  354. * @static
  355. * @access public
  356. * @return bool
  357. */
  358. public static function checkCaptcha($var)
  359. {
  360. if(!isset($_SESSION['captcha'])) return false;
  361. return $var == $_SESSION['captcha'];
  362. }
  363. /**
  364. * 是否等于给定的值。
  365. * Must equal a value.
  366. *
  367. * @param mixed $var
  368. * @param mixed $value
  369. * @static
  370. * @access public
  371. * @return bool
  372. */
  373. public static function checkEqual($var, $value)
  374. {
  375. return $var == $value;
  376. }
  377. /**
  378. * 检查不等于给定的值
  379. * Must not equal a value.
  380. *
  381. * @param mixed $var
  382. * @param mixed $value
  383. * @static
  384. * @access public
  385. * @return bool
  386. */
  387. public static function checkNotEqual($var, $value)
  388. {
  389. return $var != $value;
  390. }
  391. /**
  392. * 检查大于给定的值。
  393. * Must greater than a value.
  394. *
  395. * @param mixed $var
  396. * @param mixed $value
  397. * @static
  398. * @access public
  399. * @return bool
  400. */
  401. public static function checkGT($var, $value)
  402. {
  403. return $var > $value;
  404. }
  405. /**
  406. * 检查小于给定的值
  407. * Must less than a value.
  408. *
  409. * @param mixed $var
  410. * @param mixed $value
  411. * @static
  412. * @access public
  413. * @return bool
  414. */
  415. public static function checkLT($var, $value)
  416. {
  417. return $var < $value;
  418. }
  419. /**
  420. * 检查大于等于给定的值
  421. * Must greater than a value or equal a value.
  422. *
  423. * @param mixed $var
  424. * @param mixed $value
  425. * @static
  426. * @access public
  427. * @return bool
  428. */
  429. public static function checkGE($var, $value)
  430. {
  431. return $var >= $value;
  432. }
  433. /**
  434. * 检查小于等于给定的值
  435. * Must less than a value or equal a value.
  436. *
  437. * @param mixed $var
  438. * @param mixed $value
  439. * @static
  440. * @access public
  441. * @return bool
  442. */
  443. public static function checkLE($var, $value)
  444. {
  445. return $var <= $value;
  446. }
  447. /**
  448. * 检查是否在给定的列表里面。
  449. * Must in value list.
  450. *
  451. * @param mixed $var
  452. * @param mixed $value
  453. * @static
  454. * @access public
  455. * @return bool
  456. */
  457. public static function checkIn($var, $value)
  458. {
  459. if(!is_array($value)) $value = explode(',', $value);
  460. return in_array($var, $value);
  461. }
  462. /**
  463. * 检查文件名。
  464. * Check file name.
  465. *
  466. * @param string $var
  467. * @static
  468. * @access public
  469. * @return bool
  470. */
  471. public static function checkFileName($var)
  472. {
  473. return !preg_match('/>+|:+|<+/', $var);
  474. }
  475. /**
  476. * 检查敏感词。
  477. * Check sensitive words.
  478. *
  479. * @param object $vars
  480. * @param array $dicts
  481. * @static
  482. * @access public
  483. * @return void
  484. */
  485. public static function checkSensitive($vars, $dicts)
  486. {
  487. foreach($vars as $var)
  488. {
  489. if(!$var) continue;
  490. foreach($dicts as $dict)
  491. {
  492. if(strpos($var, $dict) === false) continue;
  493. if(strpos($var, $dict) !== false) return false;
  494. }
  495. }
  496. return true;
  497. }
  498. /**
  499. * 过滤附件。
  500. * Filter files.
  501. *
  502. * @access public
  503. * @return array
  504. */
  505. public static function filterFiles()
  506. {
  507. global $config;
  508. if(empty($_FILES)) return $_FILES;
  509. if(isset($_FILES['scriptFile'])) unset($_FILES['scriptFile']);
  510. foreach($_FILES as $varName => $files)
  511. {
  512. if(is_array($files['name']))
  513. {
  514. foreach($files['name'] as $fileName)
  515. {
  516. if(is_array($fileName))
  517. {
  518. foreach($fileName as $name)
  519. {
  520. $extension = ltrim(strrchr($name, '.'), '.');
  521. if(stripos(",{$config->file->dangers},", ",{$extension},") !== false)
  522. {
  523. unset($_FILES);
  524. return array();
  525. }
  526. }
  527. }
  528. else
  529. {
  530. $extension = ltrim(strrchr($fileName, '.'), '.');
  531. if(stripos(",{$config->file->dangers},", ",{$extension},") !== false)
  532. {
  533. unset($_FILES);
  534. return array();
  535. }
  536. }
  537. }
  538. }
  539. else
  540. {
  541. $extension = ltrim(strrchr($files['name'], '.'), '.');
  542. if(stripos(",{$config->file->dangers},", ",{$extension},") !== false)
  543. {
  544. unset($_FILES);
  545. return array();
  546. }
  547. }
  548. }
  549. return $_FILES;
  550. }
  551. /**
  552. * 过滤超级变量。
  553. * Filter super vars.
  554. *
  555. * @param array $super
  556. * @access public
  557. * @return array
  558. */
  559. public static function filterSuper($super)
  560. {
  561. if(!is_array($super)) return $super;
  562. $super = self::filterBadKeys($super);
  563. foreach($super as $key => $item)
  564. {
  565. if(is_array($item))
  566. {
  567. $item = self::filterBadKeys($item);
  568. foreach($item as $subkey => $subItem)
  569. {
  570. if(is_array($subItem)) continue;
  571. $subItem = self::filterTrojan($subItem);
  572. $super[$key][$subkey] = self::filterXSS($subItem);
  573. }
  574. }
  575. else
  576. {
  577. $item = self::filterTrojan($item);
  578. $super[$key] = self::filterXSS($item);
  579. }
  580. }
  581. return $super;
  582. }
  583. /**
  584. * 过滤不符合规则的键值。
  585. * Filter bad keys.
  586. *
  587. * @param mix $var
  588. * @access public
  589. * @return mix
  590. */
  591. public static function filterBadKeys($var)
  592. {
  593. global $config;
  594. if(empty($config->framework->filterBadKeys)) return $var;
  595. foreach($var as $key => $value) if(preg_match('/[^a-zA-Z0-9_\.\-]/', $key)) unset($var[$key]);
  596. return $var;
  597. }
  598. /**
  599. * 过滤木马代码。
  600. * Filter trojan codes.
  601. *
  602. * @param string $var
  603. * @access public
  604. * @return string
  605. */
  606. public static function filterTrojan($var)
  607. {
  608. global $config;
  609. if(empty($config->framework->filterTrojan)) return $var;
  610. if(strpos(htmlspecialchars_decode($var), '<?') === false) return $var;
  611. $var = (string)$var;
  612. $evils = array('eval', 'exec', 'passthru', 'proc_open', 'shell_exec', 'system', '$$', 'include', 'require', 'assert');
  613. $replaces = array('e v a l', 'e x e c', 'p a s s t h r u', 'p r o c _ o p e n', 's h e l l _ e x e c', 's y s t e m', '$ $', 'i n c l u d e', 'r e q u i r e', 'a s s e r t');
  614. $var = str_ireplace($evils, $replaces, $var);
  615. return $var;
  616. }
  617. /**
  618. * 过滤 XSS代码。
  619. * Filter XSS codes.
  620. *
  621. * @param string $var
  622. * @access public
  623. * @return string
  624. */
  625. public static function filterXSS($var)
  626. {
  627. global $config;
  628. if(empty($config->framework->filterXSS)) return $var;
  629. if(stripos($var, '&lt;script') !== false || stripos($var, '<script') !== false || stripos($var, '&lt;iframe') !== false || stripos($var, '<iframe') !== false)
  630. {
  631. $var = (string)$var;
  632. $evils = array('iframe', 'script', 'appendchild(', 'createElement(', 'xss.re', 'onfocus', 'onclick', 'innerHTML', 'replaceChild(', 'html(', 'append(', 'appendTo(', 'prepend(', 'prependTo(', 'after(', 'insertBefore', 'before(', 'replaceWith(', 'alert(', 'confirm(', 'eval(');
  633. $replaces = array('iframe', 'script', 'a p p e n d c h i l d (', 'c r e a t e E l e m e n t (', 'x s s . r e', 'o n f o c u s', 'o n c l i c k', 'i n n e r H T M L', 'r e p l a c e C h i l d (', 'h t m l (', 'a p p e n d (', 'a p p e n d T o (', 'p r e p e n d (', 'p r e p e n d T o (', 'a f t e r (', 'i n s e r t B e f o r e (', 'b e f o r e (', 'r e p l a c e W i t h (', 'a l e r t (', 'c o n f i r m (', 'eval(');
  634. $var = str_ireplace($evils, $replaces, $var);
  635. }
  636. /* Process like 'javascript:' */
  637. $var = preg_replace('/j\s*a\s*v\s*a\s*s\s*c\s*r\s*i\s*p\s*t\s*:/Ui', "j a v a s c r i p t :", $var);
  638. return $var;
  639. }
  640. /**
  641. * Filter param.
  642. *
  643. * @param array $var
  644. * @param string $type
  645. * @static
  646. * @access public
  647. * @return array
  648. */
  649. public static function filterParam($var, $type)
  650. {
  651. global $config, $filter, $app;
  652. $moduleName = $app->getModuleName();
  653. $methodName = $app->getMethodName();
  654. $params = $app->getParams();
  655. if($moduleName == 'tutorial' and $methodName == 'wizard' and isset($params['module']) and isset($params['method']))
  656. {
  657. $moduleName = $params['module'];
  658. $methodName = $params['method'];
  659. }
  660. if($type == 'cookie')
  661. {
  662. $pagerCookie = 'pager' . ucfirst($moduleName) . ucfirst($methodName);
  663. $filter->default->cookie[$pagerCookie] = 'int';
  664. }
  665. foreach($var as $key => $value)
  666. {
  667. if($config->requestType == 'GET' and $type == 'get' and isset($params[$key])) continue;
  668. $rules = '';
  669. if(isset($filter->{$moduleName}->{$methodName}->{$type}[$key]))
  670. {
  671. $rules = $filter->{$moduleName}->{$methodName}->{$type}[$key];
  672. }
  673. elseif(isset($filter->{$moduleName}->default->{$type}[$key]))
  674. {
  675. $rules = $filter->{$moduleName}->default->{$type}[$key];
  676. }
  677. elseif(isset($filter->default->{$type}[$key]))
  678. {
  679. $rules = $filter->default->{$type}[$key];
  680. }
  681. if(!self::checkByRule($value, $rules)) unset($var[$key]);
  682. }
  683. return $var;
  684. }
  685. /**
  686. * Replace space to i tag.
  687. *
  688. * @param string $var
  689. * @static
  690. * @access public
  691. * @return string
  692. */
  693. public static function replaceSpace2Tag($var)
  694. {
  695. $replacedTrojan = array('e v a l', 'e x e c', 'p a s s t h r u', 'p r o c _ o p e n', 's h e l l _ e x e c', 's y s t e m', '$ $', 'i n c l u d e', 'r e q u i r e', 'a s s e r t');
  696. $replacedXSS = array('a p p e n d c h i l d (', 'c r e a t e E l e m e n t (', 'x s s . r e', 'o n f o c u s', 'o n c l i c k', 'i n n e r H T M L', 'r e p l a c e C h i l d (', 'h t m l (', 'a p p e n d (', 'a p p e n d T o (', 'p r e p e n d (', 'p r e p e n d T o (', 'a f t e r (', 'i n s e r t B e f o r e (', 'b e f o r e (', 'r e p l a c e W i t h (');
  697. $replacsTrojan = array('e<i></i>v<i></i>a<i></i>l', 'e<i></i>x<i></i>e<i></i>c', 'p<i></i>a<i></i>s<i></i>s<i></i>t<i></i>h<i></i>r<i></i>u', 'p<i></i>r<i></i>o<i></i>c<i></i>_<i></i>o<i></i>p<i></i>e<i></i>n', 's<i></i>h<i></i>e<i></i>l<i></i>l<i></i>_<i></i>e<i></i>x<i></i>e<i></i>c', 's<i></i>y<i></i>s<i></i>t<i></i>e<i></i>m', '$<i></i>$', 'i<i></i>n<i></i>c<i></i>l<i></i>u<i></i>d<i></i>e', 'r<i></i>e<i></i>q<i></i>u<i></i>i<i></i>r<i></i>e', 'a<i></i>s<i></i>s<i></i>e<i></i>r<i></i>t');
  698. $replacsXSS = array('a<i></i>p<i></i>p<i></i>e<i></i>n<i></i>d<i></i>c<i></i>h<i></i>i<i></i>l<i></i>d<i></i>(', 'c<i></i>r<i></i>e<i></i>a<i></i>t<i></i>e<i></i>E<i></i>l<i></i>e<i></i>m<i></i>e<i></i>n<i></i>t<i></i>(', 'x<i></i>s<i></i>s<i></i>.<i></i>r<i></i>e', 'o<i></i>n<i></i>f<i></i>o<i></i>c<i></i>u<i></i>s', 'o<i></i>n<i></i>c<i></i>l<i></i>i<i></i>c<i></i>k', 'i<i></i>n<i></i>n<i></i>e<i></i>r<i></i>H<i></i>T<i></i>M<i></i>L', 'r<i></i>e<i></i>p<i></i>l<i></i>a<i></i>c<i></i>e<i></i>C<i></i>h<i></i>i<i></i>l<i></i>d<i></i>(', 'h<i></i>t<i></i>m<i></i>l<i></i>(', 'a<i></i>p<i></i>p<i></i>e<i></i>n<i></i>d<i></i>(', 'a<i></i>p<i></i>p<i></i>e<i></i>n<i></i>d<i></i>T<i></i>o<i></i>(', 'p<i></i>r<i></i>e<i></i>p<i></i>e<i></i>n<i></i>d<i></i>(', 'p<i></i>r<i></i>e<i></i>p<i></i>e<i></i>n<i></i>d<i></i>T<i></i>o<i></i>(', 'a<i></i>f<i></i>t<i></i>e<i></i>r<i></i>(', 'i<i></i>n<i></i>s<i></i>e<i></i>r<i></i>t<i></i>B<i></i>e<i></i>f<i></i>o<i></i>r<i></i>e<i></i>(', 'b<i></i>e<i></i>f<i></i>o<i></i>r<i></i>e<i></i>(', 'r<i></i>e<i></i>p<i></i>l<i></i>a<i></i>c<i></i>e<i></i>W<i></i>i<i></i>t<i></i>h<i></i>(', 'j<i></i>a<i></i>v<i></i>a<i></i>s<i></i>c<i></i>r<i></i>i<i></i>p<i></i>t<i></i>:');
  699. $var = str_ireplace($replacedTrojan, $replacsTrojan, $var);
  700. $var = str_ireplace($replacedXSS, $replacsXSS, $var);
  701. return $var;
  702. }
  703. /**
  704. * Check by rule.
  705. *
  706. * @param string $var
  707. * @param string $rule like: int account reg::md5 reg::/^[a-zA-Z0-9]+$/.
  708. * @static
  709. * @access public
  710. * @return bool
  711. */
  712. public static function checkByRule($var, $rule)
  713. {
  714. if(empty($rule)) return false;
  715. /* Parse rule to operator and param. */
  716. list($operator, $param) = baseValidater::parseRuleString($rule);
  717. /* check by operator. */
  718. $checkMethod = 'check' . $operator;
  719. if(method_exists('baseValidater', $checkMethod))
  720. {
  721. if(empty($param) and self::$checkMethod($var) === false) return false;
  722. if(!empty($param) and self::$checkMethod($var, $param) === false) return false;
  723. }
  724. elseif(function_exists('is_' . $operator))
  725. {
  726. $checkFunction = 'is_' . $operator;
  727. if(!$checkFunction($var)) return false;
  728. }
  729. else
  730. {
  731. return false;
  732. }
  733. return true;
  734. }
  735. /**
  736. * Parse rule string.
  737. *
  738. * @param string $rule like: int account reg::md5 reg::/^[a-zA-Z0-9]+$/.
  739. * @static
  740. * @access public
  741. * @return array
  742. */
  743. public static function parseRuleString($rule)
  744. {
  745. global $filter;
  746. if(strpos($rule, '::') !== false) list($operator, $param) = explode('::', $rule);
  747. if(strpos($rule, '::') === false) list($operator, $param) = array($rule, '');
  748. if($operator == 'reg' and isset($filter->rules->$param)) $param = $filter->rules->$param;
  749. return array($operator, $param);
  750. }
  751. /**
  752. * 调用一个方法进行检查。
  753. * Call a function to check it.
  754. *
  755. * @param mixed $var
  756. * @param string $func
  757. * @static
  758. * @access public
  759. * @return bool
  760. */
  761. public static function call($var, $func)
  762. {
  763. return filter_var($var, FILTER_CALLBACK, array('options' => $func));
  764. }
  765. }
  766. /**
  767. * fixer类,处理数据。
  768. * fixer class, to fix data types.
  769. *
  770. * @package framework
  771. */
  772. class baseFixer
  773. {
  774. /**
  775. * 处理的数据。
  776. * The data to be fixed.
  777. *
  778. * @var object
  779. * @access public
  780. */
  781. public $data;
  782. /**
  783. * 跳过处理的字段。
  784. * The fields to striped.
  785. *
  786. * @var array
  787. * @access public
  788. */
  789. public $stripedFields = array();
  790. /**
  791. * 构造方法,将超级全局变量转换为对象。
  792. * The construction function, according the scope, convert it to object.
  793. *
  794. * @param string $scope the scope of the var, should be post|get|server|session|cookie|env
  795. * @access public
  796. * @return void
  797. */
  798. public function __construct($scope)
  799. {
  800. switch ($scope)
  801. {
  802. case 'post':
  803. $this->data = (object)$_POST;
  804. break;
  805. case 'server':
  806. $this->data = (object)$_SERVER;
  807. break;
  808. case 'get':
  809. $this->data = (object)$_GET;
  810. break;
  811. case 'session':
  812. $this->data = (object)$_SESSION;
  813. break;
  814. case 'cookie':
  815. $this->data = (object)$_COOKIE;
  816. break;
  817. case 'env':
  818. $this->data = (object)$_ENV;
  819. break;
  820. case 'file':
  821. $this->data = (object)$_FILES;
  822. break;
  823. default:
  824. helper::end('scope not supported, should be post|get|server|session|cookie|env');
  825. }
  826. }
  827. /**
  828. * 工厂方法。
  829. * The factory function.
  830. *
  831. * @param string $scope
  832. * @access public
  833. * @return object fixer object.
  834. */
  835. public static function input($scope)
  836. {
  837. return new fixer($scope);
  838. }
  839. /**
  840. * 处理Email。
  841. * Email fix.
  842. *
  843. * @param string $fieldName
  844. * @access public
  845. * @return object fixer object.
  846. */
  847. public function cleanEmail($fieldName)
  848. {
  849. $fields = $this->processFields($fieldName);
  850. foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_EMAIL);
  851. return $this;
  852. }
  853. /**
  854. * url编码。
  855. * urlencode.
  856. *
  857. * @param string $fieldName
  858. * @access public
  859. * @return object fixer object.
  860. */
  861. public function encodeURL($fieldName)
  862. {
  863. $fields = $this->processFields($fieldName);
  864. $args = func_get_args();
  865. foreach($fields as $fieldName)
  866. {
  867. $this->data->$fieldName = isset($args[1]) ? filter_var($this->data->$fieldName, FILTER_SANITIZE_ENCODED, $args[1]) : filter_var($this->data->$fieldName, FILTER_SANITIZE_ENCODED);
  868. }
  869. return $this;
  870. }
  871. /**
  872. * 清理网址。
  873. * Clean the url.
  874. *
  875. * @param string $fieldName
  876. * @access public
  877. * @return object fixer object.
  878. */
  879. public function cleanURL($fieldName)
  880. {
  881. $fields = $this->processFields($fieldName);
  882. foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_URL);
  883. return $this;
  884. }
  885. /**
  886. * 处理Float类型。
  887. * Float fixer.
  888. *
  889. * @param string $fieldName
  890. * @access public
  891. * @return object fixer object.
  892. */
  893. public function cleanFloat($fieldName)
  894. {
  895. $fields = $this->processFields($fieldName);
  896. foreach($fields as $fieldName) $this->data->$fieldName = (float)filter_var($this->data->$fieldName, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND);
  897. return $this;
  898. }
  899. /**
  900. * 处理Int类型。
  901. * Int fixer.
  902. *
  903. * @param string $fieldName
  904. * @access public
  905. * @return object fixer object.
  906. */
  907. public function cleanInt($fieldName = '')
  908. {
  909. $fields = $this->processFields($fieldName);
  910. foreach($fields as $fieldName)
  911. {
  912. $filterVar = filter_var($this->data->$fieldName, FILTER_SANITIZE_NUMBER_INT);
  913. if(empty($filterVar)) $filterVar = 0;
  914. $this->data->$fieldName = (int)$filterVar;
  915. }
  916. return $this;
  917. }
  918. /**
  919. * 将字符串转换为可以在浏览器查看的编码。
  920. * Special chars.
  921. *
  922. * @param string $fieldName
  923. * @access public
  924. * @return object fixer object
  925. */
  926. public function specialChars($fieldName)
  927. {
  928. $fields = $this->processFields($fieldName);
  929. foreach($fields as $fieldName)
  930. {
  931. if(empty($this->stripedFields) or !isset($this->stripedFields[$fieldName]))
  932. {
  933. $this->data->$fieldName = $this->specialArray($this->data->$fieldName);
  934. $this->stripedFields[$fieldName] = $fieldName;
  935. }
  936. }
  937. return $this;
  938. }
  939. /**
  940. * Special array
  941. *
  942. * @param mixed $data
  943. * @access public
  944. * @return mixed
  945. */
  946. public function specialArray($data)
  947. {
  948. /* Return directly if the $data is a numeric type to make sure $this->cleanInt() works. */
  949. if(is_numeric($data)) return $data;
  950. if(!is_array($data)) return htmlspecialchars($data, ENT_QUOTES);
  951. foreach($data as &$value) $value = $this->specialArray($value);
  952. return $data;
  953. }
  954. /**
  955. * 忽略该标签。
  956. * Strip tags
  957. *
  958. * @param string $fieldName
  959. * @param string $allowableTags
  960. * @param array $attributes
  961. * @access public
  962. * @return object fixer object
  963. */
  964. public function stripTags($fieldName, $allowedTags = '', $attributes = array())
  965. {
  966. $fields = $this->processFields($fieldName);
  967. foreach($fields as $fieldName)
  968. {
  969. if(!isset($this->stripedFields[$fieldName]) and (!defined('RUN_MODE') or RUN_MODE != 'admin'))
  970. {
  971. $this->data->$fieldName = self::stripDataTags($this->data->$fieldName, $allowedTags, $attributes);
  972. /* Code for bug #2721. */
  973. $this->data->$fieldName = baseValidater::replaceSpace2Tag($this->data->$fieldName);
  974. }
  975. $this->stripedFields[$fieldName] = $fieldName;
  976. }
  977. return $this;
  978. }
  979. /**
  980. * Strip tags for data
  981. *
  982. * @param string $data
  983. * @param string $allowedTags
  984. * @param array $attributes
  985. * @static
  986. * @access public
  987. * @return string
  988. */
  989. public static function stripDataTags($data, $allowedTags = '', $attributes = array())
  990. {
  991. if(empty($data)) return $data;
  992. global $app, $config;
  993. if(empty($allowedTags) and isset($config->allowedTags)) $allowedTags = $config->allowedTags;
  994. $usePurifier = isset($config->framework->purifier) ? $config->framework->purifier : false;
  995. if(!$usePurifier) return strip_tags($data, $allowedTags !== null && is_array($allowedTags) ? '<' . implode('><', $allowedTags) . '>' : $allowedTags);
  996. static $purifier;
  997. if(empty($purifier))
  998. {
  999. $app->loadClass('purifier', true);
  1000. $purifierConfig = HTMLPurifier_Config::createDefault();
  1001. $purifierConfig->set('Filter.YouTube', 1);
  1002. /* Disable caching. */
  1003. $purifierConfig->set('Cache.DefinitionImpl', null);
  1004. /* The name attribute is allowed. */
  1005. $purifierConfig->set('HTML.Attr.Name.UseCDATA', true);
  1006. $purifier = new HTMLPurifier($purifierConfig);
  1007. $def = $purifierConfig->getHTMLDefinition(true);
  1008. $def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
  1009. if(!empty($attributes))
  1010. {
  1011. foreach($attributes as $attribute)
  1012. {
  1013. list($element, $attribute, $values) = explode('|', $attribute);
  1014. $def->addAttribute($element, $attribute, $values);
  1015. }
  1016. }
  1017. }
  1018. /*
  1019. * purifier会把&nbsp;替换空格,kindeditor再会把行首的空格去掉。
  1020. * purifier will change &nbsp; to ' ', and kindeditor will remove the header space again.
  1021. **/
  1022. $data = str_replace('&nbsp;', '&spnb;', $data);
  1023. $data = $purifier->purify($data);
  1024. $data = str_replace('&amp;spnb;', '&nbsp;', $data);
  1025. return $data;
  1026. }
  1027. /**
  1028. * 去除字符串左右空格
  1029. * Remove the left and right Spaces of the string.
  1030. *
  1031. * @param string $fieldName
  1032. * @access public
  1033. * @return object fixer object
  1034. */
  1035. public function trim($fieldName)
  1036. {
  1037. $fields = $this->processFields($fieldName);
  1038. foreach($fields as $fieldName) $this->data->$fieldName = trim($this->data->$fieldName);
  1039. return $this;
  1040. }
  1041. /**
  1042. * 忽略处理给定的字段。
  1043. * Skip special chars check.
  1044. *
  1045. * @param string $filename
  1046. * @access public
  1047. * @return object fixer object
  1048. */
  1049. public function skipSpecial($fieldName)
  1050. {
  1051. $fields = $this->processFields($fieldName);
  1052. foreach($fields as $fieldName) $this->stripedFields[$fieldName] = $fieldName;
  1053. return $this;
  1054. }
  1055. /**
  1056. * 给字段添加引用,防止字符与关键字冲突。
  1057. * Quote
  1058. *
  1059. * @param string $fieldName
  1060. * @access public
  1061. * @return object fixer object
  1062. */
  1063. public function quote($fieldName)
  1064. {
  1065. $fields = $this->processFields($fieldName);
  1066. foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_MAGIC_QUOTES);
  1067. return $this;
  1068. }
  1069. /**
  1070. * 设置字段的默认值。
  1071. * Set default value of some fileds.
  1072. *
  1073. * @param string $fields
  1074. * @param mixed $value
  1075. * @access public
  1076. * @return object fixer object
  1077. */
  1078. public function setDefault($fields, $value)
  1079. {
  1080. $fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
  1081. foreach($fields as $fieldName) if(!isset($this->data->$fieldName) or empty($this->data->$fieldName)) $this->data->$fieldName = $value;
  1082. return $this;
  1083. }
  1084. /**
  1085. * 将字段的值进行json编码
  1086. * Cast fields to json type.
  1087. *
  1088. * @param string $filed
  1089. * @access public
  1090. * @return object fixer object
  1091. */
  1092. public function json($fields)
  1093. {
  1094. $fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
  1095. foreach($fields as $field)
  1096. {
  1097. if(isset($this->data->$field)) $this->data->$field = json_encode($this->data->$field);
  1098. }
  1099. return $this;
  1100. }
  1101. /**
  1102. * 将字段的值进行HTML标签解码
  1103. * Html decode fields
  1104. *
  1105. * @param string $filed
  1106. * @access public
  1107. * @return object fixer object
  1108. */
  1109. public function unHtml($fields)
  1110. {
  1111. $fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
  1112. foreach($fields as $field)
  1113. {
  1114. if(isset($this->data->$field)) $this->data->$field = htmlspecialchars_decode($this->data->$field);
  1115. }
  1116. return $this;
  1117. }
  1118. /**
  1119. * 如果条件为真,则为字段赋值。
  1120. * Set value of a filed on the condition is true.
  1121. *
  1122. * @param bool $condition
  1123. * @param string $fieldName
  1124. * @param string $value
  1125. * @access public
  1126. * @return object fixer object
  1127. */
  1128. public function setIF($condition, $fieldName, $value)
  1129. {
  1130. if($condition) $this->data->$fieldName = $value;
  1131. return $this;
  1132. }
  1133. /**
  1134. * 强制给字段赋值。
  1135. * Set the value of a filed in force.
  1136. *
  1137. * @param string $fieldName
  1138. * @param mixed $value
  1139. * @access public
  1140. * @return object fixer object
  1141. */
  1142. public function setForce($fieldName, $value)
  1143. {
  1144. $this->data->$fieldName = $value;
  1145. return $this;
  1146. }
  1147. /**
  1148. * 移除一个字段。
  1149. * Remove a field.
  1150. *
  1151. * @param string $fieldName
  1152. * @access public
  1153. * @return object fixer object
  1154. */
  1155. public function remove($fieldName)
  1156. {
  1157. $fields = $this->processFields($fieldName);
  1158. foreach($fields as $fieldName) unset($this->data->$fieldName);
  1159. return $this;
  1160. }
  1161. /**
  1162. * 如果条件为真,移除该字段。
  1163. * Remove a filed on the condition is true.
  1164. *
  1165. * @param bool $condition
  1166. * @param string $fields
  1167. * @access public
  1168. * @return object fixer object
  1169. */
  1170. public function removeIF($condition, $fields)
  1171. {
  1172. $fields = $this->processFields($fields);
  1173. if($condition) foreach($fields as $fieldName) unset($this->data->$fieldName);
  1174. return $this;
  1175. }
  1176. /**
  1177. * 为数据添加新的项。
  1178. * Add an item to the data.
  1179. *
  1180. * @param string $fieldName
  1181. * @param mixed $value
  1182. * @access public
  1183. * @return object fixer object
  1184. */
  1185. public function add($fieldName, $value)
  1186. {
  1187. $this->data->$fieldName = $value;
  1188. return $this;
  1189. }
  1190. /**
  1191. * 如果条件为真,则为数据添加新的项。
  1192. * Add an item to the data on the condition if true.
  1193. *
  1194. * @param bool $condition
  1195. * @param string $fieldName
  1196. * @param mixed $value
  1197. * @access public
  1198. * @return object fixer object
  1199. */
  1200. public function addIF($condition, $fieldName, $value)
  1201. {
  1202. if($condition) $this->data->$fieldName = $value;
  1203. return $this;
  1204. }
  1205. /**
  1206. * 为指定字段增加值。
  1207. * Join the field.
  1208. *
  1209. * @param string $fieldName
  1210. * @param string $value
  1211. * @access public
  1212. * @return object fixer object
  1213. */
  1214. public function join($fieldName, $value)
  1215. {
  1216. if(!isset($this->data->$fieldName) or !is_array($this->data->$fieldName)) return $this;
  1217. $this->data->$fieldName = join($value, $this->data->$fieldName);
  1218. return $this;
  1219. }
  1220. /**
  1221. * 调用一个方法来处理数据。
  1222. * Call a function to fix it.
  1223. *
  1224. * @param string $fieldName
  1225. * @param string $func
  1226. * @access public
  1227. * @return object fixer object
  1228. */
  1229. public function callFunc($fieldName, $func)
  1230. {
  1231. $fields = $this->processFields($fieldName);
  1232. foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_CALLBACK, array('options' => $func));
  1233. return $this;
  1234. }
  1235. /**
  1236. * 处理完成后返回数据。
  1237. * Get the data after fixing.
  1238. *
  1239. * @param string $fieldName
  1240. * @access public
  1241. * @return mixed
  1242. * @param string $fields
  1243. */
  1244. public function get($fields = '')
  1245. {
  1246. global $config;
  1247. $rawConfig = empty($this->rawconfig) ? array() : $this->rawconfig;
  1248. foreach($rawConfig as $field => $fieldConfig)
  1249. {
  1250. if(isset($fieldConfig['control']) && $fieldConfig['control'] == 'editor') $this->stripTags($field, $config->allowedTags);
  1251. }
  1252. $fields = str_replace(' ', '', trim($fields));
  1253. foreach($this->data as $field => $value)
  1254. {
  1255. if(isset($rawConfig[$field]['specialchars']) && $rawConfig[$field]['specialchars'] == 'no')
  1256. {
  1257. $this->stripedFields[$field] = $field;
  1258. continue;
  1259. }
  1260. $this->specialChars($field);
  1261. }
  1262. if(empty($fields)) return $this->data;
  1263. if(strpos($fields, ',') === false) return $this->data->$fields;
  1264. $fields = array_flip(explode(',', $fields));
  1265. foreach($this->data as $field => $value)
  1266. {
  1267. if(!isset($fields[$field])) unset($this->data->$field);
  1268. if(!isset($this->stripedFields[$field])) $this->specialChars($field);
  1269. }
  1270. return $this->data;
  1271. }
  1272. /**
  1273. * 处理字段,如果字段中含有',',拆分成数组。如果字段不在$data中,删除掉。
  1274. * Process fields, if contains ',', split it to array. If not in $data, remove it.
  1275. *
  1276. * @param string $fields
  1277. * @access public
  1278. * @return array
  1279. */
  1280. public function processFields($fields)
  1281. {
  1282. $fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
  1283. foreach($fields as $key => $fieldName) if(!isset($this->data->$fieldName)) unset($fields[$key]);
  1284. return $fields;
  1285. }
  1286. }