From: Dirk Brenken Date: Sun, 18 Jan 2026 22:39:39 +0000 (+0100) Subject: luci-app-adblock: sync with adblock 4.5.0-1 X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=b72dad0a00f432a31dfc930d5452cf3e62a8e7e2;p=project%2Fluci.git luci-app-adblock: sync with adblock 4.5.0-1 Signed-off-by: Dirk Brenken --- diff --git a/applications/luci-app-adblock/Makefile b/applications/luci-app-adblock/Makefile index 21d0f5cf96..516c404e7a 100644 --- a/applications/luci-app-adblock/Makefile +++ b/applications/luci-app-adblock/Makefile @@ -1,4 +1,4 @@ -# Copyright 2017-2025 Dirk Brenken (dev@brenken.org) +# Copyright 2017-2026 Dirk Brenken (dev@brenken.org) # This is free software, licensed under the Apache License, Version 2.0 include $(TOPDIR)/rules.mk @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for Adblock LUCI_DEPENDS:=+luci-base +adblock -PKG_VERSION:=4.4.5 +PKG_VERSION:=4.5.0 PKG_RELEASE:=1 PKG_LICENSE:=Apache-2.0 PKG_MAINTAINER:=Dirk Brenken diff --git a/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/feeds.js b/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/feeds.js index 06c5fe0945..13d3c6eeeb 100644 --- a/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/feeds.js +++ b/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/feeds.js @@ -117,49 +117,50 @@ function handleEdit(ev) { return ui.addNotification(null, E('p', _('Invalid input values, unable to save modifications.')), 'error'); } } - let sumSubElements = [], exportJson; + /* + gather all input data + */ + let sumSubElements = []; const nodeKeys = document.querySelectorAll('[id^="widget.cbid.json"][id$="name"]'); - for (let i = 0; i < nodeKeys.length; i++) { - let subElements = {}; - const elements = document.querySelectorAll('[id^="widget.cbid.json.' + nodeKeys[i].id.split('.')[3] + '\."], \ - [id^="cbid.json.' + nodeKeys[i].id.split('.')[3] + '\.rule"]'); - for (const element of elements) { - let key; - const value = element.value || ""; - const parts = element.id.split('.'); - if (parts.length === 5) { - key = element.id.split('.')[4]; - } else if (parts.length === 4) { - key = element.id.split('.')[3]; - } - if (!key || value === "") { - continue; - } - switch (key) { - case 'url': - subElements.url = value; - break; - case 'rule': - subElements.rule = value; - break; - case 'size': - subElements.size = value; - break; - case 'descr': - subElements.descr = value; - break; + for (const keyNode of nodeKeys) { + const keyValue = keyNode.value?.trim(); + if (!keyValue) continue; + const idParts = keyNode.id.split("."); + const ruleId = idParts[3]; + if (!ruleId) continue; + const selector = + `[id^="widget.cbid.json.${ruleId}."], ` + + `[id^="cbid.json.${ruleId}.rule"]`; + const elements = document.querySelectorAll(selector); + const sub = {}; + for (const el of elements) { + const parts = el.id.split("."); + const key = parts[parts.length - 1]; + const value = el.value?.trim(); + if (!value) continue; + if (["url", "rule", "size", "descr"].includes(key)) { + sub[key] = value; } } - if (nodeKeys[i].value !== "" && subElements.descr !== "") { - sumSubElements.push(nodeKeys[i].value, subElements); + if (sub.descr) { + sumSubElements.push(keyValue, sub); } } - if (sumSubElements.length > 0) { - exportJson = JSON.stringify(sumSubElements).replace(/^\[/, '{\n').replace(/\}]$/, '\n\t}\n}\n').replace(/,{"/g, ':{\n\t"').replace(/"},"/g, '"\n\t},\n"').replace(/","/g, '",\n\t"'); + /* + construct json object + */ + let exportObj = {}; + for (let i = 0; i < sumSubElements.length; i += 2) { + const key = sumSubElements[i]; + const value = sumSubElements[i + 1]; + exportObj[key] = value; } - return fs.write('/etc/adblock/adblock.custom.feeds', exportJson).then(function () { - location.reload(); - }); + const exportJson = JSON.stringify(exportObj, null, 4); + /* + save to file and reload + */ + return fs.write('/etc/adblock/adblock.custom.feeds', exportJson) + .then(() => location.reload()); } return view.extend({ diff --git a/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/overview.js b/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/overview.js index ae7effc6f0..c87eb38a56 100644 --- a/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/overview.js +++ b/applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/overview.js @@ -85,10 +85,14 @@ return view.extend({ } if (status && info) { status.textContent = `${info.adblock_status || '-'} (frontend: ${info.frontend_ver || '-'} / backend: ${info.backend_ver || '-'})`; - if (info.adblock_status === "running") { + if (info.adblock_status === "processing") { if (!status.classList.contains("spinning")) { status.classList.add("spinning"); } + buttons.forEach(function (btn) { + btn.disabled = true; + btn.blur(); + }) } else { if (status.classList.contains("spinning")) { buttons.forEach(function (btn) { @@ -120,7 +124,7 @@ return view.extend({ } if (info) { setText('domains', info.blocked_domains); - setText('feeds', info.active_feeds?.join(', ')); + setText('feeds', info.active_feeds?.join(' ')); setText('backend', info.dns_backend); setText('ifaces', info.run_ifaces); setText('dirs', info.run_directories); @@ -185,6 +189,7 @@ return view.extend({ s.addremove = false; s.tab('general', _('General Settings')); s.tab('additional', _('Additional Settings')); + s.tab('firewall', _('Firewall Settings')); s.tab('adv_dns', _('Advanced DNS Settings')); s.tab('adv_report', _('Advanced Report Settings')); s.tab('adv_email', _('Advanced E-Mail Settings')); @@ -211,25 +216,6 @@ return view.extend({ o.datatype = 'range(1,300)'; o.rmempty = true; - o = s.taboption('general', form.Flag, 'adb_dnsforce', _('Force Local DNS'), _('Redirect all local DNS queries from specified LAN zones to the local DNS resolver, applies to UDP and TCP protocol.')); - o.rmempty = false; - - o = s.taboption('general', widgets.ZoneSelect, 'adb_zonelist', _('Forced Zones'), _('Firewall LAN source zones that should be forced locally.')); - o.depends('adb_dnsforce', '1'); - o.multiple = true; - o.nocreate = true; - o.rmempty = true; - - o = s.taboption('general', form.DynamicList, 'adb_portlist', _('Forced Ports'), _('Firewall ports that should be forced locally.')); - o.depends('adb_dnsforce', '1'); - o.multiple = true; - o.nocreate = false; - o.datatype = 'port'; - o.value('53'); - o.value('853'); - o.value('5353'); - o.rmempty = true; - o = s.taboption('general', form.Flag, 'adb_tld', _('TLD Compression'), _('The top level domain compression removes thousands of needless host entries from the final DNS blocklist.')); o.default = 1 o.rmempty = true; @@ -303,6 +289,145 @@ return view.extend({ o.default = 0 o.rmempty = true; + /* + firewall settings tab + */ + o = s.taboption('firewall', form.DummyValue, '_sub'); + o.rawhtml = true; + o.default = '' + _('Changes on this tab needs an adblock service restart to take effect.') + '' + + '
' + + '' + _('External Unfiltered DNS Policy (MAC-/Interface‑based DNS bypass)') + ''; + + o = s.taboption('firewall', form.Flag, 'adb_nftallow', _('Enable Unfiltered DNS Routing'), _('Routes selected MACs or interfaces to an unfiltered external DNS resolver, bypassing local adblock.')); + o.rmempty = false; + + o = s.taboption('firewall', form.DynamicList, 'adb_nftmacallow', _('MAC DNS Filter Targets'), _('Devices with listed MAC addresses will always use the configured unfiltered DNS server.')); + o.depends('adb_nftallow', '1'); + o.datatype = 'macaddr'; + o.placeholder = '00:11:22:33:44:55'; + o.multiple = true; + o.optional = true; + o.rmempty = true; + + o = s.taboption('firewall', widgets.DeviceSelect, 'adb_nftdevallow', _('Interface DNS Filter Targets'), _('Entire interfaces or VLANs will be routed to the unfiltered DNS server.')); + o.depends('adb_nftallow', '1'); + o.multiple = true; + o.nocreate = true; + o.optional = true; + o.rmempty = true; + + o = s.taboption('firewall', form.Value, 'adb_allowdnsv4', _('IPv4 DNS Resolver'), _('IPv4 DNS resolver applied to MACs and interfaces using the unfiltered DNS policy.')); + o.depends('adb_nftallow', '1'); + o.datatype = 'ip4addr("nomask")'; + o.value('86.54.11.100', _('DNS4EU (unfiltered)')); + o.value('94.140.14.140', _('AdGuard (unfiltered)')); + o.value('76.76.2.0', _('Control D (unfiltered)')); + o.value('1.1.1.1', _('Cloudflare (unfiltered)')); + o.value('9.9.9.10', _('Quad9 (unfiltered)')); + o.value('185.150.99.255', _('Digitale Gesellschaft (unfiltered)')); + o.default = '86.54.11.100'; + o.rmempty = true; + + o = s.taboption('firewall', form.Value, 'adb_allowdnsv6', _('IPv6 DNS Resolver'), _('IPv6 DNS resolver applied to MACs and interfaces using the unfiltered DNS policy.')); + o.depends('adb_nftallow', '1'); + o.datatype = 'ip6addr("nomask")'; + o.value('2a13:1001::86:54:11:100', _('DNS4EU (unfiltered)')); + o.value('2a10:50c0::1:ff', _('AdGuard (unfiltered)')); + o.value('2606:1a40::', _('Control D (unfiltered)')); + o.value('2606:4700:4700::1111', _('Cloudflare (unfiltered)')); + o.value('2620:fe::10', _('Quad9 (unfiltered)')); + o.value('2a07:6b47:6b47::255', _('Digitale Gesellschaft (unfiltered)')); + o.default = '2a13:1001::86:54:11:100'; + o.rmempty = true; + + o = s.taboption('firewall', form.DummyValue, '_sub'); + o.rawhtml = true; + o.default = '
' + _('External Filtered DNS Policy (MAC-/Interface‑based DNS bypass)') + ''; + + o = s.taboption('firewall', form.Flag, 'adb_nftblock', _('Enable Filtered DNS Routing'), _('Routes selected MACs or interfaces to a filtered external DNS resolver, bypassing local adblock.')); + o.rmempty = false; + + o = s.taboption('firewall', form.DynamicList, 'adb_nftmacblock', _('MAC DNS Filter Targets'), _('Devices with listed MAC addresses will always use the configured filtered DNS server.')); + o.depends('adb_nftblock', '1'); + o.datatype = 'macaddr'; + o.placeholder = '00:11:22:33:44:55'; + o.multiple = true; + o.optional = true; + o.rmempty = true; + + o = s.taboption('firewall', widgets.DeviceSelect, 'adb_nftdevblock', _('Interface DNS Filter Targets'), _('Entire interfaces or VLANs will be routed to the filtered DNS server.')); + o.depends('adb_nftblock', '1'); + o.multiple = true; + o.nocreate = true; + o.optional = true; + o.rmempty = true; + + o = s.taboption('firewall', form.Value, 'adb_blockdnsv4', _('IPv4 DNS Resolver'), _('IPv4 DNS resolver applied to MACs and interfaces using the filtered DNS policy.')); + o.depends('adb_nftblock', '1'); + o.datatype = 'ip4addr("nomask")'; + o.value('86.54.11.1', _('DNS4EU (protective)')); + o.value('86.54.11.12', _('DNS4EU (protective+family)')); + o.value('86.54.11.13', _('DNS4EU (protective+adblock)')); + o.value('86.54.11.11', _('DNS4EU (protective+family+adblock)')); + o.value('176.9.93.198', _('dnsforge (normal)')); + o.value('49.12.43.208', _('dnsforge (clean)')); + o.value('49.12.222.213', _('dnsforge (hard)')); + o.value('94.140.14.14', _('AdGuard (default)')); + o.value('94.140.14.15', _('AdGuard (family)')); + o.value('76.76.10.0', _('Control D (security)')); + o.value('76.76.10.10', _('Control D (family)')); + o.value('76.76.10.11', _('Control D (adblock)')); + o.value('1.1.1.2', _('Cloudflare (malware)')); + o.value('1.1.1.3', _('Cloudflare (malware+family)')); + o.value('9.9.9.9', _('Quad9 (malware)')); + o.default = '86.54.11.13'; + o.rmempty = true; + + o = s.taboption('firewall', form.Value, 'adb_blockdnsv6', _('IPv6 DNS Resolver'), _('IPv6 DNS resolver applied to MACs and interfaces using the filtered DNS policy.')); + o.depends('adb_nftblock', '1'); + o.datatype = 'ip6addr("nomask")'; + o.value('2a13:1001::86:54:11:1', _('DNS4EU (protective)')); + o.value('2a13:1001::86:54:11:12', _('DNS4EU (protective+family)')); + o.value('2a13:1001::86:54:11:13', _('DNS4EU (protective+adblock)')); + o.value('2a13:1001::86:54:11:11', _('DNS4EU (protective+family+adblock)')); + o.value('2a01:4f8:151:34aa::198', _('dnsforge (normal)')); + o.value('2a01:4f8:c012:ed89::208', _('dnsforge (clean)')); + o.value('2a01:4f8:c17:2c61::213', _('dnsforge (hard)')); + o.value('2a10:50c0::ad1:ff', _('AdGuard (default)')); + o.value('2a10:50c0::bad1:ff', _('AdGuard (family)')); + o.value('2606:1a40:1::', _('Control D (security)')); + o.value('2606:1a40:1::1', _('Control D (family)')); + o.value('2606:1a40:1::2', _('Control D (adblock)')); + o.value('2606:4700:4700::1112', _('Cloudflare (malware)')); + o.value('2606:4700:4700::1113', _('Cloudflare (malware+family)')); + o.value('2620:fe::fe', _('Quad9 (malware)')); + o.default = '2a13:1001::86:54:11:13'; + o.rmempty = true; + + o = s.taboption('firewall', form.DummyValue, '_sub'); + o.rawhtml = true; + o.default = '
' + _('Local DNS Enforcement') + ''; + + o = s.taboption('firewall', form.Flag, 'adb_nftforce', _('Force Local DNS'), _('Redirect all local DNS queries from specified LAN zones to the local DNS resolver, applies to UDP and TCP protocol.')); + o.rmempty = false; + + o = s.taboption('firewall', widgets.DeviceSelect, 'adb_nftdevforce', _('Forced Devices/VLANs'), _('Firewall LAN Devices/VLANs that should be forced locally.')); + o.depends('adb_nftforce', '1'); + o.multiple = true; + o.nocreate = true; + o.optional = true; + o.rmempty = true; + + o = s.taboption('firewall', form.DynamicList, 'adb_nftportforce', _('Forced Ports'), _('Firewall ports that should be forced locally.')); + o.depends('adb_nftforce', '1'); + o.multiple = true; + o.nocreate = false; + o.datatype = 'port'; + o.value('53'); + o.value('853'); + o.value('5353'); + o.rmempty = true; + /* advanced dns settings tab */ @@ -335,11 +460,11 @@ return view.extend({ o = s.taboption('adv_dns', form.Value, 'adb_dnsdir', _('DNS Directory'), _('Overwrite the default target directory for the generated blocklist.')); o.rmempty = true; - o = s.taboption('adv_dns', form.ListValue, 'adb_dnsinstance', _('DNS Instance'), _('Set the dns backend instance used by adblock.')); + o = s.taboption('adv_dns', form.Value, 'adb_dnsinstance', _('DNS Instance'), _('Set the dns backend instance used by adblock.')); o.depends('adb_dns', 'dnsmasq'); - o.value('0', _('First instance (default)')); + o.value('0', _('First instance')); o.value('1', _('Second instance')); - o.value('2', _('Third instance')); + o.default = '0'; o.optional = true; o.rmempty = true; @@ -348,26 +473,7 @@ return view.extend({ o.datatype = 'range(5,60)'; o.rmempty = true; - o = s.taboption('adv_dns', form.DynamicList, 'adb_denyip', _('Block Local Client IPs'), _('Block all requests of certain DNS clients based on their IP address (RPZ-CLIENT-IP).')); - o.datatype = 'or(ip4addr("nomask"),ip6addr("nomask"))'; - o.depends('adb_dns', 'bind'); - o.optional = true; - o.rmempty = true; - - o = s.taboption('adv_dns', form.DynamicList, 'adb_allowip', _('Allow Local Client IPs'), _('Allow all requests of certain DNS clients based on their IP address (RPZ-CLIENT-IP).')); - o.datatype = 'or(ip4addr("nomask"),ip6addr("nomask"))'; - o.depends('adb_dns', 'bind'); - o.optional = true; - o.rmempty = true; - - o = s.taboption('adv_dns', form.Flag, 'adb_jail', _('Jail Blocklist'), _('Builds an additional restrictive DNS blocklist to block access to all domains except those listed in the allowlist. \ - You can use this restrictive blocklist e.g. for guest wifi or kidsafe configurations.')); - o.rmempty = true; - - o = s.taboption('adv_dns', form.Value, 'adb_jaildir', _('Jail Directory'), _('Target directory for the generated jail blocklist. \ - If this directory points to your DNS directory, the jail blocklist replaces your default blocklist.')); - o.depends('adb_jail', '1'); - o.placeholder = '/tmp'; + o = s.taboption('adv_dns', form.Flag, 'adb_jail', _('Jail Mode'), _('Only domains on the allowlist are permitted, all other DNS requests are rejected.')); o.rmempty = true; /* @@ -403,7 +509,7 @@ return view.extend({ o = s.taboption('adv_report', form.Flag, 'adb_represolve', _('Resolve IPs'), _('Resolve reporting IP addresses by using reverse DNS (PTR) lookups.')); o.rmempty = true; - o = s.taboption('adv_report', form.Flag, 'adb_map', _('GeoIP Map'), _('Enable a GeoIP map that shows the geographical location of the blocked domains. This requires external requests to get the map tiles and geolocation data.')); + o = s.taboption('adv_report', form.Flag, 'adb_map', _('GeoIP Map'), _('Enable a GeoIP map that shows the geographical location of the blocked domains.')); o.optional = true; o.rmempty = true;