国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
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.

614 lines
22KB

  1. <?php
  2. if (!defined('DEDEINC')) exit('dedebiz');
  3. /**
  4. * 数据库类
  5. * 说明:系统底层数据库核心类
  6. * 调用这个类前,请先设定这些外部变量
  7. * $GLOBALS['cfg_dbhost'];
  8. * $GLOBALS['cfg_dbuser'];
  9. * $GLOBALS['cfg_dbpwd'];
  10. * $GLOBALS['cfg_dbname'];
  11. * $GLOBALS['cfg_dbprefix'];
  12. *
  13. * @version $Id: dedesqli.class.php 1 15:00 2011-1-21 tianya $
  14. * @package DedeBIZ.Libraries
  15. * @copyright Copyright (c) 2022, DedeBIZ.COM
  16. * @license https://www.dedebiz.com/license
  17. * @link https://www.dedebiz.com
  18. */
  19. @set_time_limit(0);
  20. //在工程所有文件中均不需要单独初始化这个类,可直接用 $dsql 或 $db 进行操作
  21. //为了防止错误,操作完后不必关闭数据库
  22. if (!function_exists("mysqli_init")) {
  23. ShowMsg("尚未发现开启mysqli模块,请在php.ini中启用`extension=mysqli`","javasctipt:;",-1) ;
  24. exit;
  25. }
  26. $dsql = $dsqli = $db = new DedeSqli(FALSE);
  27. /**
  28. * Dede MySQLi数据库类
  29. *
  30. * @package DedeSqli
  31. * @subpackage DedeBIZ.Libraries
  32. * @link https://www.dedebiz.com
  33. */
  34. class DedeSqli
  35. {
  36. var $linkID;
  37. var $dbHost;
  38. var $dbUser;
  39. var $dbPwd;
  40. var $dbName;
  41. var $dbPrefix;
  42. var $result;
  43. var $queryString;
  44. var $parameters;
  45. var $isClose;
  46. var $safeCheck;
  47. var $showError = true;
  48. var $recordLog = false; //记录日志到data/mysqli_record_log.inc便于进行调试
  49. var $isInit = false;
  50. var $pconnect = false;
  51. //用外部定义的变量初始类,并连接数据库
  52. function __construct($pconnect = FALSE, $nconnect = FALSE)
  53. {
  54. $this->isClose = FALSE;
  55. $this->safeCheck = TRUE;
  56. $this->pconnect = $pconnect;
  57. $this->dbHost = $GLOBALS['cfg_dbhost'];
  58. $this->dbUser = $GLOBALS['cfg_dbuser'];
  59. $this->dbPwd = $GLOBALS['cfg_dbpwd'];
  60. $this->dbName = $GLOBALS['cfg_dbname'];
  61. $this->dbPrefix = $GLOBALS['cfg_dbprefix'];
  62. if ($nconnect) {
  63. $this->Init($pconnect);
  64. }
  65. }
  66. function DedeSql($pconnect = FALSE, $nconnect = TRUE)
  67. {
  68. $this->__construct($pconnect, $nconnect);
  69. }
  70. function Init($pconnect = FALSE)
  71. {
  72. $this->linkID = 0;
  73. //$this->queryString = '';
  74. //$this->parameters = Array();
  75. $this->result["me"] = 0;
  76. $this->Open($pconnect);
  77. }
  78. //用指定参数初始数据库信息
  79. function SetSource($host, $username, $pwd, $dbname, $dbprefix = "dede_")
  80. {
  81. $this->dbHost = $host;
  82. $this->dbUser = $username;
  83. $this->dbPwd = $pwd;
  84. $this->dbName = $dbname;
  85. $this->dbPrefix = $dbprefix;
  86. $this->result["me"] = 0;
  87. }
  88. function SelectDB($dbname)
  89. {
  90. mysqli_select_db($this->linkID, $dbname);
  91. }
  92. //设置SQL里的参数
  93. function SetParameter($key, $value)
  94. {
  95. $this->parameters[$key] = $value;
  96. }
  97. //连接数据库
  98. function Open($pconnect = FALSE)
  99. {
  100. global $dsqli;
  101. //连接数据库
  102. if ($dsqli && !$dsqli->isClose && $dsqli->isInit) {
  103. $this->linkID = $dsqli->linkID;
  104. } else {
  105. $i = 0;
  106. @list($dbhost, $dbport) = explode(':', $this->dbHost);
  107. !$dbport && $dbport = 3306;
  108. $this->linkID = mysqli_init();
  109. try {
  110. mysqli_real_connect($this->linkID, $dbhost, $this->dbUser, $this->dbPwd, false, $dbport);
  111. mysqli_errno($this->linkID) != 0 && $this->DisplayError('链接('.$this->pconnect.') 到MySQL发生错误');
  112. } catch (Exception $e) {
  113. $this->DisplayError("<span class='text-danger'>连接数据库失败,可能数据库密码不对或数据库服务器出错</span>");
  114. exit;
  115. }
  116. //复制一个对象副本
  117. CopySQLiPoint($this);
  118. }
  119. //处理错误,成功连接则选择数据库
  120. if (!$this->linkID) {
  121. $this->DisplayError("<span class='text-danger'>连接数据库失败,可能数据库密码不对或数据库服务器出错</span>");
  122. exit();
  123. }
  124. $this->isInit = TRUE;
  125. $serverinfo = mysqli_get_server_info($this->linkID);
  126. if (version_compare($serverinfo, '4.1', ">=") && $GLOBALS['cfg_db_language']) {
  127. mysqli_query($this->linkID, "SET character_set_connection=".$GLOBALS['cfg_db_language'].",character_set_results=".$GLOBALS['cfg_db_language'].",character_set_client=binary");
  128. }
  129. if (version_compare($serverinfo, '5.0', ">")) {
  130. mysqli_query($this->linkID, "SET sql_mode=''");
  131. }
  132. if ($this->dbName && !@mysqli_select_db($this->linkID, $this->dbName)) {
  133. $this->DisplayError('无法使用数据库');
  134. }
  135. return TRUE;
  136. }
  137. //为了防止采集等需要较长运行时间的程序超时,在运行这类程序时设置系统等待和交互时间
  138. function SetLongLink()
  139. {
  140. if ($this->linkID) {
  141. @mysqli_query($this->linkID, "SET interactive_timeout=3600, wait_timeout=3600 ;");
  142. }
  143. }
  144. //获得错误描述
  145. function GetError()
  146. {
  147. $str = mysqli_error($this->linkID);
  148. return $str;
  149. }
  150. //关闭数据库
  151. //mysql能自动管理非持久连接的连接池
  152. //实际上关闭并无意义并且容易出错,所以取消这函数
  153. function Close($isok = FALSE)
  154. {
  155. $this->FreeResultAll();
  156. if ($isok) {
  157. @mysqli_close($this->linkID);
  158. $this->isClose = TRUE;
  159. $GLOBALS['dsql'] = NULL;
  160. }
  161. }
  162. //定期清理死连接
  163. function ClearErrLink()
  164. {
  165. }
  166. //关闭指定的数据库连接
  167. function CloseLink($dblink)
  168. {
  169. @mysqli_close($dblink);
  170. }
  171. function Esc($_str)
  172. {
  173. global $dsqli;
  174. if (!$dsqli->isInit) {
  175. $this->Init($this->pconnect);
  176. }
  177. if (version_compare(phpversion(), '4.3.0', '>=')) {
  178. return @mysqli_real_escape_string($this->linkID, $_str);
  179. } else {
  180. return @mysqli_escape_string($this->linkID, $_str);
  181. }
  182. }
  183. //执行一个不返回结果的SQL语句,如update,delete,insert等
  184. function ExecuteNoneQuery($sql = '')
  185. {
  186. global $dsqli;
  187. if (!$dsqli->isInit) {
  188. $this->Init($this->pconnect);
  189. }
  190. if ($dsqli->isClose) {
  191. $this->Open(FALSE);
  192. $dsqli->isClose = FALSE;
  193. }
  194. if (!empty($sql)) {
  195. $this->SetQuery($sql);
  196. } else {
  197. return FALSE;
  198. }
  199. if (is_array($this->parameters)) {
  200. foreach ($this->parameters as $key => $value) {
  201. $this->queryString = str_replace("@".$key, "'$value'", $this->queryString);
  202. }
  203. }
  204. //SQL语句安全检查
  205. if ($this->safeCheck) CheckSql($this->queryString, 'update');
  206. $t1 = ExecTime();
  207. $rs = mysqli_query($this->linkID, $this->queryString);
  208. //查询性能测试
  209. if ($this->recordLog) {
  210. $queryTime = ExecTime() - $t1;
  211. $this->RecordLog($queryTime);
  212. }
  213. if (DEBUG_LEVEL === TRUE) {
  214. $queryTime = ExecTime() - $t1;
  215. if (PHP_SAPI === 'cli') {
  216. echo "执行SQL:".$this->queryString.",执行时间:{$queryTime}\r\n";
  217. } else {
  218. echo "<div style='width:98%;margin:1rem auto;color:#155724;background:#d4edda;border-color:#c3e6cb;position:relative;padding:.75rem 1.25rem;border:1px solid transparent;border-radius:.2rem'>执行SQL:".$this->queryString.",执行时间:{$queryTime}</div>\r\n";
  219. }
  220. }
  221. return $rs;
  222. }
  223. //执行一个返回影响记录条数的SQL语句,如update,delete,insert等
  224. function ExecuteNoneQuery2($sql = '')
  225. {
  226. global $dsqli;
  227. if (!$dsqli->isInit) {
  228. $this->Init($this->pconnect);
  229. }
  230. if ($dsqli->isClose) {
  231. $this->Open(FALSE);
  232. $dsqli->isClose = FALSE;
  233. }
  234. if (!empty($sql)) {
  235. $this->SetQuery($sql);
  236. }
  237. if (is_array($this->parameters)) {
  238. foreach ($this->parameters as $key => $value) {
  239. $this->queryString = str_replace("@".$key, "'$value'", $this->queryString);
  240. }
  241. }
  242. $t1 = ExecTime();
  243. mysqli_query($this->linkID, $this->queryString);
  244. //查询性能测试
  245. if ($this->recordLog) {
  246. $queryTime = ExecTime() - $t1;
  247. $this->RecordLog($queryTime);
  248. //echo $this->queryString."--{$queryTime}<hr />\r\n";
  249. }
  250. if (DEBUG_LEVEL === TRUE) {
  251. $queryTime = ExecTime() - $t1;
  252. if (PHP_SAPI === 'cli') {
  253. echo "执行SQL:".$this->queryString.",执行时间:{$queryTime}\r\n";
  254. } else {
  255. echo "<div style='width:98%;margin:1rem auto;color:#155724;background:#d4edda;border-color:#c3e6cb;position:relative;padding:.75rem 1.25rem;border:1px solid transparent;border-radius:.2rem'>执行SQL:".$this->queryString.",执行时间:{$queryTime}</div>\r\n";
  256. }
  257. }
  258. return mysqli_affected_rows($this->linkID);
  259. }
  260. function ExecNoneQuery($sql = '')
  261. {
  262. return $this->ExecuteNoneQuery($sql);
  263. }
  264. function GetFetchRow($id = 'me')
  265. {
  266. return @mysqli_fetch_row($this->result[$id]);
  267. }
  268. function GetAffectedRows()
  269. {
  270. return mysqli_affected_rows($this->linkID);
  271. }
  272. //执行一个带返回结果的SQL语句,如SELECT,SHOW等
  273. function Execute($id = "me", $sql = '')
  274. {
  275. global $dsqli;
  276. if (!$dsqli->isInit) {
  277. $this->Init($this->pconnect);
  278. }
  279. if ($dsqli->isClose) {
  280. $this->Open(FALSE);
  281. $dsqli->isClose = FALSE;
  282. }
  283. if (!empty($sql)) {
  284. $this->SetQuery($sql);
  285. }
  286. //SQL语句安全检查
  287. if ($this->safeCheck) {
  288. CheckSql($this->queryString);
  289. }
  290. $t1 = ExecTime();
  291. //var_dump($this->queryString);
  292. $this->result[$id] = mysqli_query($this->linkID, $this->queryString);
  293. //var_dump(mysql_error());
  294. //查询性能测试
  295. if ($this->recordLog) {
  296. $queryTime = ExecTime() - $t1;
  297. $this->RecordLog($queryTime);
  298. //echo $this->queryString."--{$queryTime}<hr />\r\n";
  299. }
  300. if (DEBUG_LEVEL === TRUE) {
  301. $queryTime = ExecTime() - $t1;
  302. if (PHP_SAPI === 'cli') {
  303. echo "执行SQL:".$this->queryString.",执行时间:{$queryTime}\r\n";
  304. } else {
  305. echo "<div style='width:98%;margin:1rem auto;color:#155724;background:#d4edda;border-color:#c3e6cb;position:relative;padding:.75rem 1.25rem;border:1px solid transparent;border-radius:.2rem'>执行SQL:".$this->queryString.",执行时间:{$queryTime}</div>\r\n";
  306. }
  307. }
  308. if ($this->result[$id] === FALSE) {
  309. $this->DisplayError(mysqli_error($this->linkID)." <br>Error sql: <span class='text-danger'>".$this->queryString."</span>");
  310. }
  311. }
  312. function Query($id = "me", $sql = '')
  313. {
  314. $this->Execute($id, $sql);
  315. }
  316. //执行一个SQL语句,返回前一条记录或仅返回一条记录
  317. function GetOne($sql = '', $acctype = MYSQLI_ASSOC)
  318. {
  319. global $dsqli;
  320. //$t1 = ExecTime();
  321. if (!$dsqli->isInit) {
  322. $this->Init($this->pconnect);
  323. }
  324. //echo ExecTime() - $t1;
  325. if ($dsqli->isClose) {
  326. $this->Open(FALSE);
  327. $dsqli->isClose = FALSE;
  328. }
  329. if (!empty($sql)) {
  330. if (!preg_match("/LIMIT/i", $sql)) $this->SetQuery(preg_replace("/[,;]$/i", '', trim($sql))." LIMIT 0,1;");
  331. else $this->SetQuery($sql);
  332. }
  333. $this->Execute("one");
  334. $arr = $this->GetArray("one", $acctype);
  335. if (!is_array($arr)) {
  336. return '';
  337. } else {
  338. @mysqli_free_result($this->result["one"]);
  339. return ($arr);
  340. }
  341. }
  342. //执行一个不与任何表名有关的SQL语句,Create等
  343. function ExecuteSafeQuery($sql, $id = "me")
  344. {
  345. global $dsqli;
  346. if (!$dsqli->isInit) {
  347. $this->Init($this->pconnect);
  348. }
  349. if ($dsqli->isClose) {
  350. $this->Open(FALSE);
  351. $dsqli->isClose = FALSE;
  352. }
  353. $this->result[$id] = @mysqli_query($sql, $this->linkID);
  354. }
  355. //返回当前的一条记录并把游标移向下一记录
  356. //MYSQLI_ASSOC、MYSQLI_NUM、MYSQLI_BOTH
  357. function GetArray($id = "me", $acctype = MYSQLI_ASSOC)
  358. {
  359. //var_dump($this->result);
  360. if ($this->result[$id] === 0) {
  361. return FALSE;
  362. } else {
  363. return @mysqli_fetch_array($this->result[$id], $acctype);
  364. }
  365. }
  366. function GetObject($id = "me")
  367. {
  368. if ($this->result[$id] === 0) {
  369. return FALSE;
  370. } else {
  371. return mysqli_fetch_object($this->result[$id]);
  372. }
  373. }
  374. //检测是否存在某数据表
  375. function IsTable($tbname)
  376. {
  377. global $dsqli;
  378. if (!$dsqli->isInit) {
  379. $this->Init($this->pconnect);
  380. }
  381. $prefix = "#@__";
  382. $tbname = str_replace($prefix, $GLOBALS['cfg_dbprefix'], $tbname);
  383. if (mysqli_num_rows(@mysqli_query($this->linkID, "SHOW TABLES LIKE '".$tbname."'"))) {
  384. return TRUE;
  385. }
  386. return FALSE;
  387. }
  388. //获得MySql的版本号
  389. function GetVersion($isformat = TRUE)
  390. {
  391. global $dsqli;
  392. if (!$dsqli->isInit) {
  393. $this->Init($this->pconnect);
  394. }
  395. if ($dsqli->isClose) {
  396. $this->Open(FALSE);
  397. $dsqli->isClose = FALSE;
  398. }
  399. $rs = mysqli_query($this->linkID, "SELECT VERSION();");
  400. $row = mysqli_fetch_array($rs);
  401. $mysql_version = $row[0];
  402. mysqli_free_result($rs);
  403. if ($isformat) {
  404. $mysql_versions = explode(".", trim($mysql_version));
  405. $mysql_version = number_format($mysql_versions[0].".".$mysql_versions[1], 2);
  406. }
  407. return $mysql_version;
  408. }
  409. //获取特定表的信息
  410. function GetTableFields($tbname, $id = "me")
  411. {
  412. global $dsqli;
  413. if (!$dsqli->isInit) {
  414. $this->Init($this->pconnect);
  415. }
  416. $prefix = "#@__";
  417. $tbname = str_replace($prefix, $GLOBALS['cfg_dbprefix'], $tbname);
  418. $query = "SELECT * FROM {$tbname} LIMIT 0,1";
  419. $this->result[$id] = mysqli_query($this->linkID, $query);
  420. }
  421. //获取字段详细信息
  422. function GetFieldObject($id = "me")
  423. {
  424. return mysqli_fetch_field($this->result[$id]);
  425. }
  426. //获得查询的总记录数
  427. function GetTotalRow($id = "me")
  428. {
  429. if ($this->result[$id] === 0) {
  430. return -1;
  431. } else {
  432. return @mysqli_num_rows($this->result[$id]);
  433. }
  434. }
  435. //获取上一步INSERT操作产生的ID
  436. function GetLastID()
  437. {
  438. //如果 AUTO_INCREMENT 的列的类型是 BIGINT,则 mysqli_insert_id() 返回的值将不正确
  439. //可以在 SQL 查询中用 MySQL 内部的 SQL 函数 LAST_INSERT_ID() 来替代
  440. //$rs = mysqli_query($this->linkID, "Select LAST_INSERT_ID() as lid");
  441. //$row = mysqli_fetch_array($rs);
  442. //return $row["lid"];
  443. return mysqli_insert_id($this->linkID);
  444. }
  445. //释放记录集占用的资源
  446. function FreeResult($id = "me")
  447. {
  448. @mysqli_free_result($this->result[$id]);
  449. }
  450. function FreeResultAll()
  451. {
  452. if (!is_array($this->result)) {
  453. return '';
  454. }
  455. foreach ($this->result as $vv) {
  456. if ($vv) {
  457. @mysqli_free_result($vv);
  458. }
  459. }
  460. }
  461. //设置SQL语句,会自动把SQL语句里的#@__替换为$this->dbPrefix(在配置文件中为$cfg_dbprefix)
  462. function SetQuery($sql)
  463. {
  464. $prefix = "#@__";
  465. $sql = str_replace($prefix, $GLOBALS['cfg_dbprefix'], $sql);
  466. $this->queryString = $sql;
  467. }
  468. function SetSql($sql)
  469. {
  470. $this->SetQuery($sql);
  471. }
  472. function RecordLog($runtime = 0)
  473. {
  474. $RecordLogFile = DEDEDATA.'/mysqli_record_log.inc';
  475. $url = $this->GetCurUrl();
  476. $savemsg = <<<EOT
  477. ------------------------------------------
  478. SQL:{$this->queryString}
  479. Page:$url
  480. Runtime:$runtime
  481. EOT;
  482. $fp = @fopen($RecordLogFile, 'a');
  483. @fwrite($fp, $savemsg);
  484. @fclose($fp);
  485. }
  486. //显示数据链接错误信息
  487. function DisplayError($msg)
  488. {
  489. $errorTrackFile = DEDEDATA.'/mysqli_error_trace.inc';
  490. if ($this->showError) {
  491. $msg = str_replace(array("\r","\n"),"",addslashes($msg));
  492. ShowMsg("{$msg}", "javascript:;", -1);
  493. exit;
  494. }
  495. $savemsg = 'Page: '.$this->GetCurUrl()."\r\nError: ".$msg."\r\nTime".date('Y-m-d H:i:s');
  496. //保存MySql错误日志
  497. $fp = @fopen($errorTrackFile, 'a');
  498. @fwrite($fp, '<'.'?php exit();'."\r\n/*\r\n{$savemsg}\r\n*/\r\n?".">\r\n");
  499. @fclose($fp);
  500. }
  501. //获得当前的脚本网址
  502. function GetCurUrl()
  503. {
  504. if (!empty($_SERVER["REQUEST_URI"])) {
  505. $scriptName = $_SERVER["REQUEST_URI"];
  506. $nowurl = $scriptName;
  507. } else {
  508. $scriptName = $_SERVER["PHP_SELF"];
  509. if (empty($_SERVER["QUERY_STRING"])) {
  510. $nowurl = $scriptName;
  511. } else {
  512. $nowurl = $scriptName."?".$_SERVER["QUERY_STRING"];
  513. }
  514. }
  515. return $nowurl;
  516. }
  517. }
  518. //复制一个对象副本
  519. function CopySQLiPoint(&$ndsql)
  520. {
  521. $GLOBALS['dsqli'] = $ndsql;
  522. }
  523. //SQL语句过滤程序,由80sec提供,这里作了适当的修改
  524. if (!function_exists('CheckSql')) {
  525. function CheckSql($db_string, $querytype = 'select')
  526. {
  527. global $cfg_cookie_encode;
  528. $clean = '';
  529. $error = '';
  530. $old_pos = 0;
  531. $pos = -1;
  532. $log_file = DEDEDATA.'/'.md5($cfg_cookie_encode).'_safe.txt';
  533. $userIP = GetIP();
  534. $getUrl = GetCurUrl();
  535. //如果是普通查询语句,直接过滤一些特殊语法
  536. if ($querytype == 'select') {
  537. $notallow1 = "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}";
  538. //$notallow2 = "--|/\*";
  539. if (preg_match("/".$notallow1."/i", $db_string)) {
  540. fputs(fopen($log_file, 'a+'), "$userIP||$getUrl||$db_string||SelectBreak\r\n");
  541. exit("<span>Safe Alert: Request Error step 1 !</span>");
  542. }
  543. }
  544. //完整的SQL检查
  545. while (TRUE) {
  546. $pos = strpos($db_string, '\'', $pos + 1);
  547. if ($pos === FALSE) {
  548. break;
  549. }
  550. $clean .= substr($db_string, $old_pos, $pos - $old_pos);
  551. while (TRUE) {
  552. $pos1 = strpos($db_string, '\'', $pos + 1);
  553. $pos2 = strpos($db_string, '\\', $pos + 1);
  554. if ($pos1 === FALSE) {
  555. break;
  556. } elseif ($pos2 == FALSE || $pos2 > $pos1) {
  557. $pos = $pos1;
  558. break;
  559. }
  560. $pos = $pos2 + 1;
  561. }
  562. $clean .= '$s$';
  563. $old_pos = $pos + 1;
  564. }
  565. $clean .= substr($db_string, $old_pos);
  566. $clean = trim(strtolower(preg_replace(array('~\s+~s'), array(' '), $clean)));
  567. if (
  568. strpos($clean, '@') !== FALSE or strpos($clean, 'char(') !== FALSE or strpos($clean, '"') !== FALSE
  569. or strpos($clean, '$s$$s$') !== FALSE
  570. ) {
  571. $fail = TRUE;
  572. if (preg_match("#^create table#i", $clean)) $fail = FALSE;
  573. $error = "unusual character";
  574. }
  575. //老版本的Mysql并不支持union,常用的程序里也不使用union,但是一些黑客使用它,所以检查它
  576. if (strpos($clean, 'union') !== FALSE && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) {
  577. $fail = TRUE;
  578. $error = "union detect";
  579. }
  580. //发布版本的程序可能比较少包括--,#这样的注释,但是黑客经常使用它们
  581. elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== FALSE || strpos($clean, '#') !== FALSE) {
  582. $fail = TRUE;
  583. $error = "comment detect";
  584. }
  585. //这些函数不会被使用,但是黑客会用它来操作文件,down掉数据库
  586. elseif (strpos($clean, 'sleep') !== FALSE && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0) {
  587. $fail = TRUE;
  588. $error = "slown down detect";
  589. } elseif (strpos($clean, 'benchmark') !== FALSE && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0) {
  590. $fail = TRUE;
  591. $error = "slown down detect";
  592. } elseif (strpos($clean, 'load_file') !== FALSE && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s', $clean) != 0) {
  593. $fail = TRUE;
  594. $error = "file fun detect";
  595. } elseif (strpos($clean, 'into outfile') !== FALSE && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s', $clean) != 0) {
  596. $fail = TRUE;
  597. $error = "file fun detect";
  598. }
  599. //老版本的MYSQL不支持子查询,我们的程序里可能也用得少,但是黑客可以使用它来查询数据库敏感信息
  600. elseif (preg_match('~\([^)]*?select~s', $clean) != 0) {
  601. $fail = TRUE;
  602. $error = "sub select detect";
  603. }
  604. if (!empty($fail)) {
  605. fputs(fopen($log_file, 'a+'), "$userIP||$getUrl||$db_string||$error\r\n");
  606. exit("<span>Safe Alert: Request Error step 2!</span>");
  607. } else {
  608. return $db_string;
  609. }
  610. }
  611. }