diff --git a/autoinstall/2.x/autoinstall.sh b/autoinstall/2.x/autoinstall.sh index 0534d03..0496a54 100755 --- a/autoinstall/2.x/autoinstall.sh +++ b/autoinstall/2.x/autoinstall.sh @@ -10,9 +10,9 @@ LUCI_APP=1 HTTPS_DNS_PROXY=1 OWRT_VERSION="current" -RUAB_VERSION="2.1.4-r3" -RUAB_MOD_LUA_VERSION="2.1.4-r1" -RUAB_LUCI_APP_VERSION="2.1.4-r1" +RUAB_VERSION="2.1.5-r1" +RUAB_MOD_LUA_VERSION="2.1.5-r1" +RUAB_LUCI_APP_VERSION="2.1.5-r1" BASE_URL="https://raw.githubusercontent.com/gSpotx2f/packages-openwrt/master" PKG_DIR="/tmp" @@ -29,7 +29,6 @@ URL_LUCI_APP_PKG="${BASE_URL}/${OWRT_VERSION}/luci-app-ruantiblock_${RUAB_LUCI_A URL_LUCI_APP_RU_PKG="${BASE_URL}/${OWRT_VERSION}/luci-i18n-ruantiblock-ru_${RUAB_LUCI_APP_VERSION}_all.ipk" ### tor URL_TORRC="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master/tor/etc/tor/torrc" -### ruantiblock-mod-lua URL_LUA_IDN="https://raw.githubusercontent.com/haste/lua-idn/master/idn.lua" ### Local files @@ -37,7 +36,7 @@ URL_LUA_IDN="https://raw.githubusercontent.com/haste/lua-idn/master/idn.lua" CONFIG_DIR="${PREFIX}/etc/ruantiblock" USER_LISTS_DIR="${CONFIG_DIR}/user_lists" EXEC_DIR="${PREFIX}/usr/bin" -BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.`date +%s`" +BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.$(date +%s)" ### packages FILE_RUAB_PKG="${PKG_DIR}/ruantiblock_${RUAB_VERSION}_all.ipk" FILE_MOD_LUA_PKG="${PKG_DIR}/ruantiblock-mod-lua_${RUAB_MOD_LUA_VERSION}_all.ipk" @@ -56,23 +55,21 @@ FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock" FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock" ### tor FILE_TORRC="${PREFIX}/etc/tor/torrc" -### ruantiblock-mod-lua -#FILE_LUA_IPTOOL="${PREFIX}/usr/lib/lua/iptool.lua" FILE_LUA_IDN="${PREFIX}/usr/lib/lua/idn.lua" AWK_CMD="awk" -WGET_CMD=`which wget` +WGET_CMD="$(which wget)" if [ $? -ne 0 ]; then echo " Error! wget doesn't exists" >&2 exit 1 fi WGET_PARAMS="--no-check-certificate -q -O " -OPKG_CMD=`which opkg` +OPKG_CMD="$(which opkg)" if [ $? -ne 0 ]; then echo " Error! opkg doesn't exists" >&2 exit 1 fi -UCI_CMD=`which uci` +UCI_CMD="$(which uci)" if [ $? -ne 0 ]; then echo " Error! uci doesn't exists" >&2 exit 1 @@ -104,7 +101,7 @@ RemoveFile() { DlFile() { local _dir _file if [ -n "$2" ]; then - _dir=`dirname "$2"` + _dir=$(dirname "$2") MakeDir "$_dir" _file="$2" else @@ -119,19 +116,19 @@ DlFile() { } BackupFile() { - [ -e "$1" ] && cp -f "$1" "${1}.bak.`date +%s`" + [ -e "$1" ] && cp -f "$1" "${1}.bak.$(date +%s)" } BackupCurrentConfig() { local _file MakeDir "$BACKUP_DIR" - for _file in `ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)"` + for _file in $(ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)") do cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}" done for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC" do - [ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/`basename ${_file}`" + [ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/$(basename ${_file})" done } @@ -165,7 +162,7 @@ InstallPackages() { local _pkg for _pkg in $@ do - if [ -z "`$OPKG_CMD list-installed $_pkg`" ]; then + if [ -z "$($OPKG_CMD list-installed $_pkg)" ]; then $OPKG_CMD --force-overwrite install $_pkg if [ $? -ne 0 ]; then echo "Error during installation of the package (${_pkg})" >&2 @@ -181,7 +178,6 @@ InstallBaseConfig() { RemoveFile "$FILE_RUAB_PKG" > /dev/null DlFile "$URL_RUAB_PKG" "$FILE_RUAB_PKG" && $OPKG_CMD install "$FILE_RUAB_PKG" > /dev/null _return_code=$? - # костыль для остановки сервиса, который запускается автоматически после установки пакета! AppStop return $_return_code } @@ -205,7 +201,7 @@ InstallTPConfig() { } TorrcSettings() { - local _lan_ip=`$UCI_CMD get network.lan.ipaddr | $AWK_CMD -F "/" '{print $1}'` + local _lan_ip=$($UCI_CMD get network.lan.ipaddr | $AWK_CMD -F "/" '{print $1}') if [ -z "$_lan_ip" ]; then _lan_ip="0.0.0.0" fi @@ -223,7 +219,6 @@ InstallTorConfig() { TorrcSettings $UCI_CMD set ruantiblock.config.proxy_mode="1" $UCI_CMD commit ruantiblock - # dnsmasq rebind protection $UCI_CMD add_list dhcp.@dnsmasq[0].rebind_domain='onion' $UCI_CMD commit dhcp } @@ -392,7 +387,6 @@ ConfirmProcessing() { ConfirmProxyMode ConfirmBlacklist -#ConfirmLuaModule ConfirmLuciApp ConfirmHttpsDnsProxy ConfirmProcessing @@ -414,7 +408,7 @@ if [ $? -eq 0 ]; then else PrintBold "Installing Tor configuration..." InstallTorConfig - if `/etc/init.d/tor enabled`; then + if $(/etc/init.d/tor enabled); then /etc/init.d/tor restart fi fi diff --git a/autoinstall/2.x/uninstall.sh b/autoinstall/2.x/uninstall.sh index 82568c7..67516f8 100755 --- a/autoinstall/2.x/uninstall.sh +++ b/autoinstall/2.x/uninstall.sh @@ -7,7 +7,7 @@ PREFIX="" CONFIG_DIR="${PREFIX}/etc/ruantiblock" USER_LISTS_DIR="${CONFIG_DIR}/user_lists" EXEC_DIR="${PREFIX}/usr/bin" -BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.`date +%s`" +BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.$(date +%s)" HTDOCS_VIEW="${PREFIX}/www/luci-static/resources/view" HTDOCS_RUAB="${HTDOCS_VIEW}/ruantiblock" CRONTAB_FILE="/etc/crontabs/root" @@ -33,7 +33,7 @@ FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock" FILE_TORRC="${PREFIX}/etc/tor/torrc" AWK_CMD="awk" -OPKG_CMD=`which opkg` +OPKG_CMD="$(which opkg)" if [ $? -ne 0 ]; then echo " Error! opkg doesn't exists" >&2 exit 1 @@ -61,13 +61,13 @@ RemoveFile() { BackupCurrentConfig() { local _file MakeDir "$BACKUP_DIR" - for _file in `ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)"` + for _file in $(ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)") do cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}" done for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC" do - [ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/`basename ${_file}`" + [ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/$(basename ${_file})" done } @@ -91,7 +91,7 @@ RemoveCronTask() { RestoreTorConfig() { [ -e "${FILE_TORRC}.bak" ] && mv -f "${FILE_TORRC}.bak" "$FILE_TORRC" if [ -x "/etc/init.d/tor" ]; then - if `/etc/init.d/tor enabled`; then + if $(/etc/init.d/tor enabled); then /etc/init.d/tor restart fi fi diff --git a/luci-app-ruantiblock/Makefile b/luci-app-ruantiblock/Makefile index 6aaa118..2729256 100644 --- a/luci-app-ruantiblock/Makefile +++ b/luci-app-ruantiblock/Makefile @@ -1,11 +1,11 @@ # -# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) +# (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-ruantiblock -PKG_VERSION:=2.1.4 +PKG_VERSION:=2.1.5 PKG_RELEASE:=1 LUCI_TITLE:=LuCI support for ruantiblock LUCI_DEPENDS:=+ruantiblock diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-base.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-base.js index 3bebb13..294b681 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-base.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-base.js @@ -10,6 +10,7 @@ document.head.append(E('style', {'type': 'text/css'}, --app-log-dark-font-color: #2e2e2e; --app-log-light-font-color: #fff; --app-log-debug-font-color: #737373; + --app-log-raw-font-color: #737373; --app-log-emerg-color: #a93734; --app-log-alert: #ff7968; --app-log-crit: #fcc3bf; @@ -18,12 +19,14 @@ document.head.append(E('style', {'type': 'text/css'}, --app-log-notice: #e3ffec; --app-log-info: rgba(0,0,0,0); --app-log-debug: #ebf6ff; + --app-log-raw: #eee; --app-log-entries-count-border: #ccc; } :root[data-darkmode="true"] { --app-log-dark-font-color: #fff; --app-log-light-font-color: #fff; --app-log-debug-font-color: #e7e7e7; + --app-log-raw-font-color: #aaa; --app-log-emerg-color: #960909; --app-log-alert: #eb5050; --app-log-crit: #dc7f79; @@ -32,6 +35,7 @@ document.head.append(E('style', {'type': 'text/css'}, --app-log-notice: #007627; --app-log-info: rgba(0,0,0,0); --app-log-debug: #5986b1; + --app-log-raw: #353535; --app-log-entries-count-border: #555; } #logWrapper { @@ -114,6 +118,16 @@ log-emerg td { .log-debug td { color: var(--app-log-debug-font-color) !important; } +.log-raw { + background-color: var(--app-log-raw) !important; + color: var(--app-log-raw-font-color) !important; +} +.log-raw .td { + color: var(--app-log-raw-font-color) !important; +} +.log-raw td { + color: var(--app-log-raw-font-color) !important; +} .log-highlight-item { background-color: #ffef00; color: #2e2e2e; @@ -168,25 +182,32 @@ return baseclass.extend({ * * @property {string} viewName */ - viewName : null, + viewName : null, /** * Page title. * * @property {string} title */ - title : null, + title : null, /** * Enable auto refresh log. * - * @property {bool} autoRefresh + * @property {bool} enableAutoRefresh */ - autoRefresh : false, + enableAutoRefresh : false, - pollInterval : L.env.pollinterval, + /** + * Enable timestamp conversion. + * + * @property {bool} enableConvertTimestamp + */ + enableConvertTimestamp: false, - logFacilities : { + pollInterval : L.env.pollinterval, + + logFacilities : { 'kern' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'kern')), 'user' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'user')), 'mail' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'mail')), @@ -211,7 +232,7 @@ return baseclass.extend({ 'local7' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'local7')), }, - logLevels : { + 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')), @@ -246,13 +267,15 @@ return baseclass.extend({ autoRefreshValue : true, - isAutorefresh : true, + autorefreshOn : true, - isHosts : false, + logTimestampFlag : false, - isFacilities : false, + logHostsFlag : false, - isLevels : false, + logFacilitiesFlag : false, + + logLevelsFlag : false, logHosts : {}, @@ -266,7 +289,13 @@ return baseclass.extend({ totalLogLines : 0, - lastHash : null, + logCols : [ '#', null, null, null, null, _('Message') ], + + convertTimestampValue: false, + + convertTimestampOn : false, + + lastHash : null, actionButtons : [], @@ -283,6 +312,68 @@ return baseclass.extend({ return (/^[0-9]+$/.test(value)) ? value : 0 }, + makeLogConvertTimestampSection() { + if(!this.enableConvertTimestamp) { + return ''; + }; + return E('div', { 'class': 'cbi-value' }, [ + E('label', { + 'class': 'cbi-value-title', + 'for' : 'convertTimestamp', + }, _('Date')), + E('div', { 'class': 'cbi-value-field' }, [ + E('div', { 'class': 'cbi-checkbox' }, [ + this.convertTimestamp, + E('label', {}), + ]), + E('div', { 'class': 'cbi-value-description' }, + _('Convert timestamps to a human readable date') + ), + ]), + ]); + }, + + makeLogTimeFilterSection() { + return E('div', { 'class': 'cbi-value' }, [ + E('label', { + 'class': 'cbi-value-title', + 'for' : 'timeFilter', + }, _('Timestamp filter')), + E('div', { 'class': 'cbi-value-field' }, + E('span', { 'class': 'control-group' }, [ + this.timeFilter, + E('button', { + 'class': 'cbi-button btn', + 'click': L.bind(ev => { + ev.target.blur(); + ev.preventDefault(); + this.timeFilter.value = null; + this.timeFilter.focus(); + }, this), + }, '⌫'), + ]) + ), + ]); + }, + + makeLogtimeFilterReSection() { + return E('div', { 'class': 'cbi-value' }, [ + E('label', { + 'class': 'cbi-value-title', + 'for' : 'timeFilterRe', + }, _('Filter is regexp')), + E('div', { 'class': 'cbi-value-field' }, [ + E('div', { 'class': 'cbi-checkbox' }, [ + this.timeFilterRe, + E('label', {}), + ]), + E('div', { 'class': 'cbi-value-description' }, + _('Apply timestamp filter as regular expression') + ), + ]), + ]); + }, + makeLogHostsDropdownItem(host) { return E( 'span', @@ -385,23 +476,28 @@ return baseclass.extend({ }, setFilterSettings() { - this.tailValue = this.checkZeroValue(this.tailInput.value); - this.timeFilterValue = this.timeFilter.value; - this.timeFilterReValue = this.timeFilterRe.checked; - if(this.isHosts) { + this.tailValue = this.checkZeroValue(this.tailInput.value); + if(this.logTimestampFlag) { + if(this.enableConvertTimestamp) { + this.convertTimestampValue = this.convertTimestamp.checked; + }; + this.timeFilterValue = this.timeFilter.value; + this.timeFilterReValue = this.timeFilterRe.checked; + }; + if(this.logHostsFlag) { this.hostFilterValue = this.logHostsDropdown.getValue(); }; - if(this.isFacilities) { + if(this.logFacilitiesFlag) { this.facilityFilterValue = this.logFacilitiesDropdown.getValue(); }; - if(this.isLevels) { + if(this.logLevelsFlag) { this.levelFilterValue = this.logLevelsDropdown.getValue(); }; - this.msgFilterValue = this.msgFilter.value; - this.msgFilterReValue = this.msgFilterRe.checked; - this.logSortingValue = this.logSorting.value; - this.autoRefreshValue = this.autoRefresh.checked; - if(this.isAutorefresh) { + this.msgFilterValue = this.msgFilter.value; + this.msgFilterReValue = this.msgFilterRe.checked; + this.logSortingValue = this.logSorting.value; + this.autoRefreshValue = this.autoRefresh.checked; + if(this.autorefreshOn) { if(this.autoRefreshValue) { poll.add(this.pollFuncWrapper, this.pollInterval); this.refreshBtn.style.visibility = 'hidden'; @@ -413,16 +509,21 @@ return baseclass.extend({ }, resetFormValues() { - this.tailInput.value = this.tailValue; - this.timeFilter.value = this.timeFilterValue; - this.timeFilterRe.checked = this.timeFilterReValue; - if(this.isHosts) { + this.tailInput.value = this.tailValue; + if(this.logTimestampFlag) { + if(this.enableConvertTimestamp) { + this.convertTimestamp.checked = this.convertTimestampValue; + }; + this.timeFilter.value = this.timeFilterValue; + this.timeFilterRe.checked = this.timeFilterReValue; + }; + if(this.logHostsFlag) { this.logHostsDropdown.setValue(this.hostFilterValue); }; - if(this.isFacilities) { + if(this.logFacilitiesFlag) { this.logFacilitiesDropdown.setValue(this.facilityFilterValue); }; - if(this.isLevels) { + if(this.logLevelsFlag) { this.logLevelsDropdown.setValue(this.levelFilterValue); }; this.msgFilter.value = this.msgFilterValue; @@ -508,7 +609,7 @@ return baseclass.extend({ regExp.lastIndex = 0; }); } catch(err) { - if(err.name === 'SyntaxError') { + if(err.name == 'SyntaxError') { ui.addNotification(null, E('p', {}, _('Invalid regular expression') + ': ' + err.message)); return entriesArray; @@ -533,7 +634,7 @@ return baseclass.extend({ let logHostsKeys = Object.keys(this.logHosts); if(logHostsKeys.length > 0 && this.logHostsDropdown) { this.logHostsDropdown.addChoices(logHostsKeys, this.logHosts); - if(this.hostFilterValue.length === 0 || logHostsKeys.length === this.hostFilterValue.length) { + if(this.hostFilterValue.length == 0) { return entriesArray; }; return entriesArray.filter(e => this.hostFilterValue.includes(e[2])); @@ -544,7 +645,7 @@ return baseclass.extend({ setFacilityFilter(entriesArray) { let logFacilitiesKeys = Object.keys(this.logFacilities); if(logFacilitiesKeys.length > 0 && this.logFacilitiesDropdown) { - if(this.facilityFilterValue.length === 0 || logFacilitiesKeys.length === this.facilityFilterValue.length) { + if(this.facilityFilterValue.length == 0) { return entriesArray; }; return entriesArray.filter(e => this.facilityFilterValue.includes(e[3])); @@ -555,7 +656,7 @@ return baseclass.extend({ setLevelFilter(entriesArray) { let logLevelsKeys = Object.keys(this.logLevels); if(logLevelsKeys.length > 0 && this.logLevelsDropdown) { - if(this.levelFilterValue.length === 0 || logLevelsKeys.length === this.levelFilterValue.length) { + if(this.levelFilterValue.length == 0) { return entriesArray; }; return entriesArray.filter(e => this.levelFilterValue.includes(e[4])); @@ -630,7 +731,13 @@ return baseclass.extend({ if(logSortingLocal) { this.logSortingValue = logSortingLocal; }; - if(this.isAutorefresh) { + if(this.enableConvertTimestamp) { + let convertTimestampLocal = localStorage.getItem(`luci-app-${this.viewName}-convertTimestampValue`); + if(convertTimestampLocal) { + this.convertTimestampValue = Boolean(Number(convertTimestampLocal)); + }; + }; + if(this.enableAutoRefresh) { let autoRefreshLocal = localStorage.getItem(`luci-app-${this.viewName}-autoRefreshValue`); if(autoRefreshLocal) { this.autoRefreshValue = Boolean(Number(autoRefreshLocal)); @@ -638,7 +745,7 @@ return baseclass.extend({ }; }, - saveSettingsToLocalStorage(tailValue, logSortingValue, autoRefreshValue) { + saveSettingsToLocalStorage(tailValue, logSortingValue, autoRefreshValue, convertTimestampValue) { tailValue = this.checkZeroValue(tailValue); if(this.tailValue != tailValue) { localStorage.setItem( @@ -648,7 +755,13 @@ return baseclass.extend({ localStorage.setItem( `luci-app-${this.viewName}-logSortingValue`, logSortingValue); }; - if(this.isAutorefresh) { + if(this.convertTimestampOn) { + if(this.convertTimestampValue != convertTimestampValue) { + localStorage.setItem( + `luci-app-${this.viewName}-convertTimestampValue`, String(Number(convertTimestampValue))); + }; + }; + if(this.autorefreshOn) { if(this.autoRefreshValue != autoRefreshValue) { localStorage.setItem( `luci-app-${this.viewName}-autoRefreshValue`, String(Number(autoRefreshValue))); @@ -681,13 +794,23 @@ return baseclass.extend({ ) ); if(logdata && logdata !== '') { - if(this.isFacilities && !this.logFacilitiesDropdown) { + if(this.enableConvertTimestamp && !this.logConvertTimestampElem) { + this.logConvertTimestampElem = this.makeLogConvertTimestampSection(); + }; + if(this.logTimestampFlag && !this.logTimeFilterElem) { + this.logTimeFilterElem = this.makeLogTimeFilterSection(); + }; + if(this.logTimestampFlag && !this.logtimeFilterReElem) { + this.logtimeFilterReElem = this.makeLogtimeFilterReSection(); + }; + + if(this.logFacilitiesFlag && !this.logFacilitiesDropdown) { this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection(); }; - if(this.isLevels && !this.logLevelsDropdown) { + if(this.logLevelsFlag && !this.logLevelsDropdown) { this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection(); }; - if(this.isHosts && !this.logHostsDropdown) { + if(this.logHostsFlag && !this.logHostsDropdown) { this.logHostsDropdownElem = this.makeLogHostsDropdownSection(); }; }; @@ -730,41 +853,9 @@ return baseclass.extend({ ]) ), ]), - E('div', { 'class': 'cbi-value' }, [ - E('label', { - 'class': 'cbi-value-title', - 'for' : 'timeFilter', - }, _('Timestamp filter')), - E('div', { 'class': 'cbi-value-field' }, - E('span', { 'class': 'control-group' }, [ - this.timeFilter, - E('button', { - 'class': 'cbi-button btn', - 'click': L.bind(ev => { - ev.target.blur(); - ev.preventDefault(); - this.timeFilter.value = null; - this.timeFilter.focus(); - }, this), - }, '⌫'), - ]) - ), - ]), - E('div', { 'class': 'cbi-value' }, [ - E('label', { - 'class': 'cbi-value-title', - 'for' : 'timeFilterRe', - }, _('Filter is regexp')), - E('div', { 'class': 'cbi-value-field' }, [ - E('div', { 'class': 'cbi-checkbox' }, [ - this.timeFilterRe, - E('label', {}), - ]), - E('div', { 'class': 'cbi-value-description' }, - _('Apply timestamp filter as regular expression') - ), - ]), - ]), + this.logConvertTimestampElem, + this.logTimeFilterElem, + this.logtimeFilterReElem, this.logHostsDropdownElem, this.logFacilitiesDropdownElem, this.logLevelsDropdownElem, @@ -810,7 +901,7 @@ return baseclass.extend({ }, _('Sorting entries')), E('div', { 'class': 'cbi-value-field' }, this.logSorting), ]), - ((this.isAutorefresh) ? + ((this.autorefreshOn) ? E('div', { 'class': 'cbi-value' }, [ E('label', { 'class': 'cbi-value-title', @@ -877,6 +968,25 @@ return baseclass.extend({ throw new Error('getLogHash must be overridden by a subclass'); }, + /** + * Converts the timestamp format. + * Abstract method, must be overridden by a subclass! + * + * To completely disable the convert timrstamp option, views extending + * this base class should overwrite the `convertTimestampFunc` function + * with `null`. + * + * @instance + * @abstract + * + * @param {string} t + * @returns {String} + * Returns the converted timestamp string. + */ + convertTimestampFunc(t) { + throw new Error('convertTimestampFunc must be overridden by a subclass'); + }, + async pollFunc() { await this.getLogHash().then(async hash => { if(this.lastHash !== hash) { @@ -895,7 +1005,8 @@ return baseclass.extend({ }; }; this.saveSettingsToLocalStorage( - this.tailInput.value, this.logSorting.value, this.autoRefresh.checked); + this.tailInput.value, this.logSorting.value, + this.autoRefresh.checked, this.convertTimestamp.checked); this.setFilterSettings(); this.fastTailValue = Number(this.tailValue); return this.reloadLog(Number(this.tailValue), true); @@ -911,10 +1022,13 @@ return baseclass.extend({ load() { this.restoreSettingsFromLocalStorage(); - if(!this.autoRefresh || typeof(this.getLogHash) != 'function') { - this.isAutorefresh = false; + if(!this.enableAutoRefresh || typeof(this.getLogHash) != 'function') { + this.autorefreshOn = false; this.autoRefreshValue = false; }; + if(this.enableConvertTimestamp && typeof(this.convertTimestampFunc) == 'function') { + this.convertTimestampOn = true; + }; return this.getLogData(this.tailValue); }, @@ -939,18 +1053,13 @@ return baseclass.extend({ this.tailInput.value = this.tailValue; ui.addValidator(this.tailInput, 'uinteger', true); - this.logHostsDropdownElem = ''; - this.logFacilitiesDropdownElem = ''; - this.logLevelsDropdownElem = ''; - if(this.isLevels) { - this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection(); - }; - if(this.isFacilities) { - this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection(); - }; - if(this.isHosts) { - this.logHostsDropdownElem = this.makeLogHostsDropdownSection(); - }; + this.convertTimestamp = E('input', { + 'id' : 'convertTimestamp', + 'name' : 'convertTimestamp', + 'type' : 'checkbox', + 'form' : 'logFilterForm', + }); + this.convertTimestamp.checked = this.convertTimestampValue; this.timeFilter = E('input', { 'id' : 'timeFilter', @@ -971,6 +1080,28 @@ return baseclass.extend({ this.setRegexpValidator(this.timeFilter, this.timeFilterRe); + this.logConvertTimestampElem = ''; + this.logTimeFilterElem = ''; + this.logtimeFilterReElem = ''; + this.logHostsDropdownElem = ''; + this.logFacilitiesDropdownElem = ''; + this.logLevelsDropdownElem = ''; + + if(this.logTimestampFlag) { + this.logConvertTimestampElem = this.makeLogConvertTimestampSection(); + this.logTimeFilterElem = this.makeLogTimeFilterSection(); + this.logtimeFilterReElem = this.makeLogtimeFilterReSection(); + }; + if(this.logLevelsFlag) { + this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection(); + }; + if(this.logFacilitiesFlag) { + this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection(); + }; + if(this.logHostsFlag) { + this.logHostsDropdownElem = this.makeLogHostsDropdownSection(); + }; + this.msgFilter = E('input', { 'id' : 'msgFilter', 'name' : 'msgFilter', @@ -1123,7 +1254,7 @@ return baseclass.extend({ ]) ); - if(this.isAutorefresh && this.autoRefreshValue) { + if(this.autorefreshOn && this.autoRefreshValue) { poll.add(this.pollFuncWrapper, this.pollInterval); }; diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-abstract.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-system.js similarity index 57% rename from luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-abstract.js rename to luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-system.js index 3c40261..34fb157 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-abstract.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-system.js @@ -1,17 +1,18 @@ 'use strict'; 'require baseclass'; 'require fs'; -'require ui'; 'require view.ruantiblock.log-widget as widget'; return baseclass.extend({ view: widget.view.extend({ + enableAutoRefresh: true, + /** * Pattern for picking application-specific entries from the log. * * @property {string} appPattern */ - appPattern : '^', + appPattern : '^', /** * Enable "tail" option for the logread (logread -l). @@ -19,19 +20,19 @@ return baseclass.extend({ * * @property {bool} loggerTail */ - loggerTail : false, + loggerTail : false, - logdRegexp : new RegExp(/^([^\s]{3}\s+[^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}\s+\d{4})\s+([a-z0-9]+)\.([a-z]+)\s+(.*)$/), + logdRegexp : new RegExp(/^([^\s]{3}\s+[^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}\s+\d{4})\s+([a-z0-9]+)\.([a-z]+)\s+(.*)$/), - syslog_ngRegexp: new RegExp(/^([^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2})\s+([^\s]+)\s+(.*)$/), + syslog_ngRegexp : new RegExp(/^([^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2})\s+([^\s]+)\s+(.*)$/), - entryRegexp : null, + entryRegexp : null, - isLoggerChecked: false, + loggerChecked : false, - entriesHandler : null, + entriesHandler : null, - logger : null, + logger : null, getLogHash() { return this.getLogData(1, true).then(data => { @@ -66,6 +67,18 @@ return baseclass.extend({ ]; }, + // unsupported log handler + unsupportedLogHandler(line, lineNum) { + return [ + lineNum, // # (Number) + null, // Timestamp (String) + null, // Host (String) + null, // Facility (String) + null, // Level (String) + this.htmlEntities(line) || ' ', // Message (String) + ]; + }, + checkLogread() { return Promise.all([ L.resolveDefault(fs.stat('/sbin/logread'), null), @@ -102,8 +115,7 @@ return baseclass.extend({ return []; }; - let unsupportedLog = false; - let strings = logdata.trim().split(/\n/); + let strings = logdata.trim().split(/\n/); if(!this.loggerTail && tail && tail > 0 && strings) { strings = strings.slice(-tail); @@ -111,45 +123,61 @@ return baseclass.extend({ this.totalLogLines = strings.length; - let entriesArray = strings.map((e, i) => { - if(!this.isLoggerChecked) { + let entriesArray = strings.map((e, i) => { + if(!this.loggerChecked) { if(this.logdRegexp.test(e)) { - this.entryRegexp = this.logdRegexp; - this.isFacilities = true; - this.isLevels = true; - this.logHosts = {}; - this.entriesHandler = this.logdHandler; + this.entryRegexp = this.logdRegexp; + this.logTimestampFlag = true; + this.logFacilitiesFlag = true; + this.logLevelsFlag = true; + this.logHostsFlag = false; + this.logHosts = {}; + this.entriesHandler = this.logdHandler; + this.logCols = [ + '#', + _('Timestamp'), + null, + _('Facility'), + _('Level'), + _('Message'), + ]; + this.loggerChecked = true; } else if(this.syslog_ngRegexp.test(e)) { - this.entryRegexp = this.syslog_ngRegexp; - this.isHosts = true; - this.logFacilities = {}; - this.logLevels = {}; - this.entriesHandler = this.syslog_ngHandler; + this.entryRegexp = this.syslog_ngRegexp; + this.logTimestampFlag = true; + this.logFacilitiesFlag = false; + this.logLevelsFlag = false; + this.logHostsFlag = true; + this.logFacilities = {}; + this.logLevels = {}; + this.entriesHandler = this.syslog_ngHandler; + this.logCols = [ + '#', + _('Timestamp'), + _('Host'), + null, + null, + _('Message'), + ]; + this.loggerChecked = true; } else { - unsupportedLog = true; - return; + return this.unsupportedLogHandler(e, i + 1); }; - this.isLoggerChecked = true; }; let strArray = e.match(this.entryRegexp); if(strArray) { return this.entriesHandler(strArray, i + 1); } else { - unsupportedLog = true; - return; + return this.unsupportedLogHandler(e, i + 1); }; }); - if(unsupportedLog) { - throw new Error(_('Unable to load log data:') + ' ' + _('Unsupported log format')); - } else { - if(this.logSortingValue === 'desc') { - entriesArray.reverse(); - }; - return entriesArray; + if(this.logSortingValue == 'desc') { + entriesArray.reverse(); }; + return entriesArray; }, }), }); diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-widget.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-widget.js index 5a8e6c5..3aab422 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-widget.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/log-widget.js @@ -46,38 +46,50 @@ return baseclass.extend({ if(e[4] in this.logLevels) { this.logLevelsStat[e[4]] = this.logLevelsStat[e[4]] + 1; }; - lines.push( - `${e[0]}` + - ((e[1]) ? `${e[1]}` : '') + - ((e[2]) ? `${e[2]}` : '') + - ((e[3]) ? `${e[3]}` : '') + - ((e[4]) ? `${e[4]}` : '') + - ((e[5]) ? `${e[5]}` : '') + - '' - ); + + let line = [ `` ]; + this.logCols.forEach((c, i) => { + if(c) { + let cellClass = ''; + switch(i) { + case 0: + case 3: + case 4: + cellClass = 'log-entry-text-nowrap'; + break; + case 1: + cellClass = 'log-entry-time-cell'; + break; + case 2: + cellClass = 'log-entry-host-cell'; + break; + case 5: + cellClass = 'log-entry-message-cell'; + break; + }; + line.push(`${e[i] || ' '}`); + }; + }); + line.push(''); + lines.push(line.join('')); }); lines = lines.join(''); - logTable.append( - E('tr', { 'class': 'tr table-titles' }, [ - E('th', { 'class': 'th left log-entry-text-nowrap' }, '#'), - (logdataArray[0][1]) ? - E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Timestamp')) : '', - (logdataArray[0][2]) ? - E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Host')) : '', - (logdataArray[0][3]) ? - E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Facility')) : '', - (logdataArray[0][4]) ? - E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Level')) : '', - (logdataArray[0][5]) ? - E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Message')) : '', - ]) - ); + + let logTableHeader = E('tr', { 'class': 'tr table-titles' }); + this.logCols.forEach(e => { + if(e) { + logTableHeader.append( + E('th', { 'class': 'th left log-entry-text-nowrap' }, e) + ); + }; + }); + logTable.append(logTableHeader); }; try { logTable.insertAdjacentHTML('beforeend', lines); } catch(err) { - if(err.name === 'SyntaxError') { + if(err.name == 'SyntaxError') { ui.addNotification(null, E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error'); }; 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 c899dd3..ad16f3c 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,10 +1,10 @@ 'use strict'; -'require view.ruantiblock.log-abstract as abc'; +'require view.ruantiblock.log-system as abc'; 'require view.ruantiblock.tools as tools'; return abc.view.extend({ - viewName : 'ruantiblock', - title : _('Ruantiblock') + ' - ' + _('Log'), - autoRefresh: false, - appPattern : tools.appName + ':', + viewName : 'ruantiblock', + title : _('Ruantiblock') + ' - ' + _('Log'), + enableAutoRefresh: false, + appPattern : tools.appName + ':', }); diff --git a/ruantiblock-mod-lua/Makefile b/ruantiblock-mod-lua/Makefile index ef2b6b9..9c0a465 100644 --- a/ruantiblock-mod-lua/Makefile +++ b/ruantiblock-mod-lua/Makefile @@ -1,11 +1,11 @@ # -# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) +# (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-lua -PKG_VERSION:=2.1.4 +PKG_VERSION:=2.1.5 PKG_RELEASE:=1 PKG_MAINTAINER:=gSpot diff --git a/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua b/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua index 9be06f9..72ee471 100755 --- a/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua +++ b/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua @@ -1,7 +1,7 @@ #!/usr/bin/env lua --[[ - (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) + (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) lua == 5.1 --]] diff --git a/ruantiblock-mod-py/Makefile b/ruantiblock-mod-py/Makefile index d482983..47aa4af 100644 --- a/ruantiblock-mod-py/Makefile +++ b/ruantiblock-mod-py/Makefile @@ -1,11 +1,11 @@ # -# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) +# (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-py -PKG_VERSION:=2.1.4 +PKG_VERSION:=2.1.5 PKG_RELEASE:=1 PKG_MAINTAINER:=gSpot diff --git a/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py b/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py index b7c1806..e9b0311 100755 --- a/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py +++ b/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ -(с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) +(с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) Python >= 3.6 """ diff --git a/ruantiblock/Makefile b/ruantiblock/Makefile index d6bf160..4f45c4f 100644 --- a/ruantiblock/Makefile +++ b/ruantiblock/Makefile @@ -1,12 +1,12 @@ # -# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) +# (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock -PKG_VERSION:=2.1.4 -PKG_RELEASE:=3 +PKG_VERSION:=2.1.5 +PKG_RELEASE:=1 PKG_MAINTAINER:=gSpot include $(INCLUDE_DIR)/package.mk diff --git a/ruantiblock/files/etc/hotplug.d/iface/40-ruantiblock b/ruantiblock/files/etc/hotplug.d/iface/40-ruantiblock index 28c431d..6ac1371 100755 --- a/ruantiblock/files/etc/hotplug.d/iface/40-ruantiblock +++ b/ruantiblock/files/etc/hotplug.d/iface/40-ruantiblock @@ -12,10 +12,10 @@ if [ "$ACTION" = "ifup" ]; then DEBUG=0 IF_VPN_CURRENT="" - ruab_route_status=`$RUAB_CMD raw-status` + ruab_route_status=$($RUAB_CMD raw-status) [ $ruab_route_status -eq 1 -o $ruab_route_status -eq 2 ] && exit 0 - UCI_CMD=`which uci` + UCI_CMD="$(which uci)" if [ $? -ne 0 ]; then echo " Error! UCI doesn't exists" >&2 exit 1 @@ -23,19 +23,19 @@ if [ "$ACTION" = "ifup" ]; then [ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE" - VPN_ROUTE_CHECK=`$UCI_CMD get ruantiblock.config.vpn_route_check` + VPN_ROUTE_CHECK=$($UCI_CMD get ruantiblock.config.vpn_route_check) [ "$VPN_ROUTE_CHECK" != "0" ] && exit 0 - PROXY_MODE=`$UCI_CMD get ruantiblock.config.proxy_mode` + PROXY_MODE=$($UCI_CMD get ruantiblock.config.proxy_mode) if [ "$PROXY_MODE" = "2" ]; then - IF_VPN_CURRENT=`$UCI_CMD get ruantiblock.config.if_vpn` + IF_VPN_CURRENT=$($UCI_CMD get ruantiblock.config.if_vpn) fi if [ "$DEVICE" != "$IF_VPN_CURRENT" ]; then . "$USER_INSTANCES_COMMON" - for inst in `GetUserInstances 2` + for inst in $(GetUserInstances 2) do IncludeUserInstanceVars "$inst" if [ "$DEVICE" = "$U_IF_VPN" ]; then diff --git a/ruantiblock/files/usr/bin/ruantiblock b/ruantiblock/files/usr/bin/ruantiblock index 1df9fb6..cf07871 100755 --- a/ruantiblock/files/usr/bin/ruantiblock +++ b/ruantiblock/files/usr/bin/ruantiblock @@ -3,13 +3,13 @@ ######################################################################## # # Ruantiblock -# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) +# (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # ######################################################################## export NAME="ruantiblock" export APP_EXEC="$0" -export APP_NAME="`basename $0`" +export APP_NAME="$(basename $0)" export LANG="en_US.UTF-8" export LANGUAGE="en" @@ -182,6 +182,18 @@ export BLLIST_ALT_NSLOOKUP=0 ### Альтернативный DNS-сервер export BLLIST_ALT_DNS_ADDR="8.8.8.8" +########################## Instances defaults ########################## + +INSTANCES_DEF_PROXY_MODE=$PROXY_MODE +INSTANCES_DEF_TOR_TRANS_PORT=$TOR_TRANS_PORT +INSTANCES_DEF_IF_VPN=$IF_VPN +INSTANCES_DEF_T_PROXY_TYPE=$T_PROXY_TYPE +INSTANCES_DEF_T_PROXY_PORT_TCP=$T_PROXY_PORT_TCP +INSTANCES_DEF_T_PROXY_PORT_UDP=$T_PROXY_PORT_UDP +INSTANCES_DEF_T_PROXY_ALLOW_UDP=$T_PROXY_ALLOW_UDP +INSTANCES_DEF_ENABLE_BLLIST_PROXY=$ENABLE_BLLIST_PROXY +INSTANCES_DEF_ENABLE_FPROXY=$ENABLE_FPROXY + ############################ Configuration ############################# ### External config @@ -207,24 +219,24 @@ export DNSMASQ_DATA_FILE="${DNSMASQ_CONFDIR}/02-${NAME}.dnsmasq" ### Utilities AWK_CMD="awk" -NFT_CMD=`which nft` +NFT_CMD="$(which nft)" if [ $? -ne 0 ]; then echo " Error! Nftables doesn't exists" >&2 exit 1 fi -LOGGER_CMD=`which logger` +LOGGER_CMD="$(which logger)" if [ $ENABLE_LOGGING = "1" -a $? -ne 0 ]; then echo " Logger doesn't exists" >&2 ENABLE_LOGGING=0 fi LOGGER_PARAMS="-t ${APP_NAME}" -WGET_CMD=`which wget` +WGET_CMD="$(which wget)" if [ $? -ne 0 ]; then echo " Error! Wget doesn't exists" >&2 exit 1 fi WGET_PARAMS="--no-check-certificate -q -O" -NSLOOKUP_CMD=`which nslookup` +NSLOOKUP_CMD="$(which nslookup)" if [ $? -ne 0 ]; then echo " Error! Nslookup doesn't exists" >&2 exit 1 @@ -261,8 +273,8 @@ export NFTSET_IP_TYPE="ipv4_addr" export NFTSET_DNSMASQ_TYPE="ipv4_addr" export NFTSET_CIDR_PATTERN="set %s {type ${NFTSET_CIDR_TYPE};size ${NFTSET_MAXELEM_CIDR};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;" export NFTSET_IP_PATTERN="set %s {type ${NFTSET_IP_TYPE};size ${NFTSET_MAXELEM_IP};policy ${NFTSET_POLICY_IP};flags dynamic;" -export NFTSET_CIDR_STRING_MAIN=`printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}"` -export NFTSET_IP_STRING_MAIN=`printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}"` +export NFTSET_CIDR_STRING_MAIN=$(printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}") +export NFTSET_IP_STRING_MAIN=$(printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}") export NFTSET_BYPASS_IP_STRING="set ${NFTSET_BYPASS_IP} {type ${NFTSET_BYPASS_IP_TYPE};size ${NFTSET_MAXELEM_BYPASS_IP};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;" export UPDATE_STATUS_FILE="${DATA_DIR}/update_status" export USER_ENTRIES_STATUS_FILE="${DATA_DIR}/user_entries_status" @@ -402,7 +414,7 @@ DownloadNativeBlacklist() { } RestartDnsmasq() { - eval `echo "$DNSMASQ_RESTART_CMD"` + eval $(echo "$DNSMASQ_RESTART_CMD") } FlushNftSets() { @@ -443,14 +455,14 @@ FormatNftSetElemsList() { AddBaseNftSets() { local _allowed_hosts _fproxy_private $NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } - _allowed_hosts=`FormatNftSetElemsList "$ALLOWED_HOSTS_LIST"` + _allowed_hosts=$(FormatNftSetElemsList "$ALLOWED_HOSTS_LIST") if [ -n "$_allowed_hosts" ]; then $NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_allowed_hosts" } fi $NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_IP" { type "$NFTSET_BYPASS_IP_TYPE"\; size $NFTSET_MAXELEM_BYPASS_IP\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_FQDN" { type "$NFTSET_BYPASS_FQDN_TYPE"\; size $NFTSET_MAXELEM_BYPASS_FQDN\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { type "$NFTSET_FPROXY_PRIVATE_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } - _fproxy_private=`FormatNftSetElemsList "$FPROXY_PRIVATE_NETS"` + _fproxy_private=$(FormatNftSetElemsList "$FPROXY_PRIVATE_NETS") if [ -n "$_fproxy_private" ]; then $NFT_CMD add element $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { "$_fproxy_private" } fi @@ -468,7 +480,7 @@ MakeInstanceNftSets() { $NFT_CMD add set $NFT_TABLE "${NFTSET_DNSMASQ}${_name}" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } $NFT_CMD add set $NFT_TABLE "${NFTSET_ONION}${_name}" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } $NFT_CMD add set $NFT_TABLE "${NFTSET_FPROXY}${_name}" { type "$NFTSET_FPROXY_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } - _fproxy_hosts=`FormatNftSetElemsList "$_fproxy_list"` + _fproxy_hosts=$(FormatNftSetElemsList "$_fproxy_list") if [ -n "$_fproxy_hosts" ]; then $NFT_CMD add element $NFT_TABLE "${NFTSET_FPROXY}${_name}" { "$_fproxy_hosts" } fi @@ -494,7 +506,7 @@ UpdateBllistProxySet() { _name=".${_name}" fi FlushNftSets "${NFTSET_BLLIST_PROXY}${_name}" - for _host in `echo "$_urls" | $AWK_CMD ' + for _host in $(echo "$_urls" | $AWK_CMD ' BEGIN { RS = " "; } @@ -511,15 +523,15 @@ UpdateBllistProxySet() { for(i in hosts_arr) { printf i " "; }; - }'` + }') do if printf "$_host" | $AWK_CMD '{exit ($0 ~ /^([0-9]{1,3}.){3}[0-9]{1,3}$/) ? 0 : 1}'; then _ip_string="${_ip_string}${_host} " else - _ip_string="${_ip_string}`$NSLOOKUP_CMD $_host 2> /dev/null | $AWK_CMD '/^Address: ([0-9]{1,3}.){3}[0-9]{1,3}$/ {printf $2" "}'`" + _ip_string="${_ip_string}$($NSLOOKUP_CMD $_host 2> /dev/null | $AWK_CMD '/^Address: ([0-9]{1,3}.){3}[0-9]{1,3}$/ {printf $2" "}')" fi done - _ip_string=`FormatNftSetElemsList "$_ip_string"` + _ip_string=$(FormatNftSetElemsList "$_ip_string") if [ $DEBUG -ge 1 ]; then echo " ruantiblock.UpdateBllistProxySet()._ip_string=${_ip_string}; _name=${_name}" >&2 @@ -570,7 +582,7 @@ AddUserInstancesNftRules() { _route_table_id=$_tproxy_route_table_id fi _pkts_mark=$(($_pkts_mark + 1)) - NftInstanceAdd "\"$U_NAME\"" $_pkts_mark $U_PROXY_MODE $U_TOR_TRANS_PORT $_route_table_id "\"$U_IF_VPN\"" $U_T_PROXY_TYPE $U_T_PROXY_PORT_TCP $U_T_PROXY_PORT_UDP $U_T_PROXY_ALLOW_UDP $U_ENABLE_ENTRIES_REMOTE_PROXY $U_ENABLE_FPROXY "\"$U_VPN_GW_IP\"" + NftInstanceAdd "\"$U_NAME\"" $_pkts_mark ${U_PROXY_MODE:=$INSTANCES_DEF_PROXY_MODE} ${U_TOR_TRANS_PORT:=$INSTANCES_DEF_TOR_TRANS_PORT} $_route_table_id "\"${U_IF_VPN:=$INSTANCES_DEF_IF_VPN}\"" ${U_T_PROXY_TYPE:=$INSTANCES_DEF_T_PROXY_TYPE} ${U_T_PROXY_PORT_TCP:=$INSTANCES_DEF_T_PROXY_PORT_TCP} ${U_T_PROXY_PORT_UDP:=$INSTANCES_DEF_T_PROXY_PORT_UDP} ${U_T_PROXY_ALLOW_UDP:=$INSTANCES_DEF_T_PROXY_ALLOW_UDP} ${U_ENABLE_ENTRIES_REMOTE_PROXY:=$INSTANCES_DEF_ENABLE_BLLIST_PROXY} ${U_ENABLE_FPROXY:=$INSTANCES_DEF_ENABLE_FPROXY} "\"$U_VPN_GW_IP\"" ClearUserInstanceVars _prio_offset=$(($_prio_offset - 1)) done @@ -603,7 +615,7 @@ AddNftRules() { NftAddBaseChains $_chain_prio_first $_chain_prio_local $_chain_prio_fproxy NftAddActionChains $_chain_prio_action AddUserInstancesNftRules - NftInstanceAdd "\" \"" $PKTS_MARK_START $PROXY_MODE $TOR_TRANS_PORT $_route_table_id "\"$IF_VPN\"" $T_PROXY_TYPE $T_PROXY_PORT_TCP $T_PROXY_PORT_UDP $T_PROXY_ALLOW_UDP $ENABLE_BLLIST_PROXY $ENABLE_FPROXY "\"$VPN_GW_IP\"" + NftInstanceAdd "\" \"" $PKTS_MARK_START ${PROXY_MODE:=$INSTANCES_DEF_PROXY_MODE} ${TOR_TRANS_PORT:=$INSTANCES_DEF_TOR_TRANS_PORT} $_route_table_id "\"${IF_VPN:=$INSTANCES_DEF_IF_VPN}\"" ${T_PROXY_TYPE:=$INSTANCES_DEF_T_PROXY_TYPE} ${T_PROXY_PORT_TCP:=$INSTANCES_DEF_T_PROXY_PORT_TCP} ${T_PROXY_PORT_UDP:=$INSTANCES_DEF_T_PROXY_PORT_UDP} ${T_PROXY_ALLOW_UDP:=$INSTANCES_DEF_T_PROXY_ALLOW_UDP} ${ENABLE_BLLIST_PROXY:=$INSTANCES_DEF_ENABLE_BLLIST_PROXY} ${ENABLE_FPROXY:=$INSTANCES_DEF_ENABLE_FPROXY} "\"$VPN_GW_IP\"" if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then NftAddLocalClientsRule fi @@ -864,7 +876,7 @@ AddUserEntries() { printf "server=/onion/%s\nnftset=/onion/%s#%s\n" "$U_ONION_DNS_ADDR" "$NFT_TABLE_DNSMASQ" "${NFTSET_ONION}.${U_NAME}" >> "$_dnsmasq_data_file_user_instances" fi if [ -f "$_instance_entries_file" ]; then - { cat "$_instance_entries_file"; printf "\n0\n"; } | ParseUserEntries "`printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}"`" "`printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}"`" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:local" "$U_ENTRIES_DNS" + { cat "$_instance_entries_file"; printf "\n0\n"; } | ParseUserEntries "$(printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}")" "$(printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}")" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:local" "$U_ENTRIES_DNS" fi if [ -n "$U_ENTRIES_REMOTE" ]; then for _url in $U_ENTRIES_REMOTE @@ -876,7 +888,7 @@ AddUserEntries() { if [ "$U_ENABLE_ENTRIES_REMOTE_PROXY" = "1" ]; then UpdateBllistProxySet "$U_NAME" "$_url" fi - { Download - "$_url"; printf "\n$?\n"; } | ParseUserEntries "`printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}"`" "`printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}"`" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:${_url}" "$U_ENTRIES_DNS" + { Download - "$_url"; printf "\n$?\n"; } | ParseUserEntries "$(printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}")" "$(printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}")" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:${_url}" "$U_ENTRIES_DNS" if [ $? -eq 0 ]; then _instance_return_code=0 break @@ -922,11 +934,11 @@ AddUserEntries() { if [ "$ENABLE_TMP_DOWNLOADS" != "1" ] || [ "$ENABLE_TMP_DOWNLOADS" = "1" -a $_return_code -eq 0 ]; then while read _str do - _update_string=`printf "$_str" | $AWK_CMD '{ + _update_string=$(printf "$_str" | $AWK_CMD '{ if(NF == 4) { printf "User entries (%s): CIDR: %s, IP: %s, FQDN: %s", $4, $1, $2, $3; }; - }'` + }') if [ -n "$_update_string" ]; then ### STDOUT echo " ${_update_string}" @@ -983,14 +995,14 @@ GetMainInstanceEntries() { FlushNftSets "$NFTSET_BLLIST_PROXY" fi if [ $_return_code -eq 0 ]; then - _update_string=`$AWK_CMD '{ + _update_string=$($AWK_CMD '{ printf "Received entries: %s\n", (NF < 3) ? "No data" : "CIDR: "$1", IP: "$2", FQDN: "$3; exit; - }' "$UPDATE_STATUS_FILE"` + }' "$UPDATE_STATUS_FILE") ### STDOUT echo " ${_update_string}" MakeLogRecord "notice" "${_update_string}" - printf " `date +%d.%m.%Y-%H:%M`\n" >> "$UPDATE_STATUS_FILE" + printf " $(date +%d.%m.%Y-%H:%M)\n" >> "$UPDATE_STATUS_FILE" fi elif [ -z "$BLLIST_PRESET" -a -z "$BLLIST_MODULE" ]; then ClearDataFiles main_instance @@ -1199,20 +1211,20 @@ Reload() { Status() { local _update_status _user_entries_status _vpn_error if [ -f "$UPDATE_STATUS_FILE" ]; then - _update_status=`$AWK_CMD '{ + _update_status=$($AWK_CMD '{ update_string=(NF < 4) ? "No data" : $4" (CIDR: "$1" | IP: "$2" | FQDN: "$3")"; printf "Last blacklist update: %s", update_string; - }' "$UPDATE_STATUS_FILE"` + }' "$UPDATE_STATUS_FILE") else _update_status="Last blacklist update: No data" fi if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then - _user_entries_status=`$AWK_CMD '{ + _user_entries_status=$($AWK_CMD '{ if(NF == 4) { printf " User entries (%s): CIDR: %s | IP: %s | FQDN: %s\n", $4, $1, $2, $3; }; - }' "$USER_ENTRIES_STATUS_FILE"` + }' "$USER_ENTRIES_STATUS_FILE") fi if ! GetVpnRouteStatus; then diff --git a/ruantiblock/files/usr/libexec/ruantiblock/ruab_route_check b/ruantiblock/files/usr/libexec/ruantiblock/ruab_route_check index 76ae813..fbccf4b 100755 --- a/ruantiblock/files/usr/libexec/ruantiblock/ruab_route_check +++ b/ruantiblock/files/usr/libexec/ruantiblock/ruab_route_check @@ -1,6 +1,6 @@ #!/bin/sh -PID_FILE="/var/run/`basename $0`.pid" +PID_FILE="/var/run/$(basename $0).pid" APP_EXEC="/usr/bin/ruantiblock" . "$USER_INSTANCES_COMMON" @@ -9,7 +9,7 @@ VPN_IFACES_STATUS=1 CheckIfaceStatus() { local _iface="$1" _ret_val=0 - if [ -z "`$IP_CMD link show dev $_iface up 2> /dev/null`" ]; then + if [ -z "$($IP_CMD link show dev $_iface up 2> /dev/null)" ]; then _ret_val=1 if [ $DEBUG -ge 1 ]; then @@ -23,7 +23,7 @@ CheckIfaceStatus() { VpnRouteInstanceStatus() { local _vpn_route_table_id=$1 - [ -n "`$IP_CMD route show table $_vpn_route_table_id 2> /dev/null`" ] && return 0 + [ -n "$($IP_CMD route show table $_vpn_route_table_id 2> /dev/null)" ] && return 0 return 1 } @@ -83,7 +83,7 @@ Start() { } Stop() { - kill -s SIGKILL `cat "$PID_FILE"` 2> /dev/null + kill -s SIGKILL $(cat "$PID_FILE") 2> /dev/null rm -f "$PID_FILE" } @@ -104,7 +104,7 @@ case "$1" in fi ;; *) - echo "Usage: `basename $0` start|stop" + echo "Usage: $(basename $0) start|stop" exit 1 ;; esac diff --git a/ruantiblock/files/usr/share/ruantiblock/config_script b/ruantiblock/files/usr/share/ruantiblock/config_script index 1290863..28fd02d 100644 --- a/ruantiblock/files/usr/share/ruantiblock/config_script +++ b/ruantiblock/files/usr/share/ruantiblock/config_script @@ -1,13 +1,14 @@ + UCI_SECTION="ruantiblock.config" UCI_VARS="dnsmasq_confdir proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns enable_fproxy fproxy_list enable_bllist_proxy if_vpn vpn_gw_ip vpn_route_check tor_trans_port onion_dns_addr t_proxy_type t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup enable_tmp_downloads" -UCI_CMD=`which uci` +UCI_CMD="$(which uci)" if [ $? -ne 0 ]; then echo " Error! UCI doesn't exists" >&2 exit 1 fi AWK_CMD="awk" -eval `$UCI_CMD show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' +eval $($UCI_CMD show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' BEGIN { split(UCI_VARS, split_array, " "); for(i in split_array) @@ -26,7 +27,7 @@ eval `$UCI_CMD show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' for(i in vars_array) print toupper(i) "=\"""\""; }; - }'` + }') . /lib/functions/network.sh network_get_subnet subnet_lan "lan" diff --git a/ruantiblock/files/usr/share/ruantiblock/config_script_user_instances b/ruantiblock/files/usr/share/ruantiblock/config_script_user_instances index 6e92d2f..02e5d47 100644 --- a/ruantiblock/files/usr/share/ruantiblock/config_script_user_instances +++ b/ruantiblock/files/usr/share/ruantiblock/config_script_user_instances @@ -1,5 +1,6 @@ + UCI_VARS="u_enabled u_proxy_mode u_tor_trans_port u_onion_dns_addr u_if_vpn u_vpn_gw_ip u_t_proxy_type u_t_proxy_port_tcp u_t_proxy_port_udp u_t_proxy_allow_udp u_entries_dns u_entries_remote u_enable_entries_remote_proxy u_enable_fproxy u_fproxy_list" -UCI_CMD=`which uci` +UCI_CMD="$(which uci)" if [ $? -ne 0 ]; then echo " Error! UCI doesn't exists" >&2 exit 1 @@ -26,7 +27,7 @@ IncludeUserInstanceVars() { local _inst="$1" local _uci_section="${NAME}.${_inst}" U_NAME="$_inst" - eval `$UCI_CMD show "$_uci_section" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' + eval $($UCI_CMD show "$_uci_section" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' BEGIN { split(UCI_VARS, split_array, " "); for(i in split_array) @@ -45,7 +46,7 @@ IncludeUserInstanceVars() { for(i in vars_array) print toupper(i) "=\"""\""; }; - }'` + }') if [ $DEBUG -ge 2 ]; then echo " user_instances_config_script.IncludeUserInstanceVars: _inst=${_inst} U_NAME=${U_NAME} U_PROXY_MODE=${U_PROXY_MODE}" >&2 diff --git a/ruantiblock/files/usr/share/ruantiblock/info_output b/ruantiblock/files/usr/share/ruantiblock/info_output index f673c98..13e26d9 100644 --- a/ruantiblock/files/usr/share/ruantiblock/info_output +++ b/ruantiblock/files/usr/share/ruantiblock/info_output @@ -1,18 +1,18 @@ Info() { local _update_status _user_entries_status _inst if [ -f "$UPDATE_STATUS_FILE" ]; then - _update_status=`$AWK_CMD '{ + _update_status=$($AWK_CMD '{ if(NF < 4) { printf "{\"status\":false}"; } else { printf "{\"status\":true,\"date\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\"}"; }; - }' "$UPDATE_STATUS_FILE"` + }' "$UPDATE_STATUS_FILE") else _update_status="{\"status\":false}" fi if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then - _user_entries_status=`$AWK_CMD ' + _user_entries_status=$($AWK_CMD ' BEGIN { items = 0; printf "["; @@ -29,7 +29,7 @@ Info() { } END { printf "]"; - }' "$USER_ENTRIES_STATUS_FILE"` + }' "$USER_ENTRIES_STATUS_FILE") else _user_entries_status="[]" fi diff --git a/ruantiblock/files/usr/share/ruantiblock/nft_functions b/ruantiblock/files/usr/share/ruantiblock/nft_functions index edabd2f..dbf806f 100644 --- a/ruantiblock/files/usr/share/ruantiblock/nft_functions +++ b/ruantiblock/files/usr/share/ruantiblock/nft_functions @@ -56,7 +56,7 @@ NftRouteAdd() { if [ -n "$_vpn_gw_ip" ]; then _vpn_ip="$_vpn_gw_ip" else - _vpn_ip=`$IP_CMD addr list dev "$_if_vpn" 2> /dev/null | $AWK_CMD '/inet/{f=($3 == "peer") ? 4 : 2; sub("/[0-9]{1,2}$", "", $f); print $f; exit}'` + _vpn_ip=$($IP_CMD addr list dev "$_if_vpn" 2> /dev/null | $AWK_CMD '/inet/{f=($3 == "peer") ? 4 : 2; sub("/[0-9]{1,2}$", "", $f); print $f; exit}') fi if [ -n "$_vpn_ip" -a "$_type" = "vpn" ]; then echo 0 > "/proc/sys/net/ipv4/conf/${_if_vpn}/rp_filter" @@ -80,7 +80,7 @@ NftRouteAdd() { NftRouteStatus() { local _route_table_id=$1 - [ -n "`$IP_CMD route show table "$_route_table_id" 2> /dev/null`" ] && return 0 + [ -n "$($IP_CMD route show table "$_route_table_id" 2> /dev/null)" ] && return 0 return 1 } @@ -90,9 +90,7 @@ NftAddBaseChains() { $NFT_CMD add chain $NFT_TABLE "$NFT_BLLIST_CHAIN" $NFT_CMD add chain $NFT_TABLE "$NFT_FPROXY_CHAIN" { type filter hook prerouting priority ${_chain_prio_fproxy}\; policy accept\; } $NFT_CMD add chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" { type filter hook prerouting priority ${_chain_prio_first}\; policy accept\; } - NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_CHAIN" meta iif lo return NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_CHAIN" ip daddr "@${NFTSET_FPROXY_PRIVATE}" return - NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" meta iif lo return NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" "$NFT_ALLOWED_HOSTS_PATTERN" if [ "$BYPASS_MODE" = "1" ]; then for _set in "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN" diff --git a/ruantiblock/files/usr/share/ruantiblock/user_instances_common b/ruantiblock/files/usr/share/ruantiblock/user_instances_common index 8882386..04e45cb 100644 --- a/ruantiblock/files/usr/share/ruantiblock/user_instances_common +++ b/ruantiblock/files/usr/share/ruantiblock/user_instances_common @@ -25,7 +25,7 @@ ListUserInstances() { GetUserInstances() { local _type="$1" _fnames="$2" _i=0 _inst _instances="" - for _inst in `ListUserInstances` + for _inst in $(ListUserInstances) do IncludeUserInstanceVars "$_inst" if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then @@ -45,7 +45,7 @@ GetUserInstances() { SetUserInstancesItems() { local _i=0 _inst _instances_all="" _instances_all_fnames="" _instances_vpn="" _instances_vpn_fnames="" _instances_cfg="" _instances_cfg_fnames="" - for _inst in `ListUserInstances` + for _inst in $(ListUserInstances) do IncludeUserInstanceVars "$_inst" if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then