]);
},
handleSave: function (ev) {
- var value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n')) + '\n';
+ let value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n')) + '\n';
return fs.write('/etc/banip/banip.allowlist', value)
- .then(function (rc) {
+ .then(function () {
document.querySelector('textarea').value = value;
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
ui.addNotification(null, E('p', _('Allowlist modifications have been saved, start the Domain Lookup or restart banIP that changes take effect.')), 'info');
}).catch(function (e) {
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
ui.addNotification(null, E('p', _('Unable to save modifications: %s').format(e.message)), 'error');
});
},
render: function (allowlist) {
if (allowlist[0].size >= 100000) {
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
ui.addNotification(null, E('p', _('The allowlist is too big, unable to save modifications.')), 'error');
}
return E([
]);
},
handleSave: function (ev) {
- var value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n')) + '\n';
+ let value = ((document.querySelector('textarea').value || '').trim().toLowerCase().replace(/\r\n/g, '\n')) + '\n';
return fs.write('/etc/banip/banip.blocklist', value)
- .then(function (rc) {
+ .then(function () {
document.querySelector('textarea').value = value;
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
ui.addNotification(null, E('p', _('Blocklist modifications have been saved, start the Domain Lookup or restart banIP that changes take effect.')), 'info');
}).catch(function (e) {
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
ui.addNotification(null, E('p', _('Unable to save modifications: %s').format(e.message)), 'error');
});
},
render: function (blocklist) {
if (blocklist[0].size >= 100000) {
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
ui.addNotification(null, E('p', _('The blocklist is too big, unable to save modifications.')), 'error');
}
return E([
--- /dev/null
+.cbi-input-text {
+ width: 90% !important;
+}
\ No newline at end of file
--- /dev/null
+'use strict';
+'require view';
+'require form';
+'require fs';
+'require ui';
+
+/*
+ include custom CSS
+*/
+document.querySelector('head').appendChild(E('link', {
+ 'rel': 'stylesheet',
+ 'type': 'text/css',
+ 'href': L.resource('view/banip/custom.css')
+}));
+
+/*
+ observe DOM changes
+*/
+const observer = new MutationObserver(function (mutations) {
+ if (mutations) {
+ const inputs = document.querySelectorAll('input');
+ inputs.forEach(function (input) {
+ input.setAttribute('autocomplete', 'off')
+ input.setAttribute('autocorrect', 'off')
+ input.setAttribute('autocapitalize', 'off')
+ input.setAttribute('spellcheck', false)
+ })
+ const labels = document.querySelectorAll('label[for^="widget.cbid.json"][for$="name"]');
+ labels.forEach(function (label) {
+ label.setAttribute("style", "font-weight: bold !important; color: #595 !important;");
+ })
+ L.resolveDefault(fs.stat('/etc/banip/banip.custom.feeds'), '').then(function (stat) {
+ const buttons = document.querySelectorAll('#btnClear, #btnCreate, #btnSave');
+ if (buttons[0] && stat.size === 0) {
+ buttons[0].removeAttribute('disabled');
+ } else if (buttons[1] && buttons[2] && stat.size > 0) {
+ buttons[1].removeAttribute('disabled');
+ buttons[2].removeAttribute('disabled');
+ }
+ });
+ }
+});
+
+const targetNode = document.getElementById('view');
+const observerConfig = {
+ childList: true,
+ subtree: true,
+ attributes: false,
+ characterData: false
+};
+observer.observe(targetNode, observerConfig);
+
+/*
+ button handling
+*/
+function handleEdit(ev) {
+ if (ev === 'create') {
+ return fs.read_direct('/etc/banip/banip.feeds', 'json').then(function (content) {
+ fs.write('/etc/banip/banip.custom.feeds', JSON.stringify(content)).then(function () {
+ location.reload();
+ });
+ });
+ }
+ if (ev === 'clear') {
+ return fs.write('/etc/banip/banip.custom.feeds', null).then(function () {
+ location.reload();
+ });
+ }
+ if (ev === 'save') {
+ const invalid = document.querySelectorAll('.cbi-input-invalid');
+ if (invalid.length > 0) {
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
+ return ui.addNotification(null, E('p', _('Invalid input values, unable to save modifications.')), 'error');
+ }
+ }
+ let sumSubElements = [], exportJson;
+ const nodeKeys = document.querySelectorAll('[id^="widget.cbid.json"][id$="name"]');
+ for (let i = 0; i < nodeKeys.length; i++) {
+ let subElements = {};
+ let elements = document.querySelectorAll('[id^="widget.cbid.json.' + nodeKeys[i].id.split('.')[3] + '\."]');
+ for (const element of elements) {
+ let key = element.id.split('.')[4];
+ let value = element.value || "";
+ switch (key) {
+ case 'url_4':
+ subElements.url_4 = value;
+ break;
+ case 'rule_4':
+ subElements.rule_4 = value;
+ break;
+ case 'url_6':
+ subElements.url_6 = value;
+ break;
+ case 'rule_6':
+ subElements.rule_6 = value;
+ break;
+ case 'descr':
+ subElements.descr = value;
+ break;
+ case 'flag':
+ subElements.flag = value;
+ break;
+ }
+ }
+ sumSubElements.push(nodeKeys[i].value, subElements);
+ }
+ exportJson = JSON.stringify(sumSubElements).replace(/,{/g, ':{').replace(/^\[/g, '{').replace(/\]$/g, '}');
+ return fs.write('/etc/banip/banip.custom.feeds', exportJson).then(function () {
+ location.reload();
+ });
+}
+
+return view.extend({
+ load: function () {
+ return L.resolveDefault(fs.read_direct('/etc/banip/banip.custom.feeds', 'json'), "");
+ },
+
+ render: function (data) {
+ let m, s, o, feed, url_4, url_6, rule_4, rule_6, descr, flag;
+
+ m = new form.JSONMap(data, 'Custom Feed Editor', _('With this editor you can fill up an initial custom feed file (a 1:1 copy of the version shipped with the package). \
+ The file is located at \'/etc/banip/banip.custom.feeds\'. \
+ Then you can edit this file, delete entries, add new ones, etc. To go back to the maintainers version just empty the custom feed file again (do not delete it!).'));
+ for (let i = 0; i < Object.keys(m.data.data).length; i++) {
+ feed = Object.keys(m.data.data)[i];
+ url_4 = m.data.data[feed].url_4;
+ rule_4 = m.data.data[feed].rule_4;
+ url_6 = m.data.data[feed].url_6;
+ rule_6 = m.data.data[feed].rule_6;
+ descr = m.data.data[feed].descr;
+ flag = m.data.data[feed].flag;
+
+ s = m.section(form.TypedSection, feed, null);
+ s.addremove = true;
+ s.anonymous = true;
+
+ o = s.option(form.Value, 'name', _('Feed Name'));
+ o.ucioption = '.name';
+ o.datatype = 'and(minlength(3),maxlength(15))';
+ o.validate = function (section_id, value) {
+ if (!value) {
+ return _('Empty field not allowed');
+ }
+ if (!value.match(/^[a-z0-9]+$/)) {
+ return _('Invalid characters');
+ }
+ return true;
+ }
+
+ o = s.option(form.Value, 'url_4', _('URLv4'));
+ o.validate = function (section_id, value) {
+ if (!value) {
+ return true;
+ }
+ if (!value.match(/^(http:\/\/|https:\/\/)[A-Za-z0-9\/\.\-_\?\&=]+$/)) {
+ return _('Protocol/URL format not supported');
+ }
+ return true;
+ }
+
+ o = s.option(form.Value, 'rule_4', _('Rulev4'));
+
+ o = s.option(form.Value, 'url_6', _('URLv6'));
+ o.validate = function (section_id, value) {
+ if (!value) {
+ return true;
+ }
+ if (!value.match(/^(http:\/\/|https:\/\/)[A-Za-z0-9\/\.\-_\?\&=:]+$/)) {
+ return _('Protocol/URL format not supported');
+ }
+ return true;
+ }
+
+ o = s.option(form.Value, 'rule_6', _('Rulev6'));
+
+ o = s.option(form.Value, 'descr', _('Description'));
+ o.datatype = 'and(minlength(3),maxlength(30))';
+ o.validate = function (section_id, value) {
+ if (!value) {
+ return _('Empty field not allowed');
+ }
+ return true;
+ }
+
+ o = s.option(form.Value, 'flag', _('Flag'));
+ o.datatype = 'and(minlength(2),maxlength(2))';
+ o.validate = function (section_id, value) {
+ if (!value) {
+ return true;
+ }
+ if (!value.match(/^gz$/)) {
+ return _('Flag not supported');
+ }
+ return true;
+ }
+ }
+
+ s = m.section(form.NamedSection, 'global');
+ s.render = L.bind(function () {
+ return E('div', { class: 'right' }, [
+ E('button', {
+ 'class': 'btn cbi-button cbi-button-action important',
+ 'id': 'btnCreate',
+ 'disabled': 'disabled',
+ 'click': ui.createHandlerFn(this, function () {
+ return handleEdit('create');
+ })
+ }, [_('Fill Custom Feeds')]),
+ '\xa0\xa0\xa0',
+ E('button', {
+ 'class': 'btn cbi-button cbi-button-negative important',
+ 'id': 'btnClear',
+ 'disabled': 'disabled',
+ 'click': ui.createHandlerFn(this, function () {
+ return handleEdit('clear');
+ })
+ }, [_('Clear Custom Feeds')]),
+ '\xa0\xa0\xa0',
+ E('button', {
+ 'class': 'btn cbi-button cbi-button-positive important',
+ 'id': 'btnSave',
+ 'disabled': 'disabled',
+ 'click': ui.createHandlerFn(this, function () {
+ return handleEdit('save');
+ })
+ }, [_('Save Custom Feeds')])
+ ])
+ });
+ return m.render();
+ },
+ handleSaveApply: null,
+ handleSave: null,
+ handleReset: null
+});
'require form';
'require tools.widgets as widgets';
+/*
+ button handling
+*/
function handleAction(ev) {
fs.exec_direct('/etc/init.d/banip', [ev])
}
return view.extend({
load: function () {
return Promise.all([
+ L.resolveDefault(fs.read_direct('/etc/banip/banip.custom.feeds'), ''),
L.resolveDefault(fs.read_direct('/etc/banip/banip.feeds'), ''),
L.resolveDefault(fs.read_direct('/etc/banip/banip.countries'), ''),
uci.load('banip')
},
render: function (result) {
- var m, s, o;
+ let m, s, o;
m = new form.Map('banip', 'banIP', _('Configuration of the banIP package to ban incoming and outgoing ip addresses/subnets via sets in nftables. \
For further information <a href="https://github.com/openwrt/packages/blob/master/net/banip/files/README.md" target="_blank" rel="noreferrer noopener" >check the online documentation</a>'));
/*
poll runtime information
*/
- var buttons, rt_res, inf_stat, inf_version, inf_elements, inf_feeds, inf_devices, inf_subnets, inf_system, nft_infos, run_infos, inf_flags, last_run
+ let buttons, rtRes, infStat, infVer, infElements, infFeeds, infDevices, infSubnets, infSystem, nftInfos, runInfos, infFlags, last_run
pollData: poll.add(function () {
return L.resolveDefault(fs.stat('/var/run/banip.lock')).then(function (stat) {
buttons = document.querySelectorAll('.cbi-button');
- inf_stat = document.getElementById('status');
+ infStat = document.getElementById('status');
if (stat) {
- for (var i = 0; i < buttons.length; i++) {
+ for (let i = 0; i < buttons.length; i++) {
buttons[i].setAttribute('disabled', 'true');
}
- if (inf_stat && !inf_stat.classList.contains('spinning')) {
- inf_stat.classList.add('spinning');
+ if (infStat && !infStat.classList.contains('spinning')) {
+ infStat.classList.add('spinning');
}
} else {
- for (var i = 0; i < buttons.length; i++) {
+ for (let i = 0; i < buttons.length; i++) {
buttons[i].removeAttribute('disabled');
}
- if (inf_stat && inf_stat.classList.contains('spinning')) {
- inf_stat.classList.remove('spinning');
+ if (infStat && infStat.classList.contains('spinning')) {
+ infStat.classList.remove('spinning');
}
}
L.resolveDefault(fs.exec_direct('/etc/init.d/banip', ['status'])).then(function (result) {
if (result) {
- rt_res = result.trim().split('\n');
- if (rt_res) {
- for (var i = 0; i < rt_res.length; i++) {
- if (rt_res[i].match(/^\s+\+\sstatus\s+\:\s+(.*)$/)) {
- rt_res.status = rt_res[i].match(/^\s+\+\sstatus\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\sversion\s+\:\s+(.*)$/)) {
- rt_res.version = rt_res[i].match(/^\s+\+\sversion\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\selement_count\s+\:\s+(.*)$/)) {
- rt_res.element_count = rt_res[i].match(/^\s+\+\selement_count\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\sactive_feeds\s+\:\s+(.*)$/)) {
- rt_res.active_feeds = rt_res[i].match(/^\s+\+\sactive_feeds\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\sactive_devices\s+\:\s+(.*)$/)) {
- rt_res.active_devices = rt_res[i].match(/^\s+\+\sactive_devices\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\sactive_subnets\s+\:\s+(.*)$/)) {
- rt_res.active_subnets = rt_res[i].match(/^\s+\+\sactive_subnets\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\snft_info\s+\:\s+(.*)$/)) {
- rt_res.nft_info = rt_res[i].match(/^\s+\+\snft_info\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\srun_info\s+\:\s+(.*)$/)) {
- rt_res.run_info = rt_res[i].match(/^\s+\+\srun_info\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\srun_flags\s+\:\s+(.*)$/)) {
- rt_res.run_flags = rt_res[i].match(/^\s+\+\srun_flags\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\slast_run\s+\:\s+(.*)$/)) {
- rt_res.last_run = rt_res[i].match(/^\s+\+\slast_run\s+\:\s+(.*)$/)[1];
- } else if (rt_res[i].match(/^\s+\+\ssystem_info\s+\:\s+(.*)$/)) {
- rt_res.system_info = rt_res[i].match(/^\s+\+\ssystem_info\s+\:\s+(.*)$/)[1];
+ rtRes = result.trim().split('\n');
+ if (rtRes) {
+ for (let i = 0; i < rtRes.length; i++) {
+ if (rtRes[i].match(/^\s+\+\sstatus\s+\:\s+(.*)$/)) {
+ rtRes.status = rtRes[i].match(/^\s+\+\sstatus\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\sversion\s+\:\s+(.*)$/)) {
+ rtRes.version = rtRes[i].match(/^\s+\+\sversion\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\selement_count\s+\:\s+(.*)$/)) {
+ rtRes.elementCount = rtRes[i].match(/^\s+\+\selement_count\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\sactive_feeds\s+\:\s+(.*)$/)) {
+ rtRes.activeFeeds = rtRes[i].match(/^\s+\+\sactive_feeds\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\sactive_devices\s+\:\s+(.*)$/)) {
+ rtRes.activeDevices = rtRes[i].match(/^\s+\+\sactive_devices\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\sactive_subnets\s+\:\s+(.*)$/)) {
+ rtRes.activeSubnets = rtRes[i].match(/^\s+\+\sactive_subnets\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\snft_info\s+\:\s+(.*)$/)) {
+ rtRes.nftInfo = rtRes[i].match(/^\s+\+\snft_info\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\srun_info\s+\:\s+(.*)$/)) {
+ rtRes.runInfo = rtRes[i].match(/^\s+\+\srun_info\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\srun_flags\s+\:\s+(.*)$/)) {
+ rtRes.runFlags = rtRes[i].match(/^\s+\+\srun_flags\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\slast_run\s+\:\s+(.*)$/)) {
+ rtRes.lastRun = rtRes[i].match(/^\s+\+\slast_run\s+\:\s+(.*)$/)[1];
+ } else if (rtRes[i].match(/^\s+\+\ssystem_info\s+\:\s+(.*)$/)) {
+ rtRes.systemInfo = rtRes[i].match(/^\s+\+\ssystem_info\s+\:\s+(.*)$/)[1];
}
}
}
- if (rt_res) {
- inf_stat = document.getElementById('status');
- if (inf_stat) {
- inf_stat.textContent = rt_res.status || '-';
+ if (rtRes) {
+ infStat = document.getElementById('status');
+ if (infStat) {
+ infStat.textContent = rtRes.status || '-';
}
- inf_version = document.getElementById('version');
- if (inf_version) {
- inf_version.textContent = rt_res.version || '-';
+ infVer = document.getElementById('version');
+ if (infVer) {
+ infVer.textContent = rtRes.version || '-';
}
- inf_elements = document.getElementById('elements');
- if (inf_elements) {
- inf_elements.textContent = rt_res.element_count || '-';
+ infElements = document.getElementById('elements');
+ if (infElements) {
+ infElements.textContent = rtRes.elementCount || '-';
}
- inf_feeds = document.getElementById('feeds');
- if (inf_feeds) {
- inf_feeds.textContent = rt_res.active_feeds || '-';
+ infFeeds = document.getElementById('feeds');
+ if (infFeeds) {
+ infFeeds.textContent = rtRes.activeFeeds || '-';
}
- inf_devices = document.getElementById('devices');
- if (inf_devices) {
- inf_devices.textContent = rt_res.active_devices || '-';
+ infDevices = document.getElementById('devices');
+ if (infDevices) {
+ infDevices.textContent = rtRes.activeDevices || '-';
}
- inf_subnets = document.getElementById('subnets');
- if (inf_subnets) {
- inf_subnets.textContent = rt_res.active_subnets || '-';
+ infSubnets = document.getElementById('subnets');
+ if (infSubnets) {
+ infSubnets.textContent = rtRes.activeSubnets || '-';
}
- nft_infos = document.getElementById('nft');
- if (nft_infos) {
- nft_infos.textContent = rt_res.nft_info || '-';
+ nftInfos = document.getElementById('nft');
+ if (nftInfos) {
+ nftInfos.textContent = rtRes.nftInfo || '-';
}
- run_infos = document.getElementById('run');
- if (run_infos) {
- run_infos.textContent = rt_res.run_info || '-';
+ runInfos = document.getElementById('run');
+ if (runInfos) {
+ runInfos.textContent = rtRes.runInfo || '-';
}
- inf_flags = document.getElementById('flags');
- if (inf_flags) {
- inf_flags.textContent = rt_res.run_flags || '-';
+ infFlags = document.getElementById('flags');
+ if (infFlags) {
+ infFlags.textContent = rtRes.runFlags || '-';
}
last_run = document.getElementById('last');
if (last_run) {
- last_run.textContent = rt_res.last_run || '-';
+ last_run.textContent = rtRes.lastRun || '-';
}
- inf_system = document.getElementById('system');
- if (inf_system) {
- inf_system.textContent = rt_res.system_info || '-';
+ infSystem = document.getElementById('system');
+ if (infSystem) {
+ infSystem.textContent = rtRes.systemInfo || '-';
}
}
} else {
- inf_stat = document.getElementById('status');
- if (inf_stat) {
- inf_stat.textContent = '-';
+ infStat = document.getElementById('status');
+ if (infStat) {
+ infStat.textContent = '-';
poll.stop();
- if (inf_stat.classList.contains('spinning')) {
- inf_stat.classList.remove('spinning');
+ if (infStat.classList.contains('spinning')) {
+ infStat.classList.remove('spinning');
}
}
}
]),
E('div', { class: 'right' }, [
E('button', {
- 'class': 'btn cbi-button cbi-button-apply',
+ 'class': 'btn cbi-button cbi-button-action',
'click': ui.createHandlerFn(this, function () {
return handleAction('lookup');
})
o.rawhtml = true;
o.default = '<em><b>' + _('Changes on this tab needs a banIP service restart to take effect.') + '</b></em>';
- o = s.taboption('adv_chain', form.ListValue, 'ban_nftpolicy', _('Set Policy'), _('Set the nft policy for banIP-related sets.'));
+ o = s.taboption('adv_chain', form.ListValue, 'ban_nftpolicy', _('NFT Set Policy'), _('Set the nft policy for banIP-related Sets.'));
o.value('memory', _('memory (default)'));
o.value('performance', _('performance'));
o.optional = true;
o.rmempty = true;
- o = s.taboption('adv_chain', form.ListValue, 'ban_nftpriority', _('Chain Priority'), _('Set the nft chain priority within the banIP table. Please note: lower values means higher priority.'));
+ o = s.taboption('adv_chain', form.ListValue, 'ban_nftpriority', _('NFT Chain Priority'), _('Set the nft chain priority within the banIP table. Please note: lower values means higher priority.'));
o.value('0', _('0'));
o.value('-100', _('-100'));
o.value('-200', _('-200 (default)'));
o.optional = true;
o.rmempty = true;
+ o = s.taboption('adv_chain', form.ListValue, 'ban_blockpolicy', _('Default Block Policy'), _('By default each feed is active in all supported chains. Limit the default block policy to a certain chain.'));
+ o.value('input', _('WAN-Input Chain'));
+ o.value('forwardwan', _('WAN-Forward Chain'));
+ o.value('forwardlan', _('LAN-Forward Chain'));
+ o.optional = true;
+ o.rmempty = true;
+
+ let feed, feeds, descr;
if (result[0]) {
- var feed, feeds;
feeds = JSON.parse(result[0]);
-
+ } else if (result[1]) {
+ feeds = JSON.parse(result[1]);
+ }
+ if (feeds) {
o = s.taboption('adv_chain', form.MultiValue, 'ban_blockinput', _('WAN-Input Chain'), _('Limit certain feeds to the WAN-Input chain.'));
o.value('allowlist', _('local allowlist'));
o.value('blocklist', _('local blocklist'));
- for (var i = 0; i < Object.keys(feeds).length; i++) {
+ for (let i = 0; i < Object.keys(feeds).length; i++) {
feed = Object.keys(feeds)[i].trim();
o.value(feed);
}
o = s.taboption('adv_chain', form.MultiValue, 'ban_blockforwardwan', _('WAN-Forward Chain'), _('Limit certain feeds to the WAN-Forward chain.'));
o.value('allowlist', _('local allowlist'));
o.value('blocklist', _('local blocklist'));
- for (var i = 0; i < Object.keys(feeds).length; i++) {
+ for (let i = 0; i < Object.keys(feeds).length; i++) {
feed = Object.keys(feeds)[i].trim();
o.value(feed);
}
o = s.taboption('adv_chain', form.MultiValue, 'ban_blockforwardlan', _('LAN-Forward Chain'), _('Limit certain feeds to the LAN-Forward chain.'));
o.value('allowlist', _('local allowlist'));
o.value('blocklist', _('local blocklist'));
- for (var i = 0; i < Object.keys(feeds).length; i++) {
+ for (let i = 0; i < Object.keys(feeds).length; i++) {
feed = Object.keys(feeds)[i].trim();
o.value(feed);
}
o.value('notice', _('notice'));
o.value('info', _('info'));
o.value('debug', _('debug'));
- o.value('audit', _('audit'));
o.optional = true;
o.rmempty = true;
- o = s.taboption('adv_log', form.ListValue, 'ban_loglimit', _('Log Limit'), _('Parse only the last stated number of log entries for suspicious events.'));
+ o = s.taboption('adv_log', form.ListValue, 'ban_loglimit', _('Log Limit'), _('Parse only the last stated number of log entries for suspicious events. To disable the log monitor at all set it to \'0\'.'));
+ o.value('0', _('0 (disable)'));
o.value('50', _('50'));
o.value('100', _('100 (default)'));
o.value('250', _('250'));
o.rawhtml = true;
o.default = '<em><b>' + _('List of supported and fully pre-configured banIP feeds.') + '</b></em>';
- if (result[0]) {
- var focus, feed, feeds;
- feeds = JSON.parse(result[0]);
-
+ if (feeds) {
o = s.taboption('feeds', form.MultiValue, 'ban_feed', _('Feed Selection'));
- for (var i = 0; i < Object.keys(feeds).length; i++) {
+ for (let i = 0; i < Object.keys(feeds).length; i++) {
feed = Object.keys(feeds)[i].trim();
- focus = feeds[feed].focus.trim();
- o.value(feed, feed + ' (' + focus + ')');
+ descr = feeds[feed].descr.trim() || '-';
+ o.value(feed, feed + ' (' + descr + ')');
}
o.optional = true;
o.rmempty = true;
/*
prepare country data
*/
- var code, country, countries = [];
- if (result[1]) {
- countries = result[1].trim().split('\n');
+ let code, country, countries = [];
+ if (result[2]) {
+ countries = result[2].trim().split('\n');
o = s.taboption('feeds', form.MultiValue, 'ban_country', _('Countries'));
- for (var i = 0; i < countries.length; i++) {
+ for (let i = 0; i < countries.length; i++) {
code = countries[i].match(/^(\w+);/)[1].trim();
country = countries[i].match(/^\w+;(.*$)/)[1].trim();
o.value(code, country);
E('button', {
'class': 'btn cbi-button-action',
'click': ui.createHandlerFn(this, function (ev) {
- var ip = document.getElementById('search').value.trim().toLowerCase();
+ let ip = document.getElementById('search').value.trim().toLowerCase();
if (ip) {
document.getElementById('run').classList.add("spinning");
document.getElementById('search').value = ip;
document.getElementById('result').textContent = 'The search is running, please wait...';
L.resolveDefault(fs.exec_direct('/etc/init.d/banip', ['search', ip])).then(function (res) {
- var result = document.getElementById('result');
+ let result = document.getElementById('result');
if (res) {
result.textContent = res.trim();
} else {
document.getElementById('search').focus();
}
if (ev === 'survey') {
- var content, selectO;
+ let content, selectOption;
if (report[1]) {
content = JSON.parse(report[1]);
} else {
content = "";
}
- selectO = [E('option', { value: '' }, [_('-- Set Selection --')])];
- for (var i = 0; i < Object.keys(content.nftables).length; i++) {
- if (content.nftables[i].set !== undefined && content.nftables[i].set.name !== undefined) {
- selectO.push(E('option', { 'value': content.nftables[i].set.name }, content.nftables[i].set.name));
+ selectOption = [E('option', { value: '' }, [_('-- Set Selection --')])];
+ for (let i = 0; i < Object.keys(content.nftables).length; i++) {
+ if (content.nftables[i].set && content.nftables[i].set.name !== undefined && content.nftables[i].set.table !== undefined && content.nftables[i].set.table === 'banIP') {
+ selectOption.push(E('option', { 'value': content.nftables[i].set.name }, content.nftables[i].set.name));
}
}
L.ui.showModal(_('Set Survey'), [
E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em', 'id': 'run' }, [
E('h5', _('Set')),
E('select', { 'class': 'cbi-input-select', 'id': 'set' },
- selectO
+ selectOption
)
]),
]),
E('button', {
'class': 'btn cbi-button-action',
'click': ui.createHandlerFn(this, function (ev) {
- var set = document.getElementById('set').value;
+ let set = document.getElementById('set').value;
if (set) {
document.getElementById('run').classList.add("spinning");
document.getElementById('result').textContent = 'The survey is running, please wait...';
L.resolveDefault(fs.exec_direct('/etc/init.d/banip', ['survey', set])).then(function (res) {
- var result = document.getElementById('result');
+ let result = document.getElementById('result');
if (res) {
result.textContent = res.trim();
} else {
},
render: function (report) {
- var content;
+ let content, rowSets, tblSets;
if (report[0]) {
content = JSON.parse(report[0]);
} else {
content = "";
}
- var rows_sets = [];
- var tbl_sets = E('table', { 'class': 'table', 'id': 'sets' }, [
+ rowSets = [];
+ tblSets = E('table', { 'class': 'table', 'id': 'sets' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Set')),
E('th', { 'class': 'th right', 'style': 'padding-right: 20px' }, _('Elements')),
]);
if (content.sets) {
- var cnt1, cnt2, cnt3;
+ let cnt1, cnt2, cnt3;
Object.keys(content.sets).forEach(function (key) {
cnt1 = content.sets[key].cnt_input ? ': (' + content.sets[key].cnt_input + ')' : '';
cnt2 = content.sets[key].cnt_forwardwan ? ': (' + content.sets[key].cnt_forwardwan + ')' : '';
cnt3 = content.sets[key].cnt_forwardlan ? ': (' + content.sets[key].cnt_forwardlan + ')' : '';
- rows_sets.push([
+ rowSets.push([
E('em', key),
E('em', { 'style': 'padding-right: 20px' }, content.sets[key].cnt_elements),
E('em', content.sets[key].input + cnt1),
E('em', content.sets[key].lan_forward + cnt3)
]);
});
- rows_sets.push([
+ rowSets.push([
E('em', { 'style': 'font-weight: bold' }, content.sum_sets),
E('em', { 'style': 'font-weight: bold; padding-right: 20px' }, content.sum_setelements),
E('em', { 'style': 'font-weight: bold' }, content.sum_setinput + ' (' + content.sum_cntinput + ')'),
E('em', { 'style': 'font-weight: bold' }, content.sum_setforwardlan + ' (' + content.sum_cntforwardlan + ')')
]);
}
- cbi_update_table(tbl_sets, rows_sets);
+ cbi_update_table(tblSets, rowSets);
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
E('div', { 'class': 'cbi-section' }, [
'\xa0\xa0\xa0',
E('button', {
'class': 'btn cbi-button cbi-button-positive',
- 'click': ui.createHandlerFn(this, async function () {
- L.resolveDefault(fs.exec_direct('/etc/init.d/banip', ['report', 'json']), '');
+ 'click': ui.createHandlerFn(this, function () {
location.reload();
})
}, [_('Refresh')])
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'left' }, [
E('h3', _('Set details')),
- tbl_sets
+ tblSets
])
])
]);
"/usr/bin/banip-service.sh": "executable",
"/etc/init.d/banip": "executable",
"/etc/banip/banip.feeds": "file",
+ "/etc/banip/banip.custom.feeds": "file",
"/etc/banip/banip.allowlist": "file",
"/etc/banip/banip.blocklist": "file",
"/etc/banip/banip.countries": "file"
"path": "banip/blocklist"
}
},
+ "admin/services/banip/feeds": {
+ "title": "Edit Custom Feeds",
+ "order": 40,
+ "action": {
+ "type": "view",
+ "path": "banip/feeds"
+ }
+ },
"admin/services/banip/setreport": {
"title": "Set Reporting",
- "order": 40,
+ "order": 50,
"action": {
"type": "view",
"path": "banip/setreport"
},
"admin/services/banip/firewall_log": {
"title": "Firewall Log",
- "order": 50,
+ "order": 60,
"action": {
"type": "view",
"path": "banip/firewall_log"
},
"admin/services/banip/processing_log": {
"title": "Processing Log",
- "order": 60,
+ "order": 70,
"action": {
"type": "view",
"path": "banip/processing_log"
"luci-app-banip": {
"description": "Grant access to LuCI app banIP",
"write": {
- "uci": [
- "banip"
- ],
"file": {
"/etc/banip/*": [
"read"
"/etc/banip/banip.blocklist": [
"write"
],
- "/etc/banip/banip.feeds": [
+ "/etc/banip/banip.custom.feeds": [
"write"
]
- }
+ },
+ "uci": [
+ "banip"
+ ]
},
"read": {
"cgi-io": [