Compare commits

..

15 Commits

Author SHA1 Message Date
remittor
2500109837 Bump version to v0.8.20260118 2026-01-18 13:35:06 +03:00
remittor
05b84183d9 luci: updater: Using 3 buttons and fix execAndRead 2026-01-18 13:34:55 +03:00
remittor
2d32f04071 luci: Fix error "XHR request timed out" into execAndRead 2026-01-18 10:01:27 +03:00
remittor
bf418db17e luci: Fix file permissions for saved configs 2026-01-17 17:36:54 +03:00
remittor
c574e04a2b luci: NFQWS2_OPT: Block enter text with quotes 2026-01-17 15:52:46 +03:00
remittor
1f0d674185 luci: Using dict for arguments of function 2026-01-17 15:52:10 +03:00
remittor
27dab23ed2 Bump version to v0.8.20260117 2026-01-17 11:02:28 +03:00
remittor
5a6c607fee makefile: Cleanup conffiles and install sections 2026-01-16 20:24:27 +03:00
remittor
0309b4b94c updater: Add uninstall oldest mdig and ip2net packages 2026-01-16 20:08:21 +03:00
remittor
13b6e4611a ipset: Update zapret-hosts-user-exclude.txt 2026-01-16 20:01:28 +03:00
remittor
15a6f9e5ae settings: Add new options on "Reset settings" dialog 2026-01-16 19:59:40 +03:00
remittor
4aca2043c1 diag: dwc: Add support resolve ip via specific dns and add recommendations 2026-01-16 19:53:07 +03:00
remittor
84f297492a luci: Fix save very long textareas to file 2026-01-16 11:33:09 +03:00
remittor
685afc1a69 comfunc: Fix recreating crontab log cleaning task on restart
PR: ad6b23f4aa
2026-01-13 21:42:04 +03:00
remittor
a84174e51d luci: Fix show NFQWS2_OPT 2026-01-13 21:36:30 +03:00
14 changed files with 635 additions and 434 deletions

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-zapret2 PKG_NAME:=luci-app-zapret2
PKG_VERSION:=0.8.20260113 PKG_VERSION:=0.8.20260118
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_LICENSE:=MIT PKG_LICENSE:=MIT
PKG_MAINTAINER:=remittor <https://github.com/remittor> PKG_MAINTAINER:=remittor <https://github.com/remittor>

View File

@@ -30,6 +30,12 @@ return baseclass.extend({
this.appendLog('Original sources: https://github.com/hyperion-cs/dpi-checkers'); this.appendLog('Original sources: https://github.com/hyperion-cs/dpi-checkers');
this.appendLog('WEB-version: https://hyperion-cs.github.io/dpi-checkers/ru/tcp-16-20/'); this.appendLog('WEB-version: https://hyperion-cs.github.io/dpi-checkers/ru/tcp-16-20/');
let cmd = [ fn_dwc_sh ]; let cmd = [ fn_dwc_sh ];
let resolve_dns = document.getElementById('cfg_resolve_dns');
let dns_ip = resolve_dns.options[resolve_dns.selectedIndex].text;
if (dns_ip && dns_ip != 'default') {
cmd.push(...[ '-d', dns_ip.trim() ]);
}
cmd.push('-R'); // show recommendations
let log = '/tmp/'+tools.appName+'_dwc.log'; let log = '/tmp/'+tools.appName+'_dwc.log';
let callback = this.execAndReadCallback; let callback = this.execAndReadCallback;
let wnd = this; let wnd = this;
@@ -60,6 +66,32 @@ return baseclass.extend({
{ {
this.pkg_arch = pkg_arch; this.pkg_arch = pkg_arch;
let DNS_LIST = [
'8.8.8.8', // Google
'8.8.4.4', // Google
'1.1.1.1', // Cloudflare
'1.0.0.1', // Cloudflare
'9.9.9.9', // Quad9
'149.112.112.112', // Quad9
'208.67.222.222', // OpenDNS
'208.67.220.220', // OpenDNS
'8.26.56.26', // Comodo
'8.20.247.20', // Comodo
'64.6.64.6', // Verisign
'64.6.65.6', // Verisign
];
let dns_list = [ ];
dns_list.push( E('option', { value: 'dns_default' }, [ 'default' ] ) );
for (let id = 0; id < DNS_LIST.length; id++) {
let dns_ipaddr = '' + DNS_LIST[id];
let val = 'dns_' + dns_ipaddr.replace(/\./g, "_");
dns_list.push( E('option', { value: val }, [ dns_ipaddr ] ));
}
let resolve_dns = E('label', [
_('Resolve IP-Addr via') + ': ',
E('select', { id: 'cfg_resolve_dns' }, dns_list)
]);
this.logArea = E('textarea', { this.logArea = E('textarea', {
'id': 'widget.modal_content', 'id': 'widget.modal_content',
'readonly': true, 'readonly': true,
@@ -84,6 +116,8 @@ return baseclass.extend({
ui.showModal(_('Diagnostics'), [ ui.showModal(_('Diagnostics'), [
E('div', { 'class': 'cbi-section' }, [ E('div', { 'class': 'cbi-section' }, [
resolve_dns,
E('br'), E('br'),
this.logArea, this.logArea,
]), ]),
E('div', { 'class': 'right' }, [ E('div', { 'class': 'right' }, [

View File

@@ -244,8 +244,18 @@ return view.extend({
' ', _('Set AutoHostList mode') ' ', _('Set AutoHostList mode')
]); ]);
let erase_autohostlist = E('label', [
E('input', { type: 'checkbox', id: 'cfg_erase_autohostlist' }),
' ', _('Erase AutoHostList (ipset)')
]);
let enable_custom_d = E('label', [
E('input', { type: 'checkbox', id: 'cfg_enable_custom_d' }),
' ', _('Enable use custom.d scripts')
]);
let strat_list = [ ]; let strat_list = [ ];
strat_list.push( E('option', { value: 'strat__skip__' }, [ '-' ] ) ); strat_list.push( E('option', { value: 'strat__skip__' }, [ 'not change' ] ) );
for (let id = 0; id < this.nfqws_strat_list.length; id++) { for (let id = 0; id < this.nfqws_strat_list.length; id++) {
let strat = '' + this.nfqws_strat_list[id]; let strat = '' + this.nfqws_strat_list[id];
strat_list.push( E('option', { value: 'strat_' + id }, [ strat ] ) ); strat_list.push( E('option', { value: 'strat_' + id }, [ strat ] ) );
@@ -276,10 +286,19 @@ return view.extend({
if (document.getElementById('cfg_autohostlist').checked) { if (document.getElementById('cfg_autohostlist').checked) {
opt_flags += '(set_mode_autohostlist)'; opt_flags += '(set_mode_autohostlist)';
}; };
if (document.getElementById('cfg_erase_autohostlist').checked) {
opt_flags += '(erase_autohostlist)';
};
if (document.getElementById('cfg_enable_custom_d').checked) {
opt_flags += '(enable_custom_d)';
};
//console.log('RESET: opt_flags = ' + opt_flags); //console.log('RESET: opt_flags = ' + opt_flags);
let sel_strat = document.getElementById('cfg_nfqws_strat'); let sel_strat = document.getElementById('cfg_nfqws_strat');
let opt_strat = sel_strat.options[sel_strat.selectedIndex].text; let opt_strat = sel_strat.options[sel_strat.selectedIndex].text;
//console.log('RESET: strat = ' + opt_strat); //console.log('RESET: strat = ' + opt_strat);
if (opt_strat == 'not change') {
opt_strat = '-';
}
opt_flags += '(sync)'; opt_flags += '(sync)';
let args = [ opt_flags, opt_strat ]; let args = [ opt_flags, opt_strat ];
return this.serviceActionEx('reset', resetcfg_btn, args, true); return this.serviceActionEx('reset', resetcfg_btn, args, true);
@@ -293,6 +312,10 @@ return view.extend({
E('br'), E('br'), E('br'), E('br'),
set_autohostlist, set_autohostlist,
E('br'), E('br'), E('br'), E('br'),
erase_autohostlist,
E('br'), E('br'),
enable_custom_d,
E('br'), E('br'),
nfqws_strat, nfqws_strat,
E('br'), E('br') E('br'), E('br')
]), ]),

View File

@@ -7,6 +7,11 @@
'require view'; 'require view';
'require view.zapret2.tools as tools'; 'require view.zapret2.tools as tools';
document.head.appendChild(E('link', {
rel: 'stylesheet',
href: L.resource('view/zapret2/styles.css')
}));
return view.extend({ return view.extend({
parsers: { }, parsers: { },
@@ -128,8 +133,10 @@ return view.extend({
let btn = sec.taboption(tabname, form.Button, '_' + param + '_btn', locname); let btn = sec.taboption(tabname, form.Button, '_' + param + '_btn', locname);
btn.inputtitle = _('Edit'); btn.inputtitle = _('Edit');
btn.inputstyle = 'edit btn'; btn.inputstyle = 'edit btn';
let val = sec.taboption(tabname, form.DummyValue, '_' + param); let val = sec.taboption(tabname, form.TextValue, '_' + param);
val.rawhtml = multiline ? true : false; val.readonly = true;
val.rows = rows + 5;
val.wrap = false;
val.cfgvalue = function(section_id) { val.cfgvalue = function(section_id) {
let value = uci.get(tools.appName, section_id, param); let value = uci.get(tools.appName, section_id, param);
if (value == null) { if (value == null) {
@@ -141,21 +148,23 @@ return view.extend({
value = value.replace(/\n --/g, "\n--"); value = value.replace(/\n --/g, "\n--");
value = value.replace(/ --/g, "\n--"); value = value.replace(/ --/g, "\n--");
} }
if (val.rawhtml) {
value = value.replace(/</g, '˂');
value = value.replace(/>/g, '˃');
value = value.replace(/\n/g, '<br/>');
}
return value; return value;
}; };
val.validate = function(section_id, value) { val.validate = function(section_id, value) {
return (value) ? value.trim() : ""; return true;
}; };
let desc = locname; let desc = locname;
if (multiline == 2) { if (multiline == 2) {
desc += '<br/>' + _('Example') + ': <a target=_blank href=%s>%s</a>'.format(tools.nfqws_opt_url); desc += '<br/>' + _('Example') + ': <a target=_blank href=%s>%s</a>'.format(tools.nfqws_opt_url);
} }
btn.onclick = () => new tools.longstrEditDialog('config', param, param, desc, rows, multiline).show(); btn.onclick = () => new tools.longstrEditDialog({
cfgsec: 'config',
cfgparam: param,
title: param,
desc: desc,
rows: rows,
multiline: multiline,
}).show();
}; };
if (tools.appName == 'zapret2') { if (tools.appName == 'zapret2') {
@@ -311,13 +320,12 @@ return view.extend({
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.autoHostListFN; o.description = tools.autoHostListFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.autoHostListFN, file: tools.autoHostListFN,
_('Auto host list'), title: _('Auto host list'),
'', desc: '',
'', rows: 15,
15 }).show();
).show();
o = s.taboption(tabname, form.Flag, 'AUTOHOSTLIST_DEBUGLOG', _('DEBUGLOG')); o = s.taboption(tabname, form.Flag, 'AUTOHOSTLIST_DEBUGLOG', _('DEBUGLOG'));
o.rmempty = false; o.rmempty = false;
@@ -327,13 +335,12 @@ return view.extend({
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.autoHostListDbgFN; o.description = tools.autoHostListDbgFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.autoHostListDbgFN, file: tools.autoHostListDbgFN,
_('Auto host debug list'), title: _('Auto host debug list'),
'', desc: '',
'', rows: 15,
15 }).show();
).show();
/* HostList settings */ /* HostList settings */
@@ -344,37 +351,37 @@ return view.extend({
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.hostsGoogleFN; o.description = tools.hostsGoogleFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.hostsGoogleFN, file: tools.hostsGoogleFN,
_('Google hostname entries'), title: _('Google hostname entries'),
_('One hostname per line.<br />Examples:'), desc: _('One hostname per line.<br />Examples:'),
'<code>youtube.com<br />googlevideo.com</code>', aux: '<code>youtube.com<br />googlevideo.com</code>',
15 rows: 15,
).show(); }).show();
o = s.taboption(tabname, form.Button, '_user_entries_btn', _('User hostname entries <HOSTLIST>')); o = s.taboption(tabname, form.Button, '_user_entries_btn', _('User hostname entries <HOSTLIST>'));
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.hostsUserFN; o.description = tools.hostsUserFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.hostsUserFN, file: tools.hostsUserFN,
_('User entries'), title: _('User entries'),
_('One hostname per line.<br />Examples:'), desc: _('One hostname per line.<br />Examples:'),
'<code>domain.net<br />sub.domain.com<br />facebook.com</code>', aux: '<code>domain.net<br />sub.domain.com<br />facebook.com</code>',
15 rows: 15,
).show(); }).show();
o = s.taboption(tabname, form.Button, '_user_excluded_entries_btn', _('User excluded hostname entries')); o = s.taboption(tabname, form.Button, '_user_excluded_entries_btn', _('User excluded hostname entries'));
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.hostsUserExcludeFN; o.description = tools.hostsUserExcludeFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.hostsUserExcludeFN, file: tools.hostsUserExcludeFN,
_('User excluded entries'), title: _('User excluded entries'),
_('One hostname per line.<br />Examples:'), desc: _('One hostname per line.<br />Examples:'),
'<code>domain.net<br />sub.domain.com<br />gosuslugi.ru</code>', aux: '<code>domain.net<br />sub.domain.com<br />gosuslugi.ru</code>',
15 rows: 15,
).show(); }).show();
add_delim(s); add_delim(s);
@@ -382,37 +389,37 @@ return view.extend({
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.iplstExcludeFN; o.description = tools.iplstExcludeFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.iplstExcludeFN, file: tools.iplstExcludeFN,
_('Excluded IP filter'), title: _('Excluded IP filter'),
_('Patterns can be strings or regular expressions. Each pattern in a separate line<br />Examples:'), desc: _('Patterns can be strings or regular expressions. Each pattern in a separate line<br />Examples:'),
'<code>128.199.0.0/16<br />34.217.90.52<br />162.13.190.77</code>', aux: '<code>128.199.0.0/16<br />34.217.90.52<br />162.13.190.77</code>',
15 rows: 15,
).show(); }).show();
o = s.taboption(tabname, form.Button, '_user_ip_filter_btn', _('User IP entries')); o = s.taboption(tabname, form.Button, '_user_ip_filter_btn', _('User IP entries'));
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.iplstUserFN; o.description = tools.iplstUserFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.iplstUserFN, file: tools.iplstUserFN,
_('User IP filter'), title: _('User IP filter'),
_('Patterns can be strings or regular expressions. Each pattern in a separate line<br />Examples:'), desc: _('Patterns can be strings or regular expressions. Each pattern in a separate line<br />Examples:'),
'<code>128.199.0.0/16<br />34.217.90.52<br />162.13.190.77</code>', aux: '<code>128.199.0.0/16<br />34.217.90.52<br />162.13.190.77</code>',
15 rows: 15,
).show(); }).show();
o = s.taboption(tabname, form.Button, '_user_excluded_ip_filter_btn', _('User excluded IP entries')); o = s.taboption(tabname, form.Button, '_user_excluded_ip_filter_btn', _('User excluded IP entries'));
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = tools.iplstUserExcludeFN; o.description = tools.iplstUserExcludeFN;
o.onclick = () => new tools.fileEditDialog( o.onclick = () => new tools.fileEditDialog({
tools.iplstUserExcludeFN, file: tools.iplstUserExcludeFN,
_('User excluded IP filter'), title: _('User excluded IP filter'),
_('Patterns can be strings or regular expressions. Each pattern in a separate line<br />Examples:'), desc: _('Patterns can be strings or regular expressions. Each pattern in a separate line<br />Examples:'),
'<code>128.199.0.0/16<br />34.217.90.52<br />162.13.190.77</code>', aux: '<code>128.199.0.0/16<br />34.217.90.52<br />162.13.190.77</code>',
15 rows: 15,
).show(); }).show();
add_delim(s); add_delim(s);
@@ -423,7 +430,7 @@ return view.extend({
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
o.description = fn; o.description = fn;
o.onclick = () => new tools.fileEditDialog(fn, name, '', '', 15).show(); o.onclick = () => new tools.fileEditDialog({ file: fn, title: name, rows: 15}).show();
} }
/* custom.d files */ /* custom.d files */
@@ -465,7 +472,7 @@ return view.extend({
desc += '<a target=_blank href=' + url + '>' + filename + '</a>'; desc += '<a target=_blank href=' + url + '>' + filename + '</a>';
} }
} }
o.onclick = () => new tools.fileEditDialog(fn, name, desc, '', 15).show(); o.onclick = () => new tools.fileEditDialog({ file: fn, title: name, desc: desc, rows: 15}).show();
} }
let map_promise = m.render(); let map_promise = m.render();

View File

@@ -0,0 +1,6 @@
textarea, .cbi-value textarea
{
white-space: pre;
overflow-x: auto;
font-family: monospace;
}

View File

@@ -320,14 +320,18 @@ return baseclass.extend({
}, },
fileEditDialog: baseclass.extend({ fileEditDialog: baseclass.extend({
__init__: function(file, title, desc, aux = null, rows = 10, callback, file_exists = false) { __init__: function(opts = {})
this.file = file; {
this.title = title; Object.assign(this, {
this.desc = desc; file: '',
this.aux = aux; title: '',
this.rows = rows, desc: '',
this.callback = callback; aux: '',
this.file_exists = file_exists; rows: 10,
callback: null,
file_exists: false,
setperm: 644,
}, opts);
}, },
load: function() { load: function() {
@@ -370,11 +374,52 @@ return baseclass.extend({
]); ]);
}, },
handleSaveAdv: function(ev) { writeAdv: async function(fileName, data, chunkSize = 8000)
let txt = document.getElementById('widget.modal_content'); {
let value = txt.value.trim().replace(/\r\n/g, '\n') + '\n'; let tmpFile = fileName + '.tmp';
try {
for (let wsize = 0; wsize <= data.length; wsize += chunkSize) {
let chunk = data.slice(wsize, wsize + chunkSize);
if (wsize > 0 && chunk.length == 0) {
break; // EOF
}
chunk = chunk.replace(/'/g, `'\"'\"'`);
let teeArg = (wsize === 0) ? '' : '-a';
let cmd = `printf %s '${chunk}' | tee ${teeArg} '${tmpFile}'`;
let res = await fs.exec('/bin/busybox', [ 'sh', '-c', cmd ]);
if (res.code !== 0) {
throw new Error('tee failed, rc = ' + res.code);
}
}
if (this.setperm) {
let res = await fs.exec('/bin/busybox', [ 'chmod', '' + this.setperm, tmpFile ]);
if (res.code != 0) {
throw new Error('chmod failed, rc = ' + res.code);
}
}
let res = await fs.exec('/bin/busybox', [ 'mv', '-f', tmpFile, fileName ]);
if (res.code != 0) {
throw new Error('mv failed, rc = ' + res.code);
}
} catch(e) {
try {
await fs.exec('/bin/busybox', [ 'rm', '-f', tmpFile ]);
} catch(e2) {
// nothing
}
throw e;
}
return fs.stat(fileName);
},
return fs.write(this.file, value).then(async rc => { handleSaveAdv: async function(ev)
{
let txt = document.getElementById('widget.modal_content');
let value = txt.value.trim().replace(/\r\n/g, '\n');
if (value.length > 0) {
value += '\n';
}
return this.writeAdv(this.file, value).then(async rc => {
txt.value = value; txt.value = value;
ui.addNotification(null, E('p', _('Contents have been saved.')), 'info'); ui.addNotification(null, E('p', _('Contents have been saved.')), 'info');
if (this.callback) { if (this.callback) {
@@ -420,13 +465,16 @@ return baseclass.extend({
}), }),
longstrEditDialog: baseclass.extend({ longstrEditDialog: baseclass.extend({
__init__: function(cfgsec, cfgparam, title, desc, rows = 10, multiline = false) { __init__: function(opts = {})
this.cfgsec = cfgsec; {
this.cfgparam = cfgparam; Object.assign(this, {
this.title = title; cfgsec: '',
this.desc = desc; cfgparam: '',
this.rows = rows; title: '',
this.multiline = multiline; desc: '',
rows: 10,
multiline: false // may be 2
}, opts);
env_tools.load_env(this); env_tools.load_env(this);
}, },
@@ -490,6 +538,10 @@ return baseclass.extend({
if (value != "" && value != "\t") { if (value != "" && value != "\t") {
value = '\n' + value + '\n'; value = '\n' + value + '\n';
if (this.multiline == 2) { if (this.multiline == 2) {
if (value.includes("'") || value.includes('"')) {
alert(_('Unable to save the contents') + ':\n' + _('text cannot contain quotes!'));
return false;
}
value = value.replace(/"/g, ''); value = value.replace(/"/g, '');
value = value.replace(/'/g, ''); value = value.replace(/'/g, '');
} }
@@ -506,24 +558,10 @@ return baseclass.extend({
value = value.replace(/˂/g, '<'); value = value.replace(/˂/g, '<');
value = value.replace(/˃/g, '>'); value = value.replace(/˃/g, '>');
try { try {
let elem = document.getElementById("cbi-" + this.appName + "-" + this.cfgsec + "-_" + this.cfgparam); let elem = document.getElementById("widget.cbid." + this.appName + ".config._" + this.cfgparam);
if (elem) {
if (elem.querySelector('div')) {
elem = elem.querySelector('div');
} else {
elem = elem.querySelector('output');
}
}
if (elem) { if (elem) {
let val = value.trim(); let val = value.trim();
if (this.multiline) { elem.textContent = val;
val = val.replace(/</g, '˂');
val = val.replace(/>/g, '˃');
val = val.replace(/\n/g, '<br/>');
elem.innerHTML = val;
} else {
elem.textContent = val;
}
} }
} catch(e) { } catch(e) {
console.error('ERROR: cannot found elem for ' + this.cfgsec + '.' + this.cfgparam); console.error('ERROR: cannot found elem for ' + this.cfgsec + '.' + this.cfgparam);
@@ -601,54 +639,62 @@ return baseclass.extend({
} }
let lastLen = 0; let lastLen = 0;
let retCode = -1; let retCode = -1;
let timerBusy = false; return await new Promise(async (resolve, reject) => {
let timer = setInterval(async () => { async function poll()
if (timerBusy) {
return; // skip iteration try {
timerBusy = true; let res = await fs.exec('/bin/cat', [ logFile ], null, rpc_opt);
try { if (res.stdout && res.stdout.length > lastLen) {
let res = await fs.exec('/bin/cat', [ logFile ], null, rpc_opt); let log = res.stdout.slice(lastLen);
if (res.stdout && res.stdout.length > lastLen) { hide_rows.forEach(re => {
let log = res.stdout.slice(lastLen); log = log.replace(re, '');
hide_rows.forEach(re => { });
log = log.replace(re, ''); appendLog(log, '');
}); lastLen = res.stdout.length;
appendLog(log, ''); }
lastLen = res.stdout.length; if (retCode < 0) {
} let rc = await fs.exec('/bin/cat', [ rcFile ], null, rpc_opt);
if (retCode < 0) { if (rc.code != 0) {
let rc = await fs.exec('/bin/cat', [ rcFile ], null, rpc_opt); fixLogEnd();
if (rc.code != 0) { resolve(callback(cbarg, 545, 'ERROR: cannot read file "' + rcFile + '"'));
clearInterval(timer); return;
}
if (rc.stdout) {
retCode = parseInt(rc.stdout.trim(), 10);
}
}
if (retCode >= 0) {
fixLogEnd(); fixLogEnd();
return callback(cbarg, 545, 'ERROR: cannot read file "' + rcFile + '"'); if (retCode == 0 && res.stdout) {
resolve(callback(cbarg, 0, res.stdout));
return;
}
resolve(callback(cbarg, retCode, 'ERROR: Process failed with error ' + retCode));
return;
} }
if (rc.stdout) { setTimeout(poll, 500);
retCode = parseInt(rc.stdout.trim(), 10); } catch (e) {
let skip_err = false;
if (e.message?.includes('RPC call to file/exec failed with error -32000: Object not found')) {
skip_err = true;
}
if (e.message?.includes('XHR request timed out')) {
skip_err = true;
}
if (skip_err) {
console.warn('WARN: execAndRead: ' + e.message);
setTimeout(poll, 500);
return; // goto next poll iteration
} }
}
if (retCode >= 0) {
clearInterval(timer);
fixLogEnd(); fixLogEnd();
if (retCode == 0 && res.stdout) { let errtxt = 'ERROR: execAndRead: ' + e.message;
return callback(cbarg, 0, res.stdout); errtxt += 'ERROR: execAndRead: ' + e.stack?.trim().split('\n')[0];
} callback(cbarg, 540, errtxt);
return callback(cbarg, retCode, 'ERROR: Process failed with error ' + retCode); reject(e);
} }
} catch (e) {
if (e.message?.includes('RPC call to file/exec failed with error -32000: Object not found')) {
console.warn('WARN: execAndRead: ' + e.message);
return; // goto next timer iteration
}
clearInterval(timer);
fixLogEnd();
let errtxt = 'ERROR: execAndRead: ' + e.message;
errtxt += 'ERROR: execAndRead: ' + e.stack?.trim().split('\n')[0];
return callback(cbarg, 540, errtxt);
} finally {
timerBusy = false;
} }
}, 500); poll();
});
}, },
}); });

View File

@@ -25,35 +25,28 @@ return baseclass.extend({
this.logArea.scrollTop = this.logArea.scrollHeight; this.logArea.scrollTop = this.logArea.scrollHeight;
}, },
setBtnMode: function(enable) setBtnMode: function(check, install, cancel)
{ {
this.btn_cancel.disabled = enable ? false : true; this.btn_check.disabled = check ? false : true;
this.btn_action.disabled = (enable == 2) ? false : true; this.btn_install.disabled = install ? false : true;
this.btn_cancel.disabled = cancel ? false : true;
}, },
setStage: function(stage, btn_flag = true) setStage: function(stage, btn_flag = true)
{ {
if (stage == 0) { if (stage == 0) this.setBtnMode(1, 0, 1);
this.btn_action.textContent = _('Check for updates'); if (stage == 1) this.setBtnMode(0, 0, 1);
this.btn_action.classList.remove('hidden'); if (stage == 2) this.setBtnMode(1, 1, 1);
} else if (stage == 3) this.setBtnMode(0, 0, 0);
if (stage == 1) { if (stage == 8) this.setBtnMode(0, 0, 1);
this.btn_action.textContent = _('Update packages'); if (stage >= 9) this.setBtnMode(0, 0, 0);
this.btn_action.classList.remove('hidden');
} else {
this.btn_action.classList.add('hidden');
}
if (stage > 1 && typeof(this.btn_action) == 'object') {
this.setBtnMode(1);
}
this.stage = stage; this.stage = stage;
}, },
checkUpdates: async function() checkUpdates: async function(ev)
{ {
this._action = 'checkUpdates'; this._action = 'checkUpdates';
this.setStage(0); this.setStage(1);
this.setBtnMode(0);
this.pkg_url = null; this.pkg_url = null;
this.appendLog(_('Checking for updates...')); this.appendLog(_('Checking for updates...'));
let cmd = [ fn_update_pkg_sh, '-c' ]; // check for updates let cmd = [ fn_update_pkg_sh, '-c' ]; // check for updates
@@ -61,33 +54,38 @@ return baseclass.extend({
cmd.push('-p'); // include prereleases ZIP-files cmd.push('-p'); // include prereleases ZIP-files
} }
this.forced_reinstall = document.getElementById('cfg_forced_reinstall').checked; this.forced_reinstall = document.getElementById('cfg_forced_reinstall').checked;
let log = '/tmp/'+tools.appName+'_pkg_check.log'; return tools.execAndRead({
let callback = this.execAndReadCallback; cmd: cmd,
let wnd = this; log: '/tmp/'+tools.appName+'_pkg_check.log',
return tools.execAndRead({ cmd: cmd, log: log, logArea: this.logArea, callback: callback, cbarg: wnd }); logArea: this.logArea,
callback: this.execAndReadCallback,
cbarg: this, // wnd
});
}, },
installUpdates: async function() installUpdates: async function(ev)
{ {
this._action = 'installUpdates';
this.setStage(1);
this.setBtnMode(0);
if (!this.pkg_url || this.pkg_url.length < 10) { if (!this.pkg_url || this.pkg_url.length < 10) {
this.appendLog('ERROR: pkg_url = null'); this.appendLog('ERROR: pkg_url = null');
this.setStage(999); this.setStage(9);
return; return;
} }
this._action = 'installUpdates';
this.setStage(3);
this.appendLog(_('Install updates...')); this.appendLog(_('Install updates...'));
let cmd = [ fn_update_pkg_sh, '-u', this.pkg_url ]; // update packages let cmd = [ fn_update_pkg_sh, '-u', this.pkg_url ]; // update packages
if (document.getElementById('cfg_forced_reinstall').checked == true) { if (document.getElementById('cfg_forced_reinstall').checked == true) {
cmd.push('-f'); // forced reinstall if same version cmd.push('-f'); // forced reinstall if same version
} }
//this._test = 1; cmd.push('-t'); cmd.push('45'); // only for testing //this._test = 1; cmd.push('-t'); cmd.push('45'); // only for testing
let log = '/tmp/'+tools.appName+'_pkg_install.log'; return tools.execAndRead({
let hiderow = /^ \* resolve_conffiles.*(?:\r?\n|$)/gm; cmd: cmd,
let callback = this.execAndReadCallback; log: '/tmp/'+tools.appName+'_pkg_install.log',
let wnd = this; logArea: this.logArea,
return tools.execAndRead({ cmd: cmd, log: log, logArea: this.logArea, hiderow: hiderow, callback: callback, cbarg: wnd }); hiderow: /^ \* resolve_conffiles.*(?:\r?\n|$)/gm,
callback: this.execAndReadCallback,
cbarg: this, // wnd
});
}, },
execAndReadCallback: function(wnd, rc, txt = '') execAndReadCallback: function(wnd, rc, txt = '')
@@ -96,30 +94,32 @@ return baseclass.extend({
if (rc == 0 && txt) { if (rc == 0 && txt) {
let code = txt.match(/^RESULT:\s*\(([^)]+)\)\s+.+$/m); let code = txt.match(/^RESULT:\s*\(([^)]+)\)\s+.+$/m);
if (wnd._action == 'checkUpdates') { if (wnd._action == 'checkUpdates') {
wnd.appendLog('=========================================================');
if (code && code[1] == 'E') {
wnd.btn_install.textContent = _('Reinstall');
} else {
wnd.btn_install.textContent = _('Install');
}
let pkg_url = txt.match(/^ZAP_PKG_URL\s*=\s*(.+)$/m); let pkg_url = txt.match(/^ZAP_PKG_URL\s*=\s*(.+)$/m);
if (code && pkg_url) { if (code && pkg_url) {
wnd.appendLog('========================================================='); if (code[1] == 'E' && !wnd.forced_reinstall) {
wnd.pkg_url = pkg_url[1]; wnd.setStage(0); // install not needed
code = code[1];
if (code == 'E' && !wnd.forced_reinstall) {
wnd.setStage(999); // install not needed
return; return;
} }
wnd.setStage(1); wnd.pkg_url = pkg_url[1];
wnd.setBtnMode(2); // enable all buttons wnd.setStage(2); // enable all buttons
return; // install allowed return; // install allowed
} }
} }
if (wnd._action == 'installUpdates') { if (wnd._action == 'installUpdates') {
if (wnd._test || (code && code[1] == '+')) { if (wnd._test || (code && code[1] == '+')) {
wnd.stage = 999; wnd.setStage(9);
wnd.btn_action.textContent = _('OK'); wnd.appendLog('Please update WEB-page (press F5)');
wnd.btn_action.disabled = false;
wnd.btn_cancel.disabled = true;
return; return;
} }
} }
} }
wnd.setStage(0);
if (rc >= 500) { if (rc >= 500) {
if (txt) { if (txt) {
wnd.appendLog(txt.startsWith('ERROR') ? txt : 'ERROR: ' + txt); wnd.appendLog(txt.startsWith('ERROR') ? txt : 'ERROR: ' + txt);
@@ -129,10 +129,7 @@ return baseclass.extend({
} else { } else {
wnd.appendLog('ERROR: Process finished with retcode = ' + rc); wnd.appendLog('ERROR: Process finished with retcode = ' + rc);
} }
wnd.setStage(999); wnd.appendLog('=========================================================');
if (wnd._action == 'checkUpdates') {
wnd.appendLog('=========================================================');
}
}, },
openUpdateDialog: function(pkg_arch) openUpdateDialog: function(pkg_arch)
@@ -166,25 +163,30 @@ return baseclass.extend({
}, _('Cancel')); }, _('Cancel'));
this.btn_cancel.onclick = ui.hideModal; this.btn_cancel.onclick = ui.hideModal;
this.btn_action = E('button', { this.btn_check = E('button', {
'id': 'btn_action', 'id': 'btn_check',
'name': 'btn_action', 'name': 'btn_check',
'class': btn_style_action, 'class': btn_style_action,
}, 'BUTTON_ACTION'); }, _('Check'));
this.btn_action.onclick = ui.createHandlerFn(this, () => { this.btn_check.onclick = ui.createHandlerFn(this, this.checkUpdates);
if (this.stage == 0) {
return this.checkUpdates(); this.btn_install = E('button', {
'id': 'btn_install',
'name': 'btn_install',
'class': btn_style_positive,
}, _('Install'));
this.btn_install.onclick = ui.createHandlerFn(this, async () => {
let res = await this.installUpdates();
if (true) {
setTimeout(() => {
this.btn_install.disabled = true;
}, 0);
} }
if (this.stage == 1) {
return this.installUpdates();
}
return ui.hideModal();
}); });
this.setStage(0); this.setStage(0);
this.setBtnMode(2);
ui.showModal(_('Package update'), [ ui.showModal(_('Check for updates and install'), [
E('div', { 'class': 'cbi-section' }, [ E('div', { 'class': 'cbi-section' }, [
exclude_prereleases, exclude_prereleases,
E('br'), E('br'), E('br'), E('br'),
@@ -194,9 +196,11 @@ return baseclass.extend({
this.logArea, this.logArea,
]), ]),
E('div', { 'class': 'right' }, [ E('div', { 'class': 'right' }, [
this.btn_cancel, this.btn_check,
' ', ' ',
this.btn_action, this.btn_install,
' ',
this.btn_cancel,
]) ])
]); ]);
} }

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=zapret2 PKG_NAME:=zapret2
PKG_VERSION:=0.8.20260113 PKG_VERSION:=0.8.20260118
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_MAINTAINER:=bol-van PKG_MAINTAINER:=bol-van
@@ -14,8 +14,8 @@ PKG_LICENSE_FILES:=docs/LICENSE.txt
PKG_SOURCE_URL:=https://github.com/bol-van/zapret2.git PKG_SOURCE_URL:=https://github.com/bol-van/zapret2.git
PKG_SOURCE_PROTO:=git PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=dced388652c49fea6eb82401f79146b484a9cd7a PKG_SOURCE_VERSION:=8e67260a23deeaa14b9de325bb911e5594b2d225
PKG_SOURCE_DATE:=2026-01-13 PKG_SOURCE_DATE:=2026-01-18
#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz #PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
#PKG_SOURCE_URL:=https://github.com/bol-van/zapret2/archive/refs/tags/v$(PKG_VERSION).tar.gz? #PKG_SOURCE_URL:=https://github.com/bol-van/zapret2/archive/refs/tags/v$(PKG_VERSION).tar.gz?
@@ -71,89 +71,101 @@ define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)/mdig $(TARGET_CONFIGURE_OPTS) $(MAKE) -C $(PKG_BUILD_DIR)/mdig $(TARGET_CONFIGURE_OPTS)
endef endef
ZAPRET_DIR := /opt/zapret2
define ZAPRET_CONFFILES_LIST
$(ZAPRET_DIR)/config
$(ZAPRET_DIR)/ipset/zapret-hosts-google.txt
$(ZAPRET_DIR)/ipset/zapret-hosts-user.txt
$(ZAPRET_DIR)/ipset/zapret-hosts-user-exclude.txt
$(ZAPRET_DIR)/ipset/zapret-ip-exclude.txt
$(ZAPRET_DIR)/ipset/zapret-hosts-auto.txt
$(ZAPRET_DIR)/ipset/cust1.txt
$(ZAPRET_DIR)/ipset/cust2.txt
$(ZAPRET_DIR)/ipset/cust3.txt
$(ZAPRET_DIR)/ipset/cust4.txt
$(ZAPRET_DIR)/init.d/openwrt/custom.d/10-script.sh
$(ZAPRET_DIR)/init.d/openwrt/custom.d/20-script.sh
$(ZAPRET_DIR)/init.d/openwrt/custom.d/50-script.sh
$(ZAPRET_DIR)/init.d/openwrt/custom.d/60-script.sh
$(ZAPRET_DIR)/init.d/openwrt/custom.d/90-script.sh
endef
$(eval ZAPRET_CONFFILES := $(foreach file,$(ZAPRET_CONFFILES_LIST),$(strip $(file))))
define Package/$(PKG_NAME)/conffiles define Package/$(PKG_NAME)/conffiles
/opt/zapret2/config $(ZAPRET_CONFFILES_LIST)
/opt/zapret2/ipset/zapret-hosts-google.txt
/opt/zapret2/ipset/zapret-hosts-user.txt
/opt/zapret2/ipset/zapret-hosts-user-exclude.txt
/opt/zapret2/ipset/zapret-ip-exclude.txt
/opt/zapret2/ipset/zapret-hosts-auto.txt
/opt/zapret2/init.d/openwrt/custom.d/10-script.sh
/opt/zapret2/init.d/openwrt/custom.d/20-script.sh
/opt/zapret2/init.d/openwrt/custom.d/50-script.sh
/opt/zapret2/init.d/openwrt/custom.d/60-script.sh
/opt/zapret2/init.d/openwrt/custom.d/90-script.sh
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/opt/zapret2 $(INSTALL_DIR) $(1)$(ZAPRET_DIR)
$(INSTALL_DIR) $(1)/opt/zapret2/$(MAKE_PATH) $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/$(MAKE_PATH)
$(INSTALL_BIN) $(PKG_BUILD_DIR)/$(MAKE_PATH)/nfqws2 $(1)/opt/zapret2/$(MAKE_PATH)/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(MAKE_PATH)/nfqws2 $(1)$(ZAPRET_DIR)/$(MAKE_PATH)/
$(INSTALL_DIR) $(1)/opt/zapret2/ip2net $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/ip2net
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net/ip2net $(1)/opt/zapret2/ip2net/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net/ip2net $(1)$(ZAPRET_DIR)/ip2net/
$(INSTALL_DIR) $(1)/opt/zapret2/mdig $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/mdig
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig/mdig $(1)/opt/zapret2/mdig/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig/mdig $(1)$(ZAPRET_DIR)/mdig/
$(INSTALL_DIR) $(1)/opt/zapret2/common $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/common
$(CP) $(PKG_BUILD_DIR)/common/* $(1)/opt/zapret2/common/ $(CP) $(PKG_BUILD_DIR)/common/* $(1)$(ZAPRET_DIR)/common/
$(INSTALL_DIR) $(1)/opt/zapret2/lua $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/lua
$(CP) $(PKG_BUILD_DIR)/lua/* $(1)/opt/zapret2/lua/ $(CP) $(PKG_BUILD_DIR)/lua/* $(1)$(ZAPRET_DIR)/lua/
#$(INSTALL_DIR) $(1)/opt/zapret2/docs #$(INSTALL_DIR) $(1)$(ZAPRET_DIR)docs
#$(CP) $(PKG_BUILD_DIR)/docs/* $(1)/opt/zapret2/docs/ #$(CP) $(PKG_BUILD_DIR)/docs/* $(1)$(ZAPRET_DIR)/docs/
$(INSTALL_DIR) $(1)/opt/zapret2/files $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/files
$(CP) $(PKG_BUILD_DIR)/files/* $(1)/opt/zapret2/files/ $(CP) $(PKG_BUILD_DIR)/files/* $(1)$(ZAPRET_DIR)/files/
$(CP) ./files/* $(1)/opt/zapret2/files/ $(CP) ./files/* $(1)$(ZAPRET_DIR)/files/
$(INSTALL_DIR) $(1)/opt/zapret2/ipset $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/ipset
$(CP) $(PKG_BUILD_DIR)/ipset/* $(1)/opt/zapret2/ipset/ $(CP) $(PKG_BUILD_DIR)/ipset/* $(1)$(ZAPRET_DIR)/ipset/
$(INSTALL_DIR) $(1)/opt/zapret2/blockcheck2.d $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/blockcheck2.d
$(CP) $(PKG_BUILD_DIR)/blockcheck2.d/* $(1)/opt/zapret2/blockcheck2.d/ $(CP) $(PKG_BUILD_DIR)/blockcheck2.d/* $(1)$(ZAPRET_DIR)/blockcheck2.d/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/blockcheck2.sh $(1)/opt/zapret2/blockcheck2.sh $(INSTALL_BIN) $(PKG_BUILD_DIR)/blockcheck2.sh $(1)$(ZAPRET_DIR)/blockcheck2.sh
#$(INSTALL_DATA) $(PKG_BUILD_DIR)/config.default $(1)/opt/zapret2/config.default $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/tmp
$(INSTALL_DIR) $(1)/opt/zapret2/tmp $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/init.d/openwrt
$(INSTALL_DIR) $(1)/opt/zapret2/init.d/openwrt $(CP) $(PKG_BUILD_DIR)/init.d/openwrt/* $(1)$(ZAPRET_DIR)/init.d/openwrt/
$(CP) $(PKG_BUILD_DIR)/init.d/openwrt/* $(1)/opt/zapret2/init.d/openwrt/
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_BIN) $(PKG_BUILD_DIR)/init.d/openwrt/90-zapret2 $(1)/etc/hotplug.d/iface/90-zapret2 $(INSTALL_BIN) $(PKG_BUILD_DIR)/init.d/openwrt/90-zapret2 $(1)/etc/hotplug.d/iface/90-zapret2
$(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./init.d.sh $(1)/etc/init.d/zapret2 $(INSTALL_BIN) ./init.d.sh $(1)/etc/init.d/zapret2
$(INSTALL_DATA) ./config.default $(1)/opt/zapret2/config.default $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/init.d
$(INSTALL_DATA) ./config.default $(1)/opt/zapret2/config $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/init.d/openwrt
$(INSTALL_DATA) ./ipset/zapret-hosts-google.txt $(1)/opt/zapret2/ipset/zapret-hosts-google.txt $(INSTALL_DIR) $(1)$(ZAPRET_DIR)/init.d/openwrt/custom.d
$(INSTALL_DATA) ./ipset/zapret-hosts-user.txt $(1)/opt/zapret2/ipset/zapret-hosts-user.txt
$(INSTALL_DATA) ./ipset/zapret-hosts-user-exclude.txt $(1)/opt/zapret2/ipset/zapret-hosts-user-exclude.txt
$(INSTALL_DATA) ./ipset/zapret-ip-exclude.txt $(1)/opt/zapret2/ipset/zapret-ip-exclude.txt
$(INSTALL_DIR) $(1)/opt/zapret2/ipset_def
$(INSTALL_DATA) ./ipset/zapret-hosts-google.txt $(1)/opt/zapret2/ipset_def/zapret-hosts-google.txt
$(INSTALL_DATA) ./ipset/zapret-hosts-user.txt $(1)/opt/zapret2/ipset_def/zapret-hosts-user.txt
$(INSTALL_DATA) ./ipset/zapret-hosts-user-exclude.txt $(1)/opt/zapret2/ipset_def/zapret-hosts-user-exclude.txt
$(INSTALL_DATA) ./ipset/zapret-ip-exclude.txt $(1)/opt/zapret2/ipset_def/zapret-ip-exclude.txt
$(INSTALL_DIR) $(1)/opt/zapret2/init.d
$(INSTALL_DIR) $(1)/opt/zapret2/init.d/openwrt
$(INSTALL_DIR) $(1)/opt/zapret2/init.d/openwrt/custom.d
$(CP) ./custom.d/* $(1)/opt/zapret2/init.d/openwrt/custom.d/
$(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./uci-def-cfg.sh $(1)/etc/uci-defaults/zapret2-uci-def-cfg.sh $(INSTALL_BIN) ./uci-def-cfg.sh $(1)/etc/uci-defaults/zapret2-uci-def-cfg.sh
# install all sh-scripts # install all sh-scripts
$(CP) ./*.sh $(1)/opt/zapret2/ $(CP) ./*.sh $(1)$(ZAPRET_DIR)/
rm -f $(1)/opt/zapret2/init.d.sh rm -f $(1)$(ZAPRET_DIR)/init.d.sh
# Create empty conf files # Install conf files
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/ipset/zapret-hosts-auto.txt $(foreach cfg,$(ZAPRET_CONFFILES), \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/ipset/cust1.txt rel="$(cfg:$(ZAPRET_DIR)/%=%)"; \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/ipset/cust2.txt src="./$$$$rel"; \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/ipset/cust3.txt if echo "$$$$rel" | grep -q "/custom.d/"; then \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/ipset/cust4.txt src="./custom.d/$$$$(basename $$$$rel)"; \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/init.d/openwrt/custom.d/10-script.sh fi; \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/init.d/openwrt/custom.d/20-script.sh dst="$(1)$(cfg)"; \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/init.d/openwrt/custom.d/60-script.sh mkdir -p "$(1)$(dir $(cfg))"; \
$(INSTALL_DATA) /dev/null $(1)/opt/zapret2/init.d/openwrt/custom.d/90-script.sh rm -f "$$$${dst}"; \
if [ -f "$$$${src}" ]; then \
$(INSTALL_DATA) "$$$${src}" "$$$${dst}"; \
else \
$(INSTALL_DATA) /dev/null "$$$${dst}"; \
fi; \
)
# Fix main config file
rm -f $(1)$(ZAPRET_DIR)/config
$(INSTALL_DATA) ./config.default $(1)$(ZAPRET_DIR)/config
$(INSTALL_DATA) ./config.default $(1)$(ZAPRET_DIR)/config.default
# Install def conf files
$(INSTALL_DIR) $(1)$(ZAPRET_DIR)/ipset_def
$(CP) ./ipset/zapret*.txt $(1)$(ZAPRET_DIR)/ipset_def/
# Fix permissions # Fix permissions
chmod 644 $(1)/opt/zapret2/ipset/*.txt chmod 644 $(1)$(ZAPRET_DIR)/ipset/*.txt
chmod 644 $(1)/opt/zapret2/ipset_def/*.txt chmod 644 $(1)$(ZAPRET_DIR)/ipset_def/*.txt
chmod 644 $(1)/opt/zapret2/init.d/openwrt/custom.d/*.sh chmod 644 $(1)$(ZAPRET_DIR)/init.d/openwrt/custom.d/*.sh
chmod 644 $(1)/opt/zapret2/config* chmod 644 $(1)$(ZAPRET_DIR)/config*
chmod 755 $(1)/opt/zapret2/*.sh chmod 755 $(1)$(ZAPRET_DIR)/*.sh
chmod 755 $(1)/opt/zapret2/$(MAKE_PATH)/* chmod 755 $(1)$(ZAPRET_DIR)/$(MAKE_PATH)/*
chmod 755 $(1)/opt/zapret2/ip2net/* chmod 755 $(1)$(ZAPRET_DIR)/ip2net/*
chmod 755 $(1)/opt/zapret2/mdig/* chmod 755 $(1)$(ZAPRET_DIR)/mdig/*
endef endef
define Package/$(PKG_NAME)/preinst define Package/$(PKG_NAME)/preinst

View File

@@ -179,7 +179,7 @@ function insert_cron_task_logs
{ {
[ ! -f "$CRONTAB_FILE" ] && touch "$CRONTAB_FILE" [ ! -f "$CRONTAB_FILE" ] && touch "$CRONTAB_FILE"
[ ! -f "$CRONTAB_FILE" ] && return 1 [ ! -f "$CRONTAB_FILE" ] && return 1
if ! grep -q -e "-name '$ZAPRET_CFG_NAME\*\.log' -size \+" "$CRONTAB_FILE"; then if ! grep -q -e "-name '$ZAPRET_CFG_NAME+\*\.log' -size \+" "$CRONTAB_FILE"; then
echo "*/2 * * * * /usr/bin/find /tmp -maxdepth 1 -type f -name '$ZAPRET_CFG_NAME+*.log' -size +2600k -exec rm -f {} \;" >> "$CRONTAB_FILE" echo "*/2 * * * * /usr/bin/find /tmp -maxdepth 1 -type f -name '$ZAPRET_CFG_NAME+*.log' -size +2600k -exec rm -f {} \;" >> "$CRONTAB_FILE"
/etc/init.d/cron restart 2> /dev/null /etc/init.d/cron restart 2> /dev/null
fi fi

View File

@@ -181,5 +181,17 @@ function set_cfg_default_values
commit $cfgname commit $cfgname
EOF EOF
fi fi
if echo "$opt_flags" | grep -q "(enable_custom_d)"; then
uci batch <<-EOF
set $cfgname.config.DISABLE_CUSTOM='0'
commit $cfgname
EOF
fi
if echo "$opt_flags" | grep -q "(disable_custom_d)"; then
uci batch <<-EOF
set $cfgname.config.DISABLE_CUSTOM='1'
commit $cfgname
EOF
fi
return 0 return 0
} }

View File

@@ -1,14 +1,34 @@
#!/bin/sh #!/bin/sh
# Copyright (c) 2026 remittor # Copyright (c) 2026 remittor
. /opt/zapret2/comfunc.sh ZAP_TMP_DIR=/tmp/zapret2_dwc
ZAP_TMP_DIR=/tmp/zapret_dwc opt_dig=
opt_recom=
opt_tmp_dir=
opt_test=
rm -rf $ZAP_TMP_DIR while getopts "d:RT:t" opt; do
case $opt in
d) opt_dig="$OPTARG";;
R) opt_recom="true";; # Recommendations
T) opt_tmp_dir="$OPTARG";;
t) opt_test="true";;
esac
done
[ "$opt_tmp_dir" != "" ] && ZAP_TMP_DIR="$opt_tmp_dir"
TARGET_LIST_FILE="$ZAP_TMP_DIR/targets"
[ -f "$TARGET_LIST_FILE" ] && rm -rf "$ZAP_TMP_DIR"
[ -f "$TARGET_LIST_FILE" ] && exit 3
CURL_TIMEOUT=5 CURL_TIMEOUT=5
CURL_RANGETO=65535 CURL_RANGETO=65535
CURL_NOCACHE='cache-control: no-cache'
CURL_NOCACHE2='pragma: no-cache'
CURL_USERAGENT='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36'
if ! command -v curl >/dev/null 2>&1; then if ! command -v curl >/dev/null 2>&1; then
echo "ERROR: package \"curl\" not installed!" echo "ERROR: package \"curl\" not installed!"
@@ -24,6 +44,26 @@ if ! echo "$CURL_INFO" | grep -q 'https'; then
return 11 return 11
fi fi
if [ "$opt_dig" != "" ]; then
if ! command -v dig >/dev/null 2>&1; then
echo "ERROR: package \"bind-dig\" not installed!"
return 12
fi
OPT_DIG_DNS="@$opt_dig"
[ "$opt_dig" = "@" ] && OPT_DIG_DNS=''
[ "$opt_dig" = "8" ] && OPT_DIG_DNS='@8.8.8.8'
[ "$opt_dig" = "1" ] && OPT_DIG_DNS='@1.1.1.1'
[ "$opt_dig" = "9" ] && OPT_DIG_DNS='@9.9.9.9'
fi
if [ -f /etc/openwrt_release ]; then
CA_CERTS=/etc/ssl/certs/ca-certificates.crt
if [ ! -f $CA_CERTS ]; then
echo "ERROR: package \"ca-bundle\" not installed!"
return 15
fi
fi
#echo 'Original sources: https://github.com/hyperion-cs/dpi-checkers' #echo 'Original sources: https://github.com/hyperion-cs/dpi-checkers'
#echo 'WEB-version: https://hyperion-cs.github.io/dpi-checkers/ru/tcp-16-20/' #echo 'WEB-version: https://hyperion-cs.github.io/dpi-checkers/ru/tcp-16-20/'
@@ -45,7 +85,7 @@ TEST_SUITE='[
{ id: "DE.AWS-01", provider: "🇩🇪 AWS", times: 1, url: "https://www.getscope.com/assets/fonts/fa-solid-900.woff2" }, { id: "DE.AWS-01", provider: "🇩🇪 AWS", times: 1, url: "https://www.getscope.com/assets/fonts/fa-solid-900.woff2" },
{ id: "US.AWS-01", provider: "🇺🇸 AWS", times: 1, url: "https://corp.kaltura.com/wp-content/cache/min/1/wp-content/themes/airfleet/dist/styles/theme.css" }, { id: "US.AWS-01", provider: "🇺🇸 AWS", times: 1, url: "https://corp.kaltura.com/wp-content/cache/min/1/wp-content/themes/airfleet/dist/styles/theme.css" },
{ id: "US.GC-01", provider: "🇺🇸 Google Cloud", times: 1, url: "https://api.usercentrics.eu/gvl/v3/en.json" }, { id: "US.GC-01", provider: "🇺🇸 Google Cloud", times: 1, url: "https://api.usercentrics.eu/gvl/v3/en.json" },
{ id: "US.FST-01", provider: "🇺🇸 Fastly", times: 1, url: "https://www.jetblue.com/main.c7b61d59416f714f.js" }, { id: "US.FST-01", provider: "🇺🇸 Fastly", times: 1, url: "https://www.jetblue.com/footer/footer-element-es2015.js" },
{ id: "CA.FST-01", provider: "🇨🇦 Fastly", times: 1, url: "https://www.cnn10.com/" }, { id: "CA.FST-01", provider: "🇨🇦 Fastly", times: 1, url: "https://www.cnn10.com/" },
{ id: "US.AKM-01", provider: "🇺🇸 Akamai", times: 1, url: "https://www.roxio.com/static/roxio/images/products/creator/nxt9/call-action-footer-bg.jpg" }, { id: "US.AKM-01", provider: "🇺🇸 Akamai", times: 1, url: "https://www.roxio.com/static/roxio/images/products/creator/nxt9/call-action-footer-bg.jpg" },
{ id: "PL.AKM-01", provider: "🇵🇱 Akamai", times: 1, url: "https://media-assets.stryker.com/is/image/stryker/gateway_1?$max_width_1410$" }, { id: "PL.AKM-01", provider: "🇵🇱 Akamai", times: 1, url: "https://media-assets.stryker.com/is/image/stryker/gateway_1?$max_width_1410$" },
@@ -60,60 +100,135 @@ function trim
echo "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' echo "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
} }
mkdir -p $ZAP_TMP_DIR mkdir -p "$ZAP_TMP_DIR"
ID=0 : > "$TARGET_LIST_FILE"
while IFS='|' read -r TAG PROVIDER TIMES URL; do IDX=0
while IFS= read -r line; do
case "$line" in
*id:*provider:*url:*)
IDX=$((IDX + 1))
TAG=$( printf '%s\n' "$line" | cut -d'"' -f2 )
COUNTRY="${TAG%%.*}"
PROVIDER_RAW=$( printf '%s\n' "$line" | cut -d'"' -f4 )
PROVIDER="${PROVIDER_RAW#* }"
TIMES=$( printf '%s\n' "$line" | cut -d':' -f4 | cut -d',' -f1 | tr -d ' ')
URL=$( printf '%s\n' "$line" | cut -d'"' -f6 )
echo "${IDX}|${TAG}|${COUNTRY}|${PROVIDER}|${TIMES}|${URL}" >> "$TARGET_LIST_FILE"
;;
esac
done <<EOF
$TEST_SUITE
EOF
CURL_CON_TIMEOUT=$((CURL_TIMEOUT-2))
CURL_SPEED_TIME=$((CURL_TIMEOUT-2))
CURL_SPEED_LIMIT=1
while IFS='|' read -r ID TAG COUNTRY PROVIDER TIMES URL; do
[ -z "$TAG" ] && continue [ -z "$TAG" ] && continue
ID=$((ID+1)) ID=$((ID+1))
ID3=$(printf '%03d' "$ID") ID3=$( printf '%03d' "$ID" )
COUNTRY="$(echo "$TAG" | cut -d. -f1)" COUNTRY=$( echo "$TAG" | cut -d. -f1 )
CNTFLAG="$(echo "$PROVIDER" | awk '{print $1}')" CNTFLAG=$( echo "$PROVIDER" | awk '{print $1}' )
PROVIDER="$(echo "$PROVIDER" | cut -d' ' -f2-)"
URL_NO_PROTO="${URL#*://}" URL_NO_PROTO="${URL#*://}"
DOMAIN="${URL_NO_PROTO%%/*}" DOMAIN="${URL_NO_PROTO%%/*}"
URLPATH="/${URL_NO_PROTO#*/}" URLPATH="/${URL_NO_PROTO#*/}"
[ "$URLPATH" = "/$URL_NO_PROTO" ] && URLPATH="/" [ "$URLPATH" = "/$URL_NO_PROTO" ] && URLPATH="/"
#echo "TAG=$TAG , COUNTRY=$COUNTRY , PROVIDER=$PROVIDER , TIMES=$TIMES , URL=$URL" #echo "TAG=$TAG , COUNTRY=$COUNTRY , PROVIDER=$PROVIDER , DOMAIN=$DOMAIN , URL=$URL"
FNAME="$ZAP_TMP_DIR/$ID3=$TAG=$PROVIDER"
( (
DST_IP=$( curl -4 -s -o /dev/null -w '%{remote_ip}\n' $DOMAIN ) DST_IP=
if [ -z "$DST_IP" ]; then RESOLVE_OPT=
DST_IP="$( ping -c1 "$DOMAIN" 2>/dev/null | sed -n '1s/.*(\([0-9.]*\)).*/\1/p')" if [ "$opt_dig" != "" ]; then
DST_IP=$( dig +time=2 +retry=1 $OPT_DIG_DNS +short "$DOMAIN" 2>/dev/null | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1 )
else
CURL_TIMEOUTS="--connect-timeout 2 --max-time 3 --speed-time 3 --speed-limit 1"
DST_IP=$( curl -4 -I -s $CURL_TIMEOUTS -o /dev/null -w '%{remote_ip}\n' "$URL" )
if [ -z "$DST_IP" ]; then
DST_IP=$( curl -4 -s $CURL_TIMEOUTS -o /dev/null -r 0-0 -w '%{remote_ip}\n' "$URL" )
fi
fi fi
curl -k $URL --resolve $DOMAIN:443:$DST_IP -o /dev/null -s -w '%{size_download}\n' --max-time $CURL_TIMEOUT --range 0-$CURL_RANGETO if [ "$DST_IP" = "" ]; then
) >"$ZAP_TMP_DIR/$ID3=$TAG=$PROVIDER.txt" 2>&1 & DST_IP=$( ping -c1 "$DOMAIN" 2>/dev/null | sed -n '1s/.*(\([0-9.]*\)).*/\1/p' )
done <<EOF fi
$(printf '%s\n' "$TEST_SUITE" | sed -n ' [ "$DST_IP" != "" ] && RESOLVE_OPT="--resolve $DOMAIN:443:$DST_IP"
s/.*id:[[:space:]]*"\([^"]*\)".*provider:[[:space:]]*"\([^"]*\)".*times:[[:space:]]*\([0-9]\+\).*url:[[:space:]]*"\([^"]*\)".*/\1|\2|\3|\4/p echo "$DST_IP" > "$FNAME.ip"
') echo "$URL" > "$FNAME.url"
EOF curl "$URL" \
$RESOLVE_OPT \
--connect-timeout $CURL_CON_TIMEOUT \
--max-time $CURL_TIMEOUT \
--speed-time $CURL_SPEED_TIME \
--speed-limit $CURL_SPEED_LIMIT \
--range 0-$CURL_RANGETO \
-A "$CURL_USERAGENT" \
-D "$FNAME.hdr" \
-o "$FNAME.body"
) > "$FNAME.log" 2>&1 &
done < "$TARGET_LIST_FILE"
wait wait
printf '%s\n' "$ZAP_TMP_DIR"/*.txt | sort | while IFS= read -r file; do FAIL_URL_LIST="$ZAP_TMP_DIR/FAIL_URL_LIST.txt"
rm -f "$FAIL_URL_LIST"
printf '%s\n' "$ZAP_TMP_DIR"/*.log | sort | while IFS= read -r file; do
[ -f "$file" ] || continue [ -f "$file" ] || continue
FNAME="${file##*/}" FILENAME="${file##*/}"
ID=$( echo "$FNAME" | cut -d= -f1) FILENAME="${FILENAME%.log}"
TAG=$( echo "$FNAME" | cut -d= -f2) ID=$( echo "$FILENAME" | cut -d= -f1)
PROVIDER=$(echo "$FNAME" | cut -d= -f3 | sed 's/\.txt$//' ) TAG=$( echo "$FILENAME" | cut -d= -f2)
res=$( cat "$file" ) PROVIDER=$(echo "$FILENAME" | cut -d= -f3 )
res=$( trim "$res" ) FNAME="$ZAP_TMP_DIR/$FILENAME"
BODY_SIZE=0
[ -f "$FNAME.body" ] && BODY_SIZE=$( wc -c < "$FNAME.body" )
IPADDR="x.x.x.x"
[ -s "$FNAME.ip" ] && IPADDR=$( cat "$FNAME.ip" )
res=0
status= status=
case "$res" in if [ ! -f "$FNAME.hdr" ]; then
''|*[!0-9]*) status="ERROR: cannot Get Headers"
status="Error (incorrect value)" elif [ ! -s "$FNAME.hdr" ]; then
;; status="ERROR: cannot get headers"
esac elif [ ! -f "$FNAME.body" ]; then
if [ -z "$status" ]; then status="Possibly detected*"
if [ "$res" = 0 ]; then elif [ ! -s "$FNAME.body" ]; then
status="Possibly detected" status="Possibly detected"
elif [ "$res" -lt $CURL_RANGETO ]; then else
status="Failed to complete detection" if [ "$BODY_SIZE" -le $CURL_RANGETO ]; then
status="Failed (recv $BODY_SIZE bytes)"
res=5
else else
status="[ OK ]" status="[ OK ]"
res=100
fi fi
fi fi
printf '%12s / %-13s: %s \n' "$TAG" "$PROVIDER" "$status" printf '%12s / %-15s / %-13s: %s \n' "$TAG" "$IPADDR" "$PROVIDER" "$status"
echo "$BODY_SIZE" > "$FNAME.size"
if [ $res != 100 ]; then
URL=$( cat "$FNAME.url" )
echo "$FILENAME : $URL" >> "$FAIL_URL_LIST"
fi
done done
rm -f "$ZAP_TMP_DIR"/*.body >/dev/null 2>&1
[ "$opt_recom" != "true" ] && return 0
[ ! -f "$FAIL_URL_LIST" ] && return 0
echo "==================================================="
echo "Recommendations:"
echo "Try adding the specified domains to the \"zapret-hosts-user.txt\" file:"
while IFS=' : ' read -r FILENAME URL; do
[ -z "$FILENAME" ] && continue
URL_NO_PROTO="${URL#*://}"
DOMAIN="${URL_NO_PROTO%%/*}"
URLPATH="/${URL_NO_PROTO#*/}"
[ "$URLPATH" = "/$URL_NO_PROTO" ] && URLPATH="/"
echo "$DOMAIN"
done < "$FAIL_URL_LIST"
return 0 return 0

View File

@@ -16,6 +16,8 @@ gov.ru
sudrf.ru sudrf.ru
ottai.com ottai.com
ipstream.one ipstream.one
vkusvill.ru
kinopoisk.ru
#################################### Epicgames #################################### Epicgames
easy.ac easy.ac
fab.com fab.com
@@ -37,45 +39,14 @@ cubicmotion.com
playparagon.com playparagon.com
realityscan.com realityscan.com
epicgamescdn.com epicgamescdn.com
et.epicgames.com
ol.epicgames.com
radgametools.com radgametools.com
unrealengine.com unrealengine.com
api.epicgames.dev
easyanticheat.net easyanticheat.net
shadowcomplex.com shadowcomplex.com
battlebreakers.com battlebreakers.com
store.epicgames.com
capturingreality.com capturingreality.com
unrealtournament.com unrealtournament.com
cdn1.unrealengine.com
cdn2.unrealengine.com
accounts.epicgames.com
download.epicgames.com
tracking.epicgames.com
download2.epicgames.com
download3.epicgames.com
download4.epicgames.com
metrics.ol.epicgames.com
datarouter.ol.epicgames.com
fastly-download.epicgames.com
store-content.ak.epicgames.com
static-assets-prod.epicgames.com
epicgames-download1.akamaized.net epicgames-download1.akamaized.net
launcher-website-prod07.ol.epicgames.com
ut-public-service-prod10.ol.epicgames.com
store-site-backend-static.ak.epicgames.com
library-service.live.use1a.on.epicgames.com
accountportal-website-prod07.ol.epicgames.com
account-public-service-prod03.ol.epicgames.com
catalog-public-service-prod06.ol.epicgames.com
friends-public-service-prod06.ol.epicgames.com
launcher-public-service-prod06.ol.epicgames.com
entitlement-public-service-prod08.ol.epicgames.com
lightswitch-public-service-prod06.ol.epicgames.com
orderprocessor-public-service-ecomprod01.ol.epicgames.com
launcherwaitingroom-public-service-prod06.ol.epicgames.com
datastorage-public-service-liveegs.live.use1a.on.epicgames.com
#################################### Steam #################################### Steam
s.team s.team
steam.tv steam.tv
@@ -103,99 +74,49 @@ valvesoftware.net
steam.cdn.webra.ru steam.cdn.webra.ru
steambroadcast.com steambroadcast.com
steamcommunity.com steamcommunity.com
cdn.steamstatic.com
cs.steampowered.com
dl.steam.clngaa.com dl.steam.clngaa.com
steam.ru.qtlglb.com steam.ru.qtlglb.com
api.steampowered.com
steam.eca.qtlglb.com steam.eca.qtlglb.com
steamusercontent.com steamusercontent.com
help.steampowered.com
steam.apac.qtlglb.com steam.apac.qtlglb.com
steam.naeu.qtlglb.com steam.naeu.qtlglb.com
cdn.steamcommunity.com cdn.steamcommunity.com
gstore.val.manlaxy.com gstore.val.manlaxy.com
login.steampowered.com
media.steampowered.com
partner.steamgames.com partner.steamgames.com
shared.steamstatic.com
steam.cdn.orcon.net.nz steam.cdn.orcon.net.nz
store.steampowered.com
steamcdn-a.akamaihd.net steamcdn-a.akamaihd.net
steampipe.akamaized.net steampipe.akamaized.net
partner.steampowered.com
steamcdn-a.akamaized.net steamcdn-a.akamaized.net
steamdeckusercontent.com steamdeckusercontent.com
support.steampowered.com
checkout.steampowered.com
community.steamstatic.com
steam.cdn.slingshot.co.nz steam.cdn.slingshot.co.nz
steammobile.akamaized.net steammobile.akamaized.net
steamstatic.akamaized.net steamstatic.akamaized.net
steamstore-a.akamaihd.net steamstore-a.akamaihd.net
steamvideo-a.akamaihd.net steamvideo-a.akamaihd.net
workshop.steampowered.com
cdn.akamai.steamstatic.com
cdn.fastly.steamstatic.com
client-update.queniuqe.com client-update.queniuqe.com
community.steampowered.com
steamdeckcdn.akamaized.net steamdeckcdn.akamaized.net
steampipe-kr.akamaized.net steampipe-kr.akamaized.net
clan.fastly.steamstatic.com
steamcontent-a.akamaihd.net steamcontent-a.akamaihd.net
steambroadcast.akamaized.net steambroadcast.akamaized.net
steamcommunity.akamaized.net steamcommunity.akamaized.net
store.akamai.steamstatic.com
store.fastly.steamstatic.com
scontent.steamusercontent.com scontent.steamusercontent.com
shared.fastly.steamstatic.com
steamcommunity-a.akamaihd.net steamcommunity-a.akamaihd.net
avatars.fastly.steamstatic.com
cdn.cloudflare.steamstatic.com
edge.steam-dns.top.comcast.net edge.steam-dns.top.comcast.net
steamcommunity-a.akamaized.net steamcommunity-a.akamaized.net
steamuserimages-a.akamaihd.net steamuserimages-a.akamaihd.net
steampipe-partner.akamaized.net steampipe-partner.akamaized.net
steamusercontent-a.akamaihd.net steamusercontent-a.akamaihd.net
client-download.steampowered.com
community.fastly.steamstatic.com
store.cloudflare.steamstatic.com
community.cloudflare.steamstatic.com
steamcdn-a.akamaihd.net.edgesuite.net steamcdn-a.akamaihd.net.edgesuite.net
steamcloudsweden.blob.core.windows.net steamcloudsweden.blob.core.windows.net
steamcommunity.cloudflare.steamstatic.com
steamcommunity-a.akamaihd.net.edgesuite.net steamcommunity-a.akamaihd.net.edgesuite.net
#################################### OpenWRT #################################### OpenWRT
github.com
openwrt.org openwrt.org
gh.openwrt.org
cdn.openwrt.org
dev.openwrt.org
git.openwrt.org
lede-project.org lede-project.org
wiki.openwrt.org
forum.openwrt.org
lists.openwrt.org
openwrt.gitlab.io
archive.openwrt.org
downloads.openwrt.org
fwdownloads.openwrt.org
mirror-01.infra.openwrt.org
mirror-02.infra.openwrt.org
mirror-03.infra.openwrt.org
mirror-04.infra.openwrt.org
#################################### UbisoftConnect #################################### UbisoftConnect
ubi.com ubi.com
ubisoft.com ubisoft.com
store.ubi.com
ubisoftconnect.com ubisoftconnect.com
connect.ubisoft.com connect.ubisoft.comubisoft-orbit-savegames.s3.amazonaws.com
drops-register.ubi.com
public-ubiservices.ubi.com
ubisoftconnect.cdn.ubi.com
uplaypc-s-ubisoft.cdn.ubi.com
uplaypc-s-ubisoft-ww.cdn.ubi.com
ubisoft-orbit-savegames.s3.amazonaws.com
ubisoft-uplay-savegames.s3.amazonaws.com ubisoft-uplay-savegames.s3.amazonaws.com
#################################### Aliexpress #################################### Aliexpress
ae.com ae.com
@@ -215,55 +136,33 @@ playstation.net
playstation.com playstation.com
account.sony.com account.sony.com
psremoteplay.com psremoteplay.com
ps4.playstation.com
ps5.playstation.com
playstationcloud.com playstationcloud.com
psapi.playstation.net
store.playstation.com
media.playstation.com
auth.np.ac.playstation.net
sonyentertainmentnetwork.com sonyentertainmentnetwork.com
np.community.playstation.net
id.sonyentertainmentnetwork.com
#################################### Twitch #################################### Twitch
twitch.tv twitch.tv
ttvnw.net ttvnw.net
jtvnw.net jtvnw.net
twimg.com
m.twitch.tv
id.twitch.tv
www.twitch.tv
twitchcdn.net twitchcdn.net
ext-twitch.tv ext-twitch.tv
twitchsvc.net twitchsvc.net
api.twitch.tv
gql.twitch.tv
dev.twitch.tv
live-video.net live-video.net
twitch.a2z.com twitch.a2z.com
chat.twitch.tv
help.twitch.tv
assets.twitch.tv
twitch-shadow.net twitch-shadow.net
passport.twitch.tv
irc.chat.twitch.tv
vod-metro.twitch.tv
twitchcdn-shadow.net twitchcdn-shadow.net
static.twitchcdn.net
vod-secure.twitch.tv
irc-ws.chat.twitch.tv
pubsub-edge.twitch.tv
vod-pop-secure.twitch.tv
#################################### Valorant #################################### Valorant
qq.com
pvp.net pvp.net
vivox.com vivox.com
sd-rtn.com sd-rtn.com
adjust.com
riotcdn.net riotcdn.net
adobess.com adobess.com
valorant.com valorant.com
akamaihd.net akamaihd.net
myqcloud.com
riotgames.com riotgames.com
playvalorant.com playvalorant.com
wildrift-na.akamaized.net
#################################### TikTok #################################### TikTok
musical.ly musical.ly
tiktok.com tiktok.com
@@ -359,4 +258,30 @@ xiaomifactory.com
airstarfinance.net airstarfinance.net
dreame-technology.cn dreame-technology.cn
dreame-technology.com dreame-technology.com
#################################### Picooc
picoocru.com
picooc-g.com
picooc-int.com
#################################### Huawei
hc-cdn.cn
huawei.ru
huawei.com
hc-cdn.com
huawei.net
dbankcdn.ru
hicloud.com
dbankcdn.com
dbankcloud.ru
dbankcloud.cn
dbankcloud.com
huaweicloud.com
huaweistatic.com
hwclouds-dns.com
hwclouds-dns.net
myhuaweicloud.cn
myhuaweicloud.com
huaweicloud-dns.cn
huaweicloud-dns.ru
huaweicloud-dns.com
huaweicloud-dns.org
#################################### ####################################

View File

@@ -13,6 +13,11 @@ opt_strat=$2
if echo "$opt_flags" | grep -q "(reset_ipset)"; then if echo "$opt_flags" | grep -q "(reset_ipset)"; then
restore_all_ipset_cfg restore_all_ipset_cfg
fi fi
if echo "$opt_flags" | grep -q "(erase_autohostlist)"; then
: > $ZAPRET_BASE/ipset/zapret-hosts-auto.txt
: > $ZAPRET_BASE/ipset/zapret-hosts-auto-debug.log
fi
create_default_cfg "$opt_flags" "$opt_strat" create_default_cfg "$opt_flags" "$opt_strat"

View File

@@ -75,9 +75,13 @@ ZAP_PKG_URL=
if command -v apk >/dev/null; then if command -v apk >/dev/null; then
PKG_MGR=apk PKG_MGR=apk
ZAP_PKG_EXT=apk ZAP_PKG_EXT=apk
PKG_CHECK="apk info -e "
PKG_REMOVE="apk del --force "
elif command -v opkg >/dev/null; then elif command -v opkg >/dev/null; then
PKG_MGR=opkg PKG_MGR=opkg
ZAP_PKG_EXT=ipk ZAP_PKG_EXT=ipk
PKG_CHECK="opkg status "
PKG_REMOVE="opkg remove --force-remove "
else else
echo "ERROR: No package manager found" echo "ERROR: No package manager found"
return 1 return 1
@@ -487,7 +491,7 @@ if [ "$opt_update" != "" ]; then
fi fi
fi fi
if ! command -v unzip >/dev/null 2>&1; then if ! command -v unzip >/dev/null 2>&1; then
echo "ERROR: package \"upzip\" not installed!" echo "ERROR: package \"unzip\" not installed!"
return 218 return 218
fi fi
unzip -q "$ZAP_PKG_FN" -d $ZAP_PKG_DIR unzip -q "$ZAP_PKG_FN" -d $ZAP_PKG_DIR
@@ -525,6 +529,14 @@ if [ "$opt_update" != "" ]; then
if [ "$opt_forced" = true ]; then if [ "$opt_forced" = true ]; then
pkg_mgr_update pkg_mgr_update
fi fi
if ${PKG_CHECK} ${ZAPRET_CFG_NAME}-mdig >/dev/null 2>&1; then
echo "Uninstall mdig..."
${PKG_REMOVE} ${ZAPRET_CFG_NAME}-mdig
fi
if ${PKG_CHECK} ${ZAPRET_CFG_NAME}-ip2net >/dev/null 2>&1; then
echo "Uninstall ip2net..."
${PKG_REMOVE} ${ZAPRET_CFG_NAME}-ip2net
fi
echo "Install downloaded packages..." echo "Install downloaded packages..."
if [ "$PKG_MGR" != "apk" ]; then if [ "$PKG_MGR" != "apk" ]; then
opkg install --force-reinstall "$ZAP_PKG_BASE_FN" opkg install --force-reinstall "$ZAP_PKG_BASE_FN"