9 function handleAction(ev
) {
10 if (ev
.target
&& ev
.target
.getAttribute('name') === 'blacklist') {
11 L
.ui
.showModal(_('Add Blacklist Domain'), [
12 E('p', _('Add this (sub-)domain to your local blacklist.')),
13 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
14 E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
15 E('input', { 'class': 'cbi-input-text', 'style': 'width:300px', 'spellcheck': 'false', 'id': 'blacklist', 'value': ev
.target
.getAttribute('value') }, [])
18 E('div', { 'class': 'right' }, [
20 'class': 'btn cbi-button',
25 'class': 'btn cbi-button-action',
26 'click': ui
.createHandlerFn(this, function(ev
) {
27 L
.resolveDefault(fs
.read_direct('/etc/adblock/adblock.blacklist'), '')
29 var domain
= document
.getElementById('blacklist').value
.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
30 var pattern
= new RegExp('^' + domain
.replace(/[\.]/g,'\\.') + '$', 'm');
31 if (res
.search(pattern
) === -1) {
32 var blacklist
= res
+ domain
+ '\n';
33 fs
.write('/etc/adblock/adblock.blacklist', blacklist
);
34 ui
.addNotification(null, E('p', _('Blacklist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
42 document
.getElementById('blacklist').focus();
45 if (ev
.target
&& ev
.target
.getAttribute('name') === 'whitelist') {
46 L
.ui
.showModal(_('Add Whitelist Domain'), [
47 E('p', _('Add this (sub-)domain to your local whitelist.')),
48 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
49 E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
50 E('input', { 'class': 'cbi-input-text', 'style': 'width:300px', 'spellcheck': 'false', 'id': 'whitelist', 'value': ev
.target
.getAttribute('value') }, [])
53 E('div', { 'class': 'right' }, [
55 'class': 'btn cbi-button',
60 'class': 'btn cbi-button-action',
61 'click': ui
.createHandlerFn(this, function(ev
) {
62 L
.resolveDefault(fs
.read_direct('/etc/adblock/adblock.whitelist'), '')
64 var domain
= document
.getElementById('whitelist').value
.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
65 var pattern
= new RegExp('^' + domain
.replace(/[\.]/g,'\\.') + '$', 'm');
66 if (res
.search(pattern
) === -1) {
67 var whitelist
= res
+ domain
+ '\n';
68 fs
.write('/etc/adblock/adblock.whitelist', whitelist
);
69 ui
.addNotification(null, E('p', _('Whitelist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
77 document
.getElementById('whitelist').focus();
81 L
.ui
.showModal(_('Blocklist Query'), [
82 E('p', _('Query active blocklists and backups for a specific domain.')),
83 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
84 E('label', { 'style': 'padding-top:.5em', 'id': 'run' }, [
86 'class': 'cbi-input-text',
87 'placeholder': 'google.com',
88 'style': 'width:300px',
89 'spellcheck': 'false',
94 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
99 'style': 'width: 100% !important; padding: 5px; font-family: monospace',
100 'readonly': 'readonly',
105 E('div', { 'class': 'right' }, [
107 'class': 'btn cbi-button',
112 'class': 'btn cbi-button-action',
113 'click': ui
.createHandlerFn(this, function(ev
) {
114 var domain
= document
.getElementById('search').value
.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
116 document
.getElementById('run').classList
.add("spinning");
117 document
.getElementById('search').value
= domain
;
118 document
.getElementById('result').textContent
= 'The query is running, please wait...';
119 L
.resolveDefault(fs
.exec_direct('/etc/init.d/adblock', ['query', domain
])).then(function(res
) {
120 var result
= document
.getElementById('result');
122 result
.textContent
= res
.trim();
124 result
.textContent
= _('No Query results!');
126 document
.getElementById('run').classList
.remove("spinning");
127 document
.getElementById('search').value
= '';
130 document
.getElementById('search').focus();
135 document
.getElementById('search').focus();
138 if (ev
=== 'refresh') {
139 L
.ui
.showModal(_('Refresh DNS Report'), [
140 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
141 E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em' }, [
142 E('select', { 'class': 'cbi-input-select', 'id': 'top_count' }, [
143 E('option', { 'value': '10' }, '10'),
144 E('option', { 'value': '20' }, '20'),
145 E('option', { 'value': '30' }, '30'),
146 E('option', { 'value': '40' }, '40'),
147 E('option', { 'value': '50' }, '50')
150 _('max. top statistics')
153 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
154 E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em' }, [
155 E('select', { 'class': 'cbi-input-select', 'id': 'res_count' }, [
156 E('option', { 'value': '50' }, '50'),
157 E('option', { 'value': '100' }, '100'),
158 E('option', { 'value': '150' }, '150'),
159 E('option', { 'value': '250' }, '250'),
160 E('option', { 'value': '500' }, '500')
163 _('max. result set size')
166 E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
167 E('input', { 'class': 'cbi-input-text', 'spellcheck': 'false', 'id': 'search' }, [
170 _('Filter criteria like date, domain or client (optional)')
172 E('div', { 'class': 'right' }, [
174 'class': 'btn cbi-button',
179 'class': 'btn cbi-button-action',
181 'click': ui
.createHandlerFn(this, async
function(ev
) {
182 var top_count
= document
.getElementById('top_count').value
;
183 var res_count
= document
.getElementById('res_count').value
;
184 var search
= document
.getElementById('search').value
.trim().replace(/[^\w\.\-\:]/g,'') || '+';
185 L
.resolveDefault(fs
.exec_direct('/etc/init.d/adblock', ['report', 'gen', top_count
, res_count
, search
]),'');
187 while (running
=== 1) {
188 await
new Promise(r
=> setTimeout(r
, 1000));
189 L
.resolveDefault(fs
.read_direct('/var/run/adblock.pid')).then(function(res
) {
201 document
.getElementById('refresh').focus();
207 return L
.resolveDefault(fs
.exec_direct('/etc/init.d/adblock', ['report', 'json', '10', '50', '+']),'');
210 render: function(dnsreport
) {
215 content
= JSON
.parse(dnsreport
);
218 var tbl_top
= E('table', { 'class': 'table', 'id': 'top_10' }, [
219 E('tr', { 'class': 'tr table-titles' }, [
220 E('th', { 'class': 'th right' }, _('Count')),
221 E('th', { 'class': 'th' }, _('Clients')),
222 E('th', { 'class': 'th right' }, _('Count')),
223 E('th', { 'class': 'th' }, _('Domains')),
224 E('th', { 'class': 'th right' }, _('Count')),
225 E('th', { 'class': 'th' }, _('Blocked Domains'))
230 if (content
.top_clients
&& content
.top_domains
&& content
.top_blocked
) {
231 max
= Math
.max(content
.top_clients
.length
, content
.top_domains
.length
, content
.top_blocked
.length
);
233 for (var i
= 0; i
< max
; i
++) {
234 var a_cnt
= '\xa0', a_addr
= '\xa0', b_cnt
= '\xa0', b_addr
= '\xa0', c_cnt
= '\xa0', c_addr
= '\xa0';
235 if (content
.top_clients
[i
]) {
236 a_cnt
= content
.top_clients
[i
].count
;
238 if (content
.top_clients
[i
]) {
239 a_addr
= content
.top_clients
[i
].address
;
241 if (content
.top_domains
[i
]) {
242 b_cnt
= content
.top_domains
[i
].count
;
244 if (content
.top_domains
[i
]) {
245 b_addr
= '<a href="https://duckduckgo.com/?q=' + encodeURIComponent(content
.top_domains
[i
].address
) + '&k1=-1&km=l&kh=1" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content
.top_domains
[i
].address
+ '</a>';
247 if (content
.top_blocked
[i
]) {
248 c_cnt
= content
.top_blocked
[i
].count
;
250 if (content
.top_blocked
[i
]) {
251 c_addr
= '<a href="https://duckduckgo.com/?q=' + encodeURIComponent(content
.top_blocked
[i
].address
) + '&k1=-1&km=l&kh=1" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content
.top_blocked
[i
].address
+ '</a>';
262 cbi_update_table(tbl_top
, rows_top
);
264 var rows_requests
= [];
265 var tbl_requests
= E('table', { 'class': 'table', 'id': 'requests' }, [
266 E('tr', { 'class': 'tr table-titles' }, [
267 E('th', { 'class': 'th' }, _('Date')),
268 E('th', { 'class': 'th' }, _('Time')),
269 E('th', { 'class': 'th' }, _('Client')),
270 E('th', { 'class': 'th' }, _('Domain')),
271 E('th', { 'class': 'th' }, _('Answer')),
272 E('th', { 'class': 'th' }, _('Action'))
277 if (content
.requests
) {
279 max
= content
.requests
.length
;
280 for (var i
= 0; i
< max
; i
++) {
281 if (content
.requests
[i
].rc
=== 'NX') {
282 button
= E('button', {
283 'class': 'btn cbi-button cbi-button-positive',
284 'style': 'word-break: inherit',
286 'value': content
.requests
[i
].domain
,
287 'click': handleAction
288 }, [ _('Whitelist...') ]);
290 button
= E('button', {
291 'class': 'btn cbi-button cbi-button-negative',
292 'style': 'word-break: inherit',
294 'value': content
.requests
[i
].domain
,
295 'click': handleAction
296 }, [ _('Blacklist...') ]);
299 content
.requests
[i
].date
,
300 content
.requests
[i
].time
,
301 content
.requests
[i
].client
,
302 '<a href="https://duckduckgo.com/?q=' + encodeURIComponent(content
.requests
[i
].domain
) + '&k1=-1&km=l&kh=1" target="_blank" rel="noreferrer noopener" title="Domain Lookup">' + content
.requests
[i
].domain
+ '</a>',
303 content
.requests
[i
].rc
,
308 cbi_update_table(tbl_requests
, rows_requests
);
310 return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
311 E('div', { 'class': 'cbi-section' }, [
312 E('p', _('This tab shows the last generated DNS Report, press the \'Refresh\' button to get a current one.')),
314 E('div', { 'class': 'cbi-value' }, [
315 E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('Start Timestamp')),
316 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'float:left;color:#37c' }, (content
.start_date
|| '-') + ', ' + (content
.start_time
|| '-'))
318 E('div', { 'class': 'cbi-value' }, [
319 E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('End Timestamp')),
320 E('div', { 'class': 'cbi-value-title', 'id': 'end', 'style': 'float:left;color:#37c' }, (content
.end_date
|| '-') + ', ' + (content
.end_time
|| '-'))
322 E('div', { 'class': 'cbi-value' }, [
323 E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('Total DNS Requests')),
324 E('div', { 'class': 'cbi-value-title', 'id': 'total', 'style': 'float:left;color:#37c' }, content
.total
|| '-')
326 E('div', { 'class': 'cbi-value' }, [
327 E('div', { 'class': 'cbi-value-title', 'style': 'float:left;width:230px' }, _('Blocked DNS Requests')),
328 E('div', { 'class': 'cbi-value-title', 'id': 'blocked', 'style': 'float:left;color:#37c' }, (content
.blocked
|| '-') + ' (' + (content
.percent
|| '-') + ')')
330 E('div', { 'class': 'right' }, [
332 'class': 'btn cbi-button cbi-button-apply',
333 'click': ui
.createHandlerFn(this, function() {
334 return handleAction('query');
336 }, [ _('Blocklist Query...') ]),
339 'class': 'btn cbi-button cbi-button-positive',
340 'click': ui
.createHandlerFn(this, function() {
341 return handleAction('refresh');
343 }, [ _('Refresh...') ])
346 E('div', { 'class': 'cbi-section' }, [
347 E('div', { 'class': 'left' }, [
348 E('h3', _('Top Statistics')),
353 E('div', { 'class': 'cbi-section' }, [
354 E('div', { 'class': 'left' }, [
355 E('h3', _('Latest DNS Requests')),
361 handleSaveApply
: null,