設為首頁收藏本站

艾歐踢論壇

 找回密碼
 立即註冊

QQ登錄

只需一步,快速開始

搜索
熱搜: 活動 交友 discuz
查看: 743|回復: 0
打印 上一主題 下一主題

【discuzX2】/source/class/class_core.php DB及db_mysql分析

[複製鏈接]
跳轉到指定樓層
樓主
發表於 2015-2-8 23:24:44 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  1. <?php
  2. /**
  3. * Discuz MySQL 类的支持 程序中一般不直接使用此类,而是使用DB类,DB类对db_mysql类中的方法又进行了二次封装
  4. *
  5. */
  6. class db_mysql
  7. {
  8.         var $tablepre;
  9.         var $version = '';
  10.         var $querynum = 0;
  11.         var $slaveid = 0;
  12.         var $curlink;
  13.         var $link = array();
  14.         var $config = array();
  15.         var $sqldebug = array();
  16.         var $map = array();

  17.         function db_mysql($config = array()) {
  18.                 if(!empty($config)) {
  19.                         $this->set_config($config);
  20.                 }
  21.         }

  22.         function set_config($config) {
  23.                 $this->config = &$config;
  24.                 $this->tablepre = $config['1']['tablepre'];
  25.                 if(!empty($this->config['map'])) {
  26.                         $this->map = $this->config['map'];
  27.                 }
  28.         }

  29.         function connect($serverid = 1) {

  30.                 if(empty($this->config) || empty($this->config[$serverid])) {
  31.                         $this->halt('config_db_not_found');
  32.                 }

  33.                 $this->link[$serverid] = $this->_dbconnect(
  34.                         $this->config[$serverid]['dbhost'],
  35.                         $this->config[$serverid]['dbuser'],
  36.                         $this->config[$serverid]['dbpw'],
  37.                         $this->config[$serverid]['dbcharset'],
  38.                         $this->config[$serverid]['dbname'],
  39.                         $this->config[$serverid]['pconnect']
  40.                         );
  41.                 $this->curlink = $this->link[$serverid];

  42.         }

  43.         function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect) {
  44.                 $link = null;
  45.                 $func = empty($pconnect) ? 'mysql_connect' : 'mysql_pconnect';
  46.                 if(!$link = @$func($dbhost, $dbuser, $dbpw, 1)) {
  47.                         $this->halt('notconnect');
  48.                 } else {
  49.                         $this->curlink = $link;
  50.                         if($this->version() > '4.1') {
  51.                                 $dbcharset = $dbcharset ? $dbcharset : $this->config[1]['dbcharset'];
  52.                                 $serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary' : '';
  53.                                 $serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=\'\'') : '';
  54.                                 $serverset && mysql_query("SET $serverset", $link);
  55.                         }
  56.                         $dbname && @mysql_select_db($dbname, $link);
  57.                 }
  58.                 return $link;
  59.         }

  60.         function table_name($tablename) {
  61.                 if(!empty($this->map) && !empty($this->map[$tablename])) {
  62.                         $id = $this->map[$tablename];
  63.                         if(!$this->link[$id]) {
  64.                                 $this->connect($id);
  65.                         }
  66.                         $this->curlink = $this->link[$id];
  67.                         return $this->config[$id]['tablepre'].$tablename;
  68.                 } else {
  69.                         $this->curlink = $this->link[1];
  70.                 }
  71.                 return $this->tablepre.$tablename;
  72.         }

  73.         function select_db($dbname) {
  74.                 return mysql_select_db($dbname, $this->curlink);
  75.         }

  76.         function fetch_array($query, $result_type = MYSQL_ASSOC) {
  77.                 return mysql_fetch_array($query, $result_type);
  78.         }

  79.         function fetch_first($sql) {
  80.                 return $this->fetch_array($this->query($sql));
  81.         }

  82.         function result_first($sql) {
  83.                 return $this->result($this->query($sql), 0);
  84.         }

  85.         function query($sql, $type = '') {

  86.                 if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
  87.                         $starttime = dmicrotime();
  88.                 }
  89.                 $func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?
  90.                 'mysql_unbuffered_query' : 'mysql_query';
  91.                 if(!($query = $func($sql, $this->curlink))) {
  92.                         if(in_array($this->errno(), array(2006, 2013)) && substr($type, 0, 5) != 'RETRY') {
  93.                                 $this->connect();
  94.                                 return $this->query($sql, 'RETRY'.$type);
  95.                         }
  96.                         if($type != 'SILENT' && substr($type, 5) != 'SILENT') {
  97.                                 $this->halt('query_error', $sql);
  98.                         }
  99.                 }

  100.                 if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
  101.                         $this->sqldebug[] = array($sql, number_format((dmicrotime() - $starttime), 6), debug_backtrace());
  102.                 }

  103.                 $this->querynum++;
  104.                 return $query;
  105.         }

  106.         function affected_rows() {
  107.                 return mysql_affected_rows($this->curlink);
  108.         }

  109.         function error() {
  110.                 return (($this->curlink) ? mysql_error($this->curlink) : mysql_error());
  111.         }

  112.         function errno() {
  113.                 return intval(($this->curlink) ? mysql_errno($this->curlink) : mysql_errno());
  114.         }

  115.         function result($query, $row = 0) {
  116.                 $query = @mysql_result($query, $row);
  117.                 return $query;
  118.         }

  119.         function num_rows($query) {
  120.                 $query = mysql_num_rows($query);
  121.                 return $query;
  122.         }

  123.         function num_fields($query) {
  124.                 return mysql_num_fields($query);
  125.         }

  126.         function free_result($query) {
  127.                 return mysql_free_result($query);
  128.         }

  129.         function insert_id() {
  130.                 return ($id = mysql_insert_id($this->curlink)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
  131.         }

  132.         function fetch_row($query) {
  133.                 $query = mysql_fetch_row($query);
  134.                 return $query;
  135.         }

  136.         function fetch_fields($query) {
  137.                 return mysql_fetch_field($query);
  138.         }

  139.         function version() {
  140.                 if(empty($this->version)) {
  141.                         $this->version = mysql_get_server_info($this->curlink);
  142.                 }
  143.                 return $this->version;
  144.         }

  145.         function close() {
  146.                 return mysql_close($this->curlink);
  147.         }

  148.         function halt($message = '', $sql = '') {
  149.                 require_once libfile('class/error');
  150.                 discuz_error::db_error($message, $sql);
  151.         }

  152. }

  153. /**
  154. * 对Discuz CORE 中 DB Object中的主要方法进行二次封装,方便程序调用
  155. *
  156. */
  157. class DB
  158. {

  159.         /**
  160.          * 返回表名(pre_$table)
  161.          *
  162.          * @param 原始表名 $table
  163.          * @return 增加pre之后的名字
  164.          */
  165.         function table($table) {
  166.                 return DB::_execute('table_name', $table);
  167.         }

  168.         /**
  169.          * 删除一条或者多条记录
  170.          *
  171.          * @param string $table 原始表名
  172.          * @param string $condition 条件语句,不需要写WHERE
  173.          * @param int $limit 删除条目数
  174.          * @param boolean $unbuffered 立即返回?
  175.          */
  176.         function delete($table, $condition, $limit = 0, $unbuffered = true) {
  177.                 if(empty($condition)) {
  178.                         $where = '1';
  179.                 } elseif(is_array($condition)) {
  180.                         $where = DB::implode_field_value($condition, ' AND ');
  181.                 } else {
  182.                         $where = $condition;
  183.                 }
  184.                 $sql = "DELETE FROM ".DB::table($table)." WHERE $where ".($limit ? "LIMIT $limit" : '');
  185.                 return DB::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
  186.         }

  187.         /**
  188.          * 插入一条记录
  189.          *
  190.          * @param string $table 原始表名
  191.          * @param array $data 数组field->vlaue 对
  192.          * @param boolen $return_insert_id 返回 InsertID?
  193.          * @param boolen $replace 是否是REPLACE模式
  194.          * @param boolen $silent 屏蔽错误?
  195.          * @return InsertID or Result
  196.          */
  197.         function insert($table, $data, $return_insert_id = false, $replace = false, $silent = false) {

  198.                 $sql = DB::implode_field_value($data);

  199.                 $cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';

  200.                 $table = DB::table($table);
  201.                 $silent = $silent ? 'SILENT' : '';

  202.                 $return = DB::query("$cmd $table SET $sql", $silent);

  203.                 return $return_insert_id ? DB::insert_id() : $return;

  204.         }

  205.         /**
  206.          * 更新一条或者多条数据记录
  207.          *
  208.          * @param string $table 原始表名
  209.          * @param array $data 数据field-value
  210.          * @param string $condition 条件语句,不需要写WHERE
  211.          * @param boolean $unbuffered 迅速返回?
  212.          * @param boolan $low_priority 延迟更新?
  213.          * @return result
  214.          */
  215.         function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
  216.                 $sql = DB::implode_field_value($data);
  217.                 $cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');
  218.                 $table = DB::table($table);
  219.                 $where = '';
  220.                 if(empty($condition)) {
  221.                         $where = '1';
  222.                 } elseif(is_array($condition)) {
  223.                         $where = DB::implode_field_value($condition, ' AND ');
  224.                 } else {
  225.                         $where = $condition;
  226.                 }
  227.                 $res = DB::query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
  228.                 return $res;
  229.         }

  230.         /**
  231.          * 格式化field字段和value,并组成一个字符串
  232.          *
  233.          * @param array $array 格式为 key=>value 数组
  234.          * @param 分割符 $glue
  235.          * @return string
  236.          */
  237.         function implode_field_value($array, $glue = ',') {
  238.                 $sql = $comma = '';
  239.                 foreach ($array as $k => $v) {
  240.                         $sql .= $comma."`$k`='$v'";
  241.                         $comma = $glue;
  242.                 }
  243.                 return $sql;
  244.         }

  245.         /**
  246.          * 返回插入的ID
  247.          *
  248.          * @return int
  249.          */
  250.         function insert_id() {
  251.                 return DB::_execute('insert_id');
  252.         }

  253.         /**
  254.          * 依据查询结果,返回一行数据
  255.          *
  256.          * @param resourceID $resourceid
  257.          * @return array
  258.          */
  259.         function fetch($resourceid, $type = MYSQL_ASSOC) {
  260.                 return DB::_execute('fetch_array', $resourceid, $type);
  261.         }

  262.         /**
  263.          * 依据SQL语句,返回第一条查询结果
  264.          *
  265.          * @param string $query 查询语句
  266.          * @return array
  267.          */
  268.         function fetch_first($sql) {
  269.                 DB::checkquery($sql);
  270.                 return DB::_execute('fetch_first', $sql);
  271.         }

  272.         /**
  273.          * 依据查询结果,返回结果数值
  274.          *
  275.          * @param resourceid $resourceid
  276.          * @return string or int
  277.          */
  278.         function result($resourceid, $row = 0) {
  279.                 return DB::_execute('result', $resourceid, $row);
  280.         }

  281.         /**
  282.          * 依据查询语句,返回结果数值
  283.          *
  284.          * @param string $query SQL查询语句
  285.          * @return unknown
  286.          */
  287.         function result_first($sql) {
  288.                 DB::checkquery($sql);
  289.                 return DB::_execute('result_first', $sql);
  290.         }

  291.         /**
  292.          * 执行查询
  293.          *
  294.          * @param string $sql
  295.          * @param 类型定义 $type UNBUFFERED OR SILENT
  296.          * @return Resource OR Result
  297.          */
  298.         function query($sql, $type = '') {
  299.                 DB::checkquery($sql);
  300.                 return DB::_execute('query', $sql, $type);
  301.         }

  302.         /**
  303.          * 返回select的结果行数
  304.          *
  305.          * @param resource $resourceid
  306.          * @return int
  307.          */
  308.         function num_rows($resourceid) {
  309.                 return DB::_execute('num_rows', $resourceid);
  310.         }

  311.         /**
  312.          * 返回sql语句所影响的记录行数
  313.          *
  314.          * @return int
  315.          */
  316.         function affected_rows() {
  317.                 return DB::_execute('affected_rows');
  318.         }

  319.         function free_result($query) {
  320.                 return DB::_execute('free_result', $query);
  321.         }

  322.         function error() {
  323.                 return DB::_execute('error');
  324.         }

  325.         function errno() {
  326.                 return DB::_execute('errno');
  327.         }

  328.         function _execute($cmd , $arg1 = '', $arg2 = '') {//DB类中的很多方法都调用了此方法,此方法又调用了 &object()方法,详情请查看&object()方法,其实&object()方法返回一个db_mysql类的实例化对象,而且是statics类型的实例化对象
  329.                 static $db;
  330.                 if(empty($db)) $db = & DB::object();//返回db_mysql操作类的实例化对象
  331.                 $res = $db->$cmd($arg1, $arg2);
  332.                 return $res;
  333.         }

  334.         /**
  335.          * 返回 DB object 指针
  336.          *
  337.          * @return pointer of db object from discuz core
  338.          */
  339.         function &object($dbclass = 'db_mysql') {
  340.                 static $db;
  341.                 if(empty($db)) $db = new $dbclass();//返回db_mysql数据库操作类的一个statics类型的实例化对象
  342.                 return $db;
  343.         }

  344.         function checkquery($sql) {
  345.                 static $status = null, $checkcmd = array('SELECT', 'UPDATE', 'INSERT', 'REPLACE', 'DELETE');
  346.                 if($status === null) $status = getglobal('config/security/querysafe/status');
  347.                 if($status) {
  348.                         $cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ' '))));
  349.                         if(in_array($cmd, $checkcmd)) {
  350.                                 $test = DB::_do_query_safe($sql);
  351.                                 if($test < 1) DB::_execute('halt', 'security_error', $sql);
  352.                         }
  353.                 }
  354.                 return true;
  355.         }

  356.         function _do_query_safe($sql) {
  357.                 static $_CONFIG = null;
  358.                 if($_CONFIG === null) {
  359.                         $_CONFIG = getglobal('config/security/querysafe');
  360.                 }

  361.                 $sql = str_replace(array('\\\\', '\\\'', '\\"', '\'\''), '', $sql);
  362.                 $mark = $clean = '';
  363.                 if(strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false) {
  364.                         $clean = preg_replace("/'(.+?)'/s", '', $sql);
  365.                 } else {
  366.                         $len = strlen($sql);
  367.                         $mark = $clean = '';
  368.                         for ($i = 0; $i <$len; $i++) {
  369.                                 $str = $sql[$i];
  370.                                 switch ($str) {
  371.                                         case '\'':
  372.                                                 if(!$mark) {
  373.                                                         $mark = '\'';
  374.                                                         $clean .= $str;
  375.                                                 } elseif ($mark == '\'') {
  376.                                                         $mark = '';
  377.                                                 }
  378.                                                 break;
  379.                                         case '/':
  380.                                                 if(empty($mark) && $sql[$i+1] == '*') {
  381.                                                         $mark = '/*';
  382.                                                         $clean .= $mark;
  383.                                                         $i++;
  384.                                                 } elseif($mark == '/*' && $sql[$i -1] == '*') {
  385.                                                         $mark = '';
  386.                                                         $clean .= '*';
  387.                                                 }
  388.                                                 break;
  389.                                         case '#':
  390.                                                 if(empty($mark)) {
  391.                                                         $mark = $str;
  392.                                                         $clean .= $str;
  393.                                                 }
  394.                                                 break;
  395.                                         case "\n":
  396.                                                 if($mark == '#' || $mark == '--') {
  397.                                                         $mark = '';
  398.                                                 }
  399.                                                 break;
  400.                                         case '-':
  401.                                                 if(empty($mark)&& substr($sql, $i, 3) == '-- ') {
  402.                                                         $mark = '-- ';
  403.                                                         $clean .= $mark;
  404.                                                 }
  405.                                                 break;

  406.                                         default:

  407.                                                 break;
  408.                                 }
  409.                                 $clean .= $mark ? '' : $str;
  410.                         }
  411.                 }

  412.                 $clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/\"]+/is", "", strtolower($clean));

  413.                 if($_CONFIG['afullnote']) {
  414.                         $clean = str_replace('/**/','',$clean);
  415.                 }

  416.                 if(is_array($_CONFIG['dfunction'])) {
  417.                         foreach($_CONFIG['dfunction'] as $fun) {
  418.                                 if(strpos($clean, $fun.'(') !== false) return '-1';
  419.                         }
  420.                 }

  421.                 if(is_array($_CONFIG['daction'])) {
  422.                         foreach($_CONFIG['daction'] as $action) {
  423.                                 if(strpos($clean,$action) !== false) return '-3';
  424.                         }
  425.                 }

  426.                 if($_CONFIG['dlikehex'] && strpos($clean, 'like0x')) {
  427.                         return '-2';
  428.                 }

  429.                 if(is_array($_CONFIG['dnote'])) {
  430.                         foreach($_CONFIG['dnote'] as $note) {
  431.                                 if(strpos($clean,$note) !== false) return '-4';
  432.                         }
  433.                 }

  434.                 return 1;

  435.         }

  436. }
  437. ?>
複製代碼


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 轉播轉播 分享分享 分享淘帖
回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

小黑屋|Archiver|手機版|艾歐踢創新工坊    

GMT+8, 2024-6-11 23:43 , Processed in 0.217863 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表