您的位置:首页 > 编程语言

Discuz!早期版本 代码分析

2009-02-15 18:11 609 查看
/*
总想读一读DZ的源码,可是因为水平问题一直看不懂,这次终于耐下心来开始看这个重要的common文件,收获不小
特把分析注释拿来分享,希望对新手有所帮助
对于其中一些还是不明白地方,希望能得到高手帮助解答
注:由于自己能力有限,而且为了适合新手学习,特地找的DZ的早期版本(02年2.0版,该页面的版本为1.9.2)
讲解人:Linvo 2008-2-29
声明:最终版权归DISCUZ!所有。
*/
error_reporting(E_ERROR | E_WARNING | E_PARSE);
/*
配置错误信息回报的等级,报告简单的运行错误
*/
$mtime = explode(' ', microtime());
$starttime = $mtime[1] + $mtime[0];
/*
页面耗时,计算起始时间$starttime
在每个页面的最后再次使用该方法获取页面解析结束时的时间$endtime,求差($endtime-$starttime)即可得页面执行时间
*/
define('IN_DISCUZ', TRUE);
/*
定义入口常量,为以后合法调用文件使用
*/
set_magic_quotes_runtime(0);
/*
关闭php.ini中magic_quotes_runtime功能
打开时,所有外部引入的数据库资料或者文件等等都会自动转义,比较消耗资源;我们在需要的时候自己转义就行
*/
 
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'] ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
/*
获得该php页面自身地址
说明:DZ2中用的还是php4的用法,现在用的是$_SERVER['SCRIPT_NAME']这种形式
*/
$SCRIPT_FILENAME = str_replace('////', '/', ($HTTP_SERVER_VARS['PATH_TRANSLATED'] ? $HTTP_SERVER_VARS['PATH_TRANSLATED'] : $HTTP_SERVER_VARS['SCRIPT_FILENAME']));
/*
获得当前脚本所在服务器的绝对路径,并对“//”转换为“/”,主要针对windows环境。
说明:PHP 4.3.2 之后,PATH_TRANSLATED 在 Apache 2 SAPI 模式下不再和 Apache 1 一样隐含赋值,而是若 Apache 不生成此值,PHP 便自己生成并将其值放入 SCRIPT_FILENAME 服务器常量中。
*/
$boardurl = 'http://'.$HTTP_SERVER_VARS['HTTP_HOST'].substr($PHP_SELF, 0, strrpos($PHP_SELF, '/') + 1);
/*
获得页面所在目录的URL地址,如:http://127.0.0.1/abc/
注意:“+1”是为了最后以“/”结尾
看不懂这两个字符串函数的,自己参看手册吧,后面还会用到
*/
$discuz_root = ''; //初始化根目录变量
$plugins = $_DCACHE = $_DSESSION = array(); //初始化数组
require $discuz_root.'./config.php'; //调用配置文件
require $discuz_root.'./include/global.php'; //调用全局函数文件
require $discuz_root.'./include/db_'.$database.'.php'; //调用数据库类文件
$timestamp = time(); //获得当前的时间戳
$register_globals = @ini_get('register_globals');
/*
ini_get()用于获得配置值,此处是获取全局变量是否开启
*/
$magic_quotes_gpc = get_magic_quotes_gpc();
/*
获取配置中magic_quotes_gpc是否开启
如果开启,php会对所有Get、Post、Cookie进行自动转义
*/
if(!$magic_quotes_gpc) {
exit('Please set magic_quotes_gpc = On in your php.ini.');
}
/*
如果关闭,则终止页面,并提醒用户开启该配置
*/
$url_redirect = ''; //URL重定向?
$_DSESSION = $_DCACHE = array(); //不清楚为什么又初始化一遍- -!
if(getenv('HTTP_CLIENT_IP')) {
$onlineip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR')) {
$onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif(getenv('REMOTE_ADDR')) {
$onlineip = getenv('REMOTE_ADDR');
} else {
$onlineip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
}
/*
尽量通过各种手段获得客户端IP地址(哪怕是你通过代理^^)
*/
if(!$register_globals || !$magic_quotes_gpc) {
/*
如果未开启全局函数 或者 未开启魔法引号
*/
@extract(daddslashes($HTTP_POST_VARS), EXTR_SKIP);
@extract(daddslashes($HTTP_GET_VARS), EXTR_SKIP);
/*
1、先使用自己定义的转义函数对post、get数组变量进行转义处理
2、extract()函数为了方便创建变量而使用的,直接把数组中的“键名”做变量名,“键值”做其相应的值
第二个参数EXTR_SKIP的意思是“遇到相同的变量名则略过不取代”
3、关于@,用于错误抑制,防止用户看到出错后的错误信息
*/
if(!$register_globals) {
  foreach($HTTP_POST_FILES as $key => $val) {
   $$key = $val['tmp_name'];
   ${$key.'_name'} = $val['name'];
   ${$key.'_size'} = $val['size'];
   ${$key.'_type'} = $val['type'];
  }
  /*
  因为如果关闭了全局变量函数,
  $HTTP_POST_FILES不能在所有脚本中使用,所以需要处理文件上传数组变量(不知理解的对不对?)
  foreach用法不明白的自查手册吧
  把数组中各个元素单独做为变量,并取不同的名字(注意“变量的变量”的使用)
  */
}
}
$tables = array('attachments', 'announcements', 'banned', 'favorites', 'forumlinks', 'forums', 'karmalog',
  'members', 'memo', 'posts', 'searchindex', 'sessions', 'settings', 'smilies', 'stats', 'styles',
  'stylevars', 'subscriptions', 'templates', 'threads', 'pm', 'usergroups', 'words', 'buddys');
/*
把数据库中所有的表名做为一数组,下面马上会用到
注意:该表名只是真实表名的一部分,为不可更改的后缀名,具体表名还包括有表名前缀
*/
foreach($tables as $tablename) {
${'table_'.$tablename} = $tablepre.$tablename;
}
/*
把数据库中的具体表名赋值给统一前缀的变量,方便以后程序中使用
'table_'为统一后的表名前缀;$tablepre为自定义的表名前缀(在config.php中定义)
*/
unset($tablename); //销毁临时变量
$db = new dbstuff; //初始化一个数据库类实例
$db->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect); //连接数据库服务器
$db->select_db($dbname); //选择数据库
unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect); //销毁变量(为了安全)
$currscript = basename($PHP_SELF);
/*
获取当前脚本的文件名,只有文件名哦(如:index.php)
*/
$currscript = substr($currscript, 0, strpos($currscript, '.php'));
/*
去掉文件名的扩展名,即去掉'.php'(如:index)
*/
$cachelost = (@include $discuz_root.'./forumdata/cache/cache_settings.php') ? '' : 'settings';
/*
调用cache_settings文件,论坛页面的基本设置,若成功则返回空字符串,否则返回字符串'settings'
先说明一下,/forumdata/cache是数据库内容的缓存,它们都是数组形式,/forumdata/template是模板页面的缓存
*/
if(in_array($currscript, array('index', 'forumdisplay', 'viewthread', 'post', 'search', 'pm'))) {
/*
如果该脚本名在此数组中
该数组中的脚本名为DZ根目录下的一些文件名(具体为什么是这几个文件,尚不清楚:P)
*/
$cachelost .= (@include $discuz_root.'./forumdata/cache/cache_'.$currscript.'.php') ? '' : ' '.$currscript;
/*
应该是调用该页面的相应缓存页面
和上面类似,成功返回空字符串,否则返回"空格+当前脚本名"
注意这里用的是“.=”,最后要连接到原来$cachelost值的后面!
*/
}
 
@extract($_DCACHE['settings']); //还是把数组中元素变成能直接使用的变量
$sid = isset($HTTP_GET_VARS['sid']) ? $HTTP_GET_VARS['sid'] :
(isset($HTTP_POST_VARS['sid']) ? $HTTP_POST_VARS['sid'] :
$HTTP_COOKIE_VARS['sid']);
/*
先看GET数组中是否有sid变量,如果有直接获取即可;倘若没有的话再到POST数组中找,实在没有最后从COOKIE数组中找
连着两次使用了三目运算符,注意使用效果的先后顺序
*/
$discuz_user = daddslashes($HTTP_COOKIE_VARS['_discuz_user']);
$discuz_pw = daddslashes($HTTP_COOKIE_VARS['_discuz_pw']);
/*
对两个COOKIE变量进行自定义转义后,赋值给新变量
*/
$newpm = $ipbanned = $sessionexists = 0; //初始化变量
if($sid) {//先看sid是否有效
if($discuz_user) { //如果用户名存在
  $query = $db->query("SELECT s.sid, s.groupid, s.styleid, s.groupid, m.username AS discuz_user, m.password AS discuz_pw, m.status, m.email, m.timeoffset, m.tpp, m.ppp, m.credit, m.timeformat, m.dateformat, m.signature, m.lastvisit, m.newpm
     FROM $table_sessions s, $table_members m WHERE m.username=s.username AND s.sid='$sid' AND s.ip='$onlineip' AND ('$discuz_user'='' OR ('$discuz_user'<>'' AND m.username='$discuz_user' AND m.password='$discuz_pw'))");
  /*
  根据sid在数据库sessions表以及members表中查询相应的信息
  */
} else { //如果用户名不存在
  $query = $db->query("SELECT sid, status, username AS sessionuser, groupid, styleid FROM $table_sessions WHERE sid='$sid' AND ip='$onlineip'");
  /*
  也根据sid在sessions表中查找相应信息
  */
}
if($_DSESSION = $db->fetch_array($query)) {
/*
如果找到,就把信息存入$_DSESSION数组中
*/
  $sessionexists = 1; //说明是会员,并且标注该用户在线
  if(!empty($_DSESSION['sessionuser'])) {
   $query = $db->query("SELECT m.username AS discuz_user, m.password AS discuz_pw, m.status, m.email, m.timeoffset, m.tpp, m.ppp, m.credit, m.timeformat, m.dateformat, m.signature, m.avatar, m.lastvisit, m.newpm FROM $table_members m WHERE username='$_DSESSION[sessionuser]'");
   $_DSESSION = array_merge($_DSESSION, $db->fetch_array($query));
  }
  /*
  如果是会员的话,再进行一次查询,并用array_merge()把前面相同的值覆盖
  */
} else { //说明是游客
  $query = $db->query("SELECT sid, status, groupid, styleid FROM $table_sessions WHERE sid='$sid' AND ip='$onlineip'");
  if($_DSESSION = $db->fetch_array($query)) {
   clearcookies();
   $sessionexists = 1;
  }
  /*
  把游客的信息也再次提取出来,放入$_DSESSION数组
  并调用自定义clearcookies()函数清空cookies,同时设置该用户在线
  */
}
}
/*
说明:对于上面这一块儿数据库相关操作,具体不是太明白了,希望有达人来解释一下~
*/
…………
…………
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: