国内流行的内容管理系统(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.

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