| @@ -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; | |||
| } | |||
| }; | |||