Merge pull request #3856 from dibdot/adblock

[19.07] luci-app-adblock: release 4.0.3
This commit is contained in:
Jo-Philipp Wich 2020-04-08 09:20:04 +02:00 committed by GitHub
commit e9449d957e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 22192 additions and 14257 deletions

View file

@ -1,12 +1,14 @@
# Copyright 2017 Dirk Brenken (dev@brenken.org)
# Copyright 2017-2020 Dirk Brenken (dev@brenken.org)
# This is free software, licensed under the Apache License, Version 2.0
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for Adblock
LUCI_DEPENDS:=+luci-compat +adblock +luci-lib-jsonc
LUCI_DEPENDS:=+adblock +luci-lib-jsonc
LUCI_PKGARCH:=all
PKG_LICENSE:=Apache-2.0
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -0,0 +1,36 @@
'use strict';
'require fs';
'require ui';
return L.view.extend({
load: function() {
return L.resolveDefault(fs.read_direct('/etc/adblock/adblock.blacklist'), '');
},
handleSave: function(ev) {
var value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n').replace(/[^a-z0-9\.\-\#\n]/g, '')) + '\n';
return fs.write('/etc/adblock/adblock.blacklist', value)
.then(function(rc) {
document.querySelector('textarea').value = value;
ui.addNotification(null, E('p', _('Blacklist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
}).catch(function(e) {
ui.addNotification(null, E('p', _('Unable to save changes: %s').format(e.message)));
});
},
render: function(blacklist) {
return E([
E('p', {},
_('This is the local adblock blacklist to always-deny certain (sub) domains.<br /> \
Please note: add only one domain per line. Comments introduced with \'#\' are allowed - ip addresses, wildcards and regex are not.')),
E('p', {},
E('textarea', {
'style': 'width: 100% !important; padding: 5px; font-family: monospace',
'spellcheck': 'false',
'wrap': 'off',
'rows': 25
}, [ blacklist != null ? blacklist : '' ])
)
]);
},
handleSaveApply: null,
handleReset: null
});

View file

@ -0,0 +1,342 @@
'use strict';
'require fs';
'require ui';
/*
button handling
*/
function handleAction(ev) {
if (ev.target && ev.target.getAttribute('name') === 'blacklist') {
L.ui.showModal(_('Add Blacklist Domain'), [
E('p', _('Add this (sub-)domain to your local blacklist.')),
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
E('input', { 'class': 'cbi-input-text', 'style': 'width:300px', 'id': 'blacklist', 'value': ev.target.getAttribute('value') }, [])
])
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': L.hideModal
}, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-action',
'click': ui.createHandlerFn(this, function(ev) {
L.resolveDefault(fs.read_direct('/etc/adblock/adblock.blacklist'), '')
.then(function(res) {
var domain = document.getElementById('blacklist').value.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
var pattern = new RegExp('^' + domain.replace(/[\.]/g,'\\.') + '$', 'm');
if (res.search(pattern) === -1) {
var blacklist = res + domain + '\n';
fs.write('/etc/adblock/adblock.blacklist', blacklist);
ui.addNotification(null, E('p', _('Blacklist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
}
L.hideModal();
});
})
}, _('Save'))
])
]);
document.getElementById('blacklist').focus();
}
if (ev.target && ev.target.getAttribute('name') === 'whitelist') {
L.ui.showModal(_('Add Whitelist Domain'), [
E('p', _('Add this (sub-)domain to your local whitelist.')),
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
E('input', { 'class': 'cbi-input-text', 'style': 'width:300px', 'id': 'whitelist', 'value': ev.target.getAttribute('value') }, [])
])
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': L.hideModal
}, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-action',
'click': ui.createHandlerFn(this, function(ev) {
L.resolveDefault(fs.read_direct('/etc/adblock/adblock.whitelist'), '')
.then(function(res) {
var domain = document.getElementById('whitelist').value.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
var pattern = new RegExp('^' + domain.replace(/[\.]/g,'\\.') + '$', 'm');
if (res.search(pattern) === -1) {
var whitelist = res + domain + '\n';
fs.write('/etc/adblock/adblock.whitelist', whitelist);
ui.addNotification(null, E('p', _('Whitelist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
}
L.hideModal();
});
})
}, _('Save'))
])
]);
document.getElementById('whitelist').focus();
}
if (ev === 'query') {
L.ui.showModal(_('Blocklist Query'), [
E('p', _('Query active blocklists and backups for a specific domain.')),
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
E('label', { 'style': 'padding-top:.5em', 'id': 'run' }, [
E('input', {
'class': 'cbi-input-text',
'placeholder': 'google.com',
'style': 'width:300px',
'id': 'search'
})
])
]),
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
'\xa0',
E('h5', _('Result')),
E('textarea', {
'id': 'result',
'style': 'width: 100% !important; padding: 5px; font-family: monospace',
'readonly': 'readonly',
'wrap': 'off',
'rows': 20
})
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': L.hideModal
}, _('Cancel')),
' ',
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,'');
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');
if (res) {
result.textContent = res.trim();
} else {
result.textContent = _('No Query results!');
}
document.getElementById('run').classList.remove("spinning");
document.getElementById('search').value = '';
})
}
document.getElementById('search').focus();
})
}, _('Query'))
])
]);
document.getElementById('search').focus();
}
if (ev === 'refresh') {
L.ui.showModal(_('Refresh DNS Report'), [
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em' }, [
E('select', { 'class': 'cbi-input-select', 'id': 'count' }, [
E('option', { 'value': '50' }, '50'),
E('option', { 'value': '100' }, '100'),
E('option', { 'value': '150' }, '150'),
E('option', { 'value': '250' }, '250'),
E('option', { 'value': '500' }, '500')
]),
'\xa0\xa0\xa0',
_('max. result set size')
])
]),
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
E('input', { 'class': 'cbi-input-text', 'id': 'search' }, [
]),
'\xa0\xa0\xa0',
_('Filter criteria like date, domain or client (optional)')
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': L.hideModal
}, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-action',
'id': 'refresh',
'click': ui.createHandlerFn(this, async function(ev) {
var count = document.getElementById('count').value;
var search = document.getElementById('search').value.trim().replace(/[^a-z0-9\.\-]/g,'') || '+';
L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['report', search, count, 'true', 'json']),'');
var running = 1;
while (running === 1) {
await new Promise(r => setTimeout(r, 1000));
L.resolveDefault(fs.read_direct('/var/run/adblock.pid')).then(function(res) {
if (!res) {
running = 0;
}
})
}
L.hideModal();
location.reload();
})
}, _('Refresh'))
])
]);
document.getElementById('refresh').focus();
}
}
return L.view.extend({
load: function() {
return L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['report', '+', '50', 'false', 'json']),'');
},
render: function(dnsreport) {
if (!dnsreport) {
dnsreport = '{ "data": "" }';
};
var content;
content = JSON.parse(dnsreport);
var rows_top = [];
var tbl_top = E('div', { 'class': 'table', 'id': 'top_10' }, [
E('div', { 'class': 'tr table-titles' }, [
E('div', { 'class': 'th right' }, _('Count')),
E('div', { 'class': 'th' }, _('Name / IP Address')),
E('div', { 'class': 'th right' }, _('Count')),
E('div', { 'class': 'th' }, _('Domain')),
E('div', { 'class': 'th right' }, _('Count')),
E('div', { 'class': 'th' }, _('Blocked Domain'))
])
]);
var max = 0;
if (content.data.top_clients && content.data.top_domains && content.data.top_blocked) {
max = Math.max(content.data.top_clients.length, content.data.top_domains.length, content.data.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';
if (content.data.top_clients[i]) {
a_cnt = content.data.top_clients[i].count;
}
if (content.data.top_clients[i]) {
a_addr = content.data.top_clients[i].address;
}
if (content.data.top_domains[i]) {
b_cnt = content.data.top_domains[i].count;
}
if (content.data.top_domains[i]) {
b_addr = content.data.top_domains[i].address;
}
if (content.data.top_blocked[i]) {
c_cnt = content.data.top_blocked[i].count;
}
if (content.data.top_blocked[i]) {
c_addr = content.data.top_blocked[i].address;
}
rows_top.push([
a_cnt,
a_addr,
b_cnt,
b_addr,
c_cnt,
c_addr
]);
}
cbi_update_table(tbl_top, rows_top);
var rows_requests = [];
var tbl_requests = E('div', { 'class': 'table', 'id': 'requests' }, [
E('div', { 'class': 'tr table-titles' }, [
E('div', { 'class': 'th' }, _('Date')),
E('div', { 'class': 'th' }, _('Time')),
E('div', { 'class': 'th' }, _('Client')),
E('div', { 'class': 'th' }, _('Domain')),
E('div', { 'class': 'th' }, _('Answer')),
E('div', { 'class': 'th' }, _('Action'))
])
]);
max = 0;
if (content.data.requests) {
var button;
max = content.data.requests.length;
for (var i = 0; i < max; i++) {
if (content.data.requests[i].rc === 'NX') {
button = E('button', {
'class': 'cbi-button cbi-button-apply',
'style': 'word-break: inherit',
'name': 'whitelist',
'value': content.data.requests[i].domain,
'click': handleAction
}, [ _('Whitelist...') ]);
} else {
button = E('button', {
'class': 'cbi-button cbi-button-apply',
'style': 'word-break: inherit',
'name': 'blacklist',
'value': content.data.requests[i].domain,
'click': handleAction
}, [ _('Blacklist...') ]);
}
rows_requests.push([
content.data.requests[i].date,
content.data.requests[i].time,
content.data.requests[i].client,
content.data.requests[i].domain,
content.data.requests[i].rc,
button
]);
}
}
cbi_update_table(tbl_requests, rows_requests);
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Start Date')),
E('div', { 'class': 'cbi-value-field', 'id': 'start', 'style': 'margin-bottom:5px;margin-left:200px;color:#37c' }, (content.data.start_date || '-') + ', ' + (content.data.start_time || '-'))]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('End Date')),
E('div', { 'class': 'cbi-value-field', 'id': 'end', 'style': 'margin-bottom:5px;margin-left:200px;color:#37c' }, (content.data.end_date || '-') + ', ' + (content.data.end_time || '-'))]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('DNS Requests (total)')),
E('div', { 'class': 'cbi-value-field', 'id': 'total', 'style': 'margin-bottom:5px;margin-left:200px;color:#37c' }, content.data.total || '-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('DNS Requests (blocked)')),
E('div', { 'class': 'cbi-value-field', 'id': 'blocked', 'style': 'margin-bottom:5px;margin-left:200px;color:#37c' }, (content.data.blocked || '-') + ' (' + (content.data.percent || '-') + ')')]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
return handleAction('query');
})
}, [ _('Blocklist Query...') ]),
'\xa0\xa0\xa0',
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
return handleAction('refresh');
})
}, [ _('Refresh...') ])
]),
]),
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'left' }, [
E('h3', _('Top 10 Statistics')),
tbl_top
])
]),
E('br'),
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'left' }, [
E('h3', _('Latest DNS Requests')),
tbl_requests
])
])
]);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View file

@ -0,0 +1,39 @@
'use strict';
'require fs';
return L.view.extend({
load: function() {
return Promise.all([
L.resolveDefault(fs.stat('/sbin/logread'), null),
L.resolveDefault(fs.stat('/usr/sbin/logread'), null)
]);
},
render: function(stat) {
var logger = stat[0] ? stat[0].path : stat[1] ? stat[1].path : null;
L.Poll.add(function() {
return L.resolveDefault(fs.exec_direct(logger, ['-e', 'adblock-'])).then(function(res) {
var log = document.getElementById("logfile");
if (res) {
log.value = res.trim();
} else {
log.value = _('No adblock related logs yet!');
}
log.scrollTop = log.scrollHeight;
});
});
return E('div', { class: 'cbi-map' },
E('div', { class: 'cbi-section' }, [
E('div', { class: 'cbi-section-descr' }, _('The syslog output, pre-filtered for adblock related messages only.')),
E('textarea', {
'id': 'logfile',
'style': 'width: 100% !important; padding: 5px; font-family: monospace',
'readonly': 'readonly',
'wrap': 'off',
'rows': 25
})
]));
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View file

@ -0,0 +1,481 @@
'use strict';
'require fs';
'require ui';
'require uci';
'require form';
'require tools.widgets as widgets';
/*
button handling
*/
async function handleAction(ev) {
if (ev === 'timer') {
L.ui.showModal(_('Refresh Timer'), [
E('p', _('To keep your adblock lists up-to-date, you should setup an automatic update job for these lists.')),
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
E('h5', _('Existing job(s)')),
E('textarea', {
'id': 'cronView',
'style': 'width: 100% !important; padding: 5px; font-family: monospace',
'readonly': 'readonly',
'wrap': 'off',
'rows': 5
})
]),
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em' }, [
E('h5', _('Set/Replace a new adblock job')),
E('select', { 'class': 'cbi-input-select', 'id': 'timerA' }, [
E('option', { 'value': 'start' }, 'Start'),
E('option', { 'value': 'reload' }, 'Reload'),
E('option', { 'value': 'restart' }, 'Restart')
]),
'\xa0\xa0\xa0',
_('Adblock action')
]),
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
E('input', { 'class': 'cbi-input-text', 'id': 'timerH', 'maxlength': '2' }, [
]),
'\xa0\xa0\xa0',
_('The hours portition (req., range: 0-23)')
]),
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
E('input', { 'class': 'cbi-input-text', 'id': 'timerM', 'maxlength': '2' }),
'\xa0\xa0\xa0',
_('The minutes portion (opt., range: 0-59)')
]),
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
E('input', { 'class': 'cbi-input-text', 'id': 'timerD', 'maxlength': '13' }),
'\xa0\xa0\xa0',
_('The day of the week (opt., values: 1-7 possibly sep. by , or -)')
])
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': L.hideModal
}, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-action',
'click': ui.createHandlerFn(this, function(ev) {
var action = document.getElementById('timerA').value;
var hours = document.getElementById('timerH').value;
var minutes = document.getElementById('timerM').value || '0';
var days = document.getElementById('timerD').value || '*';
if (hours) {
L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['timer', action, hours, minutes, days]))
.then(function(res) {
if (res) {
ui.addNotification(null, E('p', _('The Refresh Timer could not been updated.')), 'error');
} else {
ui.addNotification(null, E('p', _('The Refresh Timer has been updated.')), 'info');
}
});
} else {
document.getElementById('timerH').focus();
return
}
L.hideModal();
})
}, _('Save'))
])
]);
L.resolveDefault(fs.read_direct('/etc/crontabs/root'), ' ')
.then(function(res) {
document.getElementById('cronView').value = res.trim();
});
document.getElementById('timerH').focus();
return
}
if (ev === 'suspend') {
if (document.getElementById('status') && document.getElementById('btn_suspend') && document.getElementById('status').textContent.substr(0,6) === 'paused') {
document.querySelector('#btn_suspend').textContent = 'Suspend';
ev = 'resume';
} else if (document.getElementById('status') && document.getElementById('btn_suspend')) {
document.querySelector('#btn_suspend').textContent = 'Resume';
}
}
L.Poll.start();
fs.exec_direct('/etc/init.d/adblock', [ev])
var running = 1;
while (running === 1) {
await new Promise(r => setTimeout(r, 1000));
L.resolveDefault(fs.read_direct('/var/run/adblock.pid')).then(function(res) {
if (!res) {
running = 0;
}
})
}
L.Poll.stop();
}
return L.view.extend({
load: function() {
return Promise.all([
L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['list']), {}),
uci.load('adblock')
]);
},
render: function(result) {
var m, s, o;
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>'));
/*
poll runtime information
*/
pollData: L.Poll.add(function() {
return L.resolveDefault(fs.read_direct('/tmp/adb_runtime.json'), 'null').then(function(res) {
var info = JSON.parse(res);
var status = document.getElementById('status');
if (status && info) {
status.textContent = (info.data.adblock_status || '-') + ' / ' + (info.data.adblock_version || '-');
if (info.data.adblock_status === "running") {
if (!status.classList.contains("spinning")) {
status.classList.add("spinning");
}
} else {
if (status.classList.contains("spinning")) {
status.classList.remove("spinning");
L.Poll.stop();
}
}
if (status.textContent.substr(0,6) === 'paused' && document.getElementById('btn_suspend')) {
document.querySelector('#btn_suspend').textContent = 'Resume';
}
} else if (status) {
status.textContent = '-';
if (status.classList.contains("spinning")) {
status.classList.remove("spinning");
}
}
var domains = document.getElementById('domains');
if (domains && info) {
domains.textContent = parseInt(info.data.blocked_domains, 10).toLocaleString() || '-';
}
var sources = document.getElementById('sources');
var src_array = [];
if (sources && info) {
for (var i = 0; i < info.data.active_sources.length; i++) {
if (i < info.data.active_sources.length-1) {
src_array += info.data.active_sources[i].source + ', ';
} else {
src_array += info.data.active_sources[i].source
}
}
sources.textContent = src_array || '-';
}
var backend = document.getElementById('backend');
if (backend && info) {
backend.textContent = info.data.dns_backend || '-';
}
var utils = document.getElementById('utils');
if (utils && info) {
utils.textContent = info.data.run_utils || '-';
}
var ifaces = document.getElementById('ifaces');
if (ifaces && info) {
ifaces.textContent = info.data.run_ifaces || '-';
}
var dirs = document.getElementById('dirs');
if (dirs && info) {
dirs.textContent = info.data.run_directories || '-';
}
var flags = document.getElementById('flags');
if (flags && info) {
flags.textContent = info.data.run_flags || '-';
}
var run = document.getElementById('run');
if (run && info) {
run.textContent = info.data.last_run || '-';
}
});
}, 1);
/*
runtime information and buttons
*/
s = m.section(form.NamedSection, 'global');
s.render = L.bind(function(view, section_id) {
return E('div', { 'class': 'cbi-section' }, [
E('h3', _('Information')),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Status / Version')),
E('div', { 'class': 'cbi-value-field spinning', 'id': 'status', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'\xa0')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Blocked Domains')),
E('div', { 'class': 'cbi-value-field', 'id': 'domains', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Active Sources')),
E('div', { 'class': 'cbi-value-field', 'id': 'sources', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('DNS Backend')),
E('div', { 'class': 'cbi-value-field', 'id': 'backend', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Run Utils')),
E('div', { 'class': 'cbi-value-field', 'id': 'utils', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Run Interfaces')),
E('div', { 'class': 'cbi-value-field', 'id': 'ifaces', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Run Directories')),
E('div', { 'class': 'cbi-value-field', 'id': 'dirs', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Run Flags')),
E('div', { 'class': 'cbi-value-field', 'id': 'flags', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Last Run')),
E('div', { 'class': 'cbi-value-field', 'id': 'run', 'style': 'font-weight: bold;margin-bottom:5px;color:#37c' },'-')]),
E('div', { class: 'right' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
return handleAction('timer');
})
}, [ _('Refresh Timer...') ]),
'\xa0\xa0\xa0',
E('button', {
'class': 'cbi-button cbi-button-apply',
'id': 'btn_suspend',
'click': ui.createHandlerFn(this, function() {
return handleAction('suspend');
})
}, [ _('Suspend') ]),
'\xa0\xa0\xa0',
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
return handleAction('start');
})
}, [ _('Refresh') ])
])
]);
}, o, this);
this.pollData;
/*
tabbed config section
*/
s = m.section(form.NamedSection, 'global', 'adblock', _('Settings'));
s.addremove = false;
s.tab('general', _('General Settings'));
s.tab('additional', _('Additional Settings'));
s.tab('adv_dns', _('Advanced DNS Settings'));
s.tab('adv_report', _('Advanced Report Settings'));
s.tab('adv_email', _('Advanced E-Mail Settings'));
s.tab('sources', _('Blocklist Sources'), _('List of supported and fully pre-configured adblock sources, already active sources are pre-selected.<br /> \
<b><em>To avoid OOM errors, please do not select too many lists!</em></b><br /> \
List size information with the respective domain ranges as follows:<br /> \
&#8226;&#xa0;<b>S</b> (-10k), <b>M</b> (10k-30k) and <b>L</b> (30k-80k) should work for 128 MByte devices,<br /> \
&#8226;&#xa0;<b>XL</b> (80k-200k) should work for 256-512 MByte devices,<br /> \
&#8226;&#xa0;<b>XXL</b> (200k-) needs more RAM and Multicore support, e.g. x86 or raspberry devices.<br /> \
<p>&#xa0;</p>'));
/*
general settings tab
*/
o = s.taboption('general', form.Flag, 'adb_enabled', _('Enabled'), _('Enable the adblock service.'));
o.rmempty = false;
o = s.taboption('general', widgets.NetworkSelect, 'adb_trigger', _('Startup Trigger Interface'), _('List of available network interfaces to trigger the adblock start. \
Choose \'unspecified\' to use a classic startup timeout instead of a network trigger.'));
o.unspecified = true;
o.nocreate = true;
o.rmempty = true;
o = s.taboption('general', form.Flag, 'adb_forcedns', _('Force Local DNS'), _('Redirect all DNS queries from \'lan\' zone to the local DNS resolver, applies to UDP and TCP protocol.'));
o.rmempty = false;
o = s.taboption('general', form.Value, 'adb_portlist', _('Local DNS Ports'), _('Space separated list of DNS-related firewall ports which should be forced locally.'));
o.depends('adb_forcedns', '1');
o.placeholder = '53 853 5353';
o.rmempty = true;
o = s.taboption('general', form.Flag, 'adb_safesearch', _('Enable SafeSearch'), _('Enforcing SafeSearch for google, bing, duckduckgo, yandex, youtube and pixabay.'));
o.rmempty = false;
o = s.taboption('general', form.Flag, 'adb_safesearchmod', _('SafeSearch Moderate'), _('Enable moderate SafeSearch filters for youtube.'));
o.depends('adb_safesearch', '1');
o.rmempty = true;
o = s.taboption('general', form.Flag, 'adb_report', _('DNS Report'), _('Gather DNS related network traffic via tcpdump and provide a DNS Report on demand. \
Please note: this needs additional \'tcpdump-mini\' package installation and a full adblock service restart to take effect.'));
o.rmempty = false;
o = s.taboption('general', form.Flag, 'adb_mail', _('E-Mail Notification'), _('Send adblock related notification e-mails. \
Please note: this needs additional \'msmtp\' package installation.'));
o.rmempty = false;
o = s.taboption('general', form.Value, 'adb_mailreceiver', _('E-Mail Receiver Address'), _('Receiver address for adblock notification e-mails.'));
o.depends('adb_mail', '1');
o.placeholder = 'name@example.com';
o.rmempty = true;
/*
additional settings tab
*/
o = s.taboption('additional', form.Flag, 'adb_debug', _('Verbose Debug Logging'), _('Enable verbose debug logging in case of any processing errors.'));
o.rmempty = false;
o = s.taboption('additional', form.Flag, 'adb_nice', _('Low Priority Service'), _('Reduce the priority of the adblock background processing to take fewer resources from the system. \
Please note: This change requires a full adblock service restart to take effect.'));
o.enabled = '10';
o.rmempty = true;
o = s.taboption('additional', form.Value, 'adb_triggerdelay', _('Trigger Delay'), _('Additional trigger delay in seconds before adblock processing begins.'));
o.placeholder = '2';
o.datatype = 'range(1,120)';
o.rmempty = true;
o = s.taboption('additional', form.ListValue, 'adb_maxqueue', _('Download Queue'), _('Size of the download queue for download processing (incl. sorting, merging etc.) in parallel.'));
o.value('4');
o.value('8');
o.value('16');
o.value('32');
o.rmempty = false;
o = s.taboption('additional', form.Value, 'adb_tmpbase', _('Base Temp Directory'), _('Base Temp Directory for all adblock related runtime operations, \
e.g. downloading, sorting, merging etc.'));
o.placeholder = '/tmp';
o.rmempty = true;
o = s.taboption('additional', form.Flag, 'adb_backup', _('Blocklist Backup'), _('Create compressed blocklist backups, they will be used in case of download errors or during startup.'));
o.default = 1
o.rmempty = false;
o = s.taboption('additional', form.Value, 'adb_backupdir', _('Backup Directory'), _('Target directory for blocklist backups. \
Default is \'/tmp\', please use preferably an usb stick or another local disk.'));
o.depends('adb_backup', '1');
o.placeholder = '/tmp';
o.rmempty = true;
o = s.taboption('additional', form.ListValue, 'adb_fetchutil', _('Download Utility'), _('List of supported and fully pre-configured download utilities.'));
o.value('uclient-fetch');
o.value('wget');
o.value('curl');
o.value('aria2c');
o.rmempty = false;
o = s.taboption('additional', form.Value, 'adb_fetchparm', _('Download Parameters'), _('Special config options for the selected download utility.'))
o.rmempty = true;
/*
advanced dns settings tab
*/
o = s.taboption('adv_dns', form.ListValue, 'adb_dns', _('DNS Backend'), _('List of supported DNS backends with their default list directory. \
To overwrite the default path use the \'DNS Directory\' option.'));
o.value('dnsmasq', _('dnsmasq (/tmp/dnsmasq.d)'));
o.value('unbound', _('unbound (/var/lib/unbound)'));
o.value('named', _('named (/var/lib/bind)'));
o.value('kresd', _('kresd (/etc/kresd)'));
o.value('raw', _('raw (/tmp)'));
o.rmempty = false;
o = s.taboption('adv_dns', form.Value, 'adb_dnsdir', _('DNS Directory'), _('Target directory for the generated blocklist \'adb_list.overall\'.'));
o.placeholder = '/tmp';
o.rmempty = true;
o = s.taboption('adv_dns', form.Value, 'adb_dnstimeout', _('DNS Restart Timeout'), _('Timeout to wait for a successful DNS backend restart.'));
o.placeholder = '20';
o.datatype = 'range(1,60)';
o.rmempty = true;
o = s.taboption('adv_dns', form.Value, 'adb_lookupdomain', _('External DNS Lookup Domain'), _('External domain to check for a successful DNS backend restart. \
Please note: To disable this check set this option to \'false\'.'));
o.placeholder = 'example.com';
o.rmempty = true;
o = s.taboption('adv_dns', form.Flag, 'adb_dnsfilereset', _('DNS File Reset'), _('Resets the final DNS blocklist \'adb_list.overall\' after DNS backend loading. \
Please note: This option starts a small ubus/adblock monitor in the background.'));
o.rmempty = false;
o = s.taboption('adv_dns', form.Flag, 'adb_dnsflush', _('Flush DNS Cache'), _('Flush the DNS Cache before adblock processing as well.'));
o.rmempty = true;
o = s.taboption('adv_dns', form.Flag, 'adb_dnsallow', _('Disable DNS Allow'), _('Disable selective DNS whitelisting (RPZ pass through).'));
o.rmempty = true;
o = s.taboption('adv_dns', form.Flag, 'adb_jail', _('Additional Jail Blocklist'), _('Builds an additional DNS blocklist to block access to all domains except those listed in the whitelist. \
Please note: 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 \'adb_list.jail\'.'));
o.depends('adb_jail', '1');
o.placeholder = '/tmp';
o.rmempty = true;
o = s.taboption('adv_dns', form.Flag, 'adb_dnsinotify', _('Disable DNS Restarts'), _('Disable adblock triggered restarts for dns backends with autoload/inotify functions.'));
o.depends('adb_dnsflush', '0');
o.rmempty = true;
/*
advanced report settings tab
*/
o = s.taboption('adv_report', widgets.DeviceSelect, 'adb_repiface', _('Report Interface'), _('List of available network devices used by tcpdump.'));
o.unspecified = true;
o.nocreate = false;
o.rmempty = true;
o = s.taboption('adv_report', form.Value, 'adb_reportdir', _('Report Directory'), _('Target directory for DNS related report files. \
Default is \'/tmp\', please use preferably an usb stick or another local disk.'));
o.placeholder = '/tmp';
o.rmempty = true;
o = s.taboption('adv_report', form.Value, 'adb_repchunkcnt', _('Report Chunk Count'), _('Report chunk count used by tcpdump.'));
o.placeholder = '5';
o.datatype = 'range(1,10)';
o.rmempty = true;
o = s.taboption('adv_report', form.Value, 'adb_repchunksize', _('Report Chunk Size'), _('Report chunk size used by tcpdump in MByte.'));
o.placeholder = '1';
o.datatype = 'range(1,10)';
o.rmempty = true;
o = s.taboption('adv_report', form.Value, 'adb_replisten', _('Report Ports'), _('Space separated list of ports used by tcpdump.'));
o.placeholder = '53';
o.rmempty = true;
/*
advanced email settings tab
*/
o = s.taboption('adv_email', form.Value, 'adb_mailsender', _('E-Mail Sender Address'), _('Sender address for adblock notification E-Mails.'));
o.placeholder = 'no-reply@adblock';
o.rmempty = true;
o = s.taboption('adv_email', form.Value, 'adb_mailtopic', _('E-Mail Topic'), _('Topic for adblock notification E-Mails.'));
o.placeholder = 'adblock notification';
o.rmempty = true;
o = s.taboption('adv_email', form.Value, 'adb_mailprofile', _('E-Mail Profile'), _('Profile used by \'msmtp\' for adblock notification E-Mails.'));
o.placeholder = 'adb_notify';
o.rmempty = true;
o = s.taboption('adv_email', form.Value, 'adb_mailcnt', _('E-Mail Notification Count'), _('Raise the notification count, to get E-Mails if the overall blocklist count is less or equal to the given limit.'));
o.placeholder = '0';
o.datatype = 'min(0)';
o.rmempty = true;
/*
blocklist sources tab
*/
o = s.taboption('sources', form.MultiValue, 'adb_sources', _('Sources (Size, Focus)'));
var lines, name, size, focus;
lines = result[0].trim().split('\n');
for (var i = 0; i < lines.length; i++) {
if (lines[i].match(/^\s+\+/)) {
name = lines[i].match(/^\s+\+\s(\w+)\s/)[1] || '-';
size = lines[i].match(/^\s+\+\s\w+[\sx]+(\w+)/)[1] || '-';
focus = lines[i].match(/^\s+\+\s\w+[\sx]+\w+\s+([\w\+]+)/)[1] || '-';
o.value(name, name + ' (' + size + ', ' + focus + ')');
}
}
o.rmempty = false;
return m.render();
},
handleReset: null
});

View file

@ -0,0 +1,36 @@
'use strict';
'require fs';
'require ui';
return L.view.extend({
load: function() {
return L.resolveDefault(fs.read_direct('/etc/adblock/adblock.whitelist'), '');
},
handleSave: function(ev) {
var value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n').replace(/[^a-z0-9\.\-\#\n]/g, '')) + '\n';
return fs.write('/etc/adblock/adblock.whitelist', value)
.then(function(rc) {
document.querySelector('textarea').value = value;
ui.addNotification(null, E('p', _('Whitelist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
}).catch(function(e) {
ui.addNotification(null, E('p', _('Unable to save changes: %s').format(e.message)));
});
},
render: function(whitelist) {
return E([
E('p', {},
_('This is the local adblock whitelist to always allow certain (sub) domains.<br /> \
Please note: add only one domain per line. Comments introduced with \'#\' are allowed - ip addresses, wildcards and regex are not.')),
E('p', {},
E('textarea', {
'style': 'width: 100% !important; padding: 5px; font-family: monospace',
'spellcheck': 'false',
'wrap': 'off',
'rows': 25
}, [ whitelist != null ? whitelist : '' ])
)
]);
},
handleSaveApply: null,
handleReset: null
});

View file

@ -1,175 +1,12 @@
-- Copyright 2017-2019 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
-- stub lua controller for 19.07 backward compatibility
module("luci.controller.adblock", package.seeall)
local sys = require("luci.sys")
local util = require("luci.util")
local http = require("luci.http")
local i18n = require("luci.i18n")
local json = require("luci.jsonc")
local uci = require("luci.model.uci").cursor()
function index()
if not nixio.fs.access("/etc/config/adblock") then
return
end
entry({"admin", "services", "adblock"}, firstchild(), _("Adblock"), 30).dependent = false
entry({"admin", "services", "adblock", "tab_from_cbi"}, cbi("adblock/overview_tab", {hideresetbtn=true, hidesavebtn=true}), _("Overview"), 10).leaf = true
if nixio.fs.access("/usr/sbin/tcpdump") then
entry({"admin", "services", "adblock", "report"}, template("adblock/report"), _("DNS Query Report"), 20).leaf = true
end
entry({"admin", "services", "adblock", "log"}, template("adblock/logread"), _("Logfile"), 30).leaf = true
entry({"admin", "services", "adblock", "advanced"}, firstchild(), _("Advanced"), 100)
entry({"admin", "services", "adblock", "advanced", "blacklist"}, form("adblock/blacklist_tab"), _("Edit Blacklist"), 110).leaf = true
entry({"admin", "services", "adblock", "advanced", "whitelist"}, form("adblock/whitelist_tab"), _("Edit Whitelist"), 120).leaf = true
entry({"admin", "services", "adblock", "advanced", "configuration"}, form("adblock/configuration_tab"), _("Edit Configuration"), 130).leaf = true
entry({"admin", "services", "adblock", "advanced", "query"}, template("adblock/query"), _("Query domains"), 140).leaf = true
entry({"admin", "services", "adblock", "advanced", "result"}, call("queryData"), nil, 150).leaf = true
entry({"admin", "services", "adblock", "logread"}, call("logread"), nil).leaf = true
entry({"admin", "services", "adblock", "status_update"}, call("status_update"), nil).leaf = true
entry({"admin", "services", "adblock", "report_json"}, call("report_json"), nil).leaf = true
entry({"admin", "services", "adblock", "report_text"}, call("report_text"), nil).leaf = true
entry({"admin", "services", "adblock", "action"}, call("adb_action"), nil).leaf = true
end
function adb_action(name, ...)
local domain = select(1, ...) or ""
local search = select(2, ...) or "+"
local count = select(3, ...) or "50"
local filter = select(4, ...) or "false"
local print = select(5, ...) or "false"
local report_params = {
search,
count,
filter,
print
}
if name == "do_suspend" then
luci.sys.call("/etc/init.d/adblock suspend >/dev/null 2>&1")
elseif name == "do_resume" then
luci.sys.call("/etc/init.d/adblock resume >/dev/null 2>&1")
elseif name == "do_refresh" then
luci.sys.call("/etc/init.d/adblock reload >/dev/null 2>&1")
elseif name == "do_report" then
luci.sys.call("/etc/init.d/adblock report " ..table.concat(report_params, " ").. " >/dev/null 2>&1")
local rep_dir = uci:get("adblock", "extra", "adb_repdir") or "/tmp"
repeat
nixio.nanosleep(1)
until not nixio.fs.access(rep_dir.. "/adb_report.raw")
elseif name == "do_filter" then
luci.sys.call("/etc/init.d/adblock report " ..table.concat(report_params, " ").. " >/dev/null 2>&1")
local rep_dir = uci:get("adblock", "extra", "adb_repdir") or "/tmp"
repeat
nixio.nanosleep(1)
until nixio.fs.access(rep_dir.. "/adb_report.final")
elseif name == "add_blacklist" then
local file = uci:get("adblock", "blacklist", "adb_src") or "/etc/adblock/adblock.blacklist"
if nixio.fs.access(file) then
local blacklist = nixio.fs.readfile(file)
if not string.find(blacklist, domain, 1, true)
then
nixio.fs.writefile(file, blacklist.. domain.. "\n")
end
end
elseif name == "add_whitelist" then
local file = uci:get("adblock", "global", "adb_whitelist") or "/etc/adblock/adblock.whitelist"
if nixio.fs.access(file) then
local whitelist = nixio.fs.readfile(file)
if not string.find(whitelist, domain, 1, true)
then
nixio.fs.writefile(file, whitelist.. domain.. "\n")
end
end
end
if name == "do_suspend" or name == "do_resume" or name == "do_refresh" then
local pid_file = "/var/run/adblock.pid"
if nixio.fs.access(pid_file) then
repeat
nixio.nanosleep(1)
until nixio.fs.readfile(pid_file) == ""
end
end
luci.http.prepare_content("text/plain")
luci.http.write("0")
end
function status_update()
local rt_file
local content
rt_file = uci:get("adblock", "global", "adb_rtfile") or "/tmp/adb_runtime.json"
if nixio.fs.access(rt_file) then
content = json.parse(nixio.fs.readfile(rt_file) or "")
http.prepare_content("application/json")
http.write_json(content)
end
end
function report_json()
local rep_dir
local rep_file
local content
rep_dir = uci:get("adblock", "extra", "adb_repdir") or "/tmp"
rep_file = rep_dir.. "/adb_report.json"
http.prepare_content("application/json")
if nixio.fs.access(rep_file) then
content = json.parse(nixio.fs.readfile(rep_file) or "")
http.write_json(content)
else
http.write_json("{}")
end
end
function report_text()
local file
local rep_dir
local rep_file
local content
rep_dir = uci:get("adblock", "extra", "adb_repdir") or "/tmp"
rep_file = rep_dir.. "/adb_report.final"
http.prepare_content("text/plain")
if nixio.fs.access(rep_file) then
file = io.open(rep_file, "r")
content = file:read("*all")
file:close()
http.write(content)
else
http.write("")
end
end
function logread()
local content = util.trim(util.exec("logread -e 'adblock-'")) or ""
if content == "" then
content = "No adblock related logs yet!"
end
http.write(content)
end
function queryData(domain)
if domain then
luci.http.prepare_content("text/plain")
local cmd = "/etc/init.d/adblock query %s 2>&1"
local util = io.popen(cmd % util.shellquote(domain))
if util then
while true do
local line = util:read("*l")
if not line then
break
end
luci.http.write(line)
luci.http.write("\n")
end
util:close()
end
end
entry({"admin", "services", "adblock"}, firstchild(), _("Adblock"), 60)
entry({"admin", "services", "adblock", "overview"}, view("adblock/overview"), _("Overview"), 10)
entry({"admin", "services", "adblock", "dnsreport"}, view("adblock/dnsreport"), _("DNS Report"), 20)
entry({"admin", "services", "adblock", "blacklist"}, view("adblock/blacklist"), _("Edit Blacklist"), 30)
entry({"admin", "services", "adblock", "whitelist"}, view("adblock/whitelist"), _("Edit Whitelist"), 40)
entry({"admin", "services", "adblock", "logread"}, view("adblock/logread"), _("Log View"), 50)
end

View file

@ -1,55 +0,0 @@
-- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs")
local util = require("luci.util")
local uci = require("luci.model.uci").cursor()
local input = uci:get("adblock", "blacklist", "adb_src") or "/etc/adblock/adblock.blacklist"
if not fs.access(input) then
m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
m.reset = false
m.submit = false
return m
end
if fs.stat(input).size >= 102400 then
m = SimpleForm("error", nil,
translate("The file size is too large for online editing in LuCI (&ge; 100 KB). ")
.. translate("Please edit this file directly in a terminal session."))
m.reset = false
m.submit = false
return m
end
m = SimpleForm("input", nil)
m:append(Template("adblock/adblock_css"))
m.submit = translate("Save")
m.reset = false
s = m:section(SimpleSection, nil,
translatef("This form allows you to modify the content of the adblock blacklist (%s). ", input)
.. translate("Please add only one domain per line. Comments introduced with '#' are allowed - ip addresses, wildcards and regex are not."))
f = s:option(TextValue, "data")
f.datatype = "string"
f.rows = 20
f.rmempty = true
function f.cfgvalue()
return fs.readfile(input) or ""
end
function f.write(self, section, data)
return fs.writefile(input, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
end
function f.remove(self, section, value)
return fs.writefile(input, "")
end
function s.handle(self, state, data)
return true
end
return m

View file

@ -1,52 +0,0 @@
-- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs")
local util = require("luci.util")
local input = "/etc/config/adblock"
if not fs.access(input) then
m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
m.reset = false
m.submit = false
return m
end
if fs.stat(input).size >= 102400 then
m = SimpleForm("error", nil,
translate("The file size is too large for online editing in LuCI (&ge; 100 KB). ")
.. translate("Please edit this file directly in a terminal session."))
m.reset = false
m.submit = false
return m
end
m = SimpleForm("input", nil)
m:append(Template("adblock/adblock_css"))
m.submit = translate("Save")
m.reset = false
s = m:section(SimpleSection, nil,
translate("This form allows you to modify the content of the main adblock configuration file (/etc/config/adblock)."))
f = s:option(TextValue, "data")
f.rows = 20
f.rmempty = true
function f.cfgvalue()
return fs.readfile(input) or ""
end
function f.write(self, section, data)
return fs.writefile(input, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
end
function f.remove(self, section, value)
return fs.writefile(input, "")
end
function s.handle(self, state, data)
return true
end
return m

View file

@ -1,267 +0,0 @@
-- Copyright 2017-2019 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs")
local uci = require("luci.model.uci").cursor()
local util = require("luci.util")
local net = require "luci.model.network".init()
local dump = util.ubus("network.interface", "dump", {})
m = Map("adblock", translate("Adblock"),
translate("Configuration of the adblock package to block ad/abuse domains by using DNS. ")
..translatef("For further information "
.. "<a href=\"%s\" target=\"_blank\">"
.. "check the online documentation</a>", "https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md"))
-- Main adblock options
s = m:section(NamedSection, "global", "adblock")
o1 = s:option(Flag, "adb_enabled", translate("Enable Adblock"))
o1.default = o1.disabled
o1.rmempty = false
o2 = s:option(ListValue, "adb_dns", translate("DNS Backend (DNS Directory)"),
translate("List of supported DNS backends with their default list export directory. ")
..translate("To overwrite the default path use the 'DNS Directory' option in the extra section below."))
o2:value("dnsmasq", "dnsmasq (/tmp)")
o2:value("unbound", "unbound (/var/lib/unbound)")
o2:value("named", "named (/var/lib/bind)")
o2:value("kresd", "kresd (/etc/kresd)")
o2.default = "dnsmasq (/tmp)"
o2.rmempty = false
o3 = s:option(ListValue, "adb_dnsvariant", translate("DNS Blocking Variant"),
translate("List of supported DNS blocking variants. By default 'nxdomain' will be used for all DNS backends. ")
..translate("Dnsmasq also supports 'null' block variants, which may provide better response times."))
o3:value("nxdomain", "nxdomain, all DNS backends")
o3:value("null (IPv4)", "null (IPv4), dnsmasq only")
o3:value("null (IPv4/IPv6)", "null (IPv4/IPv6), dnsmasq only")
o3.default = "nxdomain, all DNS backends"
o3.rmempty = false
o4 = s:option(ListValue, "adb_fetchutil", translate("Download Utility"),
translate("List of supported and fully pre-configured download utilities."))
o4:value("uclient-fetch")
o4:value("wget")
o4:value("curl")
o4:value("aria2c")
o4:value("wget-nossl", "wget-nossl (noSSL)")
o4:value("busybox", "wget-busybox (noSSL)")
o4.default = "uclient-fetch"
o4.rmempty = false
o5 = s:option(ListValue, "adb_trigger", translate("Startup Trigger"),
translate("List of available network interfaces. Usually the startup will be triggered by the 'wan' interface. ")
..translate("Choose 'none' to disable automatic startups, 'timed' to use a classic timeout (default 30 sec.) or select another trigger interface."))
o5:value("none")
o5:value("timed")
if dump then
local i, v
for i, v in ipairs(dump.interface) do
if v.interface ~= "loopback" then
local device = v.l3_device or v.device or "-"
o5:value(v.interface, v.interface.. " (" ..device.. ")")
end
end
end
o5.rmempty = false
-- Runtime information
ds = s:option(DummyValue, "_dummy")
ds.template = "adblock/runtime"
-- Blocklist table
bl = m:section(TypedSection, "source", translate("Blocklist Sources"),
translate("<b>Caution:</b> To prevent OOM exceptions on low memory devices with less than 64 MB free RAM, please only select a few of them!"))
bl.template = "adblock/blocklist"
name = bl:option(Flag, "enabled", translate("Enabled"))
name.rmempty = false
ssl = bl:option(DummyValue, "adb_src", translate("SSL req."))
function ssl.cfgvalue(self, section)
local source = self.map:get(section, "adb_src")
if source and source:match("https://") then
return translate("Yes")
else
return translate("No")
end
end
des = bl:option(DummyValue, "adb_src_desc", translate("Description"))
cat = bl:option(DynamicList, "adb_src_cat", translate("Archive Categories"))
cat.datatype = "uciname"
cat.optional = true
-- Extra options
e = m:section(NamedSection, "extra", "adblock", translate("Extra Options"),
translate("Options for further tweaking in case the defaults are not suitable for you."))
e1 = e:option(Flag, "adb_debug", translate("Verbose Debug Logging"),
translate("Enable verbose debug logging in case of any processing error."))
e1.rmempty = false
e2 = e:option(Flag, "adb_nice", translate("Low Priority Service"),
translate("Set the nice level to 'low priority' and the adblock background processing will take fewer resources from the system. ")
..translate("This change requires a manual service stop/re-start to take effect."))
e2.disabled = "0"
e2.enabled = "10"
e2.rmempty = false
e3 = e:option(Flag, "adb_forcedns", translate("Force Local DNS"),
translate("Redirect all DNS queries from 'lan' zone to the local resolver, applies to udp and tcp protocol on ports 53, 853 and 5353."))
e3.rmempty = false
e4 = e:option(Value, "adb_maxqueue", translate("Max. Download Queue"),
translate("Size of the download queue to handle downloads &amp; list processing in parallel (default '4'). ")
..translate("For further performance improvements you can raise this value, e.g. '8' or '16' should be safe."))
e4.default = 4
e4.datatype = "range(1,32)"
e4.rmempty = false
e5 = e:option(Flag, "adb_dnsfilereset", translate("DNS File Reset"),
translate("Resets the final DNS blockfile 'adb_list.overall' after loading through the DNS backend. ")
..translate("This option saves an enormous amount of storage space, but starts a small ubus/adblock monitor in the background."))
e5.disabled = "false"
e5.enabled = "true"
e5.rmempty = false
e6 = e:option(Flag, "adb_report", translate("DNS Query Report"),
translate("Gather dns related network traffic via tcpdump to provide a DNS Query Report on demand. ")
..translate("Please note: this needs manual 'tcpdump-mini' package installation."))
e6.rmempty = false
e7 = e:option(Value, "adb_repdir", translate("Report Directory"),
translate("Target directory for dns related report files. Default is '/tmp', please use preferably a non-volatile disk if available."))
e7:depends("adb_report", 1)
e7.datatype = "directory"
e7.default = "/tmp"
e7.rmempty = true
e8 = e:option(Value, "adb_backupdir", translate("Backup Directory"),
translate("Target directory for adblock source backups. Default is '/tmp', please use preferably a non-volatile disk if available."))
e8.datatype = "directory"
e8.default = "/tmp"
e8.rmempty = true
e9 = e:option(Flag, "adb_mail", translate("E-Mail Notification"),
translate("Send notification E-Mails in case of a processing error or if domain count is &le; 0. ")
.. translate("Please note: this needs manual 'msmtp' package installation and setup."))
e9.rmempty = true
e10 = e:option(Value, "adb_mreceiver", translate("E-Mail Receiver Address"),
translate("Receiver address for adblock notification E-Mails."))
e10:depends("adb_mail", 1)
e10.rmempty = true
-- Optional Extra Options
e20 = e:option(Value, "adb_dnsdir", translate("DNS Directory"),
translate("Target directory for the generated blocklist 'adb_list.overall'."))
e20.datatype = "directory"
e20.optional = true
e21 = e:option(Value, "adb_blacklist", translate("Blacklist File"),
translate("Full path to the blacklist file."))
e21.datatype = "file"
e21.default = "/etc/adblock/adblock.blacklist"
e21.optional = true
e22 = e:option(Value, "adb_whitelist", translate("Whitelist File"),
translate("Full path to the whitelist file."))
e22.datatype = "file"
e22.default = "/etc/adblock/adblock.whitelist"
e22.optional = true
e23 = e:option(Value, "adb_triggerdelay", translate("Trigger Delay"),
translate("Additional trigger delay in seconds before adblock processing begins."))
e23.datatype = "range(1,60)"
e23.optional = true
e24 = e:option(Value, "adb_maxtld", translate("TLD Compression Threshold"),
translate("Disable the toplevel domain compression, if the number of blocked domains is greater than this threshold."))
e24.datatype = "min(0)"
e24.default = 100000
e24.optional = true
e25 = e:option(Value, "adb_portlist", translate("Local FW/DNS Ports"),
translate("Space separated list of firewall ports which should be redirected locally."))
e25.default = "53 853 5353"
e25.optional = true
e26 = e:option(Flag, "adb_dnsinotify", translate("DNS Inotify"),
translate("Disable adblock triggered restarts and the 'DNS File Reset' for dns backends with autoload features."))
e26.default = nil
e26.enabled = "true"
e26.optional = true
e27 = e:option(Flag, "adb_dnsflush", translate("Flush DNS Cache"),
translate("Flush DNS Cache after adblock processing."))
e27.default = nil
e27.optional = true
e28 = e:option(ListValue, "adb_repiface", translate("Report Interface"),
translate("Reporting interface used by tcpdump, set to 'any' for multiple interfaces (default 'br-lan'). ")
..translate("This change requires a manual service stop/re-start to take effect."))
if dump then
local i, v
for i, v in ipairs(dump.interface) do
if v.interface ~= "loopback" then
local device = v.device
if device then
e28:value(device)
end
end
end
end
e28:value("any")
e28.optional = true
e29 = e:option(Value, "adb_replisten", translate("Report Listen Port(s)"),
translate("Space separated list of reporting port(s) used by tcpdump (default: '53'). ")
..translate("This change requires a manual service stop/re-start to take effect."))
e29.default = 53
e29.optional = true
e30 = e:option(Value, "adb_repchunkcnt", translate("Report Chunk Count"),
translate("Report chunk count used by tcpdump (default '5'). ")
..translate("This change requires a manual service stop/re-start to take effect."))
e30.datatype = "range(1,10)"
e30.default = 5
e30.optional = true
e31 = e:option(Value, "adb_repchunksize", translate("Report Chunk Size"),
translate("Report chunk size used by tcpdump in MB (default '1'). ")
..translate("This change requires a manual service stop/re-start to take effect."))
e31.datatype = "range(1,10)"
e31.default = 1
e31.optional = true
e32 = e:option(Value, "adb_msender", translate("E-Mail Sender Address"),
translate("Sender address for adblock notification E-Mails."))
e32.default = "no-reply@adblock"
e32.optional = true
e33 = e:option(Value, "adb_mtopic", translate("E-Mail Topic"),
translate("Topic for adblock notification E-Mails."))
e33.default = "adblock notification"
e33.optional = true
e34 = e:option(Value, "adb_mprofile", translate("E-Mail Profile"),
translate("Mail profile used in 'msmtp' for adblock notification E-Mails."))
e34.default = "adb_notify"
e34.optional = true
e35 = e:option(Value, "adb_mcnt", translate("E-Mail Notification Count"),
translate("Raise the minimum notification count, to get E-Mails if the overall count is less or equal to the given limit (default 0), ")
.. translate("e.g. to receive an E-Mail notification with every adblock run set this value to 200000."))
e35.default = 0
e35.datatype = "min(0)"
e35.optional = true
return m

View file

@ -1,55 +0,0 @@
-- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs")
local util = require("luci.util")
local uci = require("luci.model.uci").cursor()
local input = uci:get("adblock", "global", "adb_whitelist") or "/etc/adblock/adblock.whitelist"
if not fs.access(input) then
m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
m.reset = false
m.submit = false
return m
end
if fs.stat(input).size >= 102400 then
m = SimpleForm("error", nil,
translate("The file size is too large for online editing in LuCI (&ge; 100 KB). ")
.. translate("Please edit this file directly in a terminal session."))
m.reset = false
m.submit = false
return m
end
m = SimpleForm("input", nil)
m:append(Template("adblock/adblock_css"))
m.submit = translate("Save")
m.reset = false
s = m:section(SimpleSection, nil,
translatef("This form allows you to modify the content of the adblock whitelist (%s). ", input)
.. translate("Please add only one domain per line. Comments introduced with '#' are allowed - ip addresses, wildcards and regex are not."))
f = s:option(TextValue, "data")
f.datatype = "string"
f.rows = 20
f.rmempty = true
function f.cfgvalue()
return fs.readfile(input) or ""
end
function f.write(self, section, data)
return fs.writefile(input, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
end
function f.remove(self, section, value)
return fs.writefile(input, "")
end
function s.handle(self, state, data)
return true
end
return m

View file

@ -1,86 +0,0 @@
<style type="text/css">
textarea
{
width: 100% !important;
height: 450px !important;
border: 1px solid #cccccc;
padding: 5px;
font-size: 12px;
font-family: monospace;
resize: none;
white-space: pre;
overflow-wrap: normal;
overflow-x: scroll;
}
select[readonly],
textarea[readonly]
{
width: 100% !important;
height: 450px !important;
border: 1px solid #cccccc;
padding: 5px;
font-size: 12px;
font-family: monospace;
resize: none;
pointer-events: auto;
cursor: auto;
}
.table.cbi-section-table .th,
.table.cbi-section-table .td,
.cbi-section-table-cell,
.cbi-section-table-row,
.tr[data-title]::before
{
text-align: left !important;
vertical-align: top;
margin-left: 0px;
padding-left: 2px;
}
.table.cbi-section-table .th
{
white-space: nowrap;
}
.cbi-section-table-row > .cbi-value-field .cbi-input-select,
.table.cbi-section-table select
{
width: 70px;
}
.item,
.add-item
{
white-space: nowrap;
width: 8.2em;
}
.cbi-input-checkbox
{
height: 1em;
}
.cbi-button
{
-webkit-appearance: menulist;
}
.runtime
{
color: #37c;
font-weight: bold;
display: inline-block;
width: 100%;
padding-top: 0.5rem;
}
.button_running
{
display: inline-block;
width: 16px;
height: 16px;
margin: 0 5px;
}
</style>

View file

@ -1,47 +0,0 @@
<%#
Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
This is free software, licensed under the Apache License, Version 2.0
-%>
<%-
local anonclass = (not self.anonymous or self.sectiontitle) and "named" or "anonymous"
-%>
<%+adblock/adblock_css%>
<div class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<% if self.title then -%>
<h3><%=self.title%></h3>
<%- end %>
<div class="cbi-section-descr"><%=self.description%></div>
<div class="cbi-section-node">
<div class="table cbi-section-table">
<div class="tr cbi-section-table-titles <%=anonclass%>">
<%- for i, k in pairs(self.children) do -%>
<div class="th cbi-section-table-cell">
<%-=k.title-%>
</div>
<%- end -%>
</div>
<%- local section, scope, isempty = true
for i, k in ipairs(self:cfgsections()) do
section = k
local sectionname = striptags((type(self.sectiontitle) == "function") and self:sectiontitle(section) or k)
local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname, true)
isempty = false
scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" }
-%>
<div class="tr cbi-section-table-row" id="cbi-<%=self.config%>-<%=section%>"<%=sectiontitle%>>
<%-
for k, node in ipairs(self.children) do
node:render(section, scope or {})
end
if not scope.cbid:match("adb_src_cat") then
-%>
<div class="td cbi-value-field">&#160;</div>
<%- end -%>
</div>
<%- end -%>
</div>
</div>
</div>

View file

@ -1,36 +0,0 @@
<%#
Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
This is free software, licensed under the Apache License, Version 2.0
-%>
<%+header%>
<%+adblock/adblock_css%>
<script type="text/javascript">
//<![CDATA[
function log_update()
{
XHR.poll(-1, '<%=luci.dispatcher.build_url("admin", "services", "adblock", "logread")%>', null,
function(x)
{
if (!x)
{
return;
}
var view = document.getElementById("view_id");
view.value = x.responseText;
view.scrollTop = view.scrollHeight;
});
}
window.onload = log_update();
//]]>
</script>
<div class="cbi-map">
<div class="cbi-section">
<div class="cbi-section-descr"><%:The syslog output, pre-filtered for adblock related messages only.%></div>
<textarea id="view_id" readonly="readonly" wrap="off" value=""></textarea>
</div>
</div>
<%+footer%>

View file

@ -1,64 +0,0 @@
<%#
Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
This is free software, licensed under the Apache License, Version 2.0
-%>
<%+header%>
<script type="text/javascript">
//<![CDATA[
var stxhr = new XHR();
function update_status(data)
{
var domain = data.value || data.placeholder;
var input = document.getElementById('query_input');
var output = document.getElementById('query_output');
if (input && output)
{
output.innerHTML =
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
'<%:Waiting for command to complete...%>'
;
input.parentNode.style.display = 'block';
input.style.display = 'inline';
stxhr.post('<%=luci.dispatcher.build_url('admin/services/adblock/advanced/result/')%>' + domain, { token: '<%=token%>' },
function(x)
{
if (x.responseText)
{
input.style.display = 'none';
output.innerHTML = String.format('<pre>%h</pre>', x.responseText);
}
else
{
input.style.display = 'none';
output.innerHTML = '<span class="error"><%:Blocklist not found!%></span>';
}
}
);
}
}
//]]>
</script>
<form method="post" action="<%=REQUEST_URI%>" onsubmit="update_status(this.input); return false;">
<div class="cbi-map">
<div class="cbi-section">
<div class="cbi-section-descr"><%:This form allows you to query active block lists for certain domains, e.g. for whitelisting.%></div>
<div style="width:33%; float:left;">
<input type="text" placeholder="google.com" name="input" />
<input type="button" value="<%:Query%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.input)" />
</div>
<br style="clear:both" />
<br />
</div>
</div>
<div class="cbi-section" style="display:none">
<h3 id="query_input"><%:Collecting data...%></h3>
<span id="query_output"></span>
</div>
</form>
<%+footer%>

View file

@ -1,310 +0,0 @@
<%#
Copyright 2017-2019 Dirk Brenken (dev@brenken.org)
This is free software, licensed under the Apache License, Version 2.0
-%>
<%+header%>
<%+adblock/adblock_css%>
<script type="text/javascript">
//<![CDATA[
function report_json(json)
{
document.getElementById("value_1").innerHTML = json.data.start_date + ", " + json.data.start_time || "-";
document.getElementById("value_2").innerHTML = json.data.end_date + ", " + json.data.end_time || "-";
document.getElementById("value_3").innerHTML = json.data.total || "-";
document.getElementById("value_4").innerHTML = json.data.blocked + " (" + json.data.percent + ")" || "-";
var a_cnt;
var b_cnt;
var c_cnt;
var a_val;
var b_val;
var c_val;
var s = '<div class="tr table-titles">';
s += '<div class="th left"><%:Count%></div>';
s += '<div class="th left"><%:Name / IP-Address%></div>';
s += '<div class="th left"><%:Count%></div>';
s += '<div class="th left"><%:Domain%></div>';
s += '<div class="th left"><%:Count%></div>';
s += '<div class="th left"><%:Blocked Domain%></div></div>';
for(var i=0;i<10;i++)
{
if (i < json.top_clients.length)
{
a_cnt = json.top_clients[i].count;
a_val = json.top_clients[i].address;
}
else
{
a_cnt = "-";
a_val = "";
}
if (i < json.top_domains.length)
{
b_cnt = json.top_domains[i].count;
b_val = json.top_domains[i].address;
}
else
{
b_cnt = "-";
b_val = "";
}
if (i < json.top_blocked.length)
{
c_cnt = json.top_blocked[i].count;
c_val = json.top_blocked[i].address;
}
else
{
c_cnt = "-";
c_val = "";
}
s += '<div class="tr left">';
s += '<div class="td left" data-title="<%:Count%>">' + a_cnt + '</div>';
s += '<div class="td left" data-title="<%:Name / IP-Address%>">' + a_val + '</div>';
s += '<div class="td left" data-title="<%:Count%>">' + b_cnt + '</div>';
s += '<div class="td left" data-title="<%:Domain%>">' + b_val + '</div>';
s += '<div class="td left" data-title="<%:Count%>">' + c_cnt + '</div>';
s += '<div class="td left" data-title="<%:Blocked Domain%>">' + c_val + '</div></div>';
}
document.getElementById("value_5").innerHTML = s;
}
function report_text(text)
{
var s = '<div class="tr table-titles">';
s += '<div class="th left"><%:Date%></div>';
s += '<div class="th left"><%:Time%></div>';
s += '<div class="th left"><%:Client%></div>';
s += '<div class="th left"><%:Domain%></div>';
s += '<div class="th left"><%:Answer%></div>';
s += '<div class="th left"><%:Action%></div></div>';
var btn1;
var record;
var title_arr = ["<%:Date%>", "<%:Time%>", "<%:Client%>", "<%:Domain%>", "<%:Answer%>", "<%:Action%>"];
var array = text.split("\n");
for (var i=0;i<array.length;i++)
{
record = array[i].split("\t");
if (record[0] && record[0] != "undefined")
{
s += '<div class="tr left">';
for (var j=0;j<5;j++)
{
s += '<div class="td left" data-title="' + title_arr[j] + '">' + record[j] + '</div>';
if (record[4] === "NX")
{
btn1 = '<div class="td left" data-title="' + title_arr[5] + '"><input type="button" class="cbi-button cbi-button-edit" name="add_whitelist,' + record[3] + '" value="<%:Whitelist%>" onclick="btn_action(this)" /></div>';
}
else if (record[4] === "OK")
{
btn1 = '<div class="td left" data-title="' + title_arr[5] + '"><input type="button" class="cbi-button cbi-button-remove" name="add_blacklist,' + record[3] + '" value="<%:Blacklist%>" onclick="btn_action(this)" /></div>';
}
else
{
btn1 = '-'
}
}
s += btn1 + '</div>'
}
}
document.getElementById("value_6").innerHTML = s;
}
function btn_action(value)
{
var action = value.name.split(",");
if (action[0] === "do_report")
{
var btn1 = document.getElementById("btn1");
var btn1_running = document.getElementById("btn1_running");
btn1.disabled = true;
running(btn1_running, 1);
document.getElementById("filter_search").value = '';
document.getElementById("filter_count").selectedIndex = 1;
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock")%>/action/' + action[0], null,
function(x)
{
if (!x)
{
return;
}
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock", "report_json")%>', null,
function(x, json_info)
{
if (!x || !json_info || !json_info.data)
{
running(btn1_running, 0);
btn1.disabled = false;
return;
}
report_json(json_info);
});
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock", "report_text")%>', null,
function(x)
{
if (!x || !x.responseText)
{
return;
}
report_text(x.responseText);
running(btn1_running, 0);
btn1.disabled = false;
});
});
}
else if (action[0] === "do_filter")
{
var btn2 = document.getElementById("btn2");
var btn2_running = document.getElementById("btn2_running");
var search = document.getElementById("filter_search").value.replace(/[^\x00-\x7F]|[\s!@#$%^&*()+=\[\]{};'"\\|,<>\/?]/g,'') || "\"+\"";
var count = document.getElementById("filter_count").value;
btn2.disabled = true;
running(btn2_running, 1);
if (search != "\"+\"")
{
document.getElementById("filter_search").value = search;
}
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock")%>/action/' + action[0] + "/" + "-" + "/" + search + "/" + count + "/" + "true" + "/" + "false", null,
function(x)
{
if (!x)
{
return;
}
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock", "report_text")%>', null,
function(x)
{
if (!x || !x.responseText)
{
return;
}
report_text(x.responseText);
running(btn2_running, 0);
btn2.disabled = false;
});
});
}
else if (action[0] === "add_blacklist" || action[0] === "add_whitelist")
{
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock")%>/action/' + action[0] + "/" + action[1], null,
function(x)
{
if (!x)
{
return;
}
btn3 = document.getElementsByName(value.name);
for (var i=0; i<btn3.length; i++)
{
btn3[i].disabled = true;
}
});
}
}
function running(element, state)
{
if (state === 1)
{
var running_html = '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" width="16" height="16" style="vertical-align:middle" />';
element.innerHTML = running_html;
}
else
{
element.innerHTML = '';
}
}
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock", "report_json")%>', null,
function(x, json_info)
{
if (!x || !json_info || !json_info.data)
{
running(btn1_running, 0);
btn1.disabled = false;
return;
}
report_json(json_info);
});
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock", "report_text")%>', null,
function(x)
{
if (!x || !x.responseText)
{
return;
}
report_text(x.responseText);
});
//]]>
</script>
<div class="cbi-section">
<div class="cbi-value" id="status_1">
<label class="cbi-value-title" for="status_1"><%:Start Date%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_1">-</span>
</div>
</div>
<div class="cbi-value" id="status_2">
<label class="cbi-value-title" for="status_2"><%:End Date%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_2">-</span>
</div>
</div>
<div class="cbi-value" id="status_3">
<label class="cbi-value-title" for="status_3"><%:Total DNS Queries%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_3">-</span>
</div>
</div>
<div class="cbi-value" id="status_4">
<label class="cbi-value-title" for="status_4"><%:Blocked DNS Queries%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_4">-</span>
</div>
</div>
<br />
<div id="button">
<input type="button" class="cbi-button cbi-button-action important" id="btn1" name="do_report" value="<%:Refresh Report%>" onclick="btn_action(this)" />
<span id="btn1_running" class="btn1_running"></span>
</div>
</div>
<br />
<div class="cbi-section">
<h3><%:Top 10 Reporting%></h3>
<div class="table" id="value_5"></div>
</div>
<hr />
<div class="cbi-section">
<div class="cbi-section-descr"><%:Filter the DNS Query result set for a particular domain, client or time frame.%></div>
<div style="float:left;">
<input type="text" placeholder="<%:Domain/Client/Date/Time%>" id="filter_search" name="filter_search" />
<select name="filter_count" id="filter_count">
<option value="25">25</option>
<option value="50" selected="selected">50</option>
<option value="100">100</option>
<option value="250">250</option>
<option value="500">500</option>
</select>
<input type="button" class="cbi-button cbi-button-action" id="btn2" name="do_filter" value="<%:Filter%>" onclick="btn_action(this)" />
<span id="btn2_running" class="btn2_running"></span>
</div>
<br />
<br />
<h3><%:Latest DNS Queries%></h3>
<div class="table" id="value_6"></div>
</div>
<%+footer%>

View file

@ -1,213 +0,0 @@
<%#
Copyright 2017-2019 Dirk Brenken (dev@brenken.org)
This is free software, licensed under the Apache License, Version 2.0
-%>
<%+adblock/adblock_css%>
<script type="text/javascript">
//<![CDATA[
function format(number)
{
var string = number.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.');
return string;
}
function status_update(json)
{
var btn1 = document.getElementById("btn1");
var btn1_running = document.getElementById("btn1_running");
var btn2 = document.getElementById("btn2");
var btn2_running = document.getElementById("btn2_running");
var input = json.data.adblock_status || "-";
document.getElementById("value_1").innerHTML = input;
if (input === "enabled")
{
btn1.value = "<%:Suspend%>";
btn1.name = "do_suspend";
btn2.value = "<%:Refresh%>";
btn2.name = "do_refresh";
btn1.disabled = false;
running(btn1_running, 0);
btn2.disabled = false;
running(btn2_running, 0);
}
else if (input === "paused")
{
btn1.value = "<%:Resume%>";
btn1.name = "do_resume";
btn2.value = "<%:Refresh%>";
btn2.name = "do_refresh";
btn1.disabled = false;
running(btn1_running, 0);
btn2.disabled = false;
running(btn2_running, 0);
}
else
{
btn1.value = "<%:Suspend%>";
btn1.name = "do_suspend";
btn2.value = "<%:Refresh%>";
btn2.name = "do_refresh";
btn1.disabled = true;
btn2.disabled = true;
}
document.getElementById("value_2").innerHTML = json.data.adblock_version || "-";
document.getElementById("value_3").innerHTML = json.data.fetch_utility || "-";
document.getElementById("value_4").innerHTML = json.data.dns_backend || "-";
document.getElementById("value_5").innerHTML = json.data.dns_variant || "-";
document.getElementById("value_6").innerHTML = json.data.backup_dir || "-";
document.getElementById("value_7").innerHTML = format(json.data.overall_domains) || "-";
document.getElementById("value_8").innerHTML = json.data.last_rundate || "-";
}
function btn_action(action)
{
var btn1 = document.getElementById("btn1");
var btn1_running = document.getElementById("btn1_running");
var btn2 = document.getElementById("btn2");
var btn2_running = document.getElementById("btn2_running");
btn1.disabled = true;
btn2.disabled = true;
if (action.name === "do_refresh")
{
running(btn2_running, 1);
}
else
{
running(btn1_running, 1);
}
new XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock")%>/action/' + action.name, null,
function(x)
{
if (!x)
{
return;
}
});
}
function running(element, state)
{
if (state === 1)
{
var running_html = '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" width="16" height="16" style="vertical-align:middle" />';
element.innerHTML = running_html;
}
else
{
element.innerHTML = '';
}
}
function reset_view()
{
document.getElementById("btn1").value = "<%:Suspend%>";
document.getElementById("btn1").name = "do_suspend";
document.getElementById("btn2").value = "<%:Refresh%>";
document.getElementById("btn2").name = "do_refresh";
document.getElementById("btn1").disabled = true;
document.getElementById("btn2").disabled = true;
document.getElementById("value_1").innerHTML = "-";
document.getElementById("value_2").innerHTML = "-";
document.getElementById("value_3").innerHTML = "-";
document.getElementById("value_4").innerHTML = "-";
document.getElementById("value_5").innerHTML = "-";
document.getElementById("value_6").innerHTML = "-";
document.getElementById("value_7").innerHTML = "-";
document.getElementById("value_8").innerHTML = "-";
}
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "adblock", "status_update")%>', null,
function(x, json_info)
{
if (!x || !json_info || !json_info.data)
{
reset_view();
return;
}
status_update(json_info);
});
XHR.poll(-1, '<%=luci.dispatcher.build_url("admin", "services", "adblock", "status_update")%>', null,
function(x, json_info)
{
if (!x || !json_info || !json_info.data)
{
reset_view();
return;
}
status_update(json_info);
});
//]]>
</script>
<h3><%:Runtime Information%></h3>
<div class="cbi-value" id="status_1">
<label class="cbi-value-title" for="status_1"><%:Adblock Status%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_1">-</span>
</div>
</div>
<div class="cbi-value" id="status_2">
<label class="cbi-value-title" for="status_2"><%:Adblock Version%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_2">-</span>
</div>
</div>
<div class="cbi-value" id="status_3">
<label class="cbi-value-title" for="status_3"><%:Download Utility (SSL Library)%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_3">-</span>
</div>
</div>
<div class="cbi-value" id="status_4">
<label class="cbi-value-title" for="status_4"><%:DNS Backend, DNS Directory%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_4">-</span>
</div>
</div>
<div class="cbi-value" id="status_5">
<label class="cbi-value-title" for="status_5"><%:DNS Variant, DNS File Reset%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_5">-</span>
</div>
</div>
<div class="cbi-value" id="status_6">
<label class="cbi-value-title" for="status_6"><%:Backup Directory%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_6">-</span>
</div>
</div>
<div class="cbi-value" id="status_7">
<label class="cbi-value-title" for="status_7"><%:Overall Domains%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_7">-</span>
</div>
</div>
<div class="cbi-value" id="status_8">
<label class="cbi-value-title" for="status_8"><%:Last Run%></label>
<div class="cbi-value-field">
<span class="runtime" id="value_8">-</span>
</div>
</div>
<hr />
<div class="cbi-value" id="button_1">
<label class="cbi-value-title" for="button_1"><%:Suspend / Resume Adblock%></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-reset" id="btn1" type="button" value="" onclick="btn_action(this)" />
<span id="btn1_running" class="btn_running"></span>
</div>
</div>
<p />
<div class="cbi-value" id="button_2">
<label class="cbi-value-title" for="button_2"><%:Refresh Blocklist Sources%></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-apply" id="btn2" type="button" value="" onclick="btn_action(this)" />
<span id="btn2_running" class="btn_running"></span>
</div>
</div>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,11 +0,0 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@adblock[-1]
add ucitrack adblock
set ucitrack.@adblock[-1].init=adblock
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View file

@ -0,0 +1,57 @@
{
"admin/services/adblock": {
"title": "Adblock",
"order": "60",
"action": {
"type": "alias",
"path": "admin/services/adblock/overview"
},
"depends": {
"fs": {
"/usr/bin/adblock.sh": "executable",
"/etc/init.d/adblock": "executable"
},
"uci": { "adblock": true }
}
},
"admin/services/adblock/overview": {
"title": "Overview",
"order": 10,
"action": {
"type": "view",
"path": "adblock/overview"
}
},
"admin/services/adblock/dnsreport": {
"title": "DNS Report",
"order": 20,
"action": {
"type": "view",
"path": "adblock/dnsreport"
}
},
"admin/services/adblock/blacklist": {
"title": "Edit Blacklist",
"order": 30,
"action": {
"type": "view",
"path": "adblock/blacklist"
}
},
"admin/services/adblock/whitelist": {
"title": "Edit Whitelist",
"order": 40,
"action": {
"type": "view",
"path": "adblock/whitelist"
}
},
"admin/services/adblock/logread": {
"title": "Log View",
"order": 50,
"action": {
"type": "view",
"path": "adblock/logread"
}
}
}

View file

@ -0,0 +1,30 @@
{
"luci-app-adblock": {
"description": "Grant access to LuCI app adblock",
"write": {
"uci": ["adblock"],
"file": {
"/etc/adblock/*": ["read"],
"/etc/adblock/adblock.blacklist": ["write"],
"/etc/adblock/adblock.whitelist": ["write"]
}
},
"read": {
"cgi-io": [ "exec" ],
"file": {
"/var/run/adblock.pid": ["read"],
"/tmp/adb_runtime.json": ["read"],
"/etc/crontabs/root": ["read"],
"/sbin/logread -e adblock-": [ "exec" ],
"/usr/sbin/logread -e adblock-": [ "exec" ],
"/etc/init.d/adblock list" : [ "exec" ],
"/etc/init.d/adblock start" : [ "exec" ],
"/etc/init.d/adblock suspend" : [ "exec" ],
"/etc/init.d/adblock resume" : [ "exec" ],
"/etc/init.d/adblock report * [0-9]* [a-z]* json" : [ "exec" ],
"/etc/init.d/adblock timer * [0-9]* [0-9*]* [1-7,-*]*" : [ "exec" ],
"/etc/init.d/adblock query *" : [ "exec" ]
}
}
}
}