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,同时设置该用户在线 */ } } /* 说明:对于上面这一块儿数据库相关操作,具体不是太明白了,希望有达人来解释一下~ */ ………… …………
相关文章推荐
- Discuz代码分析——index.php
- magento -- 1.4版本使用google analytic 流量分析代码的bug
- DISCUZ代码分析
- hadoop 0.1.0版本namenode代码分析
- 管理Discuz!代码分析的收集整理[2][文件功能]
- VC高版本编译早期代码常见错误...
- leveldb代码阅读(16)——流程分析:打开数据库(详细版本)
- Android eng版本开机有fastboot界面(lk代码分析)
- discuz代码分析二 logging.php
- discuz 3.2 discuz_application.php代码执行逻辑顺序分析
- 管理Discuz!代码分析的收集整理[1]
- discuz代码分析logging.php (转载)
- Discuz!NT论坛代码小分析【转】
- 对discuz的代码分析学习(四)论坛入口文件
- Discuz! 6.x/7.x 版本 前台任意代码执行漏洞
- discuz代码分析一 从common.inc.php开始
- leveldb代码阅读(17)——流程分析:写数据(详细版本)
- discuz的htm模板代码分析
- 对discuz的代码分析学习————首页文件(转自陈)
- Discuz注册页面的邮箱验证代码分析