238 lines
7.4 KiB
PHP
Raw Normal View History

2025-05-20 16:33:23 +08:00
<?php
namespace app\admin\controller\webscan;
use app\common\controller\Backend;
use think\Db;
/**
*文件校验
*/
class Verifies extends Backend
{
//文件校验结果缓存名
private $result_cache_name = 'InconformityCacheArr';
//本地需要校验的文件缓存名
private $loca_cache_name = "WebscanVerifiesCache";
public function _initialize()
{
parent::_initialize();
$this->model = new \app\common\model\webscan\WebscanVerifies();
}
/**
* 校验首页
* @return string|\think\response\Json
* @throws \think\Exception
*/
public function index()
{
if ($this->request->isAjax()) {
/*$search=$this->request->param('search');
$limit=$this->request->param('limit','10','intval');
$offset=$this->request->param('offset','0','intval');
$sort=$this->request->param('sort');
$order=$this->request->param('order');*/
$files_arr = cache($this->result_cache_name);
$count = count($files_arr);
//分页处理
//$files_arr=array_slice($files_arr,$offset,$limit);
$result = array("total" => $count, "rows" => $files_arr);
return json($result);
} else {
$verifi_data = $this->model->where('method', 'local')->count();
if (!$verifi_data) cache($this->loca_cache_name, null);//删除缓存
return $this->view->fetch('', ['verifi_data' => $verifi_data]);
}
}
/**
* 查看文件
*/
public function show($filename)
{
if (file_exists(ROOT_PATH . $filename)) {
show_source(ROOT_PATH . $filename);
} else {
$this->error("文件不存在");
}
}
/**
*加入信任
* @param $filename
*/
public function trust($index)
{
$files_arr = cache($this->result_cache_name);
$temp = $files_arr[$index];
if ($temp) {
unset($files_arr[$index]);
$info = $this->model->where('method', $temp['method'])->where('filename', $temp['filename'])->find();
if ($info) {
$info->md5 = $temp['md5'];
$info->save();
} else {
$this->model->insert($temp);
}
}
cache($this->result_cache_name, array_values($files_arr));
$this->success();
}
/**
*批量信任
* @param $filename
*/
public function trusts($ids)
{
if (!$ids) $this->error("请选择");
$ids = explode(',', $ids);
$files_arr = cache($this->result_cache_name);
//TODO 待优化
foreach ($ids as $index) {
$temp = $files_arr[$index];
if ($temp) {
unset($files_arr[$index]);
$info = $this->model->where('method', $temp['method'])->where('filename', $temp['filename'])->find();
if ($info) {
$info->md5 = $temp['md5'];
$info->save();
} else {
$this->model->insert($temp);
}
}
}
cache($this->result_cache_name, array_values($files_arr));
$this->success();
}
/**
* 初始化数据
*/
public function build()
{
$verifi_data = $this->model->where('method', 'local')->count();
if (!$verifi_data) {
cache($this->loca_cache_name, null);//删除缓存
} else {
$this->error("已经初始化");
}
$files_arr = $this->readFiles();
if ($files_arr) {
$this->model->insertAll($files_arr);
$this->success("初始化数据成功");
} else {
$this->error("初始化失败");
}
}
/**
*遍历检查
* @param $dir
* @return array
*/
public function bianli()
{
$limit = $this->request->param('limit', '1000', 'intval');
$offset = $this->request->param('offset', '0', 'intval');
if ($offset == 0) {
cache($this->result_cache_name, null);//清空之前的结果
}
$files_arr = $this->readFiles();
$count = count($files_arr);
//分页处理
$files_arr = array_slice($files_arr, $offset, $limit);
if ($files_arr) {
$md5_arr = array_column($files_arr, 'md5');
$subQuery = Db::name('webscan_verifies')->field('md5')->where('md5', 'in', $md5_arr)->buildSql();
$sql = "SELECT md5,method,filename,mktime FROM (";
$tempsql = "";
foreach ($files_arr as $row) {
//TODO待优化
$tempsql .= $tempsql ? " UNION SELECT '" . $row['md5'] . "' as md5, '" . $row['method'] . "' as method ,'" . addslashes($row['filename']) . "' as filename ,'" . $row['mktime'] . "' as mktime " : " SELECT '" . $row['md5'] . "' as md5, '" . $row['method'] . "' as method ,'" . addslashes($row['filename']) . "' as filename ,'" . $row['mktime'] . "' as mktime ";
}
$sql = $sql . $tempsql . ")a WHERE md5 NOT IN(" . $subQuery . ")";
$result = Db::query($sql);
$InconformityCacheArr = cache($this->result_cache_name);
$InconformityCacheArr = $InconformityCacheArr ?: [];
if ($result) {
$InconformityCacheArr = $InconformityCacheArr ? array_merge($InconformityCacheArr, $result) : $result;
cache($this->result_cache_name, $InconformityCacheArr);
}
$this->success("正在检测中,已检测" . ($offset + $limit) . "个文件,有" . count($InconformityCacheArr) . "个文件不一致", url('webscan.verifies/bianli', ['offset' => ($offset + $limit)]));
}
$this->success("检测完成{$count}", url('webscan.verifies/index'));
}
/**
* 读取本地的文件数据
* @return mixed
*/
protected function readFiles()
{
$files_arr = cache($this->loca_cache_name);
if (!$files_arr) {
$config = get_addon_config('webscan');
$suffix = explode('|', $config['files_suffix']);
$dir = $config['ignore_dir'];//忽略的文件夹
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(ROOT_PATH), \RecursiveIteratorIterator::LEAVES_ONLY
);
$i = 0;
foreach ($files as $name => $file) {
$temp_str = str_replace(ROOT_PATH, '', $name);
$search = ["/", "?", "=", ".", "&", '|', '\\'];
$replace = ["\/", "\?", "\=", "\.", "\&", '|^', '\/'];
$white_url = str_replace($search, $replace, $dir);
if (preg_match("/^" . $white_url . "/is", $temp_str)) {
continue;
}
if (!$file->isDir()) {
if (in_array($file->getExtension(), $suffix)) {
$files_arr[$i]['md5'] = md5_file($name);
$files_arr[$i]['filename'] = $temp_str;
$files_arr[$i]['method'] = 'local';
$files_arr[$i]['mktime'] = $file->getMTime();
}
$i++;
}
}
unset($files);
if ($files_arr) {
cache($this->loca_cache_name, $files_arr, 86400);//缓存一天
}
}
return $files_arr;
}
}