Browse Source

完善病毒扫描,文件校验合并到病毒扫描中

tags/6.0.0
tianya 3 years ago
parent
commit
b60deb4226
24 changed files with 927 additions and 884 deletions
  1. +0
    -6
      src/dede/inc/inc_action_info.php
  2. +0
    -1
      src/dede/inc/inc_menu.php
  3. +0
    -1
      src/dede/inc/inc_menu_map.php
  4. +2
    -3
      src/dede/mytag_tag_guide_ok.php
  5. +5
    -5
      src/dede/plus_edit.php
  6. +1
    -1
      src/dede/plus_main.php
  7. +1
    -1
      src/dede/recycling.php
  8. +1
    -1
      src/dede/search_keywords_main.php
  9. +8
    -8
      src/dede/shops_delivery.php
  10. +6
    -6
      src/dede/shops_operations.php
  11. +4
    -4
      src/dede/shops_operations_cart.php
  12. +3
    -3
      src/dede/shops_operations_userinfo.php
  13. +91
    -90
      src/dede/sys_safetest.php
  14. +0
    -470
      src/dede/sys_verifies.php
  15. +4
    -3
      src/dede/templets/sys_safetest.htm
  16. +95
    -0
      src/dede/templets/sys_safetest_viewdiff.htm
  17. +0
    -78
      src/dede/templets/sys_verifies.htm
  18. +0
    -56
      src/dede/templets/sys_verifies_getfiles.htm
  19. +0
    -74
      src/dede/templets/sys_verifies_manage.htm
  20. +0
    -73
      src/dede/templets/sys_verifies_verify.htm
  21. +18
    -0
      src/include/dedehttpdown.class.php
  22. +83
    -0
      src/static/css/diffview.css
  23. +411
    -0
      src/static/js/difflib.js
  24. +194
    -0
      src/static/js/diffview.js

+ 0
- 6
src/dede/inc/inc_action_info.php View File

@@ -446,12 +446,6 @@ $actionSearch[10] = array(
'purview' =>'sys_data',
'linkurl' =>'sys_sql_query.php'
),
13 => array(
'title' =>'文件校验[S]',
'description' =>'文件校验将检查本站文件是否和dedecms原始文件是否完全一致',
'purview' =>'sys_verifies',
'linkurl' =>'sys_verifies.php'
),
14 => array(
'title' =>'病毒扫描[S]',
'description' =>'以DedeCMS开发模式为标准对现有的文件进行扫描并进行判断',


+ 0
- 1
src/dede/inc/inc_menu.php View File

@@ -72,7 +72,6 @@ $adminMenu2 = "<m:top item='7_' name='模板管理' display='none' rank='temp_On
<m:item name='计划任务管理' link='sys_task.php' rank='sys_Task' target='main' />
<m:item name='数据库备份/还原' link='sys_data.php' rank='sys_Data' target='main' />
<m:item name='SQL命令行工具' link='sys_sql_query.php' rank='sys_Data' target='main' />
<m:item name='文件校验[S]' link='sys_verifies.php' rank='sys_verify' target='main' />
<m:item name='病毒扫描[S]' link='sys_safetest.php' rank='sys_verify' target='main' />
<m:item name='系统错误修复[S]' link='sys_repair.php' rank='sys_verify' target='main' />
</m:top>


+ 0
- 1
src/dede/inc/inc_menu_map.php View File

@@ -123,7 +123,6 @@ $menusMain = "
<m:item name='计划任务管理' link='sys_task.php' rank='sys_Task' target='main' />
<m:item name='数据库备份/还原' link='sys_data.php' rank='sys_Data' target='main' />
<m:item name='SQL命令行工具' link='sys_sql_query.php' rank='sys_Data' target='main' />
<m:item name='文件校验[S]' link='sys_verifies.php' rank='sys_verify' target='main' />
<m:item name='病毒扫描[S]' link='sys_safetest.php' rank='sys_verify' target='main' />
<m:item name='系统错误修复[S]' link='sys_repair.php' rank='sys_verify' target='main' />
</m:top>


+ 2
- 3
src/dede/mytag_tag_guide_ok.php View File

@@ -45,13 +45,12 @@ if($dopost=='savetag')
{
$fulltag = addslashes($fulltag);
$tagname = "auto";
$inQuery = "
INSERT INTO #@__mytag(typeid,tagname,timeset,starttime,endtime,normbody,expbody)
$inQuery = "INSERT INTO `#@__mytag`(typeid,tagname,timeset,starttime,endtime,normbody,expbody)
VALUES('0','$tagname','0','0','0','$fulltag','');
";
$dsql->ExecuteNoneQuery($inQuery);
$id = $dsql->GetLastID();
$dsql->ExecuteNoneQuery("UPDATE #@__mytag SET tagname='{$tagname}_{$id}' WHERE aid='$id'");
$dsql->ExecuteNoneQuery("UPDATE `#@__mytag` SET tagname='{$tagname}_{$id}' WHERE aid='$id'");
$fulltag = "{dede:mytag name='{$tagname}_{$id}' ismake='yes'/}";
}
include DedeInclude('templets/mytag_tag_guide_ok.htm');

+ 5
- 5
src/dede/plus_edit.php View File

@@ -13,13 +13,13 @@ CheckPurview('sys_plus');
$aid = preg_replace("#[^0-9]#", "", $aid);
if($dopost=="show")
{
$dsql->ExecuteNoneQuery("UPDATE #@__plus SET isshow=1 WHERE aid='$aid';");
$dsql->ExecuteNoneQuery("UPDATE `#@__plus` SET isshow=1 WHERE aid='$aid';");
ShowMsg("成功启用一个插件,请刷新导航菜单!","plus_main.php");
exit();
}
else if($dopost=="hide")
{
$dsql->ExecuteNoneQuery("UPDATE #@__plus SET isshow=0 WHERE aid='$aid';");
$dsql->ExecuteNoneQuery("UPDATE `#@__plus` SET isshow=0 WHERE aid='$aid';");
ShowMsg("成功禁用一个插件,请刷新导航菜单!","plus_main.php");
exit();
}
@@ -44,17 +44,17 @@ else if($dopost=="delete")
}
else if($job=="yes") //操作
{
$dsql->ExecuteNoneQuery("DELETE FROM #@__plus WHERE aid='$aid';");
$dsql->ExecuteNoneQuery("DELETE FROM `#@__plus` WHERE aid='$aid';");
ShowMsg("成功删除一个插件,请刷新导航菜单!","plus_main.php");
exit();
}
}
else if($dopost=="saveedit") //保存更改
{
$inquery = "UPDATE #@__plus SET plusname='$plusname',menustring='$menustring',filelist='$filelist' WHERE aid='$aid';";
$inquery = "UPDATE `#@__plus` SET plusname='$plusname',menustring='$menustring',filelist='$filelist' WHERE aid='$aid';";
$dsql->ExecuteNoneQuery($inquery);
ShowMsg("成功更改插件的配置!","plus_main.php");
exit();
}
$row = $dsql->GetOne("SELECT * FROM #@__plus WHERE aid='$aid'");
$row = $dsql->GetOne("SELECT * FROM `#@__plus` WHERE aid='$aid'");
include DedeInclude('templets/plus_edit.htm');

+ 1
- 1
src/dede/plus_main.php View File

@@ -13,7 +13,7 @@ CheckPurview('sys_plus');
require_once(DEDEINC."/datalistcp.class.php");
setcookie("ENV_GOBACK_URL",$dedeNowurl,time()+3600,"/");
$sql = "SELECT aid,plusname,writer,isshow FROM #@__plus ORDER BY aid ASC";
$sql = "SELECT aid,plusname,writer,isshow FROM `#@__plus` ORDER BY aid ASC";
$dlist = new DataListCP();
$dlist->SetTemplet(DEDEADMIN."/templets/plus_main.htm");
$dlist->SetSource($sql);


+ 1
- 1
src/dede/recycling.php View File

@@ -22,7 +22,7 @@ if($cid!=0)
$whereSql = " AND arc.typeid IN (".GetSonIds($cid).")";
}
$query = "SELECT arc.*,tp.typename FROM `#@__archives` AS arc
LEFT JOIN #@__arctype AS tp ON arc.typeid = tp.id
LEFT JOIN `#@__arctype` AS tp ON arc.typeid = tp.id
WHERE arc.arcrank = '-2' $whereSql order by arc.id desc";
$dlist = new DataListCP();
$dlist->SetTemplet(DEDEADMIN."/templets/recycling.htm");


+ 1
- 1
src/dede/search_keywords_main.php View File

@@ -84,7 +84,7 @@ function GetKeywordList($dsql,$pageno,$pagesize,$orderby='aid')
echo $printhead;
if($orderby=='result') $orderby = $orderby." ASC";
else $orderby = $orderby." DESC";
$dsql->SetQuery("SELECT * FROM #@__search_keywords ORDER BY $orderby LIMIT $start,$pagesize ");
$dsql->SetQuery("SELECT * FROM `#@__search_keywords` ORDER BY $orderby LIMIT $start,$pagesize ");
$dsql->Execute();
while($row = $dsql->GetArray())
{


+ 8
- 8
src/dede/shops_delivery.php View File

@@ -26,7 +26,7 @@ if($do=='add')
$price = '0.00';
}
$des = cn_substrR($des,255);
$InQuery = "INSERT INTO #@__shops_delivery(`dname`,`price`,`des`) VALUES ('$dname','$price','$des');";
$InQuery = "INSERT INTO `#@__shops_delivery`(`dname`,`price`,`des`) VALUES ('$dname','$price','$des');";
$result = $dsql->ExecuteNoneQuery($InQuery);
if($result)
{
@@ -40,7 +40,7 @@ if($do=='add')
} else if ($do == 'del')
{
$id = intval($id);
$dsql->ExecuteNoneQuery("DELETE FROM #@__shops_delivery WHERE pid='$id'");
$dsql->ExecuteNoneQuery("DELETE FROM `#@__shops_delivery` WHERE pid='$id'");
ShowMsg("已删除当前配送方式!","shops_delivery.php");
exit();
} else if ($do == 'edit')
@@ -48,7 +48,7 @@ if($do=='add')
foreach($pid as $id)
{
$id = intval($id);
$row = $dsql->GetOne("SELECT pid,dname,price,des FROM #@__shops_delivery WHERE pid='$id' LIMIT 0,1");
$row = $dsql->GetOne("SELECT pid,dname,price,des FROM `#@__shops_delivery` WHERE pid='$id' LIMIT 0,1");
if(!is_array($row))
{
continue;
@@ -73,22 +73,22 @@ if($do=='add')
{
$des = cn_substrR($des,255);
}
$dsql->ExecuteNoneQuery("UPDATE #@__shops_delivery SET dname='$dname',price='$price',des='$des' WHERE pid='$id'");
$dsql->ExecuteNoneQuery("UPDATE `#@__shops_delivery` SET dname='$dname',price='$price',des='$des' WHERE pid='$id'");
}
ShowMsg("成功修改配送方式!","shops_delivery.php");
exit();
}
$deliveryarr = array();
$dsql->SetQuery("SELECT pid,dname,price,des FROM #@__shops_delivery ORDER BY orders ASC");
$dsql->SetQuery("SELECT pid,dname,price,des FROM `#@__shops_delivery` ORDER BY orders ASC");
$dsql->Execute();
while($row = $dsql->GetArray())
{
$deliveryarr[] = $row;
}
$dlist = new DataListCP();
$dlist->pageSize = 25; //设定每页显示记录数(默认25条)
$dlist->pageSize = 25; //设定每页显示记录数(默认25条)
//这两句的顺序不能更换
$dlist->SetTemplate(DEDEADMIN."/templets/shops_delivery.htm"); //载入模板
$dlist->SetSource("SELECT `pid`,`dname`,`price`,`des` FROM #@__shops_delivery ORDER BY `orders` ASC"); //设定查询SQL
$dlist->Display(); //显示
$dlist->SetSource("SELECT `pid`,`dname`,`price`,`des` FROM `#@__shops_delivery` ORDER BY `orders` ASC"); // 设定查询SQL
$dlist->Display(); //显示

+ 6
- 6
src/dede/shops_operations.php View File

@@ -24,7 +24,7 @@ if(isset($dopost))
if($wh=='') $wh = " WHERE oid='$n' ";
else $wh .= " OR oid='$n' ";
}
$sql="UPDATE #@__shops_orders SET `state`='1' $wh ";
$sql="UPDATE `#@__shops_orders` SET `state`='1' $wh ";
$dsql->ExecuteNoneQuery($sql);
}
else if ($dopost == 'push')
@@ -36,7 +36,7 @@ if(isset($dopost))
if($wh=='') $wh = " WHERE oid='$n' ";
else $wh .= " OR oid='$n' ";
}
$sql="UPDATE #@__shops_orders SET `state`='2' $wh ";
$sql="UPDATE `#@__shops_orders` SET `state`='2' $wh ";
$dsql->ExecuteNoneQuery($sql);
}
else if ($dopost == 'ok')
@@ -48,7 +48,7 @@ if(isset($dopost))
if($wh=='') $wh = " WHERE oid='$n' ";
else $wh .= " OR oid='$n' ";
}
$sql="UPDATE #@__shops_orders SET `state`='4' $wh ";
$sql="UPDATE `#@__shops_orders` SET `state`='4' $wh ";
$dsql->ExecuteNoneQuery($sql);
}
else if ($dopost == 'delete')
@@ -87,7 +87,7 @@ if(isset($sta))
{
$addsql = "WHERE s.`state`='$sta'";
}
$sql = "SELECT s.`oid`,s.`cartcount`,s.`price`,s.`state`,s.`stime`,s.priceCount,s.dprice,s.paytype,u.`consignee`,u.`tel`,s.`userid` FROM #@__shops_orders AS s LEFT JOIN #@__shops_userinfo AS u ON s.oid=u.oid $addsql ORDER BY `stime` DESC";
$sql = "SELECT s.`oid`,s.`cartcount`,s.`price`,s.`state`,s.`stime`,s.priceCount,s.dprice,s.paytype,u.`consignee`,u.`tel`,s.`userid` FROM `#@__shops_orders` AS s LEFT JOIN `#@__shops_userinfo` AS u ON s.oid=u.oid $addsql ORDER BY `stime` DESC";
$dlist = new DataListCP();
$dlist->SetParameter("oid",$oid);
@@ -127,7 +127,7 @@ function GetsType($pid)
{
global $dsql;
$pid = intval($pid);
$row = $dsql->GetOne("SELECT name FROM #@__payment WHERE id='$pid'");
$row = $dsql->GetOne("SELECT name FROM `#@__payment` WHERE id='$pid'");
if(is_array($row))
{
return $row['name'];
@@ -142,7 +142,7 @@ function GetMemberID($mid)
{
global $dsql;
if($mid==0) return '0';
$row = $dsql->GetOne("SELECT userid FROM #@__member WHERE mid='$mid' ");
$row = $dsql->GetOne("SELECT userid FROM `#@__member` WHERE mid='$mid' ");
if(is_array($row))
{
return "<a href='member_view.php?id={$mid}'>".$row['userid']."</a>";


+ 4
- 4
src/dede/shops_operations_cart.php View File

@@ -16,8 +16,8 @@ if(!isset($oid)) exit("<a href='javascript:window.close()'>无效操作!</a>");
$oid = preg_replace("#[^-0-9A-Z]#", "", $oid);
if(empty($oid)) exit("<a href='javascript:window.close()'>无效订单号!</a>");
$row = $dsql->GetOne("SELECT * FROM #@__shops_userinfo WHERE oid='$oid'");
$sql="SELECT o.*,p.title,p.price as uprice,d.dname FROM #@__shops_orders as o left join #@__shops_products as p on o.oid=p.oid left join #@__shops_delivery as d on d.pid=o.pid WHERE o.oid='$oid'";
$row = $dsql->GetOne("SELECT * FROM `#@__shops_userinfo` WHERE oid='$oid'");
$sql="SELECT o.*,p.title,p.price as uprice,d.dname FROM `#@__shops_orders` as o left join `#@__shops_products` as p on o.oid=p.oid left join `#@__shops_delivery` as d on d.pid=o.pid WHERE o.oid='$oid'";
$dlist = new DataListCP();
$dlist->pageSize = 20;
@@ -30,8 +30,8 @@ $dlist->Close();
function GetSta($sta,$oid)
{
global $dsql;
$row = $dsql->GetOne("SELECT paytype FROM #@__shops_orders WHERE oid='$oid'");
$payname = $dsql->GetOne("SELECT name,fee FROM #@__payment WHERE id='{$row['paytype']}'");
$row = $dsql->GetOne("SELECT paytype FROM `#@__shops_orders` WHERE oid='$oid'");
$payname = $dsql->GetOne("SELECT name,fee FROM `#@__payment` WHERE id='{$row['paytype']}'");
if($sta==0)
{
return $payname['name']." 手续费:".$payname['fee']."元";


+ 3
- 3
src/dede/shops_operations_userinfo.php View File

@@ -14,16 +14,16 @@ if(!isset($oid)) exit("<a href='javascript:window.close()'>无效操作!</a>");
$oid = preg_replace("#[^-0-9A-Z]#", "", $oid);
if(empty($oid)) exit("<a href='javascript:window.close()'>无效订单号!</a>");
$rows = $dsql->GetOne("SELECT * FROM #@__shops_userinfo WHERE oid='$oid' LIMIT 0,1");
$rows = $dsql->GetOne("SELECT * FROM `#@__shops_userinfo` WHERE oid='$oid' LIMIT 0,1");
if(!is_array($rows)){
$dsql->Close();
exit("<a href='javascript:window.close()'>该订单下没相关用户信息!</a>");
}
$row = $dsql->GetOne("SELECT pid,dprice FROM #@__shops_orders WHERE oid='$oid'");
$row = $dsql->GetOne("SELECT pid,dprice FROM `#@__shops_orders` WHERE oid='$oid'");
if(is_array($row))
{
$rs = $dsql->GetOne("SELECT dname FROM #@__shops_delivery WHERE pid='$row[pid]'");
$rs = $dsql->GetOne("SELECT dname FROM `#@__shops_delivery` WHERE pid='$row[pid]'");
$rows['dname'] = $rs['dname'];
$rows['dprice'] = $row['dprice'];
}


+ 91
- 90
src/dede/sys_safetest.php View File

@@ -1,4 +1,5 @@
<?php
/**
* 安全检测
*
@@ -8,130 +9,130 @@
* @license https://www.dedebiz.com/license
* @link https://www.dedebiz.com
*/
require_once(dirname(__FILE__).'/config.php');
require_once(dirname(__FILE__) . '/config.php');
CheckPurview('sys_Edit');
if(empty($action)) $action = '';
if(empty($message)) $message = '尚未进行检测……';
if(empty($filetype)) $filetype = 'php|inc';
if(empty($info)) $info = 'eval|cmd|_GET|_POST';
$safefile = "data/common.inc.php
index.php
dede/config.php
dede/index_body.php
dede/member_do.php
dede/sys_info_pay.php
dede/mychannel_main.php
group/postform.php
group/reply.php
include/common.inc.php
include/mail.class.php
include/Lurd.class.php
include/payment/alipay.php
include/payment/bank.php
include/payment/cod.php
include/payment/yeepay.php
include/helpers/debug.helper.php
include/request.class.php
include/dedecollection.class.php
include/dedetag.class.php
include/dialog/config.php
include/taglib/php.lib.php
include/FCKeditor/fckeditor.php
include/smtp.class.php
include/zip.class.php
install/common.inc.php
include/json.class.php
include/sphinxclient.class.php
plus/bshare.php
install/index.php";
$adminDir = preg_replace("#(.*)[\/\\\\]#", "", dirname(__FILE__));
$safefile = trim(str_replace('dede/',$adminDir.'/',$safefile));
$safefiles = preg_split("#[\r\n]{1,}#", $safefile);
if (empty($action)) $action = '';
if (empty($message)) $message = '尚未进行检测……';
if (empty($filetype)) $filetype = 'php|inc';
if (empty($info)) $info = 'eval|cmd|system|exec|_GET|_POST|_REQUEST|base64_decode';
$fileHashURL = "https://cdn.dedebiz.com/release/{$cfg_version_detail}.json";
$del = new DedeHttpDown();
$del->OpenUrl($fileHashURL);
$filelist = $del->GetJSON();
$offFiles = array();
foreach ($filelist as $key => $ff) {
$offFiles[$ff->filename] = $ff->hash;
}
$alter = "";
if (count($offFiles) == 0) {
$alter = <<<EOT
<div class="alert alert-danger maintable mb-2" style="margin:0 auto;" role="alert">
无法同官方网站文件服务器通信,校验时候无法保证本地文件是否同官方服务器文件是否一致。
</div>
EOT;;
}
function TestOneFile($f)
{
global $message, $info;
global $message, $info,$offFiles;
$str = '';
//排除safefile和data/tplcache目录
if(NotCheckFile($f) || preg_match("#data/tplcache|.svn#", $f)) return -1;
if (preg_match("#data/tplcache|.svn|data/cache#", $f)) return -1;
$fp = fopen($f, 'r');
while(!feof($fp)) { $str .= fgets($fp,1024); }
while (!feof($fp)) {
$str .= fgets($fp, 1024);
}
fclose($fp);
if(preg_match("#(".$info.")[ \r\n\t]{0,}([\[\(])#i", $str))
{
$trfile = preg_replace("#^".DEDEROOT."#", '', $f);
$message .= "<div style='clear:both;border-bottom:1px dotted #B8E6A2;line-height:24px'>
if (preg_match("#(" . $info . ")[ \r\n\t]{0,}([\[\(])#i", $str)) {
$trfile = preg_replace("#^" . DEDEROOT . "#", '', $f );
$oldTrfile = $trfile;
$trfile = substr(str_replace("/","\\",$trfile) ,1);
$localFilehash = md5_file($f);
$remoteFilehash = isset($offFiles[$trfile])? $offFiles[$trfile] : '';
if ($localFilehash === $remoteFilehash) {
return 0;
}
$message .= "<div style='clear:both;'>
<div style='width:350px;float:left'>可疑文件:{$trfile}</div>
<div style='float:left'>[<a href='file_manage_view.php?fmdo=del&filename=$trfile&activepath=' target='_blank'><u>删除</u></a>]
[<a href='file_manage_view.php?fmdo=edit&filename=$trfile&activepath=' target='_blank'><u>查看源码</u></a>]
</div></div>\r\n";
<a class='btn btn-secondary btn-sm' href='sys_safetest.php?action=viewdiff&filename=$oldTrfile' target='_blank'>更改记录</a>
<a class='btn btn-secondary btn-sm' href='file_manage_view.php?fmdo=del&filename=$oldTrfile&activepath=' target='_blank'>删除</a>
<a class='btn btn-secondary btn-sm' href='file_manage_view.php?fmdo=edit&filename=$oldTrfile&activepath=' target='_blank'>查看源码</a>
</div></div><hr>\r\n";
return 1;
}
return 0;
}
function NotCheckFile($f)
{
global $safefiles, $safefile;
if($safefile != '')
{
foreach($safefiles as $v)
{
//if(empty($v)) continue;
if( preg_match("#".$v."#i", $f) ) return TRUE;
}
}
return false;
}
function TestSafe($tdir)
{
global $filetype;
$dh = dir($tdir);
while($fname=$dh->read())
{
$fnamef = $tdir.'/'.$fname;
if(@is_dir($fnamef) && $fname != '.' && $fname != '..')
{
while ($fname = $dh->read()) {
$fnamef = $tdir . '/' . $fname;
if (@is_dir($fnamef) && $fname != '.' && $fname != '..') {
TestSafe($fnamef);
}
if(preg_match("#\.(" . $filetype . ")#i", $fnamef))
{
if (preg_match("#\.(" . $filetype . ")#i", $fnamef)) {
TestOneFile($fnamef);
}
}
}
//检测
if($action=='test')
{
$message = '';
AjaxHead();
TestSafe(DEDEROOT);
if($message=='') $message = "<font color='green' style='font-size:14px'>没发现可疑文件!</font>";
echo $message;
exit();
if ($action == 'test') {
$message = '<link rel="stylesheet" href="../static/css/bootstrap.min.css"><link href="../static/font-awesome/css/font-awesome.min.css" rel="stylesheet">';
AjaxHead();
TestSafe(DEDEROOT);
if ($message == '') $message = "<font color='green' style='font-size:14px'>没发现可疑文件!</font>";
echo $message;
exit();
}
else if($action =='viewdiff'){
$filename = isset($filename)? $filename : "";
if (empty($filename)) {
ShowMsg("没有选择对应的文件", "-1");
exit;
}
$baseFile = "https://cdn.dedebiz.com/release/{$cfg_version_detail}$filename";
$del = new DedeHttpDown();
$del->OpenUrl($baseFile);
$base = $del->GetHTML();
$file = "$cfg_basedir/$filename";
$new = "";
if(is_file($file))
{
$fp = fopen($file,"r");
$new = fread($fp,filesize($file));
fclose($fp);
}
include(dirname(__FILE__) . '/templets/sys_safetest_viewdiff.htm');
exit();
}
//清空模板缓存
else if($action=='clear')
{
else if ($action == 'clear') {
global $cfg_tplcache_dir;
$message = '';
$d = DEDEROOT.$cfg_tplcache_dir;
$d = DEDEROOT . $cfg_tplcache_dir;
AjaxHead();
sleep(1);
if(preg_match("#data\/#", $cfg_tplcache_dir) && file_exists($d) && is_dir($d))
{
if (preg_match("#data\/#", $cfg_tplcache_dir) && file_exists($d) && is_dir($d)) {
$dh = dir($d);
while($filename = $dh->read())
{
if($filename=='.'||$filename=='..'||$filename=='index.html') continue;
@unlink($d.'/'.$filename);
while ($filename = $dh->read()) {
if ($filename == '.' || $filename == '..' || $filename == 'index.html') continue;
@unlink($d . '/' . $filename);
}
}
$message = "<font color='green' style='font-size:14px'>成功清空模板缓存!</font>";
@@ -139,4 +140,4 @@ else if($action=='clear')
exit();
}
include(dirname(__FILE__).'/templets/sys_safetest.htm');
include(dirname(__FILE__) . '/templets/sys_safetest.htm');

+ 0
- 470
src/dede/sys_verifies.php View File

@@ -1,470 +0,0 @@
<?php
/**
* 系统文件校验
*
* @version $Id: sys_verifies.php 1 23:07 2010年7月20日Z tianya $
* @package DedeCMS.Administrator
* @copyright Copyright (c) 2020, DedeBIZ.COM
* @license https://www.dedebiz.com/license
* @link https://www.dedebiz.com
*/
require_once(dirname(__FILE__)."/config.php");
CheckPurview('sys_Edit');
@set_time_limit(0);
require(DEDEINC.'/dedehttpdown.class.php');
$action = isset($action) ? trim($action) : '';
//当前软件版本锁定文件
$verLockFile = DEDEDATA.'/admin/ver.txt';
//当前软件指纹码锁定文件
$verifiesLockFile = DEDEDATA.'/admin/verifies.txt';
$fp = fopen($verLockFile,'r');
$upTime = trim(fread($fp,64));
fclose($fp);
$updateTime = substr($upTime,0,4).'-'.substr($upTime,4,2).'-'.substr($upTime,6,2);
$verifiesTime = "未同步过指纹码";
if(file_exists($verifiesLockFile))
{
$fp = fopen($verifiesLockFile,'r');
$upTime = trim(fread($fp,64));
fclose($fp);
$verifiesTime = substr($upTime,0,4).'-'.substr($upTime,4,2).'-'.substr($upTime,6,2);
}
$tmpdir = substr(md5($cfg_cookie_encode),0,16);
//重定义file_get_contents来兼容不支持此函数的PHP
//因为有个别地方用fgets读文件生成校验码不兼容
if(!function_exists('file_get_contents'))
{
function file_get_contents($fname)
{
if(!file_exists($fname) || is_dir($fname))
{
return '';
}
else
{
$fp = fopen($fname, 'r');
$ct = fread($fp, filesize($fname));
fclose($fp);
return $ct;
}
}
}
if($action == '')
{
include(DEDEADMIN.'/templets/sys_verifies.htm');
exit();
}
/*----------------
校验文件
function _verify() { }
----------------*/
else if($action == 'verify')
{
$dsql->SetQuery("SELECT * FROM `#@__verifies` ");
$dsql->Execute();
$filelist = array();
while($row = $dsql->GetArray())
{
$turefile = str_replace('../dede', '.', $row['filename']);
//跳过不存在的文件
if(!file_exists($turefile)) {
continue;
}
if( filesize($turefile)==0 ) {
continue;
}
$ct = file_get_contents($turefile);
$ct = preg_replace("/\/\*\*[\r\n]{1,}(.*)[\r\n]{1,} \*\//sU", '', $ct);
$cthash = md5($ct);
if($cthash != $row['cthash'])
{
$row['localhash'] = $cthash;
$row['mtime'] = MyDate('Y-m-d H:i:s', filemtime($turefile));
$row['turefile'] = $turefile;
$filelist[] = $row;
}
}
if(!isset($filelist[0]))
{
ShowMsg("所有文件都通过效验证,核心文件没有被改动过!","sys_verifies.php");
}
else
{
include(DEDEADMIN.'/templets/sys_verifies_verify.htm');
}
exit();
}
/*--------------------
查看单个本地文件
function _view() { }
----------------------*/
else if ($action == 'view')
{
require_once(DEDEINC."/oxwindow.class.php");
$filetxt = '';
if( !preg_match("#data(.*)common.inc.php#i", $filename) )
{
$fp = fopen($filename, 'r');
$filetxt = fread($fp, filesize($filename));
fclose($fp);
}
$filetxt = str_replace('textarea', '!textarea', $filetxt);
$wintitle = "文件效验::查看文件";
$wecome_info = "<a href='sys_verifies.php'><u>文件效验</u></a>::查看文件";
$win = new OxWindow();
$win->Init();
$win->AddTitle("以下为文件 $filename 的内容,请检查是否可疑:");
$winform = $win->GetWindow("hand","<textarea name='filetxt' style='width:100%;height:450px;word-wrap: break-word;word-break:break-all;'>".$filetxt."</textarea>");
$win->Display();
exit();
}
/*-----------------
管理指纹码
function _manage() { }
-------------------*/
else if ($action == 'manage')
{
$dsql->SetQuery("SELECT * FROM `#@__verifies` ");
$dsql->Execute();
$filelist = array();
while($row = $dsql->GetArray())
{
$filelist[] = $row;
}
include(DEDEADMIN.'/templets/sys_verifies_manage.htm');
exit();
}
/*-----------------------
下载文件
function _getfiles()
------------------------*/
else if ($action == 'getfiles')
{
if(!isset($refiles))
{
ShowMsg("你没进行任何操作!","sys_verifies.php");
exit();
}
$cacheFiles = DEDEDATA.'/modifytmp.inc';
$fp = fopen($cacheFiles, 'w');
fwrite($fp, '<'.'?php'."\r\n");
fwrite($fp, '$tmpdir = "'.$tmpdir.'";'."\r\n");
$dirs = array();
$i = -1;
$adminDir = preg_replace("#(.*)[\/\\\\]#", "", dirname(__FILE__));
foreach($refiles as $filename)
{
$filename = substr($filename,3,strlen($filename)-3);
if(preg_match("#^dede/#i", $filename))
{
$curdir = GetDirName( preg_replace("#^dede/#i", $adminDir.'/', $filename) );
} else {
$curdir = GetDirName($filename);
}
if( !isset($dirs[$curdir]) )
{
$dirs[$curdir] = TestIsFileDir($curdir);
}
$i++;
fwrite($fp, '$files['.$i.'] = "'.$filename.'";'."\r\n");
}
fwrite($fp, '$fileConut = '.$i.';'."\r\n");
fwrite($fp, '?'.'>');
fclose($fp);
$dirinfos = '';
if($i > -1)
{
$dirinfos = '<tr bgcolor="#ffffff"><td colspan="2">';
$dirinfos .= "本次升级需要在下面文件夹写入更新文件,请注意文件夹是否有写入权限:<br />\r\n";
foreach($dirs as $curdir)
{
$dirinfos .= $curdir['name']." 状态:".($curdir['writeable'] ? "[√正常]" : "<font color='red'>[×不可写]</font>")."<br />\r\n";
}
$dirinfos .= "</td></tr>\r\n";
}
$doneStr = "<iframe name='stafrm' src='sys_verifies.php?action=down&curfile=0' frameborder='0' id='stafrm' width='100%' height='100%'></iframe>\r\n";
include(DEDEADMIN.'/templets/sys_verifies_getfiles.htm');
exit();
}
/*-----------------------
下载文件
function _down()
------------------------*/
else if($action=='down')
{
$cacheFiles = DEDEDATA.'/modifytmp.inc';
require_once($cacheFiles);
if($fileConut==-1 || $curfile > $fileConut)
{
ShowMsg("已下载所有文件<br /><a href='sys_verifies.php?action=apply'>[直接替换文件]</a> &nbsp; <a href='#'>[我自己手动替换文件]</a>","javascript:;");
exit();
}
//检查临时文件保存目录是否可用
MkTmpDir($tmpdir, $files[$curfile]);
$downfile = UPDATEHOST.$cfg_soft_lang.'/source/'.$files[$curfile];
$dhd = new DedeHttpDown();
$dhd->OpenUrl($downfile);
$dhd->SaveToBin(DEDEDATA.'/'.$tmpdir.'/'.$files[$curfile]);
$dhd->Close();
ShowMsg("成功下载文件:{$files[$curfile]}; 继续下载下一个文件。","sys_verifies.php?action=down&curfile=".($curfile+1));
exit();
}
/*-----------------------
修改效验方式
function _modify()
------------------------*/
else if($action=='modify')
{
if(!isset($modifys))
{
ShowMsg("没选定要修改的文件!","-1");
exit();
}
else
{
foreach($modifys as $fname)
{
if($method=='local')
{
$tureFilename = str_replace('../dede','./',$fname);
if(file_exists($tureFilename))
{
$fp = fopen($tureFilename,'r');
$ct = fread($fp,filesize($tureFilename));
fclose($fp);
$cthash = md5($ct);
$dsql->ExecuteNoneQuery("UPDATE `#@__verifies` SET `method`='local',cthash='$cthash' WHERE filename='$fname' ");
}
}
else
{
$dsql->ExecuteNoneQuery("UPDATE `#@__verifies` SET `method`='offical' WHERE filename='$fname' ");
}
}
}
if($method=='local')
{
ShowMsg("成功修改指定文件的验证方式!","sys_verifies.php?action=manage");
}
else
{
ShowMsg("成功修改指定文件的验证方式!<br /> 由于你修改了文件为远程验证方式,因此需进行更新操作<br /> <a href='sys_verifies.php?action=update'>[更新]</a> &nbsp; <a href='sys_verifies.php?action=manage'>[返回]</a>","javascript:;");
}
exit();
}
/*-----------------------
还原文件
function _applyRecover()
------------------------*/
else if ($action == 'apply')
{
$cacheFiles = DEDEDATA.'/modifytmp.inc';
require_once($cacheFiles);
$sDir = DEDEDATA."/$tmpdir";
$tDir = DEDEROOT;
$badcp = 0;
$adminDir = preg_replace("#(.*)[\/\\\\]#", "", dirname(__FILE__));
if(isset($files) && is_array($files))
{
foreach($files as $f)
{
if(preg_match("#^dede#", $f)) $tf = preg_replace("#^dede#", $adminDir, $f);
else $tf = $f;
if(file_exists($sDir.'/'.$f))
{
//还原文件前先进行文件效验
$ct = file_get_contents($sDir.'/'.$f);
$ct = preg_replace("/\/\*\*[\r\n]{1,}(.*)[\r\n]{1,} \*\//sU", '', $ct);
$newhash = md5($ct);
$row = $dsql->GetOne("SELECT * FROM `#@__verifies` WHERE filename='../{$f}' ");
if(is_array($row) && $row['cthash'] != $newhash)
{
$badcp++;
} else {
$rs = @copy($sDir.'/'.$f, $tDir.'/'.$tf);
if($rs) unlink($sDir.'/'.$f);
else $badcp++;
}
}
}
}
$badmsg = '!';
if($badcp > 0)
{
$badmsg = ",其 {$badcp} 个文件效验码不正确或复制失败,<br />请从临时目录[../data/{$tmpdir}]中取出这几个文件手动还原。";
}
ShowMsg("成功完成还原指定文件{$badmsg}", "javascript:;");
exit();
}
/*---------------
在线更新指纹码
function _update()
-----------------*/
else if($action == 'update')
{
$rmFile = UPDATEHOST.$cfg_soft_lang.'/verifys.txt';
$dhd = new DedeHttpDown();
$dhd->OpenUrl($rmFile);
$ct = $dhd->GetHtml();
$dhd->Close();
$cts = split("[\r\n]{1,}",$ct);
foreach($cts as $ct)
{
$ct = trim($ct);
if(empty($ct)) continue;
list($nameid, $cthash, $fname) = explode("\t", $ct);
$row = $dsql->GetOne("SELECT * FROM `#@__verifies` WHERE nameid='$nameid' ");
if(!is_array($row) || ($row['method']=='official' && $row['cthash']!=$cthash ))
{
$dsql->ExecuteNoneQuery("REPLACE INTO `#@__verifies`(nameid,cthash,method,filename) VALUES ('$nameid','$cthash','official','$fname'); ");
}
}
$fp = fopen($verifiesLockFile,'w');
fwrite($fp, MyDate('Ymd',time()));
fclose($fp);
ShowMsg("完成效验码更新,是否马上进行效验操作?<br /> <a href='sys_verifies.php?action=verify'>[开始效验]</a> &nbsp; <a href='sys_verifies.php?action=manage'>[管理]</a> &nbsp; <a href='sys_verifies.php'>[返回]</a>","javascript:;");
exit();
}
/*-----------------
生成指纹码
function _make() { }
-------------------*/
else if ($action == 'make')
{
$fp = fopen(DEDEROOT.'/../verifys.txt','w');
foreach (preg_ls ('../', TRUE, "/.*\.(php|htm|html|js)$/i", 'CVS,data,html,uploads,templets,special') as $onefile)
{
$nameid = md5($onefile);
$ctbody = file_get_contents(DEDEADMIN.'/'.$onefile);
$ctbody = preg_replace("/\/\*\*[\r\n]{1,}(.*)[\r\n]{1,} \*\//sU", '', $ctbody);
$cthash = md5($ctbody);
fwrite($fp,"{$nameid}\t{$cthash}\t{$onefile}\r\n");
}
fclose($fp);
ShowMsg("操作成功!","sys_verifies.php");
exit();
}
//获取所有文件列表
function preg_ls($path=".", $rec=FALSE, $pat="/.*/", $ignoredir='')
{
while (substr ($path,-1,1) =="/")
{
$path=substr ($path,0,-1);
}
if (!is_dir ($path) )
{
$path=dirname ($path);
}
if ($rec!==TRUE)
{
$rec=FALSE;
}
$d=dir ($path);
$ret=Array ();
while (FALSE!== ($e=$d->read () ) )
{
if ( ($e==".") || ($e=="..") )
{
continue;
}
if ($rec && is_dir ($path."/".$e) && ($ignoredir == '' || strpos($ignoredir,$e ) === FALSE))
{
$ret = array_merge ($ret, preg_ls($path."/".$e, $rec, $pat, $ignoredir));
continue;
}
if (!preg_match ($pat, $e) )
{
continue;
}
$ret[] = $path."/".$e;
}
return (empty ($ret) && preg_match ($pat,basename($path))) ? Array ($path."/") : $ret;
}
function TestWriteAble($d)
{
$tfile = '_dedet.txt';
$fp = @fopen($d.$tfile, 'w');
if(!$fp)
{
return FALSE;
}
else {
fclose($fp);
$rs = @unlink($d.'/'.$tfile);
return TRUE;
}
}
function GetDirName($filename)
{
$dirname = '../'.preg_replace("#[\\\\\/]{1,}#", '/', $filename);
$dirname = preg_replace("#([^\/]*)$#", '', $dirname);
return $dirname;
}
function TestIsFileDir($dirname)
{
$dirs = array('name'=>'','isdir'=>FALSE,'writeable'=>FALSE);
$dirs['name'] = $dirname;
if(is_dir($dirname))
{
$dirs['isdir'] = TRUE;
$dirs['writeable'] = TestWriteAble($dirname);
}
return $dirs;
}
function MkTmpDir($tmpdir,$filename)
{
$basedir = DEDEDATA.'/'.$tmpdir;
$dirname = trim(preg_replace("#[\\\\\/]{1,}#", '/', $filename));
$dirname = preg_replace("#([^\/]*)$#", "", $dirname);
if(!is_dir($basedir))
{
mkdir($basedir, 0777);
}
if($dirname=='')
{
return TRUE;
}
$dirs = explode('/', $dirname);
$curdir = $basedir;
foreach($dirs as $d)
{
$d = trim($d);
if(empty($d)) continue;
$curdir = $curdir.'/'.$d;
if(!is_dir($curdir))
{
mkdir($curdir,0777) or die($curdir);
}
}
return TRUE;
}

+ 4
- 3
src/dede/templets/sys_safetest.htm View File

@@ -5,8 +5,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $cfg_soft_lang; ?>">
<title>木马自检程序</title>
<link rel="stylesheet" href="../static/css/bootstrap.min.css">
<link href="../static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="../static/css/bootstrap.min.css">
<link href="../static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" type="text/css" href="css/indexbody.css" />
<style type="text/css">
@@ -48,6 +48,7 @@
<div class="bodytitleleft"></div>
<div class="bodytitletxt" style="padding-left:10px;">用户安全中心</div>
</div>
<?php echo $alter;?>
<table width="98%" border="0" cellpadding="1" cellspacing="1" align="center" class="table maintable"
style="background:#CFCFCF;">
<tr>
@@ -70,7 +71,7 @@
<input name="filetype" type="text" id="filetype" value="php|inc" style="width:420px" />
&nbsp;要检查的文件类型</p>
<p>代码特征:
<input name="info" type="text" id="info" value="eval|cmd|system|exec|_GET|_POST" style="width:420px" />
<input name="info" type="text" id="info" value="eval|cmd|system|exec|_GET|_POST|_REQUEST|base64_decode" style="width:420px" />
&nbsp;特征代码</p>
</td>
</tr>


+ 95
- 0
src/dede/templets/sys_safetest_viewdiff.htm View File

@@ -0,0 +1,95 @@
<!doctype html>
<html>

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<title>查看差异</title>
<link rel="stylesheet" type="text/css" href="../static/css/diffview.css" />
<script type="text/javascript" src="../static/js/jquery.js"></script>
<script type="text/javascript" src="../static/js/diffview.js"></script>
<script type="text/javascript" src="../static/js/difflib.js"></script>
<style type="text/css">
body {
font-size: 12px;
font-family: Sans-Serif;
}

h2 {
margin: 0.5em 0 0.1em;
text-align: center;
}

.top {
text-align: center;
}

.textInput {
display: block;
width: 49%;
float: left;
}

textarea {
width: 100%;
height: 300px;
}

label:hover {
text-decoration: underline;
cursor: pointer;
}

.spacer {
margin-left: 10px;
}

.viewType {
font-size: 16px;
clear: both;
text-align: center;
padding: 1em;
}

#diffoutput {
width: 100%;
}
</style>

<script type="text/javascript">

function diffUsingJS(viewType) {
"use strict";
var base = difflib.stringAsLines($("#baseText").val()),
newtxt = difflib.stringAsLines($("#newText").val()),
sm = new difflib.SequenceMatcher(base, newtxt),
opcodes = sm.get_opcodes(),
diffoutputdiv = $("#diffoutput");

diffoutputdiv.html("")

diffoutputdiv.html(diffview.buildView({
baseTextLines: base,
newTextLines: newtxt,
opcodes: opcodes,
baseTextName: "官方服务器文件",
newTextName: "本地文件",
viewType: 0
}));
}

</script>
</head>

<body>
<textarea id="baseText" style="display: none;"><?php echo $base ;?></textarea>
<textarea id="newText" style="display: none;"><?php echo $new ;?></textarea>
<div id="diffoutput"> </div>
<script>
$(document).ready(function () {
diffUsingJS(1);
});
</script>
</body>

</html>

+ 0
- 78
src/dede/templets/sys_verifies.htm View File

@@ -1,78 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $cfg_soft_lang; ?>">
<title>文件校验</title>
<link href='css/base.css' rel='stylesheet' type='text/css' />
<link rel="stylesheet" type="text/css" href="css/indexbody.css" />
<script language='javascript'>
function Loading(surl)
{
document.getElementById('loaddiv').style.display = 'block';
location = surl;
}
</script>
</head>
<body background='images/allbg.gif' leftmargin='8' topmargin='8'>
<div id='loaddiv' style='display:none'>
<p align='center' style='padding-top:200px'><img src='images/loadinglit.gif' /> 请稍后,正在处理中...</p>
</div>
<table width="98%" border="0" align="center" cellpadding="3" cellspacing="1" bgcolor="#D6D6D6">
<tr>
<td height="19" background="images/tbg.gif">
<table width="96%" border="0" cellspacing="1" cellpadding="1">
<tr>
<td width="24%"><strong>文件校验操作:</strong></td>
<td width="76%" align="right">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="200" bgcolor="#FFFFFF" valign="top">
<table width="100%" border="0" cellspacing="4" cellpadding="2">
<tr>
<td height="53" align="center">&nbsp;</td>
<td>
您的系统最后升级时间:<b><?php echo $updateTime; ?></b>;指纹码最后同步时间:<b><?php echo $verifiesTime; ?></b>
<br />
第一次效验文件时或您的系统已经升级过,请先点击“在线获取最新指纹码”
<br />
(文件校验将检查本站文件是否和DedeCMS原始文件是否完全一致,如果要替换差异文件,必须按提示设置被更改文件的目录有可写入权限)
</td>
<tr>
<td height="53" align="center">&nbsp;</td>
<td>
<div style='width:80%;background:#F9FCEF;border-bottom: 1px dashed #A7BA87;padding:3px;'>&nbsp;<b>效对操作:</b></div>
<div style='padding:10px 0px 20px 0px;'>
<a href="javascript:Loading('sys_verifies.php?action=update');" class='np coolbg'>在线获取最新指纹码==&gt;</a>
&nbsp;
<a href="javascript:Loading('sys_verifies.php?action=verify');" class='np coolbg'>效对本地文件==&gt;</a>
&nbsp;
下载差异文件==&gt;
&nbsp;
替换差异文件==&gt;
</div>
<div style='width:80%;background:#F9FCEF;border-bottom: 1px dashed #A7BA87;padding:3px;'>&nbsp;<b>管理指纹码:</b>(对于您自己修改过的文件,您可以在列表中屏蔽,下次忽略这些文件的效验)</div>
<div style='padding:10px 0px 180px 0px;'>
<a href="javascript:Loading('sys_verifies.php?action=manage');" class='np coolbg'>管理现有的指纹码</a>
</div>
<!--
<div style='width:80%;background:#D9E1CA;border-bottom: 1px dashed #A7BA87;padding:3px;'>&nbsp;<b>生成指纹码:</b></div>
<div style='padding:10px 0px 20px 0px;'>
<a href="javascript:Loading('sys_verifies.php?action=make');" class='np coolbg'>生成指纹码(官方使用)</a>
</div>
-->
<br />
<br />
<br />
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

+ 0
- 56
src/dede/templets/sys_verifies_getfiles.htm View File

@@ -1,56 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $cfg_soft_lang; ?>">
<title>文件效验程序--下载更新文件</title>
<link href="css/base.css" rel="stylesheet" type="text/css">
</head>
<body background='images/allbg.gif' leftmargin='8' topmargin='8'>
<table width="98%" border="0" cellpadding="3" cellspacing="1" bgcolor="#D6D6D6" align="center">
<tr>
<td height="28" colspan="2" background='images/tbg.gif'>
<div style="float:left">
<strong><a href='sys_verifies.php'><b>文件校验操作</b></a> &gt;&gt; 下载差异文件</strong>
</div>
<div style="float:right;padding-right:6px;">
<a href='index_body.php' class='np coolbg'>返回系统主页</a>
</div>
</td>
</tr>
<tr bgcolor="#ffffff">
<td height="20" colspan="2">
下载的文件临时存放在文件夹(<font color='red'>../data/<?php echo $tmpdir; ?></font>)内,如果某些基础类有重要的改动导致更新中途中错,您可以从这文件夹提取文件手工更新。
</td>
</tr>
<?php echo $dirinfos; ?>
<tr bgcolor="#F8FEDA">
<td height="20" colspan="2">
<table width="100%">
<tr>
<td width="74%">进行状态: </td>
<td width="26%" align="right">
<script language='javascript'>
function ResizeDiv(obj,ty)
{
if(ty=="+") document.all[obj].style.pixelHeight += 50;
else if(document.all[obj].style.pixelHeight>80) document.all[obj].style.pixelHeight = document.all[obj].style.pixelHeight - 50;
}
</script>
[<a href='#' onClick="ResizeDiv('mdv','+');">增大</a>] [<a href='#' onClick="ResizeDiv('mdv','-');">缩小</a>]
</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" id="mtd">
<div id='mdv' style='width:100%;height:350px;'>
<?php
echo $doneStr;
?>
</div>
</td>
</tr>
</table>
</body>
</html>

+ 0
- 74
src/dede/templets/sys_verifies_manage.htm View File

@@ -1,74 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $cfg_soft_lang; ?>">
<title>文件校验</title>
<link href='css/base.css' rel='stylesheet' type='text/css'>
</head>
<body background='images/allbg.gif' leftmargin='8' topmargin='8'>
<table width="98%" border="0" align="center" cellpadding="3" cellspacing="1" bgcolor="#D6D6D6">
<tr>
<td height="19" background="images/tbg.gif">
<table width="96%" border="0" cellspacing="1" cellpadding="1">
<tr>
<td width="24%">
<strong><a href='sys_verifies.php'><b>文件校验</b></a> &gt;&gt; 文件效验管理</strong>
</td>
<td width="76%" align="right">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="200" bgcolor="#FFFFFF" valign="top">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<form action="sys_verifies.php?action=modify" method="post">
<tr>
<td colspan="4" class='bline2' style="color:red"> &nbsp;说明:这里是系统文件列表,如果本地对某些文件做过修改,但又不希望同官方服务器上面的镜像版本(发布版本)对应文件进行同步,可将文件校验方式修改为&ldquo;本地(local)&rdquo;,以确保不会重新下载文件修复。</td>
</tr>
<tr>
<td class='bline2'> 修改? </td>
<td class='bline2'> 文件名(用 Ctrl+F 搜索) </td>
<td class='bline2'> 文件HASH </td>
<td class='bline2'> 校验方式 </td>
</tr>
<?php
foreach ($filelist as $key => $file)
{
?>
<tr>
<td class='bline'>
<input type="checkbox" name="modifys[]" value="<?php echo $file['filename'];?>" />
</td>
<td class='bline'>
<?php echo $file['filename'];?>
</td>
<td class='bline'>
<?php echo $file['cthash'];?>
</td>
<td class='bline'>
<?php echo $file['method'];?>
</td>
</tr>
<?php
}
?>
<tr>
<td colspan="20" height='28'>
<label><input type="radio" name="method" value="offical" />官方(official)</label>
<label><input type="radio" name="method" value="local" checked='1' />本地(local)</label>
</td>
</tr>
<tr>
<td colspan="20" height='36'>
<input type="submit" name="submit" value="修改要文件的校验方式" class='np coolbg' />
</td>
</tr>
</form>
</table>
</td>
</tr>
</table>
</body>
</html>

+ 0
- 73
src/dede/templets/sys_verifies_verify.htm View File

@@ -1,73 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $cfg_soft_lang; ?>">
<title>文件校验</title>
<link href='css/base.css' rel='stylesheet' type='text/css'>
</head>
<body background='images/allbg.gif' leftmargin='8' topmargin='8'>
<table width="98%" border="0" align="center" cellpadding="3" cellspacing="1" bgcolor="#D6D6D6">
<tr>
<td height="19" background="images/tbg.gif">
<table width="96%" border="0" cellspacing="1" cellpadding="1">
<tr>
<td width="24%">
<a href='sys_verifies.php'><b>文件效验</b></a>
&gt;&gt;
<strong>校验结果:</strong> 共有 <?php echo count($filelist); ?> 个文件不同
</td>
<td width="76%" align="right">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="200" bgcolor="#FFFFFF" valign="top">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<form action="sys_verifies.php?action=getfiles" method="post">
<tr>
<td class='bline2'> 恢复? </td>
<td class='bline2'> 文件名(Ctrl+F查找) </td>
<td class='bline2'> 校验方式 </td>
<td class='bline2'> 最后修改时间 </td>
<td class='bline2'> 指纹码/点击可浏览文件内容 </td>
</tr>
<?php
foreach ($filelist as $key => $file)
{
?>
<tr>
<td class='bline'>
<input type="checkbox" name="refiles[]" value="<?php echo $file['filename'];?>" checked='1' />
</td>
<td class='bline'>
<?php echo $file['filename']; ?>
</td>
<td class='bline'>
<?php echo $file['method']; ?>
</td>
<td class='bline'>
<?php echo $file['mtime']; ?>
</td>
<td class='bline'>
<a href="sys_verifies.php?action=view&filename=<?php echo $file['turefile']; ?>" target="_blank" class='coolbg' title="标准效验码为: <?php echo $file['cthash']; ?>">
<?php echo $file['localhash']; ?>
</a>
</td>
</tr>
<?php
}
?>
<tr>
<td colspan="20" height='42'>
<input type="submit" name="submit" value="从官方下载选中的文件并恢复" class='np coolbg' />
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</body>
</html>

+ 18
- 0
src/include/dedehttpdown.class.php View File

@@ -283,6 +283,24 @@ class DedeHttpDown
return $this->m_html;
}

function GetJSON()
{
if ($this->m_html != '') {
return json_decode($this->m_html);
}
if (!$this->IsText()) {
return '';
}
if (!$this->m_fp || @feof($this->m_fp)) {
return '';
}
while (!feof($this->m_fp)) {
$this->m_html .= fgets($this->m_fp, 256);
}
@fclose($this->m_fp);
return json_decode($this->m_html);
}

/**
* 开始HTTP会话
*


+ 83
- 0
src/static/css/diffview.css View File

@@ -0,0 +1,83 @@
/*
This is part of jsdifflib v1.0. <http://github.com/cemerick/jsdifflib>

Copyright 2007 - 2011 Chas Emerick <cemerick@snowtide.com>. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.

THIS SOFTWARE IS PROVIDED BY Chas Emerick ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Chas Emerick OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of Chas Emerick.
*/
table.diff {
border-collapse:collapse;
border:1px solid darkgray;
white-space:pre-wrap
}
table.diff tbody {
font-family:Courier, monospace
}
table.diff tbody th {
font-family:verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif;
background:#EED;
font-size:11px;
font-weight:normal;
border:1px solid #BBC;
color:#886;
padding:.3em .5em .1em 2em;
text-align:right;
vertical-align:top
}
table.diff thead {
border-bottom:1px solid #BBC;
background:#EFEFEF;
font-family:Verdana
}
table.diff thead th.texttitle {
text-align:left
}
table.diff tbody td {
padding:0px .4em;
padding-top:.4em;
vertical-align:top;
}
table.diff .empty {
background-color:#DDD;
}
table.diff .replace {
background-color:#FD8
}
table.diff .delete {
background-color:#E99;
}
table.diff .skip {
background-color:#EFEFEF;
border:1px solid #AAA;
border-right:1px solid #BBC;
}
table.diff .insert {
background-color:#9E9
}
table.diff th.author {
text-align:right;
border-top:1px solid #BBC;
background:#EFEFEF
}

+ 411
- 0
src/static/js/difflib.js View File

@@ -0,0 +1,411 @@
/***
This is part of jsdifflib v1.0. <http://snowtide.com/jsdifflib>

Copyright (c) 2007, Snowtide Informatics Systems, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Snowtide Informatics Systems nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
/* Author: Chas Emerick <cemerick@snowtide.com> */
__whitespace = {" ":true, "\t":true, "\n":true, "\f":true, "\r":true};

difflib = {
defaultJunkFunction: function (c) {
return __whitespace.hasOwnProperty(c);
},
stripLinebreaks: function (str) { return str.replace(/^[\n\r]*|[\n\r]*$/g, ""); },
stringAsLines: function (str) {
var lfpos = str.indexOf("\n");
var crpos = str.indexOf("\r");
var linebreak = ((lfpos > -1 && crpos > -1) || crpos < 0) ? "\n" : "\r";
var lines = str.split(linebreak);
for (var i = 0; i < lines.length; i++) {
lines[i] = difflib.stripLinebreaks(lines[i]);
}
return lines;
},
// iteration-based reduce implementation
__reduce: function (func, list, initial) {
if (initial != null) {
var value = initial;
var idx = 0;
} else if (list) {
var value = list[0];
var idx = 1;
} else {
return null;
}
for (; idx < list.length; idx++) {
value = func(value, list[idx]);
}
return value;
},
// comparison function for sorting lists of numeric tuples
__ntuplecomp: function (a, b) {
var mlen = Math.max(a.length, b.length);
for (var i = 0; i < mlen; i++) {
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
return a.length == b.length ? 0 : (a.length < b.length ? -1 : 1);
},
__calculate_ratio: function (matches, length) {
return length ? 2.0 * matches / length : 1.0;
},
// returns a function that returns true if a key passed to the returned function
// is in the dict (js object) provided to this function; replaces being able to
// carry around dict.has_key in python...
__isindict: function (dict) {
return function (key) { return dict.hasOwnProperty(key); };
},
// replacement for python's dict.get function -- need easy default values
__dictget: function (dict, key, defaultValue) {
return dict.hasOwnProperty(key) ? dict[key] : defaultValue;
},
SequenceMatcher: function (a, b, isjunk) {
this.set_seqs = function (a, b) {
this.set_seq1(a);
this.set_seq2(b);
}
this.set_seq1 = function (a) {
if (a == this.a) return;
this.a = a;
this.matching_blocks = this.opcodes = null;
}
this.set_seq2 = function (b) {
if (b == this.b) return;
this.b = b;
this.matching_blocks = this.opcodes = this.fullbcount = null;
this.__chain_b();
}
this.__chain_b = function () {
var b = this.b;
var n = b.length;
var b2j = this.b2j = {};
var populardict = {};
for (var i = 0; i < b.length; i++) {
var elt = b[i];
if (b2j.hasOwnProperty(elt)) {
var indices = b2j[elt];
if (n >= 200 && indices.length * 100 > n) {
populardict[elt] = 1;
delete b2j[elt];
} else {
indices.push(i);
}
} else {
b2j[elt] = [i];
}
}
for (var elt in populardict) {
if (populardict.hasOwnProperty(elt)) {
delete b2j[elt];
}
}
var isjunk = this.isjunk;
var junkdict = {};
if (isjunk) {
for (var elt in populardict) {
if (populardict.hasOwnProperty(elt) && isjunk(elt)) {
junkdict[elt] = 1;
delete populardict[elt];
}
}
for (var elt in b2j) {
if (b2j.hasOwnProperty(elt) && isjunk(elt)) {
junkdict[elt] = 1;
delete b2j[elt];
}
}
}
this.isbjunk = difflib.__isindict(junkdict);
this.isbpopular = difflib.__isindict(populardict);
}
this.find_longest_match = function (alo, ahi, blo, bhi) {
var a = this.a;
var b = this.b;
var b2j = this.b2j;
var isbjunk = this.isbjunk;
var besti = alo;
var bestj = blo;
var bestsize = 0;
var j = null;
var j2len = {};
var nothing = [];
for (var i = alo; i < ahi; i++) {
var newj2len = {};
var jdict = difflib.__dictget(b2j, a[i], nothing);
for (var jkey in jdict) {
if (jdict.hasOwnProperty(jkey)) {
j = jdict[jkey];
if (j < blo) continue;
if (j >= bhi) break;
newj2len[j] = k = difflib.__dictget(j2len, j - 1, 0) + 1;
if (k > bestsize) {
besti = i - k + 1;
bestj = j - k + 1;
bestsize = k;
}
}
}
j2len = newj2len;
}
while (besti > alo && bestj > blo && !isbjunk(b[bestj - 1]) && a[besti - 1] == b[bestj - 1]) {
besti--;
bestj--;
bestsize++;
}
while (besti + bestsize < ahi && bestj + bestsize < bhi &&
!isbjunk(b[bestj + bestsize]) &&
a[besti + bestsize] == b[bestj + bestsize]) {
bestsize++;
}
while (besti > alo && bestj > blo && isbjunk(b[bestj - 1]) && a[besti - 1] == b[bestj - 1]) {
besti--;
bestj--;
bestsize++;
}
while (besti + bestsize < ahi && bestj + bestsize < bhi && isbjunk(b[bestj + bestsize]) &&
a[besti + bestsize] == b[bestj + bestsize]) {
bestsize++;
}
return [besti, bestj, bestsize];
}
this.get_matching_blocks = function () {
if (this.matching_blocks != null) return this.matching_blocks;
var la = this.a.length;
var lb = this.b.length;
var queue = [[0, la, 0, lb]];
var matching_blocks = [];
var alo, ahi, blo, bhi, qi, i, j, k, x;
while (queue.length) {
qi = queue.pop();
alo = qi[0];
ahi = qi[1];
blo = qi[2];
bhi = qi[3];
x = this.find_longest_match(alo, ahi, blo, bhi);
i = x[0];
j = x[1];
k = x[2];
if (k) {
matching_blocks.push(x);
if (alo < i && blo < j)
queue.push([alo, i, blo, j]);
if (i+k < ahi && j+k < bhi)
queue.push([i + k, ahi, j + k, bhi]);
}
}
matching_blocks.sort(difflib.__ntuplecomp);
var i1 = j1 = k1 = block = 0;
var non_adjacent = [];
for (var idx in matching_blocks) {
if (matching_blocks.hasOwnProperty(idx)) {
block = matching_blocks[idx];
i2 = block[0];
j2 = block[1];
k2 = block[2];
if (i1 + k1 == i2 && j1 + k1 == j2) {
k1 += k2;
} else {
if (k1) non_adjacent.push([i1, j1, k1]);
i1 = i2;
j1 = j2;
k1 = k2;
}
}
}
if (k1) non_adjacent.push([i1, j1, k1]);
non_adjacent.push([la, lb, 0]);
this.matching_blocks = non_adjacent;
return this.matching_blocks;
}
this.get_opcodes = function () {
if (this.opcodes != null) return this.opcodes;
var i = 0;
var j = 0;
var answer = [];
this.opcodes = answer;
var block, ai, bj, size, tag;
var blocks = this.get_matching_blocks();
for (var idx in blocks) {
if (blocks.hasOwnProperty(idx)) {
block = blocks[idx];
ai = block[0];
bj = block[1];
size = block[2];
tag = '';
if (i < ai && j < bj) {
tag = 'replace';
} else if (i < ai) {
tag = 'delete';
} else if (j < bj) {
tag = 'insert';
}
if (tag) answer.push([tag, i, ai, j, bj]);
i = ai + size;
j = bj + size;
if (size) answer.push(['equal', ai, i, bj, j]);
}
}
return answer;
}
// this is a generator function in the python lib, which of course is not supported in javascript
// the reimplementation builds up the grouped opcodes into a list in their entirety and returns that.
this.get_grouped_opcodes = function (n) {
if (!n) n = 3;
var codes = this.get_opcodes();
if (!codes) codes = [["equal", 0, 1, 0, 1]];
var code, tag, i1, i2, j1, j2;
if (codes[0][0] == 'equal') {
code = codes[0];
tag = code[0];
i1 = code[1];
i2 = code[2];
j1 = code[3];
j2 = code[4];
codes[0] = [tag, Math.max(i1, i2 - n), i2, Math.max(j1, j2 - n), j2];
}
if (codes[codes.length - 1][0] == 'equal') {
code = codes[codes.length - 1];
tag = code[0];
i1 = code[1];
i2 = code[2];
j1 = code[3];
j2 = code[4];
codes[codes.length - 1] = [tag, i1, Math.min(i2, i1 + n), j1, Math.min(j2, j1 + n)];
}
var nn = n + n;
var group = [];
var groups = [];
for (var idx in codes) {
if (codes.hasOwnProperty(idx)) {
code = codes[idx];
tag = code[0];
i1 = code[1];
i2 = code[2];
j1 = code[3];
j2 = code[4];
if (tag == 'equal' && i2 - i1 > nn) {
group.push([tag, i1, Math.min(i2, i1 + n), j1, Math.min(j2, j1 + n)]);
groups.push(group);
group = [];
i1 = Math.max(i1, i2-n);
j1 = Math.max(j1, j2-n);
}
group.push([tag, i1, i2, j1, j2]);
}
}
if (group && !(group.length == 1 && group[0][0] == 'equal')) groups.push(group)
return groups;
}
this.ratio = function () {
matches = difflib.__reduce(
function (sum, triple) { return sum + triple[triple.length - 1]; },
this.get_matching_blocks(), 0);
return difflib.__calculate_ratio(matches, this.a.length + this.b.length);
}
this.quick_ratio = function () {
var fullbcount, elt;
if (this.fullbcount == null) {
this.fullbcount = fullbcount = {};
for (var i = 0; i < this.b.length; i++) {
elt = this.b[i];
fullbcount[elt] = difflib.__dictget(fullbcount, elt, 0) + 1;
}
}
fullbcount = this.fullbcount;
var avail = {};
var availhas = difflib.__isindict(avail);
var matches = numb = 0;
for (var i = 0; i < this.a.length; i++) {
elt = this.a[i];
if (availhas(elt)) {
numb = avail[elt];
} else {
numb = difflib.__dictget(fullbcount, elt, 0);
}
avail[elt] = numb - 1;
if (numb > 0) matches++;
}
return difflib.__calculate_ratio(matches, this.a.length + this.b.length);
}
this.real_quick_ratio = function () {
var la = this.a.length;
var lb = this.b.length;
return _calculate_ratio(Math.min(la, lb), la + lb);
}
this.isjunk = isjunk ? isjunk : difflib.defaultJunkFunction;
this.a = this.b = null;
this.set_seqs(a, b);
}
};


+ 194
- 0
src/static/js/diffview.js View File

@@ -0,0 +1,194 @@
/*
This is part of jsdifflib v1.0. <http://github.com/cemerick/jsdifflib>

Copyright 2007 - 2011 Chas Emerick <cemerick@snowtide.com>. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.

THIS SOFTWARE IS PROVIDED BY Chas Emerick ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Chas Emerick OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of Chas Emerick.
*/
diffview = {
/**
* Builds and returns a visual diff view. The single parameter, `params', should contain
* the following values:
*
* - baseTextLines: the array of strings that was used as the base text input to SequenceMatcher
* - newTextLines: the array of strings that was used as the new text input to SequenceMatcher
* - opcodes: the array of arrays returned by SequenceMatcher.get_opcodes()
* - baseTextName: the title to be displayed above the base text listing in the diff view; defaults
* to "Base Text"
* - newTextName: the title to be displayed above the new text listing in the diff view; defaults
* to "New Text"
* - contextSize: the number of lines of context to show around differences; by default, all lines
* are shown
* - viewType: if 0, a side-by-side diff view is generated (default); if 1, an inline diff view is
* generated
*/
buildView: function (params) {
var baseTextLines = params.baseTextLines;
var newTextLines = params.newTextLines;
var opcodes = params.opcodes;
var baseTextName = params.baseTextName ? params.baseTextName : "Base Text";
var newTextName = params.newTextName ? params.newTextName : "New Text";
var contextSize = params.contextSize;
var inline = (params.viewType == 0 || params.viewType == 1) ? params.viewType : 0;

if (baseTextLines == null)
throw "Cannot build diff view; baseTextLines is not defined.";
if (newTextLines == null)
throw "Cannot build diff view; newTextLines is not defined.";
if (!opcodes)
throw "Canno build diff view; opcodes is not defined.";
function celt (name, clazz) {
var e = document.createElement(name);
e.className = clazz;
return e;
}
function telt (name, text) {
var e = document.createElement(name);
e.appendChild(document.createTextNode(text));
return e;
}
function ctelt (name, clazz, text) {
var e = document.createElement(name);
e.className = clazz;
e.appendChild(document.createTextNode(text));
return e;
}
var tdata = document.createElement("thead");
var node = document.createElement("tr");
tdata.appendChild(node);
if (inline) {
node.appendChild(document.createElement("th"));
node.appendChild(document.createElement("th"));
node.appendChild(ctelt("th", "texttitle", baseTextName + " vs. " + newTextName));
} else {
node.appendChild(document.createElement("th"));
node.appendChild(ctelt("th", "texttitle", baseTextName));
node.appendChild(document.createElement("th"));
node.appendChild(ctelt("th", "texttitle", newTextName));
}
tdata = [tdata];
var rows = [];
var node2;
/**
* Adds two cells to the given row; if the given row corresponds to a real
* line number (based on the line index tidx and the endpoint of the
* range in question tend), then the cells will contain the line number
* and the line of text from textLines at position tidx (with the class of
* the second cell set to the name of the change represented), and tidx + 1 will
* be returned. Otherwise, tidx is returned, and two empty cells are added
* to the given row.
*/
function addCells (row, tidx, tend, textLines, change) {
if (tidx < tend) {
row.appendChild(telt("th", (tidx + 1).toString()));
row.appendChild(ctelt("td", change, textLines[tidx].replace(/\t/g, "\u00a0\u00a0\u00a0\u00a0")));
return tidx + 1;
} else {
row.appendChild(document.createElement("th"));
row.appendChild(celt("td", "empty"));
return tidx;
}
}
function addCellsInline (row, tidx, tidx2, textLines, change) {
row.appendChild(telt("th", tidx == null ? "" : (tidx + 1).toString()));
row.appendChild(telt("th", tidx2 == null ? "" : (tidx2 + 1).toString()));
row.appendChild(ctelt("td", change, textLines[tidx != null ? tidx : tidx2].replace(/\t/g, "\u00a0\u00a0\u00a0\u00a0")));
}
for (var idx = 0; idx < opcodes.length; idx++) {
code = opcodes[idx];
change = code[0];
var b = code[1];
var be = code[2];
var n = code[3];
var ne = code[4];
var rowcnt = Math.max(be - b, ne - n);
var toprows = [];
var botrows = [];
for (var i = 0; i < rowcnt; i++) {
// jump ahead if we've alredy provided leading context or if this is the first range
if (contextSize && opcodes.length > 1 && ((idx > 0 && i == contextSize) || (idx == 0 && i == 0)) && change=="equal") {
var jump = rowcnt - ((idx == 0 ? 1 : 2) * contextSize);
if (jump > 1) {
toprows.push(node = document.createElement("tr"));
b += jump;
n += jump;
i += jump - 1;
node.appendChild(telt("th", "..."));
if (!inline) node.appendChild(ctelt("td", "skip", ""));
node.appendChild(telt("th", "..."));
node.appendChild(ctelt("td", "skip", ""));
// skip last lines if they're all equal
if (idx + 1 == opcodes.length) {
break;
} else {
continue;
}
}
}
toprows.push(node = document.createElement("tr"));
if (inline) {
if (change == "insert") {
addCellsInline(node, null, n++, newTextLines, change);
} else if (change == "replace") {
botrows.push(node2 = document.createElement("tr"));
if (b < be) addCellsInline(node, b++, null, baseTextLines, "delete");
if (n < ne) addCellsInline(node2, null, n++, newTextLines, "insert");
} else if (change == "delete") {
addCellsInline(node, b++, null, baseTextLines, change);
} else {
// equal
addCellsInline(node, b++, n++, baseTextLines, change);
}
} else {
b = addCells(node, b, be, baseTextLines, change);
n = addCells(node, n, ne, newTextLines, change);
}
}

for (var i = 0; i < toprows.length; i++) rows.push(toprows[i]);
for (var i = 0; i < botrows.length; i++) rows.push(botrows[i]);
}

tdata.push(node = document.createElement("tbody"));
for (var idx in rows) rows.hasOwnProperty(idx) && node.appendChild(rows[idx]);
node = celt("table", "diff" + (inline ? " inlinediff" : ""));
for (var idx in tdata) tdata.hasOwnProperty(idx) && node.appendChild(tdata[idx]);
return node;
}
};


Loading…
Cancel
Save