feat(rulesets): add native plain list (.lst/.txt) download and compilation in rule_set & fix OlcRTC/WDTT status
This commit is contained in:
@@ -2743,11 +2743,44 @@ function import_rule_sets_with_subnets_from_rule(section, settings) {
|
||||
if (!import_custom_ruleset_subnets_from_local(reference, "source", section, "Rule set " + reference))
|
||||
ok = false;
|
||||
}
|
||||
else if (match(reference, /^https?:\/\//) != null) {
|
||||
let format = extension == "json" ? "source" : (extension == "srs" ? "binary" : singbox_rulesets_module().remote_format(reference));
|
||||
if (!import_custom_ruleset_subnets_from_remote(reference, format, section, "Rule set " + reference, settings))
|
||||
else if (match(reference, /^\/.*\.(lst|txt)$/) != null) {
|
||||
if (!add_plain_subnet_file_to_nft_for_section(section, reference))
|
||||
ok = false;
|
||||
}
|
||||
else if (match(reference, /^https?:\/\//) != null) {
|
||||
if (extension == "lst" || extension == "txt" || singbox_rulesets_module().is_plain_list_reference(reference)) {
|
||||
let tmpfile = temp_path();
|
||||
if (tmpfile == "") {
|
||||
ok = false;
|
||||
} else {
|
||||
if (download_to_file(reference, tmpfile, service_proxy_address(settings, "lists")) && file_nonempty(tmpfile)) {
|
||||
convert_crlf_to_lf(tmpfile);
|
||||
if (!add_plain_subnet_file_to_nft_for_section(section, tmpfile))
|
||||
ok = false;
|
||||
let tag_name = "inline-custom-" + singbox_rulesets_module().hash12(reference) + "-ruleset";
|
||||
let srs_path = TMP_RULESET_FOLDER + "/" + tag_name + ".srs";
|
||||
let json_path = TMP_RULESET_FOLDER + "/" + tag_name + ".json";
|
||||
let etc_srs = "/etc/tachyon/rulesets/" + tag_name + ".srs";
|
||||
let etc_json = "/etc/tachyon/rulesets/" + tag_name + ".json";
|
||||
common.ensure_dir("/etc/tachyon/rulesets");
|
||||
common.ensure_dir(TMP_RULESET_FOLDER);
|
||||
let res = routing_rulesets_module().compile_plain_list(tmpfile, srs_path, json_path);
|
||||
if (res.format == "binary")
|
||||
common.copy_file(srs_path, etc_srs);
|
||||
else
|
||||
common.copy_file(json_path, etc_json);
|
||||
} else {
|
||||
log_message("Failed to download remote plain list " + reference + "; keeping existing cache", "warn");
|
||||
}
|
||||
remove_file(tmpfile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let format = extension == "json" ? "source" : (extension == "srs" ? "binary" : singbox_rulesets_module().remote_format(reference));
|
||||
if (!import_custom_ruleset_subnets_from_remote(reference, format, section, "Rule set " + reference, settings))
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log_message("Unsupported rule set reference for subnet import: " + reference, "error");
|
||||
ok = false;
|
||||
@@ -2757,6 +2790,52 @@ function import_rule_sets_with_subnets_from_rule(section, settings) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
function update_remote_plain_rulesets_from_rule(section, settings) {
|
||||
if (!bool_option(section, "enabled", true))
|
||||
return true;
|
||||
|
||||
let rulesets = connections.rule_sets(section);
|
||||
if (length(rulesets) == 0)
|
||||
return true;
|
||||
|
||||
let ok = true;
|
||||
for (let reference in rulesets) {
|
||||
reference = as_string(reference);
|
||||
if (match(reference, /^https?:\/\//) == null)
|
||||
continue;
|
||||
if (!singbox_rulesets_module().is_plain_list_reference(reference))
|
||||
continue;
|
||||
|
||||
log_message("Updating remote plain rule set for '" + section_name(section) + "': " + reference, "info");
|
||||
let tmpfile = temp_path();
|
||||
if (tmpfile == "") {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (download_to_file(reference, tmpfile, service_proxy_address(settings, "lists")) && file_nonempty(tmpfile)) {
|
||||
convert_crlf_to_lf(tmpfile);
|
||||
let tag_name = "inline-custom-" + singbox_rulesets_module().hash12(reference) + "-ruleset";
|
||||
let srs_path = TMP_RULESET_FOLDER + "/" + tag_name + ".srs";
|
||||
let json_path = TMP_RULESET_FOLDER + "/" + tag_name + ".json";
|
||||
let etc_srs = "/etc/tachyon/rulesets/" + tag_name + ".srs";
|
||||
let etc_json = "/etc/tachyon/rulesets/" + tag_name + ".json";
|
||||
common.ensure_dir("/etc/tachyon/rulesets");
|
||||
common.ensure_dir(TMP_RULESET_FOLDER);
|
||||
let res = routing_rulesets_module().compile_plain_list(tmpfile, srs_path, json_path);
|
||||
if (res.format == "binary")
|
||||
common.copy_file(srs_path, etc_srs);
|
||||
else
|
||||
common.copy_file(json_path, etc_json);
|
||||
}
|
||||
else {
|
||||
log_message("Failed to download remote plain rule set " + reference + "; keeping existing cache", "warn");
|
||||
}
|
||||
remove_file(tmpfile);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
function import_domains_from_remote_plain_file(url, section, settings) {
|
||||
let tmpfile = temp_path();
|
||||
if (tmpfile == "")
|
||||
@@ -3155,6 +3234,9 @@ function list_update() {
|
||||
for (let section in sections)
|
||||
if (!import_domains_from_remote_domain_lists(section, settings))
|
||||
ok = false;
|
||||
for (let section in sections)
|
||||
if (!update_remote_plain_rulesets_from_rule(section, settings))
|
||||
ok = false;
|
||||
|
||||
// Фаза 2: применение к nft (захватываем лок reload, чтобы не конфликтовать
|
||||
// с reload-firewall, который пересоздаёт таблицы и сеты nftables)
|
||||
|
||||
@@ -363,8 +363,9 @@ function ruleset_reference_valid(reference, community_services) {
|
||||
|
||||
return reference == "" ||
|
||||
community_service_valid(reference, community_services) ||
|
||||
(remote_reference(reference) && !remote_plain_list_reference(reference)) ||
|
||||
absolute_reference_with_extension(reference, ".srs", ".json");
|
||||
remote_reference(reference) ||
|
||||
absolute_reference_with_extension(reference, ".srs", ".json") ||
|
||||
absolute_reference_with_extension(reference, ".lst", ".txt");
|
||||
}
|
||||
|
||||
function plain_domain_ip_list_reference_valid(reference) {
|
||||
@@ -1223,8 +1224,6 @@ function validate_service_value(service, context) {
|
||||
}
|
||||
|
||||
function validate_ruleset_reference_value(reference, context) {
|
||||
if (remote_plain_list_reference(reference))
|
||||
fail_validation("Plain .lst/.txt list '" + reference + "' belongs in domain_ip_lists, not rule_set. Aborted.");
|
||||
if (ruleset_reference_valid(reference, context.community_services))
|
||||
return;
|
||||
|
||||
|
||||
@@ -538,6 +538,18 @@ function remove_file(path) {
|
||||
try { fs.unlink(path); return true; } catch (e) { return true; }
|
||||
}
|
||||
|
||||
function copy_file(source, target) {
|
||||
source = as_string(source);
|
||||
target = as_string(target);
|
||||
let data = fs.readfile(source);
|
||||
if (data == null)
|
||||
return false;
|
||||
let slash = rindex(target, "/");
|
||||
if (slash > 0)
|
||||
ensure_dir(substr(target, 0, slash));
|
||||
return fs.writefile(target, data) != null;
|
||||
}
|
||||
|
||||
function unlink_file(path) {
|
||||
return remove_file(path);
|
||||
}
|
||||
@@ -705,6 +717,7 @@ return {
|
||||
command_output_from_args,
|
||||
ensure_dir,
|
||||
remove_file,
|
||||
copy_file,
|
||||
unlink_file,
|
||||
write_file,
|
||||
file_exists,
|
||||
|
||||
@@ -1218,6 +1218,10 @@ function build_system_info() {
|
||||
let zapret2_version = zapret2_installed ? provider_version(ZAPRET2_RUNTIME_UC) : "not installed";
|
||||
let byedpi_installed = provider_installed(BYEDPI_RUNTIME_UC) ? 1 : 0;
|
||||
let byedpi_version = byedpi_installed ? provider_version(BYEDPI_RUNTIME_UC) : "not installed";
|
||||
let wdtt_installed = provider_installed(WDTT_RUNTIME_UC) ? 1 : 0;
|
||||
let wdtt_version = wdtt_installed ? provider_version(WDTT_RUNTIME_UC) : "not installed";
|
||||
let olcrtc_installed = provider_installed(OLCRTC_RUNTIME_UC) ? 1 : 0;
|
||||
let olcrtc_version = olcrtc_installed ? provider_version(OLCRTC_RUNTIME_UC) : "not installed";
|
||||
let tailscale_installed = provider_installed(TAILSCALE_RUNTIME_UC) ? 1 : 0;
|
||||
let tailscale_version = tailscale_installed ? provider_version(TAILSCALE_RUNTIME_UC) : "not installed";
|
||||
let fptn_installed = provider_installed(FPTN_RUNTIME_UC) ? 1 : 0;
|
||||
@@ -1261,6 +1265,8 @@ function build_system_info() {
|
||||
let zapret_meta = read_backup_meta("zapret");
|
||||
let zapret2_meta = read_backup_meta("zapret2");
|
||||
let byedpi_meta = read_backup_meta("byedpi");
|
||||
let wdtt_meta = read_backup_meta("wdtt");
|
||||
let olcrtc_meta = read_backup_meta("olcrtc");
|
||||
let tailscale_meta = read_backup_meta("tailscale");
|
||||
let fptn_meta = read_backup_meta("fptn");
|
||||
|
||||
@@ -1290,6 +1296,14 @@ function build_system_info() {
|
||||
byedpi_installed,
|
||||
byedpi_backup_version: byedpi_meta ? as_string(byedpi_meta.version) : "",
|
||||
byedpi_backup_time: byedpi_meta ? int(byedpi_meta.timestamp || 0) : 0,
|
||||
wdtt_version,
|
||||
wdtt_installed,
|
||||
wdtt_backup_version: wdtt_meta ? as_string(wdtt_meta.version) : "",
|
||||
wdtt_backup_time: wdtt_meta ? int(wdtt_meta.timestamp || 0) : 0,
|
||||
olcrtc_version,
|
||||
olcrtc_installed,
|
||||
olcrtc_backup_version: olcrtc_meta ? as_string(olcrtc_meta.version) : "",
|
||||
olcrtc_backup_time: olcrtc_meta ? int(olcrtc_meta.timestamp || 0) : 0,
|
||||
tailscale_version,
|
||||
tailscale_installed,
|
||||
tailscale_backup_version: tailscale_meta ? as_string(tailscale_meta.version) : "",
|
||||
|
||||
@@ -31,6 +31,7 @@ let bool_option = common.bool_option;
|
||||
let list_option = common.list_option;
|
||||
let section_name = common.section_name;
|
||||
let read_json_file = common.read_json_file;
|
||||
let write_json = common.write_json;
|
||||
|
||||
function yaml_quote(value) {
|
||||
value = as_string(value);
|
||||
@@ -70,6 +71,12 @@ function package_version() {
|
||||
let ver = trim(fs.readfile("/etc/olcrtc/.version") || "");
|
||||
if (ver != "")
|
||||
return ver;
|
||||
let pkgs = require("core.packages");
|
||||
if (pkgs && pkgs.version) {
|
||||
let v = pkgs.version("olcrtc");
|
||||
if (v != "")
|
||||
return v;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ let list_option = common.list_option;
|
||||
let section_name = common.section_name;
|
||||
let read_json_file = common.read_json_file;
|
||||
let write_json_file = common.write_json_file;
|
||||
let write_json = common.write_json;
|
||||
|
||||
function lan_mac_address() {
|
||||
for (let iface in ["br-lan", "lan", "eth0", "eth1"]) {
|
||||
@@ -84,6 +85,12 @@ function package_version() {
|
||||
if (ver != "")
|
||||
return ver;
|
||||
}
|
||||
let pkgs = require("core.packages");
|
||||
if (pkgs && pkgs.version) {
|
||||
let v = pkgs.version("wdtt") || pkgs.version("qwdtt");
|
||||
if (v != "")
|
||||
return v;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -469,6 +469,34 @@ function has_rules(path) {
|
||||
return length(array_or_empty(ruleset.rules)) > 0;
|
||||
}
|
||||
|
||||
function compile_plain_list(plain_path, ruleset_srs_path, ruleset_json_path) {
|
||||
create_source(ruleset_json_path);
|
||||
import_plain_list(plain_path, ruleset_json_path, "domain_suffix", "domains", "5000");
|
||||
import_plain_list(plain_path, ruleset_json_path, "ip_cidr", "subnets", "5000");
|
||||
|
||||
let has_doms = has_domain_matchers(ruleset_json_path);
|
||||
let rules_exist = has_rules(ruleset_json_path);
|
||||
|
||||
if (rules_exist) {
|
||||
let compile_ok = common.command_success_from_args([
|
||||
"sing-box", "rule-set", "compile", ruleset_json_path, "-o", ruleset_srs_path
|
||||
]);
|
||||
let srs_st = fs.stat(ruleset_srs_path);
|
||||
if (compile_ok && srs_st != null && srs_st.size >= 16) {
|
||||
fs.unlink(ruleset_json_path);
|
||||
return { format: "binary", path: ruleset_srs_path, has_domains: has_doms };
|
||||
}
|
||||
return { format: "source", path: ruleset_json_path, has_domains: has_doms };
|
||||
}
|
||||
|
||||
let rulesets_mod = null;
|
||||
try { rulesets_mod = require("singbox.rulesets"); } catch (e) {}
|
||||
if (rulesets_mod && rulesets_mod.ensure_empty_srs_stub)
|
||||
rulesets_mod.ensure_empty_srs_stub(ruleset_srs_path);
|
||||
fs.unlink(ruleset_json_path);
|
||||
return { format: "binary", path: ruleset_srs_path, has_domains: false };
|
||||
}
|
||||
|
||||
function module_exports() {
|
||||
return {
|
||||
create_source,
|
||||
@@ -480,6 +508,7 @@ function module_exports() {
|
||||
extract_ip_cidr_nft_elements,
|
||||
has_domain_matchers,
|
||||
has_rules,
|
||||
compile_plain_list,
|
||||
ruleset_tag,
|
||||
read_json_file,
|
||||
write_json_file
|
||||
|
||||
@@ -751,11 +751,19 @@ function has_community_subnet_list(value) {
|
||||
return rule_config.has_community_subnet_list(value);
|
||||
}
|
||||
|
||||
function rule_has_list_update_source(enabled, action, community_lists, remote_domain_lists, remote_subnet_lists, rule_set_with_subnets, domain_ip_lists) {
|
||||
function has_remote_plain_ruleset(value) {
|
||||
for (let item in split(as_string(value), /[ \t\r\n]+/)) {
|
||||
if (match(item, /^https?:\/\//) != null && match(item, /\.(lst|txt)$/i) != null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function rule_has_list_update_source(enabled, action, community_lists, remote_domain_lists, remote_subnet_lists, rule_set_with_subnets, domain_ip_lists, rule_set) {
|
||||
if (!arg_bool(enabled))
|
||||
return false;
|
||||
if (as_string(action) == "dns")
|
||||
return list_has_remote_references(domain_ip_lists);
|
||||
return list_has_remote_references(domain_ip_lists) || has_remote_plain_ruleset(rule_set);
|
||||
if (as_string(action) == "hosts")
|
||||
return false;
|
||||
|
||||
@@ -764,7 +772,8 @@ function rule_has_list_update_source(enabled, action, community_lists, remote_do
|
||||
as_string(remote_domain_lists) != "" ||
|
||||
as_string(remote_subnet_lists) != "" ||
|
||||
as_string(rule_set_with_subnets) != "" ||
|
||||
list_has_remote_references(domain_ip_lists)
|
||||
list_has_remote_references(domain_ip_lists) ||
|
||||
has_remote_plain_ruleset(rule_set)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1244,6 +1253,7 @@ function append_list_update_signature_body(body, section) {
|
||||
body = signature_add_value(body, "lists." + name + ".action", action);
|
||||
if (action == "dns") {
|
||||
body = signature_add_value(body, "lists." + name + ".domain_ip_lists", option(section, "domain_ip_lists", ""));
|
||||
body = signature_add_value(body, "lists." + name + ".rule_set", connections.rule_sets_value(section));
|
||||
return body;
|
||||
}
|
||||
if (action == "hosts") {
|
||||
@@ -1261,6 +1271,7 @@ function append_list_update_signature_body(body, section) {
|
||||
body = signature_add_value(body, "lists." + name + ".remote_subnet_lists", option(section, "remote_subnet_lists", ""));
|
||||
body = signature_add_value(body, "lists." + name + ".rule_set_with_subnets", connections.rule_sets_with_subnets_value(section));
|
||||
body = signature_add_value(body, "lists." + name + ".domain_ip_lists", option(section, "domain_ip_lists", ""));
|
||||
body = signature_add_value(body, "lists." + name + ".rule_set", connections.rule_sets_value(section));
|
||||
|
||||
return body;
|
||||
}
|
||||
@@ -1959,7 +1970,8 @@ function has_list_update_sources_from_sections(sections) {
|
||||
option(section, "remote_domain_lists", ""),
|
||||
option(section, "remote_subnet_lists", ""),
|
||||
connections.rule_sets_with_subnets_value(section),
|
||||
option(section, "domain_ip_lists", "")
|
||||
option(section, "domain_ip_lists", ""),
|
||||
connections.rule_sets_value(section)
|
||||
))
|
||||
return true;
|
||||
|
||||
@@ -2221,7 +2233,7 @@ else if (mode == "community-service-has-subnet-list")
|
||||
else if (mode == "filter-community-subnet-lists")
|
||||
filter_community_subnet_lists(ARGV[1]);
|
||||
else if (mode == "rule-has-list-update-source")
|
||||
exit(rule_has_list_update_source(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6], ARGV[7]) ? 0 : 1);
|
||||
exit(rule_has_list_update_source(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6], ARGV[7], ARGV[8]) ? 0 : 1);
|
||||
else if (mode == "rule-has-nft-list-update-source")
|
||||
exit(rule_has_nft_list_update_source(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6]) ? 0 : 1);
|
||||
else if (mode == "rule-has-subscription-update-source")
|
||||
|
||||
@@ -1011,6 +1011,8 @@ function capability_flags() {
|
||||
zapret_installed: file_executable(ZAPRET_PROVIDER_NFQWS_BIN) ? 1 : 0,
|
||||
zapret2_installed: file_executable(ZAPRET2_PROVIDER_NFQWS2_BIN) ? 1 : 0,
|
||||
byedpi_installed: file_executable(BYEDPI_BIN) ? 1 : 0,
|
||||
wdtt_installed: (file_executable("/usr/bin/qwdtt") || file_executable("/usr/bin/wdtt")) ? 1 : 0,
|
||||
olcrtc_installed: file_executable("/usr/bin/olcrtc") ? 1 : 0,
|
||||
server_inbounds_enabled_count: 0
|
||||
};
|
||||
|
||||
|
||||
@@ -952,9 +952,121 @@ function ensure_custom_ruleset(config, reference) {
|
||||
return { tag: tag_name, kind };
|
||||
|
||||
let extension = runtime_rulesets.file_extension(reference);
|
||||
if (runtime_rulesets.is_plain_list_reference(reference))
|
||||
ctx.runtime_generate_unsupported("plain .lst/.txt list '" + reference + "' belongs in domain_ip_lists, not rule_set");
|
||||
if (substr(reference, 0, 1) == "/") {
|
||||
let folder = ctx.runtime_ruleset_folder || runtime_ruleset_folder;
|
||||
common.ensure_dir(folder);
|
||||
|
||||
if (runtime_rulesets.is_plain_list_reference(reference)) {
|
||||
let srs_path = folder + "/" + tag_name + ".srs";
|
||||
let json_path = folder + "/" + tag_name + ".json";
|
||||
let etc_srs = "/etc/tachyon/rulesets/" + tag_name + ".srs";
|
||||
let etc_json = "/etc/tachyon/rulesets/" + tag_name + ".json";
|
||||
|
||||
if (substr(reference, 0, 1) == "/") {
|
||||
if (!helpers.file_is_usable(reference, 1))
|
||||
return null;
|
||||
|
||||
let ref_st = fs.stat(reference);
|
||||
let srs_st = fs.stat(srs_path);
|
||||
if (srs_st && runtime_rulesets.is_valid_srs_file(srs_path) && ref_st && srs_st.mtime >= ref_st.mtime) {
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: "binary",
|
||||
path: srs_path
|
||||
});
|
||||
return { tag: tag_name, kind: "domains" };
|
||||
}
|
||||
|
||||
let res = source_rulesets.compile_plain_list(reference, srs_path, json_path);
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: res.format,
|
||||
path: res.path
|
||||
});
|
||||
return { tag: tag_name, kind: res.has_domains ? "domains" : "unknown" };
|
||||
}
|
||||
else if (substr(reference, 0, 7) == "http://" || substr(reference, 0, 8) == "https://") {
|
||||
if (runtime_rulesets.is_valid_srs_file(srs_path)) {
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: "binary",
|
||||
path: srs_path
|
||||
});
|
||||
return { tag: tag_name, kind: "domains" };
|
||||
}
|
||||
else if (runtime_rulesets.is_valid_srs_file(etc_srs)) {
|
||||
common.copy_file(etc_srs, srs_path);
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: "binary",
|
||||
path: srs_path
|
||||
});
|
||||
return { tag: tag_name, kind: "domains" };
|
||||
}
|
||||
else if (fs.stat(json_path) != null) {
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: "source",
|
||||
path: json_path
|
||||
});
|
||||
return { tag: tag_name, kind: "domains" };
|
||||
}
|
||||
else if (fs.stat(etc_json) != null) {
|
||||
common.copy_file(etc_json, json_path);
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: "source",
|
||||
path: json_path
|
||||
});
|
||||
return { tag: tag_name, kind: "domains" };
|
||||
}
|
||||
else {
|
||||
let tmp_plain = folder + "/" + tag_name + ".tmp.plain";
|
||||
let dl_ok = false;
|
||||
if (common.command_success("command -v curl"))
|
||||
dl_ok = common.command_success_from_args([ "curl", "-fsSL", "--connect-timeout", "5", "-m", "10", reference, "-o", tmp_plain ]);
|
||||
else if (common.command_success("command -v wget"))
|
||||
dl_ok = common.command_success_from_args([ "wget", "-q", "-T", "10", "-O", tmp_plain, reference ]);
|
||||
|
||||
if (dl_ok && helpers.file_is_usable(tmp_plain, 1)) {
|
||||
common.ensure_dir("/etc/tachyon/rulesets");
|
||||
let res = source_rulesets.compile_plain_list(tmp_plain, srs_path, json_path);
|
||||
if (res.format == "binary")
|
||||
common.copy_file(srs_path, etc_srs);
|
||||
else
|
||||
common.copy_file(json_path, etc_json);
|
||||
fs.unlink(tmp_plain);
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: res.format,
|
||||
path: res.path
|
||||
});
|
||||
return { tag: tag_name, kind: res.has_domains ? "domains" : "unknown" };
|
||||
}
|
||||
else {
|
||||
fs.unlink(tmp_plain);
|
||||
runtime_rulesets.ensure_empty_srs_stub(srs_path);
|
||||
push(config.route.rule_set, {
|
||||
type: "local",
|
||||
tag: tag_name,
|
||||
format: "binary",
|
||||
path: srs_path
|
||||
});
|
||||
return { tag: tag_name, kind: "domains" };
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.runtime_generate_unsupported("plain list reference is not supported by sing-box config generation");
|
||||
}
|
||||
}
|
||||
else if (substr(reference, 0, 1) == "/") {
|
||||
if (extension != "srs" && extension != "json")
|
||||
ctx.runtime_generate_unsupported("local rule_set extension is not supported by sing-box config generation");
|
||||
// Skip broken local ruleset files — nonexistent or suspiciously small
|
||||
|
||||
Reference in New Issue
Block a user