收藏 分销(赏)

discuz!源码分析.doc

上传人:xrp****65 文档编号:7032267 上传时间:2024-12-25 格式:DOC 页数:100 大小:433KB 下载积分:10 金币
下载 相关 举报
discuz!源码分析.doc_第1页
第1页 / 共100页
discuz!源码分析.doc_第2页
第2页 / 共100页


点击查看更多>>
资源描述
网站建设 作者:边城浪子 discuz!源码分析 源代码分析[1] 第一个文件当然是分析./include/common.inc.php这个文件,这个是Discuz的核心中的核心,基本上每次操作都include到了这个文件,下面就分七段来分析这个文件: Section One: 以下内容为程序代码: //定义PHP一些环境 error_reporting(0); set_magic_quotes_runtime(0); //设置Discuz开始的时间 $mtime = explode(' ', microtime()); $discuz_starttime = $mtime[1] + $mtime[0]; //定义一些常量 define('SYS_DEBUG', FALSE); define('IN_DISCUZ', TRUE); define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -7)); //获得绝对目录 //通用性 if(PHP_VERSION < '4.1.0') { $_GET = &$HTTP_GET_VARS; $_POST = &$HTTP_POST_VARS; $_COOKIE = &$HTTP_COOKIE_VARS; $_SERVER = &$HTTP_SERVER_VARS; $_ENV = &$HTTP_ENV_VARS; $_FILES = &$HTTP_POST_FILES; } 这一段基本上就是设置一下错误报告,把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这样的方式得到,有通用性~! 以下内容为程序代码: require_once DISCUZ_ROOT.'./include/global.func.php'; 把include/global.inc.php引用进来,这个文件是Discuz的核心函数文件,包含了Discuz用到的很多通用的函数,可以说它就是一个大的通用函数库。 以下内容为程序代码: define('ISROBOT', getrobot()); if(defined('NOROBOT') && ISROBOT) { exit(header("HTTP/1.1 403 Forbidden")); } 这里是定义一个ISROBOT常量,看看浏览者是什么东东,比方说如果浏览者是一个robot那么就直接来一个 403 Forbidden了…… 以下内容为程序代码: define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc()); isset($_REQUEST['GLOBALS']) && exit('Access Error'); foreach(array('_COOKIE', '_POST', '_GET') as $_request) { foreach($$_request as $_key => $_value) { $_key{0} != '_' && $$_key = daddslashes($_value); } } (!MAGIC_QUOTES_GPC) && $_FILES = daddslashes($_FILES); 此处是过滤提交的变量用的,提高安全性的用法。。 以下内容为程序代码: $charset = $dbcharset = $forumfounders = $metakeywords = $extrahead = ''; $plugins = $hooks = $admincp = array(); require_once DISCUZ_ROOT.'./config.inc.php'; $_DCOOKIE = $_DSESSION = $_DCACHE = $_DPLUGIN = $advlist = array(); $prelength = strlen($cookiepre); foreach($_COOKIE as $key => $val) { if(substr($key, 0, $prelength) == $cookiepre) { $_DCOOKIE[(substr($key, $prelength))] = MAGIC_QUOTES_GPC ? $val : daddslashes($val); } } 初始化一些变量,然后引用config.inc.php这个配置文件,这样开始初始化程序的一些东西了。接下来的一个循环把$_COOKIE中的东西取出来存到$_DCOOKIE这个数组中。注意:在登陆的时候Discuz会把登陆信息存放到$_COOKIE中去。在下面一段会有取出的代码。 以下内容为程序代码: unset($prelength, $_request, $_key, $_value); $timestamp = time(); if($attackevasive) { require_once DISCUZ_ROOT.'./include/security.inc.php'; } 这一部分代码是提高安全用的,防一些非法的入侵,include/security.inc.php文件中就是这样一些检查。 以下内容为程序代码: require_once DISCUZ_ROOT.'./include/db_'.$database.'.class.php'; $PHP_SELF = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; $SCRIPT_FILENAME = str_replace('\\\\', '/', (isset($_SERVER['PATH_TRANSLATED']) ? $_SERVER['PATH_TRANSLATED'] : $_SERVER['SCRIPT_FILENAME'])); $boardurl = 'http://'.$_SERVER['HTTP_HOST'].preg_replace("/\/+(api|archiver|wap)?\/*$/i", '', substr($PHP_SELF, 0, strrpos($PHP_SELF, '/'))).'/'; if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) { $onlineip = getenv('HTTP_CLIENT_IP'); } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) { $onlineip = getenv('HTTP_X_FORWARDED_FOR'); } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) { $onlineip = getenv('REMOTE_ADDR'); } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) { $onlineip = $_SERVER['REMOTE_ADDR']; } 第一行是把include/db_mysql.class.php引用进来,这个文件是一个数据库的类。我觉得是不是放在这里太早了点? 然后接下的作用就是得到自身的名称$PHP_SELF,自身的文件名字$SCRIPT_FILENAME,论坛的地址$boardurl,得到浏览者的一些信息,比方说ip地址,浏览器类型等等。 以下内容为程序代码: preg_match("/[\d\.]{7,15}/", $onlineip, $onlineipmatches); $onlineip = $onlineipmatches[0] ? $onlineipmatches[0] : 'unknown'; unset($onlineipmatches); 看看ip是不是点分段,7-15个数字之间,用到了一个正则表达式, 以下内容为程序代码: $cachelost = (@include DISCUZ_ROOT.'./forumdata/cache/cache_settings.php') ? '' : 'settings'; @extract($_DCACHE['settings']); 这一段是获得./forumdata/cache/cache_settings.php(即缓存下的设置数组,并展开,方面以后的写法 以下内容为程序代码: if($gzipcompress && function_exists('ob_gzhandler') && CURSCRIPT != 'wap') { ob_start('ob_gzhandler'); } else { $gzipcompress = 0; ob_start(); } 检查gzip是不是打开了,打开就用ob_gzhandler,没有就用ob_start。 以下内容为程序代码: if(!empty($loadctrl) && substr(PHP_OS, 0, 3) != 'WIN') { if($fp = @fopen('/proc/loadavg', 'r')) { list($loadaverage) = explode(' ', fread($fp, 6)); fclose($fp); if($loadaverage > $loadctrl) { header("HTTP/1.0 503 Service Unavailable"); include DISCUZ_ROOT.'./include/serverbusy.htm'; exit(); } } } 看到了熟悉的service unavailable了吧?呵呵,平衡负载用的。 以下内容为程序代码: if(defined('CURSCRIPT') && in_array(CURSCRIPT, array('index', 'forumdisplay', 'viewthread', 'post', 'blog', 'pm', 'topicadmin', 'register', 'archiver'))) { $cachelost .= (@include DISCUZ_ROOT.'./forumdata/cache/cache_'.CURSCRIPT.'.php') ? '' : ' '.CURSCRIPT; } 看看是不是index, forumdisplay, viewthread这些文件是不是缓存了,有的话把它装到$cachelost这个变量中。 Section Four: 以下内容为程序代码: $db = new dbstuff; $db->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect); $dbhost = $dbuser = $dbpw = $dbname = $pconnect = NULL; 好了,这里是初始化一个dbstull类的实例,也就是说前面的include/db_mysql.class.php在这里用上了,所以我觉得那个require_once早了点,放到这里的前面最合适了~!J下面就是连上mysql了,然后把几个配置的变量NULL掉,安全性考虑得真多,武装到牙齿! 以下内容为程序代码: $sid = daddslashes(($transsidstatus || (defined('CURSCRIPT') && CURSCRIPT == 'wap'))&& (isset($_GET['sid']) || isset($_POST['sid'])) ? (isset($_GET['sid']) ? $_GET['sid'] : $_POST['sid']) : (isset($_DCOOKIE['sid']) ? $_DCOOKIE['sid'] : '')); 看看是不是后台设置了通过sid传输的那个东东,还有是不是通过wap访问的,还有是不是有sid这个东东在$_GET或$_POST这两个的任何一个中,以上结论都成立的话从GET中获得sid,不成立的话从$_DCOOKIE中获得。 以下内容为程序代码: $discuz_auth_key = md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']); 设置一个$discuz_auth_key,md5加密。。 以下内容为程序代码: if(isset($_DCOOKIE['auth']) && $_DCOOKIE['auth']) { list($discuz_pw, $discuz_secques, $discuz_uid) = daddslashes(explode("\t", authcode($_DCOOKIE['auth'], 'DECODE')), 1); if(!is_numeric($discuz_uid) || !$discuz_uid) { clearcookies(); } } else { list($discuz_pw, $discuz_secques, $discuz_uid) = array('', '', 0); } 这一段是用来检查是不是$_DCOOKIE[‘auth’]存在,如果有的话就把其中存放的东西分别给$discuz_pw, $discuz_secques, $discuz_uid这三个变量,分别对应密码,提示问题和uid。 Section Five: 以下内容为程序代码: $newpm = $newpmexists = $sessionexists = $seccode = $bloguid = 0;//初始化变量 $membertablefields = 'm.uid AS discuz_uid, m.username AS discuz_user, m.password AS discuz_pw, m.secques AS discuz_secques, m.adminid, m.groupid, m.groupexpiry, m.extgroupids, m.email, m.timeoffset, m.tpp, m.ppp, m.posts, m.digestposts, m.oltime, m.pageviews, m.credits, m.extcredits1, m.extcredits2, m.extcredits3, m.extcredits4, m.extcredits5, m.extcredits6, m.extcredits7, m.extcredits8, m.timeformat, m.dateformat, m.pmsound, m.sigstatus, m.invisible, m.lastvisit, m.lastactivity, m.lastpost, m.newpm, m.accessmasks, m.xspacestatus, m.editormode, m.customshow'; if($sid) { if($discuz_uid) { $query = $db->query("SELECT s.sid, s.styleid, s.groupid='6' AS ipbanned, s.pageviews AS spageviews, s.lastolupdate, s.seccode, $membertablefields FROM {$tablepre}sessions s, {$tablepre}members m WHERE m.uid=s.uid AND s.sid='$sid' AND CONCAT_WS('.',s.ip1,s.ip2,s.ip3,s.ip4)='$onlineip' AND m.uid='$discuz_uid' AND m.password='$discuz_pw' AND m.secques='$discuz_secques'"); } else { $query = $db->query("SELECT sid, uid AS sessionuid, groupid, groupid='6' AS ipbanned, pageviews AS spageviews, styleid, lastolupdate, seccode FROM {$tablepre}sessions WHERE sid='$sid' AND CONCAT_WS('.',ip1,ip2,ip3,ip4)='$onlineip'"); } if($_DSESSION = $db->fetch_array($query)) { $sessionexists = 1; if(!empty($_DSESSION['sessionuid'])) { $query = $db->query("SELECT $membertablefields FROM {$tablepre}members m WHERE uid='$_DSESSION[sessionuid]'"); $_DSESSION = array_merge($_DSESSION, $db->fetch_array($query)); } } else { $query = $db->query("SELECT sid, groupid, groupid='6' AS ipbanned, pageviews AS spageviews, styleid, lastolupdate, seccode FROM {$tablepre}sessions WHERE sid='$sid' AND CONCAT_WS('.',ip1,ip2,ip3,ip4)='$onlineip'"); if($_DSESSION = $db->fetch_array($query)) { clearcookies(); $sessionexists = 1; } } } 这一段是有蛮长的,不过看着长不代表它就难,第一行是初始化变量用的(无论何时用变量都要考虑初始化,要不然安全性不值得一提,一个get就完了) 接下来是判断是不是有sid,有的话就从cdb_session表中取来,然后连接一下cdb_members表取出一些更具体的东西,具体是哪些东西?在$membertablefields这个变量里面已经全面写出来了,对应数据库看吧,不看的话用英语猜猜得出的。。。在这里Discuz标记了一个sessionexist变量,表示这个会员是在线的。 以下内容为程序代码: if(!$sessionexists) { if($discuz_uid) { $query = $db->query("SELECT $membertablefields FROM {$tablepre}members m WHERE m.uid='$discuz_uid' AND m.password='$discuz_pw' AND m.secques='$discuz_secques'"); if(!($_DSESSION = $db->fetch_array($query))) { clearcookies(); } } 要是不存在sid,不存在discuz_uid,那就肯定没有登陆了,清掉cookie,要是有$discuz_uid的话,还是从members表中取出信息存放到$_DSESSION数组中 以下内容为程序代码: if(ipbanned($onlineip)) $_DSESSION['ipbanned'] = 1; $_DSESSION['sid'] = random(6); $_DSESSION['seccode'] = random(6, 1); } $_DSESSION['dateformat'] = empty($_DSESSION['dateformat']) ? $_DCACHE['settings']['dateformat'] : $_DSESSION['dateformat']; $_DSESSION['timeformat'] = empty($_DSESSION['timeformat']) ? $_DCACHE['settings']['timeformat'] : ($_DSESSION['timeformat'] == 1 ? 'h:i A' : 'H:i'); $_DSESSION['timeoffset'] = isset($_DSESSION['timeoffset']) && $_DSESSION['timeoffset'] != 9999 ? $_DSESSION['timeoffset'] : $_DCACHE['settings']['timeoffset']; 这个是判断ip是不是在被阻止的list里,是的话就标记一下,用$_DSESSION[‘ipbanned’]标记的。再把一个随机的sid和seccode写到$_DSESSION数组。然后接下来是把日期,时间,时差写入$_DSESSION这个变量。 以下内容为程序代码: $membertablefields = ''; @extract($_DSESSION); $lastvisit = empty($lastvisit) ? $timestamp - 86400 : $lastvisit; $timenow = array('time' => gmdate("$dateformat $timeformat", $timestamp + 3600 * $timeoffset), 'offset' => ($timeoffset >= 0 ? ($timeoffset == 0 ? '' : '+'.$timeoffset) : $timeoffset)); if(PHP_VERSION > '5.1') { @date_default_timezone_set('Etc/GMT'.($timeoffset > 0 ? '-' : '+').(abs($timeoffset))); } 又见变量初始化,然后是把$_DESSION给展开,这样方便多了。接下来判断是不是有上次访问的时间,有的话就没事,没有的话就减去24小时。 接下来给一个现在的时间,这里有一个时间的问题,所以把时间加上时差乘上3600秒就得到当前时间了。 PHP 5 能处理时差了,所以Discuz在这里也设置了一下,想得真全面!! Section Six: [quote] 以下内容为程序代码: $accessadd1 = $accessadd2 = $modadd1 = $modadd2 = ''; if(empty($discuz_uid) || empty($discuz_user)) { $discuz_user = $extgroupids = ''; $discuz_uid = $adminid = $posts = $digestposts = $pageviews = $oltime = $invisible = $credits = $extcredits1 = $extcredits2 = $extcredits3 = $extcredits4 = $extcredits5 = $extcredits6 = $extcredits7 = $extcredits8 = 0; $groupid = empty($groupid) || $groupid != 6 ? 7 : 6; } else { $discuz_userss = $discuz_user; $discuz_user = addslashes($discuz_user); if($accessmasks) { $accessadd1 = ', a.allowview, a.allowpost, a.allowreply, a.allowgetattach, a.allowpostattach'; $accessadd2 = "LEFT JOIN {$tablepre}access a ON a.uid='$discuz_uid' AND a.fid=f.fid"; } if($adminid == 3) { $modadd1 = ', m.uid AS ismoderator'; $modadd2 = "LEFT JOIN {$tablepre}moderators m ON m.uid='$discuz_uid' AND m.fid=f.fid"; } } if($errorreport == 2 || ($errorreport == 1 && $adminid > 0)) { error_reporting(E_ERROR | E_WARNING | E_PARSE); } 首先初始化变量,然后看看$discuz_user$和$discuz_user这两个变量是不是存在,不存在的话一系列的变量全部置0(没登陆当然不存在版主权限管理员什么的),存在的话就来两个赋值,这就是为什么在Discuz UserGuide里面说$discuz_userss是没有过滤的,而$discuz_user是过滤掉的,能直接进行数据库操作的。 然后看看怎么样设置PHP 的出错级别,注意如果你的管理员的话,Discuz给的是一个更高的错误显示级别! 以下内容为程序代码: define('FORMHASH', formhash()); $statstatus && require_once DISCUZ_ROOT.'./include/counter.inc.php'; $extra = isset($extra) && @preg_match("/^[&=;a-z0-9]+$/i", $extra) ? $extra : ''; $tpp = intval(empty($_DSESSION['tpp']) ? $topicperpage : $_DSESSION['tpp']); $ppp = intval(empty($_DSESSION['ppp']) ? $postperpage : $_DSESSION['ppp']); 这一段定义一个form hash,这个是通过global.func.php这个文件中的formhash()函数来的。然后看是不是要等到统计信息,要的话就引用./include/counter.inc.php这个文件,不要的话当然就不引用了。 $extra这个东东不知道做嘛用的。。。。 $tpp-threads per page每页的帖子数 $ppp-posts per page每页的回复数 以下内容为程序代码: $rsshead = $navtitle = $navigation = ''; $_DSESSION['groupid'] = $groupid = empty($ipbanned) ? (empty($groupid) ? 7 : intval($groupid)) : 6; if(!@include DISCUZ_ROOT.'./forumdata/cache/usergroup_'.$groupid.'.php') { $query = $db->query("SELECT type FROM {$tablepre}usergroups WHERE groupid='$groupid'"); $grouptype = $db->result($query, 0); if(!empty($grouptype)) { $cachelost .= ' usergroup_'.$groupid; } else { $grouptype = 'member'; } } 用来得到用户组的,首先看看是不是缓存中有,没有的话就访问数据库了,有的话当然就用缓存的。。 以下内容为程序代码: if($passport_status && ($passport_status != 'shopex' || !$passport_shopex)) { $passport_forward = rawurlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); $link_login = $passport_url.$passport_login_url.(strpos($passport_login_url, '?') === FALSE ? '?' : '&').'forward='.$passport_forward; $link_logout = $passport_url.$passport_logout_url.(strpos($passport_logout_url, '?') === FALSE ? '?' : '&').'forward='.$passport_forward; $link_register = $passport_url.$passport_register_url.(strpos($passport_register_url, '?') === FALSE ? '?' : '&').'forward='.$passport_forward; } else { $link_login = 'logging.php?action=login'; $link_logout = 'logging.php?action=logout&formhash='.FORMHASH; $link_register = 'register.php'; } Discuz通行证用的。主要就是得到一些应用程序的地址。 以下内容为程序代码: if($discuz_uid && $_DSESSION) { if(!empty($groupexpiry) && $groupexpiry < $timestamp && (!defined('CURSCRIPT') || (CURSCRIPT != 'wap' && CURSCRIPT != 'member'))) { dheader("Location: {$boardurl}member.php?ac
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服