国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

728 Zeilen
21KB

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