国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

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