mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-10 06:47:52 +08:00
🎄 Sync 2026-09-26 02:25:56
This commit is contained in:
1 parent
99196a85d3
commit
4136a9b488
73 files changed
+2401
-4124
No files matched your search
@@ -17,26 +17,9 @@
|
||||
*/
|
||||
|
||||
function chipFieldLabel(spec) {
|
||||
switch (spec.key) {
|
||||
case 'q':
|
||||
return _('Search');
|
||||
case 'action':
|
||||
return _('Action');
|
||||
case 'interface':
|
||||
return _('Interface');
|
||||
case 'proto':
|
||||
return _('Proto');
|
||||
case 'src':
|
||||
return _('Source');
|
||||
case 'dst':
|
||||
return _('Destination');
|
||||
case 'sport':
|
||||
return _('Source port');
|
||||
case 'dport':
|
||||
return _('Destination port');
|
||||
default:
|
||||
return spec.label || spec.key;
|
||||
}
|
||||
const mapped = log.filterFieldLabel(spec.key);
|
||||
if (mapped !== spec.key) return mapped;
|
||||
return spec.label || spec.key;
|
||||
}
|
||||
|
||||
function chipValueNodes(spec, val) {
|
||||
@@ -58,9 +41,7 @@ function chipValueNodes(spec, val) {
|
||||
if (key === 'q' || key === 'src' || key === 'dst')
|
||||
return [
|
||||
label + ': ',
|
||||
E('strong', { 'class': 'fwlive-chip-not' }, [_('not')]),
|
||||
' ',
|
||||
_('contains'),
|
||||
E('strong', { 'class': 'fwlive-chip-not' }, [_('does not contain')]),
|
||||
' ',
|
||||
valueNode
|
||||
];
|
||||
|
||||
@@ -60,7 +60,7 @@ function filterLink(field, value, label, onFilterClick) {
|
||||
{
|
||||
'href': '#',
|
||||
'class': 'fwlive-filter-link',
|
||||
'title': _('Filter by %s').format(field),
|
||||
'title': _('Filter by %s').format(log.filterFieldLabel(field)),
|
||||
'click': function (ev) {
|
||||
onFilterClick(field, value, ev);
|
||||
}
|
||||
@@ -88,7 +88,7 @@ function addrFilterLink(field, ip, showHostnames, hostnameCache, onFilterClick)
|
||||
: hostnameCache.get(ip);
|
||||
}
|
||||
const display = name || ip;
|
||||
const title = name ? ip : _('Filter by %s').format(field);
|
||||
const title = name ? ip : _('Filter by %s').format(log.filterFieldLabel(field));
|
||||
|
||||
return E(
|
||||
'a',
|
||||
@@ -153,7 +153,7 @@ function ifaceLink(value, onFilterClick) {
|
||||
{
|
||||
'href': '#',
|
||||
'class': 'fwlive-filter-link fwlive-iface-badge',
|
||||
'title': _('Filter by interface'),
|
||||
'title': _('Filter by %s').format(log.filterFieldLabel('interface')),
|
||||
'click': function (ev) {
|
||||
onFilterClick('interface', value, ev);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ const CLASSIFY_SPEC = {
|
||||
'PREC',
|
||||
'DF'
|
||||
],
|
||||
/* Classify trim (not JS String#trim): ASCII space/tab/LF/CR + NBSP (U+00A0). */
|
||||
trimWhitespace: [' ', '\t', '\n', '\r', '\u00a0'],
|
||||
nonFirewallPrefixes: [
|
||||
'dnsmasq',
|
||||
'procd',
|
||||
@@ -64,6 +66,15 @@ function wordPattern(words) {
|
||||
return new RegExp('(^|[^A-Za-z0-9_])(' + alt + ')([^A-Za-z0-9_]|$)', 'i');
|
||||
}
|
||||
|
||||
function classifyTrim(s) {
|
||||
const ws = CLASSIFY_SPEC.trimWhitespace;
|
||||
let start = 0;
|
||||
let end = s.length;
|
||||
while (start < end && ws.indexOf(s.charAt(start)) >= 0) start++;
|
||||
while (end > start && ws.indexOf(s.charAt(end - 1)) >= 0) end--;
|
||||
return s.slice(start, end);
|
||||
}
|
||||
|
||||
/* ---- spec-derived classification regexes (mirror core/fwlive-log.js) ---- */
|
||||
const DENY_CLASS_WORDS = CLASSIFY_SPEC.actionWords.slice(3);
|
||||
const NON_FIREWALL_PREFIX = new RegExp(
|
||||
@@ -335,10 +346,25 @@ return baseclass.extend({
|
||||
|
||||
return m;
|
||||
},
|
||||
|
||||
filterFieldLabel: function (field) {
|
||||
const labels = {
|
||||
'q': _('Search'),
|
||||
'action': _('Action'),
|
||||
'interface': _('Interface'),
|
||||
'proto': _('Proto'),
|
||||
'src': _('Source'),
|
||||
'dst': _('Destination'),
|
||||
'sport': _('Source port'),
|
||||
'dport': _('Destination port')
|
||||
};
|
||||
|
||||
return labels[field] || field;
|
||||
},
|
||||
/* @fwlive-codegen:luci-preserve-end */
|
||||
|
||||
isFirewallEvent: function (entry) {
|
||||
const msg = this.normalizeNetfilterMessage((entry && entry.msg) || '').trim();
|
||||
const msg = classifyTrim(this.normalizeNetfilterMessage((entry && entry.msg) || ''));
|
||||
if (!msg) return false;
|
||||
|
||||
if (this.NON_FIREWALL_PREFIX.test(msg)) return false;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
* renderManualTestNodes(host, state, callbacks) → void
|
||||
* host - <ul> element inside #fwlive-help (cleared and rebuilt)
|
||||
* state - unused; nft-only instruction
|
||||
* state - unused; instruction is nft-only (rpcd never emits iptables)
|
||||
*
|
||||
* Empty-state helpers:
|
||||
* buildEmptyStateNodes(state, callbacks) → Node[]
|
||||
@@ -200,17 +200,17 @@ function buildConsentPanel(state, callbacks) {
|
||||
E('li', {}, [
|
||||
E('strong', {}, [_('Changes:')]),
|
||||
' ',
|
||||
_('sets log on the WAN firewall zone and reloads the firewall.')
|
||||
_('Turns on logging for the WAN firewall zone and reloads the firewall.')
|
||||
]),
|
||||
E('li', {}, [
|
||||
E('strong', {}, [_('Does not change:')]),
|
||||
' ',
|
||||
_('allow/deny rules, LAN logging, or anything else.')
|
||||
_('Allow/deny rules, LAN logging, or anything else.')
|
||||
]),
|
||||
E('li', {}, [
|
||||
E('strong', {}, [_('Undo:')]),
|
||||
' ',
|
||||
_('turn it back off with the WAN logging on control on the watch strip.')
|
||||
_('Turn it back off with the WAN logging control on the watch strip.')
|
||||
])
|
||||
]),
|
||||
E('p', { 'class': 'fwlive-consent-check' }, [
|
||||
@@ -272,7 +272,8 @@ function buildEmptyStateNodes(state, callbacks) {
|
||||
);
|
||||
nodes.push(
|
||||
E('p', {}, [
|
||||
_('No WAN firewall zone found in /etc/config/firewall. Configure zones under '),
|
||||
_('No WAN firewall zone found in /etc/config/firewall. Configure zones under:'),
|
||||
' ',
|
||||
links.firewallZonesLink()
|
||||
])
|
||||
);
|
||||
@@ -368,19 +369,21 @@ function renderEmptyState(host, state, callbacks) {
|
||||
}
|
||||
|
||||
/**
|
||||
* renderManualTestNodes — fills a <li> host element with the nft manual test
|
||||
* renderManualTestNodes — fills a <li> host element with the firewall manual test
|
||||
* instruction. Call from addFooter() after render() has inserted
|
||||
* the placeholder <li id="fwlive-manual-test">.
|
||||
*/
|
||||
function renderManualTestNodes(host, _state, _callbacks) {
|
||||
host.innerHTML = '';
|
||||
host.appendChild(document.createTextNode(_('Manual test (System → Terminal): ')));
|
||||
host.appendChild(document.createTextNode(_('Manual test (System → Terminal):')));
|
||||
host.appendChild(document.createTextNode(' '));
|
||||
host.appendChild(
|
||||
E('code', {}, [
|
||||
'nft insert rule inet fw4 input ip protocol icmp icmp type echo-request log prefix "fwlive-ping " accept'
|
||||
])
|
||||
);
|
||||
host.appendChild(document.createTextNode(_(' then ping the router.')));
|
||||
host.appendChild(document.createTextNode(' '));
|
||||
host.appendChild(document.createTextNode(_('Then ping the router.')));
|
||||
}
|
||||
|
||||
return baseclass.extend({
|
||||
|
||||
@@ -52,6 +52,28 @@ function columnLabel(col) {
|
||||
return labels[col] || col;
|
||||
}
|
||||
|
||||
function dirLabel(dir) {
|
||||
const labels = {
|
||||
'in': _('Inbound'),
|
||||
'out': _('Outbound'),
|
||||
'forward': _('Forwarded'),
|
||||
'unknown': _('unknown')
|
||||
};
|
||||
|
||||
return labels[dir] || log.formatCell(dir);
|
||||
}
|
||||
|
||||
function actionLabel(action) {
|
||||
const labels = {
|
||||
'pass': _('pass'),
|
||||
'block': _('block'),
|
||||
'drop': _('drop'),
|
||||
'reject': _('reject')
|
||||
};
|
||||
|
||||
return labels[action] || log.formatActionLabel(action);
|
||||
}
|
||||
|
||||
function columnCellClass(col) {
|
||||
switch (col) {
|
||||
case 'time':
|
||||
@@ -124,12 +146,7 @@ function buildColumnCell(col, row, state, callbacks) {
|
||||
const msgDisplay = log.formatMessageDisplay(row.message, state.messageLayout);
|
||||
const actionCell =
|
||||
row.action && row.action !== 'unknown'
|
||||
? links.filterLink(
|
||||
'action',
|
||||
row.action,
|
||||
log.formatActionLabel(row.action),
|
||||
onFilterClick
|
||||
)
|
||||
? links.filterLink('action', row.action, actionLabel(row.action), onFilterClick)
|
||||
: log.formatActionLabel(row.action);
|
||||
|
||||
switch (col) {
|
||||
@@ -162,7 +179,7 @@ function buildColumnCell(col, row, state, callbacks) {
|
||||
)
|
||||
]);
|
||||
case 'dir':
|
||||
return E('td', { 'class': columnCellClass(col) }, [log.formatCell(row.direction)]);
|
||||
return E('td', { 'class': columnCellClass(col) }, [dirLabel(row.direction)]);
|
||||
case 'proto':
|
||||
return E('td', { 'class': columnCellClass(col) }, [
|
||||
links.filterLink('proto', row.proto, null, onFilterClick)
|
||||
|
||||
@@ -2488,11 +2488,11 @@ return view.extend({
|
||||
}),
|
||||
E('select', { 'id': 'fwlive-action', 'class': 'cbi-input-select' }, [
|
||||
E('option', { 'value': '' }, [_('Any action')]),
|
||||
E('option', { 'value': 'pass' }, ['pass']),
|
||||
E('option', { 'value': 'block' }, ['block']),
|
||||
E('option', { 'value': 'drop' }, ['drop']),
|
||||
E('option', { 'value': 'reject' }, ['reject']),
|
||||
E('option', { 'value': 'unknown' }, ['unknown']),
|
||||
E('option', { 'value': 'pass' }, [_('pass')]),
|
||||
E('option', { 'value': 'block' }, [_('block')]),
|
||||
E('option', { 'value': 'drop' }, [_('drop')]),
|
||||
E('option', { 'value': 'reject' }, [_('reject')]),
|
||||
E('option', { 'value': 'unknown' }, [_('unknown')]),
|
||||
E('option', { 'value': '!pass' }, [_('not pass')]),
|
||||
E('option', { 'value': '!drop' }, [_('not drop')]),
|
||||
E('option', { 'value': '!block' }, [_('not block')]),
|
||||
@@ -2607,7 +2607,8 @@ return view.extend({
|
||||
this.updateTintWarnUi();
|
||||
this.renderRows(true);
|
||||
const testLi = document.getElementById('fwlive-manual-test');
|
||||
if (testLi) logging.renderManualTestNodes(testLi, {}, {});
|
||||
if (testLi)
|
||||
logging.renderManualTestNodes(testLi, { firewallBackend: this.firewallBackend }, {});
|
||||
if (this.showHostnames) this.resolveHostnamesForEntries(this.filteredRows());
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user