From a459a74f198ff996cf850e232f332768b70cf1ef Mon Sep 17 00:00:00 2001 From: action Date: Sat, 15 Aug 2026 20:26:22 +0800 Subject: [PATCH] update 2026-08-15 20:26:22 --- dae/Makefile | 2 +- luci-app-amlogic/Makefile | 2 +- luci-app-amlogic/root/usr/sbin/openwrt-kernel | 8 +- .../root/usr/sbin/openwrt-update-rockchip | 8 + luci-app-dnsproxy/README.md | 9 + .../luci-static/resources/view/dnsproxy.js | 210 ++++- luci-app-dnsproxy/po/templates/dnsproxy.pot | 224 ++++-- .../99-luci-app-dnsproxy-defaults | 58 ++ .../luasrc/controller/passwall2.lua | 11 +- .../model/cbi/passwall2/client/acl_config.lua | 3 +- .../cbi/passwall2/client/node_config.lua | 9 +- .../cbi/passwall2/client/socks_config.lua | 17 +- .../cbi/passwall2/client/type/hysteria2.lua | 106 +-- .../model/cbi/passwall2/client/type/naive.lua | 30 +- .../model/cbi/passwall2/client/type/ray.lua | 555 +++++++------- .../cbi/passwall2/client/type/sing-box.lua | 716 +++++++++--------- .../cbi/passwall2/client/type/ss-rust.lua | 42 +- .../model/cbi/passwall2/client/type/ssr.lua | 40 +- .../cbi/passwall2/server/server_config.lua | 2 +- .../cbi/passwall2/server/type/hysteria2.lua | 225 +++--- .../model/cbi/passwall2/server/type/ray.lua | 440 ++++++----- .../cbi/passwall2/server/type/sing-box.lua | 407 +++++----- .../cbi/passwall2/server/type/ss-rust.lua | 74 +- .../model/cbi/passwall2/server/type/ssr.lua | 104 ++- luci-app-passwall2/luasrc/passwall2/api.lua | 221 +++--- .../luasrc/passwall2/server_app.lua | 8 +- .../luasrc/passwall2/util_hysteria2.lua | 30 +- .../luasrc/passwall2/util_sing-box.lua | 6 +- .../luasrc/passwall2/util_xray.lua | 20 +- .../root/usr/share/passwall2/app.sh | 2 +- .../usr/share/passwall2/socks_auto_switch.sh | 4 +- .../root/usr/share/passwall2/test.sh | 4 +- 32 files changed, 1991 insertions(+), 1606 deletions(-) create mode 100755 luci-app-dnsproxy/root/etc/uci-defaults/99-luci-app-dnsproxy-defaults 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 }