我是小站长 發表於 2019-6-2 19:20:02

史上第一强:Discuz!源代码分析系列(1)--./include/common.inc.php

好久没有开始写一篇像样的技术文档了,五一难得有这么多的时间,就早起来写一篇好的文章给大家吧~最近都忙一些自己的事情,没多少机会上网来回答问题,实在抱歉……<br />好了,言归正传,这次我打算写一个系列的文章,把Discuz的核心文件的源代码一一分解解释出来,大家都知道Discuz的源代码是很经得起时间的考验的,是众多程序员智慧的结晶,我想大家能借鉴一下也是很不错的,唯一一点不好就是,不是OOP(面向对象)的,我最近看了几个框架(framework),也用了一下,感觉OOP的编程让人热血沸腾,大大提高了开发效率,一个小型论坛的开发的话不用像Discuz 这样写这么这么多的代码,很是不错,不过说到面向对象,当然要看看Java,Jsp 或ASP.NET,前两个看得我郁闷,没看了,只学会了ASP.NET,感觉很不错,比PHP先进多了,针对事件、驱动编程,封装,编译,跨平台,听着就觉得很帅了,很适合大型应用,呵呵,扯远了……<br /><blockquote><strong><font color="Red">申明下版权:</font></strong><br />1.这里面的每个中文字都是我打的,code部分是引用的,当然我也加了一点注释在里面了。<br />2.如果要转载的话请注明<ol><li>转自www.discuz.net 作者:郭鑫</ol><br />3.由于我个人的能力有限,写这篇文章没有参考一点资料,甚至连本地环境也没有搭建(遇到了白屏问题),所以难免会有错误的地方,大家发现了的话请跟帖或者联系我吧,我会尽快更正。</blockquote><br />第一个文件当然是分析./include/common.inc.php这个文件,这个是Discuz的核心中的核心,基本上每次操作都include到了这个文件,下面就分七段来分析这个文件:<br /><br />Section One:<br /><blockquote><ol><li><br /><li>//定义PHP一些环境<br /><li>error_reporting(0);<br /><li>set_magic_quotes_runtime(0);<br /><li><br /><li>//设置Discuz开始的时间<br /><li>$mtime = explode(' ', microtime());<br /><li>$discuz_starttime = $mtime + $mtime;<br /><li><br /><li>//定义一些常量<br /><li>define('SYS_DEBUG', FALSE);<br /><li>define('IN_DISCUZ', TRUE);<br /><li>define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -7)); //获得绝对目录<br /><li><br /><li>//通用性<br /><li>if(PHP_VERSION &lt; '4.1.0') {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$_GET = &amp;$HTTP_GET_VARS;<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$_POST = &amp;$HTTP_POST_VARS;<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$_COOKIE = &amp;$HTTP_COOKIE_VARS;<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$_SERVER = &amp;$HTTP_SERVER_VARS;<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$_ENV = &amp;$HTTP_ENV_VARS;<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$_FILES = &amp;$HTTP_POST_FILES;<br /><li>}<br /><li></ol><br />这一段基本上就是设置一下错误报告,把magic_quotes这个sick家伙给关了,然后定一个开始的时间,这样我们在论坛底部看到的Process Time就是通过这个开始的时间和一个结束的时间的差来计算的,然后定义一个IN_DISCUZ为真,这个IN_DISCUZ常量的作用就是在其他inc这样的包含文件中防止被非法引用,一旦没有这个常量的话就出现Access Denied这样的字样然后退出。然后获得Discuz运行的绝对目录。接下来是判断PHP 的版本是4.1 以下还是以上,因为PHP以4.1为一个分界线,在4.1以下以$HTTP_GET_VARS[‘xx’]这样的方式来得到get过来的值,而以后用$_GET来得到get过来的值,这样做的目的是为了无论是什么样的PHP版本,都能用$_GET这样的方式得到,有通用性~!</blockquote><br />Section Two:<br /><blockquote><ol><li><br /><li>require_once DISCUZ_ROOT.'./include/global.func.php';<br /><li></ol><br />把include/global.inc.php引用进来,这个文件是Discuz的核心函数文件,包含了Discuz用到的很多通用的函数,可以说它就是一个大的通用函数库。<br /><br /><ol><li><br /><li>define('ISROBOT', getrobot());<br /><li>if(defined('NOROBOT') &amp;&amp; ISROBOT) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;exit(header(&quot;HTTP/1.1 403 Forbidden&quot;));<br /><li>}<br /><li></ol><br />这里是定义一个ISROBOT常量,看看浏览者是什么东东,比方说如果浏览者是一个robot那么就直接来一个 403 Forbidden了……<br /><br /><ol><li><br /><li>define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());<br /><li>isset($_REQUEST['GLOBALS']) &amp;&amp; exit('Access Error');<br /><li>foreach(array('_COOKIE', '_POST', '_GET') as $_request) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;foreach($_request as $_key =&gt; $_value) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $_key{0} != '_' &amp;&amp; $_key = daddslashes($_value);<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br /><li>}<br /><li>(!MAGIC_QUOTES_GPC) &amp;&amp; $_FILES = daddslashes($_FILES);<br /><li></ol><br />此处是过滤提交的变量用的,提高安全性的用法。。<br /><br /><ol><li><br /><li>$charset = $dbcharset = $forumfounders = $metakeywords = $extrahead = '';<br /><li>$plugins = $hooks = $admincp = array();<br /><li><br /><li>require_once DISCUZ_ROOT.'./config.inc.php';<br /><li><br /><li>$_DCOOKIE = $_DSESSION = $_DCACHE = $_DPLUGIN = $advlist = array();<br /><li><br /><li>$prelength = strlen($cookiepre);<br /><li>foreach($_COOKIE as $key =&gt; $val) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if(substr($key, 0, $prelength) == $cookiepre) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $_DCOOKIE[(substr($key, $prelength))] = MAGIC_QUOTES_GPC ? $val : daddslashes($val);<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br /><li>}<br /><li></ol><br />初始化一些变量,然后引用config.inc.php这个配置文件,这样开始初始化程序的一些东西了。接下来的一个循环把$_COOKIE中的东西取出来存到$_DCOOKIE这个数组中。注意:在登陆的时候Discuz会把登陆信息存放到$_COOKIE中去。在下面一段会有取出的代码。<br /><br /><ol><li><br /><li>unset($prelength, $_request, $_key, $_value);<br /><li>$timestamp = time();<br /><li><br /><li>if($attackevasive) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;require_once DISCUZ_ROOT.'./include/security.inc.php';<br /><li>}<br /><li></ol><br />这一部分代码是提高安全用的,防一些非法的入侵,include/security.inc.php文件中就是这样一些检查。<br /><br /><ol><li><br /><li>require_once DISCUZ_ROOT.'./include/db_'.$database.'.class.php';<br /><li><br /><li><br /><li>$PHP_SELF = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];<br /><li>$SCRIPT_FILENAME = str_replace('\\\\', '/', (isset($_SERVER['PATH_TRANSLATED']) ? $_SERVER['PATH_TRANSLATED'] : $_SERVER['SCRIPT_FILENAME']));<br /><li>$boardurl = 'http://'.$_SERVER['HTTP_HOST'].preg_replace(&quot;/\/+(api|archiver|wap)?\/*$/i&quot;, '', substr($PHP_SELF, 0, strrpos($PHP_SELF, '/'))).'/';<br /><li><br /><li>if(getenv('HTTP_CLIENT_IP') &amp;&amp; strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$onlineip = getenv('HTTP_CLIENT_IP');<br /><li>} elseif(getenv('HTTP_X_FORWARDED_FOR') &amp;&amp; strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$onlineip = getenv('HTTP_X_FORWARDED_FOR');<br /><li>} elseif(getenv('REMOTE_ADDR') &amp;&amp; strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$onlineip = getenv('REMOTE_ADDR');<br /><li>} elseif(isset($_SERVER['REMOTE_ADDR']) &amp;&amp; $_SERVER['REMOTE_ADDR'] &amp;&amp; strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$onlineip = $_SERVER['REMOTE_ADDR'];<br /><li>}<br /><li></ol><br />第一行是把include/db_mysql.class.php引用进来,这个文件是一个数据库的类。我觉得是不是放在这里太早了点?<br />然后接下的作用就是得到自身的名称$PHP_SELF,自身的文件名字$SCRIPT_FILENAME,论坛的地址$boardurl,得到浏览者的一些信息,比方说ip地址,浏览器类型等等。<br /> </blockquote><br />Section Three:<br /><blockquote><ol><li><br /><li>preg_match(&quot;/[\d\.]{7,15}/&quot;, $onlineip, $onlineipmatches);<br /><li>$onlineip = $onlineipmatches ? $onlineipmatches : 'unknown';<br /><li>unset($onlineipmatches);<br /><li></ol><br />看看ip是不是点分段,7-15个数字之间,用到了一个正则表达式,<br /><ol><li><br /><li>$cachelost = (@include DISCUZ_ROOT.'./forumdata/cache/cache_settings.php') ? '' : 'settings';<br /><li>@extract($_DCACHE['settings']);<br /><li></ol><br />这一段是获得./forumdata/cache/cache_settings.php(即缓存下的设置数组,并展开,方面以后的写法<br /><ol><li><br /><li>if($gzipcompress &amp;&amp; function_exists('ob_gzhandler') &amp;&amp; CURSCRIPT != 'wap') {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;ob_start('ob_gzhandler');<br /><li>} else {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$gzipcompress = 0;<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;ob_start();<br /><li>}<br /><li></ol><br />检查gzip是不是打开了,打开就用ob_gzhandler,没有就用ob_start。<br /><ol><li><br /><li>if(!empty($loadctrl) &amp;&amp; substr(PHP_OS, 0, 3) != 'WIN') {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if($fp = @fopen('/proc/loadavg', 'r')) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; list($loadaverage) = explode(' ', fread($fp, 6));<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; fclose($fp);<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; if($loadaverage &gt; $loadctrl) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;header(&quot;HTTP/1.0 503 Service Unavailable&quot;);<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;include DISCUZ_ROOT.'./include/serverbusy.htm';<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;exit();<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; }<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br /><li>}</ol><br />看到了熟悉的service unavailable了吧?呵呵,平衡负载用的。<br /><br /><ol><li><br /><li>if(defined('CURSCRIPT') &amp;&amp; in_array(CURSCRIPT, array('index', 'forumdisplay', 'viewthread', 'post', 'blog', 'pm', 'topicadmin', 'register', 'archiver'))) {<br /><li>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$cachelost .= (@include DISCUZ_ROOT.'./forumdata/cache/cache_'.CURSCRIPT.'.php') ? '' : ' '.CURSCRIPT;<br /><li>}<br /><li></ol><br /></blockquote><br /><br />Discuz<em>, </em>这么<em>, </em>大家<em>, </em>源代码<em>, </em>一篇

耗子 發表於 2019-6-2 19:57:22

收藏了 很需要!

tuhemm 發表於 2023-3-29 00:31:18

:) 收藏了 很需要!<br />

398601673 發表於 2023-4-7 10:22:11

支持支持zc

tcfa 發表於 2023-4-7 16:54:13

收藏了,学习一下

yuanbintb 發表於 2023-7-10 16:00:09

:) 收藏了 很需要!

plaodj 發表於 2023-7-11 13:22:24

DDDDDDDDDDDDDDDDDDD

71954443 發表於 2023-8-12 05:51:08

感谢分享!

DayFall 發表於 2023-8-15 16:27:10

:) 收藏了 很需要!:) 收藏了 很需要!
頁: [1]
查看完整版本: 史上第一强:Discuz!源代码分析系列(1)--./include/common.inc.php