1 // Copyright 2023 MOSSDeF, Stan Grishin <stangri@melmac.ca>
2 // This code wouldn't have been possible without help from:
3 // - [@stokito](https://github.com/stokito)
4 // - [@vsviridov](https://github.com/vsviridov)
9 "require adblock-fast.status as adb";
13 return "adblock-fast";
16 return "https://docs.openwrt.melmac.net/" + pkg
.Name
+ "/";
18 humanFileSize: function (bytes
, si
= false, dp
= 2) {
19 return `%${si ? 1000 : 1024}.${dp ?? 0}mB`.format(bytes
);
21 isObjEmpty: function (obj
) {
22 return Object
.keys(obj
).length
=== 0;
29 L
.resolveDefault(adb
.getFileUrlFilesizes(pkg
.Name
), {}),
30 L
.resolveDefault(adb
.getPlatformSupport(pkg
.Name
), {}),
31 L
.resolveDefault(L
.uci
.load(pkg
.Name
), {}),
32 L
.resolveDefault(L
.uci
.load("dhcp"), {}),
33 L
.resolveDefault(L
.uci
.load("smartdns"), {}),
37 render: function (data
) {
39 sizes
: (data
[0] && data
[0][pkg
.Name
] && data
[0][pkg
.Name
]["sizes"]) || [],
40 platform
: (data
[1] && data
[1][pkg
.Name
]) || {
41 ipset_installed
: false,
43 dnsmasq_installed
: false,
44 dnsmasq_ipset_support
: false,
45 dnsmasq_nftset_support
: false,
46 smartdns_installed
: false,
47 smartdns_ipset_support
: false,
48 smartdns_nftset_support
: false,
49 unbound_installed
: false,
52 pkg
: (!pkg
.isObjEmpty(data
[2]) && data
[2]) || null,
53 dhcp
: (!pkg
.isObjEmpty(data
[3]) && data
[3]) || null,
54 smartdns
: (!pkg
.isObjEmpty(data
[4]) && data
[4]) || null,
56 var status
, m
, s1
, s2
, s3
, o
;
58 status
= new adb
.status();
59 m
= new form
.Map(pkg
.Name
, _("AdBlock-Fast - Configuration"));
61 s1
= m
.section(form
.NamedSection
, "config", pkg
.Name
);
62 s1
.tab("tab_basic", _("Basic Configuration"));
63 s1
.tab("tab_advanced", _("Advanced Configuration"));
66 "DNS resolution option, see the %sREADME%s for details."
68 '<a href="' + pkg
.URL
+ '#dns-resolver-option" target="_blank">',
71 if (!reply
.platform
.dnsmasq_installed
) {
74 _("Please note that %s is not supported on this system.").format(
75 "<i>dnsmasq.addnhosts</i>"
79 _("Please note that %s is not supported on this system.").format(
84 _("Please note that %s is not supported on this system.").format(
85 "<i>dnsmasq.ipset</i>"
89 _("Please note that %s is not supported on this system.").format(
90 "<i>dnsmasq.servers</i>"
93 if (!reply
.platform
.dnsmasq_ipset_support
) {
96 _("Please note that %s is not supported on this system.").format(
97 "<i>dnsmasq.ipset</i>"
100 if (!reply
.platform
.dnsmasq_nftset_support
) {
103 _("Please note that %s is not supported on this system.").format(
104 "<i>dnsmasq.nftset</i>"
108 if (!reply
.platform
.smartdns_installed
) {
112 _("Please note that %s is not supported on this system.").format(
113 "<i>smartdns.domainset</i>"
116 if (!reply
.platform
.smartdns_ipset_support
) {
119 _("Please note that %s is not supported on this system.").format(
120 "<i>smartdns.ipset</i>"
123 if (!reply
.platform
.smartdns_nftset_support
) {
126 _("Please note that %s is not supported on this system.").format(
127 "<i>smartdns.nftset</i>"
131 if (!reply
.platform
.unbound_installed
) {
135 _("Please note that %s is not supported on this system.").format(
136 "<i>unbound.adb_list</i>"
147 if (reply
.platform
.dnsmasq_installed
) {
148 o
.value("dnsmasq.addnhosts", _("dnsmasq additional hosts"));
149 o
.value("dnsmasq.conf", _("dnsmasq config"));
150 if (reply
.platform
.dnsmasq_ipset_support
) {
151 o
.value("dnsmasq.ipset", _("dnsmasq ipset"));
153 if (reply
.platform
.dnsmasq_nftset_support
) {
154 o
.value("dnsmasq.nftset", _("dnsmasq nft set"));
156 o
.value("dnsmasq.servers", _("dnsmasq servers file"));
158 if (reply
.platform
.smartdns_installed
) {
159 o
.value("smartdns.domainset", _("smartdns domain set"));
160 if (reply
.platform
.smartdns_ipset_support
) {
161 o
.value("smartdns.ipset", _("smartdns ipset"));
163 if (reply
.platform
.smartdns_nftset_support
) {
164 o
.value("smartdns.nftset", _("smartdns nft set"));
167 if (reply
.platform
.unbound_installed
) {
168 o
.value("unbound.adb_list", _("unbound adblock list"));
170 o
.default = "dnsmasq.servers";
175 "dnsmasq_config_file_url",
176 _("Dnsmasq Config File URL"),
178 "URL to the external dnsmasq config file, see the %sREADME%s for details."
180 '<a href="' + pkg
.URL
+ '#dnsmasq_config_file_url" target="_blank">',
184 o
.depends("dns", "dnsmasq.conf");
186 if (reply
.platform
.dnsmasq_installed
&& reply
.dhcp
) {
190 "dnsmasq_instance_option",
191 _("Use AdBlocking on the dnsmasq instance(s)"),
193 "You can limit the AdBlocking to the specific dnsmasq instance(s) (%smore information%s)."
195 '<a href="' + pkg
.URL
+ "#dnsmasq_instance" + '" target="_blank">',
199 o
.value("*", _("AdBlock on all instances"));
200 o
.value("+", _("AdBlock on select instances"));
201 o
.value("-", _("No AdBlock on dnsmasq"));
203 o
.depends("dns", "dnsmasq.addnhosts");
204 o
.depends("dns", "dnsmasq.servers");
206 o
.cfgvalue = function (section_id
) {
207 let val
= this.map
.data
.get(
222 o
.write = function (section_id
, formvalue
) {
223 L
.uci
.set(pkg
.Name
, section_id
, "dnsmasq_instance", formvalue
);
230 _("Pick the dnsmasq instance(s) for AdBlocking")
232 Object
.values(L
.uci
.sections("dhcp", "dnsmasq")).forEach(function (
237 if (element
[".name"] === L
.uci
.resolveSID("dhcp", element
[".name"])) {
238 key
= element
[".index"];
239 description
= "dnsmasq[" + element
[".index"] + "]";
241 key
= element
[".name"];
242 description
= element
[".name"];
244 o
.value(key
, description
);
246 o
.depends("dnsmasq_instance_option", "+");
250 if (reply
.platform
.smartdns_installed
&& reply
.smartdns
) {
254 "smartdns_instance_option",
255 _("Use AdBlocking on the SmartDNS instance(s)"),
257 "You can limit the AdBlocking to the specific SmartDNS instance(s) (%smore information%s)."
259 '<a href="' + pkg
.URL
+ "#smartdns_instance" + '" target="_blank">',
263 o
.value("*", _("AdBlock on all instances"));
264 o
.value("+", _("AdBlock on select instances"));
265 o
.value("-", _("No AdBlock on SmartDNS"));
267 o
.depends("dns", "smartdns.domainset");
269 o
.cfgvalue = function (section_id
) {
270 let val
= this.map
.data
.get(
285 o
.write = function (section_id
, formvalue
) {
286 L
.uci
.set(pkg
.Name
, section_id
, "smartdns_instance", formvalue
);
293 _("Pick the SmartDNS instance(s) for AdBlocking")
295 Object
.values(L
.uci
.sections("smartdns", "smartdns")).forEach(function (
301 element
[".name"] === L
.uci
.resolveSID("smartdns", element
[".name"])
303 key
= element
[".index"];
304 description
= "smartdns[" + element
[".index"] + "]";
306 key
= element
[".name"];
307 description
= element
[".name"];
309 o
.value(key
, description
);
311 o
.depends("smartdns_instance_option", "+");
318 _("Force Router DNS"),
319 _("Forces Router DNS use on local devices, also known as DNS Hijacking.")
321 o
.value("0", _("Let local devices use their own DNS servers if set"));
322 o
.value("1", _("Force Router DNS server to all local devices"));
329 _("Output Verbosity Setting"),
330 _("Controls system log and console output verbosity.")
332 o
.value("0", _("Suppress output"));
333 o
.value("1", _("Some output"));
334 o
.value("2", _("Verbose output"));
337 if (reply
.platform
.leds
.length
) {
342 _("LED to indicate status"),
344 "Pick the LED not already used in %sSystem LED Configuration%s."
345 ).format('<a href="' + L
.url("admin", "system", "leds") + '">', "</a>")
347 o
.value("", _("none"));
348 reply
.platform
.leds
.forEach((element
) => {
356 "config_update_enabled",
357 _("Automatic Config Update"),
358 _("Perform config update before downloading the block/allow-lists.")
360 o
.value("0", _("Disable"));
361 o
.value("1", _("Enable"));
369 _("Add IPv6 entries to block-list.")
371 o
.value("", _("Do not add IPv6 entries"));
372 o
.value("1", _("Add IPv6 entries"));
373 o
.depends("dns", "dnsmasq.addnhosts");
374 o
.depends("dns", "dnsmasq.nftset");
383 _("Download time-out (in seconds)"),
384 _("Stop the download if it is stalled for set number of seconds.")
387 o
.datatype
= "range(1,60)";
392 "curl_max_file_size",
393 _("Curl maximum file size (in bytes)"),
395 "If curl is installed and detected, it would not download files bigger than this."
399 o
.datatype
= "uinteger";
406 _("Curl download retry"),
408 "If curl is installed and detected, it would retry download this many times on timeout/fail."
412 o
.datatype
= "range(0,30)";
417 "parallel_downloads",
418 _("Simultaneous processing"),
420 "Launch all lists downloads and processing simultaneously, reducing service start time."
423 o
.value("0", _("Do not use simultaneous processing"));
424 o
.value("1", _("Use simultaneous processing"));
431 _("Store compressed cache file on router"),
433 "Attempt to create a compressed cache of block-list in the persistent memory."
436 o
.value("0", _("Do not store compressed cache"));
437 o
.value("1", _("Store compressed cache"));
443 "compressed_cache_dir",
444 _("Directory for compressed cache file"),
446 "Directory for compressed cache file of block-list in the persistent memory."
449 o
.datatype
= "string";
452 o
.depends("compressed_cache", "1");
459 _("Enable Debugging"),
460 _("Enables debug output to /tmp/adblock-fast.log.")
462 o
.value("0", _("Disable Debugging"));
463 o
.value("1", _("Enable Debugging"));
470 _("AdBlock-Fast - Allowed and Blocked Domains")
478 _("Allowed Domains"),
479 _("Individual domains to be allowed.")
486 _("Blocked Domains"),
487 _("Individual domains to be blocked.")
494 _("AdBlock-Fast - Allowed and Blocked Lists URLs"),
495 _("URLs to file(s) containing lists to be allowed or blocked.")
502 o
= s3
.option(form
.DummyValue
, "_size", _("Size"));
504 o
.cfgvalue = function (section_id
) {
505 let url
= L
.uci
.get(pkg
.Name
, section_id
, "url");
506 let ret
= _("Unknown");
507 reply
.sizes
.forEach((element
) => {
508 if (element
.url
=== url
) {
509 ret
= element
.size
=== 0 ? ret
: pkg
.humanFileSize(element
.size
);
512 return _("Size: %s").format(ret
);
515 o
= s3
.option(form
.Flag
, "enabled", _("Enable"));
519 o
= s3
.option(form
.ListValue
, "action", _("Action"));
520 o
.value("allow", _("Allow"));
521 o
.value("block", _("Block"));
523 o
.textvalue = function (section_id
) {
524 var val
= this.cfgvalue(section_id
);
525 return val
== "allow" ? _("Allow") : _("Block");
528 o
= s3
.option(form
.Value
, "url", _("URL"));
531 return Promise
.all([status
.render(), m
.render()]);