luci-app-adblock: sync with adblock 4.4.4-1
authorDirk Brenken <dev@brenken.org>
Fri, 21 Nov 2025 18:05:22 +0000 (19:05 +0100)
committerDirk Brenken <dev@brenken.org>
Fri, 21 Nov 2025 18:05:36 +0000 (19:05 +0100)
Signed-off-by: Dirk Brenken <dev@brenken.org>
applications/luci-app-adblock/Makefile
applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/allowlist.js
applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/blocklist.js
applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/dnsreport.js
applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/logtemplate.js
applications/luci-app-adblock/htdocs/luci-static/resources/view/adblock/overview.js
applications/luci-app-adblock/root/usr/share/rpcd/acl.d/luci-app-adblock.json

index d67ad27c55847bef65e1da65cbffbc9941e7a45d..bd66bdfd7c1483a05cf96abb6ff37230ffd4694a 100644 (file)
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
 LUCI_TITLE:=LuCI support for Adblock
 LUCI_DEPENDS:=+luci-base +adblock
 
-PKG_VERSION:=4.4.3
+PKG_VERSION:=4.4.4
 PKG_RELEASE:=1
 PKG_LICENSE:=Apache-2.0
 PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
index e6374e3f744c44f97749ba9b9db5c29bc3ab565b..a2e08e267df51c41fcd18d1cc7b3e47d1b93f60f 100644 (file)
@@ -3,8 +3,12 @@
 'require fs';
 'require ui';
 
-let localFile = '/etc/adblock/adblock.allowlist';
-let notMsg, errMsg;
+const localFile = '/etc/adblock/adblock.allowlist';
+let notMsg = false, errMsg = false;
+
+const resetScroll = () => {
+       document.body.scrollTop = document.documentElement.scrollTop = 0;
+};
 
 return view.extend({
        load: function () {
@@ -21,7 +25,7 @@ return view.extend({
        },
        render: function (allowlist) {
                if (allowlist[0] && allowlist[0].size >= 100000) {
-                       document.body.scrollTop = document.documentElement.scrollTop = 0;
+                       resetScroll();
                        ui.addNotification(null, E('p', _('The allowlist is too big, unable to save modifications.')), 'error');
                }
                return E('div', { 'class': 'cbi-section cbi-section-descr' }, [
@@ -36,22 +40,22 @@ return view.extend({
                ]);
        },
        handleSave: function (ev) {
-               let value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n')) + '\n';
-               return fs.write(localFile, value)
-                       .then(function () {
-                               document.querySelector('textarea').value = value;
-                               document.body.scrollTop = document.documentElement.scrollTop = 0;
-                               if (!notMsg) {
-                                       ui.addNotification(null, E('p', _('Allowlist modifications have been saved, reload adblock that changes take effect.')), 'info');
-                                       notMsg = true;
-                               }
-                       }).catch(function (e) {
-                               document.body.scrollTop = document.documentElement.scrollTop = 0;
-                               if (!errMsg) {
-                                       ui.addNotification(null, E('p', _('Unable to save modifications: %s').format(e.message)), 'error');
-                                       errMsg = true;
-                               }
-                       });
+               let value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/[^a-z0-9\.\-# \r\n]/g, '').replace(/\r\n?/g, '\n'));
+               return fs.write(localFile, value + "\n")
+               .then(function () {
+                       document.querySelector('textarea').value = value;
+                       resetScroll();
+                       if (!notMsg) {
+                               ui.addNotification(null, E('p', _('Allowlist modifications have been saved, reload adblock that changes take effect.')), 'info');
+                               notMsg = true;
+                       }
+               }).catch(function (e) {
+                       resetScroll();
+                       if (!errMsg) {
+                               ui.addNotification(null, E('p', _('Unable to save modifications: %s').format(e.message)), 'error');
+                               errMsg = true;
+                       }
+               });
        },
        handleSaveApply: null,
        handleReset: null
index 9fec0895afe2939ee8719e66347050ae28361511..46542bcad5093ccecc2d0ca4ac9fcb8316c494a8 100644 (file)
@@ -3,8 +3,12 @@
 'require fs';
 'require ui';
 
-let localFile = '/etc/adblock/adblock.blocklist';
-let notMsg, errMsg;
+const localFile = '/etc/adblock/adblock.blocklist';
+let notMsg = false, errMsg = false;
+
+const resetScroll = () => {
+       document.body.scrollTop = document.documentElement.scrollTop = 0;
+};
 
 return view.extend({
        load: function () {
@@ -21,14 +25,14 @@ return view.extend({
        },
        render: function (blocklist) {
                if (blocklist[0] && blocklist[0].size >= 100000) {
-                       document.body.scrollTop = document.documentElement.scrollTop = 0;
+                       resetScroll();
                        ui.addNotification(null, E('p', _('The blocklist is too big, unable to save modifications.')), 'error');
                }
                return E('div', { 'class': 'cbi-section cbi-section-descr' }, [
                        E('p', _('This is the local adblock blocklist to always-block certain domains.<br /> \
                                <em><b>Please note:</b></em> add only one domain per line. Comments introduced with \'#\' are allowed - ip addresses, wildcards and regex are not.')),
                        E('textarea', {
-                               'style': 'width: 100% !important; padding: 5px; font-family: monospace; margin-top: .4em',
+                               'style': 'min-height: 500px; max-height: 90vh; width: 100%; padding: 5px; font-family: monospace; resize: vertical;',
                                'spellcheck': 'false',
                                'wrap': 'off',
                                'rows': 25
@@ -36,22 +40,22 @@ return view.extend({
                ]);
        },
        handleSave: function (ev) {
-               let value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n')) + '\n';
-               return fs.write(localFile, value)
-                       .then(function () {
-                               document.querySelector('textarea').value = value;
-                               document.body.scrollTop = document.documentElement.scrollTop = 0;
-                               if (!notMsg) {
-                                       ui.addNotification(null, E('p', _('Blocklist modifications have been saved, reload adblock that changes take effect.')), 'info');
-                                       notMsg = true;
-                               }
-                       }).catch(function (e) {
-                               document.body.scrollTop = document.documentElement.scrollTop = 0;
-                               if (!errMsg) {
-                                       ui.addNotification(null, E('p', _('Unable to save modifications: %s').format(e.message)), 'error');
-                                       errMsg = true;
-                               }
-                       });
+               let value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/[^a-z0-9\.\-# \r\n]/g, '').replace(/\r\n?/g, '\n'));
+               return fs.write(localFile, value + "\n")
+               .then(function () {
+                       document.querySelector('textarea').value = value;
+                       resetScroll();
+                       if (!notMsg) {
+                               ui.addNotification(null, E('p', _('Blocklist modifications have been saved, reload adblock that changes take effect.')), 'info');
+                               notMsg = true;
+                       }
+               }).catch(function (e) {
+                       resetScroll();
+                       if (!errMsg) {
+                               ui.addNotification(null, E('p', _('Unable to save modifications: %s').format(e.message)), 'error');
+                               errMsg = true;
+                       }
+               });
        },
        handleSaveApply: null,
        handleReset: null
index 59d4e442d85b94cbc7c436372e01a96bf0c67d45..c41a4907000d1097df77deb2f4fddcd5cd209bda 100644 (file)
@@ -4,6 +4,8 @@
 'require ui';
 'require uci';
 
+var notMsg = false, errMsg = false;
+
 /*
        button handling
 */
@@ -32,7 +34,10 @@ function handleAction(ev) {
                                                                if (res.search(pattern) === -1) {
                                                                        var blocklist = res + domain + '\n';
                                                                        fs.write('/etc/adblock/adblock.blocklist', blocklist);
-                                                                       ui.addNotification(null, E('p', _('Blocklist modifications have been saved, reload adblock that changes take effect.')), 'info');
+                                                                       if (!notMsg) {
+                                                                               notMsg = true;
+                                                                               ui.addNotification(null, E('p', _('Blocklist modifications have been saved, reload adblock that changes take effect.')), 'info');
+                                                                       }
                                                                }
                                                                ui.hideModal();
                                                        });
@@ -67,7 +72,10 @@ function handleAction(ev) {
                                                                if (res.search(pattern) === -1) {
                                                                        var allowlist = res + domain + '\n';
                                                                        fs.write('/etc/adblock/adblock.allowlist', allowlist);
-                                                                       ui.addNotification(null, E('p', _('Allowlist modifications have been saved, reload adblock that changes take effect.')), 'info');
+                                                                       if (!notMsg) {
+                                                                               notMsg = true;
+                                                                               ui.addNotification(null, E('p', _('Allowlist modifications have been saved, reload adblock that changes take effect.')), 'info');
+                                                                       }
                                                                }
                                                                ui.hideModal();
                                                        });
@@ -112,13 +120,13 @@ function handleAction(ev) {
                                E('button', {
                                        'class': 'btn cbi-button-action',
                                        'click': ui.createHandlerFn(this, function (ev) {
-                                               var domain = document.getElementById('search').value.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g, '');
+                                               const domain = document.getElementById('search').value.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g, '');
                                                if (domain) {
                                                        document.getElementById('run').classList.add("spinning");
                                                        document.getElementById('search').value = domain;
                                                        document.getElementById('result').textContent = 'The query is running, please wait...';
                                                        L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['query', domain])).then(function (res) {
-                                                               var result = document.getElementById('result');
+                                                               const result = document.getElementById('result');
                                                                if (res) {
                                                                        result.textContent = res.trim();
                                                                } else {
@@ -244,7 +252,7 @@ return view.extend({
        },
 
        render: function (dnsreport) {
-               let content = [], notMsg, errMsg;
+               let content = [];
 
                if (dnsreport) {
                        try {
@@ -256,8 +264,8 @@ return view.extend({
                        content[0] = "";
                }
 
-               var rows_top = [];
-               var tbl_top = E('table', { 'class': 'table', 'id': 'top_10' }, [
+               let rows_top = [];
+               const tbl_top = E('table', { 'class': 'table', 'id': 'top_10' }, [
                        E('tr', { 'class': 'tr table-titles' }, [
                                E('th', { 'class': 'th right' }, _('Count')),
                                E('th', { 'class': 'th' }, _('Clients')),
@@ -268,12 +276,12 @@ return view.extend({
                        ])
                ]);
 
-               var max = 0;
+               let max = 0;
                if (content[0].top_clients && content[0].top_domains && content[0].top_blocked) {
                        max = Math.max(content[0].top_clients.length, content[0].top_domains.length, content[0].top_blocked.length);
                }
-               for (var i = 0; i < max; i++) {
-                       var a_cnt = '\xa0', a_addr = '\xa0', b_cnt = '\xa0', b_addr = '\xa0', c_cnt = '\xa0', c_addr = '\xa0';
+               for (let i = 0; i < max; i++) {
+                       let a_cnt = '\xa0', a_addr = '\xa0', b_cnt = '\xa0', b_addr = '\xa0', c_cnt = '\xa0', c_addr = '\xa0';
                        if (content[0].top_clients[i]) {
                                a_cnt = content[0].top_clients[i].count;
                        }
@@ -303,8 +311,8 @@ return view.extend({
                }
                cbi_update_table(tbl_top, rows_top);
 
-               var rows_requests = [];
-               var tbl_requests = E('table', { 'class': 'table', 'id': 'requests' }, [
+               let rows_requests = [];
+               const tbl_requests = E('table', { 'class': 'table', 'id': 'requests' }, [
                        E('tr', { 'class': 'tr table-titles' }, [
                                E('th', { 'class': 'th' }, _('Date')),
                                E('th', { 'class': 'th' }, _('Time')),
@@ -317,9 +325,9 @@ return view.extend({
 
                max = 0;
                if (content[0].requests) {
-                       var button;
+                       let button;
                        max = content[0].requests.length;
-                       for (var i = 0; i < max; i++) {
+                       for (let i = 0; i < max; i++) {
                                if (content[0].requests[i].rc === 'NX') {
                                        button = E('button', {
                                                'class': 'btn cbi-button cbi-button-positive',
index 23a8fbebe77245c4cdf6b42b905ae6f594793b91..10c552721f3fee1f2134633f4305b07070cd33b6 100644 (file)
@@ -1,33 +1,54 @@
 'use strict';
-'require fs';
+'require rpc';
+
+const callLogRead = rpc.declare({
+       object: 'log',
+       method: 'read',
+       params: ['lines', 'stream', 'oneshot'],
+       expect: {}
+});
 
 function Logview(logtag, name) {
        return L.view.extend({
-               load: function() {
-                       return Promise.all([
-                               L.resolveDefault(fs.stat('/sbin/logread'), null),
-                               L.resolveDefault(fs.stat('/usr/sbin/logread'), null)
-                       ]);
-               },
+               load: () => Promise.resolve(),
 
-               render: function(stat) {
-                       let logger = stat[0]?.path || stat[1]?.path || null;
+               render: () => {
+                       L.Poll.add(() => {
+                               return callLogRead(1000, false, true).then(res => {
+                                       const logEl = document.getElementById('logfile');
+                                       if (!logEl) return;
 
-                       if (!logger) {
-                               return E('div', { class: 'error' }, _('logread not found on system.'));
-                       }
-                       L.Poll.add(function() {
-                               return L.resolveDefault(fs.exec_direct(logger, ['-e', logtag])).then(function(res) {
-                                       var log = document.getElementById('logfile');
-                                       if (log) {
-                                               log.value = res ? res.trim() : _('No %s related logs yet!').format(name);
-                                               log.scrollTop = log.scrollHeight;
+                                       const entries = res?.log ?? [];
+                                       if (entries.length > 0) {
+                                               const filtered = entries
+                                                       .filter(entry => !logtag || entry.msg.includes(logtag))
+                                                       .map(entry => {
+                                                               const d = new Date(entry.time);
+                                                               const date = d.toLocaleDateString([], {
+                                                                       year: 'numeric',
+                                                                       month: '2-digit',
+                                                                       day: '2-digit'
+                                                               });
+                                                               const time = d.toLocaleTimeString([], {
+                                                                       hour: '2-digit',
+                                                                       minute: '2-digit',
+                                                                       second: '2-digit',
+                                                                       hour12: false
+                                                               });
+                                                               return `[${date}-${time}] ${entry.msg}`;
+                                                       });
+                                               logEl.value = filtered.join('\n');
+                                       } else {
+                                               logEl.value = _('No %s related logs yet!').format(name);
                                        }
+                                       logEl.scrollTop = logEl.scrollHeight;
                                });
                        });
+
                        return E('div', { class: 'cbi-map' }, [
                                E('div', { class: 'cbi-section' }, [
-                                       E('div', { class: 'cbi-section-descr' }, _('The syslog output, pre-filtered for messages related to: %s').format(name)),
+                                       E('div', { class: 'cbi-section-descr' },
+                                               _('The syslog output, pre-filtered for messages related to: %s').format(name)),
                                        E('textarea', {
                                                id: 'logfile',
                                                style: 'min-height: 500px; max-height: 90vh; width: 100%; padding: 5px; font-family: monospace; resize: vertical;',
@@ -37,12 +58,11 @@ function Logview(logtag, name) {
                                ])
                        ]);
                },
+
                handleSaveApply: null,
                handleSave: null,
                handleReset: null
        });
 }
 
-return L.Class.extend({
-       Logview: Logview
-});
+return L.Class.extend({ Logview });
index 7b55e907bfdde9ba7e447cebeab1c47595e6592a..ae7effc6f03d19fc157781fec0c62914f09bb68d 100644 (file)
@@ -53,6 +53,16 @@ return view.extend({
                m = new form.Map('adblock', 'Adblock', _('Configuration of the adblock package to block ad/abuse domains by using DNS. \
                        For further information <a href="https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md" target="_blank" rel="noreferrer noopener" >check the online documentation</a>'));
 
+               /*
+                       set text content helper function
+               */
+               const setText = (id, value) => {
+                       const el = document.getElementById(id);
+                       if (el) {
+                               el.textContent = value || '-';
+                       }
+               };
+
                /*
                        poll runtime information
                */
@@ -74,7 +84,7 @@ return view.extend({
                                        ui.addNotification(null, E('p', _('Unable to parse the runtime information!')), 'error');
                                }
                                if (status && info) {
-                                       status.textContent = (info.adblock_status || '-') + ' / ' + (info.adblock_version || '-');
+                                       status.textContent = `${info.adblock_status || '-'} (frontend: ${info.frontend_ver || '-'} / backend: ${info.backend_ver || '-'})`;
                                        if (info.adblock_status === "running") {
                                                if (!status.classList.contains("spinning")) {
                                                        status.classList.add("spinning");
@@ -108,45 +118,15 @@ return view.extend({
                                                status.classList.remove('spinning');
                                        }
                                }
-                               var domains = document.getElementById('domains');
-                               if (domains && info) {
-                                       domains.textContent = info.blocked_domains || '-';
-                               }
-                               var feeds = document.getElementById('feeds');
-                               var src_array = [];
-                               if (feeds && info) {
-                                       for (var i = 0; i < info.active_feeds.length; i++) {
-                                               if (i < info.active_feeds.length - 1) {
-                                                       src_array += info.active_feeds[i] + ', ';
-                                               } else {
-                                                       src_array += info.active_feeds[i]
-                                               }
-                                       }
-                                       feeds.textContent = src_array || '-';
-                               }
-                               var backend = document.getElementById('backend');
-                               if (backend && info) {
-                                       backend.textContent = info.dns_backend || '-';
-                               }
-                               var ifaces = document.getElementById('ifaces');
-                               if (ifaces && info) {
-                                       ifaces.textContent = info.run_ifaces || '-';
-                               }
-                               var dirs = document.getElementById('dirs');
-                               if (dirs && info) {
-                                       dirs.textContent = info.run_directories || '-';
-                               }
-                               var flags = document.getElementById('flags');
-                               if (flags && info) {
-                                       flags.textContent = info.run_flags || '-';
-                               }
-                               var run = document.getElementById('run');
-                               if (run && info) {
-                                       run.textContent = info.last_run || '-';
-                               }
-                               var sys = document.getElementById('sys');
-                               if (sys && info) {
-                                       sys.textContent = info.system_info || '-';
+                               if (info) {
+                                       setText('domains', info.blocked_domains);
+                                       setText('feeds', info.active_feeds?.join(', '));
+                                       setText('backend', info.dns_backend);
+                                       setText('ifaces', info.run_ifaces);
+                                       setText('dirs', info.run_directories);
+                                       setText('flags', info.run_flags);
+                                       setText('run', info.last_run);
+                                       setText('sys', info.system_info);
                                }
                        });
                }, 2);
index 5fc914d3e76756d77a3d45eeda68011a17113199..c4bad140cb2066e2e195a860bf139247955dfb8e 100644 (file)
@@ -2,68 +2,31 @@
        "luci-app-adblock": {
                "description": "Grant access to LuCI app adblock",
                "write": {
-                       "uci": [
-                               "adblock"
-                       ],
+                       "uci": [ "adblock" ],
                        "file": {
-                               "/etc/adblock/*": [
-                                       "read",
-                                       "write"
-                               ],
-                               "/etc/adblock/adblock.allowlist": [
-                                       "write"
-                               ],
-                               "/etc/adblock/adblock.blocklist": [
-                                       "write"
-                               ],
-                               "/etc/adblock/adblock.custom.feeds": [
-                                       "read",
-                                       "write"
-                               ]
+                               "/etc/adblock/*": [ "read", "write" ],
+                               "/etc/adblock/adblock.allowlist": [ "write" ],
+                               "/etc/adblock/adblock.blocklist": [ "write" ],
+                               "/etc/adblock/adblock.custom.feeds": [ "read", "write" ]
                        }
                },
                "read": {
-                       "cgi-io": [
-                               "exec"
-                       ],
+                       "cgi-io": [ "exec" ],
                        "file": {
-                               "/var/run/adblock.pid": [
-                                       "read"
-                               ],
-                               "/var/run/adb_runtime.json": [
-                                       "read"
-                               ],
-                               "/sbin/logread -e adblock-": [
-                                       "exec"
-                               ],
-                               "/usr/sbin/logread -e adblock-": [
-                                       "exec"
-                               ],
-                               "/etc/init.d/adblock reload": [
-                                       "exec"
-                               ],
-                               "/etc/init.d/adblock restart": [
-                                       "exec"
-                               ],
-                               "/etc/init.d/adblock suspend": [
-                                       "exec"
-                               ],
-                               "/etc/init.d/adblock resume": [
-                                       "exec"
-                               ],
-                               "/etc/init.d/adblock stop": [
-                                       "exec"
-                               ],
-                               "/etc/init.d/adblock report [a-z]* [0-9]* [0-9]* *": [
-                                       "exec"
-                               ],
-                               "/etc/init.d/adblock query *": [
-                                       "exec"
-                               ]
+                               "/var/run/adblock.pid": [ "read" ],
+                               "/var/run/adb_runtime.json": [ "read" ],
+                               "/sbin/logread -e adblock-": [ "exec" ],
+                               "/usr/sbin/logread -e adblock-": [ "exec" ],
+                               "/etc/init.d/adblock reload": [ "exec" ],
+                               "/etc/init.d/adblock restart": [ "exec" ],
+                               "/etc/init.d/adblock suspend": [ "exec" ],
+                               "/etc/init.d/adblock resume": [ "exec" ],
+                               "/etc/init.d/adblock stop": [ "exec" ],
+                               "/etc/init.d/adblock report [a-z]* [0-9]* [0-9]* *": [ "exec" ],
+                               "/etc/init.d/adblock query *": [ "exec" ]
                        },
-                       "uci": [
-                               "adblock"
-                       ]
+                       "uci": [ "adblock" ],
+                       "log": [ "read" ]
                }
        }
 }
\ No newline at end of file