diff --git a/autoinstall/autoinstall.sh b/autoinstall/autoinstall.sh
index 262c2b2..7a061ba 100755
--- a/autoinstall/autoinstall.sh
+++ b/autoinstall/autoinstall.sh
@@ -11,7 +11,7 @@ LUCI_APP=1
OWRT_VERSION="19.07"
RUAB_VERSION="0.9.0-2"
RUAB_MOD_LUA_VERSION="0.9.0-2"
-RUAB_LUCI_APP_VERSION="0.9.0-3"
+RUAB_LUCI_APP_VERSION="0.9.0-4"
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master"
PKG_DIR="/tmp"
diff --git a/luci-app-ruantiblock/Makefile b/luci-app-ruantiblock/Makefile
index 85c0bbf..833340a 100644
--- a/luci-app-ruantiblock/Makefile
+++ b/luci-app-ruantiblock/Makefile
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=0.9.0
-PKG_RELEASE:=3
+PKG_RELEASE:=4
LUCI_TITLE:=LuCI support for ruantiblock
LUCI_DEPENDS:=+ruantiblock +luci-mod-admin-full
LUCI_PKGARCH:=all
diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/baselog.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/baselog.js
index 76437ba..f6b13cf 100644
--- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/baselog.js
+++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/baselog.js
@@ -44,7 +44,8 @@ return L.Class.extend({
/&/g, '&').replace(
//g, '>').replace(
- /"/g, '"');
+ /"/g, '"').replace(
+ /'/g, ''');
},
/**
@@ -70,6 +71,44 @@ return L.Class.extend({
throw new Error('parseLogData needs to be reloaded in subclass');
},
+ 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(e[4] !== null && regExp.test(e[4])) {
+ e[4] = e[4].replace(regExp, '$1');
+ 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;
+ },
+
makeLogArea: function(logdataArray) {
let lines = `
${_('No entries available...')}
`;
let logTable = E('div', { 'id': 'logTable', 'class': 'table' });
@@ -81,15 +120,16 @@ return L.Class.extend({
if(logdataArray.length > 0) {
lines = [];
logdataArray.forEach((e, i) => {
- this.logLevelsStat[e[2]] = (this.logLevelsStat[e[2]] != undefined) ?
- this.logLevelsStat[e[2]] + 1 : 1;
+ if(e[2] in this.logLevels) {
+ this.logLevelsStat[e[2]] = this.logLevelsStat[e[2]] + 1;
+ };
lines.push(
`${e[0]}
` +
((e[1]) ? `
${e[1]}
` : '') +
((e[2]) ? `
${e[2]}
` : '') +
((e[3]) ? `
${e[3]}
` : '') +
- ((e[4]) ? `
${e[4]}
` : '') +
+ ((e[4]) ? `
${e[4]}
` : '') +
`
`
);
});
@@ -119,7 +159,7 @@ return L.Class.extend({
let levelsStatString = '';
if((Object.values(this.logLevelsStat).reduce((s,c) => s + c, 0)) > 0) {
Object.entries(this.logLevelsStat).forEach(e => {
- if(e[1] > 0) {
+ if(e[0] in this.logLevels && e[1] > 0) {
levelsStatString += `${e[1]}`;
};
});
@@ -133,52 +173,14 @@ return L.Class.extend({
]);
},
- 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, '$1');
- 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() {
+ downloadLog: function(ev) {
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',
+ 'download': this.viewName + '.log',
'href': URL.createObjectURL(
new Blob([ logdata ], { type: 'text/plain' })),
});
@@ -228,16 +230,32 @@ return L.Class.extend({
.log-entry-message {
min-width: 25em !important;
}
+.log-entry-message-cell {
+ overflow-x: hidden !important;
+ text-overflow: ellipsis !important;
+}
.log-empty {
}
.log-emerg {
background-color: #a93734 !important;
color: #fff;
}
+log-emerg .td {
+ color: #fff !important;
+}
+log-emerg td {
+ color: #fff !important;
+}
.log-alert {
background-color: #ff7968 !important;
color: #fff;
}
+.log-alert .td {
+ color: #fff !important;
+}
+.log-alert td {
+ color: #fff !important;
+}
.log-crit {
background-color: #fcc3bf !important;
}
@@ -354,6 +372,7 @@ return L.Class.extend({
let logSorting = E('select', {
'id': 'logSorting',
+ 'name': 'logSorting',
'form': 'logForm',
'class': "cbi-input-select",
}, [
@@ -363,6 +382,8 @@ return L.Class.extend({
logSorting.value = this.logSortingValue;
let logDownloadBtn = E('button', {
+ 'id': 'logDownloadBtn',
+ 'name': 'logDownloadBtn',
'class': 'cbi-button btn',
'click': ui.createHandlerFn(this, this.downloadLog),
}, _('Download log'));
@@ -412,7 +433,7 @@ return L.Class.extend({
E('form', {
'id': 'logForm',
'name': 'logForm',
- 'style': 'display:inline-block',
+ 'style': 'display:inline-block; margin-top:0.5em',
'submit': ui.createHandlerFn(this, function(ev) {
ev.preventDefault();
let formElems = Array.from(document.forms.logForm.elements);
@@ -458,38 +479,33 @@ return L.Class.extend({
])
),
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-node' }, [
+ 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,
- ])
- )
+ E('div', { 'style': 'width:100%; text-align:right !important' }, logDownloadBtn)
+ ),
)
),
]);
diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log.js
index 7f2d312..ad21c26 100644
--- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log.js
+++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log.js
@@ -1,13 +1,44 @@
'require fs';
'require ui';
-'require view.ruantiblock.baselog as baselog';
+'require view.log.baselog as baselog';
'require view.ruantiblock.tools as tools';
return baselog.view.extend({
- viewName: 'ruantiblock-log',
+ viewName: 'ruantiblock',
title: _('Ruantiblock') + ' - ' + _('Log'),
+ appRegexp: new RegExp(`^.*${tools.app_name}\[[0-9]+\].*$`, 'gm'),
+
+ testRegexp: new RegExp(/([0-9]{2}:){2}[0-9]{2}/),
+
+ isLoggerChecked: false,
+
+ entriesHandler: null,
+
+ // logd
+ logdHandler: function(strArray, lineNum) {
+ let logLevel = strArray[5].split('.');
+ return [
+ lineNum, // # (Number)
+ strArray.slice(0, 5).join(' '), // Timestamp (String)
+ logLevel[1], // Level (String)
+ logLevel[0], // Facility (String)
+ this.htmlEntities(strArray.slice(6).join(' ')), // Message (String)
+ ];
+ },
+
+ // syslog-ng
+ syslog_ngHandler: function(strArray, lineNum) {
+ return [
+ lineNum, // # (Number)
+ strArray.slice(0, 3).join(' '), // Timestamp (String)
+ null, // Level (String)
+ null, // Facility (String)
+ this.htmlEntities(strArray.slice(4).join(' ')), // Message (String)
+ ];
+ },
+
getLogData: function(tail) {
return Promise.all([
L.resolveDefault(fs.stat('/sbin/logread'), null),
@@ -16,10 +47,8 @@ return baselog.view.extend({
let logger = (stat[0]) ? stat[0].path : (stat[1]) ? stat[1].path : null;
if(logger) {
- return fs.exec_direct(logger, [ '-e', '^' + tools.app_name ]).catch(err => {
- ui.addNotification(null, E('p', _('Unable to execute or read contents')
- + ': %s
[ %s ]'.format(err.message, logger)
- ));
+ return fs.exec_direct(logger, [ '-e', tools.app_name ]).catch(err => {
+ ui.addNotification(null, E('p', {}, _('Unable to load log data: ' + err.message)));
return '';
});
};
@@ -31,7 +60,7 @@ return baselog.view.extend({
return [];
};
- let strings = logdata.trim().split(/\n/);
+ let strings = logdata.trim().match(this.appRegexp) || [];
if(tail && tail > 0 && strings) {
strings = strings.slice(-tail);
@@ -41,15 +70,22 @@ return baselog.view.extend({
let entriesArray = strings.map((e, i) => {
let strArray = e.split(/\s+/);
- let logLevel = strArray[5].split('.');
- return [
- i + 1, // # (Number)
- strArray.slice(0, 5).join(' '), // Timestamp (String)
- logLevel[1], // Level (String)
- logLevel[0], // Facility (String)
- this.htmlEntities(strArray.slice(6).join(' ')), // Message (String)
- ];
+ if(!this.isLoggerChecked) {
+ /**
+ * Checking the third field of a line.
+ * If it contains time then syslog-ng.
+ */
+ if(this.testRegexp.test(strArray[2])) {
+ this.logLevels = {};
+ this.entriesHandler = this.syslog_ngHandler;
+ } else {
+ this.entriesHandler = this.logdHandler;
+ };
+ this.isLoggerChecked = true;
+ };
+
+ return this.entriesHandler(strArray, i + 1);
});
if(this.logSortingValue === 'desc') {
diff --git a/luci-app-ruantiblock/root/usr/share/rpcd/acl.d/luci-app-ruantiblock.json b/luci-app-ruantiblock/root/usr/share/rpcd/acl.d/luci-app-ruantiblock.json
index 32e0b22..7c239e0 100644
--- a/luci-app-ruantiblock/root/usr/share/rpcd/acl.d/luci-app-ruantiblock.json
+++ b/luci-app-ruantiblock/root/usr/share/rpcd/acl.d/luci-app-ruantiblock.json
@@ -18,8 +18,8 @@
"/etc/init.d/cron enabled": [ "exec" ],
"/etc/init.d/cron enable": [ "exec" ],
"/etc/init.d/cron restart": [ "exec" ],
- "/sbin/logread -e ^ruantiblock": [ "exec" ],
- "/usr/sbin/logread -e ^ruantiblock": [ "exec" ]
+ "/sbin/logread -e ruantiblock": [ "exec" ],
+ "/usr/sbin/logread -e ruantiblock": [ "exec" ]
},
"uci": [ "network", "ruantiblock" ]
},
diff --git a/packages/19.07/luci-app-ruantiblock_0.9.0-3_all.ipk b/packages/19.07/luci-app-ruantiblock_0.9.0-3_all.ipk
deleted file mode 100644
index 236617e..0000000
Binary files a/packages/19.07/luci-app-ruantiblock_0.9.0-3_all.ipk and /dev/null differ
diff --git a/packages/19.07/luci-app-ruantiblock_0.9.0-4_all.ipk b/packages/19.07/luci-app-ruantiblock_0.9.0-4_all.ipk
new file mode 100644
index 0000000..6d91ce6
Binary files /dev/null and b/packages/19.07/luci-app-ruantiblock_0.9.0-4_all.ipk differ
diff --git a/packages/19.07/luci-i18n-ruantiblock-ru_0.9.0-3_all.ipk b/packages/19.07/luci-i18n-ruantiblock-ru_0.9.0-3_all.ipk
deleted file mode 100644
index 57cd059..0000000
Binary files a/packages/19.07/luci-i18n-ruantiblock-ru_0.9.0-3_all.ipk and /dev/null differ
diff --git a/packages/19.07/luci-i18n-ruantiblock-ru_0.9.0-4_all.ipk b/packages/19.07/luci-i18n-ruantiblock-ru_0.9.0-4_all.ipk
new file mode 100644
index 0000000..00b3f45
Binary files /dev/null and b/packages/19.07/luci-i18n-ruantiblock-ru_0.9.0-4_all.ipk differ