diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js
index 020ea3e01..be47bd5ef 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2022-2023 ImmortalWrt.org
+ * Copyright (C) 2022-2025 ImmortalWrt.org
*/
'use strict';
@@ -73,7 +73,7 @@ return baseclass.extend({
}
}),
- calcStringMD5: function(e) {
+ calcStringMD5(e) {
/* Thanks to https://stackoverflow.com/a/41602636 */
function h(a, b) {
var c, d, e, f, g;
@@ -154,7 +154,7 @@ return baseclass.extend({
return (p(a) + p(b) + p(c) + p(d)).toLowerCase();
},
- decodeBase64Str: function(str) {
+ decodeBase64Str(str) {
if (!str)
return null;
@@ -169,7 +169,7 @@ return baseclass.extend({
).join(''));
},
- getBuiltinFeatures: function() {
+ getBuiltinFeatures() {
const callGetSingBoxFeatures = rpc.declare({
object: 'luci.homeproxy',
method: 'singbox_get_features',
@@ -179,7 +179,7 @@ return baseclass.extend({
return L.resolveDefault(callGetSingBoxFeatures(), {});
},
- generateRand: function(type, length) {
+ generateRand(type, length) {
var byteArr;
if (['base64', 'hex'].includes(type))
byteArr = crypto.getRandomValues(new Uint8Array(length));
@@ -201,7 +201,7 @@ return baseclass.extend({
};
},
- loadDefaultLabel: function(uciconfig, ucisection) {
+ loadDefaultLabel(uciconfig, ucisection) {
var label = uci.get(uciconfig, ucisection, 'label');
if (label) {
return label;
@@ -211,12 +211,12 @@ return baseclass.extend({
}
},
- loadModalTitle: function(title, addtitle, uciconfig, ucisection) {
+ loadModalTitle(title, addtitle, uciconfig, ucisection) {
var label = uci.get(uciconfig, ucisection, 'label');
return label ? title + ' » ' + label : addtitle;
},
- renderSectionAdd: function(section, extra_class) {
+ renderSectionAdd(section, extra_class) {
var el = form.GridSection.prototype.renderSectionAdd.apply(section, [ extra_class ]),
nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, (v) => {
@@ -238,7 +238,7 @@ return baseclass.extend({
return el;
},
- uploadCertificate: function(option, type, filename, ev) {
+ uploadCertificate(_option, type, filename, ev) {
const callWriteCertificate = rpc.declare({
object: 'luci.homeproxy',
method: 'certificate_write',
@@ -247,7 +247,7 @@ return baseclass.extend({
});
return ui.uploadFile('/tmp/homeproxy_certificate.tmp', ev.target)
- .then(L.bind((btn, res) => {
+ .then(L.bind((_btn, res) => {
return L.resolveDefault(callWriteCertificate(filename), {}).then((ret) => {
if (ret.result === true)
ui.addNotification(null, E('p', _('Your %s was successfully uploaded. Size: %sB.').format(type, res.size)));
@@ -258,7 +258,7 @@ return baseclass.extend({
.catch((e) => { ui.addNotification(null, E('p', e.message)) });
},
- validateBase64Key: function(length, section_id, value) {
+ validateBase64Key(length, section_id, value) {
/* Thanks to luci-proto-wireguard */
if (section_id && value)
if (value.length !== length || !value.match(/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/) || value[length-1] !== '=')
@@ -267,7 +267,7 @@ return baseclass.extend({
return true;
},
- validateCertificatePath: function(section_id, value) {
+ validateCertificatePath(section_id, value) {
if (section_id && value)
if (!value.match(/^(\/etc\/homeproxy\/certs\/|\/etc\/acme\/|\/etc\/ssl\/).+$/))
return _('Expecting: %s').format(_('/etc/homeproxy/certs/..., /etc/acme/..., /etc/ssl/...'));
@@ -275,7 +275,7 @@ return baseclass.extend({
return true;
},
- validateUniqueValue: function(uciconfig, ucisection, ucioption, section_id, value) {
+ validateUniqueValue(uciconfig, ucisection, ucioption, section_id, value) {
if (section_id) {
if (!value)
return _('Expecting: %s').format(_('non-empty value'));
@@ -295,7 +295,7 @@ return baseclass.extend({
return true;
},
- validateUUID: function(section_id, value) {
+ validateUUID(section_id, value) {
if (section_id) {
if (!value)
return _('Expecting: %s').format(_('non-empty value'));
diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js
index 16e6b996f..8b5474a4c 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2022-2023 ImmortalWrt.org
+ * Copyright (C) 2022-2025 ImmortalWrt.org
*/
'use strict';
@@ -40,7 +40,7 @@ const callWriteDomainList = rpc.declare({
function getServiceStatus() {
return L.resolveDefault(callServiceList('homeproxy'), {}).then((res) => {
- var isRunning = false;
+ let isRunning = false;
try {
isRunning = res['homeproxy']['instances']['sing-box-c']['running'];
} catch (e) { }
@@ -49,8 +49,8 @@ function getServiceStatus() {
}
function renderStatus(isRunning, version) {
- var spanTemp = '%s (sing-box v%s) %s';
- var renderHTML;
+ let spanTemp = '%s (sing-box v%s) %s';
+ let renderHTML;
if (isRunning)
renderHTML = spanTemp.format('green', _('HomeProxy'), version, _('RUNNING'));
else
@@ -78,21 +78,21 @@ function validatePortRange(section_id, value) {
return true;
}
-var stubValidator = {
+let stubValidator = {
factory: validation,
- apply: function(type, value, args) {
+ apply(type, value, args) {
if (value != null)
this.value = value;
return validation.types[type].apply(this, args);
},
- assert: function(condition) {
+ assert(condition) {
return !!condition;
}
};
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('homeproxy'),
hp.getBuiltinFeatures(),
@@ -100,16 +100,16 @@ return view.extend({
]);
},
- render: function(data) {
+ render(data) {
let m, s, o, ss, so;
- var features = data[1],
+ let features = data[1],
hosts = data[2]?.hosts;
/* Cache all configured proxy nodes, they will be called multiple times */
- var proxy_nodes = {};
+ let proxy_nodes = {};
uci.sections(data[0], 'node', (res) => {
- var nodeaddr = ((res.type === 'direct') ? res.override_address : res.address) || '',
+ let nodeaddr = ((res.type === 'direct') ? res.override_address : res.address) || '',
nodeport = ((res.type === 'direct') ? res.override_port : res.port) || '';
proxy_nodes[res['.name']] =
@@ -124,7 +124,7 @@ return view.extend({
s.render = function () {
poll.add(function () {
return L.resolveDefault(getServiceStatus()).then((res) => {
- var view = document.getElementById('service_status');
+ let view = document.getElementById('service_status');
view.innerHTML = renderStatus(res, features.version);
});
});
@@ -140,7 +140,7 @@ return view.extend({
o = s.taboption('routing', form.ListValue, 'main_node', _('Main node'));
o.value('nil', _('Disable'));
- for (var i in proxy_nodes)
+ for (let i in proxy_nodes)
o.value(i, proxy_nodes[i]);
o.default = 'nil';
o.depends({'routing_mode': 'custom', '!reverse': true});
@@ -149,7 +149,7 @@ return view.extend({
o = s.taboption('routing', form.ListValue, 'main_udp_node', _('Main UDP node'));
o.value('nil', _('Disable'));
o.value('same', _('Same as main node'));
- for (var i in proxy_nodes)
+ for (let i in proxy_nodes)
o.value(i, proxy_nodes[i]);
o.default = 'nil';
o.depends({'routing_mode': /^((?!custom).)+$/, 'proxy_mode': /^((?!redirect$).)+$/});
@@ -173,9 +173,9 @@ return view.extend({
if (!value)
return _('Expecting: %s').format(_('non-empty value'));
- var ipv6_support = this.map.lookupOption('ipv6_support', section_id)[0].formvalue(section_id);
+ let ipv6_support = this.map.lookupOption('ipv6_support', section_id)[0].formvalue(section_id);
try {
- var url = new URL(value);
+ let url = new URL(value);
if (stubValidator.apply('hostname', url.hostname))
return true;
else if (stubValidator.apply('ip4addr', url.hostname))
@@ -209,7 +209,7 @@ return view.extend({
return _('Expecting: %s').format(_('non-empty value'));
try {
- var url = new URL(value);
+ let url = new URL(value);
if (stubValidator.apply('hostname', url.hostname))
return true;
else if (stubValidator.apply('ip4addr', url.hostname))
@@ -247,8 +247,8 @@ return view.extend({
o.validate = function(section_id, value) {
if (section_id && value && value !== 'common') {
- var ports = [];
- for (var i of value.split(',')) {
+ let ports = [];
+ for (let i of value.split(',')) {
if (!stubValidator.apply('port', i) && !stubValidator.apply('portrange', i))
return _('Expecting: %s').format(_('valid port value'));
if (ports.includes(i))
@@ -301,7 +301,7 @@ return view.extend({
so.depends('homeproxy.config.proxy_mode', 'tun');
so.rmempty = false;
so.onchange = function(ev, section_id, value) {
- var desc = ev.target.nextElementSibling;
+ let desc = ev.target.nextElementSibling;
if (value === 'mixed')
desc.innerHTML = _('Mixed system
TCP stack and gVisor
UDP stack.')
else if (value === 'gvisor')
@@ -333,7 +333,7 @@ return view.extend({
so = ss.option(form.ListValue, 'domain_strategy', _('Domain strategy'),
_('If set, the requested domain name will be resolved to IP before routing.'));
- for (var i in hp.dns_strategy)
+ for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i])
so = ss.option(form.Flag, 'sniff_override', _('Override destination'),
@@ -387,14 +387,14 @@ return view.extend({
so = ss.option(form.ListValue, 'node', _('Node'),
_('Outbound node'));
so.value('urltest', _('URLTest'));
- for (var i in proxy_nodes)
+ for (let i in proxy_nodes)
so.value(i, proxy_nodes[i]);
so.validate = L.bind(hp.validateUniqueValue, this, data[0], 'routing_node', 'node');
so.editable = true;
so = ss.option(form.ListValue, 'domain_strategy', _('Domain strategy'),
_('If set, the server domain name will be resolved to IP before connecting.
'));
- for (var i in hp.dns_strategy)
+ for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]);
so.depends({'node': 'urltest', '!reverse': true});
so.modalonly = true;
@@ -422,9 +422,9 @@ return view.extend({
}
so.validate = function(section_id, value) {
if (section_id && value) {
- var node = this.map.lookupOption('node', section_id)[0].formvalue(section_id);
+ let node = this.map.lookupOption('node', section_id)[0].formvalue(section_id);
- var conflict = false;
+ let conflict = false;
uci.sections(data[0], 'routing_node', (res) => {
if (res['.name'] !== section_id) {
if (res.outbound === section_id && res['.name'] == value)
@@ -444,7 +444,7 @@ return view.extend({
so = ss.option(hp.CBIStaticList, 'urltest_nodes', _('URLTest nodes'),
_('List of nodes to test.'));
- for (var i in proxy_nodes)
+ for (let i in proxy_nodes)
so.value(i, proxy_nodes[i]);
so.depends('node', 'urltest');
so.modalonly = true;
@@ -454,7 +454,7 @@ return view.extend({
so.validate = function(section_id, value) {
if (section_id && value) {
try {
- var url = new URL(value);
+ let url = new URL(value);
if (!url.hostname)
return _('Expecting: %s').format(_('valid URL'));
}
@@ -473,7 +473,7 @@ return view.extend({
so.datatype = 'uinteger';
so.validate = function(section_id, value) {
if (section_id && value) {
- var idle_timeout = this.map.lookupOption('urltest_idle_timeout', section_id)[0].formvalue(section_id) || '1800';
+ let idle_timeout = this.map.lookupOption('urltest_idle_timeout', section_id)[0].formvalue(section_id) || '1800';
if (parseInt(value) > parseInt(idle_timeout))
return _('Test interval must be less or equal than idle timeout.');
}
@@ -706,7 +706,7 @@ return view.extend({
ss = o.subsection;
so = ss.option(form.ListValue, 'default_strategy', _('Default DNS strategy'),
_('The DNS strategy for resolving the domain name in the address.'));
- for (var i in hp.dns_strategy)
+ for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]);
so = ss.option(form.ListValue, 'default_server', _('Default DNS server'));
@@ -788,7 +788,7 @@ return view.extend({
return _('Expecting: %s').format(_('non-empty value'));
try {
- var url = new URL(value);
+ let url = new URL(value);
if (stubValidator.apply('hostname', url.hostname))
return true;
else if (stubValidator.apply('ip4addr', url.hostname))
@@ -824,7 +824,7 @@ return view.extend({
}
so.validate = function(section_id, value) {
if (section_id && value) {
- var conflict = false;
+ let conflict = false;
uci.sections(data[0], 'dns_server', (res) => {
if (res['.name'] !== section_id)
if (res.address_resolver === section_id && res['.name'] == value)
@@ -840,13 +840,13 @@ return view.extend({
so = ss.option(form.ListValue, 'address_strategy', _('Address strategy'),
_('The domain strategy for resolving the domain name in the address.'));
- for (var i in hp.dns_strategy)
+ for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]);
so.modalonly = true;
so = ss.option(form.ListValue, 'resolve_strategy', _('Resolve strategy'),
_('Default domain strategy for resolving the domain names.'));
- for (var i in hp.dns_strategy)
+ for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]);
so.editable = true;
@@ -1150,7 +1150,7 @@ return view.extend({
return _('Expecting: %s').format(_('non-empty value'));
try {
- var url = new URL(value);
+ let url = new URL(value);
if (!url.hostname)
return _('Expecting: %s').format(_('valid URL'));
}
@@ -1278,20 +1278,24 @@ return view.extend({
so.monospace = true;
so.datatype = 'hostname';
so.depends({'homeproxy.config.routing_mode': 'custom', '!reverse': true});
- so.load = function(section_id) {
+ so.load = function(/* ... */) {
return L.resolveDefault(callReadDomainList('proxy_list')).then((res) => {
return res.content;
}, {});
}
- so.write = function(section_id, value) {
+ so.write = function(_section_id, value) {
return callWriteDomainList('proxy_list', value);
}
- so.remove = function(section_id, value) {
- return callWriteDomainList('proxy_list', '');
+ so.remove = function(/* ... */) {
+ let routing_mode = this.map.lookupOption('routing_mode', 'config')[0].formvalue('config');
+
+ if (routing_mode !== 'custom')
+ return callWriteDomainList('proxy_list', '');
+ return true;
}
so.validate = function(section_id, value) {
if (section_id && value)
- for (var i of value.split('\n'))
+ for (let i of value.split('\n'))
if (i && !stubValidator.apply('hostname', i))
return _('Expecting: %s').format(_('valid hostname'));
@@ -1307,20 +1311,24 @@ return view.extend({
so.monospace = true;
so.datatype = 'hostname';
so.depends({'homeproxy.config.routing_mode': 'custom', '!reverse': true});
- so.load = function(section_id) {
+ so.load = function(/* ... */) {
return L.resolveDefault(callReadDomainList('direct_list')).then((res) => {
return res.content;
}, {});
}
- so.write = function(section_id, value) {
+ so.write = function(_section_id, value) {
return callWriteDomainList('direct_list', value);
}
- so.remove = function(section_id, value) {
- return callWriteDomainList('direct_list', '');
+ so.remove = function(/* ... */) {
+ let routing_mode = this.map.lookupOption('routing_mode', 'config')[0].formvalue('config');
+
+ if (routing_mode !== 'custom')
+ return callWriteDomainList('direct_list', '');
+ return true;
}
so.validate = function(section_id, value) {
if (section_id && value)
- for (var i of value.split('\n'))
+ for (let i of value.split('\n'))
if (i && !stubValidator.apply('hostname', i))
return _('Expecting: %s').format(_('valid hostname'));
diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js
index 31ce172ec..b108137bd 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2022-2024 ImmortalWrt.org
+ * Copyright (C) 2022-2025 ImmortalWrt.org
*/
'use strict';
@@ -14,20 +14,20 @@
'require homeproxy as hp';
'require tools.widgets as widgets';
-function allowInsecureConfirm(ev, section_id, value) {
+function allowInsecureConfirm(ev, _section_id, value) {
if (value === '1' && !confirm(_('Are you sure to allow insecure?')))
ev.target.firstElementChild.checked = null;
}
function parseShareLink(uri, features) {
- var config;
+ let config, url, params;
uri = uri.split('://');
if (uri[0] && uri[1]) {
switch (uri[0]) {
case 'http':
case 'https':
- var url = new URL('http://' + uri[1]);
+ url = new URL('http://' + uri[1]);
config = {
label: url.hash ? decodeURIComponent(url.hash.slice(1)) : null,
@@ -42,8 +42,8 @@ function parseShareLink(uri, features) {
break;
case 'hysteria':
/* https://github.com/HyNetwork/hysteria/wiki/URI-Scheme */
- var url = new URL('http://' + uri[1]);
- var params = url.searchParams;
+ url = new URL('http://' + uri[1]);
+ params = url.searchParams;
/* WeChat-Video / FakeTCP are unsupported by sing-box currently */
if (!features.with_quic || (params.get('protocol') && params.get('protocol') !== 'udp'))
@@ -70,8 +70,8 @@ function parseShareLink(uri, features) {
case 'hysteria2':
case 'hy2':
/* https://v2.hysteria.network/docs/developers/URI-Scheme/ */
- var url = new URL('http://' + uri[1]);
- var params = url.searchParams;
+ url = new URL('http://' + uri[1]);
+ params = url.searchParams;
if (!features.with_quic)
return null;
@@ -97,7 +97,7 @@ function parseShareLink(uri, features) {
case 'socks4a':
case 'socsk5':
case 'socks5h':
- var url = new URL('http://' + uri[1]);
+ url = new URL('http://' + uri[1]);
config = {
label: url.hash ? decodeURIComponent(url.hash.slice(1)) : null,
@@ -114,7 +114,7 @@ function parseShareLink(uri, features) {
try {
/* "Lovely" Shadowrocket format */
try {
- var suri = uri[1].split('#'), slabel = '';
+ let suri = uri[1].split('#'), slabel = '';
if (suri.length <= 2) {
if (suri.length === 2)
slabel = '#' + suri[1];
@@ -123,9 +123,9 @@ function parseShareLink(uri, features) {
} catch(e) { }
/* SIP002 format https://shadowsocks.org/guide/sip002.html */
- var url = new URL('http://' + uri[1]);
+ url = new URL('http://' + uri[1]);
- var userinfo;
+ let userinfo;
if (url.username && url.password)
/* User info encoded with URIComponent */
userinfo = [url.username, decodeURIComponent(url.password)];
@@ -136,9 +136,9 @@ function parseShareLink(uri, features) {
if (!hp.shadowsocks_encrypt_methods.includes(userinfo[0]))
return null;
- var plugin, plugin_opts;
+ let plugin, plugin_opts;
if (url.search && url.searchParams.get('plugin')) {
- var plugin_info = url.searchParams.get('plugin').split(';');
+ let plugin_info = url.searchParams.get('plugin').split(';');
plugin = plugin_info[0];
plugin_opts = plugin_info.slice(1) ? plugin_info.slice(1).join(';') : null;
}
@@ -173,8 +173,8 @@ function parseShareLink(uri, features) {
break;
case 'trojan':
/* https://p4gefau1t.github.io/trojan-go/developer/url/ */
- var url = new URL('http://' + uri[1]);
- var params = url.searchParams;
+ url = new URL('http://' + uri[1]);
+ params = url.searchParams;
/* Check if password exists */
if (!url.username)
@@ -208,8 +208,8 @@ function parseShareLink(uri, features) {
break;
case 'tuic':
/* https://github.com/daeuniverse/dae/discussions/182 */
- var url = new URL('http://' + uri[1]);
- var params = url.searchParams;
+ url = new URL('http://' + uri[1]);
+ params = url.searchParams;
/* Check if uuid exists */
if (!url.username)
@@ -232,8 +232,8 @@ function parseShareLink(uri, features) {
break;
case 'vless':
/* https://github.com/XTLS/Xray-core/discussions/716 */
- var url = new URL('http://' + uri[1]);
- var params = url.searchParams;
+ url = new URL('http://' + uri[1]);
+ params = url.searchParams;
/* Unsupported protocol */
if (params.get('type') === 'kcp')
@@ -356,7 +356,7 @@ function parseShareLink(uri, features) {
}
function renderNodeSettings(section, data, features, main_node, routing_mode) {
- var s = section, o;
+ let s = section, o;
s.rowcolors = true;
s.sortable = true;
s.nodescriptions = true;
@@ -439,12 +439,12 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.depends({'type': 'socks', 'socks_version': '5'});
o.validate = function(section_id, value) {
if (section_id) {
- var type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
- var required_type = [ 'shadowsocks', 'shadowtls', 'trojan' ];
+ let type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
+ let required_type = [ 'shadowsocks', 'shadowtls', 'trojan' ];
if (required_type.includes(type)) {
if (type === 'shadowsocks') {
- var encmode = this.map.lookupOption('shadowsocks_encrypt_method', section_id)[0].formvalue(section_id);
+ let encmode = this.map.lookupOption('shadowsocks_encrypt_method', section_id)[0].formvalue(section_id);
if (encmode === 'none')
return true;
}
@@ -546,7 +546,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
/* Shadowsocks config start */
o = s.option(form.ListValue, 'shadowsocks_encrypt_method', _('Encrypt method'));
- for (var i of hp.shadowsocks_encrypt_methods)
+ for (let i of hp.shadowsocks_encrypt_methods)
o.value(i);
/* Stream ciphers */
o.value('aes-128-ctr');
@@ -720,7 +720,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.depends('type', 'vless');
o.depends('type', 'vmess');
o.onchange = function(ev, section_id, value) {
- var desc = this.map.findElement('id', 'cbid.homeproxy.%s.transport'.format(section_id)).nextElementSibling;
+ let desc = this.map.findElement('id', 'cbid.homeproxy.%s.transport'.format(section_id)).nextElementSibling;
if (value === 'http')
desc.innerHTML = _('TLS is not enforced. If TLS is not configured, plain HTTP 1.1 is used.');
else if (value === 'quic')
@@ -728,7 +728,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
else
desc.innerHTML = _('No TCP transport, plain HTTP is merged into the HTTP transport.');
- var tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
+ let tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
if ((value === 'http' && tls.checked) || (value === 'grpc' && !features.with_grpc)) {
this.map.findElement('id', 'cbid.homeproxy.%s.http_idle_timeout'.format(section_id)).nextElementSibling.innerHTML =
_('Specifies the period of time (in seconds) after which a health check will be performed using a ping frame if no frames have been received on the connection.
' +
@@ -951,10 +951,10 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.depends('type', 'tuic');
o.depends('type', 'vless');
o.depends('type', 'vmess');
- o.validate = function(section_id, value) {
+ o.validate = function(section_id, _value) {
if (section_id) {
- var type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
- var tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
+ let type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
+ let tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
if (['hysteria', 'hysteria2', 'shadowtls', 'tuic'].includes(type)) {
tls.checked = true;
@@ -990,7 +990,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.ListValue, 'tls_min_version', _('Minimum TLS version'),
_('The minimum TLS version that is acceptable.'));
o.value('', _('default'));
- for (var i of hp.tls_versions)
+ for (let i of hp.tls_versions)
o.value(i);
o.depends('tls', '1');
o.modalonly = true;
@@ -998,14 +998,14 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.ListValue, 'tls_max_version', _('Maximum TLS version'),
_('The maximum TLS version that is acceptable.'));
o.value('', _('default'));
- for (var i of hp.tls_versions)
+ for (let i of hp.tls_versions)
o.value(i);
o.depends('tls', '1');
o.modalonly = true;
o = s.option(hp.CBIStaticList, 'tls_cipher_suites', _('Cipher suites'),
_('The elliptic curves that will be used in an ECDHE handshake, in preference order. If empty, the default will be used.'));
- for (var i of hp.tls_cipher_suites)
+ for (let i of hp.tls_cipher_suites)
o.value(i);
o.depends('tls', '1');
o.optional = true;
@@ -1144,22 +1144,22 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
}
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('homeproxy'),
hp.getBuiltinFeatures()
]);
},
- render: function(data) {
+ render(data) {
let m, s, o, ss, so;
- var main_node = uci.get(data[0], 'config', 'main_node');
- var routing_mode = uci.get(data[0], 'config', 'routing_mode');
- var features = data[1];
+ let main_node = uci.get(data[0], 'config', 'main_node');
+ let routing_mode = uci.get(data[0], 'config', 'routing_mode');
+ let features = data[1];
/* Cache subscription information, it will be called multiple times */
- var subinfo = [];
- for (var suburl of (uci.get(data[0], 'subscription', 'subscription_url') || [])) {
+ let subinfo = [];
+ for (let suburl of (uci.get(data[0], 'subscription', 'subscription_url') || [])) {
const url = new URL(suburl);
const urlhash = hp.calcStringMD5(suburl.replace(/#.*$/, ''));
const title = url.hash ? decodeURIComponent(url.hash.slice(1)) : url.hostname;
@@ -1177,7 +1177,7 @@ return view.extend({
ss = renderNodeSettings(o.subsection, data, features, main_node, routing_mode);
ss.addremove = true;
ss.filter = function(section_id) {
- for (var info of subinfo)
+ for (let info of subinfo)
if (info.hash === uci.get(data[0], section_id, 'grouphash'))
return false;
@@ -1186,7 +1186,7 @@ return view.extend({
/* Import subscription links start */
/* Thanks to luci-app-shadowsocks-libev */
ss.handleLinkImport = function() {
- var textarea = new ui.Textarea();
+ let textarea = new ui.Textarea();
ui.showModal(_('Import share links'), [
E('p', _('Support Hysteria, Shadowsocks, Trojan, v2rayN (VMess), and XTLS (VLESS) online configuration delivery standard.')),
textarea.render(),
@@ -1199,25 +1199,25 @@ return view.extend({
E('button', {
class: 'btn cbi-button-action',
click: ui.createHandlerFn(this, function() {
- var input_links = textarea.getValue().trim().split('\n');
+ let input_links = textarea.getValue().trim().split('\n');
if (input_links && input_links[0]) {
/* Remove duplicate lines */
input_links = input_links.reduce((pre, cur) =>
(!pre.includes(cur) && pre.push(cur), pre), []);
- var allow_insecure = uci.get(data[0], 'subscription', 'allow_insecure');
- var packet_encoding = uci.get(data[0], 'subscription', 'packet_encoding');
- var imported_node = 0;
+ let allow_insecure = uci.get(data[0], 'subscription', 'allow_insecure');
+ let packet_encoding = uci.get(data[0], 'subscription', 'packet_encoding');
+ let imported_node = 0;
input_links.forEach((l) => {
- var config = parseShareLink(l, features);
+ let config = parseShareLink(l, features);
if (config) {
if (config.tls === '1' && allow_insecure === '1')
config.tls_insecure = '1'
if (['vless', 'vmess'].includes(config.type))
config.packet_encoding = packet_encoding
- var nameHash = hp.calcStringMD5(config.label);
- var sid = uci.add(data[0], 'node', nameHash);
+ let nameHash = hp.calcStringMD5(config.label);
+ let sid = uci.add(data[0], 'node', nameHash);
Object.keys(config).forEach((k) => {
uci.set(data[0], sid, k, config[k]);
});
@@ -1245,12 +1245,12 @@ return view.extend({
])
}
ss.renderSectionAdd = function(/* ... */) {
- var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
+ let el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, (v) => {
- var button = el.querySelector('.cbi-section-create > .cbi-button-add');
- var uciconfig = this.uciconfig || this.map.config;
+ let button = el.querySelector('.cbi-section-create > .cbi-button-add');
+ let uciconfig = this.uciconfig || this.map.config;
if (!v) {
button.disabled = true;
@@ -1296,7 +1296,7 @@ return view.extend({
o.rmempty = false;
o = s.taboption('subscription', form.ListValue, 'auto_update_time', _('Update time'));
- for (var i = 0; i < 24; i++)
+ for (let i = 0; i < 24; i++)
o.value(i, i + ':00');
o.default = '2';
o.depends('auto_update', '1');
@@ -1311,7 +1311,7 @@ return view.extend({
o.validate = function(section_id, value) {
if (section_id && value) {
try {
- var url = new URL(value);
+ let url = new URL(value);
if (!url.hostname)
return _('Expecting: %s').format(_('valid URL'));
}
@@ -1364,7 +1364,7 @@ return view.extend({
o = s.taboption('subscription', form.Button, '_update_subscriptions', _('Update nodes from subscriptions'));
o.inputstyle = 'apply';
o.inputtitle = function(section_id) {
- var sublist = uci.get(data[0], section_id, 'subscription_url') || [];
+ let sublist = uci.get(data[0], section_id, 'subscription_url') || [];
if (sublist.length > 0) {
return _('Update %s subscriptions').format(sublist.length);
} else {
@@ -1384,7 +1384,7 @@ return view.extend({
o = s.taboption('subscription', form.Button, '_remove_subscriptions', _('Remove all nodes from subscriptions'));
o.inputstyle = 'reset';
o.inputtitle = function() {
- var subnodes = [];
+ let subnodes = [];
uci.sections(data[0], 'node', (res) => {
if (res.grouphash)
subnodes = subnodes.concat(res['.name'])
@@ -1398,13 +1398,13 @@ return view.extend({
}
}
o.onclick = function() {
- var subnodes = [];
+ let subnodes = [];
uci.sections(data[0], 'node', (res) => {
if (res.grouphash)
subnodes = subnodes.concat(res['.name'])
});
- for (var i in subnodes)
+ for (let i in subnodes)
uci.remove(data[0], subnodes[i]);
if (subnodes.includes(uci.get(data[0], 'config', 'main_node')))
diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js
index c93960f83..cf8c6d83d 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2022-2023 ImmortalWrt.org
+ * Copyright (C) 2022-2025 ImmortalWrt.org
*/
'use strict';
@@ -23,7 +23,7 @@ const callServiceList = rpc.declare({
function getServiceStatus() {
return L.resolveDefault(callServiceList('homeproxy'), {}).then((res) => {
- var isRunning = false;
+ let isRunning = false;
try {
isRunning = res['homeproxy']['instances']['sing-box-s']['running'];
} catch (e) { }
@@ -32,8 +32,8 @@ function getServiceStatus() {
}
function renderStatus(isRunning, version) {
- var spanTemp = '%s (sing-box v%s) %s';
- var renderHTML;
+ let spanTemp = '%s (sing-box v%s) %s';
+ let renderHTML;
if (isRunning)
renderHTML = spanTemp.format('green', _('HomeProxy Server'), version, _('RUNNING'));
else
@@ -43,10 +43,10 @@ function renderStatus(isRunning, version) {
}
function handleGenKey(option) {
- var section_id = this.section.section;
- var type = this.section.getOption('type').formvalue(section_id);
- var widget = this.map.findElement('id', 'widget.cbid.homeproxy.%s.%s'.format(section_id, option));
- var password, required_method;
+ let section_id = this.section.section;
+ let type = this.section.getOption('type').formvalue(section_id);
+ let widget = this.map.findElement('id', 'widget.cbid.homeproxy.%s.%s'.format(section_id, option));
+ let password, required_method;
if (option === 'uuid')
required_method = 'uuid';
@@ -83,16 +83,16 @@ function handleGenKey(option) {
}
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('homeproxy'),
hp.getBuiltinFeatures()
]);
},
- render: function(data) {
+ render(data) {
let m, s, o;
- var features = data[1];
+ let features = data[1];
m = new form.Map('homeproxy', _('HomeProxy Server'),
_('The modern OpenWrt proxy platform for ARM64/AMD64.'));
@@ -101,7 +101,7 @@ return view.extend({
s.render = function () {
poll.add(function () {
return L.resolveDefault(getServiceStatus()).then((res) => {
- var view = document.getElementById('service_status');
+ let view = document.getElementById('service_status');
view.innerHTML = renderStatus(res, features.version);
});
});
@@ -183,7 +183,7 @@ return view.extend({
o.depends('type', 'trojan');
o.depends('type', 'tuic');
o.renderWidget = function() {
- var node = form.Value.prototype.renderWidget.apply(this, arguments);
+ let node = form.Value.prototype.renderWidget.apply(this, arguments);
(node.querySelector('.control-group') || node).appendChild(E('button', {
'class': 'cbi-button cbi-button-apply',
@@ -195,12 +195,12 @@ return view.extend({
}
o.validate = function(section_id, value) {
if (section_id) {
- var type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
- var required_type = [ 'http', 'mixed', 'naive', 'socks', 'shadowsocks' ];
+ let type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
+ let required_type = [ 'http', 'mixed', 'naive', 'socks', 'shadowsocks' ];
if (required_type.includes(type)) {
if (type === 'shadowsocks') {
- var encmode = this.map.lookupOption('shadowsocks_encrypt_method', section_id)[0].formvalue(section_id);
+ let encmode = this.map.lookupOption('shadowsocks_encrypt_method', section_id)[0].formvalue(section_id);
if (encmode === 'none')
return true;
else if (encmode === '2022-blake3-aes-128-gcm')
@@ -266,7 +266,7 @@ return view.extend({
o.depends('type', 'hysteria');
o.depends({'type': 'hysteria2', 'hysteria_obfs_type': /[\s\S]/});
o.renderWidget = function() {
- var node = form.Value.prototype.renderWidget.apply(this, arguments);
+ let node = form.Value.prototype.renderWidget.apply(this, arguments);
(node.querySelector('.control-group') || node).appendChild(E('button', {
'class': 'cbi-button cbi-button-apply',
@@ -319,7 +319,7 @@ return view.extend({
/* Shadowsocks config */
o = s.option(form.ListValue, 'shadowsocks_encrypt_method', _('Encrypt method'));
- for (var i of hp.shadowsocks_encrypt_methods)
+ for (let i of hp.shadowsocks_encrypt_methods)
o.value(i);
o.default = 'aes-128-gcm';
o.depends('type', 'shadowsocks');
@@ -331,7 +331,7 @@ return view.extend({
o.depends('type', 'vless');
o.depends('type', 'vmess');
o.renderWidget = function() {
- var node = form.Value.prototype.renderWidget.apply(this, arguments);
+ let node = form.Value.prototype.renderWidget.apply(this, arguments);
(node.querySelector('.control-group') || node).appendChild(E('button', {
'class': 'cbi-button cbi-button-apply',
@@ -402,7 +402,7 @@ return view.extend({
o.depends('type', 'vless');
o.depends('type', 'vmess');
o.onchange = function(ev, section_id, value) {
- var desc = this.map.findElement('id', 'cbid.homeproxy.%s.transport'.format(section_id)).nextElementSibling;
+ let desc = this.map.findElement('id', 'cbid.homeproxy.%s.transport'.format(section_id)).nextElementSibling;
if (value === 'http')
desc.innerHTML = _('TLS is not enforced. If TLS is not configured, plain HTTP 1.1 is used.');
else if (value === 'quic')
@@ -410,7 +410,7 @@ return view.extend({
else
desc.innerHTML = _('No TCP transport, plain HTTP is merged into the HTTP transport.');
- var tls_element = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
+ let tls_element = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
if ((value === 'http' && tls_element.checked) || (value === 'grpc' && !features.with_grpc))
this.map.findElement('id', 'cbid.homeproxy.%s.http_idle_timeout'.format(section_id)).nextElementSibling.innerHTML =
_('Specifies the time (in seconds) until idle clients should be closed with a GOAWAY frame. PING frames are not considered as activity.');
@@ -539,8 +539,8 @@ return view.extend({
o.rmempty = false;
o.validate = function(section_id, value) {
if (section_id) {
- var type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
- var tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
+ let type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
+ let tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
if (['hysteria', 'hysteria2', 'tuic'].includes(type)) {
tls.checked = true;
@@ -567,7 +567,7 @@ return view.extend({
o = s.option(form.ListValue, 'tls_min_version', _('Minimum TLS version'),
_('The minimum TLS version that is acceptable.'));
o.value('', _('default'));
- for (var i of hp.tls_versions)
+ for (let i of hp.tls_versions)
o.value(i);
o.depends('tls', '1');
o.modalonly = true;
@@ -575,14 +575,14 @@ return view.extend({
o = s.option(form.ListValue, 'tls_max_version', _('Maximum TLS version'),
_('The maximum TLS version that is acceptable.'));
o.value('', _('default'));
- for (var i of hp.tls_versions)
+ for (let i of hp.tls_versions)
o.value(i);
o.depends('tls', '1');
o.modalonly = true;
o = s.option(hp.CBIStaticList, 'tls_cipher_suites', _('Cipher suites'),
_('The elliptic curves that will be used in an ECDHE handshake, in preference order. If empty, the default will be used.'));
- for (var i of hp.tls_cipher_suites)
+ for (let i of hp.tls_cipher_suites)
o.value(i);
o.depends('tls', '1');
o.optional = true;
@@ -808,7 +808,7 @@ return view.extend({
o = s.option(form.ListValue, 'domain_strategy', _('Domain strategy'),
_('If set, the requested domain name will be resolved to IP before routing.'));
- for (var i in hp.dns_strategy)
+ for (let i in hp.dns_strategy)
o.value(i, hp.dns_strategy[i])
o.modalonly = true;
diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js
index 139d6d5e4..2d2bc49d7 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2022-2023 ImmortalWrt.org
+ * Copyright (C) 2022-2025 ImmortalWrt.org
*/
'use strict';
@@ -15,7 +15,7 @@
'require view';
/* Thanks to luci-app-aria2 */
-var css = ' \
+const css = ' \
#log_textarea { \
padding: 10px; \
text-align: left; \
@@ -29,7 +29,7 @@ var css = ' \
background-color: #33ccff; \
}';
-var hp_dir = '/var/run/homeproxy';
+const hp_dir = '/var/run/homeproxy';
function getConnStat(self, site) {
const callConnStat = rpc.declare({
@@ -44,7 +44,7 @@ function getConnStat(self, site) {
'class': 'btn cbi-button cbi-button-action',
'click': ui.createHandlerFn(this, function() {
return L.resolveDefault(callConnStat(site), {}).then((ret) => {
- var ele = self.default.firstElementChild.nextElementSibling;
+ let ele = self.default.firstElementChild.nextElementSibling;
if (ret.result) {
ele.style.setProperty('color', 'green');
ele.innerHTML = _('passed');
@@ -76,7 +76,7 @@ function getResVersion(self, type) {
});
return L.resolveDefault(callResVersion(type), {}).then((res) => {
- var spanTemp = E('div', { 'style': 'cbi-value-field' }, [
+ let spanTemp = E('div', { 'style': 'cbi-value-field' }, [
E('button', {
'class': 'btn cbi-button cbi-button-action',
'click': ui.createHandlerFn(this, function() {
@@ -121,7 +121,7 @@ function getRuntimeLog(name, filename) {
expect: { '': {} }
});
- var log_textarea = E('div', { 'id': 'log_textarea' },
+ let log_textarea = E('div', { 'id': 'log_textarea' },
E('img', {
'src': L.resource('icons/loading.gif'),
'alt': _('Loading'),
@@ -129,7 +129,7 @@ function getRuntimeLog(name, filename) {
}, _('Collecting data...'))
);
- var log;
+ let log;
poll.add(L.bind(function() {
return fs.read_direct(String.format('%s/%s.log', hp_dir, filename), 'text')
.then(function(res) {
@@ -176,15 +176,8 @@ function getRuntimeLog(name, filename) {
}
return view.extend({
- load: function() {
- return Promise.all([
- uci.load('homeproxy')
- ]);
- },
-
- render: function(data) {
- var m, s, o;
- var routing_mode = uci.get(data[0], 'config', 'routing_mode') || 'bypass_mainland_china';
+ render() {
+ let m, s, o;
m = new form.Map('homeproxy');
diff --git a/luci-app-homeproxy/po/templates/homeproxy.pot b/luci-app-homeproxy/po/templates/homeproxy.pot
index 0a6379fe5..4358f3e53 100644
--- a/luci-app-homeproxy/po/templates/homeproxy.pot
+++ b/luci-app-homeproxy/po/templates/homeproxy.pot
@@ -209,7 +209,7 @@ msgstr ""
msgid "BBR"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:194
+#: htdocs/luci-static/resources/view/homeproxy/status.js:187
msgid "BaiDu"
msgstr ""
@@ -309,15 +309,15 @@ msgstr ""
msgid "China DNS server"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:204
+#: htdocs/luci-static/resources/view/homeproxy/status.js:197
msgid "China IPv4 list version"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:208
+#: htdocs/luci-static/resources/view/homeproxy/status.js:201
msgid "China IPv6 list version"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:212
+#: htdocs/luci-static/resources/view/homeproxy/status.js:205
msgid "China list version"
msgstr ""
@@ -373,7 +373,7 @@ msgstr ""
msgid "Congestion control algorithm"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:191
+#: htdocs/luci-static/resources/view/homeproxy/status.js:184
msgid "Connection check"
msgstr ""
@@ -467,7 +467,7 @@ msgstr ""
msgid "Direct"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1303
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1307
msgid "Direct Domain List"
msgstr ""
@@ -737,8 +737,8 @@ msgstr ""
#: htdocs/luci-static/resources/view/homeproxy/client.js:1150
#: htdocs/luci-static/resources/view/homeproxy/client.js:1155
#: htdocs/luci-static/resources/view/homeproxy/client.js:1158
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1296
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1325
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1300
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1333
#: htdocs/luci-static/resources/view/homeproxy/node.js:452
#: htdocs/luci-static/resources/view/homeproxy/node.js:1087
#: htdocs/luci-static/resources/view/homeproxy/node.js:1260
@@ -791,7 +791,7 @@ msgstr ""
msgid "GET"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:216
+#: htdocs/luci-static/resources/view/homeproxy/status.js:209
msgid "GFW list version"
msgstr ""
@@ -849,7 +849,7 @@ msgstr ""
msgid "Global settings"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:197
+#: htdocs/luci-static/resources/view/homeproxy/status.js:190
msgid "Google"
msgstr ""
@@ -897,7 +897,7 @@ msgstr ""
#: htdocs/luci-static/resources/view/homeproxy/client.js:55
#: htdocs/luci-static/resources/view/homeproxy/client.js:57
#: htdocs/luci-static/resources/view/homeproxy/client.js:120
-#: htdocs/luci-static/resources/view/homeproxy/status.js:224
+#: htdocs/luci-static/resources/view/homeproxy/status.js:217
#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:3
msgid "HomeProxy"
msgstr ""
@@ -1787,7 +1787,7 @@ msgstr ""
msgid "Resolve strategy"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:201
+#: htdocs/luci-static/resources/view/homeproxy/status.js:194
msgid "Resources management"
msgstr ""
@@ -2653,11 +2653,11 @@ msgstr ""
msgid "quic-go / uquic chrome"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:227
+#: htdocs/luci-static/resources/view/homeproxy/status.js:220
msgid "sing-box client"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/status.js:230
+#: htdocs/luci-static/resources/view/homeproxy/status.js:223
msgid "sing-box server"
msgstr ""
@@ -2722,8 +2722,8 @@ msgstr ""
msgid "valid base64 key with %d characters"
msgstr ""
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1296
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1325
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1300
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1333
msgid "valid hostname"
msgstr ""
diff --git a/luci-app-homeproxy/po/zh_Hans/homeproxy.po b/luci-app-homeproxy/po/zh_Hans/homeproxy.po
index 59fc05e9a..fa34d586b 100644
--- a/luci-app-homeproxy/po/zh_Hans/homeproxy.po
+++ b/luci-app-homeproxy/po/zh_Hans/homeproxy.po
@@ -218,7 +218,7 @@ msgstr "自动更新订阅和地理数据。"
msgid "BBR"
msgstr "BBR"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:194
+#: htdocs/luci-static/resources/view/homeproxy/status.js:187
msgid "BaiDu"
msgstr "百度"
@@ -318,15 +318,15 @@ msgstr "检查更新"
msgid "China DNS server"
msgstr "国内 DNS 服务器"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:204
+#: htdocs/luci-static/resources/view/homeproxy/status.js:197
msgid "China IPv4 list version"
msgstr "国内 IPv4 库版本"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:208
+#: htdocs/luci-static/resources/view/homeproxy/status.js:201
msgid "China IPv6 list version"
msgstr "国内 IPv6 库版本"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:212
+#: htdocs/luci-static/resources/view/homeproxy/status.js:205
msgid "China list version"
msgstr "国内域名列表版本"
@@ -382,7 +382,7 @@ msgstr "仅常用端口(绕过 P2P 流量)"
msgid "Congestion control algorithm"
msgstr "拥塞控制算法"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:191
+#: htdocs/luci-static/resources/view/homeproxy/status.js:184
msgid "Connection check"
msgstr "连接检查"
@@ -476,7 +476,7 @@ msgstr "默认服务器名称"
msgid "Direct"
msgstr "直连"
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1303
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1307
msgid "Direct Domain List"
msgstr "直连域名列表"
@@ -758,8 +758,8 @@ msgstr "加密方式"
#: htdocs/luci-static/resources/view/homeproxy/client.js:1150
#: htdocs/luci-static/resources/view/homeproxy/client.js:1155
#: htdocs/luci-static/resources/view/homeproxy/client.js:1158
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1296
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1325
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1300
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1333
#: htdocs/luci-static/resources/view/homeproxy/node.js:452
#: htdocs/luci-static/resources/view/homeproxy/node.js:1087
#: htdocs/luci-static/resources/view/homeproxy/node.js:1260
@@ -812,7 +812,7 @@ msgstr "格式"
msgid "GET"
msgstr "GET"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:216
+#: htdocs/luci-static/resources/view/homeproxy/status.js:209
msgid "GFW list version"
msgstr "GFW 域名列表版本"
@@ -870,7 +870,7 @@ msgstr "全局代理 MAC 地址"
msgid "Global settings"
msgstr "全局设置"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:197
+#: htdocs/luci-static/resources/view/homeproxy/status.js:190
msgid "Google"
msgstr "谷歌"
@@ -918,7 +918,7 @@ msgstr "心跳间隔"
#: htdocs/luci-static/resources/view/homeproxy/client.js:55
#: htdocs/luci-static/resources/view/homeproxy/client.js:57
#: htdocs/luci-static/resources/view/homeproxy/client.js:120
-#: htdocs/luci-static/resources/view/homeproxy/status.js:224
+#: htdocs/luci-static/resources/view/homeproxy/status.js:217
#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:3
msgid "HomeProxy"
msgstr "HomeProxy"
@@ -1814,7 +1814,7 @@ msgstr "保留字段字节"
msgid "Resolve strategy"
msgstr "解析策略"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:201
+#: htdocs/luci-static/resources/view/homeproxy/status.js:194
msgid "Resources management"
msgstr "资源管理"
@@ -2720,11 +2720,11 @@ msgstr "私钥"
msgid "quic-go / uquic chrome"
msgstr "quic-go / uquic chrome"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:227
+#: htdocs/luci-static/resources/view/homeproxy/status.js:220
msgid "sing-box client"
msgstr "sing-box 客户端"
-#: htdocs/luci-static/resources/view/homeproxy/status.js:230
+#: htdocs/luci-static/resources/view/homeproxy/status.js:223
msgid "sing-box server"
msgstr "sing-box 服务端"
@@ -2790,8 +2790,8 @@ msgstr "有效网址"
msgid "valid base64 key with %d characters"
msgstr "包含 %d 个字符的有效 base64 密钥"
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1296
-#: htdocs/luci-static/resources/view/homeproxy/client.js:1325
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1300
+#: htdocs/luci-static/resources/view/homeproxy/client.js:1333
msgid "valid hostname"
msgstr "有效主机名"
diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc
index 74e880897..162a5779c 100755
--- a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc
+++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc
@@ -13,8 +13,8 @@ import { connect } from 'ubus';
import { cursor } from 'uci';
import {
- executeCommand, isEmpty, strToBool, strToInt,
- removeBlankAttrs, validateHostname, validation,
+ isEmpty, strToBool, strToInt,
+ removeBlankAttrs, validation,
HP_DIR, RUN_DIR
} from 'homeproxy';
@@ -373,20 +373,15 @@ config.dns = {
if (!isEmpty(main_node)) {
/* Main DNS */
- let default_final_dns = 'default-dns';
- if (dns_server !== wan_dns) {
- push(config.dns.servers, {
- tag: 'main-dns',
- address: !match(dns_server, /:\/\//) ? 'tcp://' + (validation('ip6addr', dns_server) ? `[${dns_server}]` : dns_server) : dns_server,
- strategy: (ipv6_support !== '1') ? 'ipv4_only' : null,
- address_resolver: 'default-dns',
- address_strategy: (ipv6_support !== '1') ? 'ipv4_only' : null,
- detour: 'main-out'
- });
-
- default_final_dns = 'main-dns';
- }
- config.dns.final = default_final_dns;
+ push(config.dns.servers, {
+ tag: 'main-dns',
+ address: !match(dns_server, /:\/\//) ? 'tcp://' + (validation('ip6addr', dns_server) ? `[${dns_server}]` : dns_server) : dns_server,
+ strategy: (ipv6_support !== '1') ? 'ipv4_only' : null,
+ address_resolver: 'default-dns',
+ address_strategy: (ipv6_support !== '1') ? 'ipv4_only' : null,
+ detour: 'main-out'
+ });
+ config.dns.final = 'main-dns';
/* Avoid DNS loop */
push(config.dns.rules, {
@@ -394,16 +389,16 @@ if (!isEmpty(main_node)) {
server: 'default-dns'
});
- if (direct_domain_list)
+ if (length(direct_domain_list))
push(config.dns.rules, {
- domain_keyword: direct_domain_list,
- server: 'default-dns'
+ rule_set: 'direct-domain',
+ server: (routing_mode === 'bypass_mainland_china' ) ? 'china-dns' : 'default-dns'
});
/* Filter out SVCB/HTTPS queries for "exquisite" Apple devices */
- if (routing_mode === 'gfwlist' || proxy_domain_list)
+ if (routing_mode === 'gfwlist' || length(proxy_domain_list))
push(config.dns.rules, {
- domain_keyword: (routing_mode !== 'gfwlist') ? proxy_domain_list : null,
+ rule_set: (routing_mode !== 'gfwlist') ? 'proxy-domain' : null,
query_type: [64, 65],
server: 'block-dns'
});
@@ -415,10 +410,10 @@ if (!isEmpty(main_node)) {
detour: 'direct-out'
});
- if (proxy_domain_list)
+ if (length(proxy_domain_list))
push(config.dns.rules, {
- domain_keyword: proxy_domain_list,
- server: default_final_dns
+ rule_set: 'proxy-domain',
+ server: 'main-dns'
});
push(config.dns.rules, {
@@ -440,6 +435,7 @@ if (!isEmpty(main_node)) {
server: 'china-dns'
});
}
+
} else if (!isEmpty(default_outbound)) {
/* DNS servers */
uci.foreach(uciconfig, ucidnsserver, (cfg) => {
@@ -590,11 +586,13 @@ config.outbounds = [
if (!isEmpty(main_node)) {
const main_node_cfg = uci.get_all(uciconfig, main_node) || {};
push(config.outbounds, generate_outbound(main_node_cfg));
+ config.outbounds[length(config.outbounds)-1].domain_strategy = (ipv6_support !== '1') ? 'prefer_ipv4' : null;
config.outbounds[length(config.outbounds)-1].tag = 'main-out';
if (dedicated_udp_node) {
const main_udp_node_cfg = uci.get_all(uciconfig, main_udp_node) || {};
push(config.outbounds, generate_outbound(main_udp_node_cfg));
+ config.outbounds[length(config.outbounds)-1].domain_strategy = (ipv6_support !== '1') ? 'prefer_ipv4' : null;
config.outbounds[length(config.outbounds)-1].tag = 'main-udp-out';
}
} else if (!isEmpty(default_outbound)) {
@@ -651,7 +649,7 @@ if (!isEmpty(main_node)) {
/* Direct list */
if (length(direct_domain_list))
push(config.route.rules, {
- domain_keyword: direct_domain_list,
+ rule_set: 'direct-domain',
outbound: 'direct-out'
});
@@ -665,6 +663,30 @@ if (!isEmpty(main_node)) {
config.route.final = 'main-out';
/* Rule set */
+ /* Direct list */
+ if (length(direct_domain_list))
+ push(config.route.rule_set, {
+ type: 'inline',
+ tag: 'direct-domain',
+ rules: [
+ {
+ domain_keyword: direct_domain_list,
+ }
+ ]
+ });
+
+ /* Proxy list */
+ if (length(proxy_domain_list))
+ push(config.route.rule_set, {
+ type: 'inline',
+ tag: 'proxy-domain',
+ rules: [
+ {
+ domain_keyword: proxy_domain_list,
+ }
+ ]
+ });
+
if (routing_mode === 'bypass_mainland_china') {
push(config.route.rule_set, {
type: 'remote',
@@ -688,6 +710,9 @@ if (!isEmpty(main_node)) {
download_detour: 'main-out'
});
}
+
+ if (isEmpty(config.route.rule_set))
+ config.route.rule_set = null;
} else if (!isEmpty(default_outbound)) {
uci.foreach(uciconfig, uciroutingrule, (cfg) => {
if (cfg.enabled !== '1')
diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc
index bd4fdcd33..0432bb26d 100755
--- a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc
+++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc
@@ -7,13 +7,12 @@
'use strict';
-import { readfile, writefile } from 'fs';
+import { writefile } from 'fs';
import { cursor } from 'uci';
import {
- executeCommand, isEmpty, strToBool, strToInt,
- removeBlankAttrs, validateHostname, validation,
- HP_DIR, RUN_DIR
+ isEmpty, strToBool, strToInt,
+ removeBlankAttrs, HP_DIR, RUN_DIR
} from 'homeproxy';
/* UCI config start */
diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc
index 5623ab0dd..3f7cb2bc3 100644
--- a/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc
+++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc
@@ -5,7 +5,7 @@
*/
import { mkstemp } from 'fs';
-import { urldecode, urldecode_params } from 'luci.http';
+import { urldecode_params } from 'luci.http';
/* Global variables start */
export const HP_DIR = '/etc/homeproxy';
diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc
index 0dfbf1fac..b10dc5edd 100755
--- a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc
+++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc
@@ -11,11 +11,11 @@ import { open } from 'fs';
import { connect } from 'ubus';
import { cursor } from 'uci';
-import { urldecode, urlencode, urldecode_params } from 'luci.http';
+import { urldecode, urlencode } from 'luci.http';
import { init_action } from 'luci.sys';
import {
- calcStringMD5, wGET, executeCommand, decodeBase64Str,
+ calcStringMD5, wGET, decodeBase64Str,
getTime, isEmpty, parseURL, validation,
HP_DIR, RUN_DIR
} from 'homeproxy';
diff --git a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy
index 10a96896e..6605a96b4 100644
--- a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy
+++ b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy
@@ -7,7 +7,7 @@
'use strict';
-import { access, error, lstat, mkstemp, popen, readfile, writefile } from 'fs';
+import { access, error, lstat, popen, readfile, writefile } from 'fs';
/* Kanged from ucode/luci */
function shellquote(s) {