fix(ruleset): reject plain lists in ruleset references (#58) and route components to Dushnilin repos

This commit is contained in:
Dushnilin
2026-09-16 15:16:56 +03:00
parent a23c2a2a55
commit d28af621c9
9 changed files with 101 additions and 26 deletions
+55 -19
View File
@@ -1352,10 +1352,18 @@ function resolve_byedpi_release(arch, tag) {
function resolve_wdtt_release(arch, tag) {
let asset_ext = is_apk() ? "apk" : "ipk";
let release_series = trim(helper_output("openwrt-release-series", [ "/etc/openwrt_release" ]));
let owner = "Dushnilin";
let repo = "qwdtt-openwrt";
let releases_json = (tag != null && tag != "") ?
fetch_github_release_by_tag_json("SpaceNeuroX", "qwdtt-openwrt", tag) :
fetch_github_releases_json("SpaceNeuroX", "qwdtt-openwrt", "30");
if (releases_json != "") {
fetch_github_release_by_tag_json(owner, repo, tag) :
fetch_github_releases_json(owner, repo, "30");
if (releases_json == "" || releases_json == "[]") {
owner = "SpaceNeuroX";
releases_json = (tag != null && tag != "") ?
fetch_github_release_by_tag_json(owner, repo, tag) :
fetch_github_releases_json(owner, repo, "30");
}
if (releases_json != "" && releases_json != "[]") {
let resolved = trim(helper_output_input(releases_json, "wdtt-select-asset", [ release_series, asset_ext, arch.candidates ]));
let fields = split(resolved, "\t");
if (length(fields) >= 4) {
@@ -1372,11 +1380,13 @@ function resolve_wdtt_release(arch, tag) {
let distrib_arch = read_openwrt_release_value("DISTRIB_ARCH");
let tag_clean = replace(tag, /^v/, "");
let pkg_name = "wdtt_" + tag_clean + "_openwrt_" + distrib_arch + "." + asset_ext;
let dushnilin_url = "https://github.com/Dushnilin/qwdtt-openwrt/releases/download/" + tag + "/" + pkg_name;
let target_owner = url_exists(dushnilin_url) ? "Dushnilin" : "SpaceNeuroX";
return {
arch: distrib_arch,
package_name: pkg_name,
package_url: "https://github.com/SpaceNeuroX/qwdtt-openwrt/releases/download/" + tag + "/" + pkg_name,
release_url: "https://github.com/SpaceNeuroX/qwdtt-openwrt/releases/tag/" + tag,
package_url: "https://github.com/" + target_owner + "/qwdtt-openwrt/releases/download/" + tag + "/" + pkg_name,
release_url: "https://github.com/" + target_owner + "/qwdtt-openwrt/releases/tag/" + tag,
version: tag
};
}
@@ -1386,10 +1396,18 @@ function resolve_wdtt_release(arch, tag) {
function resolve_olcrtc_release(arch, tag) {
let asset_ext = is_apk() ? "apk" : "ipk";
let release_series = trim(helper_output("openwrt-release-series", [ "/etc/openwrt_release" ]));
let owner = "Dushnilin";
let repo = "openwrt-olcrtc";
let releases_json = (tag != null && tag != "") ?
fetch_github_release_by_tag_json("alekvol", "openwrt-olcrtc", tag) :
fetch_github_releases_json("alekvol", "openwrt-olcrtc", "30");
if (releases_json != "") {
fetch_github_release_by_tag_json(owner, repo, tag) :
fetch_github_releases_json(owner, repo, "30");
if (releases_json == "" || releases_json == "[]") {
owner = "alekvol";
releases_json = (tag != null && tag != "") ?
fetch_github_release_by_tag_json(owner, repo, tag) :
fetch_github_releases_json(owner, repo, "30");
}
if (releases_json != "" && releases_json != "[]") {
let resolved = trim(helper_output_input(releases_json, "olcrtc-select-asset", [ release_series, asset_ext, arch.candidates ]));
let fields = split(resolved, "\t");
if (length(fields) >= 4) {
@@ -1406,11 +1424,13 @@ function resolve_olcrtc_release(arch, tag) {
let distrib_arch = read_openwrt_release_value("DISTRIB_ARCH");
let tag_clean = replace(tag, /^v/, "");
let pkg_name = "olcrtc_" + tag_clean + "_openwrt_" + distrib_arch + "." + asset_ext;
let dushnilin_url = "https://github.com/Dushnilin/openwrt-olcrtc/releases/download/" + tag + "/" + pkg_name;
let target_owner = url_exists(dushnilin_url) ? "Dushnilin" : "alekvol";
return {
arch: distrib_arch,
package_name: pkg_name,
package_url: "https://github.com/alekvol/openwrt-olcrtc/releases/download/" + tag + "/" + pkg_name,
release_url: "https://github.com/alekvol/openwrt-olcrtc/releases/tag/" + tag,
package_url: "https://github.com/" + target_owner + "/openwrt-olcrtc/releases/download/" + tag + "/" + pkg_name,
release_url: "https://github.com/" + target_owner + "/openwrt-olcrtc/releases/tag/" + tag,
version: tag
};
}
@@ -1420,10 +1440,18 @@ function resolve_olcrtc_release(arch, tag) {
function resolve_fptn_release(arch, tag) {
let asset_ext = is_apk() ? "apk" : "ipk";
let release_series = trim(helper_output("openwrt-release-series", [ "/etc/openwrt_release" ]));
let owner = "Dushnilin";
let repo = "fptn";
let releases_json = (tag != null && tag != "") ?
fetch_github_release_by_tag_json("fptn-project", "fptn", tag) :
fetch_github_releases_json("fptn-project", "fptn", "30");
if (releases_json != "") {
fetch_github_release_by_tag_json(owner, repo, tag) :
fetch_github_releases_json(owner, repo, "30");
if (releases_json == "" || releases_json == "[]") {
owner = "fptn-project";
releases_json = (tag != null && tag != "") ?
fetch_github_release_by_tag_json(owner, repo, tag) :
fetch_github_releases_json(owner, repo, "30");
}
if (releases_json != "" && releases_json != "[]") {
let resolved = trim(helper_output_input(releases_json, "fptn-select-asset", [ release_series, asset_ext, arch.candidates ]));
let fields = split(resolved, "\t");
if (length(fields) >= 4) {
@@ -1443,11 +1471,13 @@ function resolve_fptn_release(arch, tag) {
let distrib_arch = read_openwrt_release_value("DISTRIB_ARCH");
let tag_clean = replace(tag, /^v/, "");
let pkg_name = "fptn-client-" + tag_clean + "-openwrt-" + (release_series != "" ? release_series + ".x" : "24.10.x") + "-" + distrib_arch + "." + asset_ext;
let dushnilin_url = "https://github.com/Dushnilin/fptn/releases/download/" + tag + "/" + pkg_name;
let target_owner = url_exists(dushnilin_url) ? "Dushnilin" : "fptn-project";
return {
arch: distrib_arch,
package_name: pkg_name,
package_url: "https://github.com/fptn-project/fptn/releases/download/" + tag + "/" + pkg_name,
release_url: "https://github.com/fptn-project/fptn/releases/tag/" + tag,
package_url: "https://github.com/" + target_owner + "/fptn/releases/download/" + tag + "/" + pkg_name,
release_url: "https://github.com/" + target_owner + "/fptn/releases/tag/" + tag,
version: tag_clean
};
}
@@ -3498,17 +3528,23 @@ function list_component_releases(component, count) {
} else if (component == "byedpi") {
owner = "DPITrickster"; repo = "ByeDPI-OpenWrt";
} else if (component == "wdtt") {
owner = "SpaceNeuroX"; repo = "qwdtt-openwrt";
owner = "Dushnilin"; repo = "qwdtt-openwrt";
} else if (component == "olcrtc") {
owner = "alekvol"; repo = "openwrt-olcrtc";
owner = "Dushnilin"; repo = "openwrt-olcrtc";
} else if (component == "fptn") {
owner = "fptn-project"; repo = "fptn";
owner = "Dushnilin"; repo = "fptn";
} else {
print("[]\n"); return;
}
let releases_json = fetch_github_releases_json(owner, repo, per_page);
if (releases_json == "") { print("[]\n"); return; }
if ((releases_json == "" || releases_json == "[]") && (component == "wdtt" || component == "olcrtc" || component == "fptn")) {
if (component == "wdtt") { owner = "SpaceNeuroX"; repo = "qwdtt-openwrt"; }
else if (component == "olcrtc") { owner = "alekvol"; repo = "openwrt-olcrtc"; }
else if (component == "fptn") { owner = "fptn-project"; repo = "fptn"; }
releases_json = fetch_github_releases_json(owner, repo, per_page);
}
if (releases_json == "" || releases_json == "[]") { print("[]\n"); return; }
let releases = [];
try {
+15 -1
View File
@@ -337,6 +337,18 @@ function remote_reference(value) {
return string_starts_with(value, "http://") || string_starts_with(value, "https://");
}
function remote_plain_list_reference(value) {
value = lc(as_string(value));
let query = index(value, "?");
if (query >= 0)
value = substr(value, 0, query);
let fragment = index(value, "#");
if (fragment >= 0)
value = substr(value, 0, fragment);
return string_ends_with(value, ".lst") || string_ends_with(value, ".txt");
}
function absolute_reference_with_extension(value, first_extension, second_extension) {
value = as_string(value);
if (!string_starts_with(value, "/"))
@@ -351,7 +363,7 @@ function ruleset_reference_valid(reference, community_services) {
return reference == "" ||
community_service_valid(reference, community_services) ||
remote_reference(reference) ||
(remote_reference(reference) && !remote_plain_list_reference(reference)) ||
absolute_reference_with_extension(reference, ".srs", ".json");
}
@@ -1211,6 +1223,8 @@ 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;
@@ -952,6 +952,8 @@ 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) == "/") {
if (extension != "srs" && extension != "json")
ctx.runtime_generate_unsupported("local rule_set extension is not supported by sing-box config generation");
@@ -134,6 +134,11 @@ function remote_format(reference) {
return file_extension(reference) == "json" ? "source" : "binary";
}
function is_plain_list_reference(reference) {
let extension = file_extension(reference);
return extension == "lst" || extension == "txt";
}
function is_valid_srs_file(path) {
let p = as_string(path);
let st = fs.stat(p);
@@ -180,6 +185,7 @@ function module_exports() {
file_extension,
kind_from_reference_hint,
remote_format,
is_plain_list_reference,
is_valid_srs_file,
ensure_empty_srs_stub
};
@@ -198,6 +204,8 @@ else if (mode == "kind-from-reference-hint")
print(kind_from_reference_hint(ARGV[1]), "\n");
else if (mode == "remote-format")
print(remote_format(ARGV[1]), "\n");
else if (mode == "is-plain-list-reference")
exit(is_plain_list_reference(ARGV[1]) ? 0 : 1);
else if (mode == "is-valid-srs-file")
exit(is_valid_srs_file(ARGV[1]) ? 0 : 1);
else if (mode == "ensure-empty-srs-stub")