luci-app-adblock [19.07]: sync with adblock 4.0.6
[oweals/luci.git] / applications / luci-app-adblock / htdocs / luci-static / resources / view / adblock / dnsreport.js
1 'use strict';
2 'require fs';
3 'require ui';
4
5 /*
6         button handling
7 */
8 function handleAction(ev) {
9         if (ev.target && ev.target.getAttribute('name') === 'blacklist') {
10                 L.ui.showModal(_('Add Blacklist Domain'), [
11                         E('p', _('Add this (sub-)domain to your local blacklist.')),
12                         E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
13                                 E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
14                                         E('input', { 'class': 'cbi-input-text', 'style': 'width:300px', 'id': 'blacklist', 'value': ev.target.getAttribute('value') }, [])
15                                 ])
16                         ]),
17                         E('div', { 'class': 'right' }, [
18                                 E('button', {
19                                         'class': 'btn',
20                                         'click': L.hideModal
21                                 }, _('Cancel')),
22                                 ' ',
23                                 E('button', {
24                                         'class': 'btn cbi-button-action',
25                                         'click': ui.createHandlerFn(this, function(ev) {
26                                                 L.resolveDefault(fs.read_direct('/etc/adblock/adblock.blacklist'), '')
27                                                 .then(function(res) {
28                                                         var domain = document.getElementById('blacklist').value.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
29                                                         var pattern = new RegExp('^' + domain.replace(/[\.]/g,'\\.') + '$', 'm');
30                                                         if (res.search(pattern) === -1) {
31                                                                 var blacklist = res + domain + '\n';
32                                                                 fs.write('/etc/adblock/adblock.blacklist', blacklist);
33                                                                 ui.addNotification(null, E('p', _('Blacklist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
34                                                         }
35                                                         L.hideModal();
36                                                 });
37                                         })
38                                 }, _('Save'))
39                         ])
40                 ]);
41                 document.getElementById('blacklist').focus();
42         }
43
44         if (ev.target && ev.target.getAttribute('name') === 'whitelist') {
45                 L.ui.showModal(_('Add Whitelist Domain'), [
46                         E('p', _('Add this (sub-)domain to your local whitelist.')),
47                         E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
48                                 E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
49                                         E('input', { 'class': 'cbi-input-text', 'style': 'width:300px', 'id': 'whitelist', 'value': ev.target.getAttribute('value') }, [])
50                                 ])
51                         ]),
52                         E('div', { 'class': 'right' }, [
53                                 E('button', {
54                                         'class': 'btn',
55                                         'click': L.hideModal
56                                 }, _('Cancel')),
57                                 ' ',
58                                 E('button', {
59                                         'class': 'btn cbi-button-action',
60                                         'click': ui.createHandlerFn(this, function(ev) {
61                                                 L.resolveDefault(fs.read_direct('/etc/adblock/adblock.whitelist'), '')
62                                                 .then(function(res) {
63                                                         var domain = document.getElementById('whitelist').value.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
64                                                         var pattern = new RegExp('^' + domain.replace(/[\.]/g,'\\.') + '$', 'm');
65                                                         if (res.search(pattern) === -1) {
66                                                                 var whitelist = res + domain + '\n';
67                                                                 fs.write('/etc/adblock/adblock.whitelist', whitelist);
68                                                                 ui.addNotification(null, E('p', _('Whitelist changes have been saved. Refresh your adblock lists that changes take effect.')), 'info');
69                                                         }
70                                                         L.hideModal();
71                                                 });
72                                         })
73                                 }, _('Save'))
74                         ])
75                 ]);
76                 document.getElementById('whitelist').focus();
77         }
78
79         if (ev === 'query') {
80                 L.ui.showModal(_('Blocklist Query'), [
81                         E('p', _('Query active blocklists and backups for a specific domain.')),
82                         E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
83                                 E('label', { 'style': 'padding-top:.5em', 'id': 'run' }, [
84                                         E('input', { 
85                                                 'class': 'cbi-input-text',
86                                                 'placeholder': 'google.com',
87                                                 'style': 'width:300px',
88                                                 'id': 'search'
89                                         })
90                                 ])
91                         ]),
92                         E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
93                                 '\xa0',
94                                 E('h5', _('Result')),
95                                 E('textarea', {
96                                         'id': 'result',
97                                         'style': 'width: 100% !important; padding: 5px; font-family: monospace',
98                                         'readonly': 'readonly',
99                                         'wrap': 'off',
100                                         'rows': 20
101                                 })
102                         ]),
103                         E('div', { 'class': 'right' }, [
104                                 E('button', {
105                                         'class': 'btn',
106                                         'click': L.hideModal
107                                 }, _('Cancel')),
108                                 ' ',
109                                 E('button', {
110                                         'class': 'btn cbi-button-action',
111                                         'click': ui.createHandlerFn(this, function(ev) {
112                                                 var domain = document.getElementById('search').value.trim().toLowerCase().replace(/[^a-z0-9\.\-]/g,'');
113                                                 if (domain) {
114                                                         document.getElementById('run').classList.add("spinning");
115                                                         document.getElementById('search').value = domain;
116                                                         document.getElementById('result').textContent = 'The query is running, please wait...';
117                                                         L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['query', domain])).then(function(res) {
118                                                                 var result = document.getElementById('result');
119                                                                 if (res) {
120                                                                         result.textContent = res.trim();
121                                                                 } else {
122                                                                         result.textContent = _('No Query results!');
123                                                                 }
124                                                                 document.getElementById('run').classList.remove("spinning");
125                                                                 document.getElementById('search').value = '';
126                                                         })
127                                                 }
128                                                 document.getElementById('search').focus();
129                                         })
130                                 }, _('Query'))
131                         ])
132                 ]);
133                 document.getElementById('search').focus();
134         }
135
136         if (ev === 'refresh') {
137                 L.ui.showModal(_('Refresh DNS Report'), [
138                         E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
139                                 E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em' }, [
140                                         E('select', { 'class': 'cbi-input-select', 'id': 'count' }, [
141                                                 E('option', { 'value': '50' }, '50'),
142                                                 E('option', { 'value': '100' }, '100'),
143                                                 E('option', { 'value': '150' }, '150'),
144                                                 E('option', { 'value': '250' }, '250'),
145                                                 E('option', { 'value': '500' }, '500')
146                                         ]),
147                                         '\xa0\xa0\xa0',
148                                         _('max. result set size')
149                                 ])
150                         ]),
151                         E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
152                                 E('input', { 'class': 'cbi-input-text', 'spellcheck': 'false', 'id': 'search' }, [
153                         ]),
154                         '\xa0\xa0\xa0',
155                         _('Filter criteria like date, domain or client (optional)')
156                         ]),
157                         E('div', { 'class': 'right' }, [
158                                 E('button', {
159                                         'class': 'btn',
160                                         'click': L.hideModal
161                                 }, _('Cancel')),
162                                 ' ',
163                                 E('button', {
164                                         'class': 'btn cbi-button-action',
165                                         'id': 'refresh',
166                                         'click': ui.createHandlerFn(this, async function(ev) {
167                                                 var count = document.getElementById('count').value;
168                                                 var search = document.getElementById('search').value.trim().replace(/[^\w\.\-\:]/g,'') || '+';
169                                                 L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['report', search, count, 'true', 'json']),'');
170                                                 var running = 1;
171                                                 while (running === 1) {
172                                                         await new Promise(r => setTimeout(r, 1000));
173                                                         L.resolveDefault(fs.read_direct('/var/run/adblock.pid')).then(function(res) {
174                                                                 if (!res) {
175                                                                         running = 0;
176                                                                 }
177                                                         })
178                                                 }
179                                                 L.hideModal();
180                                                 location.reload();
181                                         })
182                                 }, _('Refresh'))
183                         ])
184                 ]);
185                 document.getElementById('refresh').focus();
186         }
187 }
188
189 return L.view.extend({
190         load: function() {
191                 return L.resolveDefault(fs.exec_direct('/etc/init.d/adblock', ['report', '+', '50', 'false', 'json']),'');
192         },
193
194         render: function(dnsreport) {
195                 if (!dnsreport) {
196                         dnsreport = '{ "data": "" }';
197                 };
198                 var content;
199                 content = JSON.parse(dnsreport);
200
201                 var rows_top = [];
202                 var tbl_top  = E('div', { 'class': 'table', 'id': 'top_10' }, [
203                         E('div', { 'class': 'tr table-titles' }, [
204                                 E('div', { 'class': 'th right' }, _('Count')),
205                                 E('div', { 'class': 'th' }, _('Name / IP Address')),
206                                 E('div', { 'class': 'th right' }, _('Count')),
207                                 E('div', { 'class': 'th' }, _('Domain')),
208                                 E('div', { 'class': 'th right' }, _('Count')),
209                                 E('div', { 'class': 'th' }, _('Blocked Domain'))
210                         ])
211                 ]);
212
213                 var max = 0;
214                 if (content.data.top_clients && content.data.top_domains && content.data.top_blocked) {
215                         max = Math.max(content.data.top_clients.length, content.data.top_domains.length, content.data.top_blocked.length);
216                 }
217                 for (var i = 0; i < max; i++) {
218                         var a_cnt = '\xa0', a_addr = '\xa0', b_cnt = '\xa0', b_addr = '\xa0', c_cnt = '\xa0', c_addr = '\xa0';
219                         if (content.data.top_clients[i]) {
220                                 a_cnt = content.data.top_clients[i].count;
221                         }
222                         if (content.data.top_clients[i]) {
223                                 a_addr = content.data.top_clients[i].address;
224                         }
225                         if (content.data.top_domains[i]) {
226                                 b_cnt = content.data.top_domains[i].count;
227                         }
228                         if (content.data.top_domains[i]) {
229                                 b_addr = content.data.top_domains[i].address;
230                         }
231                         if (content.data.top_blocked[i]) {
232                                 c_cnt = content.data.top_blocked[i].count;
233                         }
234                         if (content.data.top_blocked[i]) {
235                                 c_addr = content.data.top_blocked[i].address;
236                         }
237                         rows_top.push([
238                                 a_cnt,
239                                 a_addr,
240                                 b_cnt,
241                                 b_addr,
242                                 c_cnt,
243                                 c_addr
244                         ]);
245                 }
246                 cbi_update_table(tbl_top, rows_top);
247
248                 var rows_requests = [];
249                 var tbl_requests  = E('div', { 'class': 'table', 'id': 'requests' }, [
250                         E('div', { 'class': 'tr table-titles' }, [
251                                 E('div', { 'class': 'th' }, _('Date')),
252                                 E('div', { 'class': 'th' }, _('Time')),
253                                 E('div', { 'class': 'th' }, _('Client')),
254                                 E('div', { 'class': 'th' }, _('Domain')),
255                                 E('div', { 'class': 'th' }, _('Answer')),
256                                 E('div', { 'class': 'th' }, _('Action'))
257                         ])
258                 ]);
259
260                 max = 0;
261                 if (content.data.requests) {
262                         var button;
263                         max = content.data.requests.length;
264                         for (var i = 0; i < max; i++) {
265                                 if (content.data.requests[i].rc === 'NX') {
266                                         button = E('button', {
267                                                 'class': 'cbi-button cbi-button-apply',
268                                                 'style': 'word-break: inherit',
269                                                 'name': 'whitelist',
270                                                 'value': content.data.requests[i].domain,
271                                                 'click': handleAction
272                                         }, [ _('Whitelist...') ]);
273                                 } else {
274                                         button = E('button', {
275                                                 'class': 'cbi-button cbi-button-apply',
276                                                 'style': 'word-break: inherit',
277                                                 'name': 'blacklist',
278                                                 'value': content.data.requests[i].domain,
279                                                 'click': handleAction
280                                         }, [ _('Blacklist...') ]);
281                                 }
282                                 rows_requests.push([
283                                         content.data.requests[i].date,
284                                         content.data.requests[i].time,
285                                         content.data.requests[i].client,
286                                         content.data.requests[i].domain,
287                                         content.data.requests[i].rc,
288                                         button
289                                 ]);
290                         }
291                 }
292                 cbi_update_table(tbl_requests, rows_requests);
293
294                 return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
295                         E('div', { 'class': 'cbi-section' }, [
296                                 E('p', _('This shows the last generated DNS Report, press the refresh button to get a current one.')),
297                                 E('p', '\xa0'),
298                                 E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
299                                 E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('Start Date')),
300                                 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 || '-'))]),
301                                 E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
302                                 E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('End Date')),
303                                 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 || '-'))]),
304                                 E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
305                                 E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('DNS Requests (total)')),
306                                 E('div', { 'class': 'cbi-value-field', 'id': 'total', 'style': 'margin-bottom:5px;margin-left:200px;color:#37c' }, content.data.total || '-')]),
307                                 E('div', { 'class': 'cbi-value', 'style': 'margin-bottom:5px' }, [
308                                 E('label', { 'class': 'cbi-value-title', 'style': 'padding-top:0rem' }, _('DNS Requests (blocked)')),
309                                 E('div', { 'class': 'cbi-value-field', 'id': 'blocked', 'style': 'margin-bottom:5px;margin-left:200px;color:#37c' }, (content.data.blocked || '-') + ' (' + (content.data.percent || '-') + ')')]),
310                                 E('div', { 'class': 'right' }, [
311                                         E('button', {
312                                                 'class': 'cbi-button cbi-button-apply',
313                                                 'click': ui.createHandlerFn(this, function() {
314                                                         return handleAction('query');
315                                                 })
316                                         }, [ _('Blocklist Query...') ]),
317                                         '\xa0\xa0\xa0',
318                                         E('button', {
319                                                 'class': 'cbi-button cbi-button-apply',
320                                                 'click': ui.createHandlerFn(this, function() {
321                                                         return handleAction('refresh');
322                                                 })
323                                         }, [ _('Refresh...') ])
324                                 ]),
325                         ]),
326                         E('div', { 'class': 'cbi-section' }, [
327                                 E('div', { 'class': 'left' }, [
328                                         E('h3', _('Top 10 Statistics')),
329                                         tbl_top
330                                 ])
331                         ]),
332                         E('br'),
333                         E('div', { 'class': 'cbi-section' }, [
334                                 E('div', { 'class': 'left' }, [
335                                         E('h3', _('Latest DNS Requests')),
336                                         tbl_requests
337                                 ])
338                         ])
339                 ]);
340         },
341         handleSaveApply: null,
342         handleSave: null,
343         handleReset: null
344 });