mirror of
https://github.com/remittor/zapret-openwrt.git
synced 2025-12-31 21:59:06 +03:00
Add support check and install updates from GitHub
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
'require ui';
|
'require ui';
|
||||||
'require view';
|
'require view';
|
||||||
'require view.zapret.tools as tools';
|
'require view.zapret.tools as tools';
|
||||||
|
'require view.zapret.updater as updater';
|
||||||
|
|
||||||
const btn_style_neutral = 'btn';
|
const btn_style_neutral = 'btn';
|
||||||
const btn_style_action = 'btn cbi-button-action';
|
const btn_style_action = 'btn cbi-button-action';
|
||||||
@@ -22,6 +23,7 @@ return view.extend({
|
|||||||
restart : elems.btn_restart || document.getElementById('btn_restart'),
|
restart : elems.btn_restart || document.getElementById('btn_restart'),
|
||||||
stop : elems.btn_stop || document.getElementById('btn_stop'),
|
stop : elems.btn_stop || document.getElementById('btn_stop'),
|
||||||
reset : elems.btn_reset || document.getElementById('btn_reset'),
|
reset : elems.btn_reset || document.getElementById('btn_reset'),
|
||||||
|
update : elems.btn_update || document.getElementById('btn_update'),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@ return view.extend({
|
|||||||
btn.restart.disabled = flag;
|
btn.restart.disabled = flag;
|
||||||
btn.stop.disabled = flag;
|
btn.stop.disabled = flag;
|
||||||
btn.reset.disabled = (error_code == 0) ? flag : false;
|
btn.reset.disabled = (error_code == 0) ? flag : false;
|
||||||
|
btn.update.disabled = (error_code == 0) ? flag : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
getAppStatus: function() {
|
getAppStatus: function() {
|
||||||
@@ -103,6 +106,7 @@ return view.extend({
|
|||||||
}
|
}
|
||||||
let btn = this.get_svc_buttons(elems);
|
let btn = this.get_svc_buttons(elems);
|
||||||
btn.reset.disabled = false;
|
btn.reset.disabled = false;
|
||||||
|
btn.update.disabled = false;
|
||||||
|
|
||||||
if (Number.isInteger(svcinfo)) {
|
if (Number.isInteger(svcinfo)) {
|
||||||
ui.addNotification(null, E('p', _('Error')
|
ui.addNotification(null, E('p', _('Error')
|
||||||
@@ -203,17 +207,7 @@ return view.extend({
|
|||||||
let elem = document.getElementById(button);
|
let elem = document.getElementById(button);
|
||||||
this.disableButtons(true, elem);
|
this.disableButtons(true, elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
poll.stop();
|
poll.stop();
|
||||||
|
|
||||||
if (action === 'update') {
|
|
||||||
this.getAppStatus().then(
|
|
||||||
(status_array) => {
|
|
||||||
this.setAppStatus(status_array, [], 4);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.exec_direct(tools.execPath, [ action ]).then(res => {
|
return fs.exec_direct(tools.execPath, [ action ]).then(res => {
|
||||||
return this.getAppStatus().then(
|
return this.getAppStatus().then(
|
||||||
(status_array) => {
|
(status_array) => {
|
||||||
@@ -387,6 +381,10 @@ return view.extend({
|
|||||||
btn_reset.onclick = L.bind(this.dialogResetCfg, this);
|
btn_reset.onclick = L.bind(this.dialogResetCfg, this);
|
||||||
layout_append(_('Reset settings to default'), null, [ btn_reset ] );
|
layout_append(_('Reset settings to default'), null, [ btn_reset ] );
|
||||||
|
|
||||||
|
let btn_update = create_btn('btn_update', btn_style_action, _('Update'));
|
||||||
|
btn_update.onclick = ui.createHandlerFn(this, () => { updater.openUpdateDialog(this.pkg_arch) });
|
||||||
|
layout_append(_('Update package'), null, [ btn_update ] );
|
||||||
|
|
||||||
let elems = {
|
let elems = {
|
||||||
"status": status_string,
|
"status": status_string,
|
||||||
"btn_enable": btn_enable,
|
"btn_enable": btn_enable,
|
||||||
@@ -395,6 +393,7 @@ return view.extend({
|
|||||||
"btn_restart": btn_restart,
|
"btn_restart": btn_restart,
|
||||||
"btn_stop": btn_stop,
|
"btn_stop": btn_stop,
|
||||||
"btn_reset": btn_reset,
|
"btn_reset": btn_reset,
|
||||||
|
"btn_update": btn_update,
|
||||||
};
|
};
|
||||||
this.setAppStatus(status_array, elems);
|
this.setAppStatus(status_array, elems);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,244 @@
|
|||||||
|
'use strict';
|
||||||
|
'require baseclass';
|
||||||
|
'require fs';
|
||||||
|
'require poll';
|
||||||
|
'require uci';
|
||||||
|
'require ui';
|
||||||
|
'require view';
|
||||||
|
'require view.zapret.tools as tools';
|
||||||
|
|
||||||
|
const btn_style_neutral = 'btn';
|
||||||
|
const btn_style_action = 'btn cbi-button-action';
|
||||||
|
const btn_style_positive = 'btn cbi-button-save important';
|
||||||
|
const btn_style_negative = 'btn cbi-button-reset important';
|
||||||
|
const btn_style_warning = 'btn cbi-button-negative';
|
||||||
|
const btn_style_success = 'btn cbi-button-success important';
|
||||||
|
|
||||||
|
const fn_update_pkg_sh = '/opt/zapret/update-pkg.sh';
|
||||||
|
|
||||||
|
return baseclass.extend({
|
||||||
|
releasesUrlPrefix : 'https://raw.githubusercontent.com/remittor/zapret-openwrt/gh-pages/releases/',
|
||||||
|
|
||||||
|
appendLog: function(msg, end = '\n') {
|
||||||
|
this.logArea.value += msg + end;
|
||||||
|
this.logArea.scrollTop = this.logArea.scrollHeight;
|
||||||
|
},
|
||||||
|
|
||||||
|
setBtnMode: function(enable) {
|
||||||
|
this.btn_cancel.disabled = enable ? false : true;
|
||||||
|
this.btn_action.disabled = (enable == 2) ? false : true;
|
||||||
|
},
|
||||||
|
|
||||||
|
setStage: function(stage, btn_flag = true) {
|
||||||
|
if (stage == 0) {
|
||||||
|
this.btn_action.textContent = _('Check for updates');
|
||||||
|
} else
|
||||||
|
if (stage == 1) {
|
||||||
|
this.btn_action.textContent = _('Update packages');
|
||||||
|
} else {
|
||||||
|
this.btn_action.textContent = _('');
|
||||||
|
}
|
||||||
|
if (stage > 1 && typeof(this.btn_action) == 'object') {
|
||||||
|
this.setBtnMode(1);
|
||||||
|
}
|
||||||
|
this.stage = stage;
|
||||||
|
},
|
||||||
|
|
||||||
|
checkUpdates: function() {
|
||||||
|
this.setStage(0);
|
||||||
|
this.setBtnMode(0);
|
||||||
|
this.pkg_url = null;
|
||||||
|
this.appendLog(_('Checking for updates...'));
|
||||||
|
let opt_list = [ '-c' ]; // check for updates
|
||||||
|
if (document.getElementById('cfg_exclude_prereleases').checked == false) {
|
||||||
|
opt_list.push('-p'); // include prereleases ZIP-files
|
||||||
|
}
|
||||||
|
let forced_reinstall = document.getElementById('cfg_forced_reinstall').checked;
|
||||||
|
let rpc_opt = { timeout: 20*1000 }
|
||||||
|
//rpc_opt.uid = 0; // run under root
|
||||||
|
let res = fs.exec(fn_update_pkg_sh, opt_list, null, rpc_opt).then(res => {
|
||||||
|
let log = res.stdout.trim();
|
||||||
|
this.appendLog(log);
|
||||||
|
let code = log.match(/^RESULT:\s*\(([^)]+)\)\s+.+$/m);
|
||||||
|
let pkg_url = log.match(/^ZAP_PKG_URL\s*=\s*(.+)$/m);
|
||||||
|
if (res.code == 0 && code && pkg_url) {
|
||||||
|
this.pkg_url = pkg_url[1];
|
||||||
|
code = code[1];
|
||||||
|
if (code == 'E' && !forced_reinstall) {
|
||||||
|
this.setStage(999);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
this.setStage(1);
|
||||||
|
this.setBtnMode(2); // enable all buttons
|
||||||
|
} else {
|
||||||
|
if (res.code != 0) {
|
||||||
|
this.appendLog('ERROR: Check for updates failed with error ' + res.code);
|
||||||
|
}
|
||||||
|
this.setStage(999);
|
||||||
|
}
|
||||||
|
return res.code;
|
||||||
|
}).catch(e => {
|
||||||
|
this.appendLog('ERROR: ' + _('Updates checking failed'));
|
||||||
|
this.appendLog('ERROR: ' + e);
|
||||||
|
this.setStage(999);
|
||||||
|
return 1;
|
||||||
|
}).finally(() => {
|
||||||
|
this.appendLog('=========================================================');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
installUpdates: async function() {
|
||||||
|
this.setStage(1);
|
||||||
|
this.setBtnMode(0);
|
||||||
|
if (!this.pkg_url || this.pkg_url.length < 10) {
|
||||||
|
this.appendLog('ERROR: pkg_url = null');
|
||||||
|
this.setStage(999);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
this.appendLog(_('Install updates...'));
|
||||||
|
let opt_list = [ '-u', this.pkg_url ]; // update packages
|
||||||
|
if (document.getElementById('cfg_forced_reinstall').checked == true) {
|
||||||
|
opt_list.push('-f'); // forced reinstall if same version
|
||||||
|
}
|
||||||
|
let rpc_opt = { timeout: 5*1000 }
|
||||||
|
//rpc_opt.uid = 0; // run under root
|
||||||
|
const logFile = '/tmp/zapret_pkg_install.log';
|
||||||
|
const pidFile = '/tmp/zapret_pkg_install.pid';
|
||||||
|
try {
|
||||||
|
await fs.exec('/bin/busybox', [ 'rm', '-f', '/tmp/zapret_pkg_install.*' ], null, rpc_opt);
|
||||||
|
this.appendLog('Install log cleared.');
|
||||||
|
} catch (e) {
|
||||||
|
this.appendLog('ERROR: Failed to clear log file');
|
||||||
|
this.setStage(999);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//console.log(`Start ${fn_update_pkg_sh}...`);
|
||||||
|
try {
|
||||||
|
let opt = [ logFile, pidFile, fn_update_pkg_sh ];
|
||||||
|
//opt.push('-t'); // only for testing
|
||||||
|
opt.push(...opt_list);
|
||||||
|
await fs.exec('/opt/zapret/script-exec.sh', opt, null, rpc_opt);
|
||||||
|
this.appendLog('Process started...');
|
||||||
|
} catch (e) {
|
||||||
|
this.appendLog('ERROR: Failed to start process: ' + e.message);
|
||||||
|
this.setStage(999);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
let lastLen = 0;
|
||||||
|
let pid = 0;
|
||||||
|
//console.log('setInterval...');
|
||||||
|
let timer = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
if (pid == 0) {
|
||||||
|
try {
|
||||||
|
let pid_data = await fs.exec('/bin/cat', [ pidFile ], null, rpc_opt);
|
||||||
|
pid = parseInt(pid_data.stdout.trim(), 10);
|
||||||
|
} catch (e) {
|
||||||
|
//return; // goto next timer iteration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let alive = null;
|
||||||
|
if (pid > 0) {
|
||||||
|
try {
|
||||||
|
await fs.stat(`/proc/${pid}`, [ ], null, { timeout: 4*1000 });
|
||||||
|
alive = true;
|
||||||
|
} catch (e) {
|
||||||
|
// file "/proc/${pid}" not founded ==> sh process terminated
|
||||||
|
alive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res = await fs.exec('/bin/cat', [ logFile ], null, rpc_opt);
|
||||||
|
if (res.stdout.length > lastLen) {
|
||||||
|
let log = res.stdout.slice(lastLen);
|
||||||
|
log = log.replace(/^ \* resolve_conffiles.*(?:\r?\n|$)/gm, '');
|
||||||
|
this.appendLog(log, '');
|
||||||
|
lastLen = res.stdout.length;
|
||||||
|
}
|
||||||
|
if (pid > 0 && !alive) {
|
||||||
|
clearInterval(timer);
|
||||||
|
this.appendLog('\nProcess finished.');
|
||||||
|
let log = res.stdout;
|
||||||
|
let code = log.match(/^RESULT:\s*\(([^)]+)\)\s+.+$/m);
|
||||||
|
if (code && code[1] == '+') {
|
||||||
|
this.setStage(999);
|
||||||
|
this.btn_action.textContent = _('OK');
|
||||||
|
this.btn_action.disabled = false;
|
||||||
|
this.btn_cancel.disabled = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
this.appendLog('ERROR: Install updates failed!');
|
||||||
|
this.setStage(999);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
clearInterval(timer);
|
||||||
|
this.appendLog('ERROR: reading log: ' + e.message);
|
||||||
|
this.setStage(999);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
|
||||||
|
openUpdateDialog: function(pkg_arch) {
|
||||||
|
this.stage = 0;
|
||||||
|
this.pkg_arch = pkg_arch;
|
||||||
|
this.pkg_url = null;
|
||||||
|
|
||||||
|
let exclude_prereleases = E('label', [
|
||||||
|
E('input', { type: 'checkbox', id: 'cfg_exclude_prereleases', checked: true }),
|
||||||
|
' ', _('Exclude PreReleases')
|
||||||
|
]);
|
||||||
|
|
||||||
|
let forced_reinstall = E('label', [
|
||||||
|
E('input', { type: 'checkbox', id: 'cfg_forced_reinstall'}),
|
||||||
|
' ', _('Forced reinstall packages')
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.logArea = E('textarea', {
|
||||||
|
'readonly': true,
|
||||||
|
'style': 'width:100%; height:400px; font-family: monospace;'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.btn_cancel = E('button', {
|
||||||
|
'id': 'btn_cancel',
|
||||||
|
'name': 'btn_cancel',
|
||||||
|
'class': btn_style_warning,
|
||||||
|
}, _('Cancel'));
|
||||||
|
this.btn_cancel.onclick = ui.hideModal;
|
||||||
|
|
||||||
|
this.btn_action = E('button', {
|
||||||
|
'id': 'btn_action',
|
||||||
|
'name': 'btn_action',
|
||||||
|
'class': btn_style_action,
|
||||||
|
}, 'BUTTON_ACTION');
|
||||||
|
this.btn_action.onclick = ui.createHandlerFn(this, () => {
|
||||||
|
if (this.stage == 0) {
|
||||||
|
return this.checkUpdates();
|
||||||
|
}
|
||||||
|
if (this.stage == 1) {
|
||||||
|
return this.installUpdates();
|
||||||
|
}
|
||||||
|
return ui.hideModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setStage(0);
|
||||||
|
this.setBtnMode(2);
|
||||||
|
|
||||||
|
ui.showModal(_('Package update'), [
|
||||||
|
E('div', { 'class': 'cbi-section' }, [
|
||||||
|
E('div', {}, [
|
||||||
|
E('p', {'class': 'cbi-title-field'}, [ 'CPU architecture: ' + pkg_arch ]),
|
||||||
|
]),
|
||||||
|
exclude_prereleases,
|
||||||
|
E('br'), E('br'),
|
||||||
|
forced_reinstall,
|
||||||
|
E('br'), E('br'),
|
||||||
|
E('hr'),
|
||||||
|
this.logArea,
|
||||||
|
]),
|
||||||
|
E('div', { 'class': 'right' }, [
|
||||||
|
this.btn_cancel,
|
||||||
|
' ',
|
||||||
|
this.btn_action,
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
"/usr/bin/apk*": [ "exec" ],
|
"/usr/bin/apk*": [ "exec" ],
|
||||||
"/usr/bin/find*": [ "exec" ],
|
"/usr/bin/find*": [ "exec" ],
|
||||||
"/opt/zapret/restore-def-cfg.sh*": [ "exec" ],
|
"/opt/zapret/restore-def-cfg.sh*": [ "exec" ],
|
||||||
|
"/opt/zapret/script-exec.sh*": [ "exec" ],
|
||||||
|
"/opt/zapret/update-pkg.sh*": [ "exec" ],
|
||||||
"/opt/zapret/sync_config.sh*": [ "exec" ]
|
"/opt/zapret/sync_config.sh*": [ "exec" ]
|
||||||
},
|
},
|
||||||
"uci": [ "zapret", "network" ],
|
"uci": [ "zapret", "network" ],
|
||||||
|
|||||||
@@ -90,6 +90,16 @@ function get_run_on_boot_option
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_cpu_arch
|
||||||
|
{
|
||||||
|
if [ -f /etc/openwrt_release ]; then
|
||||||
|
. /etc/openwrt_release
|
||||||
|
printf '%s' "$DISTRIB_ARCH"
|
||||||
|
else
|
||||||
|
printf 'unknown'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
function restore_ipset_txt
|
function restore_ipset_txt
|
||||||
{
|
{
|
||||||
local cfgname=$1
|
local cfgname=$1
|
||||||
|
|||||||
12
zapret/script-exec.sh
Executable file
12
zapret/script-exec.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright (c) 2024 remittor
|
||||||
|
LOG_FILE=$1
|
||||||
|
PID_FILE=$2
|
||||||
|
shift 2
|
||||||
|
: > $LOG_FILE
|
||||||
|
(
|
||||||
|
exec </dev/null >/dev/null 2>&1
|
||||||
|
"$@" >> $LOG_FILE 2>&1
|
||||||
|
) &
|
||||||
|
echo $! > $PID_FILE
|
||||||
|
exit 0
|
||||||
388
zapret/update-pkg.sh
Executable file
388
zapret/update-pkg.sh
Executable file
@@ -0,0 +1,388 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright (c) 2025 remittor
|
||||||
|
|
||||||
|
. /opt/zapret/comfunc.sh
|
||||||
|
. /usr/share/libubox/jshn.sh
|
||||||
|
|
||||||
|
opt_check=
|
||||||
|
opt_prerelease=
|
||||||
|
opt_update=
|
||||||
|
opt_forced=
|
||||||
|
opt_test=
|
||||||
|
|
||||||
|
while getopts "cu:pft" opt; do
|
||||||
|
case $opt in
|
||||||
|
c) opt_check=true;;
|
||||||
|
p) opt_prerelease=true;;
|
||||||
|
u) opt_update="$OPTARG";;
|
||||||
|
f) opt_forced=true;;
|
||||||
|
t) opt_test=true;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
ZAP_PKG_DIR=/tmp/zapret_pkg
|
||||||
|
|
||||||
|
if [ "$opt_test" = "true" ]; then
|
||||||
|
echo 1; sleep 2;
|
||||||
|
echo 2; sleep 2;
|
||||||
|
echo 3; sleep 2;
|
||||||
|
echo ' * resolve_conffiles 123456'; sleep 1;
|
||||||
|
echo 4; sleep 2;
|
||||||
|
echo END
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZAP_CPU_ARCH=$(get_cpu_arch)
|
||||||
|
ZAP_REL_URL="https://raw.githubusercontent.com/remittor/zapret-openwrt/gh-pages/releases/releases_zap1_$ZAP_CPU_ARCH.json"
|
||||||
|
|
||||||
|
WGET_TIMEOUT=5
|
||||||
|
WGET_HEADER1="Accept: application/json"
|
||||||
|
WGET_HEADER2="Cache-Control: no-cache"
|
||||||
|
|
||||||
|
REL_JSON=
|
||||||
|
REL_ACTUAL_TAG=
|
||||||
|
REL_ACTUAL_PRE=
|
||||||
|
REL_ACTUAL_URL=
|
||||||
|
|
||||||
|
ZAP_OUT=
|
||||||
|
ZAP_ERR=
|
||||||
|
ZAP_PKG_URL=
|
||||||
|
|
||||||
|
function download_json
|
||||||
|
{
|
||||||
|
local url="$1"
|
||||||
|
wget -q -T "$WGET_TIMEOUT" --header="$WGET_HEADER1" --header="$WGET_HEADER2" -O - "$url"
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v apk >/dev/null; then
|
||||||
|
PKG_MGR=apk
|
||||||
|
ZAP_PKG_EXT=apk
|
||||||
|
elif command -v opkg >/dev/null; then
|
||||||
|
PKG_MGR=opkg
|
||||||
|
ZAP_PKG_EXT=ipk
|
||||||
|
else
|
||||||
|
echo "ERROR: No package manager found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function get_pkg_version
|
||||||
|
{
|
||||||
|
local pkg_name="$1"
|
||||||
|
local ver line pkg_prefix
|
||||||
|
if [ "$PKG_MGR" = opkg ]; then
|
||||||
|
ver=$( opkg list-installed "$pkg_name" 2>/dev/null | awk -F' - ' '{print $2}' | tr -d '\r' )
|
||||||
|
if [ -n "$ver" ]; then
|
||||||
|
echo -n "$ver"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$PKG_MGR" = apk ]; then
|
||||||
|
line=$( apk info -e "$pkg_name" 2>/dev/null || true )
|
||||||
|
if [ -n "$line" ]; then
|
||||||
|
pkg_prefix="${pkg_name}-"
|
||||||
|
case "$line" in
|
||||||
|
"$pkg_prefix"*)
|
||||||
|
ver=${line#"$pkg_prefix"}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ver=${line##*-}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo -n "$ver"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalize_version
|
||||||
|
{
|
||||||
|
local ver="$1"
|
||||||
|
local base
|
||||||
|
local major minor rel
|
||||||
|
case "$ver" in
|
||||||
|
*-r*)
|
||||||
|
rel="${ver##*-r}"
|
||||||
|
base="${ver%-r*}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
rel=1
|
||||||
|
base="$ver"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
major="${base%%.*}"
|
||||||
|
minor="${base#*.}"
|
||||||
|
[ -z "$minor" ] && minor=0
|
||||||
|
[ -z "$rel" ] && rel=1
|
||||||
|
echo "$major.$minor.$rel"
|
||||||
|
}
|
||||||
|
|
||||||
|
function pkg_version_cmp
|
||||||
|
{
|
||||||
|
local ver1=$( normalize_version "$1" )
|
||||||
|
local ver2=$( normalize_version "$2" )
|
||||||
|
local x1 x2
|
||||||
|
# major
|
||||||
|
x1=$( echo "$ver1" | cut -d. -f1 )
|
||||||
|
x2=$( echo "$ver2" | cut -d. -f1 )
|
||||||
|
[ "$x1" -gt "$x2" ] && { echo -n "G"; return 0; }
|
||||||
|
[ "$x1" -lt "$x2" ] && { echo -n "L"; return 0; }
|
||||||
|
# minor
|
||||||
|
x1=$( echo "$ver1" | cut -d. -f2 )
|
||||||
|
x2=$( echo "$ver2" | cut -d. -f2 )
|
||||||
|
[ "$x1" -gt "$x2" ] && { echo -n "G"; return 0; }
|
||||||
|
[ "$x1" -lt "$x2" ] && { echo -n "L"; return 0; }
|
||||||
|
# release
|
||||||
|
x1=$( echo "$ver1" | cut -d. -f3 )
|
||||||
|
x2=$( echo "$ver2" | cut -d. -f3 )
|
||||||
|
[ "$x1" -gt "$x2" ] && { echo -n "G"; return 0; }
|
||||||
|
[ "$x1" -lt "$x2" ] && { echo -n "L"; return 0; }
|
||||||
|
echo -n "E"
|
||||||
|
}
|
||||||
|
|
||||||
|
function download_releases_info
|
||||||
|
{
|
||||||
|
local txt txtlen txtlines generated_at
|
||||||
|
REL_JSON=
|
||||||
|
echo "CPU arch: $ZAP_CPU_ARCH"
|
||||||
|
echo "Download releases info..."
|
||||||
|
txt=$(download_json $ZAP_REL_URL)
|
||||||
|
txtlen=${#txt}
|
||||||
|
txtlines=$(printf '%s\n' "$txt" | wc -l)
|
||||||
|
if [[ $txtlen -lt 64 ]]; then
|
||||||
|
echo "ERROR: Cannot download releases info!"
|
||||||
|
return 104
|
||||||
|
fi
|
||||||
|
echo "Releases info downloaded! Size = $txtlen, Lines = $txtlines"
|
||||||
|
generated_at=$(printf '%s\n' "$txt" | grep -m1 -o '"generated_at"[[:space:]]*:[[:space:]]*".*"' | cut -d'"' -f4)
|
||||||
|
if [[ "$generated_at" = "" ]]; then
|
||||||
|
echo "ERROR: Cannot download releases info! (incorrect generated_at)"
|
||||||
|
return 105
|
||||||
|
fi
|
||||||
|
echo "Releases info generated_at = $generated_at"
|
||||||
|
REL_JSON="$txt"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_actual_release
|
||||||
|
{
|
||||||
|
local tag url pre idx_list
|
||||||
|
REL_ACTUAL_TAG=
|
||||||
|
REL_ACTUAL_PRE=
|
||||||
|
REL_ACTUAL_URL=
|
||||||
|
json_load "$(printf '%s' "$REL_JSON")"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: incorrect format of ${ZAP_REL_URL##*/}"
|
||||||
|
json_cleanup
|
||||||
|
return 151
|
||||||
|
fi
|
||||||
|
json_select releases
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: incorrect format of ${ZAP_REL_URL##*/}"
|
||||||
|
json_cleanup
|
||||||
|
return 157
|
||||||
|
fi
|
||||||
|
json_get_keys idx_list
|
||||||
|
# array already sorted by created_at => take first elem
|
||||||
|
for rel_id in $idx_list; do
|
||||||
|
json_select "$rel_id" # enter into releases[rel_id]
|
||||||
|
json_get_var tag tag
|
||||||
|
json_get_var pre prerelease
|
||||||
|
#echo "rel_id = $rel_id opt_prerelease = $opt_prerelease pre = $pre"
|
||||||
|
if [ "$opt_prerelease" != "true" ] && [ "$pre" = "1" ]; then
|
||||||
|
json_select .. # exit from releases[rel_id]
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
json_select assets
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: release[$rel_id] has not include 'assets'"
|
||||||
|
json_cleanup
|
||||||
|
return 160
|
||||||
|
fi
|
||||||
|
json_select 0 > /dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
json_select 1 > /dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: release[$rel_id] include incorrect 'assets'"
|
||||||
|
json_cleanup
|
||||||
|
return 162
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
json_get_var url browser_download_url
|
||||||
|
json_select .. .. .. # assets-elem -> assets -> releases[rel_id] -> releases
|
||||||
|
json_cleanup
|
||||||
|
REL_ACTUAL_TAG="$tag"
|
||||||
|
REL_ACTUAL_PRE="$pre"
|
||||||
|
REL_ACTUAL_URL="$url"
|
||||||
|
return 0
|
||||||
|
done
|
||||||
|
json_cleanup
|
||||||
|
echo "ERROR: latest release for arch \"$ZAP_CPU_ARCH\" not founded!"
|
||||||
|
return 1 # release not founded
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ "$opt_check" != "true" -a "$opt_update" = "" ]; then
|
||||||
|
echo 'ERROR: Incorrect arguments'
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$opt_update" = "@" ]; then
|
||||||
|
opt_check="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$opt_check" = "true" ]; then
|
||||||
|
download_releases_info
|
||||||
|
ZAP_ERR=$?
|
||||||
|
if [ $ZAP_ERR -ne 0 ]; then
|
||||||
|
echo "ERROR: Func download_releases_info return error code: $ZAP_ERR"
|
||||||
|
return $ZAP_ERR
|
||||||
|
fi
|
||||||
|
get_actual_release
|
||||||
|
ZAP_ERR=$?
|
||||||
|
if [ $ZAP_ERR -ne 0 ]; then
|
||||||
|
echo "ERROR: Func get_actual_release return error code: $ZAP_ERR"
|
||||||
|
return $ZAP_ERR
|
||||||
|
fi
|
||||||
|
echo "Latest package version: $REL_ACTUAL_TAG"
|
||||||
|
echo "Latest package url: $REL_ACTUAL_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZAP_PKG_SIZE=
|
||||||
|
ZAP_PKG_SZ=
|
||||||
|
ZAP_PKG_ZIP_NAME=
|
||||||
|
ZAP_PKG_FN=
|
||||||
|
ZAP_PKG_BASE_FN=
|
||||||
|
ZAP_PKG_LUCI_FN=
|
||||||
|
|
||||||
|
ZAP_CUR_PKG_VER=$( get_pkg_version zapret )
|
||||||
|
echo "Current installed version: $ZAP_CUR_PKG_VER"
|
||||||
|
|
||||||
|
if [ "$opt_update" = "" ]; then
|
||||||
|
ZAP_PKG_URL="$REL_ACTUAL_URL"
|
||||||
|
if [ "$ZAP_PKG_URL" = "" ]; then
|
||||||
|
echo "ERROR: actual release not founded!"
|
||||||
|
return 199
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
ZAP_PKG_URL="$opt_update"
|
||||||
|
if [ "$opt_update" = "@" ]; then
|
||||||
|
ZAP_PKG_URL="$REL_ACTUAL_URL"
|
||||||
|
fi
|
||||||
|
if [ "$opt_update" = "@" -a "$ZAP_PKG_URL" = "" ]; then
|
||||||
|
echo "ERROR: actual release not founded!"
|
||||||
|
return 199
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZAP_PKG_ZIP_NAME=${ZAP_PKG_URL##*/}
|
||||||
|
ZAP_PKG_ZIP_VER=${ZAP_PKG_ZIP_NAME#*_v}
|
||||||
|
ZAP_PKG_ZIP_VER=${ZAP_PKG_ZIP_VER%%_*}
|
||||||
|
|
||||||
|
if [ "$opt_update" != "" ]; then
|
||||||
|
if [ "$opt_update" = "@" ]; then
|
||||||
|
echo "Latest available version: $ZAP_PKG_ZIP_VER"
|
||||||
|
else
|
||||||
|
echo "Target requested version: $ZAP_PKG_ZIP_VER"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "ZAP_PKG_URL = $ZAP_PKG_URL"
|
||||||
|
|
||||||
|
ZAP_VER_CMP=$( pkg_version_cmp "$ZAP_CUR_PKG_VER" "$ZAP_PKG_ZIP_VER" )
|
||||||
|
if [ "$opt_update" = "" ]; then
|
||||||
|
if [ "$ZAP_VER_CMP" = "E" ]; then
|
||||||
|
echo "RESULT: (E) No update required for this package!"
|
||||||
|
elif [ "$ZAP_VER_CMP" = "G" ]; then
|
||||||
|
echo "RESULT: (G) You have a newer version installed than the one on GitHub!"
|
||||||
|
elif [ "$ZAP_VER_CMP" = "L" ]; then
|
||||||
|
echo "RESULT: (L) You have an older version installed than the one on GitHub!"
|
||||||
|
else
|
||||||
|
echo "ERROR: ZAP_PKG_ZIP_VER='$ZAP_PKG_ZIP_VER' ZAP_VER_CMP='$ZAP_VER_CMP'"
|
||||||
|
return 199
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$opt_update" != "" ]; then
|
||||||
|
if [ "$opt_forced" != "true" ]; then
|
||||||
|
if [ "$ZAP_VER_CMP" = "E" ]; then
|
||||||
|
echo "RESULT: (E) No update required for this package!"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
ZAP_PKG_DIR=/tmp/zapret_pkg
|
||||||
|
rm -rf $ZAP_PKG_DIR
|
||||||
|
ZAP_PKG_SIZE=$( wget --spider -T $WGET_TIMEOUT --header="$WGET_HEADER2" -S "$ZAP_PKG_URL" 2>&1 | grep -i 'Content-Length:' | tail -n1 | awk '{print $2}' | tr -d '\r' )
|
||||||
|
echo "Downloded ZIP-file size = $ZAP_PKG_SIZE bytes"
|
||||||
|
[ "$ZAP_PKG_SIZE" = "" ] || [[ $ZAP_PKG_SIZE -lt 256 ]] && {
|
||||||
|
echo "ERROR: incorrect package size!"
|
||||||
|
return 210
|
||||||
|
}
|
||||||
|
mkdir $ZAP_PKG_DIR
|
||||||
|
ZAP_PKG_FN="$ZAP_PKG_DIR/${ZAP_PKG_URL##*/}"
|
||||||
|
echo "Download ZIP-file..."
|
||||||
|
wget -q -T 15 --header="$WGET_HEADER2" -O "$ZAP_PKG_FN" "$ZAP_PKG_URL"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: cannot download package!"
|
||||||
|
return 215
|
||||||
|
fi
|
||||||
|
ZAP_PKG_SZ=$( wc -c < "$ZAP_PKG_FN" )
|
||||||
|
if [ "$ZAP_PKG_SZ" != "$ZAP_PKG_SIZE" ]; then
|
||||||
|
echo "ERROR: downloaded package is incorrect!"
|
||||||
|
return 216
|
||||||
|
fi
|
||||||
|
unzip -q "$ZAP_PKG_FN" -d $ZAP_PKG_DIR
|
||||||
|
rm -f "$ZAP_PKG_FN"
|
||||||
|
if [ "$PKG_MGR" = "apk" ]; then
|
||||||
|
if [ ! -d "$ZAP_PKG_DIR/apk" ]; then
|
||||||
|
echo "ERROR: APK-files not founded"
|
||||||
|
return 221
|
||||||
|
fi
|
||||||
|
rm -f "$ZAP_PKG_DIR/*.ipk"
|
||||||
|
mv "$ZAP_PKG_DIR/apk/*" "$ZAP_PKG_DIR/"
|
||||||
|
else
|
||||||
|
rm -rf "$ZAP_PKG_DIR/apk"
|
||||||
|
fi
|
||||||
|
ZAP_PKG_LIST=$( ls -1 "$ZAP_PKG_DIR" )
|
||||||
|
echo "------ Downloaded packages:"
|
||||||
|
echo "$ZAP_PKG_LIST"
|
||||||
|
echo "------"
|
||||||
|
ZAP_PKG_BASE_FN=$( find "$ZAP_PKG_DIR" -maxdepth 1 -type f -name "zapret_*.${ZAP_PKG_EXT}" | head -n 1 )
|
||||||
|
ZAP_PKG_LUCI_FN=$( find "$ZAP_PKG_DIR" -maxdepth 1 -type f -name "luci-app-*.${ZAP_PKG_EXT}" | head -n 1 )
|
||||||
|
if [ ! -f "$ZAP_PKG_BASE_FN" ]; then
|
||||||
|
echo "ERROR: File \"zapret_*.${ZAP_PKG_EXT}\" not found!"
|
||||||
|
return 231
|
||||||
|
fi
|
||||||
|
echo "ZAP_PKG_BASE_FN = $ZAP_PKG_BASE_FN"
|
||||||
|
if [ ! -f "$ZAP_PKG_LUCI_FN" ]; then
|
||||||
|
echo "ERROR: File \"luci-app-*.${ZAP_PKG_EXT}\" not found!"
|
||||||
|
return 232
|
||||||
|
fi
|
||||||
|
echo "ZAP_PKG_LUCI_FN = $ZAP_PKG_LUCI_FN"
|
||||||
|
echo "Install downloaded packages..."
|
||||||
|
if [ "$PKG_MGR" != "apk" ]; then
|
||||||
|
opkg install --force-reinstall "$ZAP_PKG_BASE_FN"
|
||||||
|
else
|
||||||
|
apk add --allow-untrusted --upgrade "$ZAP_PKG_BASE_FN"
|
||||||
|
fi
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to install package $ZAP_PKG_BASE_FN"
|
||||||
|
return 245
|
||||||
|
fi
|
||||||
|
if [ "$PKG_MGR" != "apk" ]; then
|
||||||
|
opkg install --force-reinstall "$ZAP_PKG_LUCI_FN"
|
||||||
|
else
|
||||||
|
apk add --allow-untrusted --upgrade "$ZAP_PKG_LUCI_FN"
|
||||||
|
fi
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to install package $ZAP_PKG_LUCI_FN"
|
||||||
|
return 247
|
||||||
|
fi
|
||||||
|
echo "RESULT: (+) Packages from $ZAP_PKG_ZIP_NAME successfully installed!"
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user