@@ -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开发模式为标准对现有的文件进行扫描并进行判断', | |||
@@ -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> | |||
@@ -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> | |||
@@ -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'); |
@@ -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'); |
@@ -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); | |||
@@ -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"); | |||
@@ -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()) | |||
{ | |||
@@ -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(); //显示 |
@@ -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>"; | |||
@@ -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']."元"; | |||
@@ -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']; | |||
} | |||
@@ -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'); |
@@ -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> <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> <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> <a href='sys_verifies.php?action=manage'>[管理]</a> <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; | |||
} |
@@ -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" /> | |||
要检查的文件类型</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" /> | |||
特征代码</p> | |||
</td> | |||
</tr> | |||
@@ -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> |
@@ -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"> </td> | |||
<td> | |||
您的系统最后升级时间:<b><?php echo $updateTime; ?></b>;指纹码最后同步时间:<b><?php echo $verifiesTime; ?></b> | |||
<br /> | |||
第一次效验文件时或您的系统已经升级过,请先点击“在线获取最新指纹码” | |||
<br /> | |||
(文件校验将检查本站文件是否和DedeCMS原始文件是否完全一致,如果要替换差异文件,必须按提示设置被更改文件的目录有可写入权限) | |||
</td> | |||
<tr> | |||
<td height="53" align="center"> </td> | |||
<td> | |||
<div style='width:80%;background:#F9FCEF;border-bottom: 1px dashed #A7BA87;padding:3px;'> <b>效对操作:</b></div> | |||
<div style='padding:10px 0px 20px 0px;'> | |||
<a href="javascript:Loading('sys_verifies.php?action=update');" class='np coolbg'>在线获取最新指纹码==></a> | |||
| |||
<a href="javascript:Loading('sys_verifies.php?action=verify');" class='np coolbg'>效对本地文件==></a> | |||
| |||
下载差异文件==> | |||
| |||
替换差异文件==> | |||
</div> | |||
<div style='width:80%;background:#F9FCEF;border-bottom: 1px dashed #A7BA87;padding:3px;'> <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;'> <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> |
@@ -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> >> 下载差异文件</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> |
@@ -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> >> 文件效验管理</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"> 说明:这里是系统文件列表,如果本地对某些文件做过修改,但又不希望同官方服务器上面的镜像版本(发布版本)对应文件进行同步,可将文件校验方式修改为“本地(local)”,以确保不会重新下载文件修复。</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> |
@@ -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> | |||
>> | |||
<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> |
@@ -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会话 | |||
* | |||
@@ -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 | |||
} |
@@ -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); | |||
} | |||
}; | |||
@@ -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; | |||
} | |||
}; | |||