国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

681 řádky
23KB

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