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

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