feat: auto scan plugins

This commit is contained in:
2026-06-08 16:07:08 +08:00
parent 7dbc529642
commit cae96dd654
6 changed files with 750 additions and 2 deletions

View File

@@ -0,0 +1,119 @@
package com.novitechie.scan;
import com.janetfilter.core.commons.DebugInfo;
import com.janetfilter.core.enums.RuleType;
import com.janetfilter.core.models.FilterRule;
import com.janetfilter.core.plugin.PluginConfig;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public final class CanaryAutoScanner {
private static final List<FilterRule> DEFAULT_SCAN_PLUGINS = Collections.unmodifiableList(Arrays.asList(new FilterRule(RuleType.EQUAL, "izhangzhihao.rainbow.brackets")));
private static final List<FilterRule> DEFAULT_SCAN_PACKAGES = Collections.unmodifiableList(Arrays.asList(new FilterRule(RuleType.PREFIX, "com.janetfilter."), new FilterRule(RuleType.PREFIX, "com.novitechie.")));
private CanaryAutoScanner() {
}
public static final class AutoScanResult {
private final List<FilterRule> classRules;
private final boolean markerResourceExists;
private AutoScanResult(List<FilterRule> classRules, boolean markerResourceExists) {
this.classRules = classRules == null ? Collections.emptyList() : classRules;
this.markerResourceExists = markerResourceExists;
}
public static AutoScanResult empty() {
return new AutoScanResult(Collections.emptyList(), false);
}
public List<FilterRule> getClassRules() {
return new ArrayList(this.classRules);
}
public boolean isMarkerResourceExists() {
return this.markerResourceExists;
}
}
public static List<FilterRule> scan(PluginConfig config) {
return scanWithResult(config).getClassRules();
}
public static AutoScanResult scanWithResult(PluginConfig config) {
List<FilterRule> pluginRules = rules(config, "Auto_Scan_Plugin", DEFAULT_SCAN_PLUGINS);
List<FilterRule> packageRules = rules(config, "Auto_Scan_Package", DEFAULT_SCAN_PACKAGES);
List<FilterRule> excludeRules = emptyIfNull(config.getBySection("Auto_Scan_Exclude"));
if (pluginRules.isEmpty() || packageRules.isEmpty()) {
DebugInfo.warn("[PRIVACY-SCAN] Auto scan disabled: plugin or package rules are empty");
return AutoScanResult.empty();
}
List<File> scanTargets = JbDirectoryScanner.getPluginDir(config);
if (scanTargets.isEmpty()) {
DebugInfo.warn("[PRIVACY-SCAN] No plugin scan targets found");
return AutoScanResult.empty();
}
DebugInfo.output("[PRIVACY-SCAN] Plugin targets: " + fileSummary(scanTargets));
DebugInfo.output("[PRIVACY-SCAN] Scan_Plugin: " + ruleSummary(pluginRules));
DebugInfo.output("[PRIVACY-SCAN] Scan_Package: " + ruleSummary(packageRules));
DebugInfo.output("[PRIVACY-SCAN] Exclude_Package: " + ruleSummary(excludeRules));
CanaryScanner.ScanResult result = CanaryScanner.scan(scanTargets, pluginRules, packageRules, excludeRules);
List<String> classNames = result.getClassNames();
List<FilterRule> classRules = new ArrayList<>(classNames.size());
DebugInfo.output("[PRIVACY-SCAN] Found " + classNames.size() + " canary classes");
for (String className : classNames) {
classRules.add(FilterRule.of("EQUAL", className));
DebugInfo.output("[PRIVACY-SCAN] - " + className);
}
DebugInfo.output("[PRIVACY-SCAN] Marker resource exists: " + result.isMarkerResourceExists());
return new AutoScanResult(classRules, result.isMarkerResourceExists());
}
private static List<FilterRule> rules(PluginConfig config, String section, List<FilterRule> defaultValue) {
List<FilterRule> configRules = config.getBySection(section);
if (hasSection(config, section)) {
return emptyIfNull(configRules);
}
if (defaultValue == null) {
return Collections.emptyList();
}
return defaultValue;
}
private static boolean hasSection(PluginConfig config, String section) {
return config.getData() != null && config.getData().containsKey(section);
}
private static List<FilterRule> emptyIfNull(List<FilterRule> rules) {
return rules == null ? Collections.emptyList() : rules;
}
private static String fileSummary(List<File> files) {
StringBuilder summary = new StringBuilder();
for (File file : files) {
if (summary.length() > 0) {
summary.append(", ");
}
summary.append(file.getAbsolutePath());
}
return summary.toString();
}
private static String ruleSummary(List<FilterRule> rules) {
if (rules == null || rules.isEmpty()) {
return "(none)";
}
StringBuilder summary = new StringBuilder();
for (FilterRule rule : rules) {
if (summary.length() > 0) {
summary.append(", ");
}
summary.append(rule);
}
return summary.toString();
}
}