summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-adblock-fast/htdocs
diff options
context:
space:
mode:
authorStan Grishin <stangri@melmac.ca>2023-08-28 21:30:42 +0000
committerStan Grishin <stangri@melmac.ca>2023-09-03 13:57:04 +0000
commit81fc75739c13881ba339d02017ec3a5d2a32948d (patch)
treebbfeb73e3f2bd18b63bf20ab37310397a776c3ef /applications/luci-app-adblock-fast/htdocs
parent324f5a3f79ac237d4ffc14624ffb4d768f7d8921 (diff)
luci-app-adblock-fast: initial commit
* Depends on https://github.com/openwrt/packages/pull/21943 Signed-off-by: Stan Grishin <stangri@melmac.ca>
Diffstat (limited to 'applications/luci-app-adblock-fast/htdocs')
-rw-r--r--applications/luci-app-adblock-fast/htdocs/luci-static/resources/adblock-fast/status.js479
-rw-r--r--applications/luci-app-adblock-fast/htdocs/luci-static/resources/view/adblock-fast/overview.js385
2 files changed, 864 insertions, 0 deletions
diff --git a/applications/luci-app-adblock-fast/htdocs/luci-static/resources/adblock-fast/status.js b/applications/luci-app-adblock-fast/htdocs/luci-static/resources/adblock-fast/status.js
new file mode 100644
index 0000000000..901d3d9f26
--- /dev/null
+++ b/applications/luci-app-adblock-fast/htdocs/luci-static/resources/adblock-fast/status.js
@@ -0,0 +1,479 @@
+// Copyright MOSSDeF, 2023 Stan Grishin <stangri@melmac.ca>
+// This code wouldn't have been possible without help from:
+// - [@vsviridov](https://github.com/vsviridov)
+
+"require ui";
+"require rpc";
+"require form";
+"require baseclass";
+
+var pkg = {
+ get Name() {
+ return "adblock-fast";
+ },
+ get URL() {
+ return "https://docs.openwrt.melmac.net/" + pkg.Name + "/";
+ },
+};
+
+var getFileUrlFilesizes = rpc.declare({
+ object: "luci." + pkg.Name,
+ method: "getFileUrlFilesizes",
+ params: ["name", "url"],
+});
+
+var getInitList = rpc.declare({
+ object: "luci." + pkg.Name,
+ method: "getInitList",
+ params: ["name"],
+});
+
+var getInitStatus = rpc.declare({
+ object: "luci." + pkg.Name,
+ method: "getInitStatus",
+ params: ["name"],
+});
+
+var getPlatformSupport = rpc.declare({
+ object: "luci." + pkg.Name,
+ method: "getPlatformSupport",
+ params: ["name"],
+});
+
+var _setInitAction = rpc.declare({
+ object: "luci." + pkg.Name,
+ method: "setInitAction",
+ params: ["name", "action"],
+ expect: { result: false },
+});
+
+var RPC = {
+ listeners: [],
+ on: function (event, callback) {
+ var pair = { event: event, callback: callback };
+ this.listeners.push(pair);
+ return function unsubscribe() {
+ this.listeners = this.listeners.filter(function (listener) {
+ return listener !== pair;
+ });
+ }.bind(this);
+ },
+ emit: function (event, data) {
+ this.listeners.forEach(function (listener) {
+ if (listener.event === event) {
+ listener.callback(data);
+ }
+ });
+ },
+ setInitAction: function (name, action) {
+ _setInitAction(name, action).then(
+ function (result) {
+ this.emit("setInitAction", result);
+ }.bind(this)
+ );
+ },
+};
+
+var status = baseclass.extend({
+ render: function () {
+ return Promise.all([L.resolveDefault(getInitStatus(pkg.Name), {})]).then(
+ function (data) {
+ var reply = {
+ status: (data[0] && data[0][pkg.Name]) || {
+ enabled: false,
+ status: null,
+ running: null,
+ version: null,
+ errors: [],
+ warnings: [],
+ force_dns_active: null,
+ force_dns_ports: [],
+ entries: null,
+ dns: null,
+ outputFile: null,
+ outputCache: null,
+ outputGzip: null,
+ outputFileExists: null,
+ outputCacheExists: null,
+ outputGzipExists: null,
+ leds: [],
+ },
+ };
+ var text = "";
+ var outputFile = reply.status.outputFile;
+ var outputCache = reply.status.outputCache;
+ var statusTable = {
+ statusNoInstall: _("%s is not installed or not found").format(
+ pkg.Name
+ ),
+ statusStopped: _("Stopped"),
+ statusStarting: _("Starting"),
+ statusProcessing: _("Processing lists"),
+ statusRestarting: _("Restarting"),
+ statusForceReloading: _("Force Reloading"),
+ statusDownloading: _("Downloading lists"),
+ statusError: _("Error"),
+ statusWarning: _("Warning"),
+ statusFail: _("Fail"),
+ statusSuccess: _("Active"),
+ };
+
+ var header = E("h2", {}, _("AdBlock-Fast - Status"));
+ var statusTitle = E(
+ "label",
+ { class: "cbi-value-title" },
+ _("Service Status")
+ );
+ if (reply.status.version) {
+ text += _("Version %s").format(reply.status.version) + " - ";
+ switch (reply.status.status) {
+ case "statusSuccess":
+ text += statusTable[reply.status.status] + ".";
+ text +=
+ "<br />" +
+ _("Blocking %s domains (with %s).").format(
+ reply.status.entries,
+ reply.status.dns
+ );
+ if (reply.status.outputGzipExists) {
+ text += "<br />" + _("Compressed cache file created.");
+ }
+ if (reply.status.force_dns_active) {
+ text += "<br />" + _("Force DNS ports:");
+ reply.status.force_dns_ports.forEach((element) => {
+ text += " " + element;
+ });
+ text += ".";
+ }
+ break;
+ case "statusStopped":
+ if (reply.status.enabled) {
+ text += statusTable[reply.status.status] + ".";
+ } else {
+ text +=
+ statusTable[reply.status.status] +
+ " (" +
+ _("Disabled") +
+ ").";
+ }
+ if (reply.status.outputCacheExists) {
+ text += "<br />" + _("Cache file found.");
+ } else if (reply.status.outputGzipExists) {
+ text += "<br />" + _("Compressed cache file found.");
+ }
+ break;
+ case "statusRestarting":
+ case "statusForceReloading":
+ case "statusDownloading":
+ case "statusProcessing":
+ text += statusTable[reply.status.status] + "...";
+ break;
+ default:
+ text += statusTable[reply.status.status] + ".";
+ break;
+ }
+ } else {
+ text = _("Not installed or not found");
+ }
+ var statusText = E("div", {}, text);
+ var statusField = E("div", { class: "cbi-value-field" }, statusText);
+ var statusDiv = E("div", { class: "cbi-value" }, [
+ statusTitle,
+ statusField,
+ ]);
+
+ var warningsDiv = [];
+ if (reply.status.warnings && reply.status.warnings.length) {
+ var warningTable = {
+ warningExternalDnsmasqConfig: _(
+ "Use of external dnsmasq config file detected, please set '%s' option to '%s'"
+ ).format("dns", "dnsmasq.conf"),
+ warningMissingRecommendedPackages: _(
+ "Some recommended packages are missing"
+ ),
+ };
+ var warningsTitle = E(
+ "label",
+ { class: "cbi-value-title" },
+ _("Service Warnings")
+ );
+ var text = "";
+ reply.status.warnings.forEach((element) => {
+ text +=
+ warningTable[element.id].format(element.extra || " ") + "<br />";
+ });
+ var warningsText = E("div", {}, text);
+ var warningsField = E(
+ "div",
+ { class: "cbi-value-field" },
+ warningsText
+ );
+ warningsDiv = E("div", { class: "cbi-value" }, [
+ warningsTitle,
+ warningsField,
+ ]);
+ }
+
+ var errorsDiv = [];
+ if (reply.status.errors && reply.status.errors.length) {
+ var errorTable = {
+ errorConfigValidationFail: _(
+ "Config (%s) validation failure!"
+ ).format("/etc/config/" + pkg.Name),
+ errorServiceDisabled: _("%s is currently disabled").format(
+ pkg.Name
+ ),
+ errorNoDnsmasqIpset: _(
+ "The dnsmasq ipset support is enabled, but dnsmasq is either not installed or installed dnsmasq does not support ipset"
+ ),
+ errorNoIpset: _(
+ "The dnsmasq ipset support is enabled, but ipset is either not installed or installed ipset does not support '%s' type"
+ ).format("hash:net"),
+ errorNoDnsmasqNftset: _(
+ "The dnsmasq nft set support is enabled, but dnsmasq is either not installed or installed dnsmasq does not support nft set"
+ ),
+ errorNoNft: _(
+ "The dnsmasq nft sets support is enabled, but nft is not installed"
+ ),
+ errorNoWanGateway: _(
+ "The %s failed to discover WAN gateway"
+ ).format(pkg.Name),
+ errorOutputDirCreate: _("Failed to create directory for %s file"),
+ errorOutputFileCreate: _("Failed to create '%s' file").format(
+ outputFile
+ ),
+ errorFailDNSReload: _("Failed to restart/reload DNS resolver"),
+ errorSharedMemory: _("Failed to access shared memory"),
+ errorSorting: _("Failed to sort data file"),
+ errorOptimization: _("Failed to optimize data file"),
+ errorAllowListProcessing: _("Failed to process allow-list"),
+ errorDataFileFormatting: _("Failed to format data file"),
+ errorMovingDataFile: _(
+ "Failed to move temporary data file to '%s'"
+ ).format(outputFile),
+ errorCreatingCompressedCache: _(
+ "Failed to create compressed cache"
+ ),
+ errorRemovingTempFiles: _("Failed to remove temporary files"),
+ errorRestoreCompressedCache: _("Failed to unpack compressed cache"),
+ errorRestoreCache: _("Failed to move '%s' to '%s'").format(
+ outputCache,
+ outputFile
+ ),
+ errorOhSnap: _(
+ "Failed to create block-list or restart DNS resolver"
+ ),
+ errorStopping: _("Failed to stop %s").format(pkg.Name),
+ errorDNSReload: _("Failed to reload/restart DNS resolver"),
+ errorDownloadingConfigUpdate: _(
+ "Failed to download Config Update file"
+ ),
+ errorDownloadingList: _("Failed to download %s"),
+ errorParsingConfigUpdate: _("Failed to parse Config Update file"),
+ errorParsingList: _("Failed to parse"),
+ errorNoSSLSupport: _("No HTTPS/SSL support on device"),
+ errorCreatingDirectory: _(
+ "Failed to create output/cache/gzip file directory"
+ ),
+ };
+ var errorsTitle = E(
+ "label",
+ { class: "cbi-value-title" },
+ _("Service Errors")
+ );
+ var text = "";
+ reply.status.errors.forEach((element) => {
+ text +=
+ errorTable[element.id].format(element.extra || " ") + "<br />";
+ });
+ text += _("Errors encountered, please check the %sREADME%s!").format(
+ "<a href='" + pkg.URL + '" target="_blank">',
+ "</a><br />"
+ );
+ var errorsText = E("div", {}, text);
+ var errorsField = E("div", { class: "cbi-value-field" }, errorsText);
+ errorsDiv = E("div", { class: "cbi-value" }, [
+ errorsTitle,
+ errorsField,
+ ]);
+ }
+
+ var btn_gap = E("span", {}, "&#160;&#160;");
+ var btn_gap_long = E(
+ "span",
+ {},
+ "&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;"
+ );
+
+ var btn_start = E(
+ "button",
+ {
+ class: "btn cbi-button cbi-button-apply",
+ disabled: true,
+ click: function (ev) {
+ ui.showModal(null, [
+ E(
+ "p",
+ { class: "spinning" },
+ _("Starting %s service").format(pkg.Name)
+ ),
+ ]);
+ return RPC.setInitAction(pkg.Name, "start");
+ },
+ },
+ _("Start")
+ );
+
+ var btn_action = E(
+ "button",
+ {
+ class: "btn cbi-button cbi-button-apply",
+ disabled: true,
+ click: function (ev) {
+ ui.showModal(null, [
+ E(
+ "p",
+ { class: "spinning" },
+ _("Force re-downloading %s block lists").format(pkg.Name)
+ ),
+ ]);
+ return RPC.setInitAction(pkg.Name, "dl");
+ },
+ },
+ _("Force Re-Download")
+ );
+
+ var btn_stop = E(
+ "button",
+ {
+ class: "btn cbi-button cbi-button-reset",
+ disabled: true,
+ click: function (ev) {
+ ui.showModal(null, [
+ E(
+ "p",
+ { class: "spinning" },
+ _("Stopping %s service").format(pkg.Name)
+ ),
+ ]);
+ return RPC.setInitAction(pkg.Name, "stop");
+ },
+ },
+ _("Stop")
+ );
+
+ var btn_enable = E(
+ "button",
+ {
+ class: "btn cbi-button cbi-button-apply",
+ disabled: true,
+ click: function (ev) {
+ ui.showModal(null, [
+ E(
+ "p",
+ { class: "spinning" },
+ _("Enabling %s service").format(pkg.Name)
+ ),
+ ]);
+ return RPC.setInitAction(pkg.Name, "enable");
+ },
+ },
+ _("Enable")
+ );
+
+ var btn_disable = E(
+ "button",
+ {
+ class: "btn cbi-button cbi-button-reset",
+ disabled: true,
+ click: function (ev) {
+ ui.showModal(null, [
+ E(
+ "p",
+ { class: "spinning" },
+ _("Disabling %s service").format(pkg.Name)
+ ),
+ ]);
+ return RPC.setInitAction(pkg.Name, "disable");
+ },
+ },
+ _("Disable")
+ );
+
+ if (reply.status.enabled) {
+ btn_enable.disabled = true;
+ btn_disable.disabled = false;
+ switch (reply.status.status) {
+ case "statusSuccess":
+ btn_start.disabled = true;
+ btn_action.disabled = false;
+ btn_stop.disabled = false;
+ break;
+ case "statusStopped":
+ btn_start.disabled = false;
+ btn_action.disabled = true;
+ btn_stop.disabled = true;
+ break;
+ default:
+ btn_start.disabled = false;
+ btn_action.disabled = true;
+ btn_stop.disabled = false;
+ btn_enable.disabled = true;
+ btn_disable.disabled = true;
+ break;
+ }
+ } else {
+ btn_start.disabled = true;
+ btn_action.disabled = true;
+ btn_stop.disabled = true;
+ btn_enable.disabled = false;
+ btn_disable.disabled = true;
+ }
+
+ var buttonsDiv = [];
+ var buttonsTitle = E(
+ "label",
+ { class: "cbi-value-title" },
+ _("Service Control")
+ );
+ var buttonsText = E("div", {}, [
+ btn_start,
+ btn_gap,
+ btn_action,
+ btn_gap,
+ btn_stop,
+ btn_gap_long,
+ btn_enable,
+ btn_gap,
+ btn_disable,
+ ]);
+ var buttonsField = E("div", { class: "cbi-value-field" }, buttonsText);
+ if (reply.status.version) {
+ buttonsDiv = E("div", { class: "cbi-value" }, [
+ buttonsTitle,
+ buttonsField,
+ ]);
+ }
+
+ return E("div", {}, [
+ header,
+ statusDiv,
+ warningsDiv,
+ errorsDiv,
+ buttonsDiv,
+ ]);
+ }
+ );
+ },
+});
+
+RPC.on("setInitAction", function (reply) {
+ ui.hideModal();
+ location.reload();
+});
+
+return L.Class.extend({
+ status: status,
+ getFileUrlFilesizes: getFileUrlFilesizes,
+ getPlatformSupport: getPlatformSupport,
+});
diff --git a/applications/luci-app-adblock-fast/htdocs/luci-static/resources/view/adblock-fast/overview.js b/applications/luci-app-adblock-fast/htdocs/luci-static/resources/view/adblock-fast/overview.js
new file mode 100644
index 0000000000..92caf6b35d
--- /dev/null
+++ b/applications/luci-app-adblock-fast/htdocs/luci-static/resources/view/adblock-fast/overview.js
@@ -0,0 +1,385 @@
+// Copyright 2023 MOSSDeF, Stan Grishin <stangri@melmac.ca>
+// This code wouldn't have been possible without help from:
+// - [@stokito](https://github.com/stokito)
+// - [@vsviridov](https://github.com/vsviridov)
+
+"use strict";
+"require form";
+"require uci";
+"require view";
+"require adblock-fast.status as adb";
+
+var pkg = {
+ get Name() {
+ return "adblock-fast";
+ },
+ get URL() {
+ return "https://docs.openwrt.melmac.net/" + pkg.Name + "/";
+ },
+ humanFileSize: function (bytes, si = false, dp = 2) {
+ return `%${si ? 1000 : 1024}.${dp ?? 0}mB`.format(bytes);
+ },
+};
+
+return view.extend({
+ load: function () {
+ return Promise.all([
+ L.resolveDefault(adb.getFileUrlFilesizes(pkg.Name), {}),
+ L.resolveDefault(adb.getPlatformSupport(pkg.Name), {}),
+ uci.load(pkg.Name),
+ uci.load("dhcp"),
+ ]);
+ },
+
+ render: function (data) {
+ var reply = {
+ sizes: (data[0] && data[0][pkg.Name] && data[0][pkg.Name]["sizes"]) || [],
+ platform: (data[1] && data[1][pkg.Name]) || {
+ ipset_installed: false,
+ nft_installed: false,
+ dnsmasq_installed: false,
+ unbound_installed: false,
+ dnsmasq_ipset_support: false,
+ dnsmasq_nftset_support: false,
+ leds: [],
+ },
+ };
+ var status, m, s1, s2, s3, o;
+
+ status = new adb.status();
+ m = new form.Map(pkg.Name, _("AdBlock-Fast - Configuration"));
+ s1 = m.section(form.NamedSection, "config", pkg.Name);
+ s1.tab("tab_basic", _("Basic Configuration"));
+ s1.tab("tab_advanced", _("Advanced Configuration"));
+
+ var text = _(
+ "DNS resolution option, see the %sREADME%s for details."
+ ).format(
+ '<a href="' + pkg.URL + '#dns-resolver-option" target="_blank">',
+ "</a>"
+ );
+ if (!reply.platform.dnsmasq_installed) {
+ text +=
+ "<br />" +
+ _("Please note that %s is not supported on this system.").format(
+ "<i>dnsmasq.addnhosts</i>"
+ );
+ text +=
+ "<br />" +
+ _("Please note that %s is not supported on this system.").format(
+ "<i>dnsmasq.conf</i>"
+ );
+ text +=
+ "<br />" +
+ _("Please note that %s is not supported on this system.").format(
+ "<i>dnsmasq.ipset</i>"
+ );
+ text +=
+ "<br />" +
+ _("Please note that %s is not supported on this system.").format(
+ "<i>dnsmasq.servers</i>"
+ );
+ } else {
+ if (!reply.platform.dnsmasq_ipset_support) {
+ text +=
+ "<br />" +
+ _("Please note that %s is not supported on this system.").format(
+ "<i>dnsmasq.ipset</i>"
+ );
+ }
+ if (!reply.platform.dnsmasq_nftset_support) {
+ text +=
+ "<br />" +
+ _("Please note that %s is not supported on this system.").format(
+ "<i>dnsmasq.nftset</i>"
+ );
+ }
+ }
+ if (!reply.platform.unbound_installed) {
+ text =
+ text +
+ "<br />" +
+ _("Please note that %s is not supported on this system.").format(
+ "<i>unbound.adb_list</i>"
+ );
+ }
+
+ o = s1.taboption(
+ "tab_basic",
+ form.ListValue,
+ "dns",
+ _("DNS Service"),
+ text
+ );
+ if (reply.platform.dnsmasq_installed) {
+ o.value("dnsmasq.addnhosts", _("dnsmasq additional hosts"));
+ o.value("dnsmasq.conf", _("dnsmasq config"));
+ if (reply.platform.dnsmasq_ipset_support) {
+ o.value("dnsmasq.ipset", _("dnsmasq ipset"));
+ }
+ if (reply.platform.dnsmasq_nftset_support) {
+ o.value("dnsmasq.nftset", _("dnsmasq nft set"));
+ }
+ o.value("dnsmasq.servers", _("dnsmasq servers file"));
+ }
+ if (reply.platform.unbound_installed) {
+ o.value("unbound.adb_list", _("unbound adblock list"));
+ }
+ o.default = ("dnsmasq.servers", _("dnsmasq servers file"));
+
+ o = s1.taboption(
+ "tab_basic",
+ form.Value,
+ "dnsmasq_config_file_url",
+ _("Dnsmasq Config File URL"),
+ _(
+ "URL to the external dnsmasq config file, see the %sREADME%s for details."
+ ).format(
+ '<a href="' + pkg.URL + '#dnsmasq_config_file_url" target="_blank">',
+ "</a>"
+ )
+ );
+ o.depends("dns", "dnsmasq.conf");
+
+ o = s1.taboption(
+ "tab_basic",
+ form.ListValue,
+ "dnsmasq_instance",
+ _("Use AdBlocking on the dnsmasq instance(s)"),
+ _(
+ "You can limit the AdBlocking to a specific dnsmasq instance(s) (%smore information%s)."
+ ).format(
+ '<a href="' + pkg.URL + "#dnsmasq_instance" + '" target="_blank">',
+ "</a>"
+ )
+ );
+ o.value("*", _("AdBlock on all instances"));
+ var sections = uci.sections("dhcp", "dnsmasq");
+ sections.forEach((element) => {
+ var description;
+ var key;
+ if (element[".name"] === uci.resolveSID("dhcp", element[".name"])) {
+ key = element[".index"];
+ description = "dnsmasq[" + element[".index"] + "]";
+ } else {
+ key = element[".name"];
+ description = element[".name"];
+ }
+ o.value(key, _("AdBlock on %s only").format(description));
+ });
+ o.value("-", _("No AdBlock on dnsmasq"));
+ o.default = "*";
+ o.depends("dns", "dnsmasq.addnhosts");
+ o.depends("dns", "dnsmasq.servers");
+ o.retain = true;
+
+ o = s1.taboption(
+ "tab_basic",
+ form.ListValue,
+ "force_dns",
+ _("Force Router DNS"),
+ _("Forces Router DNS use on local devices, also known as DNS Hijacking.")
+ );
+ o.value("0", _("Let local devices use their own DNS servers if set"));
+ o.value("1", _("Force Router DNS server to all local devices"));
+ o.default = ("1", _("Force Router DNS server to all local devices"));
+
+ o = s1.taboption(
+ "tab_basic",
+ form.ListValue,
+ "verbosity",
+ _("Output Verbosity Setting"),
+ _("Controls system log and console output verbosity.")
+ );
+ o.value("0", _("Suppress output"));
+ o.value("1", _("Some output"));
+ o.value("2", _("Verbose output"));
+ o.default = ("2", _("Verbose output"));
+
+ if (reply.platform.leds.length) {
+ o = s1.taboption(
+ "tab_basic",
+ form.ListValue,
+ "led",
+ _("LED to indicate status"),
+ _(
+ "Pick the LED not already used in %sSystem LED Configuration%s."
+ ).format('<a href="' + L.url("admin", "system", "leds") + '">', "</a>")
+ );
+ o.value("", _("none"));
+ reply.platform.leds.forEach((element) => {
+ o.value(element);
+ });
+ }
+ o = s1.taboption(
+ "tab_advanced",
+ form.ListValue,
+ "config_update_enabled",
+ _("Automatic Config Update"),
+ _("Perform config update before downloading the block/allow-lists.")
+ );
+ o.value("0", _("Disable"));
+ o.value("1", _("Enable"));
+ o.default = ("0", _("Disable"));
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.ListValue,
+ "ipv6_enabled",
+ _("IPv6 Support"),
+ _("Add IPv6 entries to block-list.")
+ );
+ o.value("", _("Do not add IPv6 entries"));
+ o.value("1", _("Add IPv6 entries"));
+ o.depends("dns", "dnsmasq.addnhosts");
+ o.depends("dns", "dnsmasq.nftset");
+ o.default = ("", _("Do not add IPv6 entries"));
+ o.rmempty = true;
+ o.retain = true;
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.Value,
+ "download_timeout",
+ _("Download time-out (in seconds)"),
+ _("Stop the download if it is stalled for set number of seconds.")
+ );
+ o.default = "20";
+ o.datatype = "range(1,60)";
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.Value,
+ "curl_max_file_size",
+ _("Curl maximum file size (in bytes)"),
+ _(
+ "If curl is installed and detected, it would not download files bigger than this."
+ )
+ );
+ o.default = "";
+ o.datatype = "uinteger";
+ o.rmempty = true;
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.Value,
+ "curl_retry",
+ _("Curl download retry"),
+ _(
+ "If curl is installed and detected, it would retry download this many times on timeout/fail."
+ )
+ );
+ o.default = "3";
+ o.datatype = "range(0,30)";
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.ListValue,
+ "parallel_downloads",
+ _("Simultaneous processing"),
+ _(
+ "Launch all lists downloads and processing simultaneously, reducing service start time."
+ )
+ );
+ o.value("0", _("Do not use simultaneous processing"));
+ o.value("1", _("Use simultaneous processing"));
+ o.default = ("1", _("Use simultaneous processing"));
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.ListValue,
+ "compressed_cache",
+ _("Store compressed cache file on router"),
+ _(
+ "Attempt to create a compressed cache of block-list in the persistent memory."
+ )
+ );
+ o.value("0", _("Do not store compressed cache"));
+ o.value("1", _("Store compressed cache"));
+ o.default = ("0", _("Do not store compressed cache"));
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.Value,
+ "compressed_cache_dir",
+ _("Directory for compressed cache file"),
+ _(
+ "Directory for compressed cache file of block-list in the persistent memory."
+ )
+ );
+ o.datatype = "string";
+ o.rmempty = true;
+ o.default = "/etc";
+ o.depends("compressed_cache", "1");
+ o.retain = true;
+
+ o = s1.taboption(
+ "tab_advanced",
+ form.ListValue,
+ "debug",
+ _("Enable Debugging"),
+ _("Enables debug output to /tmp/adblock-fast.log.")
+ );
+ o.value("0", _("Disable Debugging"));
+ o.value("1", _("Enable Debugging"));
+ o.default = ("0", _("Disable Debugging"));
+
+ s2 = m.section(
+ form.NamedSection,
+ "config",
+ "adblock-fast",
+ _("AdBlock-Fast - Allowed and Blocked Domains")
+ );
+ o.addremove = true;
+ o.rmempty = true;
+ o = s2.option(
+ form.DynamicList,
+ "allowed_domain",
+ _("Allowed Domains"),
+ _("Individual domains to be allowed.")
+ );
+
+ o.addremove = true;
+ o = s2.option(
+ form.DynamicList,
+ "blocked_domain",
+ _("Blocked Domains"),
+ _("Individual domains to be blocked.")
+ );
+ o.addremove = true;
+
+ s3 = m.section(
+ form.GridSection,
+ "file_url",
+ _("AdBlock-Fast - Allowed and Blocked Lists URLs"),
+ _("URLs to file(s) containing lists to be allowed or blocked.")
+ );
+ s3.rowcolors = true;
+ s3.sortable = true;
+ s3.anonymous = true;
+ s3.addremove = true;
+ o = s3.option(form.DummyValue, "_size", "Size");
+ o.modalonly = false;
+ o.cfgvalue = function (section_id) {
+ let url = uci.get(pkg.Name, section_id, "url");
+ let ret = _("Unknown");
+ reply.sizes.forEach((element) => {
+ if (element.url === url) {
+ ret = element.size === 0 ? ret : pkg.humanFileSize(element.size);
+ }
+ });
+ return _("Size: %s").format(ret);
+ };
+ o = s3.option(form.Flag, "enabled", _("Enable"));
+ o.editable = true;
+ o.default = "1";
+ o = s3.option(form.ListValue, "action", _("Action"));
+ o.value("allow", _("Allow"));
+ o.value("block", _("Block"));
+ o.default = "block";
+ o = s3.option(form.Value, "url", _("URL"));
+ o.optional = false;
+
+ return Promise.all([status.render(), m.render()]);
+ },
+});