在使用织梦后台管理网站的过程中,有一个网站文件管理器出现了异常,情况如下:
1.删除文件的时候在确认文件删除的对话框上下出现了两行javascript代码,代码的内容就是blank.js文件的内容(该文件在管理员目录下面的js目录中),而且这两行代码被用红色背景加重(现在 想想应该是浏览器的警示,与代码本身无关)。
2.部分文件删除的时候,系统提示警告,禁止删除
3.编辑文件的时候工作目录和文件名称的两个input的内容是空的,正常情况下应该自动填充当前目录和当前要修改的文件名称才对。所以导致编辑完成后无法保存文件,即文件无法修改。
根据编辑和删除文件的链接路径,我找到了文件管理器执行的第一个php文件---file_mange_view.php,这个文件在后台管理 员文件夹下(默认/admin),打开这个文件,可以看到这个文件控制了后台文件管理过程中显示的对话框页面,包括几种情况:重命名、新建目录、移动文 件、删除文件、编辑文件、可视化编辑、新建文件和上传文件,用if/else判断$fmdo变量的值来决定要进行的操作,$fmdo变量是通过url传递 进来的,也就是在$_GET变量中保存的。
首先针对第一个问题,先看删除文件部分的情况,删除部分的代码截取如下:
//file_mange_view.php//删除文件 else if($fmdo=="del") { $wintitle = " 文件管理"; $wecome_info = " 文件管理::删除文件 [<a href=‘file_manage_main.php?activepath=$activepath‘>文件浏览器</a>]</a>"; $win = new OxWindow(); $win->Init("file_manage_control.php","js/blank.js","POST"); $win->AddHidden("fmdo",$fmdo); $win->AddHidden("activepath",$activepath); $win->AddHidden("filename",$filename); if(@is_dir($cfg_basedir.$activepath."/$filename")) { $wmsg = "你确信要删除目录:$filename 吗?"; } else { $wmsg = "你确信要删除文件:$filename 吗?"; } $win->AddTitle("删除文件确认"); $win->AddMsgItem($wmsg,"50"); $winform = $win->GetWindow("ok"); $win->Display(); }
首先看这一行:$win = new OxWindow();,这里初始化了一个类OxWindow,随即调用了这个类的Init()方法,而这个类在本文件的开头用require_once引入进来:
require_once(DEDEINC."/oxwindow.class.php");
DEDEINC变量就是根目录下面的/include文件夹,于是也打开这个文件查看,首先发现它又引入了另一个文件:
require_once(DEDEINC."/dedetag.class.php");
先不管这个dedetag.class.php,用到它的时候再去找它,先看这个oxwindow是干什么的,根据 file_mange_view.php中代码执行的流程,首先实例化OxWindow,也就是调用它的构造方法,但是这玩意儿并没有构造方法,所以继续 看下去,调用了Init方法,下面截取这个方法的代码:
/** * 初始化为含表单的页面 * * @param string $formaction 表单操作action * @param string $checkScript 检测验证js * @param string $formmethod 表单类型 * @param string $formname 表单名称 * @return void */ function Init($formaction="", $checkScript="js/blank.js", $formmethod="POST", $formname="myform") { $this->myWin .= "<script language=‘javascript‘>\r\n"; if($checkScript!="" && file_exists($checkScript)) { $fp = fopen($checkScript,"r"); $this->myWin .= fread($fp,filesize($checkScript)); fclose($fp); } else { $this->myWin .= "<!-- function CheckSubmit()\r\n{ return true; } -->"; } $this->myWin .= "</script>\r\n"; $this->formName = $formname; $this->myWin .= "<form name=‘$formname‘ method=‘$formmethod‘ onSubmit=‘return CheckSubmit();‘ action=‘$formaction‘>\r\n"; }
这个方法是这样调用的$win->Init("file_manage_control.php","js/blank.js","POST");,所以传递的参数也显而易见,就是两个文件名和一个POST字符串,这个方法干了什么呢,正如它的注释中说的,就是将$this->myWin这个变量搞成一个非常长的字符串,字符串中就是一个html页面的一部分,开头是从js/blank.js中读出来的javascript代码,如果这个文件为空或者不存在,就写一个名叫CheckSubmit()的函数并且永远返回真,其实打开这个blank.js文件发现文件中的内容也是这个永远返回真的函数,所以这段代码其实很无聊。接下来就是一个表单的开始,就是form标签的前半部分,用传递的参数设置name,method,action等值。然后回到调用Init函数的地方接着往下看就大概明白了,原来调用这个OxWindow类就是为了在删除/编辑文件等操作的的时候初始化一个提示页面,这个页面被初始化成一个带表单的页面,也就是本文开头第一个问题中的那个问题页面,所以接下来的几行代码都是在借助OxWindow类向这个页面中添加要显示的内容,最后在调用Display()方法把这个页面显示出来。所以要解决问题一就要看一看这个页面是怎么显示出来的,下面是这个Display()方法:
/** * 显示页面 * * @access public * @param string $modfile 模型模板 * @return string */ function Display($modfile="") { global $cfg_templets_dir,$wecome_info,$cfg_basedir; if(empty($wecome_info)) { $wecome_info = "DedeCMS OX 通用对话框:"; } $ctp = new DedeTagParse(); if($modfile==‘‘) { $ctp->LoadTemplate($cfg_basedir.$cfg_templets_dir.‘/plus/win_templet.htm‘); } else { $ctp->LoadTemplate($modfile); } $emnum = $ctp->Count; for($i=0;$i<=$emnum;$i++) { if(isset($GLOBALS[$ctp->CTags[$i]->GetTagName()])) { $ctp->Assign($i,$GLOBALS[$ctp->CTags[$i]->GetTagName()]); } } $ctp->Display(); $ctp->Clear(); } } //End Class
一眼就看到这个方法又实例化了另外一个类叫DedeTagParse,然后调用它的LoadTemplate()方法,可以猜测出来,这个类是调用了模板显示前面已经初始化好的页面内容。LoadTemplate()方法就是调用模板,最后的Display()方法就是显示,所以问题1的异常就可能有两种成因:第一个是调用的模板出了问题,另一个是处理模板的过程有问题,然而处理模板的过程都是通过实例化类来完成的,类文件出问题的概率是比较小的,所以首先检查这个模板,传递的这个参数就是这个模板的路径和文件名,也就是在根目录下面的模板目录/templets/plus/win_templet.htm文件,打开仔细检查就发现问题所在了,在模板中引用织梦后台变量的时候居然单引号和双引号用的很混乱,有一处单引号中还有单引号,所以在解析模板后显示的时候很多地方都出错,于是将引号修正再进入后台就显示正常了。 问题1一解决,同理就先从模板入手来解决问题3,但是没有发现任何异常,无奈就在出现问题的页面使用firebug查看源码,发现其中在head标签中meta标记里面居然写着charset=<?php echo $cfg_charset_lang;?>为什么php代码被浏览器原样输出,而没有解析呢,于是找到另一个网站后台的同一个模板页面将其替换掉,然后就一切正常了。这样问题1和问题3都被解决。 问题2实在郁闷,进入ftp发现文件的权限被设置为644,除了root外,其他用户没有写权限,所以在后台删除不了。