mirror of
https://github.com/gSpotx2f/ruantiblock_openwrt.git
synced 2026-05-14 14:40:58 +00:00
luci-app: New log.
ruantiblock: Minor fixes.
This commit is contained in:
@@ -9,9 +9,9 @@ LUA_MODULE=1
|
|||||||
LUCI_APP=1
|
LUCI_APP=1
|
||||||
|
|
||||||
OWRT_VERSION="19.07"
|
OWRT_VERSION="19.07"
|
||||||
RUAB_VERSION="0.9.0-1"
|
RUAB_VERSION="0.9.0-2"
|
||||||
RUAB_MOD_LUA_VERSION="0.9.0-1"
|
RUAB_MOD_LUA_VERSION="0.9.0-2"
|
||||||
RUAB_LUCI_APP_VERSION="0.9.0-2"
|
RUAB_LUCI_APP_VERSION="0.9.0-3"
|
||||||
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master"
|
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master"
|
||||||
PKG_DIR="/tmp"
|
PKG_DIR="/tmp"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_VERSION:=0.9.0
|
PKG_VERSION:=0.9.0
|
||||||
PKG_RELEASE:=2
|
PKG_RELEASE:=3
|
||||||
LUCI_TITLE:=LuCI support for ruantiblock
|
LUCI_TITLE:=LuCI support for ruantiblock
|
||||||
LUCI_DEPENDS:=+ruantiblock +luci-mod-admin-full
|
LUCI_DEPENDS:=+ruantiblock +luci-mod-admin-full
|
||||||
LUCI_PKGARCH:=all
|
LUCI_PKGARCH:=all
|
||||||
|
|||||||
@@ -0,0 +1,502 @@
|
|||||||
|
'use strict';
|
||||||
|
'require ui';
|
||||||
|
|
||||||
|
return L.Class.extend({
|
||||||
|
view: L.view.extend({
|
||||||
|
viewName: null,
|
||||||
|
|
||||||
|
title: null,
|
||||||
|
|
||||||
|
logFacilities: [
|
||||||
|
'kern',
|
||||||
|
'user',
|
||||||
|
'mail',
|
||||||
|
'daemon',
|
||||||
|
'auth',
|
||||||
|
'syslog',
|
||||||
|
'lpr',
|
||||||
|
'news',
|
||||||
|
],
|
||||||
|
|
||||||
|
logLevels: {
|
||||||
|
'emerg': E('span', { 'class': 'zonebadge log-emerg' }, E('strong', _('Emergency'))),
|
||||||
|
'alert': E('span', { 'class': 'zonebadge log-alert' }, E('strong', _('Alert'))),
|
||||||
|
'crit': E('span', { 'class': 'zonebadge log-crit' }, E('strong', _('Critical'))),
|
||||||
|
'err': E('span', { 'class': 'zonebadge log-err' }, E('strong', _('Error'))),
|
||||||
|
'warn': E('span', { 'class': 'zonebadge log-warn' }, E('strong', _('Warning'))),
|
||||||
|
'notice': E('span', { 'class': 'zonebadge log-notice' }, E('strong', _('Notice'))),
|
||||||
|
'info': E('span', { 'class': 'zonebadge log-info' }, E('strong', _('Info'))),
|
||||||
|
'debug': E('span', { 'class': 'zonebadge log-debug' }, E('strong', _('Debug'))),
|
||||||
|
},
|
||||||
|
|
||||||
|
tailValue: 25,
|
||||||
|
|
||||||
|
logSortingValue: 'asc',
|
||||||
|
|
||||||
|
logLevelsStat: {},
|
||||||
|
|
||||||
|
logLevelsDropdown: null,
|
||||||
|
|
||||||
|
totalLogLines: 0,
|
||||||
|
|
||||||
|
htmlEntities: function(str) {
|
||||||
|
return String(str).replace(
|
||||||
|
/&/g, '&').replace(
|
||||||
|
/</g, '<').replace(
|
||||||
|
/>/g, '>').replace(
|
||||||
|
/"/g, '"');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} tail
|
||||||
|
* @returns {string}
|
||||||
|
* Returns the raw content of the log
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getLogData: function(tail) {
|
||||||
|
throw new Error('getLogData needs to be reloaded in subclass');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} logdata
|
||||||
|
* @param {number} tail
|
||||||
|
* @returns {Array<number, string|null, string|null, string|null, string|null>}
|
||||||
|
* Returns an array of values: [ #, Timestamp, Level, Facility, Message ]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
parseLogData: function(logdata, tail) {
|
||||||
|
throw new Error('parseLogData needs to be reloaded in subclass');
|
||||||
|
},
|
||||||
|
|
||||||
|
makeLogArea: function(logdataArray) {
|
||||||
|
let lines = `<div class="tr"><div class="td center log-entry-empty">${_('No entries available...')}</div></div>`;
|
||||||
|
let logTable = E('div', { 'id': 'logTable', 'class': 'table' });
|
||||||
|
|
||||||
|
for(let level of Object.keys(this.logLevels)) {
|
||||||
|
this.logLevelsStat[level] = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(logdataArray.length > 0) {
|
||||||
|
lines = [];
|
||||||
|
logdataArray.forEach((e, i) => {
|
||||||
|
this.logLevelsStat[e[2]] = (this.logLevelsStat[e[2]] != undefined) ?
|
||||||
|
this.logLevelsStat[e[2]] + 1 : 1;
|
||||||
|
|
||||||
|
lines.push(
|
||||||
|
`<div class="tr log-${e[2] || 'empty'}"><div class="td left" data-title="#">${e[0]}</div>` +
|
||||||
|
((e[1]) ? `<div class="td left" data-title="${_('Timestamp')}">${e[1]}</div>` : '') +
|
||||||
|
((e[2]) ? `<div class="td left" data-title="${_('Level')}">${e[2]}</div>` : '') +
|
||||||
|
((e[3]) ? `<div class="td left" data-title="${_('Facility')}">${e[3]}</div>` : '') +
|
||||||
|
((e[4]) ? `<div class="td left" data-title="${_('Message')}">${e[4]}</div>` : '') +
|
||||||
|
`</div>`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
lines = lines.join('');
|
||||||
|
|
||||||
|
logTable.append(
|
||||||
|
E('div', { 'class': 'tr table-titles' }, [
|
||||||
|
E('div', { 'class': 'th left log-entry-number' }, '#'),
|
||||||
|
(logdataArray[0][1]) ? E('div', { 'class': 'th left log-entry-time' }, _('Timestamp')) : '',
|
||||||
|
(logdataArray[0][2]) ? E('div', { 'class': 'th left log-entry-log-level' }, _('Level')) : '',
|
||||||
|
(logdataArray[0][3]) ? E('div', { 'class': 'th left log-entry-facility' }, _('Facility')) : '',
|
||||||
|
(logdataArray[0][4]) ? E('div', { 'class': 'th left log-entry-message' }, _('Message')) : '',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
logTable.insertAdjacentHTML('beforeend', lines);
|
||||||
|
} catch(err) {
|
||||||
|
if(err.name === 'SyntaxError') {
|
||||||
|
ui.addNotification(null,
|
||||||
|
E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error');
|
||||||
|
};
|
||||||
|
throw err;
|
||||||
|
};
|
||||||
|
|
||||||
|
let levelsStatString = '';
|
||||||
|
if((Object.values(this.logLevelsStat).reduce((s,c) => s + c, 0)) > 0) {
|
||||||
|
Object.entries(this.logLevelsStat).forEach(e => {
|
||||||
|
if(e[1] > 0) {
|
||||||
|
levelsStatString += `<span class="log-entries-count-level log-${e[0]}" title="${e[0]}">${e[1]}</span>`;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return E([
|
||||||
|
E('div', { 'class': 'log-entries-count' },
|
||||||
|
`${_('Entries')}: ${logdataArray.length} / ${this.totalLogLines}${levelsStatString}`
|
||||||
|
),
|
||||||
|
logTable
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
setLevelFilter: function(cArr) {
|
||||||
|
let logLevelsKeys = Object.keys(this.logLevels);
|
||||||
|
if(logLevelsKeys.length > 0) {
|
||||||
|
let selectedLevels = this.logLevelsDropdown.getValue();
|
||||||
|
if(logLevelsKeys.length === selectedLevels.length) {
|
||||||
|
return cArr;
|
||||||
|
};
|
||||||
|
return cArr.filter(s => selectedLevels.length === 0 || selectedLevels.includes(s[2]));
|
||||||
|
};
|
||||||
|
return cArr;
|
||||||
|
},
|
||||||
|
|
||||||
|
setRegexpFilter: function(cArr) {
|
||||||
|
let fPattern = document.getElementById('logFilter').value;
|
||||||
|
if(!fPattern) {
|
||||||
|
return cArr;
|
||||||
|
};
|
||||||
|
let fArr = [];
|
||||||
|
try {
|
||||||
|
let regExp = new RegExp(`(${fPattern})`, 'giu');
|
||||||
|
cArr.forEach((e, i) => {
|
||||||
|
if(regExp.test(e[4])) {
|
||||||
|
e[4] = e[4].replace(regExp, '<span class="log-highlight-item">$1</span>');
|
||||||
|
fArr.push(e);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
if(err.name === 'SyntaxError') {
|
||||||
|
ui.addNotification(null,
|
||||||
|
E('p', {}, _('Invalid regular expression') + ': ' + err.message));
|
||||||
|
return cArr;
|
||||||
|
} else {
|
||||||
|
throw err;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return fArr;
|
||||||
|
},
|
||||||
|
|
||||||
|
downloadLog: function() {
|
||||||
|
let formElems = Array.from(document.forms.logForm.elements);
|
||||||
|
formElems.forEach(e => e.disabled = true);
|
||||||
|
|
||||||
|
return this.getLogData(0).then(logdata => {
|
||||||
|
logdata = logdata || '';
|
||||||
|
let link = E('a', {
|
||||||
|
'download': this.viewName + '.txt',
|
||||||
|
'href': URL.createObjectURL(
|
||||||
|
new Blob([ logdata ], { type: 'text/plain' })),
|
||||||
|
});
|
||||||
|
link.click();
|
||||||
|
URL.revokeObjectURL(link.href);
|
||||||
|
}).catch(() => {
|
||||||
|
ui.addNotification(null,
|
||||||
|
E('p', {}, _('Download error') + ': ' + err.message));
|
||||||
|
}).finally(() => {
|
||||||
|
formElems.forEach(e => e.disabled = false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
load: function() {
|
||||||
|
|
||||||
|
// Restoring settings from localStorage
|
||||||
|
let tailValueLocal = localStorage.getItem(`luci-app-${this.viewName}-tailValue`);
|
||||||
|
if(tailValueLocal) {
|
||||||
|
this.tailValue = Number(tailValueLocal);
|
||||||
|
};
|
||||||
|
let logSortingLocal = localStorage.getItem(`luci-app-${this.viewName}-logSorting`);
|
||||||
|
if(logSortingLocal) {
|
||||||
|
this.logSortingValue = logSortingLocal;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.getLogData(this.tailValue);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function(logdata) {
|
||||||
|
|
||||||
|
document.head.append(E('style', {'type': 'text/css'},
|
||||||
|
`
|
||||||
|
.log-entry-empty {
|
||||||
|
}
|
||||||
|
.log-entry-number {
|
||||||
|
min-width: 4em !important;
|
||||||
|
}
|
||||||
|
.log-entry-time {
|
||||||
|
min-width: 14em !important;
|
||||||
|
}
|
||||||
|
.log-entry-log-level {
|
||||||
|
max-width: 5em !important;
|
||||||
|
}
|
||||||
|
.log-entry-facility{
|
||||||
|
max-width: 7em !important;
|
||||||
|
}
|
||||||
|
.log-entry-message {
|
||||||
|
min-width: 25em !important;
|
||||||
|
}
|
||||||
|
.log-empty {
|
||||||
|
}
|
||||||
|
.log-emerg {
|
||||||
|
background-color: #a93734 !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.log-alert {
|
||||||
|
background-color: #ff7968 !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.log-crit {
|
||||||
|
background-color: #fcc3bf !important;
|
||||||
|
}
|
||||||
|
.log-err {
|
||||||
|
background-color: #ffe9e8 !important;
|
||||||
|
}
|
||||||
|
.log-warn {
|
||||||
|
background-color: #fff7e2 !important;
|
||||||
|
}
|
||||||
|
.log-notice {
|
||||||
|
background-color: #e3ffec !important;
|
||||||
|
}
|
||||||
|
.log-info {
|
||||||
|
}
|
||||||
|
.log-debug {
|
||||||
|
background-color: #ebf6ff !important;
|
||||||
|
}
|
||||||
|
.log-highlight-item {
|
||||||
|
background-color: #ffef00;
|
||||||
|
}
|
||||||
|
.log-entries-count {
|
||||||
|
margin: 0 0 5px 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.log-entries-count-level {
|
||||||
|
display: inline-block !important;
|
||||||
|
margin: 0 0 0 5px;
|
||||||
|
padding: 0 4px;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
));
|
||||||
|
|
||||||
|
let logWrapper = E('div', {
|
||||||
|
'id': 'logWrapper',
|
||||||
|
'style': 'width:100%; min-height:20em; padding: 0 0 0 45px; font-size:0.9em !important'
|
||||||
|
}, this.makeLogArea(this.parseLogData(logdata, this.tailValue)));
|
||||||
|
|
||||||
|
let tailInput = E('input', {
|
||||||
|
'id': 'tailInput',
|
||||||
|
'name': 'tailInput',
|
||||||
|
'type': 'text',
|
||||||
|
'form': 'logForm',
|
||||||
|
'class': 'cbi-input-text',
|
||||||
|
'style': 'width:4em !important; min-width:4em !important',
|
||||||
|
'maxlength': 5,
|
||||||
|
});
|
||||||
|
tailInput.value = (this.tailValue === 0) ? null : this.tailValue;
|
||||||
|
ui.addValidator(tailInput, 'uinteger', true);
|
||||||
|
|
||||||
|
let tailReset = E('input', {
|
||||||
|
'type': 'button',
|
||||||
|
'form': 'logForm',
|
||||||
|
'class': 'cbi-button btn cbi-button-reset',
|
||||||
|
'value': 'Χ',
|
||||||
|
'click': ev => {
|
||||||
|
tailInput.value = null;
|
||||||
|
logFormSubmitBtn.click();
|
||||||
|
ev.target.blur();
|
||||||
|
},
|
||||||
|
'style': 'max-width:4em !important',
|
||||||
|
});
|
||||||
|
|
||||||
|
let logLevelsDropdownElem = '';
|
||||||
|
let logLevelsKeys = Object.keys(this.logLevels);
|
||||||
|
if(logLevelsKeys.length > 0) {
|
||||||
|
this.logLevelsDropdown = new ui.Dropdown(
|
||||||
|
null,
|
||||||
|
this.logLevels,
|
||||||
|
{
|
||||||
|
id: 'logLevelsDropdown',
|
||||||
|
sort: logLevelsKeys,
|
||||||
|
multiple: true,
|
||||||
|
select_placeholder: _('All'),
|
||||||
|
display_items: 3,
|
||||||
|
dropdown_items: -1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
logLevelsDropdownElem = E(
|
||||||
|
'div', { 'class': 'cbi-value' }, [
|
||||||
|
E('label', {
|
||||||
|
'class': 'cbi-value-title',
|
||||||
|
'for': 'logLevelsDropdown',
|
||||||
|
}, _('Logging levels')),
|
||||||
|
E('div', { 'class': 'cbi-value-field' },
|
||||||
|
this.logLevelsDropdown.render()
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let logFilter = E('input', {
|
||||||
|
'id': 'logFilter',
|
||||||
|
'name': 'logFilter',
|
||||||
|
'type': 'text',
|
||||||
|
'form': 'logForm',
|
||||||
|
'class': 'cbi-input-text',
|
||||||
|
'placeholder': _('Type an expression...'),
|
||||||
|
});
|
||||||
|
|
||||||
|
let logFormSubmitBtn = E('input', {
|
||||||
|
'type': 'submit',
|
||||||
|
'form': 'logForm',
|
||||||
|
'class': 'cbi-button btn cbi-button-action',
|
||||||
|
'value': _('Apply'),
|
||||||
|
'click': ev => ev.target.blur(),
|
||||||
|
'style': 'margin-right: 1em',
|
||||||
|
});
|
||||||
|
|
||||||
|
let logSorting = E('select', {
|
||||||
|
'id': 'logSorting',
|
||||||
|
'form': 'logForm',
|
||||||
|
'class': "cbi-input-select",
|
||||||
|
}, [
|
||||||
|
E('option', { 'value': 'asc' }, _('ascending')),
|
||||||
|
E('option', { 'value': 'desc' }, _('descending')),
|
||||||
|
]);
|
||||||
|
logSorting.value = this.logSortingValue;
|
||||||
|
|
||||||
|
let logDownloadBtn = E('button', {
|
||||||
|
'class': 'cbi-button btn',
|
||||||
|
'click': ui.createHandlerFn(this, this.downloadLog),
|
||||||
|
}, _('Download log'));
|
||||||
|
|
||||||
|
return E([
|
||||||
|
E('h2', { 'id': 'logTitle', 'class': 'fade-in' }, this.title),
|
||||||
|
E('div', { 'class': 'cbi-section-descr fade-in' }),
|
||||||
|
E('div', { 'class': 'cbi-section fade-in' },
|
||||||
|
E('div', { 'class': 'cbi-section-node' }, [
|
||||||
|
|
||||||
|
E('div', { 'class': 'cbi-value' }, [
|
||||||
|
E('label', {
|
||||||
|
'class': 'cbi-value-title',
|
||||||
|
'for': 'tailInput',
|
||||||
|
}, _('Last entries')),
|
||||||
|
E('div', { 'class': 'cbi-value-field' }, [
|
||||||
|
tailInput,
|
||||||
|
tailReset,
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
|
||||||
|
logLevelsDropdownElem,
|
||||||
|
|
||||||
|
E('div', { 'class': 'cbi-value' }, [
|
||||||
|
E('label', {
|
||||||
|
'class': 'cbi-value-title',
|
||||||
|
'for': 'logFilter',
|
||||||
|
}, _('Message filter')),
|
||||||
|
E('div', { 'class': 'cbi-value-field' }, logFilter),
|
||||||
|
]),
|
||||||
|
|
||||||
|
E('div', { 'class': 'cbi-value' }, [
|
||||||
|
E('label', {
|
||||||
|
'class': 'cbi-value-title',
|
||||||
|
'for': 'logSorting',
|
||||||
|
}, _('Sorting entries')),
|
||||||
|
E('div', { 'class': 'cbi-value-field' }, logSorting,),
|
||||||
|
]),
|
||||||
|
|
||||||
|
E('div', { 'class': 'cbi-value' }, [
|
||||||
|
E('label', {
|
||||||
|
'class': 'cbi-value-title',
|
||||||
|
'for': 'logFilter',
|
||||||
|
}),
|
||||||
|
E('div', { 'class': 'cbi-value-field' }, [
|
||||||
|
logFormSubmitBtn,
|
||||||
|
E('form', {
|
||||||
|
'id': 'logForm',
|
||||||
|
'name': 'logForm',
|
||||||
|
'style': 'display:inline-block',
|
||||||
|
'submit': ui.createHandlerFn(this, function(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
let formElems = Array.from(document.forms.logForm.elements);
|
||||||
|
formElems.forEach(e => e.disabled = true);
|
||||||
|
logDownloadBtn.disabled = true;
|
||||||
|
|
||||||
|
// Saving settings to localStorage
|
||||||
|
if(this.tailValue != tailInput.value) {
|
||||||
|
this.tailValue = (/^[0-9]+$/.test(tailInput.value)) ? tailInput.value : 0;
|
||||||
|
localStorage.setItem(
|
||||||
|
`luci-app-${this.viewName}-tailValue`, String(this.tailValue));
|
||||||
|
};
|
||||||
|
if(this.logSortingValue != logSorting.value) {
|
||||||
|
this.logSortingValue = logSorting.value;
|
||||||
|
localStorage.setItem(
|
||||||
|
`luci-app-${this.viewName}-logSorting`, this.logSortingValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
let tail = (tailInput.value && tailInput.value > 0) ? tailInput.value : 0
|
||||||
|
return this.getLogData(tail).then(logdata => {
|
||||||
|
logdata = logdata || '';
|
||||||
|
|
||||||
|
let loglines = this.makeLogArea(
|
||||||
|
this.setRegexpFilter(
|
||||||
|
this.setLevelFilter(
|
||||||
|
this.parseLogData(logdata, tail)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
logWrapper.innerHTML = '';
|
||||||
|
logWrapper.append(loglines);
|
||||||
|
|
||||||
|
}).finally(() => {
|
||||||
|
formElems.forEach(e => e.disabled = false);
|
||||||
|
logDownloadBtn.disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
}),
|
||||||
|
}, E('span', {}, ' ')),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
),
|
||||||
|
E('div', { 'class': 'cbi-section fade-in' },
|
||||||
|
E('div', { 'class': 'cbi-section-node' },
|
||||||
|
E('div', { 'class': 'cbi-value' }, [
|
||||||
|
E('div', { 'style': 'position:fixed; z-index:1 !important' }, [
|
||||||
|
E('button', {
|
||||||
|
'class': 'btn',
|
||||||
|
'style': 'position:relative; display:block; margin:0 !important; left:1px; top:1px',
|
||||||
|
'click': ev => {
|
||||||
|
document.getElementById('logTitle').scrollIntoView(true);
|
||||||
|
ev.target.blur();
|
||||||
|
},
|
||||||
|
}, '↑'),
|
||||||
|
E('button', {
|
||||||
|
'class': 'btn',
|
||||||
|
'style': 'position:relative; display:block; margin:0 !important; margin-top:1px !important; left:1px; top:1px',
|
||||||
|
'click': ev => {
|
||||||
|
logWrapper.scrollIntoView(false);
|
||||||
|
ev.target.blur();
|
||||||
|
},
|
||||||
|
}, '↓'),
|
||||||
|
]),
|
||||||
|
logWrapper,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
),
|
||||||
|
E('div', { 'class': 'cbi-section fade-in' },
|
||||||
|
E('div', { 'class': 'cbi-section-node' },
|
||||||
|
E('div', { 'class': 'cbi-value' },
|
||||||
|
E('div', { 'style': 'width:100%; text-align:right !important' }, [
|
||||||
|
E('hr'),
|
||||||
|
logDownloadBtn,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSaveApply: null,
|
||||||
|
handleSave: null,
|
||||||
|
handleReset: null,
|
||||||
|
}),
|
||||||
|
})
|
||||||
@@ -1,18 +1,14 @@
|
|||||||
'use strict';
|
|
||||||
'require fs';
|
'require fs';
|
||||||
'require ui';
|
'require ui';
|
||||||
|
'require view.ruantiblock.baselog as baselog';
|
||||||
'require view.ruantiblock.tools as tools';
|
'require view.ruantiblock.tools as tools';
|
||||||
|
|
||||||
let log_regexp = new RegExp(`^.*(user\\.notice ${tools.app_name}).*$`, 'gm');
|
return baselog.view.extend({
|
||||||
|
viewName: 'ruantiblock-log',
|
||||||
|
|
||||||
return L.view.extend({
|
title: _('Ruantiblock') + ' - ' + _('Log'),
|
||||||
tail_default: 25,
|
|
||||||
|
|
||||||
parse_log_data: function(logdata) {
|
getLogData: function(tail) {
|
||||||
return logdata.trim().match(log_regexp);
|
|
||||||
},
|
|
||||||
|
|
||||||
load: function() {
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
L.resolveDefault(fs.stat('/sbin/logread'), null),
|
L.resolveDefault(fs.stat('/sbin/logread'), null),
|
||||||
L.resolveDefault(fs.stat('/usr/sbin/logread'), null),
|
L.resolveDefault(fs.stat('/usr/sbin/logread'), null),
|
||||||
@@ -20,9 +16,9 @@ return L.view.extend({
|
|||||||
let logger = (stat[0]) ? stat[0].path : (stat[1]) ? stat[1].path : null;
|
let logger = (stat[0]) ? stat[0].path : (stat[1]) ? stat[1].path : null;
|
||||||
|
|
||||||
if(logger) {
|
if(logger) {
|
||||||
return fs.exec_direct(logger, [ '-e', tools.app_name ]).catch(e => {
|
return fs.exec_direct(logger, [ '-e', '^' + tools.app_name ]).catch(err => {
|
||||||
ui.addNotification(null, E('p', _('Unable to execute or read contents')
|
ui.addNotification(null, E('p', _('Unable to execute or read contents')
|
||||||
+ ': %s<br />[ %s ]'.format(e.message, logger)
|
+ ': %s<br />[ %s ]'.format(err.message, logger)
|
||||||
));
|
));
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
@@ -30,166 +26,36 @@ return L.view.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function(logdata) {
|
parseLogData: function(logdata, tail) {
|
||||||
let nav_btns_top = '1px';
|
if(!logdata) {
|
||||||
let loglines = this.parse_log_data(logdata);
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
let log_textarea = E('textarea', {
|
let strings = logdata.trim().split(/\n/);
|
||||||
'id': 'syslog',
|
|
||||||
'class': 'cbi-input-textarea',
|
|
||||||
'style': 'width:100% !important; resize:horizontal; padding: 0 0 0 45px; font-size:12px',
|
|
||||||
'readonly': 'readonly',
|
|
||||||
'wrap': 'off',
|
|
||||||
'rows': this.tail_default,
|
|
||||||
'spellcheck': 'false',
|
|
||||||
}, [ loglines.slice(-this.tail_default).join('\n') ]);
|
|
||||||
|
|
||||||
let tail_value = E('input', {
|
if(tail && tail > 0 && strings) {
|
||||||
'id': 'tail_value',
|
strings = strings.slice(-tail);
|
||||||
'name': 'tail_value',
|
};
|
||||||
'type': 'text',
|
|
||||||
'form': 'log_form',
|
|
||||||
'class': 'cbi-input-text',
|
|
||||||
'style': 'width:4em !important; min-width:4em !important; margin-bottom:0.3em !important',
|
|
||||||
'maxlength': 5,
|
|
||||||
});
|
|
||||||
tail_value.value = this.tail_default;
|
|
||||||
ui.addValidator(tail_value, 'uinteger', true);
|
|
||||||
|
|
||||||
let log_filter = E('input', {
|
this.totalLogLines = strings.length;
|
||||||
'id': 'log_filter',
|
|
||||||
'name': 'log_filter',
|
let entriesArray = strings.map((e, i) => {
|
||||||
'type': 'text',
|
let strArray = e.split(/\s+/);
|
||||||
'form': 'log_form',
|
let logLevel = strArray[5].split('.');
|
||||||
'class': 'cbi-input-text',
|
|
||||||
'style': 'min-width:16em !important; margin-right:1em !important; margin-bottom:0.3em !important',
|
return [
|
||||||
'placeholder': _('Message filter'),
|
i + 1, // # (Number)
|
||||||
'data-tooltip': _('Filter messages with a regexp'),
|
strArray.slice(0, 5).join(' '), // Timestamp (String)
|
||||||
|
logLevel[1], // Level (String)
|
||||||
|
logLevel[0], // Facility (String)
|
||||||
|
this.htmlEntities(strArray.slice(6).join(' ')), // Message (String)
|
||||||
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
let log_form_submit_btn = E('input', {
|
if(this.logSortingValue === 'desc') {
|
||||||
'type': 'submit',
|
entriesArray.reverse();
|
||||||
'form': 'log_form',
|
};
|
||||||
'class': 'cbi-button btn cbi-button-action',
|
|
||||||
'style': 'margin-right:1em !important; margin-bottom:0.3em !important;',
|
|
||||||
'value': _('Apply'),
|
|
||||||
'click': ev => ev.target.blur(),
|
|
||||||
});
|
|
||||||
|
|
||||||
function set_log_tail(c_arr) {
|
return entriesArray;
|
||||||
let tail_num_val = tail_value.value;
|
|
||||||
if(tail_num_val && tail_num_val > 0 && c_arr) {
|
|
||||||
return c_arr.slice(-tail_num_val);
|
|
||||||
};
|
|
||||||
return c_arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_log_filter(c_arr) {
|
|
||||||
let f_pattern = log_filter.value;
|
|
||||||
if(!f_pattern) {
|
|
||||||
return c_arr;
|
|
||||||
};
|
|
||||||
let f_arr = [];
|
|
||||||
try {
|
|
||||||
f_arr = c_arr.filter(s => new RegExp(f_pattern.toLowerCase()).test(s.toLowerCase()));
|
|
||||||
} catch(err) {
|
|
||||||
if(err.name === 'SyntaxError') {
|
|
||||||
ui.addNotification(null,
|
|
||||||
E('p', {}, _('Wrong regular expression') + ': ' + err.message));
|
|
||||||
return c_arr;
|
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
if(f_arr.length === 0) {
|
|
||||||
f_arr.push(_('No matches...'));
|
|
||||||
};
|
|
||||||
return f_arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return E([
|
|
||||||
E('h2', { 'id': 'log_title', 'class': 'fade-in' }, _('Ruantiblock') + ' - ' + _('Log')),
|
|
||||||
E('div', { 'class': 'cbi-section-descr fade-in' }),
|
|
||||||
E('div', { 'class': 'cbi-section fade-in' },
|
|
||||||
E('div', { 'class': 'cbi-section-node' },
|
|
||||||
E('div', { 'class': 'cbi-value' }, [
|
|
||||||
E('label', {
|
|
||||||
'class': 'cbi-value-title',
|
|
||||||
'for': 'tailValue',
|
|
||||||
'style': 'margin-bottom:0.3em !important',
|
|
||||||
}, _('Show only the last messages')),
|
|
||||||
E('div', { 'class': 'cbi-value-field' }, [
|
|
||||||
tail_value,
|
|
||||||
E('input', {
|
|
||||||
'type': 'button',
|
|
||||||
'form': 'log_form',
|
|
||||||
'class': 'cbi-button btn cbi-button-reset',
|
|
||||||
'value': 'Χ',
|
|
||||||
'click': ev => {
|
|
||||||
tail_value.value = null;
|
|
||||||
log_form_submit_btn.click();
|
|
||||||
ev.target.blur();
|
|
||||||
},
|
},
|
||||||
'style': 'margin-right:1em !important; margin-bottom:0.3em !important; max-width:4em !important',
|
|
||||||
}),
|
|
||||||
log_filter,
|
|
||||||
log_form_submit_btn,
|
|
||||||
E('form', {
|
|
||||||
'id': 'log_form',
|
|
||||||
'name': 'log_form',
|
|
||||||
'style': 'display:inline-block; margin-bottom:0.3em !important',
|
|
||||||
'submit': ui.createHandlerFn(this, function(ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
let form_elems = Array.from(document.forms.log_form.elements);
|
|
||||||
form_elems.forEach(e => e.disabled = true);
|
|
||||||
|
|
||||||
return this.load().then(logdata => {
|
|
||||||
let loglines = set_log_filter(set_log_tail(
|
|
||||||
this.parse_log_data(logdata)));
|
|
||||||
log_textarea.rows = (loglines.length < this.tail_default) ?
|
|
||||||
this.tail_default : loglines.length;
|
|
||||||
log_textarea.value = loglines.join('\n');
|
|
||||||
}).finally(() => {
|
|
||||||
form_elems.forEach(e => e.disabled = false);
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
}, E('span', {}, ' ')),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
)
|
|
||||||
),
|
|
||||||
E('div', { 'class': 'cbi-section fade-in' },
|
|
||||||
E('div', { 'class': 'cbi-section-node' },
|
|
||||||
E('div', { 'class': 'cbi-value' }, [
|
|
||||||
E('div', { 'style': 'position:fixed' }, [
|
|
||||||
E('button', {
|
|
||||||
'class': 'btn',
|
|
||||||
'style': 'position:relative; display:block; margin:0 !important; left:1px; top:'
|
|
||||||
+ nav_btns_top,
|
|
||||||
'click': ev => {
|
|
||||||
document.getElementById('log_title').scrollIntoView(true);
|
|
||||||
ev.target.blur();
|
|
||||||
},
|
|
||||||
}, '↑'),
|
|
||||||
E('button', {
|
|
||||||
'class': 'btn',
|
|
||||||
'style': 'position:relative; display:block; margin:0 !important; margin-top:1px !important; left:1px; top:'
|
|
||||||
+ nav_btns_top,
|
|
||||||
'click': ev => {
|
|
||||||
log_textarea.scrollIntoView(false);
|
|
||||||
ev.target.blur();
|
|
||||||
},
|
|
||||||
}, '↓'),
|
|
||||||
]),
|
|
||||||
log_textarea,
|
|
||||||
])
|
|
||||||
)
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleSaveApply: null,
|
|
||||||
handleSave: null,
|
|
||||||
handleReset: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -117,9 +117,6 @@ msgstr "Исключение IP адресов из блэклиста по ша
|
|||||||
msgid "Expecting:"
|
msgid "Expecting:"
|
||||||
msgstr "Ожидается:"
|
msgstr "Ожидается:"
|
||||||
|
|
||||||
msgid "Filter messages with a regexp"
|
|
||||||
msgstr "Фильтровать сообщения с помощью регулярного выражения"
|
|
||||||
|
|
||||||
msgid "FQDN configuration"
|
msgid "FQDN configuration"
|
||||||
msgstr "Конфигурация FQDN"
|
msgstr "Конфигурация FQDN"
|
||||||
|
|
||||||
@@ -171,9 +168,6 @@ msgstr "Основные настройки"
|
|||||||
msgid "Match-set"
|
msgid "Match-set"
|
||||||
msgstr "Правило"
|
msgstr "Правило"
|
||||||
|
|
||||||
msgid "Message filter"
|
|
||||||
msgstr "Фильтр сообщений"
|
|
||||||
|
|
||||||
msgid "Minute"
|
msgid "Minute"
|
||||||
msgstr "Минута"
|
msgstr "Минута"
|
||||||
|
|
||||||
@@ -189,9 +183,6 @@ msgstr "Нет изменений для сохранения."
|
|||||||
msgid "No data"
|
msgid "No data"
|
||||||
msgstr "Нет данных"
|
msgstr "Нет данных"
|
||||||
|
|
||||||
msgid "No matches..."
|
|
||||||
msgstr "Нет совпадений..."
|
|
||||||
|
|
||||||
msgid "No Shedule"
|
msgid "No Shedule"
|
||||||
msgstr "Нет расписания"
|
msgstr "Нет расписания"
|
||||||
|
|
||||||
@@ -262,9 +253,6 @@ msgstr "Установить"
|
|||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Настройки"
|
msgstr "Настройки"
|
||||||
|
|
||||||
msgid "Show only the last messages"
|
|
||||||
msgstr "Показать только последние сообщения"
|
|
||||||
|
|
||||||
msgid "Shutdown"
|
msgid "Shutdown"
|
||||||
msgstr "Выключение"
|
msgstr "Выключение"
|
||||||
|
|
||||||
@@ -371,3 +359,77 @@ msgstr "верный IP-адрес"
|
|||||||
|
|
||||||
msgid "valid address#port"
|
msgid "valid address#port"
|
||||||
msgstr "верный IP-адрес#порт"
|
msgstr "верный IP-адрес#порт"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
msgid "Alert"
|
||||||
|
msgstr "Тревога"
|
||||||
|
|
||||||
|
msgid "All"
|
||||||
|
msgstr "Все"
|
||||||
|
|
||||||
|
msgid "Critical"
|
||||||
|
msgstr "Критическая ситуация"
|
||||||
|
|
||||||
|
msgid "Debug"
|
||||||
|
msgstr "Отладка"
|
||||||
|
|
||||||
|
msgid "Download log"
|
||||||
|
msgstr "Скачать лог"
|
||||||
|
|
||||||
|
msgid "Emergency"
|
||||||
|
msgstr "Чрезвычайная ситуация"
|
||||||
|
|
||||||
|
msgid "Entries"
|
||||||
|
msgstr "Записи"
|
||||||
|
|
||||||
|
msgid "Facility"
|
||||||
|
msgstr "Категория"
|
||||||
|
|
||||||
|
msgid "Info"
|
||||||
|
msgstr "Информация"
|
||||||
|
|
||||||
|
msgid "Invalid regular expression"
|
||||||
|
msgstr "Неправильное регулярное выражение"
|
||||||
|
|
||||||
|
msgid "Last entries"
|
||||||
|
msgstr "Последние записи"
|
||||||
|
|
||||||
|
msgid "Level"
|
||||||
|
msgstr "Уровень"
|
||||||
|
|
||||||
|
msgid "Logging levels"
|
||||||
|
msgstr "Уровни логирования"
|
||||||
|
|
||||||
|
msgid "Message"
|
||||||
|
msgstr "Сообщение"
|
||||||
|
|
||||||
|
msgid "Message filter"
|
||||||
|
msgstr "Фильтр сообщений"
|
||||||
|
|
||||||
|
msgid "No entries available..."
|
||||||
|
msgstr "Нет доступных записей..."
|
||||||
|
|
||||||
|
msgid "Notice"
|
||||||
|
msgstr "Сообщение"
|
||||||
|
|
||||||
|
msgid "Sorting entries"
|
||||||
|
msgstr "Сортировка записей"
|
||||||
|
|
||||||
|
msgid "Timestamp"
|
||||||
|
msgstr "Время"
|
||||||
|
|
||||||
|
msgid "Type an expression..."
|
||||||
|
msgstr "Введите выражение..."
|
||||||
|
|
||||||
|
msgid "Unable to load log data:"
|
||||||
|
msgstr "Невозможно загрузить данные лога:"
|
||||||
|
|
||||||
|
msgid "Warning"
|
||||||
|
msgstr "Внимание"
|
||||||
|
|
||||||
|
msgid "ascending"
|
||||||
|
msgstr "по возрастанию"
|
||||||
|
|
||||||
|
msgid "descending"
|
||||||
|
msgstr "по убыванию"
|
||||||
|
|||||||
@@ -104,9 +104,6 @@ msgstr ""
|
|||||||
msgid "Expecting:"
|
msgid "Expecting:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Filter messages with a regexp"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "FQDN configuration"
|
msgid "FQDN configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -158,9 +155,6 @@ msgstr ""
|
|||||||
msgid "Match-set"
|
msgid "Match-set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Message filter"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Minute"
|
msgid "Minute"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -176,9 +170,6 @@ msgstr ""
|
|||||||
msgid "No data"
|
msgid "No data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "No matches..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "No Shedule"
|
msgid "No Shedule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -237,9 +228,6 @@ msgstr ""
|
|||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Show only the last messages"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Shutdown"
|
msgid "Shutdown"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -341,3 +329,77 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "valid address#port"
|
msgid "valid address#port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
msgid "Alert"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "All"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Critical"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Debug"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Download log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Emergency"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Entries"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Facility"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Info"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Invalid regular expression"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Last entries"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Level"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Logging levels"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Message"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Message filter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "No entries available..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Notice"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Sorting entries"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Timestamp"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Type an expression..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unable to load log data:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Warning"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ascending"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "descending"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
"/etc/init.d/cron enabled": [ "exec" ],
|
"/etc/init.d/cron enabled": [ "exec" ],
|
||||||
"/etc/init.d/cron enable": [ "exec" ],
|
"/etc/init.d/cron enable": [ "exec" ],
|
||||||
"/etc/init.d/cron restart": [ "exec" ],
|
"/etc/init.d/cron restart": [ "exec" ],
|
||||||
"/sbin/logread -e ruantiblock": [ "exec" ],
|
"/sbin/logread -e ^ruantiblock": [ "exec" ],
|
||||||
"/usr/sbin/logread -e ruantiblock": [ "exec" ]
|
"/usr/sbin/logread -e ^ruantiblock": [ "exec" ]
|
||||||
},
|
},
|
||||||
"uci": [ "network", "ruantiblock" ]
|
"uci": [ "network", "ruantiblock" ]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
#
|
|
||||||
# (с) 2020 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
|
|
||||||
#
|
|
||||||
|
|
||||||
include $(TOPDIR)/rules.mk
|
|
||||||
|
|
||||||
PKG_VERSION:=0.9.0
|
|
||||||
PKG_RELEASE:=2
|
|
||||||
LUCI_TITLE:=Translation for luci-app-ruantiblock - Русский (Russian)
|
|
||||||
LUCI_DEPENDS:=+luci-app-ruantiblock
|
|
||||||
LUCI_PKGARCH:=all
|
|
||||||
|
|
||||||
include ../../luci.mk
|
|
||||||
|
|
||||||
# call BuildPackage - OpenWrt buildroot signature
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=ruantiblock-mod-lua
|
PKG_NAME:=ruantiblock-mod-lua
|
||||||
PKG_VERSION:=0.9.0
|
PKG_VERSION:=0.9.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=2
|
||||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
|
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
|||||||
@@ -317,8 +317,8 @@ function BlackListParser:fill_domain_tables(val)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function BlackListParser:sink()
|
function BlackListParser:sink()
|
||||||
-- Must be reload in the subclass
|
-- Needs to be reloaded in subclass
|
||||||
error("Method BlackListParser:sink() must be reload in the subclass!")
|
error("Method BlackListParser:sink() needs to be reloaded in subclass!")
|
||||||
end
|
end
|
||||||
|
|
||||||
function BlackListParser:optimize_ip_table()
|
function BlackListParser:optimize_ip_table()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=ruantiblock-mod-py
|
PKG_NAME:=ruantiblock-mod-py
|
||||||
PKG_VERSION:=0.9.0
|
PKG_VERSION:=0.9.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=2
|
||||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
|
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
|||||||
@@ -294,9 +294,7 @@ class BlackListParser(Config):
|
|||||||
raise FieldValueError()
|
raise FieldValueError()
|
||||||
|
|
||||||
def parser_func(self):
|
def parser_func(self):
|
||||||
"""
|
"""Needs to be reloaded in subclass"""
|
||||||
Must be reload in the subclass
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def _check_sld_masks(self, sld):
|
def _check_sld_masks(self, sld):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=ruantiblock
|
PKG_NAME:=ruantiblock
|
||||||
PKG_VERSION:=0.9.0
|
PKG_VERSION:=0.9.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=2
|
||||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
|
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ CONFIG_DIR="/etc/${NAME}"
|
|||||||
CONFIG_FILE="${CONFIG_DIR}/${NAME}.conf"
|
CONFIG_FILE="${CONFIG_DIR}/${NAME}.conf"
|
||||||
export DATA_DIR="${CONFIG_DIR}/var"
|
export DATA_DIR="${CONFIG_DIR}/var"
|
||||||
export EXEC_DIR="/usr/bin"
|
export EXEC_DIR="/usr/bin"
|
||||||
|
|
||||||
### Команда для перезапуска dnsmasq
|
### Команда для перезапуска dnsmasq
|
||||||
export DNSMASQ_RESTART_CMD="/etc/init.d/dnsmasq restart"
|
export DNSMASQ_RESTART_CMD="/etc/init.d/dnsmasq restart"
|
||||||
### Директория для html-страницы статуса (не используется в OpenWrt)
|
### Директория для html-страницы статуса (не используется в OpenWrt)
|
||||||
@@ -123,12 +124,14 @@ export AF_ENCODING=""
|
|||||||
|
|
||||||
############################ Configuration #############################
|
############################ Configuration #############################
|
||||||
|
|
||||||
|
### External config
|
||||||
[ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE"
|
[ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE"
|
||||||
|
|
||||||
CONFIG_SCRIPT="${CONFIG_DIR}/scripts/config_script"
|
CONFIG_SCRIPT="${CONFIG_DIR}/scripts/config_script"
|
||||||
START_SCRIPT="${CONFIG_DIR}/scripts/start_script"
|
START_SCRIPT="${CONFIG_DIR}/scripts/start_script"
|
||||||
STOP_SCRIPT="${CONFIG_DIR}/scripts/stop_script"
|
STOP_SCRIPT="${CONFIG_DIR}/scripts/stop_script"
|
||||||
|
|
||||||
|
### Config script
|
||||||
[ -f "$CONFIG_SCRIPT" ] && . "$CONFIG_SCRIPT"
|
[ -f "$CONFIG_SCRIPT" ] && . "$CONFIG_SCRIPT"
|
||||||
|
|
||||||
AWK_CMD="awk"
|
AWK_CMD="awk"
|
||||||
@@ -208,7 +211,15 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
MakeLogRecord() {
|
MakeLogRecord() {
|
||||||
[ $USE_LOGGER = "1" ] && $LOGGER_CMD $LOGGER_PARAMS $1
|
local _log_level
|
||||||
|
if [ $USE_LOGGER = "1" ]; then
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
_log_level="info"
|
||||||
|
else
|
||||||
|
_log_level="$2"
|
||||||
|
fi
|
||||||
|
$LOGGER_CMD $LOGGER_PARAMS -p "user.${_log_level}" "$1"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
DnsmasqRestart() {
|
DnsmasqRestart() {
|
||||||
@@ -250,7 +261,7 @@ TotalProxyOn() {
|
|||||||
IptTotalProxyAdd
|
IptTotalProxyAdd
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo " ${IPSET_TOTAL_PROXY} enabled"
|
echo " ${IPSET_TOTAL_PROXY} enabled"
|
||||||
MakeLogRecord "${IPSET_TOTAL_PROXY} enabled"
|
MakeLogRecord "${IPSET_TOTAL_PROXY} enabled" "notice"
|
||||||
fi
|
fi
|
||||||
MakeToken
|
MakeToken
|
||||||
fi
|
fi
|
||||||
@@ -263,7 +274,7 @@ TotalProxyOff() {
|
|||||||
echo " ${IPSET_TOTAL_PROXY} is already disabled" >&2
|
echo " ${IPSET_TOTAL_PROXY} is already disabled" >&2
|
||||||
else
|
else
|
||||||
echo " ${IPSET_TOTAL_PROXY} disabled"
|
echo " ${IPSET_TOTAL_PROXY} disabled"
|
||||||
MakeLogRecord "${IPSET_TOTAL_PROXY} disabled"
|
MakeLogRecord "${IPSET_TOTAL_PROXY} disabled" "notice"
|
||||||
fi
|
fi
|
||||||
MakeToken
|
MakeToken
|
||||||
fi
|
fi
|
||||||
@@ -291,6 +302,7 @@ DelIptRules() {
|
|||||||
|
|
||||||
SetNetConfig() {
|
SetNetConfig() {
|
||||||
local _set
|
local _set
|
||||||
|
### Создание списков ipset. Проверка на наличие списка с таким же именем, если нет, то создается новый
|
||||||
for _set in "$IPSET_TOTAL_PROXY" "$IPSET_CIDR_TMP" "$IPSET_CIDR"
|
for _set in "$IPSET_TOTAL_PROXY" "$IPSET_CIDR_TMP" "$IPSET_CIDR"
|
||||||
do
|
do
|
||||||
IsIpsetExists "$_set" || $IPSET_CMD create "$_set" hash:net maxelem $IPSET_MAXELEM
|
IsIpsetExists "$_set" || $IPSET_CMD create "$_set" hash:net maxelem $IPSET_MAXELEM
|
||||||
@@ -311,6 +323,7 @@ DropNetConfig() {
|
|||||||
|
|
||||||
FillIpsets() {
|
FillIpsets() {
|
||||||
local _set
|
local _set
|
||||||
|
### Заполнение списков ipset $IPSET_IP и $IPSET_CIDR. Сначала restore загружает во временные списки, а затем swap из временных добавляет в основные
|
||||||
if [ -f "$IP_DATA_FILE" ]; then
|
if [ -f "$IP_DATA_FILE" ]; then
|
||||||
echo " Filling ipsets..."
|
echo " Filling ipsets..."
|
||||||
FlushIpSets "$IPSET_IP_TMP" "$IPSET_CIDR_TMP"
|
FlushIpSets "$IPSET_IP_TMP" "$IPSET_CIDR_TMP"
|
||||||
@@ -321,7 +334,7 @@ FillIpsets() {
|
|||||||
FlushIpSets "$IPSET_IP_TMP" "$IPSET_CIDR_TMP"
|
FlushIpSets "$IPSET_IP_TMP" "$IPSET_CIDR_TMP"
|
||||||
else
|
else
|
||||||
echo " Error! Ipset wasn't updated" >&2
|
echo " Error! Ipset wasn't updated" >&2
|
||||||
MakeLogRecord "Error! Ipset wasn't updated"
|
MakeLogRecord "Error! Ipset wasn't updated" "err"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -353,6 +366,7 @@ CheckStatus() {
|
|||||||
PreStartCheck() {
|
PreStartCheck() {
|
||||||
[ -d "$DATA_DIR" ] || mkdir -p "$DATA_DIR"
|
[ -d "$DATA_DIR" ] || mkdir -p "$DATA_DIR"
|
||||||
[ "$HTML_INFO" = "1" -a ! -d "$HTML_DIR" ] && mkdir -p "$HTML_DIR"
|
[ "$HTML_INFO" = "1" -a ! -d "$HTML_DIR" ] && mkdir -p "$HTML_DIR"
|
||||||
|
### Костыль для старта dnsmasq
|
||||||
[ -e "$DNSMASQ_DATA_FILE" ] || printf "\n" > "$DNSMASQ_DATA_FILE"
|
[ -e "$DNSMASQ_DATA_FILE" ] || printf "\n" > "$DNSMASQ_DATA_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,8 +418,9 @@ GetDataFiles() {
|
|||||||
$BLLIST_MODULE
|
$BLLIST_MODULE
|
||||||
_return_code=$?
|
_return_code=$?
|
||||||
[ $_return_code -eq 0 ] && break
|
[ $_return_code -eq 0 ] && break
|
||||||
|
### STDOUT
|
||||||
echo " Module run attempt ${_attempt}: failed [${BLLIST_MODULE}]"
|
echo " Module run attempt ${_attempt}: failed [${BLLIST_MODULE}]"
|
||||||
MakeLogRecord "Module run attempt ${_attempt}: failed [${BLLIST_MODULE}]"
|
MakeLogRecord "Module run attempt ${_attempt}: failed [${BLLIST_MODULE}]" "err"
|
||||||
_attempt=`expr $_attempt + 1`
|
_attempt=`expr $_attempt + 1`
|
||||||
[ $_attempt -gt $MODULE_RUN_ATTEMPTS ] && break
|
[ $_attempt -gt $MODULE_RUN_ATTEMPTS ] && break
|
||||||
sleep $MODULE_RUN_TIMEOUT
|
sleep $MODULE_RUN_TIMEOUT
|
||||||
@@ -416,8 +431,9 @@ GetDataFiles() {
|
|||||||
printf "Received entries: %s\n", (NF < 3) ? "No data" : "IP: "$1", CIDR: "$2", FQDN: "$3;
|
printf "Received entries: %s\n", (NF < 3) ? "No data" : "IP: "$1", CIDR: "$2", FQDN: "$3;
|
||||||
exit;
|
exit;
|
||||||
}' "$UPDATE_STATUS_FILE"`
|
}' "$UPDATE_STATUS_FILE"`
|
||||||
|
### STDOUT
|
||||||
echo " ${_update_string}"
|
echo " ${_update_string}"
|
||||||
MakeLogRecord "${_update_string}"
|
MakeLogRecord "${_update_string}" "info"
|
||||||
printf " `date +%d.%m.%Y-%H:%M`\n" >> "$UPDATE_STATUS_FILE"
|
printf " `date +%d.%m.%Y-%H:%M`\n" >> "$UPDATE_STATUS_FILE"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -429,6 +445,7 @@ GetDataFiles() {
|
|||||||
if [ "$PROXY_MODE" = "2" ]; then
|
if [ "$PROXY_MODE" = "2" ]; then
|
||||||
printf "\n" >> "$DNSMASQ_DATA_FILE"
|
printf "\n" >> "$DNSMASQ_DATA_FILE"
|
||||||
else
|
else
|
||||||
|
### Запись для .onion в $DNSMASQ_DATA_FILE
|
||||||
printf "server=/onion/%s\nipset=/onion/%s\n" "${ONION_DNS_ADDR}" "${IPSET_ONION}" >> "$DNSMASQ_DATA_FILE"
|
printf "server=/onion/%s\nipset=/onion/%s\n" "${ONION_DNS_ADDR}" "${IPSET_ONION}" >> "$DNSMASQ_DATA_FILE"
|
||||||
fi
|
fi
|
||||||
rm -f "$UPDATE_PID_FILE"
|
rm -f "$UPDATE_PID_FILE"
|
||||||
@@ -450,11 +467,11 @@ Update() {
|
|||||||
MakeToken
|
MakeToken
|
||||||
if [ -e "$UPDATE_PID_FILE" ] && [ "$1" != "force-update" ]; then
|
if [ -e "$UPDATE_PID_FILE" ] && [ "$1" != "force-update" ]; then
|
||||||
echo " ${NAME} ${1} - Error! Another instance of update is already running" >&2
|
echo " ${NAME} ${1} - Error! Another instance of update is already running" >&2
|
||||||
MakeLogRecord "${1} - Error! Another instance of update is already running"
|
MakeLogRecord "${1} - Error! Another instance of update is already running" "err"
|
||||||
_return_code=2
|
_return_code=2
|
||||||
else
|
else
|
||||||
echo " ${NAME} ${1}..."
|
echo " ${NAME} ${1}..."
|
||||||
MakeLogRecord "${1}..."
|
MakeLogRecord "${1}..." "notice"
|
||||||
if [ "$IPSET_CLEAR_SETS" = "1" ]; then
|
if [ "$IPSET_CLEAR_SETS" = "1" ]; then
|
||||||
FlushIpSets "$IPSET_IP" "$IPSET_CIDR" "$IPSET_DNSMASQ"
|
FlushIpSets "$IPSET_IP" "$IPSET_CIDR" "$IPSET_DNSMASQ"
|
||||||
fi
|
fi
|
||||||
@@ -462,16 +479,16 @@ Update() {
|
|||||||
case $? in
|
case $? in
|
||||||
0)
|
0)
|
||||||
echo " Blacklist updated"
|
echo " Blacklist updated"
|
||||||
MakeLogRecord "Blacklist updated"
|
MakeLogRecord "Blacklist updated" "info"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
echo " Error! Blacklist update error" >&2
|
echo " Error! Blacklist update error" >&2
|
||||||
MakeLogRecord "Error! Blacklist update error"
|
MakeLogRecord "Error! Blacklist update error" "err"
|
||||||
_return_code=1
|
_return_code=1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo " Module error! [${BLLIST_MODULE}]" >&2
|
echo " Module error! [${BLLIST_MODULE}]" >&2
|
||||||
MakeLogRecord "Module error! [${BLLIST_MODULE}]"
|
MakeLogRecord "Module error! [${BLLIST_MODULE}]" "err"
|
||||||
_return_code=1
|
_return_code=1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -498,7 +515,7 @@ Start() {
|
|||||||
_return_code=1
|
_return_code=1
|
||||||
else
|
else
|
||||||
echo " ${NAME} ${1}..."
|
echo " ${NAME} ${1}..."
|
||||||
MakeLogRecord "${1}..."
|
MakeLogRecord "${1}..." "notice"
|
||||||
DropNetConfig &> /dev/null
|
DropNetConfig &> /dev/null
|
||||||
SetNetConfig
|
SetNetConfig
|
||||||
PreStartCheck
|
PreStartCheck
|
||||||
@@ -517,7 +534,7 @@ Stop() {
|
|||||||
if CheckStatus; then
|
if CheckStatus; then
|
||||||
MakeToken
|
MakeToken
|
||||||
echo " ${NAME} ${1}..."
|
echo " ${NAME} ${1}..."
|
||||||
MakeLogRecord "${1}..."
|
MakeLogRecord "${1}..." "notice"
|
||||||
DropNetConfig &> /dev/null
|
DropNetConfig &> /dev/null
|
||||||
_return_code=$?
|
_return_code=$?
|
||||||
### Stop script
|
### Stop script
|
||||||
|
|||||||
Reference in New Issue
Block a user