diff --git a/dae/Makefile b/dae/Makefile
index 45ae1566..8de7aad5 100644
--- a/dae/Makefile
+++ b/dae/Makefile
@@ -10,7 +10,7 @@ PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git
-PKG_SOURCE_VERSION:=d44529e9525a82ae3f9a42c9cb674256b943f67e
+PKG_SOURCE_VERSION:=1f2d6de4a6d1fc9718e7179a124aad0f70002d2d
PKG_SOURCE_URL:=https://github.com/olicesx/dae.git
PKG_MIRROR_HASH:=skip
diff --git a/luci-app-amlogic/Makefile b/luci-app-amlogic/Makefile
index 872090ba..84c0ff8e 100644
--- a/luci-app-amlogic/Makefile
+++ b/luci-app-amlogic/Makefile
@@ -16,7 +16,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-amlogic
-PKG_VERSION:=3.1.320
+PKG_VERSION:=3.1.321
PKG_RELEASE:=2
PKG_LICENSE:=GPL-2.0 License
diff --git a/luci-app-amlogic/root/usr/sbin/openwrt-kernel b/luci-app-amlogic/root/usr/sbin/openwrt-kernel
index eddbdc98..20000853 100755
--- a/luci-app-amlogic/root/usr/sbin/openwrt-kernel
+++ b/luci-app-amlogic/root/usr/sbin/openwrt-kernel
@@ -68,7 +68,7 @@ get_textoffset() {
temp_dir="$(mktemp -d)"
(
cd ${temp_dir}
- tar -xf "${boot_tgz_file}" "${vmlinuz_name}"
+ tar --no-same-owner -xf "${boot_tgz_file}" "${vmlinuz_name}"
)
# With TEXT_OFFSET patch is [ 0108 ], without TEXT_OFFSET patch is [ 0000 ]
[[ "$(hexdump -n 15 -x "${temp_dir}/${vmlinuz_name}" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"
@@ -274,7 +274,7 @@ update_kernel() {
dtb* 2>/dev/null
)
# Extract the new kernel
- tar -xf ${P4_PATH}/boot-${kernel_name}.tar.gz -C /boot
+ tar --no-same-owner -xf ${P4_PATH}/boot-${kernel_name}.tar.gz -C /boot
# Check if the file exists
local valid_files
@@ -319,14 +319,14 @@ update_kernel() {
else
(cd /boot && mkdir -p dtb-${kernel_name}/${PLATFORM} && ln -sf dtb-${kernel_name} dtb)
fi
- tar -xf ${P4_PATH}/dtb-${PLATFORM}-${kernel_name}.tar.gz -C /boot/dtb/${PLATFORM}
+ tar --no-same-owner -xf ${P4_PATH}/dtb-${PLATFORM}-${kernel_name}.tar.gz -C /boot/dtb/${PLATFORM}
[[ "$(ls /boot/dtb/${PLATFORM} -l 2>/dev/null | grep "^-" | wc -l)" -ge "1" ]] || error_msg "/boot/dtb/${PLATFORM} file is missing."
echo -e "(2/3) Unpacking [ dtb-${PLATFORM}-${kernel_name}.tar.gz ] done."
fi
# 03. for /lib/modules/*
rm -rf /lib/modules/*
- tar -xf ${P4_PATH}/modules-${kernel_name}.tar.gz -C /lib/modules
+ tar --no-same-owner -xf ${P4_PATH}/modules-${kernel_name}.tar.gz -C /lib/modules
(
cd /lib/modules/${kernel_name}
rm -f *.ko
diff --git a/luci-app-amlogic/root/usr/sbin/openwrt-update-rockchip b/luci-app-amlogic/root/usr/sbin/openwrt-update-rockchip
index da6fe93f..a6521c17 100755
--- a/luci-app-amlogic/root/usr/sbin/openwrt-update-rockchip
+++ b/luci-app-amlogic/root/usr/sbin/openwrt-update-rockchip
@@ -210,6 +210,14 @@ case $MYDEVICE_NAME in
fi
SOC="ht2"
;;
+"XYLink XR3528")
+ if [ -n "${CURRENT_FDTFILE}" ]; then
+ MYDTB_FDTFILE="${CURRENT_FDTFILE}"
+ else
+ MYDTB_FDTFILE="rk3528-xylink-xr3528.dtb"
+ fi
+ SOC="xylink-xr3528"
+ ;;
"Radxa E20C")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
diff --git a/luci-app-dnsproxy/README.md b/luci-app-dnsproxy/README.md
index 4cacca4d..5a517e98 100644
--- a/luci-app-dnsproxy/README.md
+++ b/luci-app-dnsproxy/README.md
@@ -4,6 +4,15 @@
`DNS-over-TLS`, `DNS-over-HTTPS`, `DNSCrypt`, and `DNS-over-QUIC`. Moreover,
it can work as a `DNS-over-HTTPS`, `DNS-over-TLS` or `DNS-over-QUIC` server.
+The LuCI interface also supports reusable DNS profiles. Each profile stores
+its own bootstrap, upstream, and fallback server lists and can apply all three
+lists at once. Editable example profiles for Cloudflare, Quad9, Google, and a
+mixed parallel setup are included to demonstrate the feature.
+
+## Requirements
+
+- OpenWrt >= 24.10
+
## How to install
1. Go to [here](https://fantastic-packages.github.io/releases/)
diff --git a/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js b/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js
index e6f11512..c9e95772 100644
--- a/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js
+++ b/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js
@@ -2,13 +2,22 @@
'require form';
'require fs';
'require uci';
+'require dom';
'require rpc';
'require poll';
+'require ui';
'require view';
+'require validation';
'require tools.widgets as widgets';
const conf = 'dnsproxy';
const instance = 'dnsproxy';
+const profileListOptions = ['bootstrap', 'upstream', 'fallback'];
+const upstream_mode = [
+ ['load_balance', _('Load balance'), _('one upstream per request.')],
+ ['parallel', _('Parallel'), _('first DNS response wins.')],
+ ['fastest_addr', _('Fastest address'), _('tests returned IP addresses.')]
+];
const callServiceList = rpc.declare({
object: 'service',
@@ -34,6 +43,91 @@ function getServiceStatus() {
});
}
+function profileTitle(profile) {
+ return profile.label || profile['.name'];
+}
+
+function applyProfile(select) {
+ const profile = uci.sections(conf, 'profile').find((item) => item['.name'] === select.value);
+
+ if (!profile)
+ return ui.addNotification(null, E('p', _('The selected DNS profile no longer exists. Reload the page and try again.')), 'error');
+
+ const upstreams = L.toArray(profile.upstream).filter(Boolean);
+ if (!upstreams.length)
+ return ui.addNotification(null, E('p', _('The selected DNS profile has no upstream servers.')), 'error');
+
+ profileListOptions.forEach((option) => {
+ const values = L.toArray(profile[option]).filter(Boolean);
+ uci.set(conf, 'servers', option, values.length ? values : null);
+ });
+
+ if (profile.upstream_mode)
+ uci.set(conf, 'global', 'upstream_mode', profile.upstream_mode);
+
+ return uci.save()
+ .then(L.bind(this.map.load, this.map))
+ .then(L.bind(this.map.reset, this.map))
+ .then(() => {
+ ui.addNotification(null, E('p', _('DNS profile “%s” has been applied.').format(profileTitle(profile))), 'info');
+ })
+ .catch((err) => {
+ ui.addNotification(null, E('p', _('Failed to apply DNS profile: %s').format(err.message || err)), 'error');
+ });
+}
+
+function validateUniqueValue(section_id, value) {
+ if (!value)
+ return _('Expecting: %s').format(_('non-empty value'));
+
+ let duplicate = false;
+ uci.sections(this.config, this.section.sectiontype, (res) => {
+ if (res['.name'] !== section_id)
+ if (res[this.option] === value)
+ duplicate = true;
+ });
+ if (duplicate)
+ return _('Expecting: %s').format(_('unique value'));
+
+ return true;
+}
+
+function validateServerValue(section_id, value) {
+ if (!value)
+ return true;
+
+ if (!value.includes('://')) {
+ let stubValidator = {
+ factory: validation,
+ apply(type, value, args) {
+ if (value != null)
+ this.value = value;
+
+ return validation.types[type].apply(this, args);
+ },
+ assert(condition) {
+ return !!condition;
+ }
+ };
+
+ if (!stubValidator.apply('host', value) && !stubValidator.apply('hostport', value))
+ return _('Expecting: %s').format(_('valid host or hostport'));
+
+ return true;
+ }
+
+ try {
+ const url = new URL(value);
+ if (!url.hostname)
+ return _('Expecting: %s').format(_('valid URL'));
+
+ return true;
+ }
+ catch (e) {
+ return _('Invalid URI');
+ }
+}
+
return view.extend({
load() {
@@ -116,7 +210,8 @@ return view.extend({
o = s.taboption('main', form.Flag, 'insecure', _('Disable secure TLS cert validation'));
- o = s.taboption('main', form.Flag, 'http3', _('DoH uses H3 first'));
+ o = s.taboption('main', form.Flag, 'http3', _('Enable HTTP/3 for DoH'));
+ o.description = _('Use HTTP/3 when it is faster. HTTPS fallback remains available.');
o = s.taboption('main', form.Value, 'timeout', _('Timeout for queries to remote upstream (default: 10s)'));
o.datatype = 'string';
@@ -127,14 +222,17 @@ return view.extend({
o = s.taboption('main', form.Value, 'udp_buf_size', _('Size of the UDP buffer in bytes. Set 0 use the system default'));
o.datatype = 'uinteger';
- o = s.taboption('main', form.Flag, 'all_servers', _('Parallel queries all upstream'));
-
- o = s.taboption('main', form.Flag, 'fastest_addr', _('Respond to A or AAAA requests only with the fastest IP address'));
- o.depends('all_servers', '1');
+ o = s.taboption('main', form.RichListValue, 'upstream_mode', _('Upstream selection mode'),
+ _('For the lowest DNS response time choose Parallel.') + '' +
+ _('Fastest address performs additional IP reachability tests and is a different, slower operation.'));
+ upstream_mode.forEach((res) => {
+ o.value.apply(o, res);
+ })
+ o.rmempty = false;
s.tab('cache', _('Cache'));
- o = s.taboption('cache', form.SectionValue, '_cache', form.NamedSection, 'cache', 'homeproxy');
+ o = s.taboption('cache', form.SectionValue, '_cache', form.NamedSection, 'cache', 'dnsproxy');
ss = o.subsection;
so = ss.option(form.Flag, 'enabled', _('Enable Cache'));
@@ -161,7 +259,7 @@ return view.extend({
s.tab('dns64', _('DNS64'));
- o = s.taboption('dns64', form.SectionValue, '_dns64', form.NamedSection, 'dns64', 'homeproxy');
+ o = s.taboption('dns64', form.SectionValue, '_dns64', form.NamedSection, 'dns64', 'dnsproxy');
ss = o.subsection;
so = ss.option(form.Flag, 'enabled', _('Enable DNS64'));
@@ -174,7 +272,7 @@ return view.extend({
s.tab('edns', _('EDNS'));
- o = s.taboption('edns', form.SectionValue, '_edns', form.NamedSection, 'edns', 'homeproxy');
+ o = s.taboption('edns', form.SectionValue, '_edns', form.NamedSection, 'edns', 'dnsproxy');
ss = o.subsection;
so = ss.option(form.Flag, 'enabled', _('Enable EDNS'));
@@ -186,7 +284,7 @@ return view.extend({
s.tab('bogus_nxdomain', _('Bogus-NXDOMAIN'));
- o = s.taboption('bogus_nxdomain', form.SectionValue, '_bogus_nxdomain', form.NamedSection, 'bogus_nxdomain', 'homeproxy');
+ o = s.taboption('bogus_nxdomain', form.SectionValue, '_bogus_nxdomain', form.NamedSection, 'bogus_nxdomain', 'dnsproxy');
ss = o.subsection;
so = ss.option(form.DynamicList, 'ip_addr', _('Convert matching single IP responses to NXDOMAIN'));
@@ -194,15 +292,107 @@ return view.extend({
s.tab('servers', _('Upstreams'));
- o = s.taboption('servers', form.SectionValue, '_servers', form.NamedSection, 'servers', 'homeproxy');
+ o = s.taboption('servers', form.DummyValue, '_profile_switcher', _('DNS profiles'),
+ _('A profile replaces Bootstrap, Upstream and Fallback lists together. Unsaved changes elsewhere on this page are not included.'));
+ o.renderWidget = function () {
+ const profiles = uci.sections(conf, 'profile');
+ const select = E('select', {
+ 'id': 'dnsproxy-profile-select',
+ 'class': 'cbi-input-select',
+ 'disabled': profiles.length ? null : ''
+ }, profiles.map((profile) => E('option', {
+ 'value': profile['.name']
+ }, profileTitle(profile))));
+
+ return E('div', {}, [
+ E('div', { 'style': 'display:flex;gap:.75em;align-items:center;flex-wrap:wrap' }, [
+ select,
+ E('button', {
+ 'class': 'cbi-button cbi-button-positive important',
+ 'disabled': profiles.length ? null : '',
+ 'click': ui.createHandlerFn(this, applyProfile, select)
+ }, _('Use selected profile'))
+ ]),
+ profiles.length ? '' : E('p', {}, _('Create and save a profile in the “DNS profile templates” section below first.'))
+ ]);
+ };
+
+ o = s.taboption('servers', form.SectionValue, '_servers', form.NamedSection, 'servers', 'dnsproxy');
ss = o.subsection;
so = ss.option(form.DynamicList, 'bootstrap', _('Bootstrap DNS Server'));
+ so.readonly = true
so = ss.option(form.DynamicList, 'upstream', _('Upstream DNS Server'));
+ so.readonly = true
so.rmempty = false;
so = ss.option(form.DynamicList, 'fallback', _('Fallback DNS Server'));
+ so.readonly = true
+
+ o = s.taboption('servers', form.SectionValue, '_profiles', form.GridSection, 'profile', _('DNS profile templates'),
+ _('Create reusable templates here. Applying a template does not modify the template itself.'));
+ ss = o.subsection;
+ ss.anonymous = true;
+ ss.addremove = true;
+ ss.rowcolors = true;
+ ss.sortable = true;
+ ss.nodescriptions = true;
+ ss.addbtntitle = _('Add DNS profile');
+ ss.renderRowActions = function(section_id, more_label, trEl) {
+ trEl = form.GridSection.prototype.renderRowActions.apply(this, arguments);
+ const preset_ids = [
+ 'default'
+ ];
+
+ if (preset_ids.includes(section_id))
+ trEl?.lastChild.querySelector('.cbi-button-remove')?.remove();
+
+ return trEl;
+ }
+
+ so = ss.option(form.Value, 'label', _('Profile name'));
+ so.rmempty = false;
+ so.validate = validateUniqueValue;
+
+ so = ss.option(form.RichListValue, 'upstream_mode', _('Upstream selection mode'));
+ so.value(' ', _('Keep current mode'));
+ upstream_mode.forEach((res) => {
+ so.value.apply(so, res);
+ })
+ so.load = function(section_id) {
+ let value = this.super('load', section_id);
+ if (!value)
+ return ' ';
+
+ return value;
+ }
+ so.write = function(section_id, value) {
+ if (!value.trim())
+ return this.super('remove', section_id);
+
+ return form.RichListValue.prototype.write.call(this, section_id, value);
+ }
+ so.textvalue = function(section_id) {
+ let cval = this.cfgvalue(section_id);
+ let i = this.keylist.indexOf(cval);
+ let val = this.vallist[i];
+
+ return dom.elem(val) ? val.firstChild.textContent : val ?? cval;
+ }
+
+ so = ss.option(form.DynamicList, 'bootstrap', _('Bootstrap DNS'));
+ so.validate = validateServerValue;
+ so.modalonly = true;
+
+ so = ss.option(form.DynamicList, 'upstream', _('Upstream DNS'));
+ so.rmempty = false;
+ so.validate = validateServerValue;
+ so.modalonly = true;
+
+ so = ss.option(form.DynamicList, 'fallback', _('Fallback DNS'));
+ so.validate = validateServerValue;
+ so.modalonly = true;
return m.render()
.then(L.bind(function(m, nodes) {
diff --git a/luci-app-dnsproxy/po/templates/dnsproxy.pot b/luci-app-dnsproxy/po/templates/dnsproxy.pot
index 869fa122..3ab591ca 100644
--- a/luci-app-dnsproxy/po/templates/dnsproxy.pot
+++ b/luci-app-dnsproxy/po/templates/dnsproxy.pot
@@ -1,155 +1,287 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:187
+#: htdocs/luci-static/resources/view/dnsproxy.js:296
+msgid ""
+"A profile replaces Bootstrap, Upstream and Fallback lists together. Unsaved "
+"changes elsewhere on this page are not included."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:341
+msgid "Add DNS profile"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:285
msgid "Bogus-NXDOMAIN"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:200
+#: htdocs/luci-static/resources/view/dnsproxy.js:384
+msgid "Bootstrap DNS"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:323
msgid "Bootstrap DNS Server"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:135
+#: htdocs/luci-static/resources/view/dnsproxy.js:233
msgid "Cache"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:146
+#: htdocs/luci-static/resources/view/dnsproxy.js:244
msgid "Cache size (in bytes)"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:70
+#: htdocs/luci-static/resources/view/dnsproxy.js:164
msgid "Collecting data ..."
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:192
+#: htdocs/luci-static/resources/view/dnsproxy.js:290
msgid "Convert matching single IP responses to NXDOMAIN"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:65
-#: applications/luci-app-dnsproxy/root/usr/share/luci/menu.d/luci-app-dnsproxy.json:3
+#: htdocs/luci-static/resources/view/dnsproxy.js:316
+msgid ""
+"Create and save a profile in the “DNS profile templates” section below first."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:334
+msgid ""
+"Create reusable templates here. Applying a template does not modify the "
+"template itself."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:159
+#: root/usr/share/luci/menu.d/luci-app-dnsproxy.json:3
msgid "DNS Proxy"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:162
+#: htdocs/luci-static/resources/view/dnsproxy.js:333
+msgid "DNS profile templates"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:72
+msgid "DNS profile “%s” has been applied."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:295
+msgid "DNS profiles"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:260
msgid "DNS64"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:169
+#: htdocs/luci-static/resources/view/dnsproxy.js:267
msgid "DNS64 Prefix"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:113
+#: htdocs/luci-static/resources/view/dnsproxy.js:207
msgid "Disable IPv6"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:117
+#: htdocs/luci-static/resources/view/dnsproxy.js:211
msgid "Disable secure TLS cert validation"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:119
-msgid "DoH uses H3 first"
-msgstr ""
-
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:175
+#: htdocs/luci-static/resources/view/dnsproxy.js:273
msgid "EDNS"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:182
+#: htdocs/luci-static/resources/view/dnsproxy.js:280
msgid "EDNS Client Address"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:78
+#: htdocs/luci-static/resources/view/dnsproxy.js:172
msgid "Enable"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:140
+#: htdocs/luci-static/resources/view/dnsproxy.js:238
msgid "Enable Cache"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:167
+#: htdocs/luci-static/resources/view/dnsproxy.js:265
msgid "Enable DNS64"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:180
+#: htdocs/luci-static/resources/view/dnsproxy.js:278
msgid "Enable EDNS"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:205
+#: htdocs/luci-static/resources/view/dnsproxy.js:213
+msgid "Enable HTTP/3 for DoH"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:81
+#: htdocs/luci-static/resources/view/dnsproxy.js:90
+#: htdocs/luci-static/resources/view/dnsproxy.js:114
+#: htdocs/luci-static/resources/view/dnsproxy.js:122
+msgid "Expecting: %s"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:75
+msgid "Failed to apply DNS profile: %s"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:393
+msgid "Fallback DNS"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:330
msgid "Fallback DNS Server"
msgstr ""
-#: applications/luci-app-dnsproxy/root/usr/share/rpcd/acl.d/luci-app-dnsproxy.json:3
+#: htdocs/luci-static/resources/view/dnsproxy.js:19
+msgid "Fastest address"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:227
+msgid ""
+"Fastest address performs additional IP reachability tests and is a "
+"different, slower operation."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:226
+msgid "For the lowest DNS response time choose Parallel."
+msgstr ""
+
+#: root/usr/share/rpcd/acl.d/luci-app-dnsproxy.json:3
msgid "Grant access to LuCI app dnsproxy"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:86
+#: htdocs/luci-static/resources/view/dnsproxy.js:127
+msgid "Invalid URI"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:359
+msgid "Keep current mode"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:180
msgid "Listen address"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:108
+#: htdocs/luci-static/resources/view/dnsproxy.js:202
msgid "Listen ports"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:83
+#: htdocs/luci-static/resources/view/dnsproxy.js:17
+msgid "Load balance"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:177
msgid "Log file path"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:76
+#: htdocs/luci-static/resources/view/dnsproxy.js:170
msgid "Main"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:157
+#: htdocs/luci-static/resources/view/dnsproxy.js:255
msgid "Max TTL value for DNS entries, in seconds"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:152
+#: htdocs/luci-static/resources/view/dnsproxy.js:250
msgid "Min TTL value for DNS entries, in seconds"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:142
+#: htdocs/luci-static/resources/view/dnsproxy.js:240
msgid "Optimistic Cache"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:130
-msgid "Parallel queries all upstream"
+#: htdocs/luci-static/resources/view/dnsproxy.js:18
+msgid "Parallel"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:124
+#: htdocs/luci-static/resources/view/dnsproxy.js:354
+msgid "Profile name"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:219
msgid "Ratelimit (requests per second)"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:115
+#: htdocs/luci-static/resources/view/dnsproxy.js:209
msgid "Refuse ANY requests"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:132
-msgid "Respond to A or AAAA requests only with the fastest IP address"
-msgstr ""
-
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:54
+#: htdocs/luci-static/resources/view/dnsproxy.js:148
msgid "SERVER NOT RUNNING"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:52
+#: htdocs/luci-static/resources/view/dnsproxy.js:146
msgid "SERVER RUNNING"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:127
+#: htdocs/luci-static/resources/view/dnsproxy.js:222
msgid "Size of the UDP buffer in bytes. Set 0 use the system default"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:121
+#: htdocs/luci-static/resources/view/dnsproxy.js:58
+msgid "The selected DNS profile has no upstream servers."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:54
+msgid ""
+"The selected DNS profile no longer exists. Reload the page and try again."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:216
msgid "Timeout for queries to remote upstream (default: 10s)"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:202
+#: htdocs/luci-static/resources/view/dnsproxy.js:388
+msgid "Upstream DNS"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:326
msgid "Upstream DNS Server"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:195
+#: htdocs/luci-static/resources/view/dnsproxy.js:225
+#: htdocs/luci-static/resources/view/dnsproxy.js:358
+msgid "Upstream selection mode"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:293
msgid "Upstreams"
msgstr ""
-#: applications/luci-app-dnsproxy/htdocs/luci-static/resources/view/dnsproxy.js:81
+#: htdocs/luci-static/resources/view/dnsproxy.js:214
+msgid "Use HTTP/3 when it is faster. HTTPS fallback remains available."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:314
+msgid "Use selected profile"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:175
msgid "Verbose"
msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:18
+msgid "first DNS response wins."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:81
+msgid "non-empty value"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:17
+msgid "one upstream per request."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:19
+msgid "tests returned IP addresses."
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:90
+msgid "unique value"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:122
+msgid "valid URL"
+msgstr ""
+
+#: htdocs/luci-static/resources/view/dnsproxy.js:114
+msgid "valid host or hostport"
+msgstr ""
diff --git a/luci-app-dnsproxy/root/etc/uci-defaults/99-luci-app-dnsproxy-defaults b/luci-app-dnsproxy/root/etc/uci-defaults/99-luci-app-dnsproxy-defaults
new file mode 100755
index 00000000..199d5fef
--- /dev/null
+++ b/luci-app-dnsproxy/root/etc/uci-defaults/99-luci-app-dnsproxy-defaults
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+add_cloudflare_profile() {
+ uci set dnsproxy.preset_cloudflare='profile'
+ uci set dnsproxy.preset_cloudflare.label='Preset: Cloudflare DoH'
+ uci add_list dnsproxy.preset_cloudflare.bootstrap='1.1.1.1:53'
+ uci add_list dnsproxy.preset_cloudflare.bootstrap='1.0.0.1:53'
+ uci add_list dnsproxy.preset_cloudflare.upstream='https://cloudflare-dns.com/dns-query'
+ uci add_list dnsproxy.preset_cloudflare.fallback='https://dns.quad9.net/dns-query'
+ uci set dnsproxy.preset_cloudflare.upstream_mode='load_balance'
+}
+
+add_quad9_profile() {
+ uci set dnsproxy.preset_quad9='profile'
+ uci set dnsproxy.preset_quad9.label='Preset: Quad9 DoH'
+ uci add_list dnsproxy.preset_quad9.bootstrap='9.9.9.9:53'
+ uci add_list dnsproxy.preset_quad9.bootstrap='149.112.112.112:53'
+ uci add_list dnsproxy.preset_quad9.upstream='https://dns.quad9.net/dns-query'
+ uci add_list dnsproxy.preset_quad9.fallback='https://cloudflare-dns.com/dns-query'
+ uci set dnsproxy.preset_quad9.upstream_mode='load_balance'
+}
+
+add_google_profile() {
+ uci set dnsproxy.preset_google='profile'
+ uci set dnsproxy.preset_google.label='Preset: Google DoH'
+ uci add_list dnsproxy.preset_google.bootstrap='8.8.8.8:53'
+ uci add_list dnsproxy.preset_google.bootstrap='8.8.4.4:53'
+ uci add_list dnsproxy.preset_google.upstream='https://dns.google/dns-query'
+ uci add_list dnsproxy.preset_google.fallback='https://cloudflare-dns.com/dns-query'
+ uci set dnsproxy.preset_google.upstream_mode='load_balance'
+}
+
+add_fast_mixed_profile() {
+ uci set dnsproxy.preset_fast_mixed='profile'
+ uci set dnsproxy.preset_fast_mixed.label='Preset: Fast mixed DoH'
+ uci add_list dnsproxy.preset_fast_mixed.bootstrap='1.1.1.1:53'
+ uci add_list dnsproxy.preset_fast_mixed.bootstrap='9.9.9.9:53'
+ uci add_list dnsproxy.preset_fast_mixed.bootstrap='8.8.8.8:53'
+ uci add_list dnsproxy.preset_fast_mixed.upstream='https://cloudflare-dns.com/dns-query'
+ uci add_list dnsproxy.preset_fast_mixed.upstream='https://dns.quad9.net/dns-query'
+ uci add_list dnsproxy.preset_fast_mixed.fallback='https://dns.google/dns-query'
+ uci set dnsproxy.preset_fast_mixed.upstream_mode='parallel'
+}
+
+# preset
+if [ -z "$(uci -q get dnsproxy.default)" ]; then
+ uci -q get dnsproxy.preset_cloudflare >/dev/null || add_cloudflare_profile
+ uci -q get dnsproxy.preset_quad9 >/dev/null || add_quad9_profile
+ uci -q get dnsproxy.preset_google >/dev/null || add_google_profile
+ uci -q get dnsproxy.preset_fast_mixed >/dev/null || add_fast_mixed_profile
+ uci commit dnsproxy
+ # default
+ echo "config profile 'default'" >> /etc/config/dnsproxy
+ echo " option label 'Default'" >> /etc/config/dnsproxy
+ sed -n "/config dnsproxy 'servers'/,/^[^\t]/{/^\t/p}" /etc/config/dnsproxy >> /etc/config/dnsproxy
+fi
+
+exit 0
diff --git a/luci-app-passwall2/luasrc/controller/passwall2.lua b/luci-app-passwall2/luasrc/controller/passwall2.lua
index a5a1f8fe..f4b2fbf8 100644
--- a/luci-app-passwall2/luasrc/controller/passwall2.lua
+++ b/luci-app-passwall2/luasrc/controller/passwall2.lua
@@ -249,7 +249,7 @@ end
function get_redir_log()
local id = http.formvalue("id")
local name = http.formvalue("name")
- local file_path = "/tmp/etc/passwall2/acl/" .. id .. "/" .. name .. ".log"
+ local file_path = api.TMP_PATH .. "/acl/" .. id .. "/" .. name .. ".log"
if nixio.fs.access(file_path) then
local content = luci.sys.exec("tail -n 19999 '" .. file_path .. "'")
content = content:gsub("\n", "
")
@@ -261,7 +261,7 @@ end
function get_socks_log()
local name = http.formvalue("name")
- local path = "/tmp/etc/passwall2/" .. name .. ".log"
+ local path = api.TMP_PATH .. "/" .. name .. ".log"
if nixio.fs.access(path) then
local content = luci.sys.exec("tail -n 5000 ".. path)
content = content:gsub("\n", "
")
@@ -294,7 +294,7 @@ end
function index_status()
local e = {}
- e["global_status"] = luci.sys.call("/bin/busybox top -bn1 | grep -v 'grep' | grep '/tmp/etc/passwall2/bin/' | grep 'default' | grep 'global' >/dev/null") == 0
+ e["global_status"] = luci.sys.call("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/bin/' | grep 'default' | grep 'global' >/dev/null" % api.TMP_PATH) == 0
http_write_json(e)
end
@@ -665,8 +665,9 @@ end
function server_log()
local id = http.formvalue("id")
- if nixio.fs.access("/tmp/etc/passwall2_server/" .. id .. ".log") then
- local content = luci.sys.exec("cat /tmp/etc/passwall2_server/" .. id .. ".log")
+ local f_file = api.S_TMP_PATH .. "/" .. id .. ".log"
+ if nixio.fs.access(f_file) then
+ local content = luci.sys.exec("cat " .. f_file)
content = content:gsub("\n", "
")
http.write(content)
else
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua
index e32df176..cdf7870e 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua
@@ -2,9 +2,10 @@ local api = require "luci.passwall2.api"
api.set_default_cbi()
m = Map()
+m.redirect = api.url("acl")
if not arg[1] or not m:get(arg[1]) then
- luci.http.redirect(api.url("acl"))
+ luci.http.redirect(m.redirect)
end
m:appendTemplate("/cbi/nodes_listvalue_com")
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua
index 3bbe3cb0..242126af 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua
@@ -2,13 +2,12 @@ api = require "luci.passwall2.api"
api.set_default_cbi()
m = Map()
-m.redirect = api.url()
+m.redirect = api.url("node_list")
if not arg[1] or not m:get(arg[1]) then
- luci.http.redirect(api.url("node_list"))
+ luci.http.redirect(m.redirect)
end
-fs = require "nixio.fs"
formvalue_key = "cbid." .. m.config .. "." .. arg[1] .. "."
m:appendTemplate("/node_config/header", {section = arg[1]})
@@ -24,7 +23,7 @@ m:foreach("nodes", function(s)
end
end)
-s = m:section(NamedSection, arg[1], "nodes", translate("Node Config"))
+local s = m:section(NamedSection, arg[1], "nodes", translate("Node Config"))
s.addremove = false
s.dynamic = false
@@ -74,7 +73,7 @@ end
o = s:option(ListValue, "type", translate("Type"))
local type_table = {}
-for filename in fs.dir(types_dir) do
+for filename in api.fs.dir(types_dir) do
table.insert(type_table, filename)
end
table.sort(type_table)
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua
index 5237e4e6..65dd0ed8 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua
@@ -2,9 +2,10 @@ local api = require "luci.passwall2.api"
api.set_default_cbi()
m = Map()
+m.redirect = api.url()
if not arg[1] or not m:get(arg[1]) then
- luci.http.redirect(api.url())
+ luci.http.redirect(m.redirect)
end
m:appendTemplate("/cbi/nodes_dynamiclist_com")
@@ -75,6 +76,20 @@ o = s:option(Flag, "log", translate("Enable") .. " " .. translate("Log"))
o.default = 1
o.rmempty = false
+o = s:option(DummyValue, "_log", translate("Log File"))
+o.rawhtml = true
+o.cfgvalue = function(t, n)
+ local log_path = api.TMP_PATH .. "/" .. arg[1] .. ".log"
+ local log_url = api.url("get_socks_log") .. "?name=" .. arg[1]
+ return string.format(
+ '%s ',
+ log_path,
+ translate("View Log"),
+ log_url
+ )
+end
+o:depends("log", true)
+
o = s:option(Flag, "enable_autoswitch", translate("Auto Switch"))
o.default = 0
o.rmempty = false
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua
index bc3c4946..753c748a 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua
@@ -1,51 +1,43 @@
-local m, s = ...
-
if not api.finded_com("hysteria") then
return
end
-type_name = "Hysteria2"
-
-- [[ Hysteria2 ]]
+local m, s1 = ...
+local type_name = "Hysteria2"
-s.fields["type"]:value(type_name, "Hysteria2")
+s1.fields["type"]:value(type_name, "Hysteria2")
-if s.val["type"] ~= type_name then
+if s1.val["type"] ~= type_name then
return
end
-local option_prefix = "hysteria2_"
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "hysteria2_"
-local function _n(name)
- return option_prefix .. name
-end
+o = s:option(Value, "address", translate("Address (Support Domain Name)"))
+o:depends({ realms = false })
-o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
-o:depends({ [_n("realms")] = false })
-
-o = s:option(Value, _n("port"), translate("Port"))
+o = s:option(Value, "port", translate("Port"))
o.datatype = "port"
-o:depends({ [_n("realms")] = false })
+o:depends({ realms = false })
-o = s:option(Value, _n("hop"), translate("Port hopping range"))
+o = s:option(Value, "hop", translate("Port hopping range"))
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
-o.rewrite_option = o.option
-o:depends({ [_n("realms")] = false })
+o:depends({ realms = false })
-o = s:option(Value, _n("hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
+o = s:option(Value, "hop_interval", translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
o.datatype = "or(uinteger,portrange)"
o.placeholder = "30"
o.default = "30"
-o.rewrite_option = o.option
-o:depends({ [_n("realms")] = false })
+o:depends({ realms = false })
-o = s:option(Flag, _n("realms"), translate("Realms"))
+o = s:option(Flag, "realms", translate("Realms"))
o.default = "0"
-o.rewrite_option = o.option
-o = s:option(Value, _n("realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
-o.rewrite_option = o.option
-o:depends({ [_n("realms")] = "1" })
+o = s:option(Value, "realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
+o:depends({ realms = "1" })
o.validate = function(self, value)
value = api.trim(value)
local realm = api.parse_realm_uri(value)
@@ -53,76 +45,62 @@ o.validate = function(self, value)
return nil, translate("Invalid Realm URL.")
end
-o = s:option(DynamicList, _n("realm_stun"), translate("Realm STUN"))
+o = s:option(DynamicList, "realm_stun", translate("Realm STUN"))
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
-o.rewrite_option = o.option
-o:depends({ [_n("realms")] = "1" })
+o:depends({ realms = "1" })
-o = s:option(Value, _n("auth_password"), translate("Auth Password"))
+o = s:option(Value, "auth_password", translate("Auth Password"))
o.password = true
-o.rewrite_option = o.option
-o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
+o = s:option(ListValue, "obfs_type", translate("Obfs Type"))
o:value("", translate("Disable"))
o:value("salamander")
o:value("gecko")
-o.rewrite_option = o.option
-o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
-o.rewrite_option = o.option
-o:depends({ [_n("obfs_type")] = "salamander" })
-o:depends({ [_n("obfs_type")] = "gecko" })
+o = s:option(Value, "obfs_password", translate("Obfs Password"))
+o:depends({ obfs_type = "salamander" })
+o:depends({ obfs_type = "gecko" })
-o = s:option(Value, _n("obfs_MinPacketSize"), translate("Gecko Packet Size (min)"))
+o = s:option(Value, "obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
o.datatype = "uinteger"
o.placeholder = "512"
o.default = "512"
-o:depends({ [_n("obfs_type")] = "gecko" })
-o.rewrite_option = o.option
+o:depends({ obfs_type = "gecko" })
-o = s:option(Value, _n("obfs_MaxPacketSize"), translate("Gecko Packet Size (max)"))
+o = s:option(Value, "obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
o.datatype = "uinteger"
o.placeholder = "1200"
o.default = "1200"
-o:depends({ [_n("obfs_type")] = "gecko" })
-o.rewrite_option = o.option
+o:depends({ obfs_type = "gecko" })
-o = s:option(Flag, _n("fast_open"), translate("Fast Open"))
+o = s:option(Flag, "fast_open", translate("Fast Open"))
o.default = "0"
-o = s:option(Value, _n("tls_serverName"), translate("Domain"))
+o = s:option(Value, "tls_serverName", translate("Domain"))
-o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
+o = s:option(Flag, "tls_allowInsecure", translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
o.default = "0"
-o = s:option(Value, _n("tls_pinSHA256"), translate("PinSHA256"),translate("Certificate fingerprint"))
+o = s:option(Value, "tls_pinSHA256", translate("PinSHA256"),translate("Certificate fingerprint"))
-o = s:option(Value, _n("up_mbps"), translate("Max upload Mbps"))
-o.rewrite_option = o.option
+o = s:option(Value, "up_mbps", translate("Max upload Mbps"))
-o = s:option(Value, _n("down_mbps"), translate("Max download Mbps"))
-o.rewrite_option = o.option
+o = s:option(Value, "down_mbps", translate("Max download Mbps"))
-o = s:option(Value, _n("recv_window"), translate("QUIC stream receive window"))
-o.rewrite_option = o.option
+o = s:option(Value, "recv_window", translate("QUIC stream receive window"))
-o = s:option(Value, _n("recv_window_conn"), translate("QUIC connection receive window"))
-o.rewrite_option = o.option
+o = s:option(Value, "recv_window_conn", translate("QUIC connection receive window"))
-o = s:option(Value, _n("idle_timeout"), translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
+o = s:option(Value, "idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
o.datatype = "range(4,120)"
-o.rewrite_option = o.option
-o = s:option(Value, _n("keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
+o = s:option(Value, "keep_alive_period", translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
o.datatype = "range(2,60)"
-o.rewrite_option = o.option
-o = s:option(Flag, _n("disable_mtu_discovery"), translate("Disable MTU detection"))
+o = s:option(Flag, "disable_mtu_discovery", translate("Disable MTU detection"))
o.default = "0"
-o.rewrite_option = o.option
-o = s:option(Flag, _n("lazy_start"), translate("Lazy Start"))
+o = s:option(Flag, "lazy_start", translate("Lazy Start"))
o.default = "0"
-o.rewrite_option = o.option
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/naive.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/naive.lua
index 621596fd..4d5c55ac 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/naive.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/naive.lua
@@ -1,37 +1,33 @@
-local m, s = ...
-
if not api.is_finded("naive") then
return
end
-type_name = "Naiveproxy"
-
-- [[ Naive ]]
+local m, s1 = ...
+local type_name = "Naiveproxy"
-s.fields["type"]:value(type_name, "NaiveProxy")
+s1.fields["type"]:value(type_name, "NaiveProxy")
-if s.val["type"] ~= type_name then
+if s1.val["type"] ~= type_name then
return
end
-local option_prefix = "naive_"
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "naive_"
-local function _n(name)
- return option_prefix .. name
-end
-
-o = s:option(ListValue, _n("protocol"), translate("Protocol"))
+o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("https", translate("HTTPS"))
o:value("quic", translate("QUIC"))
-o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
+o = s:option(Value, "address", translate("Address (Support Domain Name)"))
-o = s:option(Value, _n("port"), translate("Port"))
+o = s:option(Value, "port", translate("Port"))
o.datatype = "port"
-o = s:option(Value, _n("username"), translate("Username"))
+o = s:option(Value, "username", translate("Username"))
-o = s:option(Value, _n("password"), translate("Password"))
+o = s:option(Value, "password", translate("Password"))
o.password = true
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua
index 113209b3..d7827092 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua
@@ -1,33 +1,27 @@
-local m, s = ...
-
if not api.finded_com("xray") then
return
end
-local jsonc = api.jsonc
-
-type_name = "Xray"
-
-- [[ Xray ]]
+local m, s1 = ...
+local type_name = "Xray"
-s.fields["type"]:value(type_name, "Xray")
-if not s.fields["type"].default then
- s.fields["type"].default = type_name
+s1.fields["type"]:value(type_name, "Xray")
+if not s1.fields["type"].default then
+ s1.fields["type"].default = type_name
end
-if s.val["type"] ~= type_name then
+if s1.val["type"] ~= type_name then
return
end
-local option_prefix = "xray_"
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "xray_"
-local function _n(name)
- return option_prefix .. name
-end
+local formvalue_proto = luci.http.formvalue(formvalue_key .. "protocol")
-local formvalue_proto = luci.http.formvalue(formvalue_key .. _n("protocol"))
-
-if formvalue_proto then s.val["protocol"] = formvalue_proto end
+if formvalue_proto then s1.val["protocol"] = formvalue_proto end
local arg_select_proto = luci.http.formvalue("select_proto") or ""
@@ -43,7 +37,7 @@ local header_type_list = {
local xray_version = api.get_app_version("xray")
-o = s:option(ListValue, _n("protocol"), translate("Protocol"))
+o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("vmess", translate("Vmess"))
o:value("vless", translate("VLESS"))
o:value("http", translate("HTTP"))
@@ -63,13 +57,13 @@ function o.custom_cfgvalue(self, section)
if arg_select_proto ~= "" then
return arg_select_proto
else
- return m:get(section, self.option:sub(1 + #option_prefix))
+ return m:get(section, self.config_option)
end
end
-local load_balancing_options = s.val["protocol"] == "_balancing" or arg_select_proto == "_balancing"
-local load_shunt_options = s.val["protocol"] == "_shunt" or arg_select_proto == "_shunt"
-local load_iface_options = s.val["protocol"] == "_iface" or arg_select_proto == "_iface"
+local load_balancing_options = s1.val["protocol"] == "_balancing" or arg_select_proto == "_balancing"
+local load_shunt_options = s1.val["protocol"] == "_shunt" or arg_select_proto == "_shunt"
+local load_iface_options = s1.val["protocol"] == "_iface" or arg_select_proto == "_iface"
local load_normal_options = true
if load_balancing_options or load_shunt_options or load_iface_options then
load_normal_options = nil
@@ -96,14 +90,14 @@ for k, e in ipairs(node_list.balancing_list or {}) do
end
if load_balancing_options then -- [[ Load balancing Start ]]
- o = s:option(ListValue, _n("node_add_mode"), translate("Node Addition Method"))
- o:depends({ [_n("protocol")] = "_balancing" })
+ o = s:option(ListValue, "node_add_mode", translate("Node Addition Method"))
+ o:depends({ protocol = "_balancing" })
o.default = "manual"
o:value("manual", translate("Manual"))
o:value("batch", translate("Batch"))
- o = s:option(MultiValue, _n("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, document"))
- o:depends({ [_n("node_add_mode")] = "manual" })
+ o = s:option(MultiValue, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, document"))
+ o:depends({ node_add_mode = "manual" })
o.widget = "checkbox"
o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {}
@@ -140,16 +134,16 @@ if load_balancing_options then -- [[ Load balancing Start ]]
end
end
- o = s:option(MultiValue, _n("node_group"), translate("Select Group"))
- o:depends({ [_n("node_add_mode")] = "batch" })
+ o = s:option(MultiValue, "node_group", translate("Select Group"))
+ o:depends({ node_add_mode = "batch" })
o.widget = "checkbox"
o:value("default", translate("default"))
for k, v in pairs(groups) do
o:value(api.UrlEncode(k), k)
end
- o = s:option(Value, _n("node_match_rule"), translate("Node Matching Rules"))
- o:depends({ [_n("node_add_mode")] = "batch" })
+ o = s:option(Value, "node_match_rule", translate("Node Matching Rules"))
+ o:depends({ node_add_mode = "batch" })
local descrStr = "Example: ^A && B && !C && D$
"
descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).
"
descrStr = descrStr .. "Conditions are joined by && (AND), and their order does not affect the result.
"
@@ -157,8 +151,8 @@ if load_balancing_options then -- [[ Load balancing Start ]]
descrStr = descrStr .. "Example: A && B || C && D means (A AND B) OR (C AND D)."
o.description = translate(descrStr)
- o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy"))
- o:depends({ [_n("protocol")] = "_balancing" })
+ o = s:option(ListValue, "balancingStrategy", translate("Balancing Strategy"))
+ o:depends({ protocol = "_balancing" })
o:value("random")
o:value("roundRobin")
o:value("leastPing")
@@ -166,11 +160,11 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o.default = "random"
-- Fallback Node
- o = s:option(ListValue, _n("fallback_node"), translate("Fallback Node"))
+ o = s:option(ListValue, "fallback_node", translate("Fallback Node"))
o.group = {"",""}
o:value("", translate("Close(Not use)"))
o:value("_direct", translate("Direct Connection"))
- o:depends({ [_n("protocol")] = "_balancing" })
+ o:depends({ protocol = "_balancing" })
o.template = m:template_path("/cbi/nodes_listvalue")
-- Maximum number of fallback nesting layers
local MAX_FALLBACK_DEPTH = 3
@@ -234,11 +228,11 @@ if load_balancing_options then -- [[ Load balancing Start ]]
end
end
- o = s:option(Flag, _n("useCustomProbeUrl"), translate("Use Custom Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
- o:depends({ [_n("protocol")] = "_balancing" })
+ o = s:option(Flag, "useCustomProbeUrl", translate("Use Custom Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
+ o:depends({ protocol = "_balancing" })
- o = s:option(Value, _n("probeUrl"), translate("Probe URL"))
- o:depends({ [_n("useCustomProbeUrl")] = true })
+ o = s:option(Value, "probeUrl", translate("Probe URL"))
+ o:depends({ useCustomProbeUrl = true })
o:value("https://cp.cloudflare.com/", "Cloudflare")
o:value("https://www.gstatic.com/generate_204", "Gstatic")
o:value("https://www.google.com/generate_204", "Google")
@@ -249,23 +243,23 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o.default = o.keylist[3]
o.description = translate("The URL used to detect the connection status.")
- o = s:option(Value, _n("probeInterval"), translate("Probe Interval"))
- o:depends({ [_n("protocol")] = "_balancing" })
+ o = s:option(Value, "probeInterval", translate("Probe Interval"))
+ o:depends({ protocol = "_balancing" })
o.default = "1m"
o.placeholder = "1m"
o.description = translate("The interval between initiating probes.") .. "
" ..
translate("The time format is numbers + units, such as '10s', '2h45m', and the supported time units are s, m, h, which correspond to seconds, minutes, and hours, respectively.") .. "
" ..
translate("When the unit is not filled in, it defaults to seconds.")
- o = s:option(Value, _n("expected"), translate("Preferred Node Count"))
- o:depends({ [_n("balancingStrategy")] = "leastLoad" })
+ o = s:option(Value, "expected", translate("Preferred Node Count"))
+ o:depends({ balancingStrategy = "leastLoad" })
o.datatype = "uinteger"
o.default = "2"
o.placeholder = "2"
o.description = translate("The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them.")
- o = s:option(Value, _n("tolerance"), translate("Failure Tolerance (%)"))
- o:depends({ [_n("balancingStrategy")] = "leastLoad" })
+ o = s:option(Value, "tolerance", translate("Failure Tolerance (%)"))
+ o:depends({ balancingStrategy = "leastLoad" })
o.datatype = "uinteger"
o.default = "10"
o.placeholder = "10"
@@ -273,8 +267,8 @@ if load_balancing_options then -- [[ Load balancing Start ]]
end -- [[ Load balancing End ]]
if load_iface_options then -- [[ Custom Interface Start ]]
- o = s:option(Value, _n("iface"), translate("Interface"))
- o:depends({ [_n("protocol")] = "_iface" })
+ o = s:option(Value, "iface", translate("Interface"))
+ o:depends({ protocol = "_iface" })
for _, d in ipairs(netdev_list) do
o:value(d.name, d.label)
end
@@ -284,73 +278,72 @@ end -- [[ Custom Interface End ]]
-- [[ Normal single node Start ]]
if load_normal_options then
-o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
+o = s:option(Value, "address", translate("Address (Support Domain Name)"))
-o = s:option(Value, _n("port"), translate("Port"))
+o = s:option(Value, "port", translate("Port"))
o.datatype = "port"
-o = s:option(Value, _n("uuid"), translate("ID"))
+o = s:option(Value, "uuid", translate("ID"))
o.password = true
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
-o = s:option(Value, _n("username"), translate("Username"))
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
+o = s:option(Value, "username", translate("Username"))
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
-o = s:option(Value, _n("password"), translate("Password"))
+o = s:option(Value, "password", translate("Password"))
o.password = true
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "trojan" })
-o = s:option(ListValue, _n("security"), translate("Encrypt Method"))
+o = s:option(ListValue, "security", translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end
-o:depends({ [_n("protocol")] = "vmess" })
+o:depends({ protocol = "vmess" })
-o = s:option(Value, _n("encryption"), translate("Encrypt Method") .. " (encryption)")
+o = s:option(Value, "encryption", translate("Encrypt Method") .. " (encryption)")
o.default = "none"
o.placeholder = "none"
-o:depends({ [_n("protocol")] = "vless" })
+o:depends({ protocol = "vless" })
o.validate = function(self, value)
value = api.trim(value)
return (value == "" and "none" or value)
end
-o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
-o.rewrite_option = "method"
+o = s:option(ListValue, "ss_method", translate("Encrypt Method"))
for a, t in ipairs(ss_method_list) do o:value(t) end
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o:depends({ protocol = "shadowsocks" })
-o = s:option(ListValue, _n("flow"), translate("flow"))
+o = s:option(ListValue, "flow", translate("flow"))
o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
o:value("xtls-rprx-vision-udp443")
-o:depends({ [_n("protocol")] = "vless" })
+o:depends({ protocol = "vless" })
---- [[hysteria2]]
-o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range"))
+o = s:option(Value, "hysteria2_hop", translate("Port hopping range"))
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+o:depends({ protocol = "hysteria2", hysteria2_realms = false })
-o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
+o = s:option(Value, "hysteria2_hop_interval", translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
o.datatype = "or(uinteger,portrange)"
o.placeholder = "30"
o.default = "30"
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+o:depends({ protocol = "hysteria2", hysteria2_realms = false })
-o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
+o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
if api.compare_versions(xray_version, ">", "26.5.9") then
- o:depends({ [_n("protocol")] = "hysteria2"})
+ o:depends({ protocol = "hysteria2"})
else
- o:depends({ [_n("protocol")] = "__hide"})
+ o:depends({ protocol = "__hide"})
end
-o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
-o:depends({ [_n("hysteria2_realms")] = "1" })
+o = s:option(Value, "hysteria2_realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
+o:depends({ hysteria2_realms = "1" })
o.validate = function(self, value)
value = api.trim(value)
local realm = api.parse_realm_uri(value)
@@ -358,73 +351,73 @@ o.validate = function(self, value)
return nil, translate("Invalid Realm URL.")
end
-o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
+o = s:option(DynamicList, "hysteria2_realm_stun", translate("Realm STUN"))
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
-o:depends({ [_n("hysteria2_realms")] = "1" })
+o:depends({ hysteria2_realms = "1" })
-o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
+o = s:option(Value, "hysteria2_auth_password", translate("Auth Password"))
o.password = true
-o:depends({ [_n("protocol")] = "hysteria2"})
+o:depends({ protocol = "hysteria2"})
-o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
+o = s:option(ListValue, "hysteria2_obfs_type", translate("Obfs Type"))
o:value("", translate("Disable"))
o:value("salamander")
o:value("gecko")
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ protocol = "hysteria2" })
-o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
-o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
-o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+o = s:option(Value, "hysteria2_obfs_password", translate("Obfs Password"))
+o:depends({ hysteria2_obfs_type = "salamander" })
+o:depends({ hysteria2_obfs_type = "gecko" })
-o = s:option(Value, _n("hysteria2_obfs_MinPacketSize"), translate("Gecko Packet Size (min)"))
+o = s:option(Value, "hysteria2_obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
o.datatype = "uinteger"
o.placeholder = "512"
o.default = "512"
-o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+o:depends({ hysteria2_obfs_type = "gecko" })
-o = s:option(Value, _n("hysteria2_obfs_MaxPacketSize"), translate("Gecko Packet Size (max)"))
+o = s:option(Value, "hysteria2_obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
o.datatype = "uinteger"
o.placeholder = "1200"
o.default = "1200"
-o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+o:depends({ hysteria2_obfs_type = "gecko" })
-o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
-o:depends({ [_n("protocol")] = "hysteria2" })
+o = s:option(Value, "hysteria2_up_mbps", translate("Max upload Mbps"))
+o:depends({ protocol = "hysteria2" })
-o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
-o:depends({ [_n("protocol")] = "hysteria2" })
+o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps"))
+o:depends({ protocol = "hysteria2" })
-o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
+o = s:option(Value, "hysteria2_idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
o.datatype = "range(4,120)"
-o:depends({ [_n("protocol")] = "hysteria2"})
+o:depends({ protocol = "hysteria2"})
-o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
+o = s:option(Value, "hysteria2_keep_alive_period", translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
o.datatype = "range(2,60)"
-o:depends({ [_n("protocol")] = "hysteria2"})
+o:depends({ protocol = "hysteria2"})
-o = s:option(Flag, _n("hysteria2_disable_mtu_discovery"), translate("Disable MTU detection"))
+o = s:option(Flag, "hysteria2_disable_mtu_discovery", translate("Disable MTU detection"))
o.default = "0"
-o:depends({ [_n("protocol")] = "hysteria2"})
+o:depends({ protocol = "hysteria2"})
---- [[hysteria2 end]]
-o = s:option(Flag, _n("tls"), translate("TLS"))
+o = s:option(Flag, "tls", translate("TLS"))
o.default = 0
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "trojan" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "trojan" })
+o:depends({ protocol = "shadowsocks" })
-o = s:option(Flag, _n("reality"), translate("REALITY"))
+o = s:option(Flag, "reality", translate("REALITY"))
o.default = 0
-o:depends({ [_n("tls")] = true, [_n("transport")] = "raw" })
-o:depends({ [_n("tls")] = true, [_n("transport")] = "ws" })
-o:depends({ [_n("tls")] = true, [_n("transport")] = "grpc" })
-o:depends({ [_n("tls")] = true, [_n("transport")] = "httpupgrade" })
-o:depends({ [_n("tls")] = true, [_n("transport")] = "xhttp" })
+o:depends({ tls = true, transport = "raw" })
+o:depends({ tls = true, transport = "ws" })
+o:depends({ tls = true, transport = "grpc" })
+o:depends({ tls = true, transport = "httpupgrade" })
+o:depends({ tls = true, transport = "xhttp" })
-o = s:option(ListValue, _n("alpn"), translate("alpn"))
+o = s:option(ListValue, "alpn", translate("alpn"))
o.default = "default"
o:value("default", translate("Default"))
o:value("h3")
@@ -433,72 +426,72 @@ o:value("h3,h2")
o:value("http/1.1")
o:value("h2,http/1.1")
o:value("h3,h2,http/1.1")
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
+o:depends({ tls = true, reality = false })
--- o = s:option(Value, _n("minversion"), translate("minversion"))
+-- o = s:option(Value, "minversion", translate("minversion"))
-- o.default = "1.3"
-- o:value("1.3")
--- o:depends({ [_n("tls")] = true })
+-- o:depends({ tls = true })
-o = s:option(Value, _n("tls_serverName"), "SNI " .. translate("Domain"))
-o:depends({ [_n("tls")] = true })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o = s:option(Value, "tls_serverName", "SNI " .. translate("Domain"))
+o:depends({ tls = true })
+o:depends({ protocol = "hysteria2" })
-o = s:option(Value, _n("tls_pinSHA256"), translate("TLS Chain Fingerprint (SHA256)"))
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o = s:option(Value, "tls_pinSHA256", translate("TLS Chain Fingerprint (SHA256)"))
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria2" })
o.description = translate("Once set, connects only when the server’s chain fingerprint matches.") ..
string.format("%s", "→ " .. translate("Fetch Manually"))
-o = s:option(Value, _n("tls_CertByName"), translate("TLS Certificate Name (CertName)"), translate("TLS is used to verify the leaf certificate name."))
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o = s:option(Value, "tls_CertByName", translate("TLS Certificate Name (CertName)"), translate("TLS is used to verify the leaf certificate name."))
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria2" })
-o = s:option(Flag, _n("tls_certificate"), translate("TLS Certificate (PEM)"))
+o = s:option(Flag, "tls_certificate", translate("TLS Certificate (PEM)"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria2" })
-o = s:option(TextValue, _n("tls_certificate_pem"), " ", translate("Full certificate (chain), PEM format."))
+o = s:option(TextValue, "tls_certificate_pem", " ", translate("Full certificate (chain), PEM format."))
o.default = ""
o.rows = 5
o.wrap = "off"
-o:depends({ [_n("tls_certificate")] = true })
+o:depends({ tls_certificate = true })
o.validate = function(self, value)
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
return value
end
-o = s:option(Flag, _n("ech"), translate("ECH"))
+o = s:option(Flag, "ech", translate("ECH"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria2", hysteria2_realms = false })
-o = s:option(TextValue, _n("ech_config"), translate("ECH Config"))
+o = s:option(TextValue, "ech_config", translate("ECH Config"))
o.default = ""
o.rows = 5
o.wrap = "soft"
-o:depends({ [_n("ech")] = true })
+o:depends({ ech = true })
o.validate = function(self, value)
return api.trim(value:gsub("[\r\n]", ""))
end
-- [[ REALITY ]] --
-o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
-o:depends({ [_n("tls")] = true, [_n("reality")] = true })
+o = s:option(Value, "reality_publicKey", translate("Public Key"))
+o:depends({ tls = true, reality = true })
-o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
-o:depends({ [_n("tls")] = true, [_n("reality")] = true })
+o = s:option(Value, "reality_shortId", translate("Short Id"))
+o:depends({ tls = true, reality = true })
-o = s:option(Value, _n("reality_spiderX"), translate("Spider X"))
+o = s:option(Value, "reality_spiderX", translate("Spider X"))
o.placeholder = "/"
-o:depends({ [_n("tls")] = true, [_n("reality")] = true })
+o:depends({ tls = true, reality = true })
-o = s:option(Flag, _n("utls"), translate("uTLS"))
+o = s:option(Flag, "utls", translate("uTLS"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
+o:depends({ tls = true, reality = false })
-o = s:option(ListValue, _n("fingerprint"), translate("Finger Print"))
+o = s:option(ListValue, "fingerprint", translate("Finger Print"))
o:value("chrome")
o:value("firefox")
o:value("edge")
@@ -511,14 +504,14 @@ o:value("random")
o:value("randomized")
o:value("unsafe")
o.default = "chrome"
-o:depends({ [_n("tls")] = true, [_n("utls")] = true })
-o:depends({ [_n("tls")] = true, [_n("reality")] = true })
+o:depends({ tls = true, utls = true })
+o:depends({ tls = true, reality = true })
-o = s:option(Flag, _n("use_mldsa65Verify"), translate("ML-DSA-65"))
+o = s:option(Flag, "use_mldsa65Verify", translate("ML-DSA-65"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("reality")] = true })
+o:depends({ tls = true, reality = true })
-o = s:option(DynamicList, _n("cipherSuites"), translate("Cipher Suites"), '***' .. " " .. translate("Configures the list of supported cipher suites."))
+o = s:option(DynamicList, "cipherSuites", translate("Cipher Suites"), '***' .. " " .. translate("Configures the list of supported cipher suites."))
o:value("TLS_AES_128_GCM_SHA256")
o:value("TLS_AES_256_GCM_SHA384")
o:value("TLS_CHACHA20_POLY1305_SHA256")
@@ -532,154 +525,154 @@ o:value("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
o:value("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384")
o:value("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256")
o:value("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
+o:depends({ tls = true, reality = false })
-o = s:option(TextValue, _n("reality_mldsa65Verify"), "ML-DSA-65 " .. translate("Public key"))
+o = s:option(TextValue, "reality_mldsa65Verify", "ML-DSA-65 " .. translate("Public key"))
o.default = ""
o.rows = 5
o.wrap = "soft"
-o:depends({ [_n("use_mldsa65Verify")] = true })
+o:depends({ use_mldsa65Verify = true })
o.validate = function(self, value)
return api.trim(value:gsub("[\r\n]", ""))
end
-o = s:option(ListValue, _n("transport"), translate("Transport"))
+o = s:option(ListValue, "transport", translate("Transport"))
o:value("raw", "RAW (TCP)")
o:value("mkcp", "mKCP")
o:value("ws", "WebSocket")
o:value("grpc", "gRPC")
o:value("httpupgrade", "HttpUpgrade")
o:value("xhttp", "XHTTP")
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "trojan" })
-o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
-o:depends({ [_n("protocol")] = "wireguard" })
+o = s:option(Value, "wireguard_public_key", translate("Public Key"))
+o:depends({ protocol = "wireguard" })
-o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
-o:depends({ [_n("protocol")] = "wireguard" })
+o = s:option(Value, "wireguard_secret_key", translate("Private Key"))
+o:depends({ protocol = "wireguard" })
-o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
-o:depends({ [_n("protocol")] = "wireguard" })
+o = s:option(Value, "wireguard_preSharedKey", translate("Pre shared key"))
+o:depends({ protocol = "wireguard" })
-o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
-o:depends({ [_n("protocol")] = "wireguard" })
+o = s:option(DynamicList, "wireguard_local_address", translate("Local Address"))
+o:depends({ protocol = "wireguard" })
-o = s:option(Value, _n("wireguard_mtu"), translate("MTU"))
+o = s:option(Value, "wireguard_mtu", translate("MTU"))
o.default = "1420"
-o:depends({ [_n("protocol")] = "wireguard" })
+o:depends({ protocol = "wireguard" })
if api.compare_versions(xray_version, ">=", "1.8.0") then
- o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(Value, "wireguard_reserved", translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
+ o:depends({ protocol = "wireguard" })
end
-o = s:option(Value, _n("wireguard_keepAlive"), translate("Keep Alive"))
+o = s:option(Value, "wireguard_keepAlive", translate("Keep Alive"))
o.default = "0"
-o:depends({ [_n("protocol")] = "wireguard" })
+o:depends({ protocol = "wireguard" })
-- [[ RAW ]]--
-o = s:option(ListValue, _n("tcp_guise"), translate("Camouflage Type"))
+o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
o:value("none", "none")
o:value("http", "http")
-o:depends({ [_n("transport")] = "raw" })
+o:depends({ transport = "raw" })
-o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
-o:depends({ [_n("tcp_guise")] = "http" })
+o = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host"))
+o:depends({ tcp_guise = "http" })
-o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
+o = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path"))
o.placeholder = "/"
-o:depends({ [_n("tcp_guise")] = "http" })
+o:depends({ tcp_guise = "http" })
-- [[ mKCP ]]--
-o = s:option(ListValue, _n("mkcp_guise"), translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests.'))
+o = s:option(ListValue, "mkcp_guise", translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests.'))
for a, t in ipairs(header_type_list) do o:value(t) end
-o:depends({ [_n("transport")] = "mkcp" })
+o:depends({ transport = "mkcp" })
-o = s:option(Value, _n("mkcp_domain"), translate("Camouflage Domain"), translate("Use it together with the DNS disguised type. You can fill in any domain."))
-o:depends({ [_n("mkcp_guise")] = "dns" })
+o = s:option(Value, "mkcp_domain", translate("Camouflage Domain"), translate("Use it together with the DNS disguised type. You can fill in any domain."))
+o:depends({ mkcp_guise = "dns" })
-o = s:option(Value, _n("mkcp_mtu"), translate("KCP MTU"))
+o = s:option(Value, "mkcp_mtu", translate("KCP MTU"))
o.datatype = "uinteger"
o.default = 1350
-o:depends({ [_n("transport")] = "mkcp" })
+o:depends({ transport = "mkcp" })
-o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
-o:depends({ [_n("transport")] = "mkcp" })
+o = s:option(Value, "mkcp_seed", translate("KCP Seed"))
+o:depends({ transport = "mkcp" })
-- [[ WebSocket ]]--
-o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
-o:depends({ [_n("transport")] = "ws" })
+o = s:option(Value, "ws_host", translate("WebSocket Host"))
+o:depends({ transport = "ws" })
-o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
+o = s:option(Value, "ws_path", translate("WebSocket Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "ws" })
+o:depends({ transport = "ws" })
-o = s:option(Value, _n("ws_heartbeatPeriod"), translate("HeartbeatPeriod(second)"))
+o = s:option(Value, "ws_heartbeatPeriod", translate("HeartbeatPeriod(second)"))
o.datatype = "integer"
-o:depends({ [_n("transport")] = "ws" })
+o:depends({ transport = "ws" })
-- [[ gRPC ]]--
-o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
-o:depends({ [_n("transport")] = "grpc" })
+o = s:option(Value, "grpc_serviceName", "ServiceName")
+o:depends({ transport = "grpc" })
-o = s:option(ListValue, _n("grpc_mode"), "gRPC " .. translate("Transfer mode"))
+o = s:option(ListValue, "grpc_mode", "gRPC " .. translate("Transfer mode"))
o:value("gun")
o:value("multi")
-o:depends({ [_n("transport")] = "grpc" })
+o:depends({ transport = "grpc" })
-o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
-o:depends({ [_n("transport")] = "grpc" })
+o = s:option(Flag, "grpc_health_check", translate("Health check"))
+o:depends({ transport = "grpc" })
-o = s:option(Value, _n("grpc_idle_timeout"), translate("Idle timeout"))
+o = s:option(Value, "grpc_idle_timeout", translate("Idle timeout"))
o.default = "10"
-o:depends({ [_n("grpc_health_check")] = true })
+o:depends({ grpc_health_check = true })
-o = s:option(Value, _n("grpc_health_check_timeout"), translate("Health check timeout"))
+o = s:option(Value, "grpc_health_check_timeout", translate("Health check timeout"))
o.default = "20"
-o:depends({ [_n("grpc_health_check")] = true })
+o:depends({ grpc_health_check = true })
-o = s:option(Flag, _n("grpc_permit_without_stream"), translate("Permit without stream"))
+o = s:option(Flag, "grpc_permit_without_stream", translate("Permit without stream"))
o.default = "0"
-o:depends({ [_n("grpc_health_check")] = true })
+o:depends({ grpc_health_check = true })
-o = s:option(Value, _n("grpc_initial_windows_size"), translate("Initial Windows Size"))
+o = s:option(Value, "grpc_initial_windows_size", translate("Initial Windows Size"))
o.default = "0"
-o:depends({ [_n("transport")] = "grpc" })
+o:depends({ transport = "grpc" })
-- [[ HttpUpgrade ]]--
-o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
-o:depends({ [_n("transport")] = "httpupgrade" })
+o = s:option(Value, "httpupgrade_host", translate("HttpUpgrade Host"))
+o:depends({ transport = "httpupgrade" })
-o = s:option(Value, _n("httpupgrade_path"), translate("HttpUpgrade Path"))
+o = s:option(Value, "httpupgrade_path", translate("HttpUpgrade Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "httpupgrade" })
+o:depends({ transport = "httpupgrade" })
-- [[ XHTTP ]]--
-o = s:option(ListValue, _n("xhttp_mode"), "XHTTP " .. translate("Mode"))
-o:depends({ [_n("transport")] = "xhttp" })
+o = s:option(ListValue, "xhttp_mode", "XHTTP " .. translate("Mode"))
+o:depends({ transport = "xhttp" })
o.default = "auto"
o:value("auto")
o:value("packet-up")
o:value("stream-up")
o:value("stream-one")
-o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
-o:depends({ [_n("transport")] = "xhttp" })
+o = s:option(Value, "xhttp_host", translate("XHTTP Host"))
+o:depends({ transport = "xhttp" })
-o = s:option(Value, _n("xhttp_path"), translate("XHTTP Path"))
+o = s:option(Value, "xhttp_path", translate("XHTTP Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "xhttp" })
+o:depends({ transport = "xhttp" })
-o = s:option(Flag, _n("use_xhttp_extra"), translate("XHTTP Extra"))
+o = s:option(Flag, "use_xhttp_extra", translate("XHTTP Extra"))
o.default = "0"
-o:depends({ [_n("transport")] = "xhttp" })
+o:depends({ transport = "xhttp" })
-o = s:option(TextValue, _n("xhttp_extra"), " ", translate("An XHttpObject in JSON format, used for sharing."))
-o:depends({ [_n("use_xhttp_extra")] = true })
+o = s:option(TextValue, "xhttp_extra", " ", translate("An XHttpObject in JSON format, used for sharing."))
+o:depends({ use_xhttp_extra = true })
o.rows = 10
o.wrap = "off"
o.datatype = "json"
@@ -698,7 +691,7 @@ o.custom_cfgvalue = function(self, section, value)
end
o.custom_write = function(self, section, value)
m:set(section, "xhttp_extra", api.base64Encode(value) or "")
- local success, data = pcall(jsonc.parse, value)
+ local success, data = pcall(api.jsonc.parse, value)
if success and data then
local address = (data.extra and data.extra.downloadSettings and data.extra.downloadSettings.address)
or (data.downloadSettings and data.downloadSettings.address)
@@ -718,7 +711,7 @@ o.custom_remove = function(self, section, value)
end
-- [[ User-Agent ]]--
-o = s:option(Value, _n("user_agent"), translate("User-Agent"))
+o = s:option(Value, "user_agent", translate("User-Agent"))
o.default = ""
o:value("", translate("default"))
o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", "chrome")
@@ -727,44 +720,44 @@ o:value("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (K
o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70", "edge")
o:value("Go-http-client/1.1", "golang")
o:value("curl/7.68.0", "curl")
-o:depends({ [_n("tcp_guise")] = "http" })
-o:depends({ [_n("transport")] = "ws" })
-o:depends({ [_n("transport")] = "httpupgrade" })
-o:depends({ [_n("transport")] = "xhttp" })
-o:depends({ [_n("transport")] = "grpc" })
+o:depends({ tcp_guise = "http" })
+o:depends({ transport = "ws" })
+o:depends({ transport = "httpupgrade" })
+o:depends({ transport = "xhttp" })
+o:depends({ transport = "grpc" })
-- [[ Mux.Cool ]]--
-o = s:option(Flag, _n("mux"), "Mux", translate("Enable Mux.Cool"))
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "raw" })
-o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "ws" })
-o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "grpc" })
-o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "httpupgrade" })
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "trojan" })
+o = s:option(Flag, "mux", "Mux", translate("Enable Mux.Cool"))
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless", transport = "raw" })
+o:depends({ protocol = "vless", transport = "ws" })
+o:depends({ protocol = "vless", transport = "grpc" })
+o:depends({ protocol = "vless", transport = "httpupgrade" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "trojan" })
-o = s:option(Value, _n("mux_concurrency"), translate("Mux concurrency"))
+o = s:option(Value, "mux_concurrency", translate("Mux concurrency"))
o.default = -1
-o:depends({ [_n("mux")] = true })
+o:depends({ mux = true })
-o = s:option(Value, _n("xudp_concurrency"), translate("XUDP Mux concurrency"))
+o = s:option(Value, "xudp_concurrency", translate("XUDP Mux concurrency"))
o.default = 8
-o:depends({ [_n("mux")] = true })
+o:depends({ mux = true })
--[[FinalMask]]
-o = s:option(Flag, _n("use_finalmask"), "FinalMask")
+o = s:option(Flag, "use_finalmask", "FinalMask")
o.default = "0"
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "trojan" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "wireguard" })
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "trojan" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "wireguard" })
+o:depends({ protocol = "hysteria2", hysteria2_realms = false })
-o = s:option(TextValue, _n("finalmask"), " ")
-o:depends({ [_n("use_finalmask")] = true })
+o = s:option(TextValue, "finalmask", " ")
+o:depends({ use_finalmask = true })
o.rows = 10
o.wrap = "off"
o.description = translate("An FinalMaskObject in JSON format, used for sharing.") .. "
" ..
@@ -788,62 +781,62 @@ o.custom_write = function(self, section, value)
end
--[[Fast Open]]
-o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
+o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"), translate("Need node support required"))
o.default = 0
--[[tcpMptcp]]
-o = s:option(Flag, _n("tcpMptcp"), "tcpMptcp", translate("Enable Multipath TCP, need to be enabled in both server and client configuration."))
+o = s:option(Flag, "tcpMptcp", "tcpMptcp", translate("Enable Multipath TCP, need to be enabled in both server and client configuration."))
o.default = 0
-o = s:option(ListValue, _n("domain_resolver"), translate("Domain DNS Resolve"), translate("If the node address is a domain name, this DNS will be used for resolution."))
+o = s:option(ListValue, "domain_resolver", translate("Domain DNS Resolve"), translate("If the node address is a domain name, this DNS will be used for resolution."))
o:value("", translate("Auto"))
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("https", "HTTPS")
-o = s:option(Value, _n("domain_resolver_dns"), "DNS")
+o = s:option(Value, "domain_resolver_dns", "DNS")
o.datatype = "or(ipaddr,ipaddrport)"
o:value("114.114.114.114")
o:value("223.5.5.5:53")
o.default = o.keylist[1]
-o:depends({ [_n("domain_resolver")] = "tcp" })
-o:depends({ [_n("domain_resolver")] = "udp" })
+o:depends({ domain_resolver = "tcp" })
+o:depends({ domain_resolver = "udp" })
-o = s:option(Value, _n("domain_resolver_dns_https"), "DNS")
+o = s:option(Value, "domain_resolver_dns_https", "DNS")
o:value("https://120.53.53.53/dns-query", "DNSPod")
o:value("https://223.5.5.5/dns-query", "AliDNS")
o.default = o.keylist[1]
-o:depends({ [_n("domain_resolver")] = "https" })
+o:depends({ domain_resolver = "https" })
-o = s:option(ListValue, _n("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect."))
+o = s:option(ListValue, "domain_strategy", translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect."))
o.default = ""
o:value("", translate("Auto"))
o:value("UseIPv4", translate("IPv4 Only"))
o:value("UseIPv6", translate("IPv6 Only"))
-o = s:option(Flag, _n("happy_eyeballs"), translate("Enable Happy Eyeballs"), translate("Attempts IPv4 and IPv6 simultaneously; automatically uses the faster connection."))
+o = s:option(Flag, "happy_eyeballs", translate("Enable Happy Eyeballs"), translate("Attempts IPv4 and IPv6 simultaneously; automatically uses the faster connection."))
o.default = 0
-local protocols = s.fields[_n("protocol")].keylist
+local protocols = s.fields["protocol"].keylist
if #protocols > 0 then
for i, v in ipairs(protocols) do
if not v:find("^_") then
- local depends_condition = { [_n("protocol")] = v }
+ local depends_condition = { protocol = v }
if v == "hysteria2" then
- depends_condition[_n("hysteria2_realms")] = false
+ depends_condition["hysteria2_realms"] = false
end
- s.fields[_n("address")]:depends(depends_condition)
- s.fields[_n("port")]:depends(depends_condition)
- s.fields[_n("domain_resolver")]:depends(depends_condition)
- s.fields[_n("happy_eyeballs")]:depends(depends_condition)
+ s.fields["address"]:depends(depends_condition)
+ s.fields["port"]:depends(depends_condition)
+ s.fields["domain_resolver"]:depends(depends_condition)
+ s.fields["happy_eyeballs"]:depends(depends_condition)
local strategy_depends = api.clone(depends_condition)
- strategy_depends[_n("happy_eyeballs")] = false
- s.fields[_n("domain_strategy")]:depends(strategy_depends)
+ strategy_depends["happy_eyeballs"] = false
+ s.fields["domain_strategy"]:depends(strategy_depends)
if v ~= "hysteria2" then
- s.fields[_n("tcp_fast_open")]:depends({ [_n("protocol")] = v })
- s.fields[_n("tcpMptcp")]:depends({ [_n("protocol")] = v })
+ s.fields["tcp_fast_open"]:depends({ protocol = v })
+ s.fields["tcpMptcp"]:depends({ protocol = v })
end
end
end
@@ -852,7 +845,7 @@ end
-- [[ Normal single node End ]]
if not load_shunt_options then
- o = s:option(ListValue, _n("chain_proxy"), translate("Chain Proxy"))
+ o = s:option(ListValue, "chain_proxy", translate("Chain Proxy"))
o:value("", translate("Close(Not use)"))
if not (load_iface_options or load_balancing_options) then
-- Special node cannot be use pre-proxy.
@@ -861,20 +854,20 @@ if not load_shunt_options then
end
o:value("2", translate("Landing Node"))
- o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
- o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false })
+ o1 = s:option(ListValue, "preproxy_node", translate("Preproxy Node"), translate("Only support a layer of proxy."))
+ o1:depends({ chain_proxy = "1", hysteria2_realms = false })
o1.template = m:template_path("/cbi/nodes_listvalue")
o1.group = {}
- o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface"))
- o3:depends({ [_n("chain_proxy")] = "3" })
+ o3 = s:option(Value, "outbound_iface", translate("Outbound Interface"))
+ o3:depends({ chain_proxy = "3" })
o3:value("", translate("All"))
for _, d in ipairs(netdev_list) do
o3:value(d.name, d.label)
end
- o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
- o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false })
+ o2 = s:option(ListValue, "to_node", translate("Landing Node"), translate("Only support a layer of proxy."))
+ o2:depends({ chain_proxy = "2", hysteria2_realms = false })
o2.template = m:template_path("/cbi/nodes_listvalue")
o2.group = {}
@@ -895,12 +888,12 @@ if not load_shunt_options then
end
end
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
if load_shunt_options then
local current_node = m:get(arg[1]) or {}
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall2/client/include/shunt_options.lua")
- setfenv(shunt_lua, getfenv(1))(m, s, {
+ setfenv(shunt_lua, getfenv(1))(m, s1, {
node_id = arg[1],
node = current_node,
node_list = node_list,
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua
index 70b3144a..c2fc0347 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua
@@ -1,33 +1,29 @@
-local m, s = ...
-
local singbox_bin = api.finded_com("sing-box")
if not singbox_bin then
return
end
-type_name = "sing-box"
-
-- [[ sing-box ]]
+local m, s1 = ...
+local type_name = "sing-box"
-s.fields["type"]:value(type_name, "Sing-Box")
-if not s.fields["type"].default then
- s.fields["type"].default = type_name
+s1.fields["type"]:value(type_name, "Sing-Box")
+if not s1.fields["type"].default then
+ s1.fields["type"].default = type_name
end
-if s.val["type"] ~= type_name then
+if s1.val["type"] ~= type_name then
return
end
-local option_prefix = "singbox_"
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "singbox_"
-local function _n(name)
- return option_prefix .. name
-end
+local formvalue_proto = luci.http.formvalue(formvalue_key .. "protocol")
-local formvalue_proto = luci.http.formvalue(formvalue_key .. _n("protocol"))
-
-if formvalue_proto then s.val["protocol"] = formvalue_proto end
+if formvalue_proto then s1.val["protocol"] = formvalue_proto end
local arg_select_proto = luci.http.formvalue("select_proto") or ""
@@ -45,7 +41,7 @@ local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | aw
local singbox_version = api.get_app_version("sing-box"):match("[^v]+")
-o = s:option(ListValue, _n("protocol"), translate("Protocol"))
+o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("socks", "Socks")
o:value("http", "HTTP")
o:value("shadowsocks", "Shadowsocks")
@@ -79,13 +75,13 @@ function o.custom_cfgvalue(self, section)
if arg_select_proto ~= "" then
return arg_select_proto
else
- return m:get(section, self.option:sub(1 + #option_prefix))
+ return m:get(section, self.config_option)
end
end
-local load_urltest_options = s.val["protocol"] == "_urltest" or arg_select_proto == "_urltest"
-local load_shunt_options = s.val["protocol"] == "_shunt" or arg_select_proto == "_shunt"
-local load_iface_options = s.val["protocol"] == "_iface" or arg_select_proto == "_iface"
+local load_urltest_options = s1.val["protocol"] == "_urltest" or arg_select_proto == "_urltest"
+local load_shunt_options = s1.val["protocol"] == "_shunt" or arg_select_proto == "_shunt"
+local load_iface_options = s1.val["protocol"] == "_iface" or arg_select_proto == "_iface"
local load_normal_options = true
if load_urltest_options or load_shunt_options or load_iface_options then
load_normal_options = nil
@@ -98,14 +94,14 @@ local netdev_list = api.get_network_devices()
local node_list = api.get_node_list()
if load_urltest_options then -- [[ URLTest Start ]]
- o = s:option(ListValue, _n("node_add_mode"), translate("Node Addition Method"))
- o:depends({ [_n("protocol")] = "_urltest" })
+ o = s:option(ListValue, "node_add_mode", translate("Node Addition Method"))
+ o:depends({ protocol = "_urltest" })
o.default = "manual"
o:value("manual", translate("Manual"))
o:value("batch", translate("Batch"))
- o = s:option(MultiValue, _n("urltest_node"), translate("URLTest node list"), translate("List of nodes to test, document"))
- o:depends({ [_n("node_add_mode")] = "manual" })
+ o = s:option(MultiValue, "urltest_node", translate("URLTest node list"), translate("List of nodes to test, document"))
+ o:depends({ node_add_mode = "manual" })
o.widget = "checkbox"
o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {}
@@ -142,16 +138,16 @@ if load_urltest_options then -- [[ URLTest Start ]]
end
end
- o = s:option(MultiValue, _n("node_group"), translate("Select Group"))
- o:depends({ [_n("node_add_mode")] = "batch" })
+ o = s:option(MultiValue, "node_group", translate("Select Group"))
+ o:depends({ node_add_mode = "batch" })
o.widget = "checkbox"
o:value("default", translate("default"))
for k, v in pairs(groups) do
o:value(api.UrlEncode(k), k)
end
- o = s:option(Value, _n("node_match_rule"), translate("Node Matching Rules"))
- o:depends({ [_n("node_add_mode")] = "batch" })
+ o = s:option(Value, "node_match_rule", translate("Node Matching Rules"))
+ o:depends({ node_add_mode = "batch" })
local descrStr = "Example: ^A && B && !C && D$
"
descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).
"
descrStr = descrStr .. "Conditions are joined by && (AND), and their order does not affect the result.
"
@@ -159,8 +155,8 @@ if load_urltest_options then -- [[ URLTest Start ]]
descrStr = descrStr .. "Example: A && B || C && D means (A AND B) OR (C AND D)."
o.description = translate(descrStr)
- o = s:option(Value, _n("urltest_url"), translate("Probe URL"))
- o:depends({ [_n("protocol")] = "_urltest" })
+ o = s:option(Value, "urltest_url", translate("Probe URL"))
+ o:depends({ protocol = "_urltest" })
o:value("https://cp.cloudflare.com/", "Cloudflare")
o:value("https://www.gstatic.com/generate_204", "Gstatic")
o:value("https://www.google.com/generate_204", "Google")
@@ -171,8 +167,8 @@ if load_urltest_options then -- [[ URLTest Start ]]
o.default = o.keylist[3]
o.description = translate("The URL used to detect the connection status.")
- o = s:option(Value, _n("urltest_interval"), translate("Test interval"))
- o:depends({ [_n("protocol")] = "_urltest" })
+ o = s:option(Value, "urltest_interval", translate("Test interval"))
+ o:depends({ protocol = "_urltest" })
o.default = "3m"
o.placeholder = "3m"
o.description = translate("The interval between initiating probes.") .. "
" ..
@@ -180,29 +176,29 @@ if load_urltest_options then -- [[ URLTest Start ]]
translate("When the unit is not filled in, it defaults to seconds.") .. "
" ..
translate("Test interval must be less or equal than idle timeout.")
- o = s:option(Value, _n("urltest_tolerance"), translate("Test tolerance"), translate("The test tolerance in milliseconds."))
- o:depends({ [_n("protocol")] = "_urltest" })
+ o = s:option(Value, "urltest_tolerance", translate("Test tolerance"), translate("The test tolerance in milliseconds."))
+ o:depends({ protocol = "_urltest" })
o.datatype = "uinteger"
o.placeholder = "50"
o.default = "50"
- o = s:option(Value, _n("urltest_idle_timeout"), translate("Idle timeout"))
- o:depends({ [_n("protocol")] = "_urltest" })
+ o = s:option(Value, "urltest_idle_timeout", translate("Idle timeout"))
+ o:depends({ protocol = "_urltest" })
o.placeholder = "30m"
o.default = "30m"
o.description = translate("The idle timeout.") .. "
" ..
translate("The time format is numbers + units, such as '10s', '2h45m', and the supported time units are s, m, h, which correspond to seconds, minutes, and hours, respectively.") .. "
" ..
translate("When the unit is not filled in, it defaults to seconds.")
- o = s:option(Flag, _n("urltest_interrupt_exist_connections"), translate("Interrupt existing connections"))
- o:depends({ [_n("protocol")] = "_urltest" })
+ o = s:option(Flag, "urltest_interrupt_exist_connections", translate("Interrupt existing connections"))
+ o:depends({ protocol = "_urltest" })
o.default = "0"
o.description = translate("Interrupt existing connections when the selected outbound has changed.")
end -- [[ URLTest End ]]
if load_iface_options then -- [[ Custom Interface Start ]]
- o = s:option(Value, _n("iface"), translate("Interface"))
- o:depends({ [_n("protocol")] = "_iface" })
+ o = s:option(Value, "iface", translate("Interface"))
+ o:depends({ protocol = "_iface" })
for _, d in ipairs(netdev_list) do
o:value(d.name, d.label)
end
@@ -212,50 +208,48 @@ end -- [[ Custom Interface End ]]
-- [[ Normal single node Start ]]
if load_normal_options then
-o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
+o = s:option(Value, "address", translate("Address (Support Domain Name)"))
-o = s:option(Value, _n("port"), translate("Port"))
+o = s:option(Value, "port", translate("Port"))
o.datatype = "port"
-o = s:option(Value, _n("uuid"), translate("ID"))
+o = s:option(Value, "uuid", translate("ID"))
o.password = true
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "tuic" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "tuic" })
-o = s:option(Value, _n("username"), translate("Username"))
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "ssh" })
-o:depends({ [_n("protocol")] = "naive" })
+o = s:option(Value, "username", translate("Username"))
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "ssh" })
+o:depends({ protocol = "naive" })
-o = s:option(Value, _n("password"), translate("Password"))
+o = s:option(Value, "password", translate("Password"))
o.password = true
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "shadowsocksr" })
-o:depends({ [_n("protocol")] = "trojan" })
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "anytls" })
-o:depends({ [_n("protocol")] = "ssh" })
-o:depends({ [_n("protocol")] = "naive" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "shadowsocksr" })
+o:depends({ protocol = "trojan" })
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "anytls" })
+o:depends({ protocol = "ssh" })
+o:depends({ protocol = "naive" })
-o = s:option(ListValue, _n("security"), translate("Encrypt Method"))
+o = s:option(ListValue, "security", translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end
-o:depends({ [_n("protocol")] = "vmess" })
+o:depends({ protocol = "vmess" })
-o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
-o.rewrite_option = "method"
+o = s:option(ListValue, "ss_method", translate("Encrypt Method"))
for a, t in ipairs(ss_method_new_list) do o:value(t) end
for a, t in ipairs(ss_method_old_list) do o:value(t) end
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o:depends({ protocol = "shadowsocks" })
if singbox_tags:find("with_shadowsocksr") then
- o = s:option(ListValue, _n("ssr_method"), translate("Encrypt Method"))
- o.rewrite_option = "method"
+ o = s:option(ListValue, "ssr_method", translate("Encrypt Method"))
for a, t in ipairs(ss_method_old_list) do o:value(t) end
- o:depends({ [_n("protocol")] = "shadowsocksr" })
+ o:depends({ protocol = "shadowsocksr" })
local ssr_protocol_list = {
"origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple",
@@ -264,122 +258,122 @@ if singbox_tags:find("with_shadowsocksr") then
"auth_chain_d", "auth_chain_e", "auth_chain_f"
}
- o = s:option(ListValue, _n("ssr_protocol"), translate("Protocol"))
+ o = s:option(ListValue, "ssr_protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do o:value(t) end
- o:depends({ [_n("protocol")] = "shadowsocksr" })
+ o:depends({ protocol = "shadowsocksr" })
- o = s:option(Value, _n("ssr_protocol_param"), translate("Protocol_param"))
- o:depends({ [_n("protocol")] = "shadowsocksr" })
+ o = s:option(Value, "ssr_protocol_param", translate("Protocol_param"))
+ o:depends({ protocol = "shadowsocksr" })
local ssr_obfs_list = {
"plain", "http_simple", "http_post", "random_head", "tls_simple",
"tls1.0_session_auth", "tls1.2_ticket_auth"
}
- o = s:option(ListValue, _n("ssr_obfs"), translate("Obfs"))
+ o = s:option(ListValue, "ssr_obfs", translate("Obfs"))
for a, t in ipairs(ssr_obfs_list) do o:value(t) end
- o:depends({ [_n("protocol")] = "shadowsocksr" })
+ o:depends({ protocol = "shadowsocksr" })
- o = s:option(Value, _n("ssr_obfs_param"), translate("Obfs_param"))
- o:depends({ [_n("protocol")] = "shadowsocksr" })
+ o = s:option(Value, "ssr_obfs_param", translate("Obfs_param"))
+ o:depends({ protocol = "shadowsocksr" })
end
-o = s:option(Flag, _n("uot"), translate("UDP over TCP"))
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "naive" })
+o = s:option(Flag, "uot", translate("UDP over TCP"))
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "naive" })
-o = s:option(Value, _n("alter_id"), "Alter ID")
+o = s:option(Value, "alter_id", "Alter ID")
o.datatype = "uinteger"
o.default = "0"
-o:depends({ [_n("protocol")] = "vmess" })
+o:depends({ protocol = "vmess" })
-o = s:option(Flag, _n("global_padding"), "global_padding", translate("Protocol parameter. Will waste traffic randomly if enabled."))
+o = s:option(Flag, "global_padding", "global_padding", translate("Protocol parameter. Will waste traffic randomly if enabled."))
o.default = "0"
-o:depends({ [_n("protocol")] = "vmess" })
+o:depends({ protocol = "vmess" })
-o = s:option(Flag, _n("authenticated_length"), "authenticated_length", translate("Protocol parameter. Enable length block encryption."))
+o = s:option(Flag, "authenticated_length", "authenticated_length", translate("Protocol parameter. Enable length block encryption."))
o.default = "0"
-o:depends({ [_n("protocol")] = "vmess" })
+o:depends({ protocol = "vmess" })
-o = s:option(ListValue, _n("flow"), translate("flow"))
+o = s:option(ListValue, "flow", translate("flow"))
o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
-o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
+o:depends({ protocol = "vless", tls = true })
if singbox_tags:find("with_quic") then
- o = s:option(Value, _n("hysteria_hop"), translate("Port hopping range"))
+ o = s:option(Value, "hysteria_hop", translate("Port hopping range"))
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval(second)"), translate("Example:") .. "30 (≥5)")
+ o = s:option(Value, "hysteria_hop_interval", translate("Hop Interval(second)"), translate("Example:") .. "30 (≥5)")
o.datatype = "uinteger"
o.placeholder = "30"
o.default = "30"
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Value, "hysteria_obfs", translate("Obfs Password"))
+ o:depends({ protocol = "hysteria" })
- o = s:option(ListValue, _n("hysteria_auth_type"), translate("Auth Type"))
+ o = s:option(ListValue, "hysteria_auth_type", translate("Auth Type"))
o:value("disable", translate("Disable"))
o:value("string", translate("STRING"))
o:value("base64", translate("BASE64"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_auth_password"), translate("Auth Password"))
+ o = s:option(Value, "hysteria_auth_password", translate("Auth Password"))
o.password = true
- o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "string"})
- o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "base64"})
+ o:depends({ protocol = "hysteria", hysteria_auth_type = "string"})
+ o:depends({ protocol = "hysteria", hysteria_auth_type = "base64"})
- o = s:option(Value, _n("hysteria_up_mbps"), translate("Max upload Mbps"))
+ o = s:option(Value, "hysteria_up_mbps", translate("Max upload Mbps"))
o.default = "10"
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_down_mbps"), translate("Max download Mbps"))
+ o = s:option(Value, "hysteria_down_mbps", translate("Max download Mbps"))
o.default = "50"
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Value, "hysteria_recv_window_conn", translate("QUIC stream receive window"))
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_recv_window"), translate("QUIC connection receive window"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Value, "hysteria_recv_window", translate("QUIC connection receive window"))
+ o:depends({ protocol = "hysteria" })
- o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Flag, "hysteria_disable_mtu_discovery", translate("Disable MTU detection"))
+ o:depends({ protocol = "hysteria" })
end
if singbox_tags:find("with_quic") then
- o = s:option(ListValue, _n("tuic_congestion_control"), translate("Congestion control algorithm"))
+ o = s:option(ListValue, "tuic_congestion_control", translate("Congestion control algorithm"))
o.default = "cubic"
o:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno"))
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
- o = s:option(ListValue, _n("tuic_udp_relay_mode"), translate("UDP relay mode"))
+ o = s:option(ListValue, "tuic_udp_relay_mode", translate("UDP relay mode"))
o.default = "native"
o:value("native", translate("native"))
o:value("quic", translate("QUIC"))
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
--[[
- o = s:option(Flag, _n("tuic_udp_over_stream"), translate("UDP over stream"))
- o:depends({ [_n("protocol")] = "tuic" })
+ o = s:option(Flag, "tuic_udp_over_stream", translate("UDP over stream"))
+ o:depends({ protocol = "tuic" })
]]--
- o = s:option(Flag, _n("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
+ o = s:option(Flag, "tuic_zero_rtt_handshake", translate("Enable 0-RTT QUIC handshake"))
o.default = 0
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
- o = s:option(Value, _n("tuic_heartbeat"), translate("Heartbeat interval(second)"))
+ o = s:option(Value, "tuic_heartbeat", translate("Heartbeat interval(second)"))
o.datatype = "uinteger"
o.default = "3"
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
- o = s:option(ListValue, _n("tuic_alpn"), translate("QUIC TLS ALPN"))
+ o = s:option(ListValue, "tuic_alpn", translate("QUIC TLS ALPN"))
o.default = "default"
o:value("default", translate("Default"))
o:value("h3")
@@ -390,30 +384,30 @@ if singbox_tags:find("with_quic") then
o:value("h3,h2,http/1.1")
o:value("spdy/3.1")
o:value("h3,spdy/3.1")
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
end
if singbox_tags:find("with_quic") then
- o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range"))
+ o = s:option(Value, "hysteria2_hop", translate("Port hopping range"))
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
- o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+ o:depends({ protocol = "hysteria2", hysteria2_realms = false })
- o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
+ o = s:option(Value, "hysteria2_hop_interval", translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
o.datatype = "or(uinteger,portrange)"
o.placeholder = "30"
o.default = "30"
- o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+ o:depends({ protocol = "hysteria2", hysteria2_realms = false })
- o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
+ o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
if api.compare_versions(singbox_version, ">=", "1.14.0") then
- o:depends({ [_n("protocol")] = "hysteria2"})
+ o:depends({ protocol = "hysteria2"})
else
- o:depends({ [_n("protocol")] = "__hide"})
+ o:depends({ protocol = "__hide"})
end
- o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
- o:depends({ [_n("hysteria2_realms")] = "1" })
+ o = s:option(Value, "hysteria2_realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
+ o:depends({ hysteria2_realms = "1" })
o.validate = function(self, value)
value = api.trim(value)
local realm = api.parse_realm_uri(value)
@@ -421,109 +415,109 @@ if singbox_tags:find("with_quic") then
return nil, translate("Invalid Realm URL.")
end
- o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
+ o = s:option(DynamicList, "hysteria2_realm_stun", translate("Realm STUN"))
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
- o:depends({ [_n("hysteria2_realms")] = "1" })
+ o:depends({ hysteria2_realms = "1" })
- o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
+ o = s:option(Value, "hysteria2_auth_password", translate("Auth Password"))
o.password = true
- o:depends({ [_n("protocol")] = "hysteria2"})
+ o:depends({ protocol = "hysteria2"})
- o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
+ o = s:option(ListValue, "hysteria2_obfs_type", translate("Obfs Type"))
o:value("", translate("Disable"))
o:value("salamander")
o:value("gecko")
- o:depends({ [_n("protocol")] = "hysteria2" })
+ o:depends({ protocol = "hysteria2" })
- o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
- o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
- o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+ o = s:option(Value, "hysteria2_obfs_password", translate("Obfs Password"))
+ o:depends({ hysteria2_obfs_type = "salamander" })
+ o:depends({ hysteria2_obfs_type = "gecko" })
- o = s:option(Value, _n("hysteria2_obfs_MinPacketSize"), translate("Gecko Packet Size (min)"))
+ o = s:option(Value, "hysteria2_obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
o.datatype = "uinteger"
o.placeholder = "512"
o.default = "512"
- o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+ o:depends({ hysteria2_obfs_type = "gecko" })
- o = s:option(Value, _n("hysteria2_obfs_MaxPacketSize"), translate("Gecko Packet Size (max)"))
+ o = s:option(Value, "hysteria2_obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
o.datatype = "uinteger"
o.placeholder = "1200"
o.default = "1200"
- o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+ o:depends({ hysteria2_obfs_type = "gecko" })
- o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
- o:depends({ [_n("protocol")] = "hysteria2" })
+ o = s:option(Value, "hysteria2_up_mbps", translate("Max upload Mbps"))
+ o:depends({ protocol = "hysteria2" })
- o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
- o:depends({ [_n("protocol")] = "hysteria2" })
+ o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps"))
+ o:depends({ protocol = "hysteria2" })
- o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
+ o = s:option(Value, "hysteria2_idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
o.datatype = "range(4,120)"
- o:depends({ [_n("protocol")] = "hysteria2"})
+ o:depends({ protocol = "hysteria2"})
- o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
+ o = s:option(Value, "hysteria2_keep_alive_period", translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
o.datatype = "range(2,60)"
- o:depends({ [_n("protocol")] = "hysteria2"})
+ o:depends({ protocol = "hysteria2"})
- o = s:option(Flag, _n("hysteria2_disable_mtu_discovery"), translate("Disable MTU detection"))
+ o = s:option(Flag, "hysteria2_disable_mtu_discovery", translate("Disable MTU detection"))
o.default = "0"
- o:depends({ [_n("protocol")] = "hysteria2"})
+ o:depends({ protocol = "hysteria2"})
end
-- [[ SSH config start ]] --
-o = s:option(TextValue, _n("ssh_priv_key"), translate("Private Key"))
+o = s:option(TextValue, "ssh_priv_key", translate("Private Key"))
o.rows = 5
o.wrap = "off"
-o:depends({ [_n("protocol")] = "ssh" })
+o:depends({ protocol = "ssh" })
o.validate = function(self, value)
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
return value
end
-o = s:option(Value, _n("ssh_priv_key_pp"), translate("Private Key Passphrase"))
+o = s:option(Value, "ssh_priv_key_pp", translate("Private Key Passphrase"))
o.password = true
-o:depends({ [_n("protocol")] = "ssh" })
+o:depends({ protocol = "ssh" })
-o = s:option(DynamicList, _n("ssh_host_key"), translate("Host Key"), translate("Accept any if empty."))
-o:depends({ [_n("protocol")] = "ssh" })
+o = s:option(DynamicList, "ssh_host_key", translate("Host Key"), translate("Accept any if empty."))
+o:depends({ protocol = "ssh" })
-o = s:option(DynamicList, _n("ssh_host_key_algo"), translate("Host Key Algorithms"))
-o:depends({ [_n("protocol")] = "ssh" })
+o = s:option(DynamicList, "ssh_host_key_algo", translate("Host Key Algorithms"))
+o:depends({ protocol = "ssh" })
-o = s:option(Value, _n("ssh_client_version"), translate("Client Version"), translate("Random version will be used if empty."))
-o:depends({ [_n("protocol")] = "ssh" })
+o = s:option(Value, "ssh_client_version", translate("Client Version"), translate("Random version will be used if empty."))
+o:depends({ protocol = "ssh" })
-- [[ SSH config end ]] --
-- [[ naive start ]] --
-o = s:option(Value, _n("naive_insecure_concurrency"), translate("Concurrent Tunnels"))
+o = s:option(Value, "naive_insecure_concurrency", translate("Concurrent Tunnels"))
o.datatype = "uinteger"
o.placeholder = "0"
o.default = "0"
-o:depends({ [_n("protocol")] = "naive" })
+o:depends({ protocol = "naive" })
-o = s:option(Flag, _n("naive_quic"), translate("QUIC"))
+o = s:option(Flag, "naive_quic", translate("QUIC"))
o.default = 0
-o:depends({ [_n("protocol")] = "naive" })
+o:depends({ protocol = "naive" })
-o = s:option(ListValue, _n("naive_congestion_control"), translate("Congestion control algorithm"))
+o = s:option(ListValue, "naive_congestion_control", translate("Congestion control algorithm"))
o.default = "bbr"
o:value("bbr", translate("BBR"))
o:value("bbr2", translate("BBRv2"))
o:value("cubic", translate("CUBIC"))
o:value("reno", translate("New Reno"))
-o:depends({ [_n("naive_quic")] = "1" })
+o:depends({ naive_quic = "1" })
-- [[ naive end ]] --
-o = s:option(Flag, _n("tls"), translate("TLS"))
+o = s:option(Flag, "tls", translate("TLS"))
o.default = 0
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "trojan" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "anytls" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "trojan" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "anytls" })
-o = s:option(ListValue, _n("alpn"), translate("ALPN"))
+o = s:option(ListValue, "alpn", translate("ALPN"))
o.default = "default"
o:value("default", translate("Default"))
o:value("h3")
@@ -532,49 +526,49 @@ o:value("h3,h2")
o:value("http/1.1")
o:value("h2,http/1.1")
o:value("h3,h2,http/1.1")
-o:depends({ [_n("tls")] = true })
-o:depends({ [_n("protocol")] = "hysteria" })
+o:depends({ tls = true })
+o:depends({ protocol = "hysteria" })
-o = s:option(Flag, _n("tls_disable_sni"), translate("Disable SNI"), translate("Do not send server name in ClientHello."))
+o = s:option(Flag, "tls_disable_sni", translate("Disable SNI"), translate("Do not send server name in ClientHello."))
o.default = "0"
-o:depends({ [_n("tls")] = true })
-o:depends({ [_n("protocol")] = "hysteria"})
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ tls = true })
+o:depends({ protocol = "hysteria"})
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2" })
-o = s:option(Value, _n("tls_serverName"), "SNI " .. translate("Domain"))
-o:depends({ [_n("tls")] = true })
-o:depends({ [_n("protocol")] = "hysteria"})
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2" })
-o:depends({ [_n("protocol")] = "naive" })
+o = s:option(Value, "tls_serverName", "SNI " .. translate("Domain"))
+o:depends({ tls = true })
+o:depends({ protocol = "hysteria"})
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2" })
+o:depends({ protocol = "naive" })
-o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
+o = s:option(Flag, "tls_allowInsecure", translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
o.default = "0"
-o:depends({ [_n("tls")] = true })
-o:depends({ [_n("protocol")] = "hysteria"})
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ tls = true })
+o:depends({ protocol = "hysteria"})
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2" })
-o = s:option(Flag, _n("tls_certificate"), translate("TLS Certificate (PEM)"))
+o = s:option(Flag, "tls_certificate", translate("TLS Certificate (PEM)"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria"})
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2" })
-o:depends({ [_n("protocol")] = "naive" })
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria"})
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2" })
+o:depends({ protocol = "naive" })
-o = s:option(TextValue, _n("tls_certificate_pem"), " ", translate("Full certificate (chain), PEM format."))
+o = s:option(TextValue, "tls_certificate_pem", " ", translate("Full certificate (chain), PEM format."))
o.default = ""
o.rows = 5
o.wrap = "off"
-o:depends({ [_n("tls_certificate")] = true })
+o:depends({ tls_certificate = true })
o.validate = function(self, value)
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
return value
end
-o = s:option(DynamicList, _n("cipherSuites"), translate("Cipher Suites"), '***' .. " " .. translate("Configures the list of supported cipher suites."))
+o = s:option(DynamicList, "cipherSuites", translate("Cipher Suites"), '***' .. " " .. translate("Configures the list of supported cipher suites."))
o:value("TLS_AES_128_GCM_SHA256")
o:value("TLS_AES_256_GCM_SHA384")
o:value("TLS_CHACHA20_POLY1305_SHA256")
@@ -588,35 +582,35 @@ o:value("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
o:value("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384")
o:value("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256")
o:value("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
-o:depends({ [_n("tls")] = true })
+o:depends({ tls = true })
-o = s:option(Flag, _n("ech"), translate("ECH"))
+o = s:option(Flag, "ech", translate("ECH"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria" })
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
-o:depends({ [_n("protocol")] = "naive" })
+o:depends({ tls = true, flow = "", reality = false })
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria" })
+o:depends({ protocol = "hysteria2", hysteria2_realms = false })
+o:depends({ protocol = "naive" })
-o = s:option(TextValue, _n("ech_config"), translate("ECH Config"))
+o = s:option(TextValue, "ech_config", translate("ECH Config"))
o.default = ""
o.rows = 5
o.wrap = "off"
-o:depends({ [_n("ech")] = true })
+o:depends({ ech = true })
o.validate = function(self, value)
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
return value
end
-o = s:option(Value, _n("ech_query_server_name"), translate("ECH Query Domain"), translate("Overrides the domain name used for ECH HTTPS record queries."))
-o:depends({ [_n("ech")] = true })
+o = s:option(Value, "ech_query_server_name", translate("ECH Query Domain"), translate("Overrides the domain name used for ECH HTTPS record queries."))
+o:depends({ ech = true })
if singbox_tags:find("with_utls") then
- o = s:option(Flag, _n("utls"), translate("uTLS"))
+ o = s:option(Flag, "utls", translate("uTLS"))
o.default = "0"
- o:depends({ [_n("tls")] = true })
+ o:depends({ tls = true })
- o = s:option(ListValue, _n("fingerprint"), translate("Finger Print"))
+ o = s:option(ListValue, "fingerprint", translate("Finger Print"))
o:value("chrome")
o:value("firefox")
o:value("edge")
@@ -628,30 +622,30 @@ if singbox_tags:find("with_utls") then
o:value("random")
o:value("randomized")
o.default = "chrome"
- o:depends({ [_n("utls")] = true })
+ o:depends({ utls = true })
-- [[ REALITY ]] --
- o = s:option(Flag, _n("reality"), translate("REALITY"))
+ o = s:option(Flag, "reality", translate("REALITY"))
o.default = 0
- o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "shadowsocks", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "socks", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "anytls", [_n("tls")] = true })
+ o:depends({ protocol = "vless", tls = true })
+ o:depends({ protocol = "vmess", tls = true })
+ o:depends({ protocol = "shadowsocks", tls = true })
+ o:depends({ protocol = "socks", tls = true })
+ o:depends({ protocol = "trojan", tls = true })
+ o:depends({ protocol = "anytls", tls = true })
- o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
- o:depends({ [_n("reality")] = true })
+ o = s:option(Value, "reality_publicKey", translate("Public Key"))
+ o:depends({ reality = true })
- o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
- o:depends({ [_n("reality")] = true })
+ o = s:option(Value, "reality_shortId", translate("Short Id"))
+ o:depends({ reality = true })
end
-o = s:option(Flag, _n("anytls_disable_reuse"), translate("Disable TLS Reuse"))
+o = s:option(Flag, "anytls_disable_reuse", translate("Disable TLS Reuse"))
o.default = 0
-o:depends({ [_n("protocol")] = "anytls" })
+o:depends({ protocol = "anytls" })
-o = s:option(ListValue, _n("transport"), translate("Transport"))
+o = s:option(ListValue, "transport", translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
o:value("ws", "WebSocket")
@@ -663,119 +657,119 @@ if singbox_tags:find("with_grpc") then
o:value("grpc", "gRPC")
else o:value("grpc", "gRPC-lite")
end
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "trojan" })
if singbox_tags:find("with_wireguard") then
- o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(Value, "wireguard_public_key", translate("Public Key"))
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(Value, "wireguard_secret_key", translate("Private Key"))
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(Value, "wireguard_preSharedKey", translate("Pre shared key"))
+ o:depends({ protocol = "wireguard" })
- o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(DynamicList, "wireguard_local_address", translate("Local Address"))
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_mtu"), translate("MTU"))
+ o = s:option(Value, "wireguard_mtu", translate("MTU"))
o.default = "1420"
- o:depends({ [_n("protocol")] = "wireguard" })
+ o:depends({ protocol = "wireguard" })
- o = s:option(Flag, _n("wireguard_system_interface"), translate("System interface"))
+ o = s:option(Flag, "wireguard_system_interface", translate("System interface"))
o.default = 0
- o:depends({ [_n("protocol")] = "wireguard" })
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_interface_name"), translate("System interface name"))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(Value, "wireguard_interface_name", translate("System interface name"))
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(Value, "wireguard_reserved", translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
+ o:depends({ protocol = "wireguard" })
end
-- [[ TCP ]]--
-o = s:option(ListValue, _n("tcp_guise"), translate("Camouflage Type"))
+o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
o:value("none", "none")
o:value("http", "http")
-o:depends({ [_n("transport")] = "tcp" })
+o:depends({ transport = "tcp" })
-o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
-o:depends({ [_n("tcp_guise")] = "http" })
+o = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host"))
+o:depends({ tcp_guise = "http" })
-o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
+o = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path"))
o.placeholder = "/"
-o:depends({ [_n("tcp_guise")] = "http" })
+o:depends({ tcp_guise = "http" })
-- [[ HTTP ]]--
-o = s:option(DynamicList, _n("http_host"), translate("HTTP Host"))
-o:depends({ [_n("transport")] = "http" })
+o = s:option(DynamicList, "http_host", translate("HTTP Host"))
+o:depends({ transport = "http" })
-o = s:option(Value, _n("http_path"), translate("HTTP Path"))
+o = s:option(Value, "http_path", translate("HTTP Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "http" })
+o:depends({ transport = "http" })
-o = s:option(Flag, _n("http_h2_health_check"), translate("Health check"))
-o:depends({ [_n("tls")] = true, [_n("transport")] = "http" })
+o = s:option(Flag, "http_h2_health_check", translate("Health check"))
+o:depends({ tls = true, transport = "http" })
-o = s:option(Value, _n("http_h2_read_idle_timeout"), translate("Idle timeout"))
+o = s:option(Value, "http_h2_read_idle_timeout", translate("Idle timeout"))
o.default = "15"
-o:depends({ [_n("http_h2_health_check")] = true })
+o:depends({ http_h2_health_check = true })
-o = s:option(Value, _n("http_h2_health_check_timeout"), translate("Health check timeout"))
+o = s:option(Value, "http_h2_health_check_timeout", translate("Health check timeout"))
o.default = "15"
-o:depends({ [_n("http_h2_health_check")] = true })
+o:depends({ http_h2_health_check = true })
-- [[ WebSocket ]]--
-o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
-o:depends({ [_n("transport")] = "ws" })
+o = s:option(Value, "ws_host", translate("WebSocket Host"))
+o:depends({ transport = "ws" })
-o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
+o = s:option(Value, "ws_path", translate("WebSocket Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "ws" })
+o:depends({ transport = "ws" })
-o = s:option(Flag, _n("ws_enableEarlyData"), translate("Enable early data"))
-o:depends({ [_n("transport")] = "ws" })
+o = s:option(Flag, "ws_enableEarlyData", translate("Enable early data"))
+o:depends({ transport = "ws" })
-o = s:option(Value, _n("ws_maxEarlyData"), translate("Early data length"))
+o = s:option(Value, "ws_maxEarlyData", translate("Early data length"))
o.default = "1024"
-o:depends({ [_n("ws_enableEarlyData")] = true })
+o:depends({ ws_enableEarlyData = true })
-o = s:option(Value, _n("ws_earlyDataHeaderName"), translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
-o:depends({ [_n("ws_enableEarlyData")] = true })
+o = s:option(Value, "ws_earlyDataHeaderName", translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
+o:depends({ ws_enableEarlyData = true })
-- [[ HTTPUpgrade ]]--
-o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
-o:depends({ [_n("transport")] = "httpupgrade" })
+o = s:option(Value, "httpupgrade_host", translate("HTTPUpgrade Host"))
+o:depends({ transport = "httpupgrade" })
-o = s:option(Value, _n("httpupgrade_path"), translate("HTTPUpgrade Path"))
+o = s:option(Value, "httpupgrade_path", translate("HTTPUpgrade Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "httpupgrade" })
+o:depends({ transport = "httpupgrade" })
-- [[ gRPC ]]--
-o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
-o:depends({ [_n("transport")] = "grpc" })
+o = s:option(Value, "grpc_serviceName", "ServiceName")
+o:depends({ transport = "grpc" })
-o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
-o:depends({ [_n("transport")] = "grpc" })
+o = s:option(Flag, "grpc_health_check", translate("Health check"))
+o:depends({ transport = "grpc" })
-o = s:option(Value, _n("grpc_idle_timeout"), translate("Idle timeout"))
+o = s:option(Value, "grpc_idle_timeout", translate("Idle timeout"))
o.default = "15"
-o:depends({ [_n("grpc_health_check")] = true })
+o:depends({ grpc_health_check = true })
-o = s:option(Value, _n("grpc_health_check_timeout"), translate("Health check timeout"))
+o = s:option(Value, "grpc_health_check_timeout", translate("Health check timeout"))
o.default = "15"
-o:depends({ [_n("grpc_health_check")] = true })
+o:depends({ grpc_health_check = true })
-o = s:option(Flag, _n("grpc_permit_without_stream"), translate("Permit without stream"))
+o = s:option(Flag, "grpc_permit_without_stream", translate("Permit without stream"))
o.default = "0"
-o:depends({ [_n("grpc_health_check")] = true })
+o:depends({ grpc_health_check = true })
-- [[ User-Agent ]]--
-o = s:option(Value, _n("user_agent"), translate("User-Agent"))
+o = s:option(Value, "user_agent", translate("User-Agent"))
o.default = ""
o:value("", translate("default"))
o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", "chrome")
@@ -784,73 +778,73 @@ o:value("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (K
o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70", "edge")
o:value("Go-http-client/1.1", "golang")
o:value("curl/7.68.0", "curl")
-o:depends({ [_n("tcp_guise")] = "http" })
-o:depends({ [_n("transport")] = "http" })
-o:depends({ [_n("transport")] = "ws" })
-o:depends({ [_n("transport")] = "httpupgrade" })
-o:depends({ [_n("protocol")] = "naive" })
+o:depends({ tcp_guise = "http" })
+o:depends({ transport = "http" })
+o:depends({ transport = "ws" })
+o:depends({ transport = "httpupgrade" })
+o:depends({ protocol = "naive" })
-- [[ Mux ]]--
-o = s:option(Flag, _n("mux"), translate("Mux"))
+o = s:option(Flag, "mux", translate("Mux"))
o.rmempty = false
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
-o:depends({ [_n("protocol")] = "shadowsocks", [_n("uot")] = "" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless", flow = "" })
+o:depends({ protocol = "shadowsocks", uot = "" })
+o:depends({ protocol = "trojan" })
-o = s:option(ListValue, _n("mux_type"), translate("Mux"))
+o = s:option(ListValue, "mux_type", translate("Mux"))
o:value("smux")
o:value("yamux")
o:value("h2mux")
-o:depends({ [_n("mux")] = true })
+o:depends({ mux = true })
-o = s:option(Value, _n("mux_concurrency"), translate("Mux concurrency"))
+o = s:option(Value, "mux_concurrency", translate("Mux concurrency"))
o.default = 4
-o:depends({ [_n("mux")] = true, [_n("tcpbrutal")] = false })
+o:depends({ mux = true, tcpbrutal = false })
-o = s:option(Flag, _n("mux_padding"), translate("Padding"))
+o = s:option(Flag, "mux_padding", translate("Padding"))
o.default = 0
-o:depends({ [_n("mux")] = true })
+o:depends({ mux = true })
-- [[ TCP Brutal ]]--
-o = s:option(Flag, _n("tcpbrutal"), translate("TCP Brutal"))
+o = s:option(Flag, "tcpbrutal", translate("TCP Brutal"))
o.default = 0
-o:depends({ [_n("mux")] = true })
+o:depends({ mux = true })
-o = s:option(Value, _n("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
+o = s:option(Value, "tcpbrutal_up_mbps", translate("Max upload Mbps"))
o.default = "10"
-o:depends({ [_n("tcpbrutal")] = true })
+o:depends({ tcpbrutal = true })
-o = s:option(Value, _n("tcpbrutal_down_mbps"), translate("Max download Mbps"))
+o = s:option(Value, "tcpbrutal_down_mbps", translate("Max download Mbps"))
o.default = "50"
-o:depends({ [_n("tcpbrutal")] = true })
+o:depends({ tcpbrutal = true })
-o = s:option(Flag, _n("shadowtls"), "ShadowTLS")
+o = s:option(Flag, "shadowtls", "ShadowTLS")
o.default = 0
-o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = false })
-o:depends({ [_n("protocol")] = "shadowsocks", [_n("tls")] = false })
+o:depends({ protocol = "vmess", tls = false })
+o:depends({ protocol = "shadowsocks", tls = false })
-o = s:option(ListValue, _n("shadowtls_version"), "ShadowTLS " .. translate("Version"))
+o = s:option(ListValue, "shadowtls_version", "ShadowTLS " .. translate("Version"))
o.default = "1"
o:value("1", "ShadowTLS v1")
o:value("2", "ShadowTLS v2")
o:value("3", "ShadowTLS v3")
-o:depends({ [_n("shadowtls")] = true })
+o:depends({ shadowtls = true })
-o = s:option(Value, _n("shadowtls_password"), "ShadowTLS " .. translate("Password"))
+o = s:option(Value, "shadowtls_password", "ShadowTLS " .. translate("Password"))
o.password = true
-o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "2" })
-o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "3" })
+o:depends({ shadowtls = true, shadowtls_version = "2" })
+o:depends({ shadowtls = true, shadowtls_version = "3" })
-o = s:option(Value, _n("shadowtls_serverName"), "ShadowTLS " .. translate("Domain"))
-o:depends({ [_n("shadowtls")] = true })
+o = s:option(Value, "shadowtls_serverName", "ShadowTLS " .. translate("Domain"))
+o:depends({ shadowtls = true })
if singbox_tags:find("with_utls") then
- o = s:option(Flag, _n("shadowtls_utls"), "ShadowTLS " .. translate("uTLS"))
+ o = s:option(Flag, "shadowtls_utls", "ShadowTLS " .. translate("uTLS"))
o.default = "0"
- o:depends({ [_n("shadowtls")] = true })
+ o:depends({ shadowtls = true })
- o = s:option(ListValue, _n("shadowtls_fingerprint"), "ShadowTLS " .. translate("Finger Print"))
+ o = s:option(ListValue, "shadowtls_fingerprint", "ShadowTLS " .. translate("Finger Print"))
o:value("chrome")
o:value("firefox")
o:value("edge")
@@ -862,44 +856,44 @@ if singbox_tags:find("with_utls") then
o:value("random")
-- o:value("randomized")
o.default = "chrome"
- o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_utls")] = true })
+ o:depends({ shadowtls = true, shadowtls_utls = true })
end
-- [[ SIP003 plugin ]]--
-o = s:option(Flag, _n("plugin_enabled"), translate("plugin"))
+o = s:option(Flag, "plugin_enabled", translate("plugin"))
o.default = 0
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o:depends({ protocol = "shadowsocks" })
-o = s:option(ListValue, _n("plugin"), "SIP003 " .. translate("plugin"))
+o = s:option(ListValue, "plugin", "SIP003 " .. translate("plugin"))
o.default = "obfs-local"
-o:depends({ [_n("plugin_enabled")] = true })
+o:depends({ plugin_enabled = true })
o:value("obfs-local")
o:value("v2ray-plugin")
-o = s:option(Value, _n("plugin_opts"), translate("opts"))
-o:depends({ [_n("plugin_enabled")] = true })
+o = s:option(Value, "plugin_opts", translate("opts"))
+o:depends({ plugin_enabled = true })
-o = s:option(ListValue, _n("domain_resolver"), translate("Domain DNS Resolve"), translate("If the node address is a domain name, this DNS will be used for resolution."))
+o = s:option(ListValue, "domain_resolver", translate("Domain DNS Resolve"), translate("If the node address is a domain name, this DNS will be used for resolution."))
o:value("", translate("Auto"))
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("https", "HTTPS")
-o = s:option(Value, _n("domain_resolver_dns"), "DNS")
+o = s:option(Value, "domain_resolver_dns", "DNS")
o.datatype = "or(ipaddr,ipaddrport)"
o:value("114.114.114.114")
o:value("223.5.5.5:53")
o.default = o.keylist[1]
-o:depends({ [_n("domain_resolver")] = "tcp" })
-o:depends({ [_n("domain_resolver")] = "udp" })
+o:depends({ domain_resolver = "tcp" })
+o:depends({ domain_resolver = "udp" })
-o = s:option(Value, _n("domain_resolver_dns_https"), "DNS")
+o = s:option(Value, "domain_resolver_dns_https", "DNS")
o:value("https://120.53.53.53/dns-query", "DNSPod")
o:value("https://223.5.5.5/dns-query", "AliDNS")
o.default = o.keylist[1]
-o:depends({ [_n("domain_resolver")] = "https" })
+o:depends({ domain_resolver = "https" })
-o = s:option(ListValue, _n("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect."))
+o = s:option(ListValue, "domain_strategy", translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect."))
o.default = ""
o:value("", translate("Auto"))
o:value("prefer_ipv4", translate("Prefer IPv4"))
@@ -907,18 +901,18 @@ o:value("prefer_ipv6", translate("Prefer IPv6"))
o:value("ipv4_only", translate("IPv4 Only"))
o:value("ipv6_only", translate("IPv6 Only"))
-local protocols = s.fields[_n("protocol")].keylist
+local protocols = s.fields["protocol"].keylist
if #protocols > 0 then
for i, v in ipairs(protocols) do
if not v:find("^_") then
- local depends_condition = { [_n("protocol")] = v }
+ local depends_condition = { protocol = v }
if v == "hysteria2" then
- depends_condition[_n("hysteria2_realms")] = false
+ depends_condition["hysteria2_realms"] = false
end
- s.fields[_n("address")]:depends(depends_condition)
- s.fields[_n("port")]:depends(depends_condition)
- s.fields[_n("domain_resolver")]:depends(depends_condition)
- s.fields[_n("domain_strategy")]:depends(depends_condition)
+ s.fields["address"]:depends(depends_condition)
+ s.fields["port"]:depends(depends_condition)
+ s.fields["domain_resolver"]:depends(depends_condition)
+ s.fields["domain_strategy"]:depends(depends_condition)
end
end
end
@@ -926,7 +920,7 @@ end
-- [[ Normal single node End ]]
if not load_shunt_options then
- o = s:option(ListValue, _n("chain_proxy"), translate("Chain Proxy"))
+ o = s:option(ListValue, "chain_proxy", translate("Chain Proxy"))
o:value("", translate("Close(Not use)"))
if not (load_iface_options or load_urltest_options) then
-- Special node cannot be use pre-proxy.
@@ -935,20 +929,20 @@ if not load_shunt_options then
end
o:value("2", translate("Landing Node"))
- o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
- o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false })
+ o1 = s:option(ListValue, "preproxy_node", translate("Preproxy Node"), translate("Only support a layer of proxy."))
+ o1:depends({ chain_proxy = "1", hysteria2_realms = false })
o1.template = m:template_path("/cbi/nodes_listvalue")
o1.group = {}
- o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface"))
- o3:depends({ [_n("chain_proxy")] = "3" })
+ o3 = s:option(Value, "outbound_iface", translate("Outbound Interface"))
+ o3:depends({ chain_proxy = "3" })
o3:value("", translate("All"))
for _, d in ipairs(netdev_list) do
o3:value(d.name, d.label)
end
- o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
- o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false })
+ o2 = s:option(ListValue, "to_node", translate("Landing Node"), translate("Only support a layer of proxy."))
+ o2:depends({ chain_proxy = "2", hysteria2_realms = false })
o2.template = m:template_path("/cbi/nodes_listvalue")
o2.group = {}
@@ -969,12 +963,12 @@ if not load_shunt_options then
end
end
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
if load_shunt_options then
local current_node = m:get(arg[1]) or {}
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall2/client/include/shunt_options.lua")
- setfenv(shunt_lua, getfenv(1))(m, s, {
+ setfenv(shunt_lua, getfenv(1))(m, s1, {
node_id = arg[1],
node = current_node,
node_list = node_list,
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss-rust.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss-rust.lua
index ae18e369..e3bc6907 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss-rust.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss-rust.lua
@@ -1,24 +1,20 @@
-local m, s = ...
-
if not api.is_finded("sslocal") then
return
end
-type_name = "SS-Rust"
-
-- [[ Shadowsocks Rust ]]
+local m, s1 = ...
+local type_name = "SS-Rust"
-s.fields["type"]:value(type_name, "Shadowsocks Rust")
+s1.fields["type"]:value(type_name, "Shadowsocks Rust")
-if s.val["type"] ~= type_name then
+if s1.val["type"] ~= type_name then
return
end
-local option_prefix = "ssrust_"
-
-local function _n(name)
- return option_prefix .. name
-end
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "ssrust_"
local ssrust_encrypt_method_list = {
"none", "plain",
@@ -26,35 +22,35 @@ local ssrust_encrypt_method_list = {
"2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha8-poly1305", "2022-blake3-chacha20-poly1305"
}
-o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
+o = s:option(Value, "address", translate("Address (Support Domain Name)"))
-o = s:option(Value, _n("port"), translate("Port"))
+o = s:option(Value, "port", translate("Port"))
o.datatype = "port"
-o = s:option(Value, _n("password"), translate("Password"))
+o = s:option(Value, "password", translate("Password"))
o.password = true
-o = s:option(Value, _n("method"), translate("Encrypt Method"))
+o = s:option(Value, "method", translate("Encrypt Method"))
for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end
-o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
+o = s:option(Value, "timeout", translate("Connection Timeout"))
o.datatype = "uinteger"
o.default = 300
-o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
+o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"), translate("Need node support required"))
o.default = 0
-o = s:option(Flag, _n("plugin_enabled"), translate("plugin"))
+o = s:option(Flag, "plugin_enabled", translate("plugin"))
o.default = 0
-o = s:option(Value, _n("plugin"), "SIP003 " .. translate("plugin"), translate("Supports custom SIP003 plugins, Make sure the plugin is installed."))
+o = s:option(Value, "plugin", "SIP003 " .. translate("plugin"), translate("Supports custom SIP003 plugins, Make sure the plugin is installed."))
o.default = "none"
o:value("none", translate("none"))
if api.is_finded("xray-plugin") then o:value("xray-plugin") end
if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end
if api.is_finded("obfs-local") then o:value("obfs-local") end
if api.is_finded("shadow-tls") then o:value("shadow-tls") end
-o:depends({ [_n("plugin_enabled")] = true })
+o:depends({ plugin_enabled = true })
o.validate = function(self, value, t)
if value and value ~= "" and value ~= "none" then
if not api.is_finded(value) then
@@ -66,7 +62,7 @@ o.validate = function(self, value, t)
return nil
end
-o = s:option(Value, _n("plugin_opts"), translate("opts"))
-o:depends({ [_n("plugin_enabled")] = true })
+o = s:option(Value, "plugin_opts", translate("opts"))
+o:depends({ plugin_enabled = true })
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ssr.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ssr.lua
index f23e8efa..4d18c36e 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ssr.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ssr.lua
@@ -1,24 +1,20 @@
-local m, s = ...
-
if not api.is_finded("ssr-local") then
return
end
-type_name = "SSR"
-
-- [[ ShadowsocksR Libev ]]
+local m, s1 = ...
+local type_name = "SSR"
-s.fields["type"]:value(type_name, "ShadowsocksR Libev")
+s1.fields["type"]:value(type_name, "ShadowsocksR Libev")
-if s.val["type"] ~= type_name then
+if s1.val["type"] ~= type_name then
return
end
-local option_prefix = "ssr_"
-
-local function _n(name)
- return option_prefix .. name
-end
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "ssr_"
local ssr_encrypt_method_list = {
"none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb",
@@ -39,32 +35,32 @@ local ssr_obfs_list = {
"tls1.0_session_auth", "tls1.2_ticket_auth"
}
-o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
+o = s:option(Value, "address", translate("Address (Support Domain Name)"))
-o = s:option(Value, _n("port"), translate("Port"))
+o = s:option(Value, "port", translate("Port"))
o.datatype = "port"
-o = s:option(Value, _n("password"), translate("Password"))
+o = s:option(Value, "password", translate("Password"))
o.password = true
-o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
+o = s:option(ListValue, "method", translate("Encrypt Method"))
for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end
-o = s:option(ListValue, _n("protocol"), translate("Protocol"))
+o = s:option(ListValue, "protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do o:value(t) end
-o = s:option(Value, _n("protocol_param"), translate("Protocol_param"))
+o = s:option(Value, "protocol_param", translate("Protocol_param"))
-o = s:option(ListValue, _n("obfs"), translate("Obfs"))
+o = s:option(ListValue, "obfs", translate("Obfs"))
for a, t in ipairs(ssr_obfs_list) do o:value(t) end
-o = s:option(Value, _n("obfs_param"), translate("Obfs_param"))
+o = s:option(Value, "obfs_param", translate("Obfs_param"))
-o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
+o = s:option(Value, "timeout", translate("Connection Timeout"))
o.datatype = "uinteger"
o.default = 300
-o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
+o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"), translate("Need node support required"))
o.default = 0
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/server_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/server_config.lua
index 79f6b54f..816d911d 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/server_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/server_config.lua
@@ -17,7 +17,7 @@ m:foreach("user", function(s)
user_list[#user_list + 1] = s
end)
-s = m:section(NamedSection, arg[1], "server", translate("Server Config"))
+local s = m:section(NamedSection, arg[1], "server", translate("Server Config"))
s.addremove = false
s.dynamic = false
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua
index 998682af..8c6114e8 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua
@@ -1,135 +1,27 @@
-local m, s = ...
-
if not api.finded_com("hysteria") then
return
end
+-- [[ Hysteria2 ]]
+local m, s1 = ...
local type_name = "Hysteria2"
--- [[ Hysteria2 ]]
+s1.fields["type"]:value(type_name, "Hysteria2")
-s.fields["type"]:value(type_name, "Hysteria2")
-
-if s.val["type"] and s.val["type"] ~= type_name then
+if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
-local option_prefix = "hysteria2_"
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "hysteria2_"
-local function _n(name)
- return option_prefix .. name
-end
+o = s:option(Flag, "custom", translate("Use Custom Config"))
-o = s:option(Flag, _n("custom"), translate("Use Custom Config"))
-
-o = s:option(Value, _n("port"), translate("Listen Port"))
-o.datatype = "port"
-o:depends({ [_n("custom")] = false })
-
-o = s:option(DynamicList, _n("users"), translate("User"))
-for i, v in ipairs(user_list) do
- o:value(v[".name"], v.username)
-end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Flag, _n("realms"), translate("Realms"))
-o.default = "0"
-o.rewrite_option = o.option
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
-o.rewrite_option = o.option
-o:depends({ [_n("realms")] = "1" })
-o.validate = function(self, value)
- value = api.trim(value)
- local realm = api.parse_realm_uri(value)
- if realm then return value end
- return nil, translate("Invalid Realm URL.")
-end
-
-o = s:option(DynamicList, _n("realm_stun"), translate("Realm STUN"))
-o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
-o.rewrite_option = o.option
-o:depends({ [_n("realms")] = "1" })
-
-o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
-o:value("", translate("Disable"))
-o:value("salamander")
-o:value("gecko")
-o.rewrite_option = o.option
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
-o.rewrite_option = o.option
-o:depends({ [_n("obfs_type")] = "salamander" })
-o:depends({ [_n("obfs_type")] = "gecko" })
-
-o = s:option(Value, _n("obfs_MinPacketSize"), translate("Gecko Packet Size (min)"))
-o.datatype = "uinteger"
-o.placeholder = "512"
-o.default = "512"
-o:depends({ [_n("obfs_type")] = "gecko" })
-o.rewrite_option = o.option
-
-o = s:option(Value, _n("obfs_MaxPacketSize"), translate("Gecko Packet Size (max)"))
-o.datatype = "uinteger"
-o.placeholder = "1200"
-o.default = "1200"
-o:depends({ [_n("obfs_type")] = "gecko" })
-o.rewrite_option = o.option
-
-o = s:option(Flag, _n("udp"), translate("UDP"))
-o.default = "1"
-o.rewrite_option = o.option
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("up_mbps"), translate("Max upload Mbps"))
-o.rewrite_option = o.option
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("down_mbps"), translate("Max download Mbps"))
-o.rewrite_option = o.option
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Flag, _n("ignoreClientBandwidth"), translate("ignoreClientBandwidth"))
-o.default = "0"
-o.rewrite_option = o.option
-o:depends({ [_n("custom")] = false })
-
-o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
-o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
-if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
-o.validate = function(self, value, t)
- if value and value ~= "" then
- if not nixio.fs.access(value) then
- return nil, translate("Can't find this file!")
- else
- return value
- end
- end
- return nil
-end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
-o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
-if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
-o.validate = function(self, value, t)
- if value and value ~= "" then
- if not nixio.fs.access(value) then
- return nil, translate("Can't find this file!")
- else
- return value
- end
- end
- return nil
-end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(TextValue, _n("custom_config"), translate("Custom Config"))
+o = s:option(TextValue, "custom_config", translate("Custom Config"))
o.rows = 10
o.wrap = "off"
-o:depends({ [_n("custom")] = true })
+o:depends({ custom = true })
o.datatype = "json"
local o_validate = o.validate
o.validate = function(self, value)
@@ -147,8 +39,101 @@ o.custom_write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
-o = s:option(Flag, _n("log"), translate("Log"))
+o = s:option(Value, "port", translate("Listen Port"))
+o.datatype = "port"
+o:depends({ custom = false })
+
+o = s:option(DynamicList, "users", translate("User"))
+for i, v in ipairs(user_list) do
+ o:value(v[".name"], v.username)
+end
+o:depends({ custom = false })
+
+o = s:option(Flag, "realms", translate("Realms"))
+o.default = "0"
+o:depends({ custom = false })
+
+o = s:option(Value, "realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
+o:depends({ realms = true })
+o.validate = function(self, value)
+ value = api.trim(value)
+ local realm = api.parse_realm_uri(value)
+ if realm then return value end
+ return nil, translate("Invalid Realm URL.")
+end
+
+o = s:option(DynamicList, "realm_stun", translate("Realm STUN"))
+o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
+o:depends({ realms = true })
+
+o = s:option(ListValue, "obfs_type", translate("Obfs Type"))
+o:value("", translate("Disable"))
+o:value("salamander")
+o:value("gecko")
+o:depends({ custom = false })
+
+o = s:option(Value, "obfs_password", translate("Obfs Password"))
+o:depends({ obfs_type = "salamander" })
+o:depends({ obfs_type = "gecko" })
+
+o = s:option(Value, "obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
+o.datatype = "uinteger"
+o.placeholder = "512"
+o.default = "512"
+o:depends({ obfs_type = "gecko" })
+
+o = s:option(Value, "obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
+o.datatype = "uinteger"
+o.placeholder = "1200"
+o.default = "1200"
+o:depends({ obfs_type = "gecko" })
+
+o = s:option(Flag, "udp", translate("UDP"))
+o.default = "1"
+o:depends({ custom = false })
+
+o = s:option(Value, "up_mbps", translate("Max upload Mbps"))
+o:depends({ custom = false })
+
+o = s:option(Value, "down_mbps", translate("Max download Mbps"))
+o:depends({ custom = false })
+
+o = s:option(Flag, "ignoreClientBandwidth", translate("ignoreClientBandwidth"))
+o.default = "0"
+o:depends({ custom = false })
+
+o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
+o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
+if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
+o.validate = function(self, value, t)
+ if value and value ~= "" then
+ if not api.fs.access(value) then
+ return nil, translate("Can't find this file!")
+ else
+ return value
+ end
+ end
+ return nil
+end
+o:depends({ custom = false })
+
+o = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
+o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
+if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
+o.validate = function(self, value, t)
+ if value and value ~= "" then
+ if not api.fs.access(value) then
+ return nil, translate("Can't find this file!")
+ else
+ return value
+ end
+ end
+ return nil
+end
+o:depends({ custom = false })
+
+o = s:option(Flag, "log", translate("Log"))
o.default = "1"
o.rmempty = false
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua
index 20ac33e8..ae79afb3 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua
@@ -1,29 +1,25 @@
-local m, s = ...
-
if not api.finded_com("xray") then
return
end
+-- [[ Xray ]]
+local m, s1 = ...
local type_name = "Xray"
--- [[ Xray ]]
-
-s.fields["type"]:value(type_name, "Xray")
-if not s.fields["type"].default then
- s.fields["type"].default = type_name
+s1.fields["type"]:value(type_name, "Xray")
+if not s1.fields["type"].default then
+ s1.fields["type"].default = type_name
end
-if s.val["type"] and s.val["type"] ~= type_name then
+if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
-local option_prefix = "xray_"
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "xray_"
-local function _n(name)
- return option_prefix .. name
-end
-
-local x_ss_method_list = {
+local ss_method_list = {
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
}
@@ -31,90 +27,91 @@ local header_type_list = {
"none", "srtp", "utp", "wechat-video", "dtls", "wireguard", "dns"
}
-o = s:option(Flag, _n("custom"), translate("Use Custom Config"))
+o = s:option(Flag, "custom", translate("Use Custom Config"))
-o = s:option(ListValue, _n("protocol"), translate("Protocol"))
+o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("vmess", "Vmess")
o:value("vless", "VLESS")
o:value("http", "HTTP")
o:value("socks", "Socks")
o:value("shadowsocks", "Shadowsocks")
o:value("trojan", "Trojan")
-o:value("hysteria2", translate("Hysteria2"))
+o:value("hysteria2", "Hysteria2")
+o:value("wireguard", "WireGuard")
o:value("dokodemo-door", "dokodemo-door")
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
-o = s:option(Value, _n("port"), translate("Listen Port"))
+o = s:option(Value, "port", translate("Listen Port"))
o.datatype = "port"
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
-o = s:option(DynamicList, _n("users"), translate("User"))
+o = s:option(DynamicList, "users", translate("User"))
for i, v in ipairs(user_list) do
o:value(v[".name"], v.username)
end
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "trojan" })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "trojan" })
+o:depends({ protocol = "hysteria2" })
+o:depends({ protocol = "wireguard" })
-o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
+o = s:option(ListValue, "d_protocol", translate("Destination protocol"))
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP")
-o:depends({ [_n("protocol")] = "dokodemo-door" })
+o:depends({ protocol = "dokodemo-door" })
-o = s:option(Value, _n("d_address"), translate("Destination address"))
-o:depends({ [_n("protocol")] = "dokodemo-door" })
+o = s:option(Value, "d_address", translate("Destination address"))
+o:depends({ protocol = "dokodemo-door" })
-o = s:option(Value, _n("d_port"), translate("Destination port"))
+o = s:option(Value, "d_port", translate("Destination port"))
o.datatype = "port"
-o:depends({ [_n("protocol")] = "dokodemo-door" })
+o:depends({ protocol = "dokodemo-door" })
-o = s:option(Value, _n("decryption"), translate("Encrypt Method") .. " (decryption)")
+o = s:option(Value, "decryption", translate("Encrypt Method") .. " (decryption)")
o.default = "none"
o.placeholder = "none"
-o:depends({ [_n("protocol")] = "vless" })
+o:depends({ protocol = "vless" })
o.validate = function(self, value)
value = api.trim(value)
return (value == "" and "none" or value)
end
-o = s:option(ListValue, _n("x_ss_method"), translate("Encrypt Method"))
-o.rewrite_option = "method"
-for a, t in ipairs(x_ss_method_list) do o:value(t) end
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o = s:option(ListValue, "ss_method", translate("Encrypt Method"))
+for a, t in ipairs(ss_method_list) do o:value(t) end
+o:depends({ protocol = "shadowsocks" })
-o = s:option(Value, _n("ss_password"), translate("Password"))
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o = s:option(Value, "ss_password", translate("Password"))
+o:depends({ protocol = "shadowsocks" })
-o = s:option(ListValue, _n("ss_network"), translate("Transport"))
+o = s:option(ListValue, "ss_network", translate("Transport"))
o.default = "tcp,udp"
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP")
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o:depends({ protocol = "shadowsocks" })
-o = s:option(Flag, _n("udp_forward"), translate("UDP Forward"))
+o = s:option(Flag, "udp_forward", translate("UDP Forward"))
o.default = "1"
o.rmempty = false
-o:depends({ [_n("protocol")] = "socks" })
+o:depends({ protocol = "socks" })
-o = s:option(ListValue, _n("flow"), translate("flow"))
+o = s:option(ListValue, "flow", translate("flow"))
o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
-o:depends({ [_n("protocol")] = "vless" })
+o:depends({ protocol = "vless" })
---- [[ hysteria2 ]]
-o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
+o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
-o:depends({ [_n("protocol")] = "hysteria2"})
+o:depends({ protocol = "hysteria2"})
-o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
-o:depends({ [_n("hysteria2_realms")] = "1" })
+o = s:option(Value, "hysteria2_realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
+o:depends({ hysteria2_realms = "1" })
o.validate = function(self, value)
value = api.trim(value)
local realm = api.parse_realm_uri(value)
@@ -122,52 +119,52 @@ o.validate = function(self, value)
return nil, translate("Invalid Realm URL.")
end
-o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
+o = s:option(DynamicList, "hysteria2_realm_stun", translate("Realm STUN"))
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
-o:depends({ [_n("hysteria2_realms")] = "1" })
+o:depends({ hysteria2_realms = "1" })
-o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
+o = s:option(ListValue, "hysteria2_obfs_type", translate("Obfs Type"))
o:value("", translate("Disable"))
o:value("salamander")
o:value("gecko")
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ protocol = "hysteria2" })
-o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
-o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
-o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+o = s:option(Value, "hysteria2_obfs_password", translate("Obfs Password"))
+o:depends({ hysteria2_obfs_type = "salamander" })
+o:depends({ hysteria2_obfs_type = "gecko" })
-o = s:option(Value, _n("hysteria2_obfs_MinPacketSize"), translate("Gecko Packet Size (min)"))
+o = s:option(Value, "hysteria2_obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
o.datatype = "uinteger"
o.placeholder = "512"
o.default = "512"
-o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+o:depends({ hysteria2_obfs_type = "gecko" })
-o = s:option(Value, _n("hysteria2_obfs_MaxPacketSize"), translate("Gecko Packet Size (max)"))
+o = s:option(Value, "hysteria2_obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
o.datatype = "uinteger"
o.placeholder = "1200"
o.default = "1200"
-o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+o:depends({ hysteria2_obfs_type = "gecko" })
-o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"))
+o = s:option(Flag, "hysteria2_ignore_client_bandwidth", translate("Client BBR Flow Control"))
o.default = 0
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ protocol = "hysteria2" })
-o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
+o = s:option(Value, "hysteria2_up_mbps", translate("Max upload Mbps"))
+o:depends({ protocol = "hysteria2", hysteria2_ignore_client_bandwidth = false })
-o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
+o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps"))
+o:depends({ protocol = "hysteria2", hysteria2_ignore_client_bandwidth = false })
---- [[ TLS ]]
-o = s:option(Flag, _n("tls"), translate("TLS"))
+o = s:option(Flag, "tls", "TLS")
o.default = 0
o.validate = function(self, value, t)
if value then
- local reality = s.fields[_n("reality")] and s.fields[_n("reality")]:formvalue(t) or nil
+ local reality = s.fields["reality"] and s.fields["reality"]:formvalue(t) or nil
if reality and reality == "1" then return value end
if value == "1" then
- local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
- local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
+ local ca = s.fields["tls_certificateFile"] and s.fields["tls_certificateFile"]:formvalue(t) or ""
+ local key = s.fields["tls_keyFile"] and s.fields["tls_keyFile"]:formvalue(t) or ""
if ca == "" or key == "" then
return nil, translate("Public key and Private key path can not be empty!")
end
@@ -175,32 +172,32 @@ o.validate = function(self, value, t)
return value
end
end
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "trojan" })
-- [[ REALITY ]] --
-o = s:option(Flag, _n("reality"), translate("REALITY"))
+o = s:option(Flag, "reality", translate("REALITY"))
o.default = 0
-o:depends({ [_n("tls")] = true })
+o:depends({ tls = true })
-o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
-o:depends({ [_n("reality")] = true })
+o = s:option(Value, "reality_private_key", translate("Private Key"))
+o:depends({ reality = true })
-o = s:option(DynamicList, _n("reality_shortId"), translate("Short Id"))
-o:depends({ [_n("reality")] = true })
+o = s:option(DynamicList, "reality_shortId", translate("Short Id"))
+o:depends({ reality = true })
-o = s:option(Value, _n("reality_dest"), translate("Dest"))
+o = s:option(Value, "reality_dest", translate("Dest"))
o.default = "google.com:443"
-o:depends({ [_n("reality")] = true })
+o:depends({ reality = true })
-o = s:option(DynamicList, _n("reality_serverNames"), translate("serverNames"))
-o:depends({ [_n("reality")] = true })
+o = s:option(DynamicList, "reality_serverNames", translate("serverNames"))
+o:depends({ reality = true })
-o = s:option(ListValue, _n("alpn"), translate("alpn"))
+o = s:option(ListValue, "alpn", translate("alpn"))
o.default = "default"
o:value("default", translate("Default"))
o:value("h3")
@@ -209,35 +206,35 @@ o:value("h3,h2")
o:value("http/1.1")
o:value("h2,http/1.1")
o:value("h3,h2,http/1.1")
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
+o:depends({ tls = true, reality = false })
-o = s:option(Flag, _n("use_mldsa65Seed"), translate("ML-DSA-65"))
+o = s:option(Flag, "use_mldsa65Seed", translate("ML-DSA-65"))
o.default = "0"
-o:depends({ [_n("reality")] = true })
+o:depends({ reality = true })
-o = s:option(TextValue, _n("reality_mldsa65Seed"), "ML-DSA-65 " .. translate("Private Key"))
+o = s:option(TextValue, "reality_mldsa65Seed", "ML-DSA-65 " .. translate("Private Key"))
o.default = ""
o.rows = 5
o.wrap = "soft"
-o:depends({ [_n("use_mldsa65Seed")] = true })
+o:depends({ use_mldsa65Seed = true })
o.validate = function(self, value)
return api.trim(value:gsub("[\r\n]", ""))
end
--- o = s:option(Value, _n("minversion"), translate("minversion"))
+-- o = s:option(Value, "minversion", translate("minversion"))
-- o.default = "1.3"
-- o:value("1.3")
---o:depends({ [_n("tls")] = true })
+--o:depends({ tls = true })
-- [[ TLS ]] --
-o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
+o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria2"})
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria2"})
o.validate = function(self, value, t)
if value and value ~= "" then
- if not nixio.fs.access(value) then
+ if not api.fs.access(value) then
return nil, translate("Can't find this file!")
else
return value
@@ -246,14 +243,14 @@ o.validate = function(self, value, t)
return nil
end
-o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
+o = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria2"})
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria2"})
o.validate = function(self, value, t)
if value and value ~= "" then
- if not nixio.fs.access(value) then
+ if not api.fs.access(value) then
return nil, translate("Can't find this file!")
else
return value
@@ -262,117 +259,116 @@ o.validate = function(self, value, t)
return nil
end
-o = s:option(Flag, _n("ech"), translate("ECH"))
+o = s:option(Flag, "ech", translate("ECH"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
+o:depends({ tls = true, reality = false })
-o = s:option(TextValue, _n("ech_key"), translate("ECH Key"))
+o = s:option(TextValue, "ech_key", translate("ECH Key"))
o.default = ""
o.rows = 5
o.wrap = "soft"
-o:depends({ [_n("ech")] = true })
+o:depends({ ech = true })
o.validate = function(self, value)
return api.trim(value:gsub("[\r\n]", ""))
end
-o = s:option(ListValue, _n("transport"), translate("Transport"))
+o = s:option(ListValue, "transport", translate("Transport"))
o:value("raw", "RAW")
o:value("mkcp", "mKCP")
o:value("ws", "WebSocket")
o:value("grpc", "gRPC")
o:value("httpupgrade", "HttpUpgrade")
o:value("xhttp", "XHTTP")
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "trojan" })
-- [[ WebSocket ]]--
-o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
-o:depends({ [_n("transport")] = "ws" })
+o = s:option(Value, "ws_host", translate("WebSocket Host"))
+o:depends({ transport = "ws" })
-o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
-o:depends({ [_n("transport")] = "ws" })
+o = s:option(Value, "ws_path", translate("WebSocket Path"))
+o:depends({ transport = "ws" })
-- [[ HttpUpgrade ]]--
-o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
-o:depends({ [_n("transport")] = "httpupgrade" })
+o = s:option(Value, "httpupgrade_host", translate("HttpUpgrade Host"))
+o:depends({ transport = "httpupgrade" })
-o = s:option(Value, _n("httpupgrade_path"), translate("HttpUpgrade Path"))
+o = s:option(Value, "httpupgrade_path", translate("HttpUpgrade Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "httpupgrade" })
+o:depends({ transport = "httpupgrade" })
-- [[ XHTTP ]]--
-o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
-o:depends({ [_n("transport")] = "xhttp" })
+o = s:option(Value, "xhttp_host", translate("XHTTP Host"))
+o:depends({ transport = "xhttp" })
-o = s:option(Value, _n("xhttp_path"), translate("XHTTP Path"))
+o = s:option(Value, "xhttp_path", translate("XHTTP Path"))
o.placeholder = "/"
-o:depends({ [_n("transport")] = "xhttp" })
+o:depends({ transport = "xhttp" })
-o = s:option(Value, _n("xhttp_maxuploadsize"), translate("maxUploadSize"))
+o = s:option(Value, "xhttp_maxuploadsize", translate("maxUploadSize"))
o.default = "1000000"
-o:depends({ [_n("transport")] = "xhttp" })
+o:depends({ transport = "xhttp" })
-o = s:option(Value, _n("xhttp_maxconcurrentuploads"), translate("maxConcurrentUploads"))
+o = s:option(Value, "xhttp_maxconcurrentuploads", translate("maxConcurrentUploads"))
o.default = "10"
-o:depends({ [_n("transport")] = "xhttp" })
+o:depends({ transport = "xhttp" })
-o = s:option(Value, _n("splithttp_maxuploadsize"), translate("maxUploadSize"))
+o = s:option(Value, "splithttp_maxuploadsize", translate("maxUploadSize"))
o.default = "1000000"
-o:depends({ [_n("transport")] = "splithttp" })
+o:depends({ transport = "splithttp" })
-o = s:option(Value, _n("splithttp_maxconcurrentuploads"), translate("maxConcurrentUploads"))
+o = s:option(Value, "splithttp_maxconcurrentuploads", translate("maxConcurrentUploads"))
o.default = "10"
-o:depends({ [_n("transport")] = "splithttp" })
+o:depends({ transport = "splithttp" })
-- [[ TCP ]]--
-o = s:option(ListValue, _n("tcp_guise"), translate("Camouflage Type"))
+o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
o:value("none", "none")
o:value("http", "http")
-o:depends({ [_n("transport")] = "raw" })
+o:depends({ transport = "raw" })
-o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
-o:depends({ [_n("tcp_guise")] = "http" })
+o = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host"))
+o:depends({ tcp_guise = "http" })
-o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
-o:depends({ [_n("tcp_guise")] = "http" })
+o = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path"))
+o:depends({ tcp_guise = "http" })
-- [[ mKCP ]]--
-o = s:option(ListValue, _n("mkcp_guise"), translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests.'))
+o = s:option(ListValue, "mkcp_guise", translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests.'))
for a, t in ipairs(header_type_list) do o:value(t) end
-o:depends({ [_n("transport")] = "mkcp" })
+o:depends({ transport = "mkcp" })
-o = s:option(Value, _n("mkcp_domain"), translate("Camouflage Domain"), translate("Use it together with the DNS disguised type. You can fill in any domain."))
-o:depends({ [_n("mkcp_guise")] = "dns" })
+o = s:option(Value, "mkcp_domain", translate("Camouflage Domain"), translate("Use it together with the DNS disguised type. You can fill in any domain."))
+o:depends({ mkcp_guise = "dns" })
-o = s:option(Value, _n("mkcp_mtu"), translate("KCP MTU"))
+o = s:option(Value, "mkcp_mtu", translate("KCP MTU"))
o.datatype = "uinteger"
o.default = 1350
-o:depends({ [_n("transport")] = "mkcp" })
+o:depends({ transport = "mkcp" })
-o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
-o:depends({ [_n("transport")] = "mkcp" })
+o = s:option(Value, "mkcp_seed", translate("KCP Seed"))
+o:depends({ transport = "mkcp" })
-- [[ gRPC ]]--
-o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
-o:depends({ [_n("transport")] = "grpc" })
+o = s:option(Value, "grpc_serviceName", "ServiceName")
+o:depends({ transport = "grpc" })
--[[FinalMask]]
-o = s:option(Flag, _n("use_finalmask"), "FinalMask")
+o = s:option(Flag, "use_finalmask", "FinalMask")
o.default = "0"
-o:depends({ [_n("custom")] = false, [_n("protocol")] = "vmess" })
-o:depends({ [_n("custom")] = false, [_n("protocol")] = "vless" })
-o:depends({ [_n("custom")] = false, [_n("protocol")] = "trojan" })
-o:depends({ [_n("custom")] = false, [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("custom")] = false, [_n("protocol")] = "wireguard" })
-o:depends({ [_n("custom")] = false, [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+o:depends({ custom = false, protocol = "vmess" })
+o:depends({ custom = false, protocol = "vless" })
+o:depends({ custom = false, protocol = "trojan" })
+o:depends({ custom = false, protocol = "shadowsocks" })
+o:depends({ custom = false, protocol = "hysteria2", hysteria2_realms = false })
-o = s:option(TextValue, _n("finalmask"), "FinalMask JSON")
-o:depends({ [_n("use_finalmask")] = true })
+o = s:option(TextValue, "finalmask", "FinalMask JSON")
+o:depends({ use_finalmask = true })
o.rows = 10
o.wrap = "off"
o.datatype = "json"
@@ -387,48 +383,78 @@ o.custom_write = function(self, section, value)
end
--[[acceptProxyProtocol]]
-o = s:option(Flag, _n("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
+o = s:option(Flag, "acceptProxyProtocol", translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
o.default = "0"
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
--[[Fast Open]]
-o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
+o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"))
o.default = "0"
-o:depends({ [_n("protocol")] = "vmess", [_n("custom")] = false })
-o:depends({ [_n("protocol")] = "vless", [_n("custom")] = false })
-o:depends({ [_n("protocol")] = "shadowsocks", [_n("custom")] = false })
-o:depends({ [_n("protocol")] = "trojan", [_n("custom")] = false })
+o:depends({ protocol = "vmess", custom = false })
+o:depends({ protocol = "vless", custom = false })
+o:depends({ protocol = "shadowsocks", custom = false })
+o:depends({ protocol = "trojan", custom = false })
-- [[ Fallback ]]--
-o = s:option(Flag, _n("fallback"), translate("Fallback"))
-o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "raw" })
-o:depends({ [_n("protocol")] = "trojan", [_n("transport")] = "raw" })
+o = s:option(Flag, "fallback", translate("Fallback"))
+o:depends({ protocol = "vless", transport = "raw" })
+o:depends({ protocol = "trojan", transport = "raw" })
--[[
-o = s:option(Value, _n("fallback_alpn"), "Fallback alpn")
-o:depends({ [_n("fallback")] = true })
+o = s:option(Value, "fallback_alpn", "Fallback alpn")
+o:depends({ fallback = true })
-o = s:option(Value, _n("fallback_path"), "Fallback path")
-o:depends({ [_n("fallback")] = true })
+o = s:option(Value, "fallback_path", "Fallback path")
+o:depends({ fallback = true })
-o = s:option(Value, _n("fallback_dest"), "Fallback dest")
-o:depends({ [_n("fallback")] = true })
+o = s:option(Value, "fallback_dest", "Fallback dest")
+o:depends({ fallback = true })
-o = s:option(Value, _n("fallback_xver"), "Fallback xver")
+o = s:option(Value, "fallback_xver", "Fallback xver")
o.default = 0
-o:depends({ [_n("fallback")] = true })
+o:depends({ fallback = true })
]]--
-o = s:option(DynamicList, _n("fallback_list"), "Fallback", translate("format: dest,path,xver"))
-o:depends({ [_n("fallback")] = true })
+o = s:option(DynamicList, "fallback_list", "Fallback", translate("format: dest,path,xver"))
+o:depends({ fallback = true })
-o = s:option(Flag, _n("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
-o.default = "0"
-o:depends({ [_n("custom")] = false })
+-- Not supported at present
+--[[
+o = s:option(Flag, "wireguard_system_interface", translate("System interface"))
+o.default = 0
+o:depends({ protocol = "wireguard" })
+]]--
-o = s:option(Flag, _n("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
+o = s:option(Value, "wireguard_mtu", "MTU")
+o.default = "1420"
+o:depends({ protocol = "wireguard" })
+
+-- Not supported at present
+--[[
+o = s:option(DynamicList, "wireguard_local_address", translate("Local Address"))
+o:depends({ protocol = "wireguard" })
+]]--
+
+o = s:option(Value, "wireguard_private_key", translate("Private Key"))
+o.datatype = "base64"
+o:depends({ protocol = "wireguard" })
+
+o = s:option(Value, "wireguard_public_key", translate("Public Key"))
+o.datatype = "base64"
+o:depends({ protocol = "wireguard" })
+
+o = s:option(DummyValue, "gen_wireguard_key")
+o.prefix = option_prefix
+o.template = m:template_path("/server/server_wireguard")
+o:depends({ protocol = "wireguard" })
+
+o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
o.default = "0"
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
+
+o = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
+o.default = "0"
+o:depends({ custom = false })
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
@@ -441,7 +467,7 @@ for k, e in ipairs(api.get_valid_nodes()) do
end
end
-o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
+o = s:option(ListValue, "outbound_node", translate("outbound node"))
o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
@@ -452,37 +478,37 @@ for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
o.group[#o.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
end
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
-o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
-o:depends({ [_n("outbound_node")] = "_socks"})
-o:depends({ [_n("outbound_node")] = "_http"})
+o = s:option(Value, "outbound_node_address", translate("Address (Support Domain Name)"))
+o:depends({ outbound_node = "_socks"})
+o:depends({ outbound_node = "_http"})
-o = s:option(Value, _n("outbound_node_port"), translate("Port"))
+o = s:option(Value, "outbound_node_port", translate("Port"))
o.datatype = "port"
-o:depends({ [_n("outbound_node")] = "_socks"})
-o:depends({ [_n("outbound_node")] = "_http"})
+o:depends({ outbound_node = "_socks"})
+o:depends({ outbound_node = "_http"})
-o = s:option(Value, _n("outbound_node_username"), translate("Username"))
-o:depends({ [_n("outbound_node")] = "_socks"})
-o:depends({ [_n("outbound_node")] = "_http"})
+o = s:option(Value, "outbound_node_username", translate("Username"))
+o:depends({ outbound_node = "_socks"})
+o:depends({ outbound_node = "_http"})
-o = s:option(Value, _n("outbound_node_password"), translate("Password"))
+o = s:option(Value, "outbound_node_password", translate("Password"))
o.password = true
-o:depends({ [_n("outbound_node")] = "_socks"})
-o:depends({ [_n("outbound_node")] = "_http"})
+o:depends({ outbound_node = "_socks"})
+o:depends({ outbound_node = "_http"})
-o = s:option(Value, _n("outbound_node_iface"), translate("Interface"))
-o:depends({ [_n("outbound_node")] = "_iface"})
+o = s:option(Value, "outbound_node_iface", translate("Interface"))
+o:depends({ outbound_node = "_iface"})
local netdev_list = api.get_network_devices()
for _, d in ipairs(netdev_list) do
o:value(d.name, d.label)
end
-o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
+o = s:option(TextValue, "custom_config", translate("Custom Config") .. " (JSON)")
o.rows = 10
o.wrap = "off"
-o:depends({ [_n("custom")] = true })
+o:depends({ custom = true })
o.datatype = "json"
local o_validate = o.validate
o.validate = function(self, value)
@@ -500,16 +526,16 @@ o.custom_write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
-o = s:option(Flag, _n("log"), translate("Log"))
+o = s:option(Flag, "log", translate("Log"))
o.default = "1"
o.rmempty = false
-o = s:option(ListValue, _n("loglevel"), translate("Log Level"))
+o = s:option(ListValue, "loglevel", translate("Log Level"))
o.default = "warning"
o:value("debug")
o:value("info")
o:value("warning")
o:value("error")
-o:depends({ [_n("log")] = true })
+o:depends({ log = true })
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua
index abbd3b67..59b772e3 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua
@@ -1,29 +1,25 @@
-local m, s = ...
-
local singbox_bin = api.finded_com("sing-box")
if not singbox_bin then
return
end
+-- [[ Sing-Box ]]
+local m, s1 = ...
local type_name = "sing-box"
--- [[ Sing-Box ]]
-
-s.fields["type"]:value(type_name, "Sing-Box")
-if not s.fields["type"].default then
- s.fields["type"].default = type_name
+s1.fields["type"]:value(type_name, "Sing-Box")
+if not s1.fields["type"].default then
+ s1.fields["type"].default = type_name
end
-if s.val["type"] and s.val["type"] ~= type_name then
+if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
-local option_prefix = "singbox_"
-
-local function _n(name)
- return option_prefix .. name
-end
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "singbox_"
local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'")
@@ -32,9 +28,9 @@ local ss_method_list = {
"2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
}
-o = s:option(Flag, _n("custom"), translate("Use Custom Config"))
+o = s:option(Flag, "custom", translate("Use Custom Config"))
-o = s:option(ListValue, _n("protocol"), translate("Protocol"))
+o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("mixed", "Mixed")
o:value("socks", "Socks")
o:value("http", "HTTP")
@@ -57,74 +53,74 @@ if singbox_tags:find("with_wireguard") then
o:value("wireguard", "WireGuard")
end
o:value("direct", "Direct")
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
-o = s:option(Value, _n("port"), translate("Listen Port"))
+o = s:option(Value, "port", translate("Listen Port"))
o.datatype = "port"
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
-o = s:option(DynamicList, _n("users"), translate("User"))
+o = s:option(DynamicList, "users", translate("User"))
for i, v in ipairs(user_list) do
o:value(v[".name"], v.username)
end
-o:depends({ [_n("protocol")] = "mixed" })
-o:depends({ [_n("protocol")] = "socks" })
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "trojan" })
-o:depends({ [_n("protocol")] = "naive" })
-o:depends({ [_n("protocol")] = "hysteria" })
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2" })
-o:depends({ [_n("protocol")] = "anytls" })
-o:depends({ [_n("protocol")] = "wireguard" })
+o:depends({ protocol = "mixed" })
+o:depends({ protocol = "socks" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "trojan" })
+o:depends({ protocol = "naive" })
+o:depends({ protocol = "hysteria" })
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2" })
+o:depends({ protocol = "anytls" })
+o:depends({ protocol = "wireguard" })
if singbox_tags:find("with_quic") then
- o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Value, "hysteria_obfs", translate("Obfs Password"))
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_up_mbps"), translate("Max upload Mbps"))
+ o = s:option(Value, "hysteria_up_mbps", translate("Max upload Mbps"))
o.default = "100"
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_down_mbps"), translate("Max download Mbps"))
+ o = s:option(Value, "hysteria_down_mbps", translate("Max download Mbps"))
o.default = "100"
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Value, "hysteria_recv_window_conn", translate("QUIC stream receive window"))
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_recv_window_client"), translate("QUIC connection receive window"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Value, "hysteria_recv_window_client", translate("QUIC connection receive window"))
+ o:depends({ protocol = "hysteria" })
- o = s:option(Value, _n("hysteria_max_conn_client"), translate("QUIC concurrent bidirectional streams"))
+ o = s:option(Value, "hysteria_max_conn_client", translate("QUIC concurrent bidirectional streams"))
o.default = "1024"
- o:depends({ [_n("protocol")] = "hysteria" })
+ o:depends({ protocol = "hysteria" })
- o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
- o:depends({ [_n("protocol")] = "hysteria" })
+ o = s:option(Flag, "hysteria_disable_mtu_discovery", translate("Disable MTU detection"))
+ o:depends({ protocol = "hysteria" })
end
if singbox_tags:find("with_quic") then
- o = s:option(ListValue, _n("tuic_congestion_control"), translate("Congestion control algorithm"))
+ o = s:option(ListValue, "tuic_congestion_control", translate("Congestion control algorithm"))
o.default = "cubic"
o:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno"))
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
- o = s:option(Flag, _n("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
+ o = s:option(Flag, "tuic_zero_rtt_handshake", translate("Enable 0-RTT QUIC handshake"))
o.default = 0
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
- o = s:option(Value, _n("tuic_heartbeat"), translate("Heartbeat interval(second)"))
+ o = s:option(Value, "tuic_heartbeat", translate("Heartbeat interval(second)"))
o.datatype = "uinteger"
o.default = "3"
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
- o = s:option(ListValue, _n("tuic_alpn"), translate("QUIC TLS ALPN"))
+ o = s:option(ListValue, "tuic_alpn", translate("QUIC TLS ALPN"))
o.default = "default"
o:value("default", translate("Default"))
o:value("h3")
@@ -135,16 +131,16 @@ if singbox_tags:find("with_quic") then
o:value("h3,h2,http/1.1")
o:value("spdy/3.1")
o:value("h3,spdy/3.1")
- o:depends({ [_n("protocol")] = "tuic" })
+ o:depends({ protocol = "tuic" })
end
if singbox_tags:find("with_quic") then
- o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
+ o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
- o:depends({ [_n("protocol")] = "hysteria2"})
+ o:depends({ protocol = "hysteria2"})
- o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
- o:depends({ [_n("hysteria2_realms")] = "1" })
+ o = s:option(Value, "hysteria2_realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
+ o:depends({ hysteria2_realms = "1" })
o.validate = function(self, value)
value = api.trim(value)
local realm = api.parse_realm_uri(value)
@@ -152,83 +148,82 @@ if singbox_tags:find("with_quic") then
return nil, translate("Invalid Realm URL.")
end
- o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
+ o = s:option(DynamicList, "hysteria2_realm_stun", translate("Realm STUN"))
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
- o:depends({ [_n("hysteria2_realms")] = "1" })
+ o:depends({ hysteria2_realms = "1" })
- o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
+ o = s:option(ListValue, "hysteria2_obfs_type", translate("Obfs Type"))
o:value("", translate("Disable"))
o:value("salamander")
o:value("gecko")
- o:depends({ [_n("protocol")] = "hysteria2" })
+ o:depends({ protocol = "hysteria2" })
- o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
- o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
- o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+ o = s:option(Value, "hysteria2_obfs_password", translate("Obfs Password"))
+ o:depends({ hysteria2_obfs_type = "salamander" })
+ o:depends({ hysteria2_obfs_type = "gecko" })
- o = s:option(Value, _n("hysteria2_obfs_MinPacketSize"), translate("Gecko Packet Size (min)"))
+ o = s:option(Value, "hysteria2_obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
o.datatype = "uinteger"
o.placeholder = "512"
o.default = "512"
- o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+ o:depends({ hysteria2_obfs_type = "gecko" })
- o = s:option(Value, _n("hysteria2_obfs_MaxPacketSize"), translate("Gecko Packet Size (max)"))
+ o = s:option(Value, "hysteria2_obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
o.datatype = "uinteger"
o.placeholder = "1200"
o.default = "1200"
- o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
+ o:depends({ hysteria2_obfs_type = "gecko" })
- o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"), translate("Commands the client to use the BBR flow control algorithm"))
+ o = s:option(Flag, "hysteria2_ignore_client_bandwidth", translate("Client BBR Flow Control"), translate("Commands the client to use the BBR flow control algorithm"))
o.default = 0
- o:depends({ [_n("protocol")] = "hysteria2" })
+ o:depends({ protocol = "hysteria2" })
- o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
- o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
+ o = s:option(Value, "hysteria2_up_mbps", translate("Max upload Mbps"))
+ o:depends({ protocol = "hysteria2", hysteria2_ignore_client_bandwidth = false })
- o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
- o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
+ o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps"))
+ o:depends({ protocol = "hysteria2", hysteria2_ignore_client_bandwidth = false })
end
-o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
+o = s:option(ListValue, "d_protocol", translate("Destination protocol"))
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP")
-o:depends({ [_n("protocol")] = "direct" })
+o:depends({ protocol = "direct" })
-o = s:option(Value, _n("d_address"), translate("Destination address"))
-o:depends({ [_n("protocol")] = "direct" })
+o = s:option(Value, "d_address", translate("Destination address"))
+o:depends({ protocol = "direct" })
-o = s:option(Value, _n("d_port"), translate("Destination port"))
+o = s:option(Value, "d_port", translate("Destination port"))
o.datatype = "port"
-o:depends({ [_n("protocol")] = "direct" })
+o:depends({ protocol = "direct" })
-o = s:option(Value, _n("decryption"), translate("Encrypt Method"))
+o = s:option(Value, "decryption", translate("Encrypt Method"))
o.default = "none"
-o:depends({ [_n("protocol")] = "vless" })
+o:depends({ protocol = "vless" })
-o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
-o.rewrite_option = "method"
+o = s:option(ListValue, "ss_method", translate("Encrypt Method"))
for a, t in ipairs(ss_method_list) do o:value(t) end
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o:depends({ protocol = "shadowsocks" })
-o = s:option(Value, _n("ss_password"), translate("Password"))
-o:depends({ [_n("protocol")] = "shadowsocks" })
+o = s:option(Value, "ss_password", translate("Password"))
+o:depends({ protocol = "shadowsocks" })
-o = s:option(ListValue, _n("flow"), translate("flow"))
+o = s:option(ListValue, "flow", translate("flow"))
o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
-o:depends({ [_n("protocol")] = "vless" , [_n("tls")] = true })
+o:depends({ protocol = "vless" , tls = true })
-o = s:option(Flag, _n("tls"), translate("TLS"))
+o = s:option(Flag, "tls", translate("TLS"))
o.default = 0
o.validate = function(self, value, t)
if value then
- local reality = s.fields[_n("reality")] and s.fields[_n("reality")]:formvalue(t) or nil
+ local reality = s.fields["reality"] and s.fields["reality"]:formvalue(t) or nil
if reality and reality == "1" then return value end
if value == "1" then
- local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
- local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
+ local ca = s.fields["tls_certificateFile"] and s.fields["tls_certificateFile"]:formvalue(t) or ""
+ local key = s.fields["tls_keyFile"] and s.fields["tls_keyFile"]:formvalue(t) or ""
if ca == "" or key == "" then
return nil, translate("Public key and Private key path can not be empty!")
end
@@ -236,40 +231,40 @@ o.validate = function(self, value, t)
return value
end
end
-o:depends({ [_n("protocol")] = "http" })
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "trojan" })
-o:depends({ [_n("protocol")] = "anytls" })
+o:depends({ protocol = "http" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "trojan" })
+o:depends({ protocol = "anytls" })
-- https://github.com/SagerNet/sing-box/commit/d2a04c4e41e6cef0937331cb6d10211f431caaab
if singbox_tags:find("with_utls") then
-- [[ REALITY ]] --
- o = s:option(Flag, _n("reality"), translate("REALITY"))
+ o = s:option(Flag, "reality", translate("REALITY"))
o.default = 0
- o:depends({ [_n("protocol")] = "http", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true })
- o:depends({ [_n("protocol")] = "anytls", [_n("tls")] = true })
+ o:depends({ protocol = "http", tls = true })
+ o:depends({ protocol = "vmess", tls = true })
+ o:depends({ protocol = "vless", tls = true })
+ o:depends({ protocol = "trojan", tls = true })
+ o:depends({ protocol = "anytls", tls = true })
- o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
- o:depends({ [_n("reality")] = true })
+ o = s:option(Value, "reality_private_key", translate("Private Key"))
+ o:depends({ reality = true })
- o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
- o:depends({ [_n("reality")] = true })
+ o = s:option(Value, "reality_shortId", translate("Short Id"))
+ o:depends({ reality = true })
- o = s:option(Value, _n("reality_handshake_server"), translate("Handshake Server"))
+ o = s:option(Value, "reality_handshake_server", translate("Handshake Server"))
o.default = "google.com"
- o:depends({ [_n("reality")] = true })
+ o:depends({ reality = true })
- o = s:option(Value, _n("reality_handshake_server_port"), translate("Handshake Server Port"))
+ o = s:option(Value, "reality_handshake_server_port", translate("Handshake Server Port"))
o.datatype = "port"
o.default = "443"
- o:depends({ [_n("reality")] = true })
+ o:depends({ reality = true })
end
-o = s:option(ListValue, _n("alpn"), translate("ALPN"))
+o = s:option(ListValue, "alpn", translate("ALPN"))
o.default = "default"
o:value("default", translate("Default"))
o:value("h3")
@@ -278,22 +273,22 @@ o:value("h3,h2")
o:value("http/1.1")
o:value("h2,http/1.1")
o:value("h3,h2,http/1.1")
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "hysteria" })
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "hysteria" })
-- [[ TLS ]] --
-o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
+o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "naive" })
-o:depends({ [_n("protocol")] = "hysteria" })
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "naive" })
+o:depends({ protocol = "hysteria" })
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2" })
o.validate = function(self, value, t)
if value and value ~= "" then
- if not fs.access(value) then
+ if not api.fs.access(value) then
return nil, translate("Can't find this file!")
else
return value
@@ -302,17 +297,17 @@ o.validate = function(self, value, t)
return nil
end
-o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
+o = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
-o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "naive" })
-o:depends({ [_n("protocol")] = "hysteria" })
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2" })
+o:depends({ tls = true, reality = false })
+o:depends({ protocol = "naive" })
+o:depends({ protocol = "hysteria" })
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2" })
o.validate = function(self, value, t)
if value and value ~= "" then
- if not fs.access(value) then
+ if not api.fs.access(value) then
return nil, translate("Can't find this file!")
else
return value
@@ -321,19 +316,19 @@ o.validate = function(self, value, t)
return nil
end
-o = s:option(Flag, _n("ech"), translate("ECH"))
+o = s:option(Flag, "ech", translate("ECH"))
o.default = "0"
-o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
-o:depends({ [_n("protocol")] = "naive" })
-o:depends({ [_n("protocol")] = "hysteria" })
-o:depends({ [_n("protocol")] = "tuic" })
-o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
+o:depends({ tls = true, flow = "", reality = false })
+o:depends({ protocol = "naive" })
+o:depends({ protocol = "hysteria" })
+o:depends({ protocol = "tuic" })
+o:depends({ protocol = "hysteria2", hysteria2_realms = false })
-o = s:option(TextValue, _n("ech_key"), translate("ECH Key"))
+o = s:option(TextValue, "ech_key", translate("ECH Key"))
o.default = ""
o.rows = 5
o.wrap = "off"
-o:depends({ [_n("ech")] = true })
+o:depends({ ech = true })
o.validate = function(self, value)
value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n")
value = value:gsub("^%s*\n", "")
@@ -343,100 +338,100 @@ o.validate = function(self, value)
return value
end
-o = s:option(ListValue, _n("transport"), translate("Transport"))
+o = s:option(ListValue, "transport", translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
o:value("ws", "WebSocket")
o:value("httpupgrade", "HTTPUpgrade")
o:value("quic", "QUIC")
o:value("grpc", "gRPC")
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless" })
+o:depends({ protocol = "trojan" })
-- [[ HTTP ]]--
-o = s:option(DynamicList, _n("http_host"), translate("HTTP Host"))
-o:depends({ [_n("transport")] = "http" })
+o = s:option(DynamicList, "http_host", translate("HTTP Host"))
+o:depends({ transport = "http" })
-o = s:option(Value, _n("http_path"), translate("HTTP Path"))
-o:depends({ [_n("transport")] = "http" })
+o = s:option(Value, "http_path", translate("HTTP Path"))
+o:depends({ transport = "http" })
-- [[ WebSocket ]]--
-o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
-o:depends({ [_n("transport")] = "ws" })
+o = s:option(Value, "ws_host", translate("WebSocket Host"))
+o:depends({ transport = "ws" })
-o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
-o:depends({ [_n("transport")] = "ws" })
+o = s:option(Value, "ws_path", translate("WebSocket Path"))
+o:depends({ transport = "ws" })
-- [[ HTTPUpgrade ]]--
-o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
-o:depends({ [_n("transport")] = "httpupgrade" })
+o = s:option(Value, "httpupgrade_host", translate("HTTPUpgrade Host"))
+o:depends({ transport = "httpupgrade" })
-o = s:option(Value, _n("httpupgrade_path"), translate("HTTPUpgrade Path"))
-o:depends({ [_n("transport")] = "httpupgrade" })
+o = s:option(Value, "httpupgrade_path", translate("HTTPUpgrade Path"))
+o:depends({ transport = "httpupgrade" })
-- [[ gRPC ]]--
-o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
-o:depends({ [_n("transport")] = "grpc" })
+o = s:option(Value, "grpc_serviceName", "ServiceName")
+o:depends({ transport = "grpc" })
-- [[ Mux ]]--
-o = s:option(Flag, _n("mux"), translate("Mux"))
+o = s:option(Flag, "mux", translate("Mux"))
o.rmempty = false
-o:depends({ [_n("protocol")] = "vmess" })
-o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
-o:depends({ [_n("protocol")] = "shadowsocks" })
-o:depends({ [_n("protocol")] = "trojan" })
+o:depends({ protocol = "vmess" })
+o:depends({ protocol = "vless", flow = "" })
+o:depends({ protocol = "shadowsocks" })
+o:depends({ protocol = "trojan" })
-- [[ TCP Brutal ]]--
-o = s:option(Flag, _n("tcpbrutal"), translate("TCP Brutal"))
+o = s:option(Flag, "tcpbrutal", translate("TCP Brutal"))
o.default = 0
-o:depends({ [_n("mux")] = true })
+o:depends({ mux = true })
-o = s:option(Value, _n("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
+o = s:option(Value, "tcpbrutal_up_mbps", translate("Max upload Mbps"))
o.default = "10"
-o:depends({ [_n("tcpbrutal")] = true })
+o:depends({ tcpbrutal = true })
-o = s:option(Value, _n("tcpbrutal_down_mbps"), translate("Max download Mbps"))
+o = s:option(Value, "tcpbrutal_down_mbps", translate("Max download Mbps"))
o.default = "50"
-o:depends({ [_n("tcpbrutal")] = true })
+o:depends({ tcpbrutal = true })
if singbox_tags:find("with_wireguard") then
- o = s:option(Flag, _n("wireguard_system_interface"), translate("System interface"))
+ o = s:option(Flag, "wireguard_system_interface", translate("System interface"))
o.default = 0
- o:depends({ [_n("protocol")] = "wireguard" })
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_mtu"), "MTU")
+ o = s:option(Value, "wireguard_mtu", "MTU")
o.default = "1408"
- o:depends({ [_n("protocol")] = "wireguard" })
+ o:depends({ protocol = "wireguard" })
- o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
- o:depends({ [_n("protocol")] = "wireguard" })
+ o = s:option(DynamicList, "wireguard_local_address", translate("Local Address"))
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_private_key"), translate("Private Key"))
+ o = s:option(Value, "wireguard_private_key", translate("Private Key"))
o.datatype = "base64"
- o:depends({ [_n("protocol")] = "wireguard" })
+ o:depends({ protocol = "wireguard" })
- o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
+ o = s:option(Value, "wireguard_public_key", translate("Public Key"))
o.datatype = "base64"
- o:depends({ [_n("protocol")] = "wireguard" })
+ o:depends({ protocol = "wireguard" })
- o = s:option(DummyValue, _n("gen_wireguard_key"))
+ o = s:option(DummyValue, "gen_wireguard_key")
o.prefix = option_prefix
o.template = m:template_path("/server/server_wireguard")
- o:depends({ [_n("protocol")] = "wireguard" })
+ o:depends({ protocol = "wireguard" })
end
-o = s:option(Flag, _n("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
+o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
o.default = "0"
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
-o = s:option(Flag, _n("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
+o = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
o.default = "0"
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
@@ -449,7 +444,7 @@ for k, e in ipairs(api.get_valid_nodes()) do
end
end
-o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
+o = s:option(ListValue, "outbound_node", translate("outbound node"))
o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
@@ -460,37 +455,37 @@ for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
o.group[#o.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
end
-o:depends({ [_n("custom")] = false })
+o:depends({ custom = false })
-o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
-o:depends({ [_n("outbound_node")] = "_socks" })
-o:depends({ [_n("outbound_node")] = "_http" })
+o = s:option(Value, "outbound_node_address", translate("Address (Support Domain Name)"))
+o:depends({ outbound_node = "_socks" })
+o:depends({ outbound_node = "_http" })
-o = s:option(Value, _n("outbound_node_port"), translate("Port"))
+o = s:option(Value, "outbound_node_port", translate("Port"))
o.datatype = "port"
-o:depends({ [_n("outbound_node")] = "_socks" })
-o:depends({ [_n("outbound_node")] = "_http" })
+o:depends({ outbound_node = "_socks" })
+o:depends({ outbound_node = "_http" })
-o = s:option(Value, _n("outbound_node_username"), translate("Username"))
-o:depends({ [_n("outbound_node")] = "_socks" })
-o:depends({ [_n("outbound_node")] = "_http" })
+o = s:option(Value, "outbound_node_username", translate("Username"))
+o:depends({ outbound_node = "_socks" })
+o:depends({ outbound_node = "_http" })
-o = s:option(Value, _n("outbound_node_password"), translate("Password"))
+o = s:option(Value, "outbound_node_password", translate("Password"))
o.password = true
-o:depends({ [_n("outbound_node")] = "_socks" })
-o:depends({ [_n("outbound_node")] = "_http" })
+o:depends({ outbound_node = "_socks" })
+o:depends({ outbound_node = "_http" })
-o = s:option(Value, _n("outbound_node_iface"), translate("Interface"))
-o:depends({ [_n("outbound_node")] = "_iface" })
+o = s:option(Value, "outbound_node_iface", translate("Interface"))
+o:depends({ outbound_node = "_iface" })
local netdev_list = api.get_network_devices()
for _, d in ipairs(netdev_list) do
o:value(d.name, d.label)
end
-o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
+o = s:option(TextValue, "custom_config", translate("Custom Config") .. " (JSON)")
o.rows = 10
o.wrap = "off"
-o:depends({ [_n("custom")] = true })
+o:depends({ custom = true })
o.datatype = "json"
local o_validate = o.validate
o.validate = function(self, value)
@@ -508,16 +503,16 @@ o.custom_write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
-o = s:option(Flag, _n("log"), translate("Log"))
+o = s:option(Flag, "log", translate("Log"))
o.default = "1"
o.rmempty = false
-o = s:option(ListValue, _n("loglevel"), translate("Log Level"))
+o = s:option(ListValue, "loglevel", translate("Log Level"))
o.default = "info"
o:value("debug")
o:value("info")
o:value("warn")
o:value("error")
-o:depends({ [_n("log")] = true })
+o:depends({ log = true })
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua
index d94c237e..1c7e88c0 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua
@@ -1,24 +1,20 @@
-local m, s = ...
-
if not api.is_finded("ssserver") then
return
end
+-- [[ Shadowsocks Rust ]]
+local m, s1 = ...
local type_name = "SS-Rust"
--- [[ Shadowsocks Rust ]]
+s1.fields["type"]:value(type_name, translate("Shadowsocks Rust"))
-s.fields["type"]:value(type_name, translate("Shadowsocks Rust"))
-
-if s.val["type"] and s.val["type"] ~= type_name then
+if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
-local option_prefix = "ssrust_"
-
-local function _n(name)
- return option_prefix .. name
-end
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "ssrust_"
local ssrust_encrypt_method_list = {
"plain", "none",
@@ -26,35 +22,12 @@ local ssrust_encrypt_method_list = {
"2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha8-poly1305", "2022-blake3-chacha20-poly1305"
}
-o = s:option(Flag, _n("custom"), translate("Use Custom Config"))
+o = s:option(Flag, "custom", translate("Use Custom Config"))
-o = s:option(Value, _n("port"), translate("Listen Port"))
-o.datatype = "port"
-o:depends({ [_n("custom")] = false })
-
-o = s:option(ListValue, _n("user"), translate("User"))
-for i, v in ipairs(user_list) do
- o:value(v[".name"], v.username)
-end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
-for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
-o.datatype = "uinteger"
-o.default = 300
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
-o.default = "0"
-o:depends({ [_n("custom")] = false })
-
-o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
+o = s:option(TextValue, "custom_config", translate("Custom Config") .. " (JSON)")
o.rows = 10
o.wrap = "off"
-o:depends({ [_n("custom")] = true })
+o:depends({ custom = true })
o.datatype = "json"
local o_validate = o.validate
o.validate = function(self, value)
@@ -72,8 +45,31 @@ o.custom_write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
-o = s:option(Flag, _n("log"), translate("Log"))
+o = s:option(Value, "port", translate("Listen Port"))
+o.datatype = "port"
+o:depends({ custom = false })
+
+o = s:option(ListValue, "user", translate("User"))
+for i, v in ipairs(user_list) do
+ o:value(v[".name"], v.username)
+end
+o:depends({ custom = false })
+
+o = s:option(ListValue, "method", translate("Encrypt Method"))
+for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end
+o:depends({ custom = false })
+
+o = s:option(Value, "timeout", translate("Connection Timeout"))
+o.datatype = "uinteger"
+o.default = 300
+o:depends({ custom = false })
+
+o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"))
+o.default = "0"
+o:depends({ custom = false })
+
+o = s:option(Flag, "log", translate("Log"))
o.default = "1"
o.rmempty = false
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua
index d1db102f..32494fb7 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua
@@ -1,24 +1,20 @@
-local m, s = ...
-
if not api.is_finded("ssr-server") then
return
end
+-- [[ ShadowsocksR ]]
+local m, s1 = ...
local type_name = "SSR"
--- [[ ShadowsocksR ]]
+s1.fields["type"]:value(type_name, translate("ShadowsocksR"))
-s.fields["type"]:value(type_name, translate("ShadowsocksR"))
-
-if s.val["type"] and s.val["type"] ~= type_name then
+if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
-local option_prefix = "ssr_"
-
-local function _n(name)
- return option_prefix .. name
-end
+local s = NamedSection(m, arg[1], "server")
+s.type_name = type_name
+s.option_prefix = "ssr_"
local ssr_encrypt_method_list = {
"none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb",
@@ -39,49 +35,12 @@ local ssr_obfs_list = {
"tls1.0_session_auth", "tls1.2_ticket_auth"
}
-o = s:option(Flag, _n("custom"), translate("Use Custom Config"))
+o = s:option(Flag, "custom", translate("Use Custom Config"))
-o = s:option(Value, _n("port"), translate("Listen Port"))
-o.datatype = "port"
-o:depends({ [_n("custom")] = false })
-
-o = s:option(ListValue, _n("user"), translate("User"))
-for i, v in ipairs(user_list) do
- o:value(v[".name"], v.username)
-end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
-for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(ListValue, _n("protocol"), translate("Protocol"))
-for a, t in ipairs(ssr_protocol_list) do o:value(t) end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("protocol_param"), translate("Protocol_param"))
-o:depends({ [_n("custom")] = false })
-
-o = s:option(ListValue, _n("obfs"), translate("Obfs"))
-for a, t in ipairs(ssr_obfs_list) do o:value(t) end
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("obfs_param"), translate("Obfs_param"))
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
-o.datatype = "uinteger"
-o.default = 300
-o:depends({ [_n("custom")] = false })
-
-o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
-o.default = "0"
-o:depends({ [_n("custom")] = false })
-
-o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
+o = s:option(TextValue, "custom_config", translate("Custom Config") .. " (JSON)")
o.rows = 10
o.wrap = "off"
-o:depends({ [_n("custom")] = true })
+o:depends({ custom = true })
o.datatype = "json"
local o_validate = o.validate
o.validate = function(self, value)
@@ -99,12 +58,49 @@ o.custom_write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
-o = s:option(Flag, _n("udp_forward"), translate("UDP Forward"))
+o = s:option(Value, "port", translate("Listen Port"))
+o.datatype = "port"
+o:depends({ custom = false })
+
+o = s:option(ListValue, "user", translate("User"))
+for i, v in ipairs(user_list) do
+ o:value(v[".name"], v.username)
+end
+o:depends({ custom = false })
+
+o = s:option(ListValue, "method", translate("Encrypt Method"))
+for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end
+o:depends({ custom = false })
+
+o = s:option(ListValue, "protocol", translate("Protocol"))
+for a, t in ipairs(ssr_protocol_list) do o:value(t) end
+o:depends({ custom = false })
+
+o = s:option(Value, "protocol_param", translate("Protocol_param"))
+o:depends({ custom = false })
+
+o = s:option(ListValue, "obfs", translate("Obfs"))
+for a, t in ipairs(ssr_obfs_list) do o:value(t) end
+o:depends({ custom = false })
+
+o = s:option(Value, "obfs_param", translate("Obfs_param"))
+o:depends({ custom = false })
+
+o = s:option(Value, "timeout", translate("Connection Timeout"))
+o.datatype = "uinteger"
+o.default = 300
+o:depends({ custom = false })
+
+o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"))
+o.default = "0"
+o:depends({ custom = false })
+
+o = s:option(Flag, "udp_forward", translate("UDP Forward"))
o.default = "1"
o.rmempty = false
-o = s:option(Flag, _n("log"), translate("Log"))
+o = s:option(Flag, "log", translate("Log"))
o.default = "1"
o.rmempty = false
-api.luci_types(arg[1], m, s, type_name, option_prefix)
+api.luci_types(s1, s)
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua
index f92159d5..533824f6 100644
--- a/luci-app-passwall2/luasrc/passwall2/api.lua
+++ b/luci-app-passwall2/luasrc/passwall2/api.lua
@@ -1,3 +1,6 @@
+-- Copyright (C) 2022-2025 xiaorouji
+-- Copyright (C) 2026 Openwrt-Passwall Organization
+
module("luci.passwall2.api", package.seeall)
appname = "passwall2"
c_config = "passwall2"
@@ -17,10 +20,11 @@ command_timeout = 300
OPENWRT_ARCH = nil
DISTRIB_ARCH = nil
-LOCK_PREFIX = "/tmp/lock/passwall2"
-LOG_FILE = "/tmp/log/passwall2.log"
-TMP_PATH = "/tmp/etc/passwall2"
+LOCK_PREFIX = "/tmp/lock/" .. c_config
+LOG_FILE = "/tmp/log/" .. c_config .. ".log"
+TMP_PATH = "/tmp/etc/" .. c_config
CACHE_PATH = TMP_PATH .. "_tmp"
+S_TMP_PATH = "/tmp/etc/" .. s_config
TMP_IFACE_PATH = TMP_PATH .. "/iface"
local lang = uci:get("luci", "main", "lang") or "auto"
@@ -814,16 +818,16 @@ function clone(org)
end
local function get_bin_version_cache(file, cmd)
- sys.call("mkdir -p /tmp/etc/passwall2_tmp")
+ sys.call("mkdir -p " .. CACHE_PATH)
if fs.access(file) then
chmod_755(file)
local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')")
- if fs.access("/tmp/etc/passwall2_tmp/" .. md5) then
- return sys.exec("echo -n $(cat /tmp/etc/passwall2_tmp/%s)" % md5)
+ if fs.access(CACHE_PATH .. "/" .. md5) then
+ return sys.exec("echo -n $(cat %s)" % { CACHE_PATH .. "/" .. md5 })
else
local version = sys.exec(string.format("echo -n $(%s %s)", file, cmd))
if version and version ~= "" then
- sys.call("echo '" .. version .. "' > " .. "/tmp/etc/passwall2_tmp/" .. md5)
+ sys.call("echo '%s' > %s" % { version, CACHE_PATH .. "/" .. md5})
return version
end
end
@@ -1415,12 +1419,24 @@ function set_default_cbi()
if true then
--Map
local Map = cbi.Map
- local original_init = Map.__init__
+ local default_init = Map.__init__
function Map.__init__(self, config, ...)
if not config then config = c_config end
- original_init(self, config, ...)
+ default_init(self, config, ...)
self.api = require "luci.passwall2.api"
end
+ if is_js_luci() == true then
+ local default_parse = Map.parse
+ function Map.parse(self, ...)
+ apply_redirect(self)
+ local old = self.on_after_save
+ self.on_after_save = function(self)
+ if old then old(self) end
+ self:set("@global[0]", "timestamp", os.time())
+ end
+ return default_parse(self, ...)
+ end
+ end
function Map.foreach(self, stype, func)
self.uci:foreach(self.config, stype, func)
end
@@ -1459,25 +1475,6 @@ function set_default_cbi()
sh_uci_set(c_config, "@global[0]", "auto_lang", lang, true)
end
end
- if is_js_luci() == true then
- local hide_popup_box = nil
- if hide_popup_box == true then
- Map.apply_on_parse = false
- Map.on_after_apply = function(self)
- if self.redirect then
- os.execute("sleep 1")
- luci.http.redirect(self.redirect)
- end
- end
- else
- apply_redirect(Map)
- local old = Map.on_after_save
- Map.on_after_save = function(self)
- if old then old(self) end
- self:set("@global[0]", "timestamp", os.time())
- end
- end
- end
end
if true then
--AbstractSection
@@ -1498,9 +1495,9 @@ function set_default_cbi()
if true then
--TextValue
local TextValue = cbi.TextValue
- local original_init = TextValue.__init__
+ local default_init = TextValue.__init__
function TextValue.__init__(self, ...)
- original_init(self, ...)
+ default_init(self, ...)
self.template = appname .. "/cbi/tvalue"
end
end
@@ -1543,102 +1540,112 @@ function return_map(map)
return map
end
-function luci_types(id, m, s, type_name, option_prefix)
+function luci_types(s, s2)
local cbi = require "luci.cbi"
+ local m = s.map
+ local id = s2.section
+ local type_name = s2.type_name
+ local option_prefix = s2.option_prefix
local fv_type
local field_type = s.fields["type"]
if field_type then
fv_type = field_type:formvalue(id)
end
- local rewrite_option_table = {}
- for key, value in pairs(s.fields) do
- if key:find(option_prefix) == 1 then
- if not s.fields[key].not_rewrite then
- if s.fields[key].rewrite_option then
- if not rewrite_option_table[s.fields[key].rewrite_option] then
- rewrite_option_table[s.fields[key].rewrite_option] = 1
+ for i, v in ipairs(s2.children) do
+ local o = s2.children[i]
+ o.config_option = o.option
+ o.option = option_prefix .. o.option
+ if not o.not_rewrite then
+ o.cfgvalue = function(self, section)
+ -- Add a custom `custom_cfgvalue` attribute. If a custom `custom_cfgvalue` function exists, the custom `cfgvalue` logic will be used.
+ if self.custom_cfgvalue then
+ return self:custom_cfgvalue(section)
+ else
+ if self.rewrite_option then
+ return m:get(section, self.rewrite_option)
else
- rewrite_option_table[s.fields[key].rewrite_option] = rewrite_option_table[s.fields[key].rewrite_option] + 1
+ return m:get(section, self.config_option)
end
end
-
- s.fields[key].cfgvalue = function(self, section)
- -- Add a custom `custom_cfgvalue` attribute. If a custom `custom_cfgvalue` function exists, the custom `cfgvalue` logic will be used.
- if self.custom_cfgvalue then
- return self:custom_cfgvalue(section)
+ end
+ o.write = function(self, section, value)
+ if s.fields["type"]:formvalue(id) == type_name then
+ -- Add a custom `custom_write` attribute; if a custom `custom_write` function exists, then use the custom write logic.
+ if self.custom_write then
+ self:custom_write(section, value)
+ else
+ local new_val = value
+ if util.instanceof(self, cbi.DynamicList) then
+ local new_t = {}
+ if type(value) == "table" then
+ new_t = table_remove_duplicates(value)
+ else
+ new_t = { value }
+ end
+ if self.cast == "string" then
+ new_val = table.concat(new_t, " ")
+ else
+ new_val = new_t
+ end
+ end
+ if self.rewrite_option then
+ m:set(section, self.rewrite_option, new_val)
+ else
+ m:set(section, self.config_option, new_val)
+ end
+ end
+ end
+ end
+ o.remove = function(self, section)
+ if s.fields["type"]:formvalue(id) == type_name then
+ -- Add a custom `custom_remove` attribute; if a custom `custom_remove` function exists, use the custom remove logic.
+ if self.custom_remove then
+ self:custom_remove(section)
else
if self.rewrite_option then
- return m:get(section, self.rewrite_option)
+ m:del(section, self.rewrite_option)
else
- if self.option:find(option_prefix) == 1 then
- return m:get(section, self.option:sub(1 + #option_prefix))
- end
+ m:del(section, self.config_option)
end
end
end
- s.fields[key].write = function(self, section, value)
- if s.fields["type"]:formvalue(id) == type_name then
- -- Add a custom `custom_write` attribute; if a custom `custom_write` function exists, then use the custom write logic.
- if self.custom_write then
- self:custom_write(section, value)
- else
- local new_val = value
- if util.instanceof(self, cbi.DynamicList) then
- local new_t = {}
- if type(value) == "table" then
- new_t = table_remove_duplicates(value)
- else
- new_t = { value }
- end
- if self.cast == "string" then
- new_val = table.concat(new_t, " ")
- else
- new_val = new_t
- end
- end
- if self.rewrite_option then
- m:set(section, self.rewrite_option, new_val)
- else
- if self.option:find(option_prefix) == 1 then
- m:set(section, self.option:sub(1 + #option_prefix), new_val)
- end
- end
- end
- end
- end
- s.fields[key].remove = function(self, section)
- if s.fields["type"]:formvalue(id) == type_name then
- -- Add a custom `custom_remove` attribute; if a custom `custom_remove` function exists, use the custom remove logic.
- if self.custom_remove then
- self:custom_remove(section)
- else
- if self.rewrite_option and rewrite_option_table[self.rewrite_option] == 1 then
- m:del(section, self.rewrite_option)
- else
- if self.option:find(option_prefix) == 1 then
- m:del(section, self.option:sub(1 + #option_prefix))
- end
- end
- end
- end
- end
- end
-
- local deps = s.fields[key].deps
- if #deps > 0 then
- for index, value in ipairs(deps) do
- deps[index]["type"] = type_name
- end
- else
- s.fields[key]:depends({ type = type_name })
- end
-
- if fv_type and fv_type ~= type_name then
- s.fields[key].rmempty = true
end
end
+
+ local deps = o.deps
+ if #deps > 0 then
+ local function process_deps(dep)
+ local rewrite_deps = {}
+ for k, v in pairs(dep) do
+ if k:find("!") then
+ rewrite_deps[k] = v
+ else
+ rewrite_deps[option_prefix .. k] = v
+ end
+ end
+ if not rewrite_deps['!reverse'] then
+ rewrite_deps["type"] = type_name
+ end
+ return rewrite_deps
+ end
+ for index, value in ipairs(deps) do
+ local rewrite_deps = process_deps(value)
+ if rewrite_deps then
+ deps[index] = rewrite_deps
+ end
+ end
+ else
+ o:depends({ type = type_name })
+ end
+
+ if fv_type and fv_type ~= type_name then
+ o.rmempty = true
+ end
+
+ s:append(o)
end
end
+
function format_go_time(input, default)
input = input and trim(input)
local N = 0
diff --git a/luci-app-passwall2/luasrc/passwall2/server_app.lua b/luci-app-passwall2/luasrc/passwall2/server_app.lua
index 1135f6b8..783ee4f9 100644
--- a/luci-app-passwall2/luasrc/passwall2/server_app.lua
+++ b/luci-app-passwall2/luasrc/passwall2/server_app.lua
@@ -7,7 +7,7 @@ local uci = api.uci
local jsonc = api.jsonc
local CONFIG = api.s_config
-local CONFIG_PATH = "/tmp/etc/" .. CONFIG
+local CONFIG_PATH = api.S_TMP_PATH
local NFT_INCLUDE_FILE = CONFIG_PATH .. "/" .. CONFIG .. ".nft"
local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log"
local TMP_BIN_PATH = CONFIG_PATH .. "/bin"
@@ -53,7 +53,7 @@ local function ln_run(s, d, command, output)
end
local function gen_include()
- cmd(string.format("echo '#!/bin/sh' > /tmp/etc/%s.include", CONFIG))
+ cmd(string.format("echo '#!/bin/sh' > %s.include", CONFIG_PATH))
local function extract_rules(n, a)
local _ipt = ipt_bin
if n == "6" then
@@ -64,7 +64,7 @@ local function gen_include()
result = result .. "COMMIT"
return result
end
- local f, err = io.open("/tmp/etc/" .. CONFIG .. ".include", "a")
+ local f, err = io.open(CONFIG_PATH .. ".include", "a")
if f and err == nil then
if nft_flag == "0" then
f:write(ipt_bin .. '-save -c | grep -v "PSW2-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n")
@@ -232,7 +232,7 @@ local function stop()
cmd("nft flush chain inet fw4 PSW2-SERVER 2>/dev/null")
cmd("nft delete chain inet fw4 PSW2-SERVER 2>/dev/null")
end
- cmd(string.format("rm -rf %s %s /tmp/etc/%s.include", CONFIG_PATH, LOG_APP_FILE, CONFIG))
+ cmd(string.format("rm -rf %s %s %s", CONFIG_PATH, LOG_APP_FILE, CONFIG_PATH .. ".include"))
end
if action then
diff --git a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua
index 9811daab..2d557bcd 100644
--- a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua
+++ b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua
@@ -18,8 +18,8 @@ function gen_config_server(node)
end
local config = {
listen = (function()
- if node.hysteria2_realms and node.hysteria2_realm_url then
- local url = node.hysteria2_realm_url:gsub("/+$", "")
+ if node.realms and node.realm_url then
+ local url = node.realm_url:gsub("/+$", "")
if node.port then
url = url .. (url:find("?") and "&lport=" or "?lport=") .. node.port
end
@@ -31,30 +31,30 @@ function gen_config_server(node)
cert = node.tls_certificateFile,
key = node.tls_keyFile,
},
- obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
- type = node.hysteria2_obfs_type,
- [node.hysteria2_obfs_type] = {
- password = node.hysteria2_obfs_password
+ obfs = (node.obfs_type and node.obfs_password) and {
+ type = node.obfs_type,
+ [node.obfs_type] = {
+ password = node.obfs_password
}
} or nil,
auth = users and {
type = "userpass",
userpass = users
} or nil,
- bandwidth = (node.hysteria2_up_mbps or node.hysteria2_down_mbps) and {
- up = node.hysteria2_up_mbps and node.hysteria2_up_mbps .. " mbps" or nil,
- down = node.hysteria2_down_mbps and node.hysteria2_down_mbps .. " mbps" or nil
+ bandwidth = (node.up_mbps or node.down_mbps) and {
+ up = node.up_mbps and node.up_mbps .. " mbps" or nil,
+ down = node.down_mbps and node.down_mbps .. " mbps" or nil
} or nil,
- ignoreClientBandwidth = (node.hysteria2_ignoreClientBandwidth == "1") and true or false,
- disableUDP = (node.hysteria2_udp == "0") and true or false,
- realm = (node.hysteria2_realms and node.hysteria2_realm_stun) and {
- stunServers = node.hysteria2_realm_stun
+ ignoreClientBandwidth = (node.ignoreClientBandwidth == "1") and true or false,
+ disableUDP = (node.udp == "0") and true or false,
+ realm = (node.realms and node.realm_stun) and {
+ stunServers = node.realm_stun
} or nil
}
if config.obfs and config.obfs.gecko then
- local min = tonumber(node.hysteria2_obfs_MinPacketSize) or 512
- local max = tonumber(node.hysteria2_obfs_MaxPacketSize) or 1200
+ local min = tonumber(node.obfs_MinPacketSize) or 512
+ local max = tonumber(node.obfs_MaxPacketSize) or 1200
if min <= 0 or min > max or max > 2048 then
min = 512
max = 1200
diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
index 97ce6b2e..a5e81a55 100644
--- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
+++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
@@ -402,7 +402,7 @@ function gen_outbound(flag, node, tag, proxy_table)
if node.protocol == "shadowsocks" then
protocol_table = {
- method = node.method or nil,
+ method = node.ss_method or nil,
password = node.password or "",
plugin = (node.plugin_enabled and node.plugin) or nil,
plugin_opts = (node.plugin_enabled and node.plugin_opts) or nil,
@@ -416,7 +416,7 @@ function gen_outbound(flag, node, tag, proxy_table)
if node.protocol == "shadowsocksr" then
protocol_table = {
- method = node.method or nil,
+ method = node.ssr_method or nil,
password = node.password or "",
obfs = node.ssr_obfs,
obfs_param = node.ssr_obfs_param,
@@ -865,7 +865,7 @@ function gen_config_server(node)
if node.protocol == "shadowsocks" then
protocol_table = {
- method = node.method,
+ method = node.ss_method,
password = node.ss_password,
users = users,
multiplex = mux,
diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua
index ebe68a89..6b496f0e 100644
--- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua
+++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua
@@ -388,8 +388,8 @@ function gen_outbound(flag, node, tag, proxy_table)
user = (node.protocol == "socks" or node.protocol == "http") and node.username or nil,
pass = (node.protocol == "socks" or node.protocol == "http") and node.password or nil,
password = (node.protocol == "shadowsocks" or node.protocol == "trojan") and node.password or nil,
- method = (node.protocol == "shadowsocks") and ((node.method == "chacha20-ietf-poly1305" and "chacha20-poly1305") or
- (node.method == "xchacha20-ietf-poly1305" and "xchacha20-poly1305") or (node.method ~= "" and node.method) or nil) or nil,
+ method = (node.protocol == "shadowsocks") and ((node.ss_method == "chacha20-ietf-poly1305" and "chacha20-poly1305") or
+ (node.ss_method == "xchacha20-ietf-poly1305" and "xchacha20-poly1305") or (node.ss_method ~= "" and node.ss_method) or nil) or nil,
secretKey = (node.protocol == "wireguard") and node.wireguard_secret_key or nil,
peers = (node.protocol == "wireguard") and {
{
@@ -523,6 +523,12 @@ function gen_config_server(node)
u.email = user.username
u.auth = user.password
end
+ if node.protocol == "wireguard" then
+ u.publicKey = user.wireguard_public_key
+ u.preSharedKey = user.wireguard_pre_shared_key
+ u.keepAlive = 0
+ u.allowedIPs = user.allowed_ips
+ end
users[#users + 1] = u
end
end
@@ -553,7 +559,7 @@ function gen_config_server(node)
node.tcp_guise = "none"
elseif node.protocol == "shadowsocks" then
settings = {
- method = node.method,
+ method = node.ss_method,
password = node.ss_password,
users = users,
network = node.ss_network or "tcp,udp"
@@ -575,6 +581,14 @@ function gen_config_server(node)
address = node.d_address,
port = tonumber(node.d_port)
}
+ elseif node.protocol == "wireguard" then
+ settings = {
+ secretKey = node.wireguard_private_key,
+ --address = node.wireguard_local_address,
+ --noKernelTun = node.wireguard_system_interface ~= "1" and true or false,
+ mtu = tonumber(node.wireguard_mtu or 1420),
+ peers = users
+ }
end
if node.fallback and node.fallback == "1" then
diff --git a/luci-app-passwall2/root/usr/share/passwall2/app.sh b/luci-app-passwall2/root/usr/share/passwall2/app.sh
index dab2fc00..49ae8c66 100755
--- a/luci-app-passwall2/root/usr/share/passwall2/app.sh
+++ b/luci-app-passwall2/root/usr/share/passwall2/app.sh
@@ -1120,7 +1120,7 @@ acl_app() {
}
start() {
- busybox pgrep -f /tmp/etc/passwall2/bin > /dev/null 2>&1 && {
+ busybox pgrep -f ${TMP_PATH}/bin > /dev/null 2>&1 && {
logger -t PW2-RESTART "Upgrade or overload residue is detected, and the subprocess is being called to perform complete cleaning..."
(stop)
sleep 2
diff --git a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh
index db9594fc..c9bcb2e9 100755
--- a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh
+++ b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh
@@ -81,10 +81,10 @@ test_node() {
local curlx="socks5h://127.0.0.1:${_tmp_port}"
local _proxy_status=$(test_url "${probe_url}" ${retry_num} ${connect_timeout} "-x $curlx" 1)
# Kill the SS plugin process
- local pid_file="/tmp/etc/${CONFIG}/test_node_${node_id}_plugin.pid"
+ local pid_file="${TMP_PATH}/test_node_${node_id}_plugin.pid"
[ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1
busybox pgrep -af "test_node_${node_id}" | awk '! /socks_auto_switch\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
- rm -rf /tmp/etc/${CONFIG}/test_node_${node_id}*.*
+ rm -rf ${TMP_PATH}/test_node_${node_id}*.*
if [ "${_proxy_status}" -eq 200 ]; then
return 0
fi
diff --git a/luci-app-passwall2/root/usr/share/passwall2/test.sh b/luci-app-passwall2/root/usr/share/passwall2/test.sh
index cd1084e9..844b42f1 100755
--- a/luci-app-passwall2/root/usr/share/passwall2/test.sh
+++ b/luci-app-passwall2/root/usr/share/passwall2/test.sh
@@ -53,10 +53,10 @@ url_test_node() {
local probeUrl=$(config_t_get global_other url_test_url https://www.google.com/generate_204)
result=$(curl --connect-timeout 3 --max-time 5 -o /dev/null -I -skL -w "%{http_code}:%{time_pretransfer}" -x ${curlx} "${probeUrl}")
# End the SS plugin process
- local pid_file="/tmp/etc/${CONFIG}/url_test_${node_id}_plugin.pid"
+ local pid_file="${TMP_PATH}/url_test_${node_id}_plugin.pid"
[ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1
busybox pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
- rm -rf /tmp/etc/${CONFIG}/*url_test_${node_id}*.*
+ rm -rf ${TMP_PATH}/*url_test_${node_id}*.*
}
echo $result
}