diff --git a/haproxy/Makefile b/haproxy/Makefile deleted file mode 100644 index 7b89e548..00000000 --- a/haproxy/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -# -# Copyright (C) 2010-2016 OpenWrt.org -# Copyright (C) 2009-2016 Thomas Heil -# Copyright (C) 2018 Christian Lachner -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=haproxy -PKG_VERSION:=3.2.19 -PKG_RELEASE:=1 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://www.haproxy.org/download/3.2/src -PKG_HASH:=skip - -PKG_MAINTAINER:=Thomas Heil , \ - Christian Lachner -PKG_LICENSE:=GPL-2.0-only -PKG_LICENSE_FILES:=LICENSE -PKG_CPE_ID:=cpe:/a:haproxy:haproxy - -include $(INCLUDE_DIR)/package.mk - -define Package/haproxy/Default - SUBMENU:=Web Servers/Proxies - SECTION:=net - CATEGORY:=Network - TITLE:=TCP/HTTP Load Balancer - URL:=https://www.haproxy.org/ - DEPENDS:= +USE_GLIBC:libcrypt-compat +libpcre2 +libltdl +zlib +libpthread +liblua5.4 +libatomic -endef - -define Package/haproxy/Default/description - Open source Reliable, High Performance TCP/HTTP Load Balancer. -endef - -define Package/haproxy - $(call Package/haproxy/Default) - TITLE+=with SSL support - DEPENDS+= +libopenssl +libncurses +libreadline - VARIANT:=ssl -endef - -define Package/haproxy/description -$(call Package/haproxy/Default/description) - This package is built with SSL and LUA support. -endef - -define Package/haproxy-nossl - $(call Package/haproxy/Default) - TITLE+=without SSL support - VARIANT:=nossl - CONFLICTS:=haproxy -endef - -define Package/haproxy-nossl/description - $(call Package/haproxy/Default/description) - This package is built without SSL support. -endef - -TARGET=linux-musl -ENABLE_LUA:=y - -ifeq ($(CONFIG_USE_GLIBC),y) - TARGET=linux-glibc -endif - -ifeq ($(BUILD_VARIANT),ssl) - ADDON+=USE_OPENSSL=1 - ADDON+=ADDLIB="-lcrypto -lm" - ADDON+=USE_QUIC=1 -endif - -define Build/Compile - $(MAKE) TARGET=$(TARGET) -C $(PKG_BUILD_DIR) \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - CC="$(TARGET_CC)" \ - PCREDIR="$(STAGING_DIR)/usr/" \ - USE_LUA=1 LUA_LIB_NAME="lua5.4" LUA_INC="$(STAGING_DIR)/usr/include/lua5.4" LUA_LIB="$(STAGING_DIR)/usr/lib" \ - USE_ZLIB=1 USE_PCRE2=1 USE_PCRE2_JIT=1 USE_LIBATOMIC=1 USE_PROMEX=1 \ - VERSION="$(PKG_VERSION)" SUBVERS="-$(PKG_RELEASE)" \ - VERDATE="$(shell date -d @$(SOURCE_DATE_EPOCH) '+%Y/%m/%d')" IGNOREGIT=1 \ - $(ADDON) \ - CFLAGS="$(TARGET_CFLAGS) -fno-strict-aliasing -Wdeclaration-after-statement -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wno-cast-function-type -Wno-address-of-packed-member -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference -fwrapv -fasynchronous-unwind-tables -Wno-null-dereference" \ - LD="$(TARGET_CC)" \ - LDFLAGS="$(TARGET_LDFLAGS)" - - $(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - LD="$(TARGET_CC)" \ - LDFLAGS="$(TARGET_LDFLAGS)" \ - $(MAKE_FLAGS) \ - install - - $(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - CC="$(TARGET_CC)" \ - CFLAGS="$(TARGET_CFLAGS) -Wno-address-of-packed-member" \ - LDFLAGS="$(TARGET_LDFLAGS)" \ - admin/halog/halog -endef - -define Package/haproxy/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/haproxy $(1)/usr/sbin/ -endef - -Package/haproxy-nossl/install = $(Package/haproxy/install) - -define Package/halog - $(call Package/haproxy) - TITLE+=halog - DEPENDS:=haproxy -endef - -define Package/halog/description - HAProxy Log Analyzer -endef - -define Package/halog/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/admin/halog/halog $(1)/usr/bin/ -endef - -$(eval $(call BuildPackage,haproxy)) -$(eval $(call BuildPackage,halog)) -$(eval $(call BuildPackage,haproxy-nossl)) diff --git a/luci-app-amlogic/Makefile b/luci-app-amlogic/Makefile index f0ce95f9..c87eb6ee 100644 --- a/luci-app-amlogic/Makefile +++ b/luci-app-amlogic/Makefile @@ -16,8 +16,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-amlogic -PKG_VERSION:=3.1.313 -PKG_RELEASE:=11 +PKG_VERSION:=3.1.315 +PKG_RELEASE:=12 PKG_LICENSE:=GPL-2.0 License PKG_MAINTAINER:=ophub diff --git a/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js b/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js index 61ad0634..06ecdd41 100644 --- a/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js +++ b/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js @@ -162,6 +162,7 @@ const inbound_type = [ ['anytls', _('AnyTLS') + ' - ' + _('TCP')], ['tuic', _('TUIC') + ' - ' + _('UDP')], ['hysteria2', _('Hysteria2') + ' - ' + _('UDP')], + ['hysteria2-realm', _('Hysteria2 Realm') + ' - ' + _('TCP/UDP')], ['trusttunnel', _('TrustTunnel') + ' - ' + _('TCP/UDP')], ['tunnel', _('Tunnel') + ' - ' + _('TCP/UDP')] ]; diff --git a/luci-app-fchomo/htdocs/luci-static/resources/fchomo/listeners.js b/luci-app-fchomo/htdocs/luci-static/resources/fchomo/listeners.js index 2a2673f3..a2db97bc 100644 --- a/luci-app-fchomo/htdocs/luci-static/resources/fchomo/listeners.js +++ b/luci-app-fchomo/htdocs/luci-static/resources/fchomo/listeners.js @@ -118,6 +118,7 @@ function renderListeners(s, uciconfig, isClient) { s.tab('field_general', _('General fields')); s.tab('field_vless_encryption', _('Vless Encryption fields')); + s.tab('field_hysteria2_realm', _('Hysteria2 Realm fields')); s.tab('field_tls', _('TLS fields')); s.tab('field_transport', _('Transport fields')); s.tab('field_multiplex', _('Multiplex fields')); @@ -209,6 +210,36 @@ function renderListeners(s, uciconfig, isClient) { o.depends('type', 'hysteria2'); o.modalonly = true; + /* Hysteria2 Realmserver fields */ + o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_token', _('Pre-shared key')); + o.placeholder = 'public'; + o.rmempty = false; + o.depends('type', 'hysteria2-realm'); + o.modalonly = true; + + o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_max_realms', _('Max realms')); + o.datatype = 'uinteger'; + o.placeholder = '65536'; + o.depends('type', 'hysteria2-realm'); + o.modalonly = true; + + o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_max_realms_per_ip', _('Max realms per client IP')); + o.datatype = 'uinteger'; + o.placeholder = '4'; + o.depends('type', 'hysteria2-realm'); + o.modalonly = true; + + o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_trusted_proxy_header', _('Trusted proxy header'), + _('Header to read real client IP from (e.g. X-Forwarded-For)')); + o.depends('type', 'hysteria2-realm'); + o.modalonly = true; + + o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_realm_name_pattern', _('Realm name pattern')); + o.default = '^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$'; + o.rmempty = false; + o.depends('type', 'hysteria2-realm'); + o.modalonly = true; + /* Shadowsocks fields */ o = s.taboption('field_general', form.ListValue, 'shadowsocks_chipher', _('Chipher')); o.default = hm.shadowsocks_cipher_methods[1][0]; @@ -498,11 +529,18 @@ function renderListeners(s, uciconfig, isClient) { /* Plugin fields */ o = s.taboption('field_general', form.ListValue, 'plugin', _('Plugin')); o.value('', _('none')); + o.value('obfs', _('obfs-simple')); o.value('shadow-tls', _('shadow-tls')); //o.value('kcp-tun', _('kcp-tun')); o.depends('type', 'shadowsocks'); o.modalonly = true; + o = s.taboption('field_general', form.ListValue, 'plugin_opts_obfsmode', _('Plugin: ') + _('Obfs Mode')); + o.value('http', _('HTTP')); + o.value('tls', _('TLS')); + o.depends('plugin', 'obfs'); + o.modalonly = true; + o = s.taboption('field_general', form.Value, 'plugin_opts_handshake_dest', _('Plugin: ') + _('Handshake target that supports TLS 1.3')); o.datatype = 'hostport'; o.placeholder = 'cloud.tencent.com:443'; @@ -782,6 +820,40 @@ function renderListeners(s, uciconfig, isClient) { o.depends('vless_decryption', '1'); o.modalonly = true; + // @xhttp-config其他的配置 + + /* Hysteria2 Realm fields */ + o = s.taboption('field_general', form.Flag, 'hysteria2_realm', _('Realm')); + o.default = o.disabled; + o.depends('type', 'hysteria2'); + o.modalonly = true; + + o = s.taboption('field_hysteria2_realm', form.Value, 'hysteria2_realm_server_url', _('Rendezvous server')); + o.placeholder = 'https://realm.hy2.io'; + o.rmempty = false; + o.depends('hysteria2_realm', '1'); + o.modalonly = true; + + o = s.taboption('field_hysteria2_realm', form.Value, 'hysteria2_realm_token', _('Pre-shared key of rendezvous server')); + o.placeholder = 'public'; + o.depends('hysteria2_realm', '1'); + o.modalonly = true; + + o = s.taboption('field_hysteria2_realm', form.Value, 'hysteria2_realm_id', _('Realm ID')); + o.placeholder = 'my-cabin-1f3a8c2e9b'; + o.rmempty = false; + o.depends('hysteria2_realm', '1'); + o.modalonly = true; + + o = s.taboption('field_hysteria2_realm', form.DynamicList, 'hysteria2_realm_stun_servers', _('STUN servers')); + o.datatype = 'hostport'; + o.default = ['stun.nextcloud.com:3478','stun.sip.us:3478','global.stun.twilio.com:3478']; + o.rmempty = false; + o.depends('hysteria2_realm', '1'); + o.modalonly = true; + + // @ 下面支持填写针对server-url的TLS配置(sni, skip-cert-verify, fingerprint, certificate, private-key, alpn) + /* TLS fields */ o = s.taboption('field_general', form.Flag, 'tls', _('TLS')); o.default = o.disabled; @@ -795,12 +867,29 @@ function renderListeners(s, uciconfig, isClient) { if (['trojan', 'anytls', 'tuic', 'hysteria2', 'trusttunnel'].includes(type)) { tls.checked = true; tls.disabled = true; - if (['tuic', 'hysteria2'].includes(type) && !`${tls_alpn.getValue()}`) - tls_alpn.setValue('h3'); } else { tls.removeAttribute('disabled'); } + // Default alpn + if (!`${tls_alpn.getValue()}`) { + let def_alpn; + + switch (type) { + case 'hysteria2': + case 'tuic': + def_alpn = ['h3']; + break; + case 'hysteria2-realm': + def_alpn = ['h2', 'http/1.1']; + break; + default: + def_alpn = []; + } + + tls_alpn.setValue(def_alpn); + } + // Force disabled if (['trusttunnel'].includes(type)) { tls_alpn.node.querySelector('input').disabled = true; @@ -817,7 +906,7 @@ function renderListeners(s, uciconfig, isClient) { return true; } - o.depends({type: /^(http|socks|mixed|vmess|vless|trojan|anytls|tuic|hysteria2|trusttunnel)$/}); + o.depends({type: /^(http|socks|mixed|vmess|vless|trojan|anytls|tuic|hysteria2|hysteria2-realm|trusttunnel)$/}); o.modalonly = true; o = s.taboption('field_tls', form.DynamicList, 'tls_alpn', _('TLS ALPN'), @@ -860,7 +949,7 @@ function renderListeners(s, uciconfig, isClient) { hm.tls_client_auth_types.forEach((res) => { o.value.apply(o, res); }) - o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|tuic|trusttunnel)$/}); + o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.modalonly = true; o = s.taboption('field_tls', form.Value, 'tls_client_auth_cert_path', _('Client Auth Certificate path') + _(' (mTLS)'), @@ -869,7 +958,7 @@ function renderListeners(s, uciconfig, isClient) { o.validate = function(/* ... */) { return hm.validateMTLSClientAuth.call(this, 'tls_client_auth_type', ...arguments); } - o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|tuic|trusttunnel)$/}); + o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.modalonly = true; o = s.taboption('field_tls', form.Button, '_upload_client_auth_cert', _('Upload certificate') + _(' (mTLS)'), @@ -918,13 +1007,13 @@ function renderListeners(s, uciconfig, isClient) { return node; } - o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|tuic|trusttunnel)$/}); + o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.modalonly = true; o = s.taboption('field_tls', hm.CopyValue, 'tls_ech_config', _('ECH config'), _('This ECH parameter needs to be added to the HTTPS record of the domain.')); o.placeholder = 'AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA'; - o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|tuic|trusttunnel)$/}); + o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.modalonly = true; // uTLS fields diff --git a/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js b/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js index 7ee34a39..c30a3feb 100644 --- a/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js +++ b/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js @@ -221,6 +221,7 @@ return view.extend({ ss.tab('field_general', _('General fields')); ss.tab('field_vless_encryption', _('Vless Encryption fields')); + ss.tab('field_hysteria2_realm', _('Hysteria2 Realm fields')); ss.tab('field_tls', _('TLS fields')); ss.tab('field_transport', _('Transport fields')); ss.tab('field_multiplex', _('Multiplex fields')); @@ -956,6 +957,40 @@ return view.extend({ so.depends('vless_encryption', '1'); so.modalonly = true; + // @ 下面支持填写针对download-settings的上下行分离配置 + + /* Hysteria2 Realm fields */ + so = ss.taboption('field_general', form.Flag, 'hysteria2_realm', _('Realm')); + so.default = so.disabled; + so.depends('type', 'hysteria2'); + so.modalonly = true; + + so = ss.taboption('field_hysteria2_realm', form.Value, 'hysteria2_realm_server_url', _('Rendezvous server')); + so.placeholder = 'https://realm.hy2.io'; + so.rmempty = false; + so.depends('hysteria2_realm', '1'); + so.modalonly = true; + + so = ss.taboption('field_hysteria2_realm', form.Value, 'hysteria2_realm_token', _('Pre-shared key of rendezvous server')); + so.placeholder = 'public'; + so.depends('hysteria2_realm', '1'); + so.modalonly = true; + + so = ss.taboption('field_hysteria2_realm', form.Value, 'hysteria2_realm_id', _('Realm ID')); + so.placeholder = 'my-cabin-1f3a8c2e9b'; + so.rmempty = false; + so.depends('hysteria2_realm', '1'); + so.modalonly = true; + + so = ss.taboption('field_hysteria2_realm', form.DynamicList, 'hysteria2_realm_stun_servers', _('STUN servers')); + so.datatype = 'hostport'; + so.default = ['stun.nextcloud.com:3478','stun.sip.us:3478','global.stun.twilio.com:3478']; + so.rmempty = false; + so.depends('hysteria2_realm', '1'); + so.modalonly = true; + + // @ 下面支持填写针对server-url的TLS配置(sni, skip-cert-verify, fingerprint, certificate, private-key, alpn) + /* TLS fields */ so = ss.taboption('field_general', form.Flag, 'tls', _('TLS')); so.default = so.disabled; diff --git a/luci-app-fchomo/po/templates/fchomo.pot b/luci-app-fchomo/po/templates/fchomo.pot index 9962dec9..9bb8cfbe 100644 --- a/luci-app-fchomo/po/templates/fchomo.pot +++ b/luci-app-fchomo/po/templates/fchomo.pot @@ -5,30 +5,30 @@ msgstr "Content-Type: text/plain; charset=UTF-8" msgid "%s log" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:239 #: htdocs/luci-static/resources/fchomo.js:240 #: htdocs/luci-static/resources/fchomo.js:241 #: htdocs/luci-static/resources/fchomo.js:242 #: htdocs/luci-static/resources/fchomo.js:243 #: htdocs/luci-static/resources/fchomo.js:244 +#: htdocs/luci-static/resources/fchomo.js:245 msgid "%s ports" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:604 -#: htdocs/luci-static/resources/fchomo.js:607 +#: htdocs/luci-static/resources/fchomo.js:605 +#: htdocs/luci-static/resources/fchomo.js:608 #: htdocs/luci-static/resources/view/fchomo/client.js:315 msgid "(Imported)" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:858 -#: htdocs/luci-static/resources/fchomo/listeners.js:866 -#: htdocs/luci-static/resources/fchomo/listeners.js:875 +#: htdocs/luci-static/resources/fchomo/listeners.js:947 +#: htdocs/luci-static/resources/fchomo/listeners.js:955 +#: htdocs/luci-static/resources/fchomo/listeners.js:964 #: htdocs/luci-static/resources/view/fchomo/global.js:543 #: htdocs/luci-static/resources/view/fchomo/global.js:549 -#: htdocs/luci-static/resources/view/fchomo/node.js:1059 -#: htdocs/luci-static/resources/view/fchomo/node.js:1065 -#: htdocs/luci-static/resources/view/fchomo/node.js:1073 -#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/view/fchomo/node.js:1094 +#: htdocs/luci-static/resources/view/fchomo/node.js:1100 +#: htdocs/luci-static/resources/view/fchomo/node.js:1108 +#: htdocs/luci-static/resources/view/fchomo/node.js:1114 msgid "(mTLS)" msgstr "" @@ -39,19 +39,19 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1056 #: htdocs/luci-static/resources/view/fchomo/client.js:1057 #: htdocs/luci-static/resources/view/fchomo/client.js:1278 -#: htdocs/luci-static/resources/view/fchomo/node.js:1862 -#: htdocs/luci-static/resources/view/fchomo/node.js:1868 -#: htdocs/luci-static/resources/view/fchomo/node.js:1882 -#: htdocs/luci-static/resources/view/fchomo/node.js:1888 +#: htdocs/luci-static/resources/view/fchomo/node.js:1897 +#: htdocs/luci-static/resources/view/fchomo/node.js:1903 +#: htdocs/luci-static/resources/view/fchomo/node.js:1917 +#: htdocs/luci-static/resources/view/fchomo/node.js:1923 msgid "-- Please choose --" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:391 +#: htdocs/luci-static/resources/fchomo.js:392 msgid "0-RTT reuse." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:388 -#: htdocs/luci-static/resources/fchomo.js:392 +#: htdocs/luci-static/resources/fchomo.js:389 +#: htdocs/luci-static/resources/fchomo.js:393 msgid "1-RTT only." msgstr "" @@ -59,15 +59,15 @@ msgstr "" msgid "163Music" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:338 +#: htdocs/luci-static/resources/fchomo.js:339 msgid "2022-blake3-aes-128-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:339 +#: htdocs/luci-static/resources/fchomo.js:340 msgid "2022-blake3-aes-256-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:340 +#: htdocs/luci-static/resources/fchomo.js:341 msgid "2022-blake3-chacha20-poly1305" msgstr "" @@ -75,16 +75,16 @@ msgstr "" msgid "0 or 1 only." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:836 -#: htdocs/luci-static/resources/fchomo/listeners.js:851 -#: htdocs/luci-static/resources/fchomo/listeners.js:876 -#: htdocs/luci-static/resources/view/fchomo/node.js:1066 -#: htdocs/luci-static/resources/view/fchomo/node.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:925 +#: htdocs/luci-static/resources/fchomo/listeners.js:940 +#: htdocs/luci-static/resources/fchomo/listeners.js:965 +#: htdocs/luci-static/resources/view/fchomo/node.js:1101 +#: htdocs/luci-static/resources/view/fchomo/node.js:1115 msgid "Save your configuration before uploading files!" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:244 -#: htdocs/luci-static/resources/view/fchomo/node.js:379 +#: htdocs/luci-static/resources/fchomo/listeners.js:275 +#: htdocs/luci-static/resources/view/fchomo/node.js:380 msgid "" "A base64 string is used to fine-tune network behavior.
Please refer to " "the document" msgstr "" @@ -387,14 +387,14 @@ msgstr "" msgid "Bypass DSCP" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:395 -#: htdocs/luci-static/resources/fchomo/listeners.js:396 -#: htdocs/luci-static/resources/fchomo/listeners.js:397 -#: htdocs/luci-static/resources/fchomo/listeners.js:398 -#: htdocs/luci-static/resources/view/fchomo/node.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:426 +#: htdocs/luci-static/resources/fchomo/listeners.js:427 +#: htdocs/luci-static/resources/fchomo/listeners.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:429 #: htdocs/luci-static/resources/view/fchomo/node.js:458 #: htdocs/luci-static/resources/view/fchomo/node.js:459 #: htdocs/luci-static/resources/view/fchomo/node.js:460 +#: htdocs/luci-static/resources/view/fchomo/node.js:461 msgid "CDN support" msgstr "" @@ -410,21 +410,21 @@ msgstr "" msgid "CORS allowed origins, * will be used if empty." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:720 +#: htdocs/luci-static/resources/fchomo.js:721 msgid "Cancel" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1038 +#: htdocs/luci-static/resources/view/fchomo/node.js:1073 msgid "Cert fingerprint" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1039 +#: htdocs/luci-static/resources/view/fchomo/node.js:1074 msgid "" "Certificate fingerprint. Used to implement SSL Pinning and prevent MitM." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:828 -#: htdocs/luci-static/resources/view/fchomo/node.js:1059 +#: htdocs/luci-static/resources/fchomo/listeners.js:917 +#: htdocs/luci-static/resources/view/fchomo/node.js:1094 msgid "Certificate path" msgstr "" @@ -453,16 +453,16 @@ msgstr "" msgid "China list version" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:213 -#: htdocs/luci-static/resources/fchomo/listeners.js:311 -#: htdocs/luci-static/resources/view/fchomo/node.js:332 -#: htdocs/luci-static/resources/view/fchomo/node.js:391 -#: htdocs/luci-static/resources/view/fchomo/node.js:644 +#: htdocs/luci-static/resources/fchomo/listeners.js:244 +#: htdocs/luci-static/resources/fchomo/listeners.js:342 +#: htdocs/luci-static/resources/view/fchomo/node.js:333 +#: htdocs/luci-static/resources/view/fchomo/node.js:392 +#: htdocs/luci-static/resources/view/fchomo/node.js:645 msgid "Chipher" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:320 -#: htdocs/luci-static/resources/view/fchomo/node.js:400 +#: htdocs/luci-static/resources/fchomo/listeners.js:351 +#: htdocs/luci-static/resources/view/fchomo/node.js:401 msgid "Chipher must be enabled if obfuscate downlink is disabled." msgstr "" @@ -476,29 +476,29 @@ msgid "" "to download the latest initial package." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:651 -#: htdocs/luci-static/resources/fchomo/listeners.js:867 +#: htdocs/luci-static/resources/fchomo/listeners.js:689 +#: htdocs/luci-static/resources/fchomo/listeners.js:956 #: htdocs/luci-static/resources/view/fchomo/global.js:550 -#: htdocs/luci-static/resources/view/fchomo/node.js:928 -#: htdocs/luci-static/resources/view/fchomo/node.js:1060 -#: htdocs/luci-static/resources/view/fchomo/node.js:1074 +#: htdocs/luci-static/resources/view/fchomo/node.js:929 +#: htdocs/luci-static/resources/view/fchomo/node.js:1095 +#: htdocs/luci-static/resources/view/fchomo/node.js:1109 #: root/usr/share/luci/menu.d/luci-app-fchomo.json:22 msgid "Client" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:866 +#: htdocs/luci-static/resources/fchomo/listeners.js:955 msgid "Client Auth Certificate path" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:858 +#: htdocs/luci-static/resources/fchomo/listeners.js:947 msgid "Client Auth type" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1105 +#: htdocs/luci-static/resources/view/fchomo/node.js:1140 msgid "Client fingerprint" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:307 +#: htdocs/luci-static/resources/fchomo/listeners.js:338 msgid "Client key" msgstr "" @@ -510,21 +510,21 @@ msgstr "" msgid "Collecting data..." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:237 #: htdocs/luci-static/resources/fchomo.js:238 +#: htdocs/luci-static/resources/fchomo.js:239 msgid "Common ports (bypass P2P traffic)" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1367 +#: htdocs/luci-static/resources/fchomo.js:1368 msgid "Complete" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1680 +#: htdocs/luci-static/resources/view/fchomo/node.js:1715 msgid "Configuration Items" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:545 -#: htdocs/luci-static/resources/view/fchomo/node.js:857 +#: htdocs/luci-static/resources/fchomo/listeners.js:583 +#: htdocs/luci-static/resources/view/fchomo/node.js:858 msgid "Congestion controller" msgstr "" @@ -536,19 +536,19 @@ msgstr "" msgid "Conservative" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:589 +#: htdocs/luci-static/resources/fchomo.js:590 msgid "Content copied to clipboard!" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:670 -#: htdocs/luci-static/resources/view/fchomo/node.js:1590 -#: htdocs/luci-static/resources/view/fchomo/node.js:1616 +#: htdocs/luci-static/resources/view/fchomo/node.js:1625 +#: htdocs/luci-static/resources/view/fchomo/node.js:1651 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:339 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:365 msgid "Content will not be verified, Please make sure you enter it correctly." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1589 +#: htdocs/luci-static/resources/view/fchomo/node.js:1624 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:338 msgid "Contents" msgstr "" @@ -557,7 +557,7 @@ msgstr "" msgid "Contents have been saved." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:591 +#: htdocs/luci-static/resources/fchomo.js:592 msgid "Copy" msgstr "" @@ -573,7 +573,7 @@ msgstr "" msgid "Custom Direct List" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1651 +#: htdocs/luci-static/resources/view/fchomo/node.js:1686 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:400 msgid "Custom HTTP header." msgstr "" @@ -582,8 +582,8 @@ msgstr "" msgid "Custom Proxy List" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:335 -#: htdocs/luci-static/resources/view/fchomo/node.js:415 +#: htdocs/luci-static/resources/fchomo/listeners.js:366 +#: htdocs/luci-static/resources/view/fchomo/node.js:416 msgid "Custom byte layout" msgstr "" @@ -592,7 +592,7 @@ msgid "" "Custom internal hosts. Support yaml or json format." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:185 +#: htdocs/luci-static/resources/fchomo.js:186 msgid "DIRECT" msgstr "" @@ -608,8 +608,8 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:873 #: htdocs/luci-static/resources/view/fchomo/client.js:1428 #: htdocs/luci-static/resources/view/fchomo/client.js:1437 -#: htdocs/luci-static/resources/view/fchomo/node.js:715 -#: htdocs/luci-static/resources/view/fchomo/node.js:798 +#: htdocs/luci-static/resources/view/fchomo/node.js:716 +#: htdocs/luci-static/resources/view/fchomo/node.js:799 msgid "DNS server" msgstr "" @@ -637,24 +637,24 @@ msgstr "" msgid "Default DNS server" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:769 +#: htdocs/luci-static/resources/view/fchomo/node.js:770 msgid "Destination addresses allowed to be forwarded via Wireguard." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1861 +#: htdocs/luci-static/resources/view/fchomo/node.js:1896 msgid "Destination provider" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1867 +#: htdocs/luci-static/resources/view/fchomo/node.js:1902 msgid "Destination proxy node" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:227 +#: htdocs/luci-static/resources/view/fchomo/node.js:228 msgid "Dial fields" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1894 +#: htdocs/luci-static/resources/view/fchomo/node.js:1909 +#: htdocs/luci-static/resources/view/fchomo/node.js:1929 msgid "Different chain head/tail" msgstr "" @@ -674,9 +674,9 @@ msgstr "" msgid "Direct MAC-s" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:193 +#: htdocs/luci-static/resources/fchomo/listeners.js:194 #: htdocs/luci-static/resources/view/fchomo/global.js:403 -#: htdocs/luci-static/resources/view/fchomo/node.js:298 +#: htdocs/luci-static/resources/view/fchomo/node.js:299 msgid "Disable" msgstr "" @@ -692,7 +692,7 @@ msgstr "" msgid "Disable ICMP Forwarding" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:979 +#: htdocs/luci-static/resources/view/fchomo/node.js:1014 msgid "Disable SNI" msgstr "" @@ -718,46 +718,46 @@ msgstr "" msgid "Domain" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:980 +#: htdocs/luci-static/resources/view/fchomo/node.js:1015 msgid "Donot send server name in ClientHello." msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1577 -#: htdocs/luci-static/resources/view/fchomo/node.js:1052 -#: htdocs/luci-static/resources/view/fchomo/node.js:1720 +#: htdocs/luci-static/resources/view/fchomo/node.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1755 msgid "Donot verifying server certificate." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1399 +#: htdocs/luci-static/resources/view/fchomo/node.js:1434 msgid "Download bandwidth" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1400 +#: htdocs/luci-static/resources/view/fchomo/node.js:1435 msgid "Download bandwidth in Mbps." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1246 +#: htdocs/luci-static/resources/fchomo.js:1247 msgid "Download failed: %s" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1244 +#: htdocs/luci-static/resources/fchomo.js:1245 msgid "Download successful." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:171 +#: htdocs/luci-static/resources/fchomo.js:172 msgid "Dual stack" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1099 +#: htdocs/luci-static/resources/view/fchomo/node.js:1134 msgid "ECH HTTPS record query servername" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:924 -#: htdocs/luci-static/resources/view/fchomo/node.js:1093 +#: htdocs/luci-static/resources/fchomo/listeners.js:1013 +#: htdocs/luci-static/resources/view/fchomo/node.js:1128 msgid "ECH config" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:883 +#: htdocs/luci-static/resources/fchomo/listeners.js:972 msgid "ECH key" msgstr "" @@ -773,11 +773,11 @@ msgstr "" msgid "ETag support" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1239 +#: htdocs/luci-static/resources/view/fchomo/node.js:1274 msgid "Early Data first packet length limit." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1245 +#: htdocs/luci-static/resources/view/fchomo/node.js:1280 msgid "Early Data header name" msgstr "" @@ -793,16 +793,16 @@ msgstr "" msgid "Edit ruleset" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1587 +#: htdocs/luci-static/resources/view/fchomo/node.js:1622 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:336 msgid "Editer" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:382 +#: htdocs/luci-static/resources/fchomo.js:383 msgid "Eliminate encryption header characteristics" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:132 +#: htdocs/luci-static/resources/fchomo/listeners.js:133 #: htdocs/luci-static/resources/view/fchomo/client.js:931 #: htdocs/luci-static/resources/view/fchomo/client.js:1024 #: htdocs/luci-static/resources/view/fchomo/client.js:1262 @@ -812,23 +812,23 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1780 #: htdocs/luci-static/resources/view/fchomo/global.js:401 #: htdocs/luci-static/resources/view/fchomo/global.js:680 -#: htdocs/luci-static/resources/view/fchomo/node.js:234 -#: htdocs/luci-static/resources/view/fchomo/node.js:1560 -#: htdocs/luci-static/resources/view/fchomo/node.js:1759 -#: htdocs/luci-static/resources/view/fchomo/node.js:1848 +#: htdocs/luci-static/resources/view/fchomo/node.js:235 +#: htdocs/luci-static/resources/view/fchomo/node.js:1595 +#: htdocs/luci-static/resources/view/fchomo/node.js:1794 +#: htdocs/luci-static/resources/view/fchomo/node.js:1883 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:264 #: htdocs/luci-static/resources/view/fchomo/server.js:49 msgid "Enable" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:553 +#: htdocs/luci-static/resources/view/fchomo/node.js:554 msgid "" "Enable 0-RTT QUIC connection handshake on the client side. This is not " "impacting much on the performance, as the protocol is fully multiplexed.
Disabling this is highly recommended, as it is vulnerable to replay attacks." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:552 +#: htdocs/luci-static/resources/view/fchomo/node.js:553 msgid "Enable 0-RTT handshake" msgstr "" @@ -838,53 +838,53 @@ msgid "" "conversion for outbound connections" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1122 msgid "Enable ECH" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1387 +#: htdocs/luci-static/resources/view/fchomo/node.js:1422 msgid "Enable TCP Brutal" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1388 +#: htdocs/luci-static/resources/view/fchomo/node.js:1423 msgid "Enable TCP Brutal congestion control algorithm" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1376 +#: htdocs/luci-static/resources/view/fchomo/node.js:1411 msgid "Enable multiplexing only for TCP." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:381 -#: htdocs/luci-static/resources/view/fchomo/node.js:443 +#: htdocs/luci-static/resources/fchomo/listeners.js:412 +#: htdocs/luci-static/resources/view/fchomo/node.js:444 msgid "Enable obfuscate for downlink" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1370 +#: htdocs/luci-static/resources/view/fchomo/node.js:1405 msgid "Enable padding" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1381 +#: htdocs/luci-static/resources/view/fchomo/node.js:1416 msgid "Enable statistic" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:1702 +#: htdocs/luci-static/resources/view/fchomo/node.js:881 +#: htdocs/luci-static/resources/view/fchomo/node.js:1737 msgid "" "Enable the SUoT protocol, requires server support. Conflict with Multiplex." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:199 -#: htdocs/luci-static/resources/view/fchomo/node.js:304 +#: htdocs/luci-static/resources/fchomo/listeners.js:200 +#: htdocs/luci-static/resources/view/fchomo/node.js:305 msgid "" "Enabling obfuscation will make the server incompatible with standard QUIC " "connections, losing the ability to masquerade with HTTP/3." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:614 +#: htdocs/luci-static/resources/fchomo/listeners.js:652 msgid "Encryption method" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:682 +#: htdocs/luci-static/resources/view/fchomo/node.js:683 msgid "Endpoint pubkic key" msgstr "" @@ -907,7 +907,7 @@ msgid "" "if empty." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1817 +#: htdocs/luci-static/resources/view/fchomo/node.js:1852 msgid "Exclude matched node types." msgstr "" @@ -918,7 +918,7 @@ msgid "" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1161 -#: htdocs/luci-static/resources/view/fchomo/node.js:1810 +#: htdocs/luci-static/resources/view/fchomo/node.js:1845 msgid "Exclude nodes that meet keywords or regexps." msgstr "" @@ -927,66 +927,66 @@ msgid "Expand/Collapse result" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1121 -#: htdocs/luci-static/resources/view/fchomo/node.js:1795 +#: htdocs/luci-static/resources/view/fchomo/node.js:1830 msgid "Expected HTTP code. 204 will be used if empty." msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1123 -#: htdocs/luci-static/resources/view/fchomo/node.js:1797 +#: htdocs/luci-static/resources/view/fchomo/node.js:1832 msgid "Expected status" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:439 -#: htdocs/luci-static/resources/fchomo.js:442 -#: htdocs/luci-static/resources/fchomo.js:445 -#: htdocs/luci-static/resources/fchomo.js:1384 -#: htdocs/luci-static/resources/fchomo.js:1392 -#: htdocs/luci-static/resources/fchomo.js:1400 -#: htdocs/luci-static/resources/fchomo.js:1423 -#: htdocs/luci-static/resources/fchomo.js:1426 -#: htdocs/luci-static/resources/fchomo.js:1433 -#: htdocs/luci-static/resources/fchomo.js:1449 -#: htdocs/luci-static/resources/fchomo.js:1458 -#: htdocs/luci-static/resources/fchomo.js:1470 -#: htdocs/luci-static/resources/fchomo.js:1473 -#: htdocs/luci-static/resources/fchomo.js:1483 -#: htdocs/luci-static/resources/fchomo.js:1495 -#: htdocs/luci-static/resources/fchomo.js:1498 -#: htdocs/luci-static/resources/fchomo.js:1508 -#: htdocs/luci-static/resources/fchomo.js:1518 -#: htdocs/luci-static/resources/fchomo.js:1553 -#: htdocs/luci-static/resources/fchomo.js:1555 -#: htdocs/luci-static/resources/fchomo.js:1568 -#: htdocs/luci-static/resources/fchomo.js:1574 -#: htdocs/luci-static/resources/fchomo.js:1581 -#: htdocs/luci-static/resources/fchomo.js:1590 -#: htdocs/luci-static/resources/fchomo/listeners.js:320 -#: htdocs/luci-static/resources/fchomo/listeners.js:367 -#: htdocs/luci-static/resources/fchomo/listeners.js:643 -#: htdocs/luci-static/resources/fchomo/listeners.js:674 -#: htdocs/luci-static/resources/fchomo/listeners.js:775 +#: htdocs/luci-static/resources/fchomo.js:440 +#: htdocs/luci-static/resources/fchomo.js:443 +#: htdocs/luci-static/resources/fchomo.js:446 +#: htdocs/luci-static/resources/fchomo.js:1385 +#: htdocs/luci-static/resources/fchomo.js:1393 +#: htdocs/luci-static/resources/fchomo.js:1401 +#: htdocs/luci-static/resources/fchomo.js:1424 +#: htdocs/luci-static/resources/fchomo.js:1427 +#: htdocs/luci-static/resources/fchomo.js:1434 +#: htdocs/luci-static/resources/fchomo.js:1450 +#: htdocs/luci-static/resources/fchomo.js:1459 +#: htdocs/luci-static/resources/fchomo.js:1471 +#: htdocs/luci-static/resources/fchomo.js:1474 +#: htdocs/luci-static/resources/fchomo.js:1484 +#: htdocs/luci-static/resources/fchomo.js:1496 +#: htdocs/luci-static/resources/fchomo.js:1499 +#: htdocs/luci-static/resources/fchomo.js:1509 +#: htdocs/luci-static/resources/fchomo.js:1519 +#: htdocs/luci-static/resources/fchomo.js:1554 +#: htdocs/luci-static/resources/fchomo.js:1556 +#: htdocs/luci-static/resources/fchomo.js:1569 +#: htdocs/luci-static/resources/fchomo.js:1575 +#: htdocs/luci-static/resources/fchomo.js:1582 +#: htdocs/luci-static/resources/fchomo.js:1591 +#: htdocs/luci-static/resources/fchomo/listeners.js:351 +#: htdocs/luci-static/resources/fchomo/listeners.js:398 +#: htdocs/luci-static/resources/fchomo/listeners.js:681 +#: htdocs/luci-static/resources/fchomo/listeners.js:712 +#: htdocs/luci-static/resources/fchomo/listeners.js:813 #: htdocs/luci-static/resources/view/fchomo/client.js:68 #: htdocs/luci-static/resources/view/fchomo/client.js:1018 #: htdocs/luci-static/resources/view/fchomo/client.js:1508 #: htdocs/luci-static/resources/view/fchomo/global.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:400 -#: htdocs/luci-static/resources/view/fchomo/node.js:436 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:491 -#: htdocs/luci-static/resources/view/fchomo/node.js:951 -#: htdocs/luci-static/resources/view/fchomo/node.js:1044 -#: htdocs/luci-static/resources/view/fchomo/node.js:1874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1894 +#: htdocs/luci-static/resources/view/fchomo/node.js:401 +#: htdocs/luci-static/resources/view/fchomo/node.js:437 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 +#: htdocs/luci-static/resources/view/fchomo/node.js:952 +#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/view/fchomo/node.js:1909 +#: htdocs/luci-static/resources/view/fchomo/node.js:1929 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:291 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:305 msgid "Expecting: %s" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:991 -#: htdocs/luci-static/resources/fchomo/listeners.js:998 -#: htdocs/luci-static/resources/view/fchomo/node.js:1154 -#: htdocs/luci-static/resources/view/fchomo/node.js:1161 -#: htdocs/luci-static/resources/view/fchomo/node.js:1169 +#: htdocs/luci-static/resources/fchomo/listeners.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1189 +#: htdocs/luci-static/resources/view/fchomo/node.js:1196 +#: htdocs/luci-static/resources/view/fchomo/node.js:1204 msgid "Expecting: only support %s." msgstr "" @@ -1005,24 +1005,24 @@ msgstr "" msgid "Factor" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1325 +#: htdocs/luci-static/resources/fchomo.js:1326 msgid "Failed to execute \"/etc/init.d/fchomo %s %s\" reason: %s" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1278 +#: htdocs/luci-static/resources/fchomo.js:1279 msgid "Failed to generate %s, error: %s." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1690 +#: htdocs/luci-static/resources/fchomo.js:1691 msgid "Failed to upload %s, error: %s." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1709 +#: htdocs/luci-static/resources/fchomo.js:1710 msgid "Failed to upload, error: %s." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:229 -#: htdocs/luci-static/resources/fchomo/listeners.js:406 +#: htdocs/luci-static/resources/fchomo.js:230 +#: htdocs/luci-static/resources/fchomo/listeners.js:437 msgid "Fallback" msgstr "" @@ -1036,7 +1036,7 @@ msgid "Fallback filter" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1156 -#: htdocs/luci-static/resources/view/fchomo/node.js:1804 +#: htdocs/luci-static/resources/view/fchomo/node.js:1839 msgid "Filter nodes that meet keywords or regexps." msgstr "" @@ -1061,12 +1061,12 @@ msgstr "" msgid "Final DNS server (For poisoned domains)" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:136 +#: htdocs/luci-static/resources/fchomo/listeners.js:137 msgid "Firewall" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:474 -#: htdocs/luci-static/resources/view/fchomo/node.js:630 +#: htdocs/luci-static/resources/fchomo/listeners.js:505 +#: htdocs/luci-static/resources/view/fchomo/node.js:631 msgid "Flow" msgstr "" @@ -1077,15 +1077,15 @@ msgid "" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1122 -#: htdocs/luci-static/resources/view/fchomo/node.js:1670 -#: htdocs/luci-static/resources/view/fchomo/node.js:1796 +#: htdocs/luci-static/resources/view/fchomo/node.js:1705 +#: htdocs/luci-static/resources/view/fchomo/node.js:1831 msgid "" "For format see
%s." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:710 -#: htdocs/luci-static/resources/view/fchomo/node.js:793 +#: htdocs/luci-static/resources/view/fchomo/node.js:711 +#: htdocs/luci-static/resources/view/fchomo/node.js:794 msgid "Force DNS remote resolution." msgstr "" @@ -1104,7 +1104,7 @@ msgstr "" msgid "FullCombo Shark!" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1194 +#: htdocs/luci-static/resources/view/fchomo/node.js:1229 msgid "GET" msgstr "" @@ -1119,7 +1119,7 @@ msgstr "" #: htdocs/luci-static/resources/fchomo/listeners.js:119 #: htdocs/luci-static/resources/view/fchomo/client.js:1009 #: htdocs/luci-static/resources/view/fchomo/node.js:222 -#: htdocs/luci-static/resources/view/fchomo/node.js:1550 +#: htdocs/luci-static/resources/view/fchomo/node.js:1585 msgid "General fields" msgstr "" @@ -1127,15 +1127,15 @@ msgstr "" msgid "General settings" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:540 -#: htdocs/luci-static/resources/fchomo.js:542 -#: htdocs/luci-static/resources/fchomo.js:556 -#: htdocs/luci-static/resources/fchomo.js:558 -#: htdocs/luci-static/resources/fchomo/listeners.js:298 -#: htdocs/luci-static/resources/fchomo/listeners.js:342 -#: htdocs/luci-static/resources/fchomo/listeners.js:344 -#: htdocs/luci-static/resources/fchomo/listeners.js:747 -#: htdocs/luci-static/resources/fchomo/listeners.js:916 +#: htdocs/luci-static/resources/fchomo.js:541 +#: htdocs/luci-static/resources/fchomo.js:543 +#: htdocs/luci-static/resources/fchomo.js:557 +#: htdocs/luci-static/resources/fchomo.js:559 +#: htdocs/luci-static/resources/fchomo/listeners.js:329 +#: htdocs/luci-static/resources/fchomo/listeners.js:373 +#: htdocs/luci-static/resources/fchomo/listeners.js:375 +#: htdocs/luci-static/resources/fchomo/listeners.js:785 +#: htdocs/luci-static/resources/fchomo/listeners.js:1005 #: htdocs/luci-static/resources/view/fchomo/global.js:587 msgid "Generate" msgstr "" @@ -1179,7 +1179,7 @@ msgstr "" msgid "Global Authentication" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:654 +#: htdocs/luci-static/resources/view/fchomo/node.js:655 msgid "Global padding" msgstr "" @@ -1187,7 +1187,7 @@ msgstr "" msgid "Google" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:242 +#: htdocs/luci-static/resources/fchomo.js:243 msgid "Google FCM" msgstr "" @@ -1200,48 +1200,49 @@ msgid "Group" msgstr "" #: htdocs/luci-static/resources/fchomo.js:153 -#: htdocs/luci-static/resources/fchomo.js:186 -#: htdocs/luci-static/resources/view/fchomo/node.js:816 -#: htdocs/luci-static/resources/view/fchomo/node.js:1143 -#: htdocs/luci-static/resources/view/fchomo/node.js:1154 -#: htdocs/luci-static/resources/view/fchomo/node.js:1161 +#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo/listeners.js:539 +#: htdocs/luci-static/resources/view/fchomo/node.js:817 +#: htdocs/luci-static/resources/view/fchomo/node.js:1178 +#: htdocs/luci-static/resources/view/fchomo/node.js:1189 +#: htdocs/luci-static/resources/view/fchomo/node.js:1196 msgid "HTTP" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:267 -#: htdocs/luci-static/resources/view/fchomo/node.js:1216 -#: htdocs/luci-static/resources/view/fchomo/node.js:1650 +#: htdocs/luci-static/resources/view/fchomo/node.js:268 +#: htdocs/luci-static/resources/view/fchomo/node.js:1251 +#: htdocs/luci-static/resources/view/fchomo/node.js:1685 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:399 msgid "HTTP header" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:387 -#: htdocs/luci-static/resources/view/fchomo/node.js:449 +#: htdocs/luci-static/resources/fchomo/listeners.js:418 +#: htdocs/luci-static/resources/view/fchomo/node.js:450 msgid "HTTP mask" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:392 -#: htdocs/luci-static/resources/view/fchomo/node.js:454 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/fchomo/listeners.js:423 +#: htdocs/luci-static/resources/view/fchomo/node.js:455 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "HTTP mask mode" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:479 +#: htdocs/luci-static/resources/view/fchomo/node.js:480 msgid "HTTP mask multiplex" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:464 -#: htdocs/luci-static/resources/view/fchomo/node.js:469 +#: htdocs/luci-static/resources/view/fchomo/node.js:465 +#: htdocs/luci-static/resources/view/fchomo/node.js:470 msgid "HTTP mask: %s" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1193 +#: htdocs/luci-static/resources/view/fchomo/node.js:1228 msgid "HTTP request method" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:402 -#: htdocs/luci-static/resources/view/fchomo/node.js:475 +#: htdocs/luci-static/resources/fchomo/listeners.js:433 +#: htdocs/luci-static/resources/view/fchomo/node.js:476 msgid "HTTP root path" msgstr "" @@ -1249,15 +1250,15 @@ msgstr "" msgid "HTTP/3" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:207 +#: htdocs/luci-static/resources/fchomo/listeners.js:208 msgid "" "HTTP3 server behavior when authentication fails.
A 404 page will be " "returned if empty." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1144 -#: htdocs/luci-static/resources/view/fchomo/node.js:1155 -#: htdocs/luci-static/resources/view/fchomo/node.js:1162 +#: htdocs/luci-static/resources/view/fchomo/node.js:1179 +#: htdocs/luci-static/resources/view/fchomo/node.js:1190 +#: htdocs/luci-static/resources/view/fchomo/node.js:1197 msgid "HTTPUpgrade" msgstr "" @@ -1265,48 +1266,52 @@ msgstr "" msgid "Handle domain" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:371 +#: htdocs/luci-static/resources/view/fchomo/node.js:372 msgid "Handshake mode" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:506 +#: htdocs/luci-static/resources/fchomo/listeners.js:544 msgid "Handshake target that supports TLS 1.3" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:374 +#: htdocs/luci-static/resources/fchomo/listeners.js:405 msgid "Handshake timeout" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:721 +#: htdocs/luci-static/resources/fchomo/listeners.js:233 +msgid "Header to read real client IP from (e.g. X-Forwarded-For)" +msgstr "" + +#: htdocs/luci-static/resources/view/fchomo/node.js:722 msgid "Health check" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1091 -#: htdocs/luci-static/resources/view/fchomo/node.js:1764 +#: htdocs/luci-static/resources/view/fchomo/node.js:1799 msgid "Health check URL" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1120 -#: htdocs/luci-static/resources/view/fchomo/node.js:1794 +#: htdocs/luci-static/resources/view/fchomo/node.js:1829 msgid "Health check expected status" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1100 -#: htdocs/luci-static/resources/view/fchomo/node.js:1774 +#: htdocs/luci-static/resources/view/fchomo/node.js:1809 msgid "Health check interval" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1107 -#: htdocs/luci-static/resources/view/fchomo/node.js:1781 +#: htdocs/luci-static/resources/view/fchomo/node.js:1816 msgid "Health check timeout" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1011 -#: htdocs/luci-static/resources/view/fchomo/node.js:1552 +#: htdocs/luci-static/resources/view/fchomo/node.js:1587 msgid "Health fields" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:559 +#: htdocs/luci-static/resources/view/fchomo/node.js:560 msgid "Heartbeat interval" msgstr "" @@ -1314,19 +1319,19 @@ msgstr "" msgid "Hidden" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:822 +#: htdocs/luci-static/resources/view/fchomo/node.js:823 msgid "Host that supports TLS 1.3" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:326 +#: htdocs/luci-static/resources/view/fchomo/node.js:327 msgid "Host-key" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:321 +#: htdocs/luci-static/resources/view/fchomo/node.js:322 msgid "Host-key algorithms" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:469 +#: htdocs/luci-static/resources/view/fchomo/node.js:470 msgid "Host/SNI override" msgstr "" @@ -1336,10 +1341,19 @@ msgid "Hosts" msgstr "" #: htdocs/luci-static/resources/fchomo.js:164 -#: htdocs/luci-static/resources/fchomo.js:198 +#: htdocs/luci-static/resources/fchomo.js:199 msgid "Hysteria2" msgstr "" +#: htdocs/luci-static/resources/fchomo.js:165 +msgid "Hysteria2 Realm" +msgstr "" + +#: htdocs/luci-static/resources/fchomo/listeners.js:121 +#: htdocs/luci-static/resources/view/fchomo/node.js:224 +msgid "Hysteria2 Realm fields" +msgstr "" + #: htdocs/luci-static/resources/view/fchomo/client.js:1806 #: htdocs/luci-static/resources/view/fchomo/client.js:1819 msgid "IP" @@ -1349,20 +1363,20 @@ msgstr "" msgid "IP CIDR" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:521 +#: htdocs/luci-static/resources/view/fchomo/node.js:522 msgid "IP override" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1432 -#: htdocs/luci-static/resources/view/fchomo/node.js:1750 +#: htdocs/luci-static/resources/view/fchomo/node.js:1467 +#: htdocs/luci-static/resources/view/fchomo/node.js:1785 msgid "IP version" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:172 +#: htdocs/luci-static/resources/fchomo.js:173 msgid "IPv4 only" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:173 +#: htdocs/luci-static/resources/fchomo.js:174 msgid "IPv6 only" msgstr "" @@ -1375,19 +1389,19 @@ msgstr "" msgid "Icon" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:603 +#: htdocs/luci-static/resources/view/fchomo/node.js:604 msgid "Idle session check interval" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:610 +#: htdocs/luci-static/resources/view/fchomo/node.js:611 msgid "Idle session timeout" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:425 +#: htdocs/luci-static/resources/fchomo/listeners.js:456 msgid "Idle timeout" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1426 +#: htdocs/luci-static/resources/fchomo.js:1427 msgid "If All ports is selected, uncheck others" msgstr "" @@ -1395,11 +1409,11 @@ msgstr "" msgid "If Block is selected, uncheck others" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:186 +#: htdocs/luci-static/resources/fchomo/listeners.js:187 msgid "Ignore client bandwidth" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:725 +#: htdocs/luci-static/resources/fchomo.js:726 msgid "Import" msgstr "" @@ -1415,8 +1429,8 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1713 #: htdocs/luci-static/resources/view/fchomo/client.js:1748 #: htdocs/luci-static/resources/view/fchomo/client.js:1769 -#: htdocs/luci-static/resources/view/fchomo/node.js:1457 -#: htdocs/luci-static/resources/view/fchomo/node.js:1538 +#: htdocs/luci-static/resources/view/fchomo/node.js:1492 +#: htdocs/luci-static/resources/view/fchomo/node.js:1573 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:153 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:241 msgid "Import mihomo config" @@ -1428,41 +1442,41 @@ msgstr "" msgid "Import rule-set links" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:175 -#: htdocs/luci-static/resources/fchomo/listeners.js:181 -#: htdocs/luci-static/resources/view/fchomo/node.js:286 -#: htdocs/luci-static/resources/view/fchomo/node.js:292 -#: htdocs/luci-static/resources/view/fchomo/node.js:1708 -#: htdocs/luci-static/resources/view/fchomo/node.js:1714 +#: htdocs/luci-static/resources/fchomo/listeners.js:176 +#: htdocs/luci-static/resources/fchomo/listeners.js:182 +#: htdocs/luci-static/resources/view/fchomo/node.js:287 +#: htdocs/luci-static/resources/view/fchomo/node.js:293 +#: htdocs/luci-static/resources/view/fchomo/node.js:1743 +#: htdocs/luci-static/resources/view/fchomo/node.js:1749 msgid "In Mbps." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1628 +#: htdocs/luci-static/resources/view/fchomo/node.js:1663 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:377 msgid "In bytes. %s will be used if empty." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:560 -#: htdocs/luci-static/resources/view/fchomo/node.js:567 +#: htdocs/luci-static/resources/view/fchomo/node.js:561 +#: htdocs/luci-static/resources/view/fchomo/node.js:568 msgid "In millisecond." msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1108 #: htdocs/luci-static/resources/view/fchomo/client.js:1137 -#: htdocs/luci-static/resources/view/fchomo/node.js:1782 +#: htdocs/luci-static/resources/view/fchomo/node.js:1817 msgid "In millisecond. %s will be used if empty." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1285 +#: htdocs/luci-static/resources/view/fchomo/node.js:1320 msgid "In milliseconds." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:375 -#: htdocs/luci-static/resources/fchomo/listeners.js:426 -#: htdocs/luci-static/resources/fchomo/listeners.js:433 -#: htdocs/luci-static/resources/view/fchomo/node.js:604 -#: htdocs/luci-static/resources/view/fchomo/node.js:611 -#: htdocs/luci-static/resources/view/fchomo/node.js:1232 +#: htdocs/luci-static/resources/fchomo/listeners.js:406 +#: htdocs/luci-static/resources/fchomo/listeners.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:464 +#: htdocs/luci-static/resources/view/fchomo/node.js:605 +#: htdocs/luci-static/resources/view/fchomo/node.js:612 +#: htdocs/luci-static/resources/view/fchomo/node.js:1267 msgid "In seconds." msgstr "" @@ -1470,15 +1484,15 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/global.js:425 #: htdocs/luci-static/resources/view/fchomo/global.js:430 #: htdocs/luci-static/resources/view/fchomo/global.js:515 -#: htdocs/luci-static/resources/view/fchomo/node.js:280 -#: htdocs/luci-static/resources/view/fchomo/node.js:1634 -#: htdocs/luci-static/resources/view/fchomo/node.js:1775 +#: htdocs/luci-static/resources/view/fchomo/node.js:281 +#: htdocs/luci-static/resources/view/fchomo/node.js:1669 +#: htdocs/luci-static/resources/view/fchomo/node.js:1810 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:383 msgid "In seconds. %s will be used if empty." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:663 -#: htdocs/luci-static/resources/view/fchomo/node.js:940 +#: htdocs/luci-static/resources/fchomo/listeners.js:701 +#: htdocs/luci-static/resources/view/fchomo/node.js:941 msgid "" "In the order of one Padding-Length and one Padding-" "Interval, infinite concatenation." @@ -1518,7 +1532,7 @@ msgstr "" msgid "Info" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1567 +#: htdocs/luci-static/resources/view/fchomo/node.js:1602 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:279 msgid "Inline" msgstr "" @@ -1529,55 +1543,55 @@ msgstr "" #: htdocs/luci-static/resources/fchomo.js:52 #: htdocs/luci-static/resources/fchomo.js:59 -#: htdocs/luci-static/resources/fchomo.js:170 -#: htdocs/luci-static/resources/fchomo.js:364 -#: htdocs/luci-static/resources/view/fchomo/node.js:1724 +#: htdocs/luci-static/resources/fchomo.js:171 +#: htdocs/luci-static/resources/fchomo.js:365 +#: htdocs/luci-static/resources/view/fchomo/node.js:1759 msgid "Keep default" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1321 +#: htdocs/luci-static/resources/view/fchomo/node.js:1356 msgid "Keep-alive period" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:254 -#: htdocs/luci-static/resources/view/fchomo/node.js:385 +#: htdocs/luci-static/resources/fchomo/listeners.js:285 +#: htdocs/luci-static/resources/view/fchomo/node.js:386 msgid "Key" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:843 -#: htdocs/luci-static/resources/view/fchomo/node.js:1073 +#: htdocs/luci-static/resources/fchomo/listeners.js:932 +#: htdocs/luci-static/resources/view/fchomo/node.js:1108 msgid "Key path" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:682 +#: htdocs/luci-static/resources/fchomo/listeners.js:720 msgid "Keypairs" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:127 +#: htdocs/luci-static/resources/fchomo/listeners.js:128 #: htdocs/luci-static/resources/view/fchomo/client.js:1014 #: htdocs/luci-static/resources/view/fchomo/client.js:1257 #: htdocs/luci-static/resources/view/fchomo/client.js:1349 #: htdocs/luci-static/resources/view/fchomo/client.js:1488 #: htdocs/luci-static/resources/view/fchomo/client.js:1719 #: htdocs/luci-static/resources/view/fchomo/client.js:1775 -#: htdocs/luci-static/resources/view/fchomo/node.js:229 -#: htdocs/luci-static/resources/view/fchomo/node.js:1555 -#: htdocs/luci-static/resources/view/fchomo/node.js:1843 +#: htdocs/luci-static/resources/view/fchomo/node.js:230 +#: htdocs/luci-static/resources/view/fchomo/node.js:1590 +#: htdocs/luci-static/resources/view/fchomo/node.js:1878 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:259 msgid "Label" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1114 -#: htdocs/luci-static/resources/view/fchomo/node.js:1788 +#: htdocs/luci-static/resources/view/fchomo/node.js:1823 msgid "Lazy" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:394 -#: htdocs/luci-static/resources/view/fchomo/node.js:456 +#: htdocs/luci-static/resources/fchomo/listeners.js:425 +#: htdocs/luci-static/resources/view/fchomo/node.js:457 msgid "Legacy" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:483 +#: htdocs/luci-static/resources/fchomo/listeners.js:514 msgid "" "Legacy protocol support (VMess MD5 Authentication) is provided for " "compatibility purposes only, use of alterId > 1 is not recommended." @@ -1587,16 +1601,16 @@ msgstr "" msgid "Less compatibility and sometimes better performance." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:824 -#: htdocs/luci-static/resources/view/fchomo/node.js:992 +#: htdocs/luci-static/resources/fchomo/listeners.js:913 +#: htdocs/luci-static/resources/view/fchomo/node.js:1027 msgid "List of supported application level protocols, in order of preference." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:147 +#: htdocs/luci-static/resources/fchomo/listeners.js:148 msgid "Listen address" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:124 +#: htdocs/luci-static/resources/fchomo/listeners.js:125 msgid "Listen fields" msgstr "" @@ -1604,7 +1618,7 @@ msgstr "" msgid "Listen interfaces" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:152 +#: htdocs/luci-static/resources/fchomo/listeners.js:153 #: htdocs/luci-static/resources/view/fchomo/client.js:1374 msgid "Listen port" msgstr "" @@ -1613,22 +1627,22 @@ msgstr "" msgid "Listen ports" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:231 +#: htdocs/luci-static/resources/fchomo.js:232 msgid "Load balance" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1565 +#: htdocs/luci-static/resources/view/fchomo/node.js:1600 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:277 msgid "Local" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:697 -#: htdocs/luci-static/resources/view/fchomo/node.js:740 +#: htdocs/luci-static/resources/view/fchomo/node.js:698 +#: htdocs/luci-static/resources/view/fchomo/node.js:741 msgid "Local IPv6 address" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:689 -#: htdocs/luci-static/resources/view/fchomo/node.js:732 +#: htdocs/luci-static/resources/view/fchomo/node.js:690 +#: htdocs/luci-static/resources/view/fchomo/node.js:733 msgid "Local address" msgstr "" @@ -1648,32 +1662,32 @@ msgstr "" msgid "Log level" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:329 -#: htdocs/luci-static/resources/fchomo/listeners.js:330 -#: htdocs/luci-static/resources/fchomo/listeners.js:331 -#: htdocs/luci-static/resources/fchomo/listeners.js:336 -#: htdocs/luci-static/resources/view/fchomo/node.js:409 +#: htdocs/luci-static/resources/fchomo/listeners.js:360 +#: htdocs/luci-static/resources/fchomo/listeners.js:361 +#: htdocs/luci-static/resources/fchomo/listeners.js:362 +#: htdocs/luci-static/resources/fchomo/listeners.js:367 #: htdocs/luci-static/resources/view/fchomo/node.js:410 #: htdocs/luci-static/resources/view/fchomo/node.js:411 -#: htdocs/luci-static/resources/view/fchomo/node.js:416 +#: htdocs/luci-static/resources/view/fchomo/node.js:412 +#: htdocs/luci-static/resources/view/fchomo/node.js:417 msgid "Low-entropy data stream" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:439 +#: htdocs/luci-static/resources/fchomo.js:440 msgid "Lowercase only" msgstr "" #: htdocs/luci-static/resources/view/fchomo/global.js:502 -#: htdocs/luci-static/resources/view/fchomo/node.js:703 -#: htdocs/luci-static/resources/view/fchomo/node.js:786 +#: htdocs/luci-static/resources/view/fchomo/node.js:704 +#: htdocs/luci-static/resources/view/fchomo/node.js:787 msgid "MTU" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:200 +#: htdocs/luci-static/resources/fchomo.js:201 msgid "Masque" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:206 +#: htdocs/luci-static/resources/fchomo/listeners.js:207 msgid "Masquerade" msgstr "" @@ -1705,24 +1719,24 @@ msgstr "" msgid "Match rule set." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1238 +#: htdocs/luci-static/resources/view/fchomo/node.js:1273 msgid "Max Early Data" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:419 -#: htdocs/luci-static/resources/view/fchomo/node.js:546 +#: htdocs/luci-static/resources/fchomo/listeners.js:450 +#: htdocs/luci-static/resources/view/fchomo/node.js:547 msgid "Max UDP relay packet size" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1042 +#: htdocs/luci-static/resources/fchomo/listeners.js:1131 msgid "Max buffered posts" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1296 +#: htdocs/luci-static/resources/view/fchomo/node.js:1331 msgid "Max concurrency" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1301 +#: htdocs/luci-static/resources/view/fchomo/node.js:1336 msgid "Max connections" msgstr "" @@ -1730,66 +1744,74 @@ msgstr "" msgid "Max count of failures" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:180 -#: htdocs/luci-static/resources/view/fchomo/node.js:291 +#: htdocs/luci-static/resources/fchomo/listeners.js:181 +#: htdocs/luci-static/resources/view/fchomo/node.js:292 msgid "Max download speed" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1053 -#: htdocs/luci-static/resources/view/fchomo/node.js:1278 +#: htdocs/luci-static/resources/fchomo/listeners.js:1142 +#: htdocs/luci-static/resources/view/fchomo/node.js:1313 msgid "Max each POST bytes" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:573 +#: htdocs/luci-static/resources/view/fchomo/node.js:574 msgid "Max open streams" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1311 +#: htdocs/luci-static/resources/fchomo/listeners.js:220 +msgid "Max realms" +msgstr "" + +#: htdocs/luci-static/resources/fchomo/listeners.js:226 +msgid "Max realms per client IP" +msgstr "" + +#: htdocs/luci-static/resources/view/fchomo/node.js:1346 msgid "Max request times" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1316 +#: htdocs/luci-static/resources/view/fchomo/node.js:1351 msgid "Max reusable seconds" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1306 +#: htdocs/luci-static/resources/view/fchomo/node.js:1341 msgid "Max reuse times" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:174 -#: htdocs/luci-static/resources/view/fchomo/node.js:285 +#: htdocs/luci-static/resources/fchomo/listeners.js:175 +#: htdocs/luci-static/resources/view/fchomo/node.js:286 msgid "Max upload speed" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1342 -#: htdocs/luci-static/resources/view/fchomo/node.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1377 +#: htdocs/luci-static/resources/view/fchomo/node.js:1397 msgid "Maximum connections" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1360 +#: htdocs/luci-static/resources/view/fchomo/node.js:1395 msgid "" "Maximum multiplexed streams in a connection before opening a new connection." "
Conflict with %s and %s." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:359 -#: htdocs/luci-static/resources/view/fchomo/node.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:390 +#: htdocs/luci-static/resources/view/fchomo/node.js:429 msgid "Maximum padding rate" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:367 -#: htdocs/luci-static/resources/view/fchomo/node.js:436 +#: htdocs/luci-static/resources/fchomo/listeners.js:398 +#: htdocs/luci-static/resources/view/fchomo/node.js:437 msgid "" "Maximum padding rate must be greater than or equal to the minimum padding " "rate." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1359 +#: htdocs/luci-static/resources/view/fchomo/node.js:1394 msgid "Maximum streams" msgstr "" #: htdocs/luci-static/resources/fchomo.js:157 -#: htdocs/luci-static/resources/fchomo.js:190 +#: htdocs/luci-static/resources/fchomo.js:191 msgid "Mieru" msgstr "" @@ -1805,26 +1827,26 @@ msgstr "" msgid "Mihomo server" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:617 +#: htdocs/luci-static/resources/view/fchomo/node.js:618 msgid "Min of idle sessions to keep" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1284 +#: htdocs/luci-static/resources/view/fchomo/node.js:1319 msgid "Min posts interval" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1351 +#: htdocs/luci-static/resources/view/fchomo/node.js:1386 msgid "" "Minimum multiplexed streams in a connection before opening a new connection." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:352 -#: htdocs/luci-static/resources/view/fchomo/node.js:421 +#: htdocs/luci-static/resources/fchomo/listeners.js:383 +#: htdocs/luci-static/resources/view/fchomo/node.js:422 msgid "Minimum padding rate" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1350 -#: htdocs/luci-static/resources/view/fchomo/node.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1385 +#: htdocs/luci-static/resources/view/fchomo/node.js:1397 msgid "Minimum streams" msgstr "" @@ -1841,16 +1863,16 @@ msgstr "" msgid "Mixed port" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1328 +#: htdocs/luci-static/resources/view/fchomo/node.js:1363 msgid "Multiplex" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:123 -#: htdocs/luci-static/resources/view/fchomo/node.js:226 +#: htdocs/luci-static/resources/fchomo/listeners.js:124 +#: htdocs/luci-static/resources/view/fchomo/node.js:227 msgid "Multiplex fields" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:362 +#: htdocs/luci-static/resources/view/fchomo/node.js:363 msgid "Multiplexing" msgstr "" @@ -1859,11 +1881,11 @@ msgstr "" msgid "NOT" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:536 +#: htdocs/luci-static/resources/fchomo/listeners.js:574 msgid "Name of the Proxy group as outbound." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1640 +#: htdocs/luci-static/resources/view/fchomo/node.js:1675 msgid "Name of the Proxy group to download provider." msgstr "" @@ -1871,23 +1893,23 @@ msgstr "" msgid "Name of the Proxy group to download rule set." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:530 +#: htdocs/luci-static/resources/fchomo/listeners.js:568 msgid "Name of the Sub rule used for inbound matching." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:530 +#: htdocs/luci-static/resources/view/fchomo/node.js:531 msgid "Native UDP" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:381 +#: htdocs/luci-static/resources/fchomo.js:382 msgid "Native appearance" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:562 +#: htdocs/luci-static/resources/fchomo/listeners.js:600 msgid "Network type" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1726 +#: htdocs/luci-static/resources/view/fchomo/node.js:1761 msgid "No" msgstr "" @@ -1895,7 +1917,7 @@ msgstr "" msgid "No Authentication IP ranges" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1037 +#: htdocs/luci-static/resources/fchomo/listeners.js:1126 msgid "No SSE header" msgstr "" @@ -1903,16 +1925,16 @@ msgstr "" msgid "No add'l params" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1268 +#: htdocs/luci-static/resources/view/fchomo/node.js:1303 msgid "No gRPC header" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1115 -#: htdocs/luci-static/resources/view/fchomo/node.js:1789 +#: htdocs/luci-static/resources/view/fchomo/node.js:1824 msgid "No testing is performed when this provider node is not in use." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:686 +#: htdocs/luci-static/resources/fchomo.js:687 msgid "No valid %s found." msgstr "" @@ -1927,17 +1949,17 @@ msgid "Node" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1160 -#: htdocs/luci-static/resources/view/fchomo/node.js:1809 +#: htdocs/luci-static/resources/view/fchomo/node.js:1844 msgid "Node exclude filter" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1165 -#: htdocs/luci-static/resources/view/fchomo/node.js:1816 +#: htdocs/luci-static/resources/view/fchomo/node.js:1851 msgid "Node exclude type" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1155 -#: htdocs/luci-static/resources/view/fchomo/node.js:1803 +#: htdocs/luci-static/resources/view/fchomo/node.js:1838 msgid "Node filter" msgstr "" @@ -1945,7 +1967,7 @@ msgstr "" msgid "Node switch tolerance" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:408 +#: htdocs/luci-static/resources/fchomo.js:409 msgid "None" msgstr "" @@ -1953,38 +1975,39 @@ msgstr "" msgid "Not Installed" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1204 +#: htdocs/luci-static/resources/fchomo.js:1205 msgid "Not Running" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:482 +#: htdocs/luci-static/resources/view/fchomo/node.js:483 msgid "OFF" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:485 msgid "ON" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:815 +#: htdocs/luci-static/resources/fchomo/listeners.js:538 +#: htdocs/luci-static/resources/view/fchomo/node.js:816 msgid "Obfs Mode" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:198 -#: htdocs/luci-static/resources/view/fchomo/node.js:303 +#: htdocs/luci-static/resources/fchomo/listeners.js:199 +#: htdocs/luci-static/resources/view/fchomo/node.js:304 msgid "Obfuscate password" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:192 -#: htdocs/luci-static/resources/fchomo/listeners.js:327 -#: htdocs/luci-static/resources/view/fchomo/node.js:297 -#: htdocs/luci-static/resources/view/fchomo/node.js:407 +#: htdocs/luci-static/resources/fchomo/listeners.js:193 +#: htdocs/luci-static/resources/fchomo/listeners.js:358 +#: htdocs/luci-static/resources/view/fchomo/node.js:298 +#: htdocs/luci-static/resources/view/fchomo/node.js:408 msgid "Obfuscate type" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:328 -#: htdocs/luci-static/resources/fchomo/listeners.js:329 -#: htdocs/luci-static/resources/view/fchomo/node.js:408 +#: htdocs/luci-static/resources/fchomo/listeners.js:359 +#: htdocs/luci-static/resources/fchomo/listeners.js:360 #: htdocs/luci-static/resources/view/fchomo/node.js:409 +#: htdocs/luci-static/resources/view/fchomo/node.js:410 msgid "Obfuscated as %s" msgstr "" @@ -1992,8 +2015,8 @@ msgstr "" msgid "One or more numbers in the range 0-63 separated by commas" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:336 -#: htdocs/luci-static/resources/view/fchomo/node.js:416 +#: htdocs/luci-static/resources/fchomo/listeners.js:367 +#: htdocs/luci-static/resources/view/fchomo/node.js:417 msgid "Only applies to the %s." msgstr "" @@ -2001,7 +2024,7 @@ msgstr "" msgid "Only process traffic from specific interfaces. Leave empty for all." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1198 +#: htdocs/luci-static/resources/fchomo.js:1199 msgid "Open Dashboard" msgstr "" @@ -2015,11 +2038,11 @@ msgid "Override destination" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1010 -#: htdocs/luci-static/resources/view/fchomo/node.js:1551 +#: htdocs/luci-static/resources/view/fchomo/node.js:1586 msgid "Override fields" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:522 +#: htdocs/luci-static/resources/view/fchomo/node.js:523 msgid "Override the IP address of the server that DNS response." msgstr "" @@ -2035,7 +2058,7 @@ msgstr "" msgid "Override the existing ECS in original request." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1100 +#: htdocs/luci-static/resources/view/fchomo/node.js:1135 msgid "Overrides the domain name used for HTTPS record queries." msgstr "" @@ -2043,47 +2066,47 @@ msgstr "" msgid "Overview" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1195 +#: htdocs/luci-static/resources/view/fchomo/node.js:1230 msgid "POST" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1196 +#: htdocs/luci-static/resources/view/fchomo/node.js:1231 msgid "PUT" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:666 +#: htdocs/luci-static/resources/view/fchomo/node.js:667 msgid "Packet encoding" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1273 +#: htdocs/luci-static/resources/view/fchomo/node.js:1308 msgid "Padding bytes" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:463 +#: htdocs/luci-static/resources/fchomo/listeners.js:494 msgid "Padding scheme" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:661 -#: htdocs/luci-static/resources/view/fchomo/node.js:938 +#: htdocs/luci-static/resources/fchomo/listeners.js:699 +#: htdocs/luci-static/resources/view/fchomo/node.js:939 msgid "Paddings" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:165 -#: htdocs/luci-static/resources/fchomo/listeners.js:221 -#: htdocs/luci-static/resources/fchomo/listeners.js:513 -#: htdocs/luci-static/resources/view/fchomo/node.js:261 -#: htdocs/luci-static/resources/view/fchomo/node.js:340 -#: htdocs/luci-static/resources/view/fchomo/node.js:830 +#: htdocs/luci-static/resources/fchomo/listeners.js:166 +#: htdocs/luci-static/resources/fchomo/listeners.js:252 +#: htdocs/luci-static/resources/fchomo/listeners.js:551 +#: htdocs/luci-static/resources/view/fchomo/node.js:262 +#: htdocs/luci-static/resources/view/fchomo/node.js:341 +#: htdocs/luci-static/resources/view/fchomo/node.js:831 msgid "Password" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:601 -#: htdocs/luci-static/resources/view/fchomo/node.js:1615 +#: htdocs/luci-static/resources/fchomo/listeners.js:639 +#: htdocs/luci-static/resources/view/fchomo/node.js:1650 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:364 msgid "Payload" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:754 +#: htdocs/luci-static/resources/view/fchomo/node.js:755 msgid "Peer pubkic key" msgstr "" @@ -2093,11 +2116,11 @@ msgid "" "it is not needed." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:781 +#: htdocs/luci-static/resources/view/fchomo/node.js:782 msgid "Periodically sends data packets to maintain connection persistence." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:780 +#: htdocs/luci-static/resources/view/fchomo/node.js:781 msgid "Persistent keepalive" msgstr "" @@ -2118,8 +2141,8 @@ msgid "" "standards." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1588 -#: htdocs/luci-static/resources/view/fchomo/node.js:1614 +#: htdocs/luci-static/resources/view/fchomo/node.js:1623 +#: htdocs/luci-static/resources/view/fchomo/node.js:1649 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:337 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:363 msgid "" @@ -2133,41 +2156,42 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1445 #: htdocs/luci-static/resources/view/fchomo/client.js:1697 #: htdocs/luci-static/resources/view/fchomo/client.js:1749 -#: htdocs/luci-static/resources/view/fchomo/node.js:1458 +#: htdocs/luci-static/resources/view/fchomo/node.js:1493 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:154 msgid "Please type %s fields of mihomo config.
" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:499 -#: htdocs/luci-static/resources/view/fchomo/node.js:804 +#: htdocs/luci-static/resources/fchomo/listeners.js:530 +#: htdocs/luci-static/resources/view/fchomo/node.js:805 msgid "Plugin" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:506 -#: htdocs/luci-static/resources/fchomo/listeners.js:513 -#: htdocs/luci-static/resources/fchomo/listeners.js:519 -#: htdocs/luci-static/resources/view/fchomo/node.js:815 -#: htdocs/luci-static/resources/view/fchomo/node.js:822 -#: htdocs/luci-static/resources/view/fchomo/node.js:830 -#: htdocs/luci-static/resources/view/fchomo/node.js:836 -#: htdocs/luci-static/resources/view/fchomo/node.js:844 -#: htdocs/luci-static/resources/view/fchomo/node.js:850 +#: htdocs/luci-static/resources/fchomo/listeners.js:538 +#: htdocs/luci-static/resources/fchomo/listeners.js:544 +#: htdocs/luci-static/resources/fchomo/listeners.js:551 +#: htdocs/luci-static/resources/fchomo/listeners.js:557 +#: htdocs/luci-static/resources/view/fchomo/node.js:816 +#: htdocs/luci-static/resources/view/fchomo/node.js:823 +#: htdocs/luci-static/resources/view/fchomo/node.js:831 +#: htdocs/luci-static/resources/view/fchomo/node.js:837 +#: htdocs/luci-static/resources/view/fchomo/node.js:845 +#: htdocs/luci-static/resources/view/fchomo/node.js:851 msgid "Plugin:" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:249 +#: htdocs/luci-static/resources/view/fchomo/node.js:250 msgid "Port" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1435 +#: htdocs/luci-static/resources/fchomo.js:1436 msgid "Port %s alrealy exists!" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:279 +#: htdocs/luci-static/resources/view/fchomo/node.js:280 msgid "Port hop interval" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:350 +#: htdocs/luci-static/resources/view/fchomo/node.js:351 msgid "Port range" msgstr "" @@ -2175,21 +2199,27 @@ msgstr "" msgid "Ports" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:152 -#: htdocs/luci-static/resources/view/fchomo/node.js:274 +#: htdocs/luci-static/resources/fchomo/listeners.js:153 +#: htdocs/luci-static/resources/view/fchomo/node.js:275 msgid "Ports pool" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:499 -#: htdocs/luci-static/resources/view/fchomo/node.js:761 +#: htdocs/luci-static/resources/fchomo/listeners.js:214 +#: htdocs/luci-static/resources/view/fchomo/node.js:500 +#: htdocs/luci-static/resources/view/fchomo/node.js:762 msgid "Pre-shared key" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:174 -msgid "Prefer IPv4" +#: htdocs/luci-static/resources/fchomo/listeners.js:837 +#: htdocs/luci-static/resources/view/fchomo/node.js:974 +msgid "Pre-shared key of rendezvous server" msgstr "" #: htdocs/luci-static/resources/fchomo.js:175 +msgid "Prefer IPv4" +msgstr "" + +#: htdocs/luci-static/resources/fchomo.js:176 msgid "Prefer IPv6" msgstr "" @@ -2200,23 +2230,23 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/global.js:736 #: htdocs/luci-static/resources/view/fchomo/global.js:753 -#: htdocs/luci-static/resources/view/fchomo/node.js:1422 -#: htdocs/luci-static/resources/view/fchomo/node.js:1428 -#: htdocs/luci-static/resources/view/fchomo/node.js:1738 -#: htdocs/luci-static/resources/view/fchomo/node.js:1745 +#: htdocs/luci-static/resources/view/fchomo/node.js:1457 +#: htdocs/luci-static/resources/view/fchomo/node.js:1463 +#: htdocs/luci-static/resources/view/fchomo/node.js:1773 +#: htdocs/luci-static/resources/view/fchomo/node.js:1780 msgid "Priority: Proxy Node > Global." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:312 +#: htdocs/luci-static/resources/view/fchomo/node.js:313 msgid "Priv-key" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:316 +#: htdocs/luci-static/resources/view/fchomo/node.js:317 msgid "Priv-key passphrase" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:674 -#: htdocs/luci-static/resources/view/fchomo/node.js:746 +#: htdocs/luci-static/resources/view/fchomo/node.js:675 +#: htdocs/luci-static/resources/view/fchomo/node.js:747 msgid "Private key" msgstr "" @@ -2225,28 +2255,28 @@ msgid "Process matching mode" msgstr "" #: htdocs/luci-static/resources/view/fchomo/global.js:684 -#: htdocs/luci-static/resources/view/fchomo/node.js:1334 +#: htdocs/luci-static/resources/view/fchomo/node.js:1369 msgid "Protocol" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:661 +#: htdocs/luci-static/resources/view/fchomo/node.js:662 msgid "Protocol parameter. Enable length block encryption." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:655 +#: htdocs/luci-static/resources/view/fchomo/node.js:656 msgid "" "Protocol parameter. Will waste traffic randomly if enabled (enabled by " "default in v2ray and cannot be disabled)." msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1055 -#: htdocs/luci-static/resources/view/fchomo/node.js:1441 -#: htdocs/luci-static/resources/view/fchomo/node.js:1450 -#: htdocs/luci-static/resources/view/fchomo/node.js:1854 +#: htdocs/luci-static/resources/view/fchomo/node.js:1476 +#: htdocs/luci-static/resources/view/fchomo/node.js:1485 +#: htdocs/luci-static/resources/view/fchomo/node.js:1889 msgid "Provider" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1621 +#: htdocs/luci-static/resources/view/fchomo/node.js:1656 msgid "Provider URL" msgstr "" @@ -2269,19 +2299,19 @@ msgid "Proxy MAC-s" msgstr "" #: htdocs/luci-static/resources/view/fchomo/node.js:208 -#: htdocs/luci-static/resources/view/fchomo/node.js:1853 +#: htdocs/luci-static/resources/view/fchomo/node.js:1888 msgid "Proxy Node" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1829 -#: htdocs/luci-static/resources/view/fchomo/node.js:1838 +#: htdocs/luci-static/resources/view/fchomo/node.js:1864 +#: htdocs/luci-static/resources/view/fchomo/node.js:1873 msgid "Proxy chain" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:535 +#: htdocs/luci-static/resources/fchomo/listeners.js:573 #: htdocs/luci-static/resources/view/fchomo/client.js:783 #: htdocs/luci-static/resources/view/fchomo/client.js:1543 -#: htdocs/luci-static/resources/view/fchomo/node.js:1639 +#: htdocs/luci-static/resources/view/fchomo/node.js:1674 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:388 msgid "Proxy group" msgstr "" @@ -2298,8 +2328,8 @@ msgstr "" msgid "Proxy routerself" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:531 -#: htdocs/luci-static/resources/view/fchomo/node.js:726 +#: htdocs/luci-static/resources/view/fchomo/node.js:532 +#: htdocs/luci-static/resources/view/fchomo/node.js:727 msgid "QUIC" msgstr "" @@ -2308,44 +2338,44 @@ msgstr "" msgid "Quick Reload" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:931 -#: htdocs/luci-static/resources/view/fchomo/node.js:1114 +#: htdocs/luci-static/resources/fchomo/listeners.js:1020 +#: htdocs/luci-static/resources/view/fchomo/node.js:1149 msgid "REALITY" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1129 +#: htdocs/luci-static/resources/view/fchomo/node.js:1164 msgid "REALITY X25519MLKEM768 PQC support" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:968 +#: htdocs/luci-static/resources/fchomo/listeners.js:1057 msgid "REALITY certificate issued to" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:936 +#: htdocs/luci-static/resources/fchomo/listeners.js:1025 msgid "REALITY handshake server" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:943 +#: htdocs/luci-static/resources/fchomo/listeners.js:1032 msgid "REALITY private key" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:958 -#: htdocs/luci-static/resources/view/fchomo/node.js:1119 +#: htdocs/luci-static/resources/fchomo/listeners.js:1047 +#: htdocs/luci-static/resources/view/fchomo/node.js:1154 msgid "REALITY public key" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:962 -#: htdocs/luci-static/resources/view/fchomo/node.js:1124 +#: htdocs/luci-static/resources/fchomo/listeners.js:1051 +#: htdocs/luci-static/resources/view/fchomo/node.js:1159 msgid "REALITY short ID" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:632 -#: htdocs/luci-static/resources/fchomo/listeners.js:651 -#: htdocs/luci-static/resources/view/fchomo/node.js:928 +#: htdocs/luci-static/resources/fchomo/listeners.js:670 +#: htdocs/luci-static/resources/fchomo/listeners.js:689 +#: htdocs/luci-static/resources/view/fchomo/node.js:929 msgid "RTT" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:373 +#: htdocs/luci-static/resources/fchomo.js:374 msgid "Random" msgstr "" @@ -2353,10 +2383,24 @@ msgstr "" msgid "Random will be used if empty." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:383 +#: htdocs/luci-static/resources/fchomo.js:384 msgid "Randomized traffic characteristics" msgstr "" +#: htdocs/luci-static/resources/fchomo/listeners.js:826 +#: htdocs/luci-static/resources/view/fchomo/node.js:963 +msgid "Realm" +msgstr "" + +#: htdocs/luci-static/resources/fchomo/listeners.js:842 +#: htdocs/luci-static/resources/view/fchomo/node.js:979 +msgid "Realm ID" +msgstr "" + +#: htdocs/luci-static/resources/fchomo/listeners.js:237 +msgid "Realm name pattern" +msgstr "" + #: htdocs/luci-static/resources/view/fchomo/global.js:460 msgid "Redir port" msgstr "" @@ -2377,7 +2421,7 @@ msgstr "" msgid "Refresh every %s seconds." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1191 +#: htdocs/luci-static/resources/fchomo.js:1192 #: htdocs/luci-static/resources/view/fchomo/client.js:927 #: htdocs/luci-static/resources/view/fchomo/global.js:193 #: htdocs/luci-static/resources/view/fchomo/server.js:45 @@ -2388,64 +2432,69 @@ msgstr "" msgid "Reload All" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1566 +#: htdocs/luci-static/resources/view/fchomo/node.js:1601 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:278 msgid "Remote" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:709 -#: htdocs/luci-static/resources/view/fchomo/node.js:792 +#: htdocs/luci-static/resources/view/fchomo/node.js:710 +#: htdocs/luci-static/resources/view/fchomo/node.js:793 msgid "Remote DNS resolve" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1356 +#: htdocs/luci-static/resources/fchomo.js:1357 msgid "Remove" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1361 -#: htdocs/luci-static/resources/view/fchomo/node.js:1542 -#: htdocs/luci-static/resources/view/fchomo/node.js:1544 +#: htdocs/luci-static/resources/fchomo.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1577 +#: htdocs/luci-static/resources/view/fchomo/node.js:1579 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:251 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:253 msgid "Remove idles" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1668 +#: htdocs/luci-static/resources/fchomo/listeners.js:831 +#: htdocs/luci-static/resources/view/fchomo/node.js:968 +msgid "Rendezvous server" +msgstr "" + +#: htdocs/luci-static/resources/view/fchomo/node.js:1703 msgid "Replace name" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1669 +#: htdocs/luci-static/resources/view/fchomo/node.js:1704 msgid "Replace node name." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:357 +#: htdocs/luci-static/resources/fchomo.js:358 msgid "Request" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1016 -#: htdocs/luci-static/resources/view/fchomo/node.js:1202 -#: htdocs/luci-static/resources/view/fchomo/node.js:1209 +#: htdocs/luci-static/resources/fchomo/listeners.js:1105 +#: htdocs/luci-static/resources/view/fchomo/node.js:1237 +#: htdocs/luci-static/resources/view/fchomo/node.js:1244 msgid "Request path" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:566 +#: htdocs/luci-static/resources/view/fchomo/node.js:567 msgid "Request timeout" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:360 +#: htdocs/luci-static/resources/fchomo.js:361 msgid "Require and verify" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:358 +#: htdocs/luci-static/resources/fchomo.js:359 msgid "Require any" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:391 -#: htdocs/luci-static/resources/view/fchomo/node.js:1130 +#: htdocs/luci-static/resources/fchomo.js:392 +#: htdocs/luci-static/resources/view/fchomo/node.js:1165 msgid "Requires server support." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:775 +#: htdocs/luci-static/resources/view/fchomo/node.js:776 msgid "Reserved field bytes" msgstr "" @@ -2453,7 +2502,7 @@ msgstr "" msgid "Resources management" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:850 +#: htdocs/luci-static/resources/view/fchomo/node.js:851 msgid "Restls script" msgstr "" @@ -2467,12 +2516,12 @@ msgid "" "Returns the string input for icon in the API to display in this proxy group." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:483 +#: htdocs/luci-static/resources/view/fchomo/node.js:484 msgid "Reuse HTTP connections to reduce RTT for each connection establishment." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:480 -#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:481 +#: htdocs/luci-static/resources/view/fchomo/node.js:485 msgid "Reusing a single tunnel to carry multiple target connections within it." msgstr "" @@ -2489,8 +2538,8 @@ msgstr "" msgid "Routing GFW" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1427 -#: htdocs/luci-static/resources/view/fchomo/node.js:1744 +#: htdocs/luci-static/resources/view/fchomo/node.js:1462 +#: htdocs/luci-static/resources/view/fchomo/node.js:1779 msgid "Routing mark" msgstr "" @@ -2550,11 +2599,11 @@ msgstr "" msgid "Ruleset-URI-Scheme" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1204 +#: htdocs/luci-static/resources/fchomo.js:1205 msgid "Running" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:239 +#: htdocs/luci-static/resources/fchomo.js:240 msgid "SMTP" msgstr "" @@ -2562,36 +2611,41 @@ msgstr "" msgid "SOCKS" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo.js:188 msgid "SOCKS5" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:203 +#: htdocs/luci-static/resources/fchomo.js:204 msgid "SSH" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:240 +#: htdocs/luci-static/resources/fchomo.js:241 msgid "STUN" msgstr "" +#: htdocs/luci-static/resources/fchomo/listeners.js:848 +#: htdocs/luci-static/resources/view/fchomo/node.js:985 +msgid "STUN servers" +msgstr "" + #: htdocs/luci-static/resources/view/fchomo/client.js:1276 msgid "SUB-RULE" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:885 +#: htdocs/luci-static/resources/view/fchomo/node.js:886 msgid "SUoT version" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:194 -#: htdocs/luci-static/resources/view/fchomo/node.js:299 +#: htdocs/luci-static/resources/fchomo/listeners.js:195 +#: htdocs/luci-static/resources/view/fchomo/node.js:300 msgid "Salamander" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:180 +#: htdocs/luci-static/resources/fchomo.js:181 msgid "Same dstaddr requests. Same node" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:181 +#: htdocs/luci-static/resources/fchomo.js:182 msgid "Same srcaddr and dstaddr requests. Same node" msgstr "" @@ -2599,7 +2653,7 @@ msgstr "" msgid "Segment maximum size" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:228 +#: htdocs/luci-static/resources/fchomo.js:229 msgid "Select" msgstr "" @@ -2607,30 +2661,30 @@ msgstr "" msgid "Select Dashboard" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:397 +#: htdocs/luci-static/resources/fchomo.js:398 msgid "Send padding randomly 0-3333 bytes with 50% probability." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:386 #: htdocs/luci-static/resources/fchomo.js:387 +#: htdocs/luci-static/resources/fchomo.js:388 msgid "Send random ticket of 300s-600s duration for client 0-RTT reuse." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:632 -#: htdocs/luci-static/resources/fchomo/listeners.js:829 -#: htdocs/luci-static/resources/fchomo/listeners.js:844 +#: htdocs/luci-static/resources/fchomo/listeners.js:670 +#: htdocs/luci-static/resources/fchomo/listeners.js:918 +#: htdocs/luci-static/resources/fchomo/listeners.js:933 #: htdocs/luci-static/resources/view/fchomo/server.js:58 #: root/usr/share/luci/menu.d/luci-app-fchomo.json:62 msgid "Server" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:244 +#: htdocs/luci-static/resources/view/fchomo/node.js:245 msgid "Server address" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1010 -#: htdocs/luci-static/resources/view/fchomo/node.js:1181 -#: htdocs/luci-static/resources/view/fchomo/node.js:1187 +#: htdocs/luci-static/resources/fchomo/listeners.js:1099 +#: htdocs/luci-static/resources/view/fchomo/node.js:1216 +#: htdocs/luci-static/resources/view/fchomo/node.js:1222 msgid "Server hostname" msgstr "" @@ -2643,26 +2697,26 @@ msgid "Service status" msgstr "" #: htdocs/luci-static/resources/fchomo.js:156 -#: htdocs/luci-static/resources/fchomo.js:188 +#: htdocs/luci-static/resources/fchomo.js:189 msgid "Shadowsocks" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:445 -#: htdocs/luci-static/resources/view/fchomo/node.js:585 +#: htdocs/luci-static/resources/fchomo/listeners.js:476 +#: htdocs/luci-static/resources/view/fchomo/node.js:586 msgid "Shadowsocks chipher" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:440 -#: htdocs/luci-static/resources/view/fchomo/node.js:580 +#: htdocs/luci-static/resources/fchomo/listeners.js:471 +#: htdocs/luci-static/resources/view/fchomo/node.js:581 msgid "Shadowsocks encrypt" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:453 -#: htdocs/luci-static/resources/view/fchomo/node.js:593 +#: htdocs/luci-static/resources/fchomo/listeners.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:594 msgid "Shadowsocks password" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1382 +#: htdocs/luci-static/resources/view/fchomo/node.js:1417 msgid "Show connections in the dashboard for breaking connections easier." msgstr "" @@ -2670,18 +2724,18 @@ msgstr "" msgid "Silent" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:179 +#: htdocs/luci-static/resources/fchomo.js:180 msgid "Simple round-robin all nodes" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1627 +#: htdocs/luci-static/resources/view/fchomo/node.js:1662 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:376 msgid "Size limit" msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1576 -#: htdocs/luci-static/resources/view/fchomo/node.js:1051 -#: htdocs/luci-static/resources/view/fchomo/node.js:1719 +#: htdocs/luci-static/resources/view/fchomo/node.js:1086 +#: htdocs/luci-static/resources/view/fchomo/node.js:1754 msgid "Skip cert verify" msgstr "" @@ -2697,7 +2751,7 @@ msgstr "" msgid "Skiped sniffing src address" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:192 +#: htdocs/luci-static/resources/fchomo.js:193 msgid "Snell" msgstr "" @@ -2713,7 +2767,7 @@ msgstr "" msgid "Sniffer settings" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:429 +#: htdocs/luci-static/resources/fchomo.js:430 msgid "Specify a ID" msgstr "" @@ -2732,11 +2786,11 @@ msgstr "" msgid "Standard" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:243 +#: htdocs/luci-static/resources/fchomo.js:244 msgid "Steam Client" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:244 +#: htdocs/luci-static/resources/fchomo.js:245 msgid "Steam P2P" msgstr "" @@ -2745,7 +2799,7 @@ msgstr "" msgid "Strategy" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:529 +#: htdocs/luci-static/resources/fchomo/listeners.js:567 #: htdocs/luci-static/resources/view/fchomo/client.js:1303 #: htdocs/luci-static/resources/view/fchomo/client.js:1312 msgid "Sub rule" @@ -2755,7 +2809,7 @@ msgstr "" msgid "Sub rule group" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:689 +#: htdocs/luci-static/resources/fchomo.js:690 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:223 msgid "Successfully imported %s %s of total %s." msgstr "" @@ -2764,12 +2818,12 @@ msgstr "" msgid "Successfully updated." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1706 +#: htdocs/luci-static/resources/fchomo.js:1707 msgid "Successfully uploaded." msgstr "" #: htdocs/luci-static/resources/fchomo.js:158 -#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:192 msgid "Sudoku" msgstr "" @@ -2793,15 +2847,15 @@ msgstr "" #: htdocs/luci-static/resources/fchomo.js:160 #: htdocs/luci-static/resources/fchomo.js:161 #: htdocs/luci-static/resources/fchomo.js:162 -#: htdocs/luci-static/resources/fchomo.js:186 -#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:187 #: htdocs/luci-static/resources/fchomo.js:192 #: htdocs/luci-static/resources/fchomo.js:193 #: htdocs/luci-static/resources/fchomo.js:194 #: htdocs/luci-static/resources/fchomo.js:195 #: htdocs/luci-static/resources/fchomo.js:196 -#: htdocs/luci-static/resources/fchomo.js:203 -#: htdocs/luci-static/resources/fchomo/listeners.js:563 +#: htdocs/luci-static/resources/fchomo.js:197 +#: htdocs/luci-static/resources/fchomo.js:204 +#: htdocs/luci-static/resources/fchomo/listeners.js:601 #: htdocs/luci-static/resources/view/fchomo/client.js:589 #: htdocs/luci-static/resources/view/fchomo/client.js:679 msgid "TCP" @@ -2811,7 +2865,7 @@ msgstr "" msgid "TCP concurrency" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1375 +#: htdocs/luci-static/resources/view/fchomo/node.js:1410 msgid "TCP only" msgstr "" @@ -2829,92 +2883,94 @@ msgstr "" #: htdocs/luci-static/resources/fchomo.js:157 #: htdocs/luci-static/resources/fchomo.js:165 #: htdocs/luci-static/resources/fchomo.js:166 -#: htdocs/luci-static/resources/fchomo.js:185 -#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo.js:167 +#: htdocs/luci-static/resources/fchomo.js:186 #: htdocs/luci-static/resources/fchomo.js:188 -#: htdocs/luci-static/resources/fchomo.js:190 -#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:189 +#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:202 msgid "TCP/UDP" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1406 -#: htdocs/luci-static/resources/view/fchomo/node.js:1686 +#: htdocs/luci-static/resources/view/fchomo/node.js:1441 +#: htdocs/luci-static/resources/view/fchomo/node.js:1721 msgid "TFO" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:786 +#: htdocs/luci-static/resources/fchomo/listeners.js:540 +#: htdocs/luci-static/resources/fchomo/listeners.js:858 #: htdocs/luci-static/resources/view/fchomo/global.js:529 -#: htdocs/luci-static/resources/view/fchomo/node.js:464 -#: htdocs/luci-static/resources/view/fchomo/node.js:817 -#: htdocs/luci-static/resources/view/fchomo/node.js:960 +#: htdocs/luci-static/resources/view/fchomo/node.js:465 +#: htdocs/luci-static/resources/view/fchomo/node.js:818 +#: htdocs/luci-static/resources/view/fchomo/node.js:995 msgid "TLS" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:823 -#: htdocs/luci-static/resources/view/fchomo/node.js:991 +#: htdocs/luci-static/resources/fchomo/listeners.js:912 +#: htdocs/luci-static/resources/view/fchomo/node.js:1026 msgid "TLS ALPN" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:985 +#: htdocs/luci-static/resources/view/fchomo/node.js:1020 msgid "TLS SNI" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:121 -#: htdocs/luci-static/resources/view/fchomo/node.js:224 +#: htdocs/luci-static/resources/fchomo/listeners.js:122 +#: htdocs/luci-static/resources/view/fchomo/node.js:225 msgid "TLS fields" msgstr "" #: htdocs/luci-static/resources/fchomo.js:163 -#: htdocs/luci-static/resources/fchomo.js:199 +#: htdocs/luci-static/resources/fchomo.js:200 msgid "TUIC" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:241 +#: htdocs/luci-static/resources/fchomo.js:242 msgid "TURN" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:492 +#: htdocs/luci-static/resources/fchomo/listeners.js:523 msgid "Target address" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:187 +#: htdocs/luci-static/resources/fchomo/listeners.js:188 msgid "" "Tell the client to use the BBR flow control algorithm instead of Hysteria CC." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:690 -#: htdocs/luci-static/resources/view/fchomo/node.js:698 +#: htdocs/luci-static/resources/view/fchomo/node.js:691 +#: htdocs/luci-static/resources/view/fchomo/node.js:699 msgid "The %s address used by local machine in the Cloudflare WARP network." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:733 -#: htdocs/luci-static/resources/view/fchomo/node.js:741 +#: htdocs/luci-static/resources/view/fchomo/node.js:734 +#: htdocs/luci-static/resources/view/fchomo/node.js:742 msgid "The %s address used by local machine in the Wireguard network." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:844 -#: htdocs/luci-static/resources/view/fchomo/node.js:1074 +#: htdocs/luci-static/resources/fchomo/listeners.js:933 +#: htdocs/luci-static/resources/view/fchomo/node.js:1109 msgid "The %s private key, in PEM format." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:829 -#: htdocs/luci-static/resources/fchomo/listeners.js:867 +#: htdocs/luci-static/resources/fchomo/listeners.js:918 +#: htdocs/luci-static/resources/fchomo/listeners.js:956 #: htdocs/luci-static/resources/view/fchomo/global.js:550 -#: htdocs/luci-static/resources/view/fchomo/node.js:1060 +#: htdocs/luci-static/resources/view/fchomo/node.js:1095 msgid "The %s public key, in PEM format." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1094 +#: htdocs/luci-static/resources/view/fchomo/node.js:1129 msgid "" "The ECH parameter of the HTTPS record for the domain. Leave empty to resolve " "via DNS." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:386 +#: htdocs/luci-static/resources/view/fchomo/node.js:387 msgid "The ED25519 available private key or UUID provided by Sudoku server." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:255 +#: htdocs/luci-static/resources/fchomo/listeners.js:286 msgid "The ED25519 master public key or UUID generated by Sudoku." msgstr "" @@ -2922,8 +2978,8 @@ msgstr "" msgid "The default value is 2:00 every day." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:664 -#: htdocs/luci-static/resources/view/fchomo/node.js:941 +#: htdocs/luci-static/resources/fchomo/listeners.js:702 +#: htdocs/luci-static/resources/view/fchomo/node.js:942 msgid "" "The first padding must have a probability of 100% and at least 35 bytes." msgstr "" @@ -2938,25 +2994,25 @@ msgstr "" msgid "The matching %s will be deemed as poisoned." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:662 -#: htdocs/luci-static/resources/view/fchomo/node.js:939 +#: htdocs/luci-static/resources/fchomo/listeners.js:700 +#: htdocs/luci-static/resources/view/fchomo/node.js:940 msgid "The server and client can set different padding parameters." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:925 +#: htdocs/luci-static/resources/fchomo/listeners.js:1014 #: htdocs/luci-static/resources/view/fchomo/global.js:594 msgid "This ECH parameter needs to be added to the HTTPS record of the domain." msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1579 -#: htdocs/luci-static/resources/view/fchomo/node.js:1054 -#: htdocs/luci-static/resources/view/fchomo/node.js:1722 +#: htdocs/luci-static/resources/view/fchomo/node.js:1089 +#: htdocs/luci-static/resources/view/fchomo/node.js:1757 msgid "" "This is DANGEROUS, your traffic is almost like " "PLAIN TEXT! Use at your own risk!" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:536 +#: htdocs/luci-static/resources/view/fchomo/node.js:537 msgid "" "This is the TUIC port of the SUoT protocol, designed to provide a QUIC " "stream based UDP relay mode that TUIC does not provide." @@ -2985,33 +3041,33 @@ msgstr "" msgid "Tproxy port" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:243 -#: htdocs/luci-static/resources/view/fchomo/node.js:378 +#: htdocs/luci-static/resources/fchomo/listeners.js:274 +#: htdocs/luci-static/resources/view/fchomo/node.js:379 msgid "Traffic pattern" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1881 +#: htdocs/luci-static/resources/view/fchomo/node.js:1916 msgid "Transit proxy group" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1887 +#: htdocs/luci-static/resources/view/fchomo/node.js:1922 msgid "Transit proxy node" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:231 -#: htdocs/luci-static/resources/fchomo/listeners.js:976 -#: htdocs/luci-static/resources/view/fchomo/node.js:355 -#: htdocs/luci-static/resources/view/fchomo/node.js:1136 +#: htdocs/luci-static/resources/fchomo/listeners.js:262 +#: htdocs/luci-static/resources/fchomo/listeners.js:1065 +#: htdocs/luci-static/resources/view/fchomo/node.js:356 +#: htdocs/luci-static/resources/view/fchomo/node.js:1171 msgid "Transport" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:122 -#: htdocs/luci-static/resources/view/fchomo/node.js:225 +#: htdocs/luci-static/resources/fchomo/listeners.js:123 +#: htdocs/luci-static/resources/view/fchomo/node.js:226 msgid "Transport fields" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:981 -#: htdocs/luci-static/resources/view/fchomo/node.js:1141 +#: htdocs/luci-static/resources/fchomo/listeners.js:1070 +#: htdocs/luci-static/resources/view/fchomo/node.js:1176 msgid "Transport type" msgstr "" @@ -3020,15 +3076,19 @@ msgid "Treat the destination IP as the source IP." msgstr "" #: htdocs/luci-static/resources/fchomo.js:161 -#: htdocs/luci-static/resources/fchomo.js:195 +#: htdocs/luci-static/resources/fchomo.js:196 msgid "Trojan" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:165 -#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:166 +#: htdocs/luci-static/resources/fchomo.js:202 msgid "TrustTunnel" msgstr "" +#: htdocs/luci-static/resources/fchomo/listeners.js:232 +msgid "Trusted proxy header" +msgstr "" + #: htdocs/luci-static/resources/view/fchomo/global.js:764 msgid "Tun Fwmark/fwmask" msgstr "" @@ -3045,35 +3105,35 @@ msgstr "" msgid "Tun stack." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:166 +#: htdocs/luci-static/resources/fchomo.js:167 msgid "Tunnel" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:141 +#: htdocs/luci-static/resources/fchomo/listeners.js:142 #: htdocs/luci-static/resources/view/fchomo/client.js:530 #: htdocs/luci-static/resources/view/fchomo/client.js:643 #: htdocs/luci-static/resources/view/fchomo/client.js:737 #: htdocs/luci-static/resources/view/fchomo/client.js:842 #: htdocs/luci-static/resources/view/fchomo/client.js:1028 -#: htdocs/luci-static/resources/view/fchomo/node.js:238 -#: htdocs/luci-static/resources/view/fchomo/node.js:1564 -#: htdocs/luci-static/resources/view/fchomo/node.js:1852 +#: htdocs/luci-static/resources/view/fchomo/node.js:239 +#: htdocs/luci-static/resources/view/fchomo/node.js:1599 +#: htdocs/luci-static/resources/view/fchomo/node.js:1887 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:276 msgid "Type" msgstr "" #: htdocs/luci-static/resources/fchomo.js:163 #: htdocs/luci-static/resources/fchomo.js:164 -#: htdocs/luci-static/resources/fchomo.js:198 #: htdocs/luci-static/resources/fchomo.js:199 #: htdocs/luci-static/resources/fchomo.js:200 -#: htdocs/luci-static/resources/fchomo.js:202 -#: htdocs/luci-static/resources/fchomo/listeners.js:564 -#: htdocs/luci-static/resources/fchomo/listeners.js:569 +#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:203 +#: htdocs/luci-static/resources/fchomo/listeners.js:602 +#: htdocs/luci-static/resources/fchomo/listeners.js:607 #: htdocs/luci-static/resources/view/fchomo/client.js:588 #: htdocs/luci-static/resources/view/fchomo/client.js:678 -#: htdocs/luci-static/resources/view/fchomo/node.js:874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1696 +#: htdocs/luci-static/resources/view/fchomo/node.js:875 +#: htdocs/luci-static/resources/view/fchomo/node.js:1731 msgid "UDP" msgstr "" @@ -3081,42 +3141,42 @@ msgstr "" msgid "UDP NAT expiration time" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:535 +#: htdocs/luci-static/resources/view/fchomo/node.js:536 msgid "UDP over stream" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:541 +#: htdocs/luci-static/resources/view/fchomo/node.js:542 msgid "UDP over stream version" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:528 +#: htdocs/luci-static/resources/view/fchomo/node.js:529 msgid "UDP packet relay mode." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:527 +#: htdocs/luci-static/resources/view/fchomo/node.js:528 msgid "UDP relay mode" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:330 -#: htdocs/luci-static/resources/fchomo/listeners.js:331 -#: htdocs/luci-static/resources/view/fchomo/node.js:410 +#: htdocs/luci-static/resources/fchomo/listeners.js:361 +#: htdocs/luci-static/resources/fchomo/listeners.js:362 #: htdocs/luci-static/resources/view/fchomo/node.js:411 +#: htdocs/luci-static/resources/view/fchomo/node.js:412 msgid "UP: %s; DOWN: %s" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:230 +#: htdocs/luci-static/resources/fchomo.js:231 msgid "URL test" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:252 -#: htdocs/luci-static/resources/fchomo/listeners.js:413 -#: htdocs/luci-static/resources/fchomo/listeners.js:468 -#: htdocs/luci-static/resources/view/fchomo/node.js:515 -#: htdocs/luci-static/resources/view/fchomo/node.js:624 +#: htdocs/luci-static/resources/fchomo/listeners.js:283 +#: htdocs/luci-static/resources/fchomo/listeners.js:444 +#: htdocs/luci-static/resources/fchomo/listeners.js:499 +#: htdocs/luci-static/resources/view/fchomo/node.js:516 +#: htdocs/luci-static/resources/view/fchomo/node.js:625 msgid "UUID" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1249 +#: htdocs/luci-static/resources/fchomo.js:1250 msgid "Unable to download unsupported type: %s" msgstr "" @@ -3141,8 +3201,8 @@ msgstr "" msgid "Unknown error: %s" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:879 -#: htdocs/luci-static/resources/view/fchomo/node.js:1701 +#: htdocs/luci-static/resources/view/fchomo/node.js:880 +#: htdocs/luci-static/resources/view/fchomo/node.js:1736 msgid "UoT" msgstr "" @@ -3150,22 +3210,22 @@ msgstr "" msgid "Update failed." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1633 +#: htdocs/luci-static/resources/view/fchomo/node.js:1668 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:382 msgid "Update interval" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1393 +#: htdocs/luci-static/resources/view/fchomo/node.js:1428 msgid "Upload bandwidth" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1394 +#: htdocs/luci-static/resources/view/fchomo/node.js:1429 msgid "Upload bandwidth in Mbps." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:835 -#: htdocs/luci-static/resources/fchomo/listeners.js:875 -#: htdocs/luci-static/resources/view/fchomo/node.js:1065 +#: htdocs/luci-static/resources/fchomo/listeners.js:924 +#: htdocs/luci-static/resources/fchomo/listeners.js:964 +#: htdocs/luci-static/resources/view/fchomo/node.js:1100 msgid "Upload certificate" msgstr "" @@ -3173,17 +3233,17 @@ msgstr "" msgid "Upload initial package" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:850 -#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/fchomo/listeners.js:939 +#: htdocs/luci-static/resources/view/fchomo/node.js:1114 msgid "Upload key" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:838 -#: htdocs/luci-static/resources/fchomo/listeners.js:853 -#: htdocs/luci-static/resources/fchomo/listeners.js:878 +#: htdocs/luci-static/resources/fchomo/listeners.js:927 +#: htdocs/luci-static/resources/fchomo/listeners.js:942 +#: htdocs/luci-static/resources/fchomo/listeners.js:967 #: htdocs/luci-static/resources/view/fchomo/global.js:306 -#: htdocs/luci-static/resources/view/fchomo/node.js:1068 -#: htdocs/luci-static/resources/view/fchomo/node.js:1082 +#: htdocs/luci-static/resources/view/fchomo/node.js:1103 +#: htdocs/luci-static/resources/view/fchomo/node.js:1117 msgid "Upload..." msgstr "" @@ -3207,7 +3267,7 @@ msgstr "" msgid "Used to resolve the domain of the Proxy node." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:986 +#: htdocs/luci-static/resources/view/fchomo/node.js:1021 msgid "Used to verify the hostname on the returned certificates." msgstr "" @@ -3215,12 +3275,12 @@ msgstr "" msgid "User Authentication" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:238 +#: htdocs/luci-static/resources/fchomo/listeners.js:269 msgid "User-hint is mandatory" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:160 -#: htdocs/luci-static/resources/view/fchomo/node.js:256 +#: htdocs/luci-static/resources/fchomo/listeners.js:161 +#: htdocs/luci-static/resources/view/fchomo/node.js:257 msgid "Username" msgstr "" @@ -3228,41 +3288,41 @@ msgstr "" msgid "Users filter mode" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1250 +#: htdocs/luci-static/resources/view/fchomo/node.js:1285 msgid "V2ray HTTPUpgrade" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1255 +#: htdocs/luci-static/resources/view/fchomo/node.js:1290 msgid "V2ray HTTPUpgrade fast open" msgstr "" #: htdocs/luci-static/resources/fchomo.js:160 -#: htdocs/luci-static/resources/fchomo.js:194 +#: htdocs/luci-static/resources/fchomo.js:195 msgid "VLESS" msgstr "" #: htdocs/luci-static/resources/fchomo.js:159 -#: htdocs/luci-static/resources/fchomo.js:193 +#: htdocs/luci-static/resources/fchomo.js:194 msgid "VMess" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1570 -#: htdocs/luci-static/resources/view/fchomo/node.js:1858 +#: htdocs/luci-static/resources/view/fchomo/node.js:1605 +#: htdocs/luci-static/resources/view/fchomo/node.js:1893 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:319 msgid "Value" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:359 +#: htdocs/luci-static/resources/fchomo.js:360 msgid "Verify if given" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:519 -#: htdocs/luci-static/resources/view/fchomo/node.js:506 -#: htdocs/luci-static/resources/view/fchomo/node.js:836 +#: htdocs/luci-static/resources/fchomo/listeners.js:557 +#: htdocs/luci-static/resources/view/fchomo/node.js:507 +#: htdocs/luci-static/resources/view/fchomo/node.js:837 msgid "Version" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:844 +#: htdocs/luci-static/resources/view/fchomo/node.js:845 msgid "Version hint" msgstr "" @@ -3271,7 +3331,7 @@ msgstr "" msgid "Vless Encryption fields" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:396 +#: htdocs/luci-static/resources/fchomo.js:397 msgid "Wait a random 0-111 milliseconds with 75% probability." msgstr "" @@ -3279,16 +3339,16 @@ msgstr "" msgid "Warning" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:398 -#: htdocs/luci-static/resources/fchomo/listeners.js:983 -#: htdocs/luci-static/resources/fchomo/listeners.js:992 -#: htdocs/luci-static/resources/fchomo/listeners.js:999 -#: htdocs/luci-static/resources/view/fchomo/node.js:460 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:1146 -#: htdocs/luci-static/resources/view/fchomo/node.js:1157 -#: htdocs/luci-static/resources/view/fchomo/node.js:1164 -#: htdocs/luci-static/resources/view/fchomo/node.js:1170 +#: htdocs/luci-static/resources/fchomo/listeners.js:429 +#: htdocs/luci-static/resources/fchomo/listeners.js:1072 +#: htdocs/luci-static/resources/fchomo/listeners.js:1081 +#: htdocs/luci-static/resources/fchomo/listeners.js:1088 +#: htdocs/luci-static/resources/view/fchomo/node.js:461 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:1181 +#: htdocs/luci-static/resources/view/fchomo/node.js:1192 +#: htdocs/luci-static/resources/view/fchomo/node.js:1199 +#: htdocs/luci-static/resources/view/fchomo/node.js:1205 msgid "WebSocket" msgstr "" @@ -3300,52 +3360,52 @@ msgstr "" msgid "White list" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:202 +#: htdocs/luci-static/resources/fchomo.js:203 msgid "WireGuard" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:755 +#: htdocs/luci-static/resources/view/fchomo/node.js:756 msgid "WireGuard peer public key." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:762 +#: htdocs/luci-static/resources/view/fchomo/node.js:763 msgid "WireGuard pre-shared key." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:747 +#: htdocs/luci-static/resources/view/fchomo/node.js:748 msgid "WireGuard requires base64-encoded private keys." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:984 -#: htdocs/luci-static/resources/fchomo/listeners.js:993 -#: htdocs/luci-static/resources/view/fchomo/node.js:1147 -#: htdocs/luci-static/resources/view/fchomo/node.js:1165 +#: htdocs/luci-static/resources/fchomo/listeners.js:1073 +#: htdocs/luci-static/resources/fchomo/listeners.js:1082 +#: htdocs/luci-static/resources/view/fchomo/node.js:1182 +#: htdocs/luci-static/resources/view/fchomo/node.js:1200 msgid "XHTTP" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1029 -#: htdocs/luci-static/resources/view/fchomo/node.js:1260 +#: htdocs/luci-static/resources/fchomo/listeners.js:1118 +#: htdocs/luci-static/resources/view/fchomo/node.js:1295 msgid "XHTTP mode" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1291 +#: htdocs/luci-static/resources/view/fchomo/node.js:1326 msgid "XMUX" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1296 -#: htdocs/luci-static/resources/view/fchomo/node.js:1301 -#: htdocs/luci-static/resources/view/fchomo/node.js:1306 -#: htdocs/luci-static/resources/view/fchomo/node.js:1311 -#: htdocs/luci-static/resources/view/fchomo/node.js:1316 -#: htdocs/luci-static/resources/view/fchomo/node.js:1321 +#: htdocs/luci-static/resources/view/fchomo/node.js:1331 +#: htdocs/luci-static/resources/view/fchomo/node.js:1336 +#: htdocs/luci-static/resources/view/fchomo/node.js:1341 +#: htdocs/luci-static/resources/view/fchomo/node.js:1346 +#: htdocs/luci-static/resources/view/fchomo/node.js:1351 +#: htdocs/luci-static/resources/view/fchomo/node.js:1356 msgid "XMUX:" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:623 +#: htdocs/luci-static/resources/fchomo/listeners.js:661 msgid "XOR mode" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:669 +#: htdocs/luci-static/resources/view/fchomo/node.js:670 msgid "Xudp (Xray-core)" msgstr "" @@ -3353,7 +3413,7 @@ msgstr "" msgid "Yaml text" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1725 +#: htdocs/luci-static/resources/view/fchomo/node.js:1760 msgid "Yes" msgstr "" @@ -3361,27 +3421,27 @@ msgstr "" msgid "YouTube" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1688 +#: htdocs/luci-static/resources/fchomo.js:1689 msgid "Your %s was successfully uploaded. Size: %sB." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:332 -#: htdocs/luci-static/resources/fchomo.js:345 -#: htdocs/luci-static/resources/fchomo.js:350 -#: htdocs/luci-static/resources/view/fchomo/node.js:649 +#: htdocs/luci-static/resources/fchomo.js:333 +#: htdocs/luci-static/resources/fchomo.js:346 +#: htdocs/luci-static/resources/fchomo.js:351 +#: htdocs/luci-static/resources/view/fchomo/node.js:650 msgid "aes-128-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:333 +#: htdocs/luci-static/resources/fchomo.js:334 msgid "aes-192-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:334 -#: htdocs/luci-static/resources/fchomo.js:351 +#: htdocs/luci-static/resources/fchomo.js:335 +#: htdocs/luci-static/resources/fchomo.js:352 msgid "aes-256-gcm" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:646 +#: htdocs/luci-static/resources/view/fchomo/node.js:647 msgid "auto" msgstr "" @@ -3389,19 +3449,19 @@ msgstr "" msgid "bbr" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:840 -#: htdocs/luci-static/resources/fchomo/listeners.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:1070 +#: htdocs/luci-static/resources/fchomo/listeners.js:929 +#: htdocs/luci-static/resources/fchomo/listeners.js:969 +#: htdocs/luci-static/resources/view/fchomo/node.js:1105 msgid "certificate" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:335 -#: htdocs/luci-static/resources/fchomo.js:346 -#: htdocs/luci-static/resources/fchomo.js:352 +#: htdocs/luci-static/resources/fchomo.js:336 +#: htdocs/luci-static/resources/fchomo.js:347 +#: htdocs/luci-static/resources/fchomo.js:353 msgid "chacha20-ietf-poly1305" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:650 +#: htdocs/luci-static/resources/view/fchomo/node.js:651 msgid "chacha20-poly1305" msgstr "" @@ -3409,8 +3469,8 @@ msgstr "" msgid "cubic" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:575 -#: htdocs/luci-static/resources/fchomo/listeners.js:606 +#: htdocs/luci-static/resources/fchomo/listeners.js:613 +#: htdocs/luci-static/resources/fchomo/listeners.js:644 msgid "decryption" msgstr "" @@ -3418,41 +3478,41 @@ msgstr "" msgid "dnsmasq selects upstream on its own. (may affect CDN accuracy)" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1713 +#: htdocs/luci-static/resources/view/fchomo/node.js:1748 msgid "down" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:610 -#: htdocs/luci-static/resources/view/fchomo/node.js:893 -#: htdocs/luci-static/resources/view/fchomo/node.js:916 +#: htdocs/luci-static/resources/fchomo/listeners.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:894 +#: htdocs/luci-static/resources/view/fchomo/node.js:917 msgid "encryption" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:382 -#: htdocs/luci-static/resources/view/fchomo/node.js:444 +#: htdocs/luci-static/resources/fchomo/listeners.js:413 +#: htdocs/luci-static/resources/view/fchomo/node.js:445 msgid "false = bandwidth optimized downlink; true = pure Sudoku downlink." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:982 -#: htdocs/luci-static/resources/fchomo/listeners.js:991 -#: htdocs/luci-static/resources/fchomo/listeners.js:998 -#: htdocs/luci-static/resources/view/fchomo/node.js:1145 -#: htdocs/luci-static/resources/view/fchomo/node.js:1156 -#: htdocs/luci-static/resources/view/fchomo/node.js:1163 -#: htdocs/luci-static/resources/view/fchomo/node.js:1169 +#: htdocs/luci-static/resources/fchomo/listeners.js:1071 +#: htdocs/luci-static/resources/fchomo/listeners.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1180 +#: htdocs/luci-static/resources/view/fchomo/node.js:1191 +#: htdocs/luci-static/resources/view/fchomo/node.js:1198 +#: htdocs/luci-static/resources/view/fchomo/node.js:1204 msgid "gRPC" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1226 +#: htdocs/luci-static/resources/view/fchomo/node.js:1261 msgid "gRPC User-Agent" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1231 +#: htdocs/luci-static/resources/view/fchomo/node.js:1266 msgid "gRPC ping interval" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1023 -#: htdocs/luci-static/resources/view/fchomo/node.js:1222 +#: htdocs/luci-static/resources/fchomo/listeners.js:1112 +#: htdocs/luci-static/resources/view/fchomo/node.js:1257 msgid "gRPC service name" msgstr "" @@ -3460,11 +3520,11 @@ msgstr "" msgid "gVisor" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1338 +#: htdocs/luci-static/resources/view/fchomo/node.js:1373 msgid "h2mux" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:775 +#: htdocs/luci-static/resources/fchomo/listeners.js:813 msgid "least one keypair required" msgstr "" @@ -3478,17 +3538,17 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1480 #: htdocs/luci-static/resources/view/fchomo/client.js:1711 #: htdocs/luci-static/resources/view/fchomo/client.js:1767 -#: htdocs/luci-static/resources/view/fchomo/node.js:1536 +#: htdocs/luci-static/resources/view/fchomo/node.js:1571 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:239 msgid "mihomo config" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:378 +#: htdocs/luci-static/resources/fchomo.js:379 msgid "mlkem768x25519plus" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1410 -#: htdocs/luci-static/resources/view/fchomo/node.js:1691 +#: htdocs/luci-static/resources/view/fchomo/node.js:1445 +#: htdocs/luci-static/resources/view/fchomo/node.js:1726 msgid "mpTCP" msgstr "" @@ -3500,20 +3560,20 @@ msgstr "" msgid "no-resolve" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1423 -#: htdocs/luci-static/resources/fchomo.js:1518 -#: htdocs/luci-static/resources/fchomo.js:1553 -#: htdocs/luci-static/resources/fchomo.js:1581 +#: htdocs/luci-static/resources/fchomo.js:1424 +#: htdocs/luci-static/resources/fchomo.js:1519 +#: htdocs/luci-static/resources/fchomo.js:1554 +#: htdocs/luci-static/resources/fchomo.js:1582 msgid "non-empty value" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:330 -#: htdocs/luci-static/resources/fchomo.js:344 -#: htdocs/luci-static/resources/fchomo.js:356 -#: htdocs/luci-static/resources/fchomo/listeners.js:500 -#: htdocs/luci-static/resources/view/fchomo/node.js:647 -#: htdocs/luci-static/resources/view/fchomo/node.js:667 -#: htdocs/luci-static/resources/view/fchomo/node.js:805 +#: htdocs/luci-static/resources/fchomo.js:331 +#: htdocs/luci-static/resources/fchomo.js:345 +#: htdocs/luci-static/resources/fchomo.js:357 +#: htdocs/luci-static/resources/fchomo/listeners.js:531 +#: htdocs/luci-static/resources/view/fchomo/node.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:668 +#: htdocs/luci-static/resources/view/fchomo/node.js:806 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:315 msgid "none" msgstr "" @@ -3526,44 +3586,45 @@ msgstr "" msgid "not included \",\"" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:216 -#: htdocs/luci-static/resources/fchomo/listeners.js:531 -#: htdocs/luci-static/resources/fchomo/listeners.js:532 +#: htdocs/luci-static/resources/fchomo.js:217 +#: htdocs/luci-static/resources/fchomo/listeners.js:569 +#: htdocs/luci-static/resources/fchomo/listeners.js:570 msgid "null" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:806 +#: htdocs/luci-static/resources/fchomo/listeners.js:532 +#: htdocs/luci-static/resources/view/fchomo/node.js:807 msgid "obfs-simple" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "only applies when %s is %s." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:489 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 msgid "only applies when %s is not %s." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1671 +#: htdocs/luci-static/resources/view/fchomo/node.js:1706 msgid "override.proxy-name" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:668 +#: htdocs/luci-static/resources/view/fchomo/node.js:669 msgid "packet addr (v2ray-core v5+)" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1033 -#: htdocs/luci-static/resources/view/fchomo/node.js:1264 +#: htdocs/luci-static/resources/fchomo/listeners.js:1122 +#: htdocs/luci-static/resources/view/fchomo/node.js:1299 msgid "packet-up" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:396 -#: htdocs/luci-static/resources/view/fchomo/node.js:458 +#: htdocs/luci-static/resources/fchomo/listeners.js:427 +#: htdocs/luci-static/resources/view/fchomo/node.js:459 msgid "poll" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:855 -#: htdocs/luci-static/resources/view/fchomo/node.js:1084 +#: htdocs/luci-static/resources/fchomo/listeners.js:944 +#: htdocs/luci-static/resources/view/fchomo/node.js:1119 msgid "private key" msgstr "" @@ -3576,7 +3637,7 @@ msgstr "" msgid "requires front-end adaptation using the API." msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:810 +#: htdocs/luci-static/resources/view/fchomo/node.js:811 msgid "restls" msgstr "" @@ -3584,17 +3645,17 @@ msgstr "" msgid "rule-set" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:501 -#: htdocs/luci-static/resources/view/fchomo/node.js:809 +#: htdocs/luci-static/resources/fchomo/listeners.js:533 +#: htdocs/luci-static/resources/view/fchomo/node.js:810 msgid "shadow-tls" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1336 +#: htdocs/luci-static/resources/view/fchomo/node.js:1371 msgid "smux" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:395 -#: htdocs/luci-static/resources/view/fchomo/node.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:426 +#: htdocs/luci-static/resources/view/fchomo/node.js:458 msgid "split-stream" msgstr "" @@ -3602,25 +3663,25 @@ msgstr "" msgid "src" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1031 -#: htdocs/luci-static/resources/view/fchomo/node.js:1262 +#: htdocs/luci-static/resources/fchomo/listeners.js:1120 +#: htdocs/luci-static/resources/view/fchomo/node.js:1297 msgid "stream-one" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1032 -#: htdocs/luci-static/resources/view/fchomo/node.js:1263 +#: htdocs/luci-static/resources/fchomo/listeners.js:1121 +#: htdocs/luci-static/resources/view/fchomo/node.js:1298 msgid "stream-up" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1048 +#: htdocs/luci-static/resources/fchomo/listeners.js:1137 msgid "stream-up server seconds" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "stream/poll/auto" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:251 +#: htdocs/luci-static/resources/fchomo/listeners.js:282 msgid "sudoku-keypair" msgstr "" @@ -3628,87 +3689,87 @@ msgstr "" msgid "unchecked" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:442 +#: htdocs/luci-static/resources/fchomo.js:443 msgid "unique UCI identifier" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:445 +#: htdocs/luci-static/resources/fchomo.js:446 msgid "unique identifier" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1590 +#: htdocs/luci-static/resources/fchomo.js:1591 msgid "unique value" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1707 +#: htdocs/luci-static/resources/view/fchomo/node.js:1742 msgid "up" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:520 -#: htdocs/luci-static/resources/view/fchomo/node.js:507 -#: htdocs/luci-static/resources/view/fchomo/node.js:542 -#: htdocs/luci-static/resources/view/fchomo/node.js:837 -#: htdocs/luci-static/resources/view/fchomo/node.js:886 +#: htdocs/luci-static/resources/fchomo/listeners.js:558 +#: htdocs/luci-static/resources/view/fchomo/node.js:508 +#: htdocs/luci-static/resources/view/fchomo/node.js:543 +#: htdocs/luci-static/resources/view/fchomo/node.js:838 +#: htdocs/luci-static/resources/view/fchomo/node.js:887 msgid "v1" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:521 -#: htdocs/luci-static/resources/view/fchomo/node.js:508 -#: htdocs/luci-static/resources/view/fchomo/node.js:838 -#: htdocs/luci-static/resources/view/fchomo/node.js:887 +#: htdocs/luci-static/resources/fchomo/listeners.js:559 +#: htdocs/luci-static/resources/view/fchomo/node.js:509 +#: htdocs/luci-static/resources/view/fchomo/node.js:839 +#: htdocs/luci-static/resources/view/fchomo/node.js:888 msgid "v2" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:522 -#: htdocs/luci-static/resources/view/fchomo/node.js:509 -#: htdocs/luci-static/resources/view/fchomo/node.js:839 +#: htdocs/luci-static/resources/fchomo/listeners.js:560 +#: htdocs/luci-static/resources/view/fchomo/node.js:510 +#: htdocs/luci-static/resources/view/fchomo/node.js:840 msgid "v3" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1470 -#: htdocs/luci-static/resources/fchomo.js:1473 +#: htdocs/luci-static/resources/fchomo.js:1471 +#: htdocs/luci-static/resources/fchomo.js:1474 msgid "valid JSON format" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1044 +#: htdocs/luci-static/resources/view/fchomo/node.js:1079 msgid "valid SHA256 string with %d characters" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1495 -#: htdocs/luci-static/resources/fchomo.js:1498 +#: htdocs/luci-static/resources/fchomo.js:1496 +#: htdocs/luci-static/resources/fchomo.js:1499 msgid "valid URL" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1508 +#: htdocs/luci-static/resources/fchomo.js:1509 msgid "valid base64 key with %d characters" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1568 -#: htdocs/luci-static/resources/fchomo.js:1574 +#: htdocs/luci-static/resources/fchomo.js:1569 +#: htdocs/luci-static/resources/fchomo.js:1575 msgid "valid format: 2x, 2p, 4v" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1555 +#: htdocs/luci-static/resources/fchomo.js:1556 msgid "valid key length with %d characters" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1433 +#: htdocs/luci-static/resources/fchomo.js:1434 msgid "valid port value" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1483 +#: htdocs/luci-static/resources/fchomo.js:1484 msgid "valid uuid" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:402 +#: htdocs/luci-static/resources/fchomo.js:403 msgid "vless-mlkem768" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:401 +#: htdocs/luci-static/resources/fchomo.js:402 msgid "vless-x25519" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:336 +#: htdocs/luci-static/resources/fchomo.js:337 msgid "xchacha20-ietf-poly1305" msgstr "" @@ -3716,7 +3777,7 @@ msgstr "" msgid "yacd-meta" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1337 +#: htdocs/luci-static/resources/view/fchomo/node.js:1372 msgid "yamux" msgstr "" @@ -3724,10 +3785,10 @@ msgstr "" msgid "zashboard" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:649 msgid "zero" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1251 +#: htdocs/luci-static/resources/fchomo.js:1252 msgid "🡇" msgstr "" diff --git a/luci-app-fchomo/po/zh_Hans/fchomo.po b/luci-app-fchomo/po/zh_Hans/fchomo.po index e344ac3e..34347f97 100644 --- a/luci-app-fchomo/po/zh_Hans/fchomo.po +++ b/luci-app-fchomo/po/zh_Hans/fchomo.po @@ -12,30 +12,30 @@ msgstr "" msgid "%s log" msgstr "%s 日志" -#: htdocs/luci-static/resources/fchomo.js:239 #: htdocs/luci-static/resources/fchomo.js:240 #: htdocs/luci-static/resources/fchomo.js:241 #: htdocs/luci-static/resources/fchomo.js:242 #: htdocs/luci-static/resources/fchomo.js:243 #: htdocs/luci-static/resources/fchomo.js:244 +#: htdocs/luci-static/resources/fchomo.js:245 msgid "%s ports" msgstr "%s 端口" -#: htdocs/luci-static/resources/fchomo.js:604 -#: htdocs/luci-static/resources/fchomo.js:607 +#: htdocs/luci-static/resources/fchomo.js:605 +#: htdocs/luci-static/resources/fchomo.js:608 #: htdocs/luci-static/resources/view/fchomo/client.js:315 msgid "(Imported)" msgstr "(已导入)" -#: htdocs/luci-static/resources/fchomo/listeners.js:858 -#: htdocs/luci-static/resources/fchomo/listeners.js:866 -#: htdocs/luci-static/resources/fchomo/listeners.js:875 +#: htdocs/luci-static/resources/fchomo/listeners.js:947 +#: htdocs/luci-static/resources/fchomo/listeners.js:955 +#: htdocs/luci-static/resources/fchomo/listeners.js:964 #: htdocs/luci-static/resources/view/fchomo/global.js:543 #: htdocs/luci-static/resources/view/fchomo/global.js:549 -#: htdocs/luci-static/resources/view/fchomo/node.js:1059 -#: htdocs/luci-static/resources/view/fchomo/node.js:1065 -#: htdocs/luci-static/resources/view/fchomo/node.js:1073 -#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/view/fchomo/node.js:1094 +#: htdocs/luci-static/resources/view/fchomo/node.js:1100 +#: htdocs/luci-static/resources/view/fchomo/node.js:1108 +#: htdocs/luci-static/resources/view/fchomo/node.js:1114 msgid "(mTLS)" msgstr "" @@ -46,19 +46,19 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1056 #: htdocs/luci-static/resources/view/fchomo/client.js:1057 #: htdocs/luci-static/resources/view/fchomo/client.js:1278 -#: htdocs/luci-static/resources/view/fchomo/node.js:1862 -#: htdocs/luci-static/resources/view/fchomo/node.js:1868 -#: htdocs/luci-static/resources/view/fchomo/node.js:1882 -#: htdocs/luci-static/resources/view/fchomo/node.js:1888 +#: htdocs/luci-static/resources/view/fchomo/node.js:1897 +#: htdocs/luci-static/resources/view/fchomo/node.js:1903 +#: htdocs/luci-static/resources/view/fchomo/node.js:1917 +#: htdocs/luci-static/resources/view/fchomo/node.js:1923 msgid "-- Please choose --" msgstr "-- 请选择 --" -#: htdocs/luci-static/resources/fchomo.js:391 +#: htdocs/luci-static/resources/fchomo.js:392 msgid "0-RTT reuse." msgstr "0-RTT 重用。" -#: htdocs/luci-static/resources/fchomo.js:388 -#: htdocs/luci-static/resources/fchomo.js:392 +#: htdocs/luci-static/resources/fchomo.js:389 +#: htdocs/luci-static/resources/fchomo.js:393 msgid "1-RTT only." msgstr "仅限 1-RTT。" @@ -66,15 +66,15 @@ msgstr "仅限 1-RTT。" msgid "163Music" msgstr "网抑云" -#: htdocs/luci-static/resources/fchomo.js:338 +#: htdocs/luci-static/resources/fchomo.js:339 msgid "2022-blake3-aes-128-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:339 +#: htdocs/luci-static/resources/fchomo.js:340 msgid "2022-blake3-aes-256-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:340 +#: htdocs/luci-static/resources/fchomo.js:341 msgid "2022-blake3-chacha20-poly1305" msgstr "" @@ -82,16 +82,16 @@ msgstr "" msgid "0 or 1 only." msgstr "仅限 01。" -#: htdocs/luci-static/resources/fchomo/listeners.js:836 -#: htdocs/luci-static/resources/fchomo/listeners.js:851 -#: htdocs/luci-static/resources/fchomo/listeners.js:876 -#: htdocs/luci-static/resources/view/fchomo/node.js:1066 -#: htdocs/luci-static/resources/view/fchomo/node.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:925 +#: htdocs/luci-static/resources/fchomo/listeners.js:940 +#: htdocs/luci-static/resources/fchomo/listeners.js:965 +#: htdocs/luci-static/resources/view/fchomo/node.js:1101 +#: htdocs/luci-static/resources/view/fchomo/node.js:1115 msgid "Save your configuration before uploading files!" msgstr "上传文件前请先保存配置!" -#: htdocs/luci-static/resources/fchomo/listeners.js:244 -#: htdocs/luci-static/resources/view/fchomo/node.js:379 +#: htdocs/luci-static/resources/fchomo/listeners.js:275 +#: htdocs/luci-static/resources/view/fchomo/node.js:380 msgid "" "A base64 string is used to fine-tune network behavior.
Please refer to " "the document" msgid "All allowed" msgstr "允许所有" -#: htdocs/luci-static/resources/fchomo.js:236 +#: htdocs/luci-static/resources/fchomo.js:237 msgid "All ports" msgstr "所有端口" @@ -255,7 +255,7 @@ msgid "" msgstr "" "允许从私有网络访问。
要从公共网站访问私有网络上的 API,则必须启用。" -#: htdocs/luci-static/resources/view/fchomo/node.js:768 +#: htdocs/luci-static/resources/view/fchomo/node.js:769 msgid "Allowed IPs" msgstr "允许的 IP" @@ -267,13 +267,13 @@ msgstr "已是最新版本。" msgid "Already in updating." msgstr "已在更新中。" -#: htdocs/luci-static/resources/fchomo/listeners.js:482 -#: htdocs/luci-static/resources/view/fchomo/node.js:638 +#: htdocs/luci-static/resources/fchomo/listeners.js:513 +#: htdocs/luci-static/resources/view/fchomo/node.js:639 msgid "Alter ID" msgstr "额外 ID" #: htdocs/luci-static/resources/fchomo.js:162 -#: htdocs/luci-static/resources/fchomo.js:196 +#: htdocs/luci-static/resources/fchomo.js:197 msgid "AnyTLS" msgstr "" @@ -290,24 +290,24 @@ msgstr "作为 dnsmasq 的最优先上游" msgid "As the TOP upstream of dnsmasq." msgstr "作为 dnsmasq 的最优先上游。" -#: htdocs/luci-static/resources/fchomo/listeners.js:432 +#: htdocs/luci-static/resources/fchomo/listeners.js:463 msgid "Auth timeout" msgstr "认证超时" -#: htdocs/luci-static/resources/view/fchomo/node.js:660 +#: htdocs/luci-static/resources/view/fchomo/node.js:661 msgid "Authenticated length" msgstr "认证长度" -#: htdocs/luci-static/resources/fchomo/listeners.js:397 -#: htdocs/luci-static/resources/fchomo/listeners.js:1030 +#: htdocs/luci-static/resources/fchomo/listeners.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:1119 #: htdocs/luci-static/resources/view/fchomo/global.js:402 -#: htdocs/luci-static/resources/view/fchomo/node.js:459 -#: htdocs/luci-static/resources/view/fchomo/node.js:483 -#: htdocs/luci-static/resources/view/fchomo/node.js:1261 +#: htdocs/luci-static/resources/view/fchomo/node.js:460 +#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:1296 msgid "Auto" msgstr "自动" -#: htdocs/luci-static/resources/fchomo/listeners.js:137 +#: htdocs/luci-static/resources/fchomo/listeners.js:138 msgid "Auto configure firewall" msgstr "自动配置防火墙" @@ -319,8 +319,8 @@ msgstr "自动更新" msgid "Auto update resources." msgstr "自动更新资源文件。" -#: htdocs/luci-static/resources/fchomo/listeners.js:553 -#: htdocs/luci-static/resources/view/fchomo/node.js:865 +#: htdocs/luci-static/resources/fchomo/listeners.js:591 +#: htdocs/luci-static/resources/view/fchomo/node.js:866 msgid "BBR profile" msgstr "BBR 配置文件" @@ -328,11 +328,11 @@ msgstr "BBR 配置文件" msgid "Baidu" msgstr "百度" -#: htdocs/luci-static/resources/view/fchomo/node.js:675 +#: htdocs/luci-static/resources/view/fchomo/node.js:676 msgid "Base64 encoded ECDSA private key on the NIST P-256 curve." msgstr "基于 NIST P-256 曲线的 Base64 编码 ECDSA 私钥。" -#: htdocs/luci-static/resources/view/fchomo/node.js:683 +#: htdocs/luci-static/resources/view/fchomo/node.js:684 msgid "Base64 encoded ECDSA public key on the NIST P-256 curve." msgstr "基于 NIST P-256 曲线的 Base64 编码 ECDSA 公钥。" @@ -354,13 +354,13 @@ msgid "Binary mrs" msgstr "二进制 mrs" #: htdocs/luci-static/resources/view/fchomo/global.js:734 -#: htdocs/luci-static/resources/view/fchomo/node.js:1420 -#: htdocs/luci-static/resources/view/fchomo/node.js:1736 +#: htdocs/luci-static/resources/view/fchomo/node.js:1455 +#: htdocs/luci-static/resources/view/fchomo/node.js:1771 msgid "Bind interface" msgstr "绑定接口" -#: htdocs/luci-static/resources/view/fchomo/node.js:1421 -#: htdocs/luci-static/resources/view/fchomo/node.js:1737 +#: htdocs/luci-static/resources/view/fchomo/node.js:1456 +#: htdocs/luci-static/resources/view/fchomo/node.js:1772 msgid "Bind outbound interface.
" msgstr "绑定出站接口。
" @@ -398,14 +398,14 @@ msgstr "绕过 CN 流量" msgid "Bypass DSCP" msgstr "绕过 DSCP" -#: htdocs/luci-static/resources/fchomo/listeners.js:395 -#: htdocs/luci-static/resources/fchomo/listeners.js:396 -#: htdocs/luci-static/resources/fchomo/listeners.js:397 -#: htdocs/luci-static/resources/fchomo/listeners.js:398 -#: htdocs/luci-static/resources/view/fchomo/node.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:426 +#: htdocs/luci-static/resources/fchomo/listeners.js:427 +#: htdocs/luci-static/resources/fchomo/listeners.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:429 #: htdocs/luci-static/resources/view/fchomo/node.js:458 #: htdocs/luci-static/resources/view/fchomo/node.js:459 #: htdocs/luci-static/resources/view/fchomo/node.js:460 +#: htdocs/luci-static/resources/view/fchomo/node.js:461 msgid "CDN support" msgstr "CDN 支持" @@ -421,21 +421,21 @@ msgstr "CORS 允许私有网络" msgid "CORS allowed origins, * will be used if empty." msgstr "CORS 允许的来源,留空则使用 *。" -#: htdocs/luci-static/resources/fchomo.js:720 +#: htdocs/luci-static/resources/fchomo.js:721 msgid "Cancel" msgstr "取消" -#: htdocs/luci-static/resources/view/fchomo/node.js:1038 +#: htdocs/luci-static/resources/view/fchomo/node.js:1073 msgid "Cert fingerprint" msgstr "证书指纹" -#: htdocs/luci-static/resources/view/fchomo/node.js:1039 +#: htdocs/luci-static/resources/view/fchomo/node.js:1074 msgid "" "Certificate fingerprint. Used to implement SSL Pinning and prevent MitM." msgstr "证书指纹。用于实现 SSL证书固定 并防止 MitM。" -#: htdocs/luci-static/resources/fchomo/listeners.js:828 -#: htdocs/luci-static/resources/view/fchomo/node.js:1059 +#: htdocs/luci-static/resources/fchomo/listeners.js:917 +#: htdocs/luci-static/resources/view/fchomo/node.js:1094 msgid "Certificate path" msgstr "证书路径" @@ -464,16 +464,16 @@ msgstr "大陆 IPv6 库版本" msgid "China list version" msgstr "大陆域名列表版本" -#: htdocs/luci-static/resources/fchomo/listeners.js:213 -#: htdocs/luci-static/resources/fchomo/listeners.js:311 -#: htdocs/luci-static/resources/view/fchomo/node.js:332 -#: htdocs/luci-static/resources/view/fchomo/node.js:391 -#: htdocs/luci-static/resources/view/fchomo/node.js:644 +#: htdocs/luci-static/resources/fchomo/listeners.js:244 +#: htdocs/luci-static/resources/fchomo/listeners.js:342 +#: htdocs/luci-static/resources/view/fchomo/node.js:333 +#: htdocs/luci-static/resources/view/fchomo/node.js:392 +#: htdocs/luci-static/resources/view/fchomo/node.js:645 msgid "Chipher" msgstr "加密方法" -#: htdocs/luci-static/resources/fchomo/listeners.js:320 -#: htdocs/luci-static/resources/view/fchomo/node.js:400 +#: htdocs/luci-static/resources/fchomo/listeners.js:351 +#: htdocs/luci-static/resources/view/fchomo/node.js:401 msgid "Chipher must be enabled if obfuscate downlink is disabled." msgstr "如果下行链路混淆功能被禁用,则必须启用加密。" @@ -489,29 +489,29 @@ msgstr "" "点击
此处下载" "最新的初始包。" -#: htdocs/luci-static/resources/fchomo/listeners.js:651 -#: htdocs/luci-static/resources/fchomo/listeners.js:867 +#: htdocs/luci-static/resources/fchomo/listeners.js:689 +#: htdocs/luci-static/resources/fchomo/listeners.js:956 #: htdocs/luci-static/resources/view/fchomo/global.js:550 -#: htdocs/luci-static/resources/view/fchomo/node.js:928 -#: htdocs/luci-static/resources/view/fchomo/node.js:1060 -#: htdocs/luci-static/resources/view/fchomo/node.js:1074 +#: htdocs/luci-static/resources/view/fchomo/node.js:929 +#: htdocs/luci-static/resources/view/fchomo/node.js:1095 +#: htdocs/luci-static/resources/view/fchomo/node.js:1109 #: root/usr/share/luci/menu.d/luci-app-fchomo.json:22 msgid "Client" msgstr "客户端" -#: htdocs/luci-static/resources/fchomo/listeners.js:866 +#: htdocs/luci-static/resources/fchomo/listeners.js:955 msgid "Client Auth Certificate path" msgstr "客户端认证证书路径" -#: htdocs/luci-static/resources/fchomo/listeners.js:858 +#: htdocs/luci-static/resources/fchomo/listeners.js:947 msgid "Client Auth type" msgstr "客户端认证类型" -#: htdocs/luci-static/resources/view/fchomo/node.js:1105 +#: htdocs/luci-static/resources/view/fchomo/node.js:1140 msgid "Client fingerprint" msgstr "客户端指纹" -#: htdocs/luci-static/resources/fchomo/listeners.js:307 +#: htdocs/luci-static/resources/fchomo/listeners.js:338 msgid "Client key" msgstr "客户端密钥" @@ -523,21 +523,21 @@ msgstr "客户端状态" msgid "Collecting data..." msgstr "收集数据中..." -#: htdocs/luci-static/resources/fchomo.js:237 #: htdocs/luci-static/resources/fchomo.js:238 +#: htdocs/luci-static/resources/fchomo.js:239 msgid "Common ports (bypass P2P traffic)" msgstr "常用端口(绕过 P2P 流量)" -#: htdocs/luci-static/resources/fchomo.js:1367 +#: htdocs/luci-static/resources/fchomo.js:1368 msgid "Complete" msgstr "完成" -#: htdocs/luci-static/resources/view/fchomo/node.js:1680 +#: htdocs/luci-static/resources/view/fchomo/node.js:1715 msgid "Configuration Items" msgstr "配置项" -#: htdocs/luci-static/resources/fchomo/listeners.js:545 -#: htdocs/luci-static/resources/view/fchomo/node.js:857 +#: htdocs/luci-static/resources/fchomo/listeners.js:583 +#: htdocs/luci-static/resources/view/fchomo/node.js:858 msgid "Congestion controller" msgstr "拥塞控制器" @@ -549,19 +549,19 @@ msgstr "连接检查" msgid "Conservative" msgstr "保守" -#: htdocs/luci-static/resources/fchomo.js:589 +#: htdocs/luci-static/resources/fchomo.js:590 msgid "Content copied to clipboard!" msgstr "内容已复制到剪贴板!" #: htdocs/luci-static/resources/view/fchomo/client.js:670 -#: htdocs/luci-static/resources/view/fchomo/node.js:1590 -#: htdocs/luci-static/resources/view/fchomo/node.js:1616 +#: htdocs/luci-static/resources/view/fchomo/node.js:1625 +#: htdocs/luci-static/resources/view/fchomo/node.js:1651 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:339 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:365 msgid "Content will not be verified, Please make sure you enter it correctly." msgstr "内容将不会被验证,请确保输入正确。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1589 +#: htdocs/luci-static/resources/view/fchomo/node.js:1624 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:338 msgid "Contents" msgstr "内容" @@ -570,7 +570,7 @@ msgstr "内容" msgid "Contents have been saved." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:591 +#: htdocs/luci-static/resources/fchomo.js:592 msgid "Copy" msgstr "复制" @@ -586,7 +586,7 @@ msgstr "Cron 表达式" msgid "Custom Direct List" msgstr "自定义直连列表" -#: htdocs/luci-static/resources/view/fchomo/node.js:1651 +#: htdocs/luci-static/resources/view/fchomo/node.js:1686 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:400 msgid "Custom HTTP header." msgstr "自定义 HTTP header。" @@ -595,8 +595,8 @@ msgstr "自定义 HTTP header。" msgid "Custom Proxy List" msgstr "自定义代理列表" -#: htdocs/luci-static/resources/fchomo/listeners.js:335 -#: htdocs/luci-static/resources/view/fchomo/node.js:415 +#: htdocs/luci-static/resources/fchomo/listeners.js:366 +#: htdocs/luci-static/resources/view/fchomo/node.js:416 msgid "Custom byte layout" msgstr "自定义字节布局" @@ -605,7 +605,7 @@ msgid "" "Custom internal hosts. Support yaml or json format." msgstr "自定义内部 hosts。支持 yamljson 格式。" -#: htdocs/luci-static/resources/fchomo.js:185 +#: htdocs/luci-static/resources/fchomo.js:186 msgid "DIRECT" msgstr "" @@ -621,8 +621,8 @@ msgstr " DNS 端口" #: htdocs/luci-static/resources/view/fchomo/client.js:873 #: htdocs/luci-static/resources/view/fchomo/client.js:1428 #: htdocs/luci-static/resources/view/fchomo/client.js:1437 -#: htdocs/luci-static/resources/view/fchomo/node.js:715 -#: htdocs/luci-static/resources/view/fchomo/node.js:798 +#: htdocs/luci-static/resources/view/fchomo/node.js:716 +#: htdocs/luci-static/resources/view/fchomo/node.js:799 msgid "DNS server" msgstr "DNS 服务器" @@ -650,24 +650,24 @@ msgstr "默认 DNS(由 WAN 下发)" msgid "Default DNS server" msgstr "默认 DNS 服务器" -#: htdocs/luci-static/resources/view/fchomo/node.js:769 +#: htdocs/luci-static/resources/view/fchomo/node.js:770 msgid "Destination addresses allowed to be forwarded via Wireguard." msgstr "允许通过 WireGuard 转发的目的地址" -#: htdocs/luci-static/resources/view/fchomo/node.js:1861 +#: htdocs/luci-static/resources/view/fchomo/node.js:1896 msgid "Destination provider" msgstr "落地供应商" -#: htdocs/luci-static/resources/view/fchomo/node.js:1867 +#: htdocs/luci-static/resources/view/fchomo/node.js:1902 msgid "Destination proxy node" msgstr "落地代理节点" -#: htdocs/luci-static/resources/view/fchomo/node.js:227 +#: htdocs/luci-static/resources/view/fchomo/node.js:228 msgid "Dial fields" msgstr "拨号字段" -#: htdocs/luci-static/resources/view/fchomo/node.js:1874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1894 +#: htdocs/luci-static/resources/view/fchomo/node.js:1909 +#: htdocs/luci-static/resources/view/fchomo/node.js:1929 msgid "Different chain head/tail" msgstr "不同的链头/链尾" @@ -687,9 +687,9 @@ msgstr "直连 IPv6 地址" msgid "Direct MAC-s" msgstr "直连 MAC 地址" -#: htdocs/luci-static/resources/fchomo/listeners.js:193 +#: htdocs/luci-static/resources/fchomo/listeners.js:194 #: htdocs/luci-static/resources/view/fchomo/global.js:403 -#: htdocs/luci-static/resources/view/fchomo/node.js:298 +#: htdocs/luci-static/resources/view/fchomo/node.js:299 msgid "Disable" msgstr "禁用" @@ -705,7 +705,7 @@ msgstr "禁用 quic-go 的 通用分段卸载(GSO)" msgid "Disable ICMP Forwarding" msgstr "禁用 ICMP 转发" -#: htdocs/luci-static/resources/view/fchomo/node.js:979 +#: htdocs/luci-static/resources/view/fchomo/node.js:1014 msgid "Disable SNI" msgstr "禁用 SNI" @@ -733,46 +733,46 @@ msgstr "" msgid "Domain" msgstr "域名" -#: htdocs/luci-static/resources/view/fchomo/node.js:980 +#: htdocs/luci-static/resources/view/fchomo/node.js:1015 msgid "Donot send server name in ClientHello." msgstr "不要在 ClientHello 中发送服务器名称。" #: htdocs/luci-static/resources/view/fchomo/client.js:1577 -#: htdocs/luci-static/resources/view/fchomo/node.js:1052 -#: htdocs/luci-static/resources/view/fchomo/node.js:1720 +#: htdocs/luci-static/resources/view/fchomo/node.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1755 msgid "Donot verifying server certificate." msgstr "不验证服务器证书。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1399 +#: htdocs/luci-static/resources/view/fchomo/node.js:1434 msgid "Download bandwidth" msgstr "下载带宽" -#: htdocs/luci-static/resources/view/fchomo/node.js:1400 +#: htdocs/luci-static/resources/view/fchomo/node.js:1435 msgid "Download bandwidth in Mbps." msgstr "下载带宽(单位:Mbps)。" -#: htdocs/luci-static/resources/fchomo.js:1246 +#: htdocs/luci-static/resources/fchomo.js:1247 msgid "Download failed: %s" msgstr "下载失败: %s" -#: htdocs/luci-static/resources/fchomo.js:1244 +#: htdocs/luci-static/resources/fchomo.js:1245 msgid "Download successful." msgstr "下载成功。" -#: htdocs/luci-static/resources/fchomo.js:171 +#: htdocs/luci-static/resources/fchomo.js:172 msgid "Dual stack" msgstr "双栈" -#: htdocs/luci-static/resources/view/fchomo/node.js:1099 +#: htdocs/luci-static/resources/view/fchomo/node.js:1134 msgid "ECH HTTPS record query servername" msgstr "ECH HTTPS 记录查询域名" -#: htdocs/luci-static/resources/fchomo/listeners.js:924 -#: htdocs/luci-static/resources/view/fchomo/node.js:1093 +#: htdocs/luci-static/resources/fchomo/listeners.js:1013 +#: htdocs/luci-static/resources/view/fchomo/node.js:1128 msgid "ECH config" msgstr "ECH 配置" -#: htdocs/luci-static/resources/fchomo/listeners.js:883 +#: htdocs/luci-static/resources/fchomo/listeners.js:972 msgid "ECH key" msgstr "ECH 密钥" @@ -788,11 +788,11 @@ msgstr "" msgid "ETag support" msgstr "ETag 支持" -#: htdocs/luci-static/resources/view/fchomo/node.js:1239 +#: htdocs/luci-static/resources/view/fchomo/node.js:1274 msgid "Early Data first packet length limit." msgstr "前置数据长度阈值" -#: htdocs/luci-static/resources/view/fchomo/node.js:1245 +#: htdocs/luci-static/resources/view/fchomo/node.js:1280 msgid "Early Data header name" msgstr "前置数据标头" @@ -808,16 +808,16 @@ msgstr "编辑节点" msgid "Edit ruleset" msgstr "编辑规则集" -#: htdocs/luci-static/resources/view/fchomo/node.js:1587 +#: htdocs/luci-static/resources/view/fchomo/node.js:1622 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:336 msgid "Editer" msgstr "编辑器" -#: htdocs/luci-static/resources/fchomo.js:382 +#: htdocs/luci-static/resources/fchomo.js:383 msgid "Eliminate encryption header characteristics" msgstr "消除加密头特征" -#: htdocs/luci-static/resources/fchomo/listeners.js:132 +#: htdocs/luci-static/resources/fchomo/listeners.js:133 #: htdocs/luci-static/resources/view/fchomo/client.js:931 #: htdocs/luci-static/resources/view/fchomo/client.js:1024 #: htdocs/luci-static/resources/view/fchomo/client.js:1262 @@ -827,16 +827,16 @@ msgstr "消除加密头特征" #: htdocs/luci-static/resources/view/fchomo/client.js:1780 #: htdocs/luci-static/resources/view/fchomo/global.js:401 #: htdocs/luci-static/resources/view/fchomo/global.js:680 -#: htdocs/luci-static/resources/view/fchomo/node.js:234 -#: htdocs/luci-static/resources/view/fchomo/node.js:1560 -#: htdocs/luci-static/resources/view/fchomo/node.js:1759 -#: htdocs/luci-static/resources/view/fchomo/node.js:1848 +#: htdocs/luci-static/resources/view/fchomo/node.js:235 +#: htdocs/luci-static/resources/view/fchomo/node.js:1595 +#: htdocs/luci-static/resources/view/fchomo/node.js:1794 +#: htdocs/luci-static/resources/view/fchomo/node.js:1883 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:264 #: htdocs/luci-static/resources/view/fchomo/server.js:49 msgid "Enable" msgstr "启用" -#: htdocs/luci-static/resources/view/fchomo/node.js:553 +#: htdocs/luci-static/resources/view/fchomo/node.js:554 msgid "" "Enable 0-RTT QUIC connection handshake on the client side. This is not " "impacting much on the performance, as the protocol is fully multiplexed.
强烈建议禁用此功能,因为它容易受到重放攻击。" -#: htdocs/luci-static/resources/view/fchomo/node.js:552 +#: htdocs/luci-static/resources/view/fchomo/node.js:553 msgid "Enable 0-RTT handshake" msgstr "启用 0-RTT 握手" @@ -857,53 +857,53 @@ msgstr "" "为出站连接启用 IP4P 转换" -#: htdocs/luci-static/resources/view/fchomo/node.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1122 msgid "Enable ECH" msgstr "启用 ECH" -#: htdocs/luci-static/resources/view/fchomo/node.js:1387 +#: htdocs/luci-static/resources/view/fchomo/node.js:1422 msgid "Enable TCP Brutal" msgstr "启用 TCP Brutal" -#: htdocs/luci-static/resources/view/fchomo/node.js:1388 +#: htdocs/luci-static/resources/view/fchomo/node.js:1423 msgid "Enable TCP Brutal congestion control algorithm" msgstr "启用 TCP Brutal 拥塞控制算法。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1376 +#: htdocs/luci-static/resources/view/fchomo/node.js:1411 msgid "Enable multiplexing only for TCP." msgstr "仅为 TCP 启用多路复用。" -#: htdocs/luci-static/resources/fchomo/listeners.js:381 -#: htdocs/luci-static/resources/view/fchomo/node.js:443 +#: htdocs/luci-static/resources/fchomo/listeners.js:412 +#: htdocs/luci-static/resources/view/fchomo/node.js:444 msgid "Enable obfuscate for downlink" msgstr "启用下行链路混淆" -#: htdocs/luci-static/resources/view/fchomo/node.js:1370 +#: htdocs/luci-static/resources/view/fchomo/node.js:1405 msgid "Enable padding" msgstr "启用填充" -#: htdocs/luci-static/resources/view/fchomo/node.js:1381 +#: htdocs/luci-static/resources/view/fchomo/node.js:1416 msgid "Enable statistic" msgstr "启用统计" -#: htdocs/luci-static/resources/view/fchomo/node.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:1702 +#: htdocs/luci-static/resources/view/fchomo/node.js:881 +#: htdocs/luci-static/resources/view/fchomo/node.js:1737 msgid "" "Enable the SUoT protocol, requires server support. Conflict with Multiplex." msgstr "启用 SUoT 协议,需要服务端支持。与多路复用冲突。" -#: htdocs/luci-static/resources/fchomo/listeners.js:199 -#: htdocs/luci-static/resources/view/fchomo/node.js:304 +#: htdocs/luci-static/resources/fchomo/listeners.js:200 +#: htdocs/luci-static/resources/view/fchomo/node.js:305 msgid "" "Enabling obfuscation will make the server incompatible with standard QUIC " "connections, losing the ability to masquerade with HTTP/3." msgstr "启用混淆将使服务器与标准的 QUIC 连接不兼容,失去 HTTP/3 伪装的能力。" -#: htdocs/luci-static/resources/fchomo/listeners.js:614 +#: htdocs/luci-static/resources/fchomo/listeners.js:652 msgid "Encryption method" msgstr "加密方法" -#: htdocs/luci-static/resources/view/fchomo/node.js:682 +#: htdocs/luci-static/resources/view/fchomo/node.js:683 msgid "Endpoint pubkic key" msgstr "端点公钥" @@ -926,7 +926,7 @@ msgid "" "if empty." msgstr "超过此限制将会触发强制健康检查。留空则使用 5。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1817 +#: htdocs/luci-static/resources/view/fchomo/node.js:1852 msgid "Exclude matched node types." msgstr "排除匹配的节点类型。" @@ -939,7 +939,7 @@ msgstr "" "rel=\"noreferrer noopener\">此处。" #: htdocs/luci-static/resources/view/fchomo/client.js:1161 -#: htdocs/luci-static/resources/view/fchomo/node.js:1810 +#: htdocs/luci-static/resources/view/fchomo/node.js:1845 msgid "Exclude nodes that meet keywords or regexps." msgstr "排除匹配关键词或表达式的节点。" @@ -948,66 +948,66 @@ msgid "Expand/Collapse result" msgstr "展开/收起 结果" #: htdocs/luci-static/resources/view/fchomo/client.js:1121 -#: htdocs/luci-static/resources/view/fchomo/node.js:1795 +#: htdocs/luci-static/resources/view/fchomo/node.js:1830 msgid "Expected HTTP code. 204 will be used if empty." msgstr "预期的 HTTP code。留空则使用 204。" #: htdocs/luci-static/resources/view/fchomo/client.js:1123 -#: htdocs/luci-static/resources/view/fchomo/node.js:1797 +#: htdocs/luci-static/resources/view/fchomo/node.js:1832 msgid "Expected status" msgstr "预期状态" -#: htdocs/luci-static/resources/fchomo.js:439 -#: htdocs/luci-static/resources/fchomo.js:442 -#: htdocs/luci-static/resources/fchomo.js:445 -#: htdocs/luci-static/resources/fchomo.js:1384 -#: htdocs/luci-static/resources/fchomo.js:1392 -#: htdocs/luci-static/resources/fchomo.js:1400 -#: htdocs/luci-static/resources/fchomo.js:1423 -#: htdocs/luci-static/resources/fchomo.js:1426 -#: htdocs/luci-static/resources/fchomo.js:1433 -#: htdocs/luci-static/resources/fchomo.js:1449 -#: htdocs/luci-static/resources/fchomo.js:1458 -#: htdocs/luci-static/resources/fchomo.js:1470 -#: htdocs/luci-static/resources/fchomo.js:1473 -#: htdocs/luci-static/resources/fchomo.js:1483 -#: htdocs/luci-static/resources/fchomo.js:1495 -#: htdocs/luci-static/resources/fchomo.js:1498 -#: htdocs/luci-static/resources/fchomo.js:1508 -#: htdocs/luci-static/resources/fchomo.js:1518 -#: htdocs/luci-static/resources/fchomo.js:1553 -#: htdocs/luci-static/resources/fchomo.js:1555 -#: htdocs/luci-static/resources/fchomo.js:1568 -#: htdocs/luci-static/resources/fchomo.js:1574 -#: htdocs/luci-static/resources/fchomo.js:1581 -#: htdocs/luci-static/resources/fchomo.js:1590 -#: htdocs/luci-static/resources/fchomo/listeners.js:320 -#: htdocs/luci-static/resources/fchomo/listeners.js:367 -#: htdocs/luci-static/resources/fchomo/listeners.js:643 -#: htdocs/luci-static/resources/fchomo/listeners.js:674 -#: htdocs/luci-static/resources/fchomo/listeners.js:775 +#: htdocs/luci-static/resources/fchomo.js:440 +#: htdocs/luci-static/resources/fchomo.js:443 +#: htdocs/luci-static/resources/fchomo.js:446 +#: htdocs/luci-static/resources/fchomo.js:1385 +#: htdocs/luci-static/resources/fchomo.js:1393 +#: htdocs/luci-static/resources/fchomo.js:1401 +#: htdocs/luci-static/resources/fchomo.js:1424 +#: htdocs/luci-static/resources/fchomo.js:1427 +#: htdocs/luci-static/resources/fchomo.js:1434 +#: htdocs/luci-static/resources/fchomo.js:1450 +#: htdocs/luci-static/resources/fchomo.js:1459 +#: htdocs/luci-static/resources/fchomo.js:1471 +#: htdocs/luci-static/resources/fchomo.js:1474 +#: htdocs/luci-static/resources/fchomo.js:1484 +#: htdocs/luci-static/resources/fchomo.js:1496 +#: htdocs/luci-static/resources/fchomo.js:1499 +#: htdocs/luci-static/resources/fchomo.js:1509 +#: htdocs/luci-static/resources/fchomo.js:1519 +#: htdocs/luci-static/resources/fchomo.js:1554 +#: htdocs/luci-static/resources/fchomo.js:1556 +#: htdocs/luci-static/resources/fchomo.js:1569 +#: htdocs/luci-static/resources/fchomo.js:1575 +#: htdocs/luci-static/resources/fchomo.js:1582 +#: htdocs/luci-static/resources/fchomo.js:1591 +#: htdocs/luci-static/resources/fchomo/listeners.js:351 +#: htdocs/luci-static/resources/fchomo/listeners.js:398 +#: htdocs/luci-static/resources/fchomo/listeners.js:681 +#: htdocs/luci-static/resources/fchomo/listeners.js:712 +#: htdocs/luci-static/resources/fchomo/listeners.js:813 #: htdocs/luci-static/resources/view/fchomo/client.js:68 #: htdocs/luci-static/resources/view/fchomo/client.js:1018 #: htdocs/luci-static/resources/view/fchomo/client.js:1508 #: htdocs/luci-static/resources/view/fchomo/global.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:400 -#: htdocs/luci-static/resources/view/fchomo/node.js:436 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:491 -#: htdocs/luci-static/resources/view/fchomo/node.js:951 -#: htdocs/luci-static/resources/view/fchomo/node.js:1044 -#: htdocs/luci-static/resources/view/fchomo/node.js:1874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1894 +#: htdocs/luci-static/resources/view/fchomo/node.js:401 +#: htdocs/luci-static/resources/view/fchomo/node.js:437 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 +#: htdocs/luci-static/resources/view/fchomo/node.js:952 +#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/view/fchomo/node.js:1909 +#: htdocs/luci-static/resources/view/fchomo/node.js:1929 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:291 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:305 msgid "Expecting: %s" msgstr "请输入:%s" -#: htdocs/luci-static/resources/fchomo/listeners.js:991 -#: htdocs/luci-static/resources/fchomo/listeners.js:998 -#: htdocs/luci-static/resources/view/fchomo/node.js:1154 -#: htdocs/luci-static/resources/view/fchomo/node.js:1161 -#: htdocs/luci-static/resources/view/fchomo/node.js:1169 +#: htdocs/luci-static/resources/fchomo/listeners.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1189 +#: htdocs/luci-static/resources/view/fchomo/node.js:1196 +#: htdocs/luci-static/resources/view/fchomo/node.js:1204 msgid "Expecting: only support %s." msgstr "请输入:仅支援 %s." @@ -1026,24 +1026,24 @@ msgstr "实验性" msgid "Factor" msgstr "条件" -#: htdocs/luci-static/resources/fchomo.js:1325 +#: htdocs/luci-static/resources/fchomo.js:1326 msgid "Failed to execute \"/etc/init.d/fchomo %s %s\" reason: %s" msgstr "无法执行 \"/etc/init.d/fchomo %s %s\" 原因: %s" -#: htdocs/luci-static/resources/fchomo.js:1278 +#: htdocs/luci-static/resources/fchomo.js:1279 msgid "Failed to generate %s, error: %s." msgstr "生成 %s 失败,错误:%s。" -#: htdocs/luci-static/resources/fchomo.js:1690 +#: htdocs/luci-static/resources/fchomo.js:1691 msgid "Failed to upload %s, error: %s." msgstr "上传 %s 失败,错误:%s。" -#: htdocs/luci-static/resources/fchomo.js:1709 +#: htdocs/luci-static/resources/fchomo.js:1710 msgid "Failed to upload, error: %s." msgstr "上传失败,错误:%s。" -#: htdocs/luci-static/resources/fchomo.js:229 -#: htdocs/luci-static/resources/fchomo/listeners.js:406 +#: htdocs/luci-static/resources/fchomo.js:230 +#: htdocs/luci-static/resources/fchomo/listeners.js:437 msgid "Fallback" msgstr "自动回退" @@ -1057,7 +1057,7 @@ msgid "Fallback filter" msgstr "後備过滤器" #: htdocs/luci-static/resources/view/fchomo/client.js:1156 -#: htdocs/luci-static/resources/view/fchomo/node.js:1804 +#: htdocs/luci-static/resources/view/fchomo/node.js:1839 msgid "Filter nodes that meet keywords or regexps." msgstr "过滤匹配关键字或表达式的节点。" @@ -1082,12 +1082,12 @@ msgstr "兜底 DNS 服务器 (用于未被投毒污染的域名)" msgid "Final DNS server (For poisoned domains)" msgstr "兜底 DNS 服务器 (用于已被投毒污染的域名)" -#: htdocs/luci-static/resources/fchomo/listeners.js:136 +#: htdocs/luci-static/resources/fchomo/listeners.js:137 msgid "Firewall" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:474 -#: htdocs/luci-static/resources/view/fchomo/node.js:630 +#: htdocs/luci-static/resources/fchomo/listeners.js:505 +#: htdocs/luci-static/resources/view/fchomo/node.js:631 msgid "Flow" msgstr "流控" @@ -1100,8 +1100,8 @@ msgstr "" "noopener\">%s." #: htdocs/luci-static/resources/view/fchomo/client.js:1122 -#: htdocs/luci-static/resources/view/fchomo/node.js:1670 -#: htdocs/luci-static/resources/view/fchomo/node.js:1796 +#: htdocs/luci-static/resources/view/fchomo/node.js:1705 +#: htdocs/luci-static/resources/view/fchomo/node.js:1831 msgid "" "For format see %s." @@ -1109,8 +1109,8 @@ msgstr "" "格式请参阅 %s." -#: htdocs/luci-static/resources/view/fchomo/node.js:710 -#: htdocs/luci-static/resources/view/fchomo/node.js:793 +#: htdocs/luci-static/resources/view/fchomo/node.js:711 +#: htdocs/luci-static/resources/view/fchomo/node.js:794 msgid "Force DNS remote resolution." msgstr "强制 DNS 远程解析。" @@ -1129,7 +1129,7 @@ msgstr "格式" msgid "FullCombo Shark!" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1194 +#: htdocs/luci-static/resources/view/fchomo/node.js:1229 msgid "GET" msgstr "" @@ -1144,7 +1144,7 @@ msgstr "常规" #: htdocs/luci-static/resources/fchomo/listeners.js:119 #: htdocs/luci-static/resources/view/fchomo/client.js:1009 #: htdocs/luci-static/resources/view/fchomo/node.js:222 -#: htdocs/luci-static/resources/view/fchomo/node.js:1550 +#: htdocs/luci-static/resources/view/fchomo/node.js:1585 msgid "General fields" msgstr "常规字段" @@ -1152,15 +1152,15 @@ msgstr "常规字段" msgid "General settings" msgstr "常规设置" -#: htdocs/luci-static/resources/fchomo.js:540 -#: htdocs/luci-static/resources/fchomo.js:542 -#: htdocs/luci-static/resources/fchomo.js:556 -#: htdocs/luci-static/resources/fchomo.js:558 -#: htdocs/luci-static/resources/fchomo/listeners.js:298 -#: htdocs/luci-static/resources/fchomo/listeners.js:342 -#: htdocs/luci-static/resources/fchomo/listeners.js:344 -#: htdocs/luci-static/resources/fchomo/listeners.js:747 -#: htdocs/luci-static/resources/fchomo/listeners.js:916 +#: htdocs/luci-static/resources/fchomo.js:541 +#: htdocs/luci-static/resources/fchomo.js:543 +#: htdocs/luci-static/resources/fchomo.js:557 +#: htdocs/luci-static/resources/fchomo.js:559 +#: htdocs/luci-static/resources/fchomo/listeners.js:329 +#: htdocs/luci-static/resources/fchomo/listeners.js:373 +#: htdocs/luci-static/resources/fchomo/listeners.js:375 +#: htdocs/luci-static/resources/fchomo/listeners.js:785 +#: htdocs/luci-static/resources/fchomo/listeners.js:1005 #: htdocs/luci-static/resources/view/fchomo/global.js:587 msgid "Generate" msgstr "生成" @@ -1204,7 +1204,7 @@ msgstr "全局" msgid "Global Authentication" msgstr "全局认证" -#: htdocs/luci-static/resources/view/fchomo/node.js:654 +#: htdocs/luci-static/resources/view/fchomo/node.js:655 msgid "Global padding" msgstr "全局填充" @@ -1212,7 +1212,7 @@ msgstr "全局填充" msgid "Google" msgstr "谷歌" -#: htdocs/luci-static/resources/fchomo.js:242 +#: htdocs/luci-static/resources/fchomo.js:243 msgid "Google FCM" msgstr "谷歌 FCM" @@ -1225,48 +1225,49 @@ msgid "Group" msgstr "组" #: htdocs/luci-static/resources/fchomo.js:153 -#: htdocs/luci-static/resources/fchomo.js:186 -#: htdocs/luci-static/resources/view/fchomo/node.js:816 -#: htdocs/luci-static/resources/view/fchomo/node.js:1143 -#: htdocs/luci-static/resources/view/fchomo/node.js:1154 -#: htdocs/luci-static/resources/view/fchomo/node.js:1161 +#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo/listeners.js:539 +#: htdocs/luci-static/resources/view/fchomo/node.js:817 +#: htdocs/luci-static/resources/view/fchomo/node.js:1178 +#: htdocs/luci-static/resources/view/fchomo/node.js:1189 +#: htdocs/luci-static/resources/view/fchomo/node.js:1196 msgid "HTTP" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:267 -#: htdocs/luci-static/resources/view/fchomo/node.js:1216 -#: htdocs/luci-static/resources/view/fchomo/node.js:1650 +#: htdocs/luci-static/resources/view/fchomo/node.js:268 +#: htdocs/luci-static/resources/view/fchomo/node.js:1251 +#: htdocs/luci-static/resources/view/fchomo/node.js:1685 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:399 msgid "HTTP header" msgstr "HTTP header" -#: htdocs/luci-static/resources/fchomo/listeners.js:387 -#: htdocs/luci-static/resources/view/fchomo/node.js:449 +#: htdocs/luci-static/resources/fchomo/listeners.js:418 +#: htdocs/luci-static/resources/view/fchomo/node.js:450 msgid "HTTP mask" msgstr "HTTP 伪装" -#: htdocs/luci-static/resources/fchomo/listeners.js:392 -#: htdocs/luci-static/resources/view/fchomo/node.js:454 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/fchomo/listeners.js:423 +#: htdocs/luci-static/resources/view/fchomo/node.js:455 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "HTTP mask mode" msgstr "HTTP 伪装模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:479 +#: htdocs/luci-static/resources/view/fchomo/node.js:480 msgid "HTTP mask multiplex" msgstr "HTTP 伪装多路复用" -#: htdocs/luci-static/resources/view/fchomo/node.js:464 -#: htdocs/luci-static/resources/view/fchomo/node.js:469 +#: htdocs/luci-static/resources/view/fchomo/node.js:465 +#: htdocs/luci-static/resources/view/fchomo/node.js:470 msgid "HTTP mask: %s" msgstr "HTTP 伪装: %s" -#: htdocs/luci-static/resources/view/fchomo/node.js:1193 +#: htdocs/luci-static/resources/view/fchomo/node.js:1228 msgid "HTTP request method" msgstr "HTTP 请求方法" -#: htdocs/luci-static/resources/fchomo/listeners.js:402 -#: htdocs/luci-static/resources/view/fchomo/node.js:475 +#: htdocs/luci-static/resources/fchomo/listeners.js:433 +#: htdocs/luci-static/resources/view/fchomo/node.js:476 msgid "HTTP root path" msgstr "HTTP 根路径" @@ -1274,15 +1275,15 @@ msgstr "HTTP 根路径" msgid "HTTP/3" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:207 +#: htdocs/luci-static/resources/fchomo/listeners.js:208 msgid "" "HTTP3 server behavior when authentication fails.
A 404 page will be " "returned if empty." msgstr "身份验证失败时的 HTTP3 服务器响应。默认返回 404 页面。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1144 -#: htdocs/luci-static/resources/view/fchomo/node.js:1155 -#: htdocs/luci-static/resources/view/fchomo/node.js:1162 +#: htdocs/luci-static/resources/view/fchomo/node.js:1179 +#: htdocs/luci-static/resources/view/fchomo/node.js:1190 +#: htdocs/luci-static/resources/view/fchomo/node.js:1197 msgid "HTTPUpgrade" msgstr "" @@ -1290,48 +1291,52 @@ msgstr "" msgid "Handle domain" msgstr "处理域名" -#: htdocs/luci-static/resources/view/fchomo/node.js:371 +#: htdocs/luci-static/resources/view/fchomo/node.js:372 msgid "Handshake mode" msgstr "握手模式" -#: htdocs/luci-static/resources/fchomo/listeners.js:506 +#: htdocs/luci-static/resources/fchomo/listeners.js:544 msgid "Handshake target that supports TLS 1.3" msgstr "握手目标 (支援 TLS 1.3)" -#: htdocs/luci-static/resources/fchomo/listeners.js:374 +#: htdocs/luci-static/resources/fchomo/listeners.js:405 msgid "Handshake timeout" msgstr "握手超时" -#: htdocs/luci-static/resources/view/fchomo/node.js:721 +#: htdocs/luci-static/resources/fchomo/listeners.js:233 +msgid "Header to read real client IP from (e.g. X-Forwarded-For)" +msgstr "" + +#: htdocs/luci-static/resources/view/fchomo/node.js:722 msgid "Health check" msgstr "健康检查" #: htdocs/luci-static/resources/view/fchomo/client.js:1091 -#: htdocs/luci-static/resources/view/fchomo/node.js:1764 +#: htdocs/luci-static/resources/view/fchomo/node.js:1799 msgid "Health check URL" msgstr "健康检查 URL" #: htdocs/luci-static/resources/view/fchomo/client.js:1120 -#: htdocs/luci-static/resources/view/fchomo/node.js:1794 +#: htdocs/luci-static/resources/view/fchomo/node.js:1829 msgid "Health check expected status" msgstr "健康检查预期状态" #: htdocs/luci-static/resources/view/fchomo/client.js:1100 -#: htdocs/luci-static/resources/view/fchomo/node.js:1774 +#: htdocs/luci-static/resources/view/fchomo/node.js:1809 msgid "Health check interval" msgstr "健康检查间隔" #: htdocs/luci-static/resources/view/fchomo/client.js:1107 -#: htdocs/luci-static/resources/view/fchomo/node.js:1781 +#: htdocs/luci-static/resources/view/fchomo/node.js:1816 msgid "Health check timeout" msgstr "健康检查超时" #: htdocs/luci-static/resources/view/fchomo/client.js:1011 -#: htdocs/luci-static/resources/view/fchomo/node.js:1552 +#: htdocs/luci-static/resources/view/fchomo/node.js:1587 msgid "Health fields" msgstr "健康字段" -#: htdocs/luci-static/resources/view/fchomo/node.js:559 +#: htdocs/luci-static/resources/view/fchomo/node.js:560 msgid "Heartbeat interval" msgstr "心跳间隔" @@ -1339,19 +1344,19 @@ msgstr "心跳间隔" msgid "Hidden" msgstr "隐藏" -#: htdocs/luci-static/resources/view/fchomo/node.js:822 +#: htdocs/luci-static/resources/view/fchomo/node.js:823 msgid "Host that supports TLS 1.3" msgstr "主机名称 (支援 TLS 1.3)" -#: htdocs/luci-static/resources/view/fchomo/node.js:326 +#: htdocs/luci-static/resources/view/fchomo/node.js:327 msgid "Host-key" msgstr "主机密钥" -#: htdocs/luci-static/resources/view/fchomo/node.js:321 +#: htdocs/luci-static/resources/view/fchomo/node.js:322 msgid "Host-key algorithms" msgstr "主机密钥算法" -#: htdocs/luci-static/resources/view/fchomo/node.js:469 +#: htdocs/luci-static/resources/view/fchomo/node.js:470 msgid "Host/SNI override" msgstr "主机/SNI 覆盖" @@ -1361,10 +1366,19 @@ msgid "Hosts" msgstr "" #: htdocs/luci-static/resources/fchomo.js:164 -#: htdocs/luci-static/resources/fchomo.js:198 +#: htdocs/luci-static/resources/fchomo.js:199 msgid "Hysteria2" msgstr "" +#: htdocs/luci-static/resources/fchomo.js:165 +msgid "Hysteria2 Realm" +msgstr "Hysteria2 Realm" + +#: htdocs/luci-static/resources/fchomo/listeners.js:121 +#: htdocs/luci-static/resources/view/fchomo/node.js:224 +msgid "Hysteria2 Realm fields" +msgstr "Hysteria2 Realm 字段" + #: htdocs/luci-static/resources/view/fchomo/client.js:1806 #: htdocs/luci-static/resources/view/fchomo/client.js:1819 msgid "IP" @@ -1374,20 +1388,20 @@ msgstr "" msgid "IP CIDR" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:521 +#: htdocs/luci-static/resources/view/fchomo/node.js:522 msgid "IP override" msgstr "IP 覆写" -#: htdocs/luci-static/resources/view/fchomo/node.js:1432 -#: htdocs/luci-static/resources/view/fchomo/node.js:1750 +#: htdocs/luci-static/resources/view/fchomo/node.js:1467 +#: htdocs/luci-static/resources/view/fchomo/node.js:1785 msgid "IP version" msgstr "IP 版本" -#: htdocs/luci-static/resources/fchomo.js:172 +#: htdocs/luci-static/resources/fchomo.js:173 msgid "IPv4 only" msgstr "仅 IPv4" -#: htdocs/luci-static/resources/fchomo.js:173 +#: htdocs/luci-static/resources/fchomo.js:174 msgid "IPv6 only" msgstr "仅 IPv6" @@ -1400,19 +1414,19 @@ msgstr "IPv6 支持" msgid "Icon" msgstr "图标" -#: htdocs/luci-static/resources/view/fchomo/node.js:603 +#: htdocs/luci-static/resources/view/fchomo/node.js:604 msgid "Idle session check interval" msgstr "闲置会话检查间隔" -#: htdocs/luci-static/resources/view/fchomo/node.js:610 +#: htdocs/luci-static/resources/view/fchomo/node.js:611 msgid "Idle session timeout" msgstr "闲置会话超时" -#: htdocs/luci-static/resources/fchomo/listeners.js:425 +#: htdocs/luci-static/resources/fchomo/listeners.js:456 msgid "Idle timeout" msgstr "闲置超时" -#: htdocs/luci-static/resources/fchomo.js:1426 +#: htdocs/luci-static/resources/fchomo.js:1427 msgid "If All ports is selected, uncheck others" msgstr "如果选择了“所有端口”,则取消选中“其他”" @@ -1420,11 +1434,11 @@ msgstr "如果选择了“所有端口”,则取消选中“其他”" msgid "If Block is selected, uncheck others" msgstr "如果选择了“阻止”,则取消选中“其他”" -#: htdocs/luci-static/resources/fchomo/listeners.js:186 +#: htdocs/luci-static/resources/fchomo/listeners.js:187 msgid "Ignore client bandwidth" msgstr "忽略客户端带宽" -#: htdocs/luci-static/resources/fchomo.js:725 +#: htdocs/luci-static/resources/fchomo.js:726 msgid "Import" msgstr "导入" @@ -1440,8 +1454,8 @@ msgstr "导入" #: htdocs/luci-static/resources/view/fchomo/client.js:1713 #: htdocs/luci-static/resources/view/fchomo/client.js:1748 #: htdocs/luci-static/resources/view/fchomo/client.js:1769 -#: htdocs/luci-static/resources/view/fchomo/node.js:1457 -#: htdocs/luci-static/resources/view/fchomo/node.js:1538 +#: htdocs/luci-static/resources/view/fchomo/node.js:1492 +#: htdocs/luci-static/resources/view/fchomo/node.js:1573 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:153 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:241 msgid "Import mihomo config" @@ -1453,41 +1467,41 @@ msgstr "导入 mihomo 配置" msgid "Import rule-set links" msgstr "导入规则集链接" -#: htdocs/luci-static/resources/fchomo/listeners.js:175 -#: htdocs/luci-static/resources/fchomo/listeners.js:181 -#: htdocs/luci-static/resources/view/fchomo/node.js:286 -#: htdocs/luci-static/resources/view/fchomo/node.js:292 -#: htdocs/luci-static/resources/view/fchomo/node.js:1708 -#: htdocs/luci-static/resources/view/fchomo/node.js:1714 +#: htdocs/luci-static/resources/fchomo/listeners.js:176 +#: htdocs/luci-static/resources/fchomo/listeners.js:182 +#: htdocs/luci-static/resources/view/fchomo/node.js:287 +#: htdocs/luci-static/resources/view/fchomo/node.js:293 +#: htdocs/luci-static/resources/view/fchomo/node.js:1743 +#: htdocs/luci-static/resources/view/fchomo/node.js:1749 msgid "In Mbps." msgstr "单位为 Mbps。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1628 +#: htdocs/luci-static/resources/view/fchomo/node.js:1663 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:377 msgid "In bytes. %s will be used if empty." msgstr "单位为字节。留空则使用 %s。" -#: htdocs/luci-static/resources/view/fchomo/node.js:560 -#: htdocs/luci-static/resources/view/fchomo/node.js:567 +#: htdocs/luci-static/resources/view/fchomo/node.js:561 +#: htdocs/luci-static/resources/view/fchomo/node.js:568 msgid "In millisecond." msgstr "单位为毫秒。" #: htdocs/luci-static/resources/view/fchomo/client.js:1108 #: htdocs/luci-static/resources/view/fchomo/client.js:1137 -#: htdocs/luci-static/resources/view/fchomo/node.js:1782 +#: htdocs/luci-static/resources/view/fchomo/node.js:1817 msgid "In millisecond. %s will be used if empty." msgstr "单位为毫秒。留空则使用 %s。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1285 +#: htdocs/luci-static/resources/view/fchomo/node.js:1320 msgid "In milliseconds." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:375 -#: htdocs/luci-static/resources/fchomo/listeners.js:426 -#: htdocs/luci-static/resources/fchomo/listeners.js:433 -#: htdocs/luci-static/resources/view/fchomo/node.js:604 -#: htdocs/luci-static/resources/view/fchomo/node.js:611 -#: htdocs/luci-static/resources/view/fchomo/node.js:1232 +#: htdocs/luci-static/resources/fchomo/listeners.js:406 +#: htdocs/luci-static/resources/fchomo/listeners.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:464 +#: htdocs/luci-static/resources/view/fchomo/node.js:605 +#: htdocs/luci-static/resources/view/fchomo/node.js:612 +#: htdocs/luci-static/resources/view/fchomo/node.js:1267 msgid "In seconds." msgstr "单位为秒。" @@ -1495,15 +1509,15 @@ msgstr "单位为秒。" #: htdocs/luci-static/resources/view/fchomo/global.js:425 #: htdocs/luci-static/resources/view/fchomo/global.js:430 #: htdocs/luci-static/resources/view/fchomo/global.js:515 -#: htdocs/luci-static/resources/view/fchomo/node.js:280 -#: htdocs/luci-static/resources/view/fchomo/node.js:1634 -#: htdocs/luci-static/resources/view/fchomo/node.js:1775 +#: htdocs/luci-static/resources/view/fchomo/node.js:281 +#: htdocs/luci-static/resources/view/fchomo/node.js:1669 +#: htdocs/luci-static/resources/view/fchomo/node.js:1810 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:383 msgid "In seconds. %s will be used if empty." msgstr "单位为秒。留空则使用 %s。" -#: htdocs/luci-static/resources/fchomo/listeners.js:663 -#: htdocs/luci-static/resources/view/fchomo/node.js:940 +#: htdocs/luci-static/resources/fchomo/listeners.js:701 +#: htdocs/luci-static/resources/view/fchomo/node.js:941 msgid "" "In the order of one Padding-Length and one Padding-" "Interval, infinite concatenation." @@ -1545,7 +1559,7 @@ msgstr "引入所有代理节点。" msgid "Info" msgstr "信息" -#: htdocs/luci-static/resources/view/fchomo/node.js:1567 +#: htdocs/luci-static/resources/view/fchomo/node.js:1602 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:279 msgid "Inline" msgstr "内嵌" @@ -1556,55 +1570,55 @@ msgstr "接口控制" #: htdocs/luci-static/resources/fchomo.js:52 #: htdocs/luci-static/resources/fchomo.js:59 -#: htdocs/luci-static/resources/fchomo.js:170 -#: htdocs/luci-static/resources/fchomo.js:364 -#: htdocs/luci-static/resources/view/fchomo/node.js:1724 +#: htdocs/luci-static/resources/fchomo.js:171 +#: htdocs/luci-static/resources/fchomo.js:365 +#: htdocs/luci-static/resources/view/fchomo/node.js:1759 msgid "Keep default" msgstr "保持缺省" -#: htdocs/luci-static/resources/view/fchomo/node.js:1321 +#: htdocs/luci-static/resources/view/fchomo/node.js:1356 msgid "Keep-alive period" msgstr "Keep-alive 周期" -#: htdocs/luci-static/resources/fchomo/listeners.js:254 -#: htdocs/luci-static/resources/view/fchomo/node.js:385 +#: htdocs/luci-static/resources/fchomo/listeners.js:285 +#: htdocs/luci-static/resources/view/fchomo/node.js:386 msgid "Key" msgstr "密钥" -#: htdocs/luci-static/resources/fchomo/listeners.js:843 -#: htdocs/luci-static/resources/view/fchomo/node.js:1073 +#: htdocs/luci-static/resources/fchomo/listeners.js:932 +#: htdocs/luci-static/resources/view/fchomo/node.js:1108 msgid "Key path" msgstr "证书路径" -#: htdocs/luci-static/resources/fchomo/listeners.js:682 +#: htdocs/luci-static/resources/fchomo/listeners.js:720 msgid "Keypairs" msgstr "密钥对" -#: htdocs/luci-static/resources/fchomo/listeners.js:127 +#: htdocs/luci-static/resources/fchomo/listeners.js:128 #: htdocs/luci-static/resources/view/fchomo/client.js:1014 #: htdocs/luci-static/resources/view/fchomo/client.js:1257 #: htdocs/luci-static/resources/view/fchomo/client.js:1349 #: htdocs/luci-static/resources/view/fchomo/client.js:1488 #: htdocs/luci-static/resources/view/fchomo/client.js:1719 #: htdocs/luci-static/resources/view/fchomo/client.js:1775 -#: htdocs/luci-static/resources/view/fchomo/node.js:229 -#: htdocs/luci-static/resources/view/fchomo/node.js:1555 -#: htdocs/luci-static/resources/view/fchomo/node.js:1843 +#: htdocs/luci-static/resources/view/fchomo/node.js:230 +#: htdocs/luci-static/resources/view/fchomo/node.js:1590 +#: htdocs/luci-static/resources/view/fchomo/node.js:1878 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:259 msgid "Label" msgstr "标签" #: htdocs/luci-static/resources/view/fchomo/client.js:1114 -#: htdocs/luci-static/resources/view/fchomo/node.js:1788 +#: htdocs/luci-static/resources/view/fchomo/node.js:1823 msgid "Lazy" msgstr "懒惰状态" -#: htdocs/luci-static/resources/fchomo/listeners.js:394 -#: htdocs/luci-static/resources/view/fchomo/node.js:456 +#: htdocs/luci-static/resources/fchomo/listeners.js:425 +#: htdocs/luci-static/resources/view/fchomo/node.js:457 msgid "Legacy" msgstr "传统" -#: htdocs/luci-static/resources/fchomo/listeners.js:483 +#: htdocs/luci-static/resources/fchomo/listeners.js:514 msgid "" "Legacy protocol support (VMess MD5 Authentication) is provided for " "compatibility purposes only, use of alterId > 1 is not recommended." @@ -1616,16 +1630,16 @@ msgstr "" msgid "Less compatibility and sometimes better performance." msgstr "有时性能更好。" -#: htdocs/luci-static/resources/fchomo/listeners.js:824 -#: htdocs/luci-static/resources/view/fchomo/node.js:992 +#: htdocs/luci-static/resources/fchomo/listeners.js:913 +#: htdocs/luci-static/resources/view/fchomo/node.js:1027 msgid "List of supported application level protocols, in order of preference." msgstr "支持的应用层协议协商列表,按顺序排列。" -#: htdocs/luci-static/resources/fchomo/listeners.js:147 +#: htdocs/luci-static/resources/fchomo/listeners.js:148 msgid "Listen address" msgstr "监听地址" -#: htdocs/luci-static/resources/fchomo/listeners.js:124 +#: htdocs/luci-static/resources/fchomo/listeners.js:125 msgid "Listen fields" msgstr "监听字段" @@ -1633,7 +1647,7 @@ msgstr "监听字段" msgid "Listen interfaces" msgstr "监听接口" -#: htdocs/luci-static/resources/fchomo/listeners.js:152 +#: htdocs/luci-static/resources/fchomo/listeners.js:153 #: htdocs/luci-static/resources/view/fchomo/client.js:1374 msgid "Listen port" msgstr "监听端口" @@ -1642,22 +1656,22 @@ msgstr "监听端口" msgid "Listen ports" msgstr "监听端口" -#: htdocs/luci-static/resources/fchomo.js:231 +#: htdocs/luci-static/resources/fchomo.js:232 msgid "Load balance" msgstr "负载均衡" -#: htdocs/luci-static/resources/view/fchomo/node.js:1565 +#: htdocs/luci-static/resources/view/fchomo/node.js:1600 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:277 msgid "Local" msgstr "本地" -#: htdocs/luci-static/resources/view/fchomo/node.js:697 -#: htdocs/luci-static/resources/view/fchomo/node.js:740 +#: htdocs/luci-static/resources/view/fchomo/node.js:698 +#: htdocs/luci-static/resources/view/fchomo/node.js:741 msgid "Local IPv6 address" msgstr "本地 IPv6 地址" -#: htdocs/luci-static/resources/view/fchomo/node.js:689 -#: htdocs/luci-static/resources/view/fchomo/node.js:732 +#: htdocs/luci-static/resources/view/fchomo/node.js:690 +#: htdocs/luci-static/resources/view/fchomo/node.js:733 msgid "Local address" msgstr "本地地址" @@ -1677,32 +1691,32 @@ msgstr "日志为空。" msgid "Log level" msgstr "日志等级" -#: htdocs/luci-static/resources/fchomo/listeners.js:329 -#: htdocs/luci-static/resources/fchomo/listeners.js:330 -#: htdocs/luci-static/resources/fchomo/listeners.js:331 -#: htdocs/luci-static/resources/fchomo/listeners.js:336 -#: htdocs/luci-static/resources/view/fchomo/node.js:409 +#: htdocs/luci-static/resources/fchomo/listeners.js:360 +#: htdocs/luci-static/resources/fchomo/listeners.js:361 +#: htdocs/luci-static/resources/fchomo/listeners.js:362 +#: htdocs/luci-static/resources/fchomo/listeners.js:367 #: htdocs/luci-static/resources/view/fchomo/node.js:410 #: htdocs/luci-static/resources/view/fchomo/node.js:411 -#: htdocs/luci-static/resources/view/fchomo/node.js:416 +#: htdocs/luci-static/resources/view/fchomo/node.js:412 +#: htdocs/luci-static/resources/view/fchomo/node.js:417 msgid "Low-entropy data stream" msgstr "低熵数据流" -#: htdocs/luci-static/resources/fchomo.js:439 +#: htdocs/luci-static/resources/fchomo.js:440 msgid "Lowercase only" msgstr "仅限小写" #: htdocs/luci-static/resources/view/fchomo/global.js:502 -#: htdocs/luci-static/resources/view/fchomo/node.js:703 -#: htdocs/luci-static/resources/view/fchomo/node.js:786 +#: htdocs/luci-static/resources/view/fchomo/node.js:704 +#: htdocs/luci-static/resources/view/fchomo/node.js:787 msgid "MTU" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:200 +#: htdocs/luci-static/resources/fchomo.js:201 msgid "Masque" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:206 +#: htdocs/luci-static/resources/fchomo/listeners.js:207 msgid "Masquerade" msgstr "伪装" @@ -1734,24 +1748,24 @@ msgstr "匹配响应通过 ipcidr
" msgid "Match rule set." msgstr "匹配规则集。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1238 +#: htdocs/luci-static/resources/view/fchomo/node.js:1273 msgid "Max Early Data" msgstr "前置数据最大值" -#: htdocs/luci-static/resources/fchomo/listeners.js:419 -#: htdocs/luci-static/resources/view/fchomo/node.js:546 +#: htdocs/luci-static/resources/fchomo/listeners.js:450 +#: htdocs/luci-static/resources/view/fchomo/node.js:547 msgid "Max UDP relay packet size" msgstr "UDP 中继数据包最大尺寸" -#: htdocs/luci-static/resources/fchomo/listeners.js:1042 +#: htdocs/luci-static/resources/fchomo/listeners.js:1131 msgid "Max buffered posts" msgstr "POST 最大缓冲" -#: htdocs/luci-static/resources/view/fchomo/node.js:1296 +#: htdocs/luci-static/resources/view/fchomo/node.js:1331 msgid "Max concurrency" msgstr "最大并发" -#: htdocs/luci-static/resources/view/fchomo/node.js:1301 +#: htdocs/luci-static/resources/view/fchomo/node.js:1336 msgid "Max connections" msgstr "最大连接数" @@ -1759,43 +1773,51 @@ msgstr "最大连接数" msgid "Max count of failures" msgstr "最大失败次数" -#: htdocs/luci-static/resources/fchomo/listeners.js:180 -#: htdocs/luci-static/resources/view/fchomo/node.js:291 +#: htdocs/luci-static/resources/fchomo/listeners.js:181 +#: htdocs/luci-static/resources/view/fchomo/node.js:292 msgid "Max download speed" msgstr "最大下载速度" -#: htdocs/luci-static/resources/fchomo/listeners.js:1053 -#: htdocs/luci-static/resources/view/fchomo/node.js:1278 +#: htdocs/luci-static/resources/fchomo/listeners.js:1142 +#: htdocs/luci-static/resources/view/fchomo/node.js:1313 msgid "Max each POST bytes" msgstr "POST 最大字节数" -#: htdocs/luci-static/resources/view/fchomo/node.js:573 +#: htdocs/luci-static/resources/view/fchomo/node.js:574 msgid "Max open streams" msgstr "限制打开流的数量" -#: htdocs/luci-static/resources/view/fchomo/node.js:1311 +#: htdocs/luci-static/resources/fchomo/listeners.js:220 +msgid "Max realms" +msgstr "最大 Realms 总数" + +#: htdocs/luci-static/resources/fchomo/listeners.js:226 +msgid "Max realms per client IP" +msgstr "每客户端 IP 最大 Realms 总数" + +#: htdocs/luci-static/resources/view/fchomo/node.js:1346 msgid "Max request times" msgstr "最大请求次数" -#: htdocs/luci-static/resources/view/fchomo/node.js:1316 +#: htdocs/luci-static/resources/view/fchomo/node.js:1351 msgid "Max reusable seconds" msgstr "最大可复用秒数" -#: htdocs/luci-static/resources/view/fchomo/node.js:1306 +#: htdocs/luci-static/resources/view/fchomo/node.js:1341 msgid "Max reuse times" msgstr "最大复用次数" -#: htdocs/luci-static/resources/fchomo/listeners.js:174 -#: htdocs/luci-static/resources/view/fchomo/node.js:285 +#: htdocs/luci-static/resources/fchomo/listeners.js:175 +#: htdocs/luci-static/resources/view/fchomo/node.js:286 msgid "Max upload speed" msgstr "最大上传速度" -#: htdocs/luci-static/resources/view/fchomo/node.js:1342 -#: htdocs/luci-static/resources/view/fchomo/node.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1377 +#: htdocs/luci-static/resources/view/fchomo/node.js:1397 msgid "Maximum connections" msgstr "最大连接数" -#: htdocs/luci-static/resources/view/fchomo/node.js:1360 +#: htdocs/luci-static/resources/view/fchomo/node.js:1395 msgid "" "Maximum multiplexed streams in a connection before opening a new connection." "
Conflict with %s and %s." @@ -1803,24 +1825,24 @@ msgstr "" "在打开新连接之前,连接中的最大多路复用流数量。
%s 和 " "%s 冲突。" -#: htdocs/luci-static/resources/fchomo/listeners.js:359 -#: htdocs/luci-static/resources/view/fchomo/node.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:390 +#: htdocs/luci-static/resources/view/fchomo/node.js:429 msgid "Maximum padding rate" msgstr "最大填充率" -#: htdocs/luci-static/resources/fchomo/listeners.js:367 -#: htdocs/luci-static/resources/view/fchomo/node.js:436 +#: htdocs/luci-static/resources/fchomo/listeners.js:398 +#: htdocs/luci-static/resources/view/fchomo/node.js:437 msgid "" "Maximum padding rate must be greater than or equal to the minimum padding " "rate." msgstr "最大填充率必须大于等于最小填充率。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1359 +#: htdocs/luci-static/resources/view/fchomo/node.js:1394 msgid "Maximum streams" msgstr "最大流数量" #: htdocs/luci-static/resources/fchomo.js:157 -#: htdocs/luci-static/resources/fchomo.js:190 +#: htdocs/luci-static/resources/fchomo.js:191 msgid "Mieru" msgstr "" @@ -1836,26 +1858,26 @@ msgstr "Mihomo 客户端" msgid "Mihomo server" msgstr "Mihomo 服务端" -#: htdocs/luci-static/resources/view/fchomo/node.js:617 +#: htdocs/luci-static/resources/view/fchomo/node.js:618 msgid "Min of idle sessions to keep" msgstr "要保留的最少闲置会话数" -#: htdocs/luci-static/resources/view/fchomo/node.js:1284 +#: htdocs/luci-static/resources/view/fchomo/node.js:1319 msgid "Min posts interval" msgstr "POST 请求最小间隔时间" -#: htdocs/luci-static/resources/view/fchomo/node.js:1351 +#: htdocs/luci-static/resources/view/fchomo/node.js:1386 msgid "" "Minimum multiplexed streams in a connection before opening a new connection." msgstr "在打开新连接之前,连接中的最小多路复用流数量。" -#: htdocs/luci-static/resources/fchomo/listeners.js:352 -#: htdocs/luci-static/resources/view/fchomo/node.js:421 +#: htdocs/luci-static/resources/fchomo/listeners.js:383 +#: htdocs/luci-static/resources/view/fchomo/node.js:422 msgid "Minimum padding rate" msgstr "最小填充率" -#: htdocs/luci-static/resources/view/fchomo/node.js:1350 -#: htdocs/luci-static/resources/view/fchomo/node.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1385 +#: htdocs/luci-static/resources/view/fchomo/node.js:1397 msgid "Minimum streams" msgstr "最小流数量" @@ -1872,16 +1894,16 @@ msgstr "混合 系统 TCP 栈和 gVisor UDP 栈。" msgid "Mixed port" msgstr "混合端口" -#: htdocs/luci-static/resources/view/fchomo/node.js:1328 +#: htdocs/luci-static/resources/view/fchomo/node.js:1363 msgid "Multiplex" msgstr "多路复用" -#: htdocs/luci-static/resources/fchomo/listeners.js:123 -#: htdocs/luci-static/resources/view/fchomo/node.js:226 +#: htdocs/luci-static/resources/fchomo/listeners.js:124 +#: htdocs/luci-static/resources/view/fchomo/node.js:227 msgid "Multiplex fields" msgstr "多路复用字段" -#: htdocs/luci-static/resources/view/fchomo/node.js:362 +#: htdocs/luci-static/resources/view/fchomo/node.js:363 msgid "Multiplexing" msgstr "多路复用" @@ -1890,11 +1912,11 @@ msgstr "多路复用" msgid "NOT" msgstr "NOT" -#: htdocs/luci-static/resources/fchomo/listeners.js:536 +#: htdocs/luci-static/resources/fchomo/listeners.js:574 msgid "Name of the Proxy group as outbound." msgstr "出站代理组的名称。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1640 +#: htdocs/luci-static/resources/view/fchomo/node.js:1675 msgid "Name of the Proxy group to download provider." msgstr "用于下载供应商订阅的代理组名称。" @@ -1902,23 +1924,23 @@ msgstr "用于下载供应商订阅的代理组名称。" msgid "Name of the Proxy group to download rule set." msgstr "用于下载规则集订阅的代理组名称。" -#: htdocs/luci-static/resources/fchomo/listeners.js:530 +#: htdocs/luci-static/resources/fchomo/listeners.js:568 msgid "Name of the Sub rule used for inbound matching." msgstr "用于入站匹配的子规则名称。" -#: htdocs/luci-static/resources/view/fchomo/node.js:530 +#: htdocs/luci-static/resources/view/fchomo/node.js:531 msgid "Native UDP" msgstr "原生 UDP" -#: htdocs/luci-static/resources/fchomo.js:381 +#: htdocs/luci-static/resources/fchomo.js:382 msgid "Native appearance" msgstr "原生外观" -#: htdocs/luci-static/resources/fchomo/listeners.js:562 +#: htdocs/luci-static/resources/fchomo/listeners.js:600 msgid "Network type" msgstr "网络类型" -#: htdocs/luci-static/resources/view/fchomo/node.js:1726 +#: htdocs/luci-static/resources/view/fchomo/node.js:1761 msgid "No" msgstr "" @@ -1926,7 +1948,7 @@ msgstr "" msgid "No Authentication IP ranges" msgstr "无需认证的 IP 范围" -#: htdocs/luci-static/resources/fchomo/listeners.js:1037 +#: htdocs/luci-static/resources/fchomo/listeners.js:1126 msgid "No SSE header" msgstr "无 SSE header" @@ -1934,16 +1956,16 @@ msgstr "无 SSE header" msgid "No add'l params" msgstr "无附加参数" -#: htdocs/luci-static/resources/view/fchomo/node.js:1268 +#: htdocs/luci-static/resources/view/fchomo/node.js:1303 msgid "No gRPC header" msgstr "无 gRPC header" #: htdocs/luci-static/resources/view/fchomo/client.js:1115 -#: htdocs/luci-static/resources/view/fchomo/node.js:1789 +#: htdocs/luci-static/resources/view/fchomo/node.js:1824 msgid "No testing is performed when this provider node is not in use." msgstr "当此供应商的节点未使用时,不执行任何测试。" -#: htdocs/luci-static/resources/fchomo.js:686 +#: htdocs/luci-static/resources/fchomo.js:687 msgid "No valid %s found." msgstr "未找到有效的%s。" @@ -1958,17 +1980,17 @@ msgid "Node" msgstr "节点" #: htdocs/luci-static/resources/view/fchomo/client.js:1160 -#: htdocs/luci-static/resources/view/fchomo/node.js:1809 +#: htdocs/luci-static/resources/view/fchomo/node.js:1844 msgid "Node exclude filter" msgstr "排除节点" #: htdocs/luci-static/resources/view/fchomo/client.js:1165 -#: htdocs/luci-static/resources/view/fchomo/node.js:1816 +#: htdocs/luci-static/resources/view/fchomo/node.js:1851 msgid "Node exclude type" msgstr "排除节点类型" #: htdocs/luci-static/resources/view/fchomo/client.js:1155 -#: htdocs/luci-static/resources/view/fchomo/node.js:1803 +#: htdocs/luci-static/resources/view/fchomo/node.js:1838 msgid "Node filter" msgstr "过滤节点" @@ -1976,7 +1998,7 @@ msgstr "过滤节点" msgid "Node switch tolerance" msgstr "节点切换容差" -#: htdocs/luci-static/resources/fchomo.js:408 +#: htdocs/luci-static/resources/fchomo.js:409 msgid "None" msgstr "无" @@ -1984,38 +2006,39 @@ msgstr "无" msgid "Not Installed" msgstr "未安装" -#: htdocs/luci-static/resources/fchomo.js:1204 +#: htdocs/luci-static/resources/fchomo.js:1205 msgid "Not Running" msgstr "未在运行" -#: htdocs/luci-static/resources/view/fchomo/node.js:482 +#: htdocs/luci-static/resources/view/fchomo/node.js:483 msgid "OFF" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:485 msgid "ON" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:815 +#: htdocs/luci-static/resources/fchomo/listeners.js:538 +#: htdocs/luci-static/resources/view/fchomo/node.js:816 msgid "Obfs Mode" msgstr "Obfs 模式" -#: htdocs/luci-static/resources/fchomo/listeners.js:198 -#: htdocs/luci-static/resources/view/fchomo/node.js:303 +#: htdocs/luci-static/resources/fchomo/listeners.js:199 +#: htdocs/luci-static/resources/view/fchomo/node.js:304 msgid "Obfuscate password" msgstr "混淆密码" -#: htdocs/luci-static/resources/fchomo/listeners.js:192 -#: htdocs/luci-static/resources/fchomo/listeners.js:327 -#: htdocs/luci-static/resources/view/fchomo/node.js:297 -#: htdocs/luci-static/resources/view/fchomo/node.js:407 +#: htdocs/luci-static/resources/fchomo/listeners.js:193 +#: htdocs/luci-static/resources/fchomo/listeners.js:358 +#: htdocs/luci-static/resources/view/fchomo/node.js:298 +#: htdocs/luci-static/resources/view/fchomo/node.js:408 msgid "Obfuscate type" msgstr "混淆类型" -#: htdocs/luci-static/resources/fchomo/listeners.js:328 -#: htdocs/luci-static/resources/fchomo/listeners.js:329 -#: htdocs/luci-static/resources/view/fchomo/node.js:408 +#: htdocs/luci-static/resources/fchomo/listeners.js:359 +#: htdocs/luci-static/resources/fchomo/listeners.js:360 #: htdocs/luci-static/resources/view/fchomo/node.js:409 +#: htdocs/luci-static/resources/view/fchomo/node.js:410 msgid "Obfuscated as %s" msgstr "混淆为%s" @@ -2023,8 +2046,8 @@ msgstr "混淆为%s" msgid "One or more numbers in the range 0-63 separated by commas" msgstr "0-63 范围内的一个或多个数字,以逗号分隔" -#: htdocs/luci-static/resources/fchomo/listeners.js:336 -#: htdocs/luci-static/resources/view/fchomo/node.js:416 +#: htdocs/luci-static/resources/fchomo/listeners.js:367 +#: htdocs/luci-static/resources/view/fchomo/node.js:417 msgid "Only applies to the %s." msgstr "只对%s生效。" @@ -2032,7 +2055,7 @@ msgstr "只对%s生效。" msgid "Only process traffic from specific interfaces. Leave empty for all." msgstr "只处理来自指定接口的流量。留空表示全部。" -#: htdocs/luci-static/resources/fchomo.js:1198 +#: htdocs/luci-static/resources/fchomo.js:1199 msgid "Open Dashboard" msgstr "打开面板" @@ -2046,11 +2069,11 @@ msgid "Override destination" msgstr "覆盖目标地址" #: htdocs/luci-static/resources/view/fchomo/client.js:1010 -#: htdocs/luci-static/resources/view/fchomo/node.js:1551 +#: htdocs/luci-static/resources/view/fchomo/node.js:1586 msgid "Override fields" msgstr "覆盖字段" -#: htdocs/luci-static/resources/view/fchomo/node.js:522 +#: htdocs/luci-static/resources/view/fchomo/node.js:523 msgid "Override the IP address of the server that DNS response." msgstr "覆盖 DNS 回应的服务器的 IP 地址。" @@ -2066,7 +2089,7 @@ msgstr "使用嗅探到的域名覆盖连接目标。" msgid "Override the existing ECS in original request." msgstr "覆盖原始请求中已有的 ECS。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1100 +#: htdocs/luci-static/resources/view/fchomo/node.js:1135 msgid "Overrides the domain name used for HTTPS record queries." msgstr "覆盖用于 HTTPS 记录查询的域名。" @@ -2074,47 +2097,47 @@ msgstr "覆盖用于 HTTPS 记录查询的域名。" msgid "Overview" msgstr "概览" -#: htdocs/luci-static/resources/view/fchomo/node.js:1195 +#: htdocs/luci-static/resources/view/fchomo/node.js:1230 msgid "POST" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1196 +#: htdocs/luci-static/resources/view/fchomo/node.js:1231 msgid "PUT" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:666 +#: htdocs/luci-static/resources/view/fchomo/node.js:667 msgid "Packet encoding" msgstr "数据包编码" -#: htdocs/luci-static/resources/view/fchomo/node.js:1273 +#: htdocs/luci-static/resources/view/fchomo/node.js:1308 msgid "Padding bytes" msgstr "填充字节" -#: htdocs/luci-static/resources/fchomo/listeners.js:463 +#: htdocs/luci-static/resources/fchomo/listeners.js:494 msgid "Padding scheme" msgstr "填充方案" -#: htdocs/luci-static/resources/fchomo/listeners.js:661 -#: htdocs/luci-static/resources/view/fchomo/node.js:938 +#: htdocs/luci-static/resources/fchomo/listeners.js:699 +#: htdocs/luci-static/resources/view/fchomo/node.js:939 msgid "Paddings" msgstr "填充 (Paddings)" -#: htdocs/luci-static/resources/fchomo/listeners.js:165 -#: htdocs/luci-static/resources/fchomo/listeners.js:221 -#: htdocs/luci-static/resources/fchomo/listeners.js:513 -#: htdocs/luci-static/resources/view/fchomo/node.js:261 -#: htdocs/luci-static/resources/view/fchomo/node.js:340 -#: htdocs/luci-static/resources/view/fchomo/node.js:830 +#: htdocs/luci-static/resources/fchomo/listeners.js:166 +#: htdocs/luci-static/resources/fchomo/listeners.js:252 +#: htdocs/luci-static/resources/fchomo/listeners.js:551 +#: htdocs/luci-static/resources/view/fchomo/node.js:262 +#: htdocs/luci-static/resources/view/fchomo/node.js:341 +#: htdocs/luci-static/resources/view/fchomo/node.js:831 msgid "Password" msgstr "密码" -#: htdocs/luci-static/resources/fchomo/listeners.js:601 -#: htdocs/luci-static/resources/view/fchomo/node.js:1615 +#: htdocs/luci-static/resources/fchomo/listeners.js:639 +#: htdocs/luci-static/resources/view/fchomo/node.js:1650 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:364 msgid "Payload" msgstr "Payload" -#: htdocs/luci-static/resources/view/fchomo/node.js:754 +#: htdocs/luci-static/resources/view/fchomo/node.js:755 msgid "Peer pubkic key" msgstr "对端公钥" @@ -2124,11 +2147,11 @@ msgid "" "it is not needed." msgstr "性能可能会略有下降,建议仅在需要时开启。" -#: htdocs/luci-static/resources/view/fchomo/node.js:781 +#: htdocs/luci-static/resources/view/fchomo/node.js:782 msgid "Periodically sends data packets to maintain connection persistence." msgstr "定期发送数据包以维持连接持久性。" -#: htdocs/luci-static/resources/view/fchomo/node.js:780 +#: htdocs/luci-static/resources/view/fchomo/node.js:781 msgid "Persistent keepalive" msgstr "持久连接" @@ -2151,8 +2174,8 @@ msgid "" "standards." msgstr "链接格式标准请参考
%s。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1588 -#: htdocs/luci-static/resources/view/fchomo/node.js:1614 +#: htdocs/luci-static/resources/view/fchomo/node.js:1623 +#: htdocs/luci-static/resources/view/fchomo/node.js:1649 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:337 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:363 msgid "" @@ -2167,41 +2190,42 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1445 #: htdocs/luci-static/resources/view/fchomo/client.js:1697 #: htdocs/luci-static/resources/view/fchomo/client.js:1749 -#: htdocs/luci-static/resources/view/fchomo/node.js:1458 +#: htdocs/luci-static/resources/view/fchomo/node.js:1493 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:154 msgid "Please type %s fields of mihomo config.
" msgstr "请输入 mihomo 配置的 %s 字段。
" -#: htdocs/luci-static/resources/fchomo/listeners.js:499 -#: htdocs/luci-static/resources/view/fchomo/node.js:804 +#: htdocs/luci-static/resources/fchomo/listeners.js:530 +#: htdocs/luci-static/resources/view/fchomo/node.js:805 msgid "Plugin" msgstr "插件" -#: htdocs/luci-static/resources/fchomo/listeners.js:506 -#: htdocs/luci-static/resources/fchomo/listeners.js:513 -#: htdocs/luci-static/resources/fchomo/listeners.js:519 -#: htdocs/luci-static/resources/view/fchomo/node.js:815 -#: htdocs/luci-static/resources/view/fchomo/node.js:822 -#: htdocs/luci-static/resources/view/fchomo/node.js:830 -#: htdocs/luci-static/resources/view/fchomo/node.js:836 -#: htdocs/luci-static/resources/view/fchomo/node.js:844 -#: htdocs/luci-static/resources/view/fchomo/node.js:850 +#: htdocs/luci-static/resources/fchomo/listeners.js:538 +#: htdocs/luci-static/resources/fchomo/listeners.js:544 +#: htdocs/luci-static/resources/fchomo/listeners.js:551 +#: htdocs/luci-static/resources/fchomo/listeners.js:557 +#: htdocs/luci-static/resources/view/fchomo/node.js:816 +#: htdocs/luci-static/resources/view/fchomo/node.js:823 +#: htdocs/luci-static/resources/view/fchomo/node.js:831 +#: htdocs/luci-static/resources/view/fchomo/node.js:837 +#: htdocs/luci-static/resources/view/fchomo/node.js:845 +#: htdocs/luci-static/resources/view/fchomo/node.js:851 msgid "Plugin:" msgstr "插件:" -#: htdocs/luci-static/resources/view/fchomo/node.js:249 +#: htdocs/luci-static/resources/view/fchomo/node.js:250 msgid "Port" msgstr "端口" -#: htdocs/luci-static/resources/fchomo.js:1435 +#: htdocs/luci-static/resources/fchomo.js:1436 msgid "Port %s alrealy exists!" msgstr "端口 %s 已存在!" -#: htdocs/luci-static/resources/view/fchomo/node.js:279 +#: htdocs/luci-static/resources/view/fchomo/node.js:280 msgid "Port hop interval" msgstr "端口跳跃间隔" -#: htdocs/luci-static/resources/view/fchomo/node.js:350 +#: htdocs/luci-static/resources/view/fchomo/node.js:351 msgid "Port range" msgstr "端口范围" @@ -2209,21 +2233,27 @@ msgstr "端口范围" msgid "Ports" msgstr "端口" -#: htdocs/luci-static/resources/fchomo/listeners.js:152 -#: htdocs/luci-static/resources/view/fchomo/node.js:274 +#: htdocs/luci-static/resources/fchomo/listeners.js:153 +#: htdocs/luci-static/resources/view/fchomo/node.js:275 msgid "Ports pool" msgstr "端口池" -#: htdocs/luci-static/resources/view/fchomo/node.js:499 -#: htdocs/luci-static/resources/view/fchomo/node.js:761 +#: htdocs/luci-static/resources/fchomo/listeners.js:214 +#: htdocs/luci-static/resources/view/fchomo/node.js:500 +#: htdocs/luci-static/resources/view/fchomo/node.js:762 msgid "Pre-shared key" msgstr "预共享密钥" -#: htdocs/luci-static/resources/fchomo.js:174 +#: htdocs/luci-static/resources/fchomo/listeners.js:837 +#: htdocs/luci-static/resources/view/fchomo/node.js:974 +msgid "Pre-shared key of rendezvous server" +msgstr "牵线服务器的预共享密钥" + +#: htdocs/luci-static/resources/fchomo.js:175 msgid "Prefer IPv4" msgstr "优先 IPv4" -#: htdocs/luci-static/resources/fchomo.js:175 +#: htdocs/luci-static/resources/fchomo.js:176 msgid "Prefer IPv6" msgstr "优先 IPv6" @@ -2234,23 +2264,23 @@ msgstr "防止某些情况下的 ICMP 环回问题。Ping 不会显示实际延 #: htdocs/luci-static/resources/view/fchomo/global.js:736 #: htdocs/luci-static/resources/view/fchomo/global.js:753 -#: htdocs/luci-static/resources/view/fchomo/node.js:1422 -#: htdocs/luci-static/resources/view/fchomo/node.js:1428 -#: htdocs/luci-static/resources/view/fchomo/node.js:1738 -#: htdocs/luci-static/resources/view/fchomo/node.js:1745 +#: htdocs/luci-static/resources/view/fchomo/node.js:1457 +#: htdocs/luci-static/resources/view/fchomo/node.js:1463 +#: htdocs/luci-static/resources/view/fchomo/node.js:1773 +#: htdocs/luci-static/resources/view/fchomo/node.js:1780 msgid "Priority: Proxy Node > Global." msgstr "优先级: 代理节点 > 全局。" -#: htdocs/luci-static/resources/view/fchomo/node.js:312 +#: htdocs/luci-static/resources/view/fchomo/node.js:313 msgid "Priv-key" msgstr "密钥" -#: htdocs/luci-static/resources/view/fchomo/node.js:316 +#: htdocs/luci-static/resources/view/fchomo/node.js:317 msgid "Priv-key passphrase" msgstr "密钥密码" -#: htdocs/luci-static/resources/view/fchomo/node.js:674 -#: htdocs/luci-static/resources/view/fchomo/node.js:746 +#: htdocs/luci-static/resources/view/fchomo/node.js:675 +#: htdocs/luci-static/resources/view/fchomo/node.js:747 msgid "Private key" msgstr "私钥" @@ -2259,28 +2289,28 @@ msgid "Process matching mode" msgstr "进程匹配模式" #: htdocs/luci-static/resources/view/fchomo/global.js:684 -#: htdocs/luci-static/resources/view/fchomo/node.js:1334 +#: htdocs/luci-static/resources/view/fchomo/node.js:1369 msgid "Protocol" msgstr "协议" -#: htdocs/luci-static/resources/view/fchomo/node.js:661 +#: htdocs/luci-static/resources/view/fchomo/node.js:662 msgid "Protocol parameter. Enable length block encryption." msgstr "协议参数。启用长度块加密。" -#: htdocs/luci-static/resources/view/fchomo/node.js:655 +#: htdocs/luci-static/resources/view/fchomo/node.js:656 msgid "" "Protocol parameter. Will waste traffic randomly if enabled (enabled by " "default in v2ray and cannot be disabled)." msgstr "协议参数。 如启用会随机浪费流量(在 v2ray 中默认启用并且无法禁用)。" #: htdocs/luci-static/resources/view/fchomo/client.js:1055 -#: htdocs/luci-static/resources/view/fchomo/node.js:1441 -#: htdocs/luci-static/resources/view/fchomo/node.js:1450 -#: htdocs/luci-static/resources/view/fchomo/node.js:1854 +#: htdocs/luci-static/resources/view/fchomo/node.js:1476 +#: htdocs/luci-static/resources/view/fchomo/node.js:1485 +#: htdocs/luci-static/resources/view/fchomo/node.js:1889 msgid "Provider" msgstr "供应商" -#: htdocs/luci-static/resources/view/fchomo/node.js:1621 +#: htdocs/luci-static/resources/view/fchomo/node.js:1656 msgid "Provider URL" msgstr "供应商订阅 URL" @@ -2303,19 +2333,19 @@ msgid "Proxy MAC-s" msgstr "代理 MAC 地址" #: htdocs/luci-static/resources/view/fchomo/node.js:208 -#: htdocs/luci-static/resources/view/fchomo/node.js:1853 +#: htdocs/luci-static/resources/view/fchomo/node.js:1888 msgid "Proxy Node" msgstr "代理节点" -#: htdocs/luci-static/resources/view/fchomo/node.js:1829 -#: htdocs/luci-static/resources/view/fchomo/node.js:1838 +#: htdocs/luci-static/resources/view/fchomo/node.js:1864 +#: htdocs/luci-static/resources/view/fchomo/node.js:1873 msgid "Proxy chain" msgstr "代理链" -#: htdocs/luci-static/resources/fchomo/listeners.js:535 +#: htdocs/luci-static/resources/fchomo/listeners.js:573 #: htdocs/luci-static/resources/view/fchomo/client.js:783 #: htdocs/luci-static/resources/view/fchomo/client.js:1543 -#: htdocs/luci-static/resources/view/fchomo/node.js:1639 +#: htdocs/luci-static/resources/view/fchomo/node.js:1674 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:388 msgid "Proxy group" msgstr "代理组" @@ -2332,8 +2362,8 @@ msgstr "代理模式" msgid "Proxy routerself" msgstr "代理路由器自身" -#: htdocs/luci-static/resources/view/fchomo/node.js:531 -#: htdocs/luci-static/resources/view/fchomo/node.js:726 +#: htdocs/luci-static/resources/view/fchomo/node.js:532 +#: htdocs/luci-static/resources/view/fchomo/node.js:727 msgid "QUIC" msgstr "" @@ -2342,44 +2372,44 @@ msgstr "" msgid "Quick Reload" msgstr "快速重载" -#: htdocs/luci-static/resources/fchomo/listeners.js:931 -#: htdocs/luci-static/resources/view/fchomo/node.js:1114 +#: htdocs/luci-static/resources/fchomo/listeners.js:1020 +#: htdocs/luci-static/resources/view/fchomo/node.js:1149 msgid "REALITY" msgstr "REALITY" -#: htdocs/luci-static/resources/view/fchomo/node.js:1129 +#: htdocs/luci-static/resources/view/fchomo/node.js:1164 msgid "REALITY X25519MLKEM768 PQC support" msgstr "REALITY X25519MLKEM768 后量子加密支持" -#: htdocs/luci-static/resources/fchomo/listeners.js:968 +#: htdocs/luci-static/resources/fchomo/listeners.js:1057 msgid "REALITY certificate issued to" msgstr "REALITY 证书颁发给" -#: htdocs/luci-static/resources/fchomo/listeners.js:936 +#: htdocs/luci-static/resources/fchomo/listeners.js:1025 msgid "REALITY handshake server" msgstr "REALITY 握手服务器" -#: htdocs/luci-static/resources/fchomo/listeners.js:943 +#: htdocs/luci-static/resources/fchomo/listeners.js:1032 msgid "REALITY private key" msgstr "REALITY 私钥" -#: htdocs/luci-static/resources/fchomo/listeners.js:958 -#: htdocs/luci-static/resources/view/fchomo/node.js:1119 +#: htdocs/luci-static/resources/fchomo/listeners.js:1047 +#: htdocs/luci-static/resources/view/fchomo/node.js:1154 msgid "REALITY public key" msgstr "REALITY 公钥" -#: htdocs/luci-static/resources/fchomo/listeners.js:962 -#: htdocs/luci-static/resources/view/fchomo/node.js:1124 +#: htdocs/luci-static/resources/fchomo/listeners.js:1051 +#: htdocs/luci-static/resources/view/fchomo/node.js:1159 msgid "REALITY short ID" msgstr "REALITY 标识符" -#: htdocs/luci-static/resources/fchomo/listeners.js:632 -#: htdocs/luci-static/resources/fchomo/listeners.js:651 -#: htdocs/luci-static/resources/view/fchomo/node.js:928 +#: htdocs/luci-static/resources/fchomo/listeners.js:670 +#: htdocs/luci-static/resources/fchomo/listeners.js:689 +#: htdocs/luci-static/resources/view/fchomo/node.js:929 msgid "RTT" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:373 +#: htdocs/luci-static/resources/fchomo.js:374 msgid "Random" msgstr "随机" @@ -2387,10 +2417,24 @@ msgstr "随机" msgid "Random will be used if empty." msgstr "留空将使用随机令牌。" -#: htdocs/luci-static/resources/fchomo.js:383 +#: htdocs/luci-static/resources/fchomo.js:384 msgid "Randomized traffic characteristics" msgstr "随机化流量特征" +#: htdocs/luci-static/resources/fchomo/listeners.js:826 +#: htdocs/luci-static/resources/view/fchomo/node.js:963 +msgid "Realm" +msgstr "Realm" + +#: htdocs/luci-static/resources/fchomo/listeners.js:842 +#: htdocs/luci-static/resources/view/fchomo/node.js:979 +msgid "Realm ID" +msgstr "Realm ID" + +#: htdocs/luci-static/resources/fchomo/listeners.js:237 +msgid "Realm name pattern" +msgstr "Realm 名称模式" + #: htdocs/luci-static/resources/view/fchomo/global.js:460 msgid "Redir port" msgstr "Redir 端口" @@ -2411,7 +2455,7 @@ msgstr "Redirect TCP + Tun UDP" msgid "Refresh every %s seconds." msgstr "每 %s 秒刷新。" -#: htdocs/luci-static/resources/fchomo.js:1191 +#: htdocs/luci-static/resources/fchomo.js:1192 #: htdocs/luci-static/resources/view/fchomo/client.js:927 #: htdocs/luci-static/resources/view/fchomo/global.js:193 #: htdocs/luci-static/resources/view/fchomo/server.js:45 @@ -2422,64 +2466,69 @@ msgstr "重载" msgid "Reload All" msgstr "重载所有" -#: htdocs/luci-static/resources/view/fchomo/node.js:1566 +#: htdocs/luci-static/resources/view/fchomo/node.js:1601 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:278 msgid "Remote" msgstr "远程" -#: htdocs/luci-static/resources/view/fchomo/node.js:709 -#: htdocs/luci-static/resources/view/fchomo/node.js:792 +#: htdocs/luci-static/resources/view/fchomo/node.js:710 +#: htdocs/luci-static/resources/view/fchomo/node.js:793 msgid "Remote DNS resolve" msgstr "远程 DNS 解析" -#: htdocs/luci-static/resources/fchomo.js:1356 +#: htdocs/luci-static/resources/fchomo.js:1357 msgid "Remove" msgstr "移除" -#: htdocs/luci-static/resources/fchomo.js:1361 -#: htdocs/luci-static/resources/view/fchomo/node.js:1542 -#: htdocs/luci-static/resources/view/fchomo/node.js:1544 +#: htdocs/luci-static/resources/fchomo.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1577 +#: htdocs/luci-static/resources/view/fchomo/node.js:1579 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:251 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:253 msgid "Remove idles" msgstr "移除闲置" -#: htdocs/luci-static/resources/view/fchomo/node.js:1668 +#: htdocs/luci-static/resources/fchomo/listeners.js:831 +#: htdocs/luci-static/resources/view/fchomo/node.js:968 +msgid "Rendezvous server" +msgstr "牵线服务器" + +#: htdocs/luci-static/resources/view/fchomo/node.js:1703 msgid "Replace name" msgstr "名称替换" -#: htdocs/luci-static/resources/view/fchomo/node.js:1669 +#: htdocs/luci-static/resources/view/fchomo/node.js:1704 msgid "Replace node name." msgstr "替换节点名称" -#: htdocs/luci-static/resources/fchomo.js:357 +#: htdocs/luci-static/resources/fchomo.js:358 msgid "Request" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1016 -#: htdocs/luci-static/resources/view/fchomo/node.js:1202 -#: htdocs/luci-static/resources/view/fchomo/node.js:1209 +#: htdocs/luci-static/resources/fchomo/listeners.js:1105 +#: htdocs/luci-static/resources/view/fchomo/node.js:1237 +#: htdocs/luci-static/resources/view/fchomo/node.js:1244 msgid "Request path" msgstr "请求路径" -#: htdocs/luci-static/resources/view/fchomo/node.js:566 +#: htdocs/luci-static/resources/view/fchomo/node.js:567 msgid "Request timeout" msgstr "请求超时" -#: htdocs/luci-static/resources/fchomo.js:360 +#: htdocs/luci-static/resources/fchomo.js:361 msgid "Require and verify" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:358 +#: htdocs/luci-static/resources/fchomo.js:359 msgid "Require any" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:391 -#: htdocs/luci-static/resources/view/fchomo/node.js:1130 +#: htdocs/luci-static/resources/fchomo.js:392 +#: htdocs/luci-static/resources/view/fchomo/node.js:1165 msgid "Requires server support." msgstr "需要服务器支持。" -#: htdocs/luci-static/resources/view/fchomo/node.js:775 +#: htdocs/luci-static/resources/view/fchomo/node.js:776 msgid "Reserved field bytes" msgstr "保留字段字节" @@ -2487,7 +2536,7 @@ msgstr "保留字段字节" msgid "Resources management" msgstr "资源管理" -#: htdocs/luci-static/resources/view/fchomo/node.js:850 +#: htdocs/luci-static/resources/view/fchomo/node.js:851 msgid "Restls script" msgstr "Restls 剧本" @@ -2501,12 +2550,12 @@ msgid "" "Returns the string input for icon in the API to display in this proxy group." msgstr "在 API 返回 icon 所输入的字符串,以在该代理组显示。" -#: htdocs/luci-static/resources/view/fchomo/node.js:483 +#: htdocs/luci-static/resources/view/fchomo/node.js:484 msgid "Reuse HTTP connections to reduce RTT for each connection establishment." msgstr "重用 HTTP 连接以减少每次建立连接的 RTT。" -#: htdocs/luci-static/resources/view/fchomo/node.js:480 -#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:481 +#: htdocs/luci-static/resources/view/fchomo/node.js:485 msgid "Reusing a single tunnel to carry multiple target connections within it." msgstr "复用单条隧道使其内部承载多条目标连线。" @@ -2523,8 +2572,8 @@ msgstr "路由 DSCP" msgid "Routing GFW" msgstr "路由 GFW 流量" -#: htdocs/luci-static/resources/view/fchomo/node.js:1427 -#: htdocs/luci-static/resources/view/fchomo/node.js:1744 +#: htdocs/luci-static/resources/view/fchomo/node.js:1462 +#: htdocs/luci-static/resources/view/fchomo/node.js:1779 msgid "Routing mark" msgstr "路由标记" @@ -2584,11 +2633,11 @@ msgstr "规则集" msgid "Ruleset-URI-Scheme" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1204 +#: htdocs/luci-static/resources/fchomo.js:1205 msgid "Running" msgstr "正在运行" -#: htdocs/luci-static/resources/fchomo.js:239 +#: htdocs/luci-static/resources/fchomo.js:240 msgid "SMTP" msgstr "" @@ -2596,36 +2645,41 @@ msgstr "" msgid "SOCKS" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo.js:188 msgid "SOCKS5" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:203 +#: htdocs/luci-static/resources/fchomo.js:204 msgid "SSH" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:240 +#: htdocs/luci-static/resources/fchomo.js:241 msgid "STUN" msgstr "" +#: htdocs/luci-static/resources/fchomo/listeners.js:848 +#: htdocs/luci-static/resources/view/fchomo/node.js:985 +msgid "STUN servers" +msgstr "STUN 服务器" + #: htdocs/luci-static/resources/view/fchomo/client.js:1276 msgid "SUB-RULE" msgstr "SUB-RULE" -#: htdocs/luci-static/resources/view/fchomo/node.js:885 +#: htdocs/luci-static/resources/view/fchomo/node.js:886 msgid "SUoT version" msgstr "SUoT 版本" -#: htdocs/luci-static/resources/fchomo/listeners.js:194 -#: htdocs/luci-static/resources/view/fchomo/node.js:299 +#: htdocs/luci-static/resources/fchomo/listeners.js:195 +#: htdocs/luci-static/resources/view/fchomo/node.js:300 msgid "Salamander" msgstr "Salamander" -#: htdocs/luci-static/resources/fchomo.js:180 +#: htdocs/luci-static/resources/fchomo.js:181 msgid "Same dstaddr requests. Same node" msgstr "相同 目标地址 请求。相同节点" -#: htdocs/luci-static/resources/fchomo.js:181 +#: htdocs/luci-static/resources/fchomo.js:182 msgid "Same srcaddr and dstaddr requests. Same node" msgstr "相同 来源地址 和 目标地址 请求。相同节点" @@ -2633,7 +2687,7 @@ msgstr "相同 来源地址 和 目标地址 请求。相同节点" msgid "Segment maximum size" msgstr "分段最大尺寸" -#: htdocs/luci-static/resources/fchomo.js:228 +#: htdocs/luci-static/resources/fchomo.js:229 msgid "Select" msgstr "手动选择" @@ -2641,30 +2695,30 @@ msgstr "手动选择" msgid "Select Dashboard" msgstr "选择面板" -#: htdocs/luci-static/resources/fchomo.js:397 +#: htdocs/luci-static/resources/fchomo.js:398 msgid "Send padding randomly 0-3333 bytes with 50% probability." msgstr "以 50% 的概率发送随机 0-3333 字节的填充。" -#: htdocs/luci-static/resources/fchomo.js:386 #: htdocs/luci-static/resources/fchomo.js:387 +#: htdocs/luci-static/resources/fchomo.js:388 msgid "Send random ticket of 300s-600s duration for client 0-RTT reuse." msgstr "发送 300-600 秒的随机票证,以供客户端 0-RTT 重用。" -#: htdocs/luci-static/resources/fchomo/listeners.js:632 -#: htdocs/luci-static/resources/fchomo/listeners.js:829 -#: htdocs/luci-static/resources/fchomo/listeners.js:844 +#: htdocs/luci-static/resources/fchomo/listeners.js:670 +#: htdocs/luci-static/resources/fchomo/listeners.js:918 +#: htdocs/luci-static/resources/fchomo/listeners.js:933 #: htdocs/luci-static/resources/view/fchomo/server.js:58 #: root/usr/share/luci/menu.d/luci-app-fchomo.json:62 msgid "Server" msgstr "服务端" -#: htdocs/luci-static/resources/view/fchomo/node.js:244 +#: htdocs/luci-static/resources/view/fchomo/node.js:245 msgid "Server address" msgstr "服务器地址" -#: htdocs/luci-static/resources/fchomo/listeners.js:1010 -#: htdocs/luci-static/resources/view/fchomo/node.js:1181 -#: htdocs/luci-static/resources/view/fchomo/node.js:1187 +#: htdocs/luci-static/resources/fchomo/listeners.js:1099 +#: htdocs/luci-static/resources/view/fchomo/node.js:1216 +#: htdocs/luci-static/resources/view/fchomo/node.js:1222 msgid "Server hostname" msgstr "服务器主机名称" @@ -2677,26 +2731,26 @@ msgid "Service status" msgstr "服务状态" #: htdocs/luci-static/resources/fchomo.js:156 -#: htdocs/luci-static/resources/fchomo.js:188 +#: htdocs/luci-static/resources/fchomo.js:189 msgid "Shadowsocks" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:445 -#: htdocs/luci-static/resources/view/fchomo/node.js:585 +#: htdocs/luci-static/resources/fchomo/listeners.js:476 +#: htdocs/luci-static/resources/view/fchomo/node.js:586 msgid "Shadowsocks chipher" msgstr "Shadowsocks 加密方法" -#: htdocs/luci-static/resources/fchomo/listeners.js:440 -#: htdocs/luci-static/resources/view/fchomo/node.js:580 +#: htdocs/luci-static/resources/fchomo/listeners.js:471 +#: htdocs/luci-static/resources/view/fchomo/node.js:581 msgid "Shadowsocks encrypt" msgstr "Shadowsocks 加密" -#: htdocs/luci-static/resources/fchomo/listeners.js:453 -#: htdocs/luci-static/resources/view/fchomo/node.js:593 +#: htdocs/luci-static/resources/fchomo/listeners.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:594 msgid "Shadowsocks password" msgstr "Shadowsocks 密码" -#: htdocs/luci-static/resources/view/fchomo/node.js:1382 +#: htdocs/luci-static/resources/view/fchomo/node.js:1417 msgid "Show connections in the dashboard for breaking connections easier." msgstr "在面板中显示连接以便于打断连接。" @@ -2704,18 +2758,18 @@ msgstr "在面板中显示连接以便于打断连接。" msgid "Silent" msgstr "静音" -#: htdocs/luci-static/resources/fchomo.js:179 +#: htdocs/luci-static/resources/fchomo.js:180 msgid "Simple round-robin all nodes" msgstr "简单轮替所有节点" -#: htdocs/luci-static/resources/view/fchomo/node.js:1627 +#: htdocs/luci-static/resources/view/fchomo/node.js:1662 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:376 msgid "Size limit" msgstr "大小限制" #: htdocs/luci-static/resources/view/fchomo/client.js:1576 -#: htdocs/luci-static/resources/view/fchomo/node.js:1051 -#: htdocs/luci-static/resources/view/fchomo/node.js:1719 +#: htdocs/luci-static/resources/view/fchomo/node.js:1086 +#: htdocs/luci-static/resources/view/fchomo/node.js:1754 msgid "Skip cert verify" msgstr "跳过证书验证" @@ -2731,7 +2785,7 @@ msgstr "跳过嗅探目标地址" msgid "Skiped sniffing src address" msgstr "跳过嗅探来源地址" -#: htdocs/luci-static/resources/fchomo.js:192 +#: htdocs/luci-static/resources/fchomo.js:193 msgid "Snell" msgstr "" @@ -2747,7 +2801,7 @@ msgstr "嗅探器" msgid "Sniffer settings" msgstr "嗅探器设置" -#: htdocs/luci-static/resources/fchomo.js:429 +#: htdocs/luci-static/resources/fchomo.js:430 msgid "Specify a ID" msgstr "指定一个ID" @@ -2766,11 +2820,11 @@ msgstr "堆栈" msgid "Standard" msgstr "标准" -#: htdocs/luci-static/resources/fchomo.js:243 +#: htdocs/luci-static/resources/fchomo.js:244 msgid "Steam Client" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:244 +#: htdocs/luci-static/resources/fchomo.js:245 msgid "Steam P2P" msgstr "" @@ -2779,7 +2833,7 @@ msgstr "" msgid "Strategy" msgstr "策略" -#: htdocs/luci-static/resources/fchomo/listeners.js:529 +#: htdocs/luci-static/resources/fchomo/listeners.js:567 #: htdocs/luci-static/resources/view/fchomo/client.js:1303 #: htdocs/luci-static/resources/view/fchomo/client.js:1312 msgid "Sub rule" @@ -2789,7 +2843,7 @@ msgstr "子规则" msgid "Sub rule group" msgstr "子规则组" -#: htdocs/luci-static/resources/fchomo.js:689 +#: htdocs/luci-static/resources/fchomo.js:690 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:223 msgid "Successfully imported %s %s of total %s." msgstr "已成功导入 %s 个%s (共 %s 个)。" @@ -2798,12 +2852,12 @@ msgstr "已成功导入 %s 个%s (共 %s 个)。" msgid "Successfully updated." msgstr "更新成功。" -#: htdocs/luci-static/resources/fchomo.js:1706 +#: htdocs/luci-static/resources/fchomo.js:1707 msgid "Successfully uploaded." msgstr "已成功上传。" #: htdocs/luci-static/resources/fchomo.js:158 -#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:192 msgid "Sudoku" msgstr "" @@ -2829,15 +2883,15 @@ msgstr "系统 DNS" #: htdocs/luci-static/resources/fchomo.js:160 #: htdocs/luci-static/resources/fchomo.js:161 #: htdocs/luci-static/resources/fchomo.js:162 -#: htdocs/luci-static/resources/fchomo.js:186 -#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:187 #: htdocs/luci-static/resources/fchomo.js:192 #: htdocs/luci-static/resources/fchomo.js:193 #: htdocs/luci-static/resources/fchomo.js:194 #: htdocs/luci-static/resources/fchomo.js:195 #: htdocs/luci-static/resources/fchomo.js:196 -#: htdocs/luci-static/resources/fchomo.js:203 -#: htdocs/luci-static/resources/fchomo/listeners.js:563 +#: htdocs/luci-static/resources/fchomo.js:197 +#: htdocs/luci-static/resources/fchomo.js:204 +#: htdocs/luci-static/resources/fchomo/listeners.js:601 #: htdocs/luci-static/resources/view/fchomo/client.js:589 #: htdocs/luci-static/resources/view/fchomo/client.js:679 msgid "TCP" @@ -2847,7 +2901,7 @@ msgstr "TCP" msgid "TCP concurrency" msgstr "TCP 并发" -#: htdocs/luci-static/resources/view/fchomo/node.js:1375 +#: htdocs/luci-static/resources/view/fchomo/node.js:1410 msgid "TCP only" msgstr "仅 TCP" @@ -2865,92 +2919,94 @@ msgstr "TCP-Keep-Alive 间隔" #: htdocs/luci-static/resources/fchomo.js:157 #: htdocs/luci-static/resources/fchomo.js:165 #: htdocs/luci-static/resources/fchomo.js:166 -#: htdocs/luci-static/resources/fchomo.js:185 -#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo.js:167 +#: htdocs/luci-static/resources/fchomo.js:186 #: htdocs/luci-static/resources/fchomo.js:188 -#: htdocs/luci-static/resources/fchomo.js:190 -#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:189 +#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:202 msgid "TCP/UDP" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1406 -#: htdocs/luci-static/resources/view/fchomo/node.js:1686 +#: htdocs/luci-static/resources/view/fchomo/node.js:1441 +#: htdocs/luci-static/resources/view/fchomo/node.js:1721 msgid "TFO" msgstr "TCP 快速打开 (TFO)" -#: htdocs/luci-static/resources/fchomo/listeners.js:786 +#: htdocs/luci-static/resources/fchomo/listeners.js:540 +#: htdocs/luci-static/resources/fchomo/listeners.js:858 #: htdocs/luci-static/resources/view/fchomo/global.js:529 -#: htdocs/luci-static/resources/view/fchomo/node.js:464 -#: htdocs/luci-static/resources/view/fchomo/node.js:817 -#: htdocs/luci-static/resources/view/fchomo/node.js:960 +#: htdocs/luci-static/resources/view/fchomo/node.js:465 +#: htdocs/luci-static/resources/view/fchomo/node.js:818 +#: htdocs/luci-static/resources/view/fchomo/node.js:995 msgid "TLS" msgstr "TLS" -#: htdocs/luci-static/resources/fchomo/listeners.js:823 -#: htdocs/luci-static/resources/view/fchomo/node.js:991 +#: htdocs/luci-static/resources/fchomo/listeners.js:912 +#: htdocs/luci-static/resources/view/fchomo/node.js:1026 msgid "TLS ALPN" msgstr "TLS ALPN" -#: htdocs/luci-static/resources/view/fchomo/node.js:985 +#: htdocs/luci-static/resources/view/fchomo/node.js:1020 msgid "TLS SNI" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:121 -#: htdocs/luci-static/resources/view/fchomo/node.js:224 +#: htdocs/luci-static/resources/fchomo/listeners.js:122 +#: htdocs/luci-static/resources/view/fchomo/node.js:225 msgid "TLS fields" msgstr "TLS字段" #: htdocs/luci-static/resources/fchomo.js:163 -#: htdocs/luci-static/resources/fchomo.js:199 +#: htdocs/luci-static/resources/fchomo.js:200 msgid "TUIC" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:241 +#: htdocs/luci-static/resources/fchomo.js:242 msgid "TURN" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:492 +#: htdocs/luci-static/resources/fchomo/listeners.js:523 msgid "Target address" msgstr "目标地址" -#: htdocs/luci-static/resources/fchomo/listeners.js:187 +#: htdocs/luci-static/resources/fchomo/listeners.js:188 msgid "" "Tell the client to use the BBR flow control algorithm instead of Hysteria CC." msgstr "让客户端使用 BBR 流控算法。" -#: htdocs/luci-static/resources/view/fchomo/node.js:690 -#: htdocs/luci-static/resources/view/fchomo/node.js:698 +#: htdocs/luci-static/resources/view/fchomo/node.js:691 +#: htdocs/luci-static/resources/view/fchomo/node.js:699 msgid "The %s address used by local machine in the Cloudflare WARP network." msgstr "Cloudflare WARP 网络中使用的本机 %s 地址。" -#: htdocs/luci-static/resources/view/fchomo/node.js:733 -#: htdocs/luci-static/resources/view/fchomo/node.js:741 +#: htdocs/luci-static/resources/view/fchomo/node.js:734 +#: htdocs/luci-static/resources/view/fchomo/node.js:742 msgid "The %s address used by local machine in the Wireguard network." msgstr "WireGuard 网络中使用的本机 %s 地址。" -#: htdocs/luci-static/resources/fchomo/listeners.js:844 -#: htdocs/luci-static/resources/view/fchomo/node.js:1074 +#: htdocs/luci-static/resources/fchomo/listeners.js:933 +#: htdocs/luci-static/resources/view/fchomo/node.js:1109 msgid "The %s private key, in PEM format." msgstr "%s私钥,需要 PEM 格式。" -#: htdocs/luci-static/resources/fchomo/listeners.js:829 -#: htdocs/luci-static/resources/fchomo/listeners.js:867 +#: htdocs/luci-static/resources/fchomo/listeners.js:918 +#: htdocs/luci-static/resources/fchomo/listeners.js:956 #: htdocs/luci-static/resources/view/fchomo/global.js:550 -#: htdocs/luci-static/resources/view/fchomo/node.js:1060 +#: htdocs/luci-static/resources/view/fchomo/node.js:1095 msgid "The %s public key, in PEM format." msgstr "%s公钥,需要 PEM 格式。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1094 +#: htdocs/luci-static/resources/view/fchomo/node.js:1129 msgid "" "The ECH parameter of the HTTPS record for the domain. Leave empty to resolve " "via DNS." msgstr "域名的 HTTPS 记录的 ECH 参数。留空则通过 DNS 解析。" -#: htdocs/luci-static/resources/view/fchomo/node.js:386 +#: htdocs/luci-static/resources/view/fchomo/node.js:387 msgid "The ED25519 available private key or UUID provided by Sudoku server." msgstr "Sudoku 服务器提供的 ED25519 可用私钥 或 UUID。" -#: htdocs/luci-static/resources/fchomo/listeners.js:255 +#: htdocs/luci-static/resources/fchomo/listeners.js:286 msgid "The ED25519 master public key or UUID generated by Sudoku." msgstr "Sudoku 生成的 ED25519 主公钥 或 UUID。" @@ -2958,8 +3014,8 @@ msgstr "Sudoku 生成的 ED25519 主公钥 或 UUID。" msgid "The default value is 2:00 every day." msgstr "默认值为每天 2:00。" -#: htdocs/luci-static/resources/fchomo/listeners.js:664 -#: htdocs/luci-static/resources/view/fchomo/node.js:941 +#: htdocs/luci-static/resources/fchomo/listeners.js:702 +#: htdocs/luci-static/resources/view/fchomo/node.js:942 msgid "" "The first padding must have a probability of 100% and at least 35 bytes." msgstr "首个填充必须为 100% 的概率并且至少 35 字节。" @@ -2974,26 +3030,26 @@ msgstr "匹配 %s 的将被视为未被投毒污染。" msgid "The matching %s will be deemed as poisoned." msgstr "匹配 %s 的将被视为已被投毒污染。" -#: htdocs/luci-static/resources/fchomo/listeners.js:662 -#: htdocs/luci-static/resources/view/fchomo/node.js:939 +#: htdocs/luci-static/resources/fchomo/listeners.js:700 +#: htdocs/luci-static/resources/view/fchomo/node.js:940 msgid "The server and client can set different padding parameters." msgstr "服务器和客户端可以设置不同的填充参数。" -#: htdocs/luci-static/resources/fchomo/listeners.js:925 +#: htdocs/luci-static/resources/fchomo/listeners.js:1014 #: htdocs/luci-static/resources/view/fchomo/global.js:594 msgid "This ECH parameter needs to be added to the HTTPS record of the domain." msgstr "此 ECH 参数需要添加到域名的 HTTPS 记录中。" #: htdocs/luci-static/resources/view/fchomo/client.js:1579 -#: htdocs/luci-static/resources/view/fchomo/node.js:1054 -#: htdocs/luci-static/resources/view/fchomo/node.js:1722 +#: htdocs/luci-static/resources/view/fchomo/node.js:1089 +#: htdocs/luci-static/resources/view/fchomo/node.js:1757 msgid "" "This is DANGEROUS, your traffic is almost like " "PLAIN TEXT! Use at your own risk!" msgstr "" "这是危险行为,您的流量将几乎等同于明文!使用风险自负!" -#: htdocs/luci-static/resources/view/fchomo/node.js:536 +#: htdocs/luci-static/resources/view/fchomo/node.js:537 msgid "" "This is the TUIC port of the SUoT protocol, designed to provide a QUIC " "stream based UDP relay mode that TUIC does not provide." @@ -3025,33 +3081,33 @@ msgstr "Tproxy Fwmark/fwmask" msgid "Tproxy port" msgstr "Tproxy 端口" -#: htdocs/luci-static/resources/fchomo/listeners.js:243 -#: htdocs/luci-static/resources/view/fchomo/node.js:378 +#: htdocs/luci-static/resources/fchomo/listeners.js:274 +#: htdocs/luci-static/resources/view/fchomo/node.js:379 msgid "Traffic pattern" msgstr "流量模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1881 +#: htdocs/luci-static/resources/view/fchomo/node.js:1916 msgid "Transit proxy group" msgstr "中转代理组" -#: htdocs/luci-static/resources/view/fchomo/node.js:1887 +#: htdocs/luci-static/resources/view/fchomo/node.js:1922 msgid "Transit proxy node" msgstr "中转代理节点" -#: htdocs/luci-static/resources/fchomo/listeners.js:231 -#: htdocs/luci-static/resources/fchomo/listeners.js:976 -#: htdocs/luci-static/resources/view/fchomo/node.js:355 -#: htdocs/luci-static/resources/view/fchomo/node.js:1136 +#: htdocs/luci-static/resources/fchomo/listeners.js:262 +#: htdocs/luci-static/resources/fchomo/listeners.js:1065 +#: htdocs/luci-static/resources/view/fchomo/node.js:356 +#: htdocs/luci-static/resources/view/fchomo/node.js:1171 msgid "Transport" msgstr "传输层" -#: htdocs/luci-static/resources/fchomo/listeners.js:122 -#: htdocs/luci-static/resources/view/fchomo/node.js:225 +#: htdocs/luci-static/resources/fchomo/listeners.js:123 +#: htdocs/luci-static/resources/view/fchomo/node.js:226 msgid "Transport fields" msgstr "传输层字段" -#: htdocs/luci-static/resources/fchomo/listeners.js:981 -#: htdocs/luci-static/resources/view/fchomo/node.js:1141 +#: htdocs/luci-static/resources/fchomo/listeners.js:1070 +#: htdocs/luci-static/resources/view/fchomo/node.js:1176 msgid "Transport type" msgstr "传输层类型" @@ -3060,15 +3116,19 @@ msgid "Treat the destination IP as the source IP." msgstr "将 目标 IP 视为 来源 IP。" #: htdocs/luci-static/resources/fchomo.js:161 -#: htdocs/luci-static/resources/fchomo.js:195 +#: htdocs/luci-static/resources/fchomo.js:196 msgid "Trojan" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:165 -#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:166 +#: htdocs/luci-static/resources/fchomo.js:202 msgid "TrustTunnel" msgstr "" +#: htdocs/luci-static/resources/fchomo/listeners.js:232 +msgid "Trusted proxy header" +msgstr "可信代理 Header" + #: htdocs/luci-static/resources/view/fchomo/global.js:764 msgid "Tun Fwmark/fwmask" msgstr "Tun Fwmark/fwmask" @@ -3085,35 +3145,35 @@ msgstr "Tun 设置" msgid "Tun stack." msgstr "Tun 堆栈" -#: htdocs/luci-static/resources/fchomo.js:166 +#: htdocs/luci-static/resources/fchomo.js:167 msgid "Tunnel" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:141 +#: htdocs/luci-static/resources/fchomo/listeners.js:142 #: htdocs/luci-static/resources/view/fchomo/client.js:530 #: htdocs/luci-static/resources/view/fchomo/client.js:643 #: htdocs/luci-static/resources/view/fchomo/client.js:737 #: htdocs/luci-static/resources/view/fchomo/client.js:842 #: htdocs/luci-static/resources/view/fchomo/client.js:1028 -#: htdocs/luci-static/resources/view/fchomo/node.js:238 -#: htdocs/luci-static/resources/view/fchomo/node.js:1564 -#: htdocs/luci-static/resources/view/fchomo/node.js:1852 +#: htdocs/luci-static/resources/view/fchomo/node.js:239 +#: htdocs/luci-static/resources/view/fchomo/node.js:1599 +#: htdocs/luci-static/resources/view/fchomo/node.js:1887 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:276 msgid "Type" msgstr "类型" #: htdocs/luci-static/resources/fchomo.js:163 #: htdocs/luci-static/resources/fchomo.js:164 -#: htdocs/luci-static/resources/fchomo.js:198 #: htdocs/luci-static/resources/fchomo.js:199 #: htdocs/luci-static/resources/fchomo.js:200 -#: htdocs/luci-static/resources/fchomo.js:202 -#: htdocs/luci-static/resources/fchomo/listeners.js:564 -#: htdocs/luci-static/resources/fchomo/listeners.js:569 +#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:203 +#: htdocs/luci-static/resources/fchomo/listeners.js:602 +#: htdocs/luci-static/resources/fchomo/listeners.js:607 #: htdocs/luci-static/resources/view/fchomo/client.js:588 #: htdocs/luci-static/resources/view/fchomo/client.js:678 -#: htdocs/luci-static/resources/view/fchomo/node.js:874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1696 +#: htdocs/luci-static/resources/view/fchomo/node.js:875 +#: htdocs/luci-static/resources/view/fchomo/node.js:1731 msgid "UDP" msgstr "UDP" @@ -3121,42 +3181,42 @@ msgstr "UDP" msgid "UDP NAT expiration time" msgstr "UDP NAT 过期时间" -#: htdocs/luci-static/resources/view/fchomo/node.js:535 +#: htdocs/luci-static/resources/view/fchomo/node.js:536 msgid "UDP over stream" msgstr "UDP over stream" -#: htdocs/luci-static/resources/view/fchomo/node.js:541 +#: htdocs/luci-static/resources/view/fchomo/node.js:542 msgid "UDP over stream version" msgstr "UDP over stream 版本" -#: htdocs/luci-static/resources/view/fchomo/node.js:528 +#: htdocs/luci-static/resources/view/fchomo/node.js:529 msgid "UDP packet relay mode." msgstr "UDP 包中继模式。" -#: htdocs/luci-static/resources/view/fchomo/node.js:527 +#: htdocs/luci-static/resources/view/fchomo/node.js:528 msgid "UDP relay mode" msgstr "UDP 中继模式" -#: htdocs/luci-static/resources/fchomo/listeners.js:330 -#: htdocs/luci-static/resources/fchomo/listeners.js:331 -#: htdocs/luci-static/resources/view/fchomo/node.js:410 +#: htdocs/luci-static/resources/fchomo/listeners.js:361 +#: htdocs/luci-static/resources/fchomo/listeners.js:362 #: htdocs/luci-static/resources/view/fchomo/node.js:411 +#: htdocs/luci-static/resources/view/fchomo/node.js:412 msgid "UP: %s; DOWN: %s" msgstr "上传: %s; 下载: %s" -#: htdocs/luci-static/resources/fchomo.js:230 +#: htdocs/luci-static/resources/fchomo.js:231 msgid "URL test" msgstr "自动选择" -#: htdocs/luci-static/resources/fchomo/listeners.js:252 -#: htdocs/luci-static/resources/fchomo/listeners.js:413 -#: htdocs/luci-static/resources/fchomo/listeners.js:468 -#: htdocs/luci-static/resources/view/fchomo/node.js:515 -#: htdocs/luci-static/resources/view/fchomo/node.js:624 +#: htdocs/luci-static/resources/fchomo/listeners.js:283 +#: htdocs/luci-static/resources/fchomo/listeners.js:444 +#: htdocs/luci-static/resources/fchomo/listeners.js:499 +#: htdocs/luci-static/resources/view/fchomo/node.js:516 +#: htdocs/luci-static/resources/view/fchomo/node.js:625 msgid "UUID" msgstr "UUID" -#: htdocs/luci-static/resources/fchomo.js:1249 +#: htdocs/luci-static/resources/fchomo.js:1250 msgid "Unable to download unsupported type: %s" msgstr "无法下载不支持的类型: %s" @@ -3181,8 +3241,8 @@ msgstr "未知错误。" msgid "Unknown error: %s" msgstr "未知错误:%s" -#: htdocs/luci-static/resources/view/fchomo/node.js:879 -#: htdocs/luci-static/resources/view/fchomo/node.js:1701 +#: htdocs/luci-static/resources/view/fchomo/node.js:880 +#: htdocs/luci-static/resources/view/fchomo/node.js:1736 msgid "UoT" msgstr "UDP over TCP (UoT)" @@ -3190,22 +3250,22 @@ msgstr "UDP over TCP (UoT)" msgid "Update failed." msgstr "更新失败。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1633 +#: htdocs/luci-static/resources/view/fchomo/node.js:1668 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:382 msgid "Update interval" msgstr "更新间隔" -#: htdocs/luci-static/resources/view/fchomo/node.js:1393 +#: htdocs/luci-static/resources/view/fchomo/node.js:1428 msgid "Upload bandwidth" msgstr "上传带宽" -#: htdocs/luci-static/resources/view/fchomo/node.js:1394 +#: htdocs/luci-static/resources/view/fchomo/node.js:1429 msgid "Upload bandwidth in Mbps." msgstr "上传带宽(单位:Mbps)。" -#: htdocs/luci-static/resources/fchomo/listeners.js:835 -#: htdocs/luci-static/resources/fchomo/listeners.js:875 -#: htdocs/luci-static/resources/view/fchomo/node.js:1065 +#: htdocs/luci-static/resources/fchomo/listeners.js:924 +#: htdocs/luci-static/resources/fchomo/listeners.js:964 +#: htdocs/luci-static/resources/view/fchomo/node.js:1100 msgid "Upload certificate" msgstr "上传证书" @@ -3213,17 +3273,17 @@ msgstr "上传证书" msgid "Upload initial package" msgstr "上传初始资源包" -#: htdocs/luci-static/resources/fchomo/listeners.js:850 -#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/fchomo/listeners.js:939 +#: htdocs/luci-static/resources/view/fchomo/node.js:1114 msgid "Upload key" msgstr "上传密钥" -#: htdocs/luci-static/resources/fchomo/listeners.js:838 -#: htdocs/luci-static/resources/fchomo/listeners.js:853 -#: htdocs/luci-static/resources/fchomo/listeners.js:878 +#: htdocs/luci-static/resources/fchomo/listeners.js:927 +#: htdocs/luci-static/resources/fchomo/listeners.js:942 +#: htdocs/luci-static/resources/fchomo/listeners.js:967 #: htdocs/luci-static/resources/view/fchomo/global.js:306 -#: htdocs/luci-static/resources/view/fchomo/node.js:1068 -#: htdocs/luci-static/resources/view/fchomo/node.js:1082 +#: htdocs/luci-static/resources/view/fchomo/node.js:1103 +#: htdocs/luci-static/resources/view/fchomo/node.js:1117 msgid "Upload..." msgstr "上传..." @@ -3247,7 +3307,7 @@ msgstr "用于解析 DNS 服务器的域名。必须是 IP。" msgid "Used to resolve the domain of the Proxy node." msgstr "用于解析代理节点的域名。" -#: htdocs/luci-static/resources/view/fchomo/node.js:986 +#: htdocs/luci-static/resources/view/fchomo/node.js:1021 msgid "Used to verify the hostname on the returned certificates." msgstr "用于验证返回的证书上的主机名。" @@ -3255,12 +3315,12 @@ msgstr "用于验证返回的证书上的主机名。" msgid "User Authentication" msgstr "用户认证" -#: htdocs/luci-static/resources/fchomo/listeners.js:238 +#: htdocs/luci-static/resources/fchomo/listeners.js:269 msgid "User-hint is mandatory" msgstr "User-hint 是必填项" -#: htdocs/luci-static/resources/fchomo/listeners.js:160 -#: htdocs/luci-static/resources/view/fchomo/node.js:256 +#: htdocs/luci-static/resources/fchomo/listeners.js:161 +#: htdocs/luci-static/resources/view/fchomo/node.js:257 msgid "Username" msgstr "用户名" @@ -3268,41 +3328,41 @@ msgstr "用户名" msgid "Users filter mode" msgstr "使用者过滤模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1250 +#: htdocs/luci-static/resources/view/fchomo/node.js:1285 msgid "V2ray HTTPUpgrade" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1255 +#: htdocs/luci-static/resources/view/fchomo/node.js:1290 msgid "V2ray HTTPUpgrade fast open" msgstr "" #: htdocs/luci-static/resources/fchomo.js:160 -#: htdocs/luci-static/resources/fchomo.js:194 +#: htdocs/luci-static/resources/fchomo.js:195 msgid "VLESS" msgstr "" #: htdocs/luci-static/resources/fchomo.js:159 -#: htdocs/luci-static/resources/fchomo.js:193 +#: htdocs/luci-static/resources/fchomo.js:194 msgid "VMess" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1570 -#: htdocs/luci-static/resources/view/fchomo/node.js:1858 +#: htdocs/luci-static/resources/view/fchomo/node.js:1605 +#: htdocs/luci-static/resources/view/fchomo/node.js:1893 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:319 msgid "Value" msgstr "可视化值" -#: htdocs/luci-static/resources/fchomo.js:359 +#: htdocs/luci-static/resources/fchomo.js:360 msgid "Verify if given" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:519 -#: htdocs/luci-static/resources/view/fchomo/node.js:506 -#: htdocs/luci-static/resources/view/fchomo/node.js:836 +#: htdocs/luci-static/resources/fchomo/listeners.js:557 +#: htdocs/luci-static/resources/view/fchomo/node.js:507 +#: htdocs/luci-static/resources/view/fchomo/node.js:837 msgid "Version" msgstr "版本" -#: htdocs/luci-static/resources/view/fchomo/node.js:844 +#: htdocs/luci-static/resources/view/fchomo/node.js:845 msgid "Version hint" msgstr "" @@ -3311,7 +3371,7 @@ msgstr "" msgid "Vless Encryption fields" msgstr "Vless Encryption 字段" -#: htdocs/luci-static/resources/fchomo.js:396 +#: htdocs/luci-static/resources/fchomo.js:397 msgid "Wait a random 0-111 milliseconds with 75% probability." msgstr "以 75% 的概率等待随机 0-111 毫秒。" @@ -3319,16 +3379,16 @@ msgstr "以 75% 的概率等待随机 0-111 毫秒。" msgid "Warning" msgstr "警告" -#: htdocs/luci-static/resources/fchomo/listeners.js:398 -#: htdocs/luci-static/resources/fchomo/listeners.js:983 -#: htdocs/luci-static/resources/fchomo/listeners.js:992 -#: htdocs/luci-static/resources/fchomo/listeners.js:999 -#: htdocs/luci-static/resources/view/fchomo/node.js:460 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:1146 -#: htdocs/luci-static/resources/view/fchomo/node.js:1157 -#: htdocs/luci-static/resources/view/fchomo/node.js:1164 -#: htdocs/luci-static/resources/view/fchomo/node.js:1170 +#: htdocs/luci-static/resources/fchomo/listeners.js:429 +#: htdocs/luci-static/resources/fchomo/listeners.js:1072 +#: htdocs/luci-static/resources/fchomo/listeners.js:1081 +#: htdocs/luci-static/resources/fchomo/listeners.js:1088 +#: htdocs/luci-static/resources/view/fchomo/node.js:461 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:1181 +#: htdocs/luci-static/resources/view/fchomo/node.js:1192 +#: htdocs/luci-static/resources/view/fchomo/node.js:1199 +#: htdocs/luci-static/resources/view/fchomo/node.js:1205 msgid "WebSocket" msgstr "" @@ -3340,52 +3400,52 @@ msgstr "用作服务端时,HomeProxy 是更好的选择。" msgid "White list" msgstr "白名单" -#: htdocs/luci-static/resources/fchomo.js:202 +#: htdocs/luci-static/resources/fchomo.js:203 msgid "WireGuard" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:755 +#: htdocs/luci-static/resources/view/fchomo/node.js:756 msgid "WireGuard peer public key." msgstr "WireGuard 对端公钥。" -#: htdocs/luci-static/resources/view/fchomo/node.js:762 +#: htdocs/luci-static/resources/view/fchomo/node.js:763 msgid "WireGuard pre-shared key." msgstr "WireGuard 预共享密钥。" -#: htdocs/luci-static/resources/view/fchomo/node.js:747 +#: htdocs/luci-static/resources/view/fchomo/node.js:748 msgid "WireGuard requires base64-encoded private keys." msgstr "WireGuard 要求 base64 编码的私钥。" -#: htdocs/luci-static/resources/fchomo/listeners.js:984 -#: htdocs/luci-static/resources/fchomo/listeners.js:993 -#: htdocs/luci-static/resources/view/fchomo/node.js:1147 -#: htdocs/luci-static/resources/view/fchomo/node.js:1165 +#: htdocs/luci-static/resources/fchomo/listeners.js:1073 +#: htdocs/luci-static/resources/fchomo/listeners.js:1082 +#: htdocs/luci-static/resources/view/fchomo/node.js:1182 +#: htdocs/luci-static/resources/view/fchomo/node.js:1200 msgid "XHTTP" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1029 -#: htdocs/luci-static/resources/view/fchomo/node.js:1260 +#: htdocs/luci-static/resources/fchomo/listeners.js:1118 +#: htdocs/luci-static/resources/view/fchomo/node.js:1295 msgid "XHTTP mode" msgstr "XHTTP 模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1291 +#: htdocs/luci-static/resources/view/fchomo/node.js:1326 msgid "XMUX" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1296 -#: htdocs/luci-static/resources/view/fchomo/node.js:1301 -#: htdocs/luci-static/resources/view/fchomo/node.js:1306 -#: htdocs/luci-static/resources/view/fchomo/node.js:1311 -#: htdocs/luci-static/resources/view/fchomo/node.js:1316 -#: htdocs/luci-static/resources/view/fchomo/node.js:1321 +#: htdocs/luci-static/resources/view/fchomo/node.js:1331 +#: htdocs/luci-static/resources/view/fchomo/node.js:1336 +#: htdocs/luci-static/resources/view/fchomo/node.js:1341 +#: htdocs/luci-static/resources/view/fchomo/node.js:1346 +#: htdocs/luci-static/resources/view/fchomo/node.js:1351 +#: htdocs/luci-static/resources/view/fchomo/node.js:1356 msgid "XMUX:" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:623 +#: htdocs/luci-static/resources/fchomo/listeners.js:661 msgid "XOR mode" msgstr "XOR 模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:669 +#: htdocs/luci-static/resources/view/fchomo/node.js:670 msgid "Xudp (Xray-core)" msgstr "" @@ -3393,7 +3453,7 @@ msgstr "" msgid "Yaml text" msgstr "Yaml 格式文本" -#: htdocs/luci-static/resources/view/fchomo/node.js:1725 +#: htdocs/luci-static/resources/view/fchomo/node.js:1760 msgid "Yes" msgstr "" @@ -3401,27 +3461,27 @@ msgstr "" msgid "YouTube" msgstr "油管" -#: htdocs/luci-static/resources/fchomo.js:1688 +#: htdocs/luci-static/resources/fchomo.js:1689 msgid "Your %s was successfully uploaded. Size: %sB." msgstr "您的 %s 已成功上传。大小:%sB。" -#: htdocs/luci-static/resources/fchomo.js:332 -#: htdocs/luci-static/resources/fchomo.js:345 -#: htdocs/luci-static/resources/fchomo.js:350 -#: htdocs/luci-static/resources/view/fchomo/node.js:649 +#: htdocs/luci-static/resources/fchomo.js:333 +#: htdocs/luci-static/resources/fchomo.js:346 +#: htdocs/luci-static/resources/fchomo.js:351 +#: htdocs/luci-static/resources/view/fchomo/node.js:650 msgid "aes-128-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:333 +#: htdocs/luci-static/resources/fchomo.js:334 msgid "aes-192-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:334 -#: htdocs/luci-static/resources/fchomo.js:351 +#: htdocs/luci-static/resources/fchomo.js:335 +#: htdocs/luci-static/resources/fchomo.js:352 msgid "aes-256-gcm" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:646 +#: htdocs/luci-static/resources/view/fchomo/node.js:647 msgid "auto" msgstr "自动" @@ -3429,19 +3489,19 @@ msgstr "自动" msgid "bbr" msgstr "bbr" -#: htdocs/luci-static/resources/fchomo/listeners.js:840 -#: htdocs/luci-static/resources/fchomo/listeners.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:1070 +#: htdocs/luci-static/resources/fchomo/listeners.js:929 +#: htdocs/luci-static/resources/fchomo/listeners.js:969 +#: htdocs/luci-static/resources/view/fchomo/node.js:1105 msgid "certificate" msgstr "证书" -#: htdocs/luci-static/resources/fchomo.js:335 -#: htdocs/luci-static/resources/fchomo.js:346 -#: htdocs/luci-static/resources/fchomo.js:352 +#: htdocs/luci-static/resources/fchomo.js:336 +#: htdocs/luci-static/resources/fchomo.js:347 +#: htdocs/luci-static/resources/fchomo.js:353 msgid "chacha20-ietf-poly1305" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:650 +#: htdocs/luci-static/resources/view/fchomo/node.js:651 msgid "chacha20-poly1305" msgstr "" @@ -3449,8 +3509,8 @@ msgstr "" msgid "cubic" msgstr "cubic" -#: htdocs/luci-static/resources/fchomo/listeners.js:575 -#: htdocs/luci-static/resources/fchomo/listeners.js:606 +#: htdocs/luci-static/resources/fchomo/listeners.js:613 +#: htdocs/luci-static/resources/fchomo/listeners.js:644 msgid "decryption" msgstr "decryption" @@ -3458,41 +3518,41 @@ msgstr "decryption" msgid "dnsmasq selects upstream on its own. (may affect CDN accuracy)" msgstr "dnsmasq 自行选择上游服务器。 (可能影响 CDN 准确性)" -#: htdocs/luci-static/resources/view/fchomo/node.js:1713 +#: htdocs/luci-static/resources/view/fchomo/node.js:1748 msgid "down" msgstr "Hysteria 下载速率" -#: htdocs/luci-static/resources/fchomo/listeners.js:610 -#: htdocs/luci-static/resources/view/fchomo/node.js:893 -#: htdocs/luci-static/resources/view/fchomo/node.js:916 +#: htdocs/luci-static/resources/fchomo/listeners.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:894 +#: htdocs/luci-static/resources/view/fchomo/node.js:917 msgid "encryption" msgstr "encryption" -#: htdocs/luci-static/resources/fchomo/listeners.js:382 -#: htdocs/luci-static/resources/view/fchomo/node.js:444 +#: htdocs/luci-static/resources/fchomo/listeners.js:413 +#: htdocs/luci-static/resources/view/fchomo/node.js:445 msgid "false = bandwidth optimized downlink; true = pure Sudoku downlink." msgstr "false = 带宽优化下行 true = 纯 Sudoku 下行。" -#: htdocs/luci-static/resources/fchomo/listeners.js:982 -#: htdocs/luci-static/resources/fchomo/listeners.js:991 -#: htdocs/luci-static/resources/fchomo/listeners.js:998 -#: htdocs/luci-static/resources/view/fchomo/node.js:1145 -#: htdocs/luci-static/resources/view/fchomo/node.js:1156 -#: htdocs/luci-static/resources/view/fchomo/node.js:1163 -#: htdocs/luci-static/resources/view/fchomo/node.js:1169 +#: htdocs/luci-static/resources/fchomo/listeners.js:1071 +#: htdocs/luci-static/resources/fchomo/listeners.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1180 +#: htdocs/luci-static/resources/view/fchomo/node.js:1191 +#: htdocs/luci-static/resources/view/fchomo/node.js:1198 +#: htdocs/luci-static/resources/view/fchomo/node.js:1204 msgid "gRPC" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1226 +#: htdocs/luci-static/resources/view/fchomo/node.js:1261 msgid "gRPC User-Agent" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1231 +#: htdocs/luci-static/resources/view/fchomo/node.js:1266 msgid "gRPC ping interval" msgstr "gRPC ping 间隔" -#: htdocs/luci-static/resources/fchomo/listeners.js:1023 -#: htdocs/luci-static/resources/view/fchomo/node.js:1222 +#: htdocs/luci-static/resources/fchomo/listeners.js:1112 +#: htdocs/luci-static/resources/view/fchomo/node.js:1257 msgid "gRPC service name" msgstr "gRPC 服务名称" @@ -3500,11 +3560,11 @@ msgstr "gRPC 服务名称" msgid "gVisor" msgstr "gVisor" -#: htdocs/luci-static/resources/view/fchomo/node.js:1338 +#: htdocs/luci-static/resources/view/fchomo/node.js:1373 msgid "h2mux" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:775 +#: htdocs/luci-static/resources/fchomo/listeners.js:813 msgid "least one keypair required" msgstr "至少需要一对密钥" @@ -3518,17 +3578,17 @@ msgstr "metacubexd" #: htdocs/luci-static/resources/view/fchomo/client.js:1480 #: htdocs/luci-static/resources/view/fchomo/client.js:1711 #: htdocs/luci-static/resources/view/fchomo/client.js:1767 -#: htdocs/luci-static/resources/view/fchomo/node.js:1536 +#: htdocs/luci-static/resources/view/fchomo/node.js:1571 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:239 msgid "mihomo config" msgstr "mihomo 配置" -#: htdocs/luci-static/resources/fchomo.js:378 +#: htdocs/luci-static/resources/fchomo.js:379 msgid "mlkem768x25519plus" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1410 -#: htdocs/luci-static/resources/view/fchomo/node.js:1691 +#: htdocs/luci-static/resources/view/fchomo/node.js:1445 +#: htdocs/luci-static/resources/view/fchomo/node.js:1726 msgid "mpTCP" msgstr "多路径 TCP (mpTCP)" @@ -3540,20 +3600,20 @@ msgstr "new_reno" msgid "no-resolve" msgstr "no-resolve" -#: htdocs/luci-static/resources/fchomo.js:1423 -#: htdocs/luci-static/resources/fchomo.js:1518 -#: htdocs/luci-static/resources/fchomo.js:1553 -#: htdocs/luci-static/resources/fchomo.js:1581 +#: htdocs/luci-static/resources/fchomo.js:1424 +#: htdocs/luci-static/resources/fchomo.js:1519 +#: htdocs/luci-static/resources/fchomo.js:1554 +#: htdocs/luci-static/resources/fchomo.js:1582 msgid "non-empty value" msgstr "非空值" -#: htdocs/luci-static/resources/fchomo.js:330 -#: htdocs/luci-static/resources/fchomo.js:344 -#: htdocs/luci-static/resources/fchomo.js:356 -#: htdocs/luci-static/resources/fchomo/listeners.js:500 -#: htdocs/luci-static/resources/view/fchomo/node.js:647 -#: htdocs/luci-static/resources/view/fchomo/node.js:667 -#: htdocs/luci-static/resources/view/fchomo/node.js:805 +#: htdocs/luci-static/resources/fchomo.js:331 +#: htdocs/luci-static/resources/fchomo.js:345 +#: htdocs/luci-static/resources/fchomo.js:357 +#: htdocs/luci-static/resources/fchomo/listeners.js:531 +#: htdocs/luci-static/resources/view/fchomo/node.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:668 +#: htdocs/luci-static/resources/view/fchomo/node.js:806 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:315 msgid "none" msgstr "无" @@ -3566,44 +3626,45 @@ msgstr "未找到" msgid "not included \",\"" msgstr "不包含 \",\"" -#: htdocs/luci-static/resources/fchomo.js:216 -#: htdocs/luci-static/resources/fchomo/listeners.js:531 -#: htdocs/luci-static/resources/fchomo/listeners.js:532 +#: htdocs/luci-static/resources/fchomo.js:217 +#: htdocs/luci-static/resources/fchomo/listeners.js:569 +#: htdocs/luci-static/resources/fchomo/listeners.js:570 msgid "null" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:806 +#: htdocs/luci-static/resources/fchomo/listeners.js:532 +#: htdocs/luci-static/resources/view/fchomo/node.js:807 msgid "obfs-simple" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "only applies when %s is %s." msgstr "仅当 %s 为 %s 时适用。" -#: htdocs/luci-static/resources/view/fchomo/node.js:489 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 msgid "only applies when %s is not %s." msgstr "仅当 %s 不为 %s 时适用。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1671 +#: htdocs/luci-static/resources/view/fchomo/node.js:1706 msgid "override.proxy-name" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:668 +#: htdocs/luci-static/resources/view/fchomo/node.js:669 msgid "packet addr (v2ray-core v5+)" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1033 -#: htdocs/luci-static/resources/view/fchomo/node.js:1264 +#: htdocs/luci-static/resources/fchomo/listeners.js:1122 +#: htdocs/luci-static/resources/view/fchomo/node.js:1299 msgid "packet-up" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:396 -#: htdocs/luci-static/resources/view/fchomo/node.js:458 +#: htdocs/luci-static/resources/fchomo/listeners.js:427 +#: htdocs/luci-static/resources/view/fchomo/node.js:459 msgid "poll" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:855 -#: htdocs/luci-static/resources/view/fchomo/node.js:1084 +#: htdocs/luci-static/resources/fchomo/listeners.js:944 +#: htdocs/luci-static/resources/view/fchomo/node.js:1119 msgid "private key" msgstr "私钥" @@ -3616,7 +3677,7 @@ msgstr "razord-meta" msgid "requires front-end adaptation using the API." msgstr "需要使用 API 的前端适配。" -#: htdocs/luci-static/resources/view/fchomo/node.js:810 +#: htdocs/luci-static/resources/view/fchomo/node.js:811 msgid "restls" msgstr "" @@ -3624,17 +3685,17 @@ msgstr "" msgid "rule-set" msgstr "规则集" -#: htdocs/luci-static/resources/fchomo/listeners.js:501 -#: htdocs/luci-static/resources/view/fchomo/node.js:809 +#: htdocs/luci-static/resources/fchomo/listeners.js:533 +#: htdocs/luci-static/resources/view/fchomo/node.js:810 msgid "shadow-tls" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1336 +#: htdocs/luci-static/resources/view/fchomo/node.js:1371 msgid "smux" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:395 -#: htdocs/luci-static/resources/view/fchomo/node.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:426 +#: htdocs/luci-static/resources/view/fchomo/node.js:458 msgid "split-stream" msgstr "" @@ -3642,25 +3703,25 @@ msgstr "" msgid "src" msgstr "src" -#: htdocs/luci-static/resources/fchomo/listeners.js:1031 -#: htdocs/luci-static/resources/view/fchomo/node.js:1262 +#: htdocs/luci-static/resources/fchomo/listeners.js:1120 +#: htdocs/luci-static/resources/view/fchomo/node.js:1297 msgid "stream-one" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1032 -#: htdocs/luci-static/resources/view/fchomo/node.js:1263 +#: htdocs/luci-static/resources/fchomo/listeners.js:1121 +#: htdocs/luci-static/resources/view/fchomo/node.js:1298 msgid "stream-up" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1048 +#: htdocs/luci-static/resources/fchomo/listeners.js:1137 msgid "stream-up server seconds" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "stream/poll/auto" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:251 +#: htdocs/luci-static/resources/fchomo/listeners.js:282 msgid "sudoku-keypair" msgstr "" @@ -3668,87 +3729,87 @@ msgstr "" msgid "unchecked" msgstr "未检查" -#: htdocs/luci-static/resources/fchomo.js:442 +#: htdocs/luci-static/resources/fchomo.js:443 msgid "unique UCI identifier" msgstr "独立 UCI 标识" -#: htdocs/luci-static/resources/fchomo.js:445 +#: htdocs/luci-static/resources/fchomo.js:446 msgid "unique identifier" msgstr "独立标识" -#: htdocs/luci-static/resources/fchomo.js:1590 +#: htdocs/luci-static/resources/fchomo.js:1591 msgid "unique value" msgstr "独立值" -#: htdocs/luci-static/resources/view/fchomo/node.js:1707 +#: htdocs/luci-static/resources/view/fchomo/node.js:1742 msgid "up" msgstr "Hysteria 上传速率" -#: htdocs/luci-static/resources/fchomo/listeners.js:520 -#: htdocs/luci-static/resources/view/fchomo/node.js:507 -#: htdocs/luci-static/resources/view/fchomo/node.js:542 -#: htdocs/luci-static/resources/view/fchomo/node.js:837 -#: htdocs/luci-static/resources/view/fchomo/node.js:886 +#: htdocs/luci-static/resources/fchomo/listeners.js:558 +#: htdocs/luci-static/resources/view/fchomo/node.js:508 +#: htdocs/luci-static/resources/view/fchomo/node.js:543 +#: htdocs/luci-static/resources/view/fchomo/node.js:838 +#: htdocs/luci-static/resources/view/fchomo/node.js:887 msgid "v1" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:521 -#: htdocs/luci-static/resources/view/fchomo/node.js:508 -#: htdocs/luci-static/resources/view/fchomo/node.js:838 -#: htdocs/luci-static/resources/view/fchomo/node.js:887 +#: htdocs/luci-static/resources/fchomo/listeners.js:559 +#: htdocs/luci-static/resources/view/fchomo/node.js:509 +#: htdocs/luci-static/resources/view/fchomo/node.js:839 +#: htdocs/luci-static/resources/view/fchomo/node.js:888 msgid "v2" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:522 -#: htdocs/luci-static/resources/view/fchomo/node.js:509 -#: htdocs/luci-static/resources/view/fchomo/node.js:839 +#: htdocs/luci-static/resources/fchomo/listeners.js:560 +#: htdocs/luci-static/resources/view/fchomo/node.js:510 +#: htdocs/luci-static/resources/view/fchomo/node.js:840 msgid "v3" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1470 -#: htdocs/luci-static/resources/fchomo.js:1473 +#: htdocs/luci-static/resources/fchomo.js:1471 +#: htdocs/luci-static/resources/fchomo.js:1474 msgid "valid JSON format" msgstr "有效的 JSON 格式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1044 +#: htdocs/luci-static/resources/view/fchomo/node.js:1079 msgid "valid SHA256 string with %d characters" msgstr "包含 %d 个字符的有效 SHA256 字符串" -#: htdocs/luci-static/resources/fchomo.js:1495 -#: htdocs/luci-static/resources/fchomo.js:1498 +#: htdocs/luci-static/resources/fchomo.js:1496 +#: htdocs/luci-static/resources/fchomo.js:1499 msgid "valid URL" msgstr "有效网址" -#: htdocs/luci-static/resources/fchomo.js:1508 +#: htdocs/luci-static/resources/fchomo.js:1509 msgid "valid base64 key with %d characters" msgstr "包含 %d 个字符的有效 base64 密钥" -#: htdocs/luci-static/resources/fchomo.js:1568 -#: htdocs/luci-static/resources/fchomo.js:1574 +#: htdocs/luci-static/resources/fchomo.js:1569 +#: htdocs/luci-static/resources/fchomo.js:1575 msgid "valid format: 2x, 2p, 4v" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1555 +#: htdocs/luci-static/resources/fchomo.js:1556 msgid "valid key length with %d characters" msgstr "包含 %d 个字符的有效密钥" -#: htdocs/luci-static/resources/fchomo.js:1433 +#: htdocs/luci-static/resources/fchomo.js:1434 msgid "valid port value" msgstr "有效端口值" -#: htdocs/luci-static/resources/fchomo.js:1483 +#: htdocs/luci-static/resources/fchomo.js:1484 msgid "valid uuid" msgstr "有效 uuid" -#: htdocs/luci-static/resources/fchomo.js:402 +#: htdocs/luci-static/resources/fchomo.js:403 msgid "vless-mlkem768" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:401 +#: htdocs/luci-static/resources/fchomo.js:402 msgid "vless-x25519" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:336 +#: htdocs/luci-static/resources/fchomo.js:337 msgid "xchacha20-ietf-poly1305" msgstr "" @@ -3756,7 +3817,7 @@ msgstr "" msgid "yacd-meta" msgstr "yacd-meta" -#: htdocs/luci-static/resources/view/fchomo/node.js:1337 +#: htdocs/luci-static/resources/view/fchomo/node.js:1372 msgid "yamux" msgstr "" @@ -3764,11 +3825,11 @@ msgstr "" msgid "zashboard" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:649 msgid "zero" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1251 +#: htdocs/luci-static/resources/fchomo.js:1252 msgid "🡇" msgstr "" diff --git a/luci-app-fchomo/po/zh_Hant/fchomo.po b/luci-app-fchomo/po/zh_Hant/fchomo.po index ac3d3c30..f11a3186 100644 --- a/luci-app-fchomo/po/zh_Hant/fchomo.po +++ b/luci-app-fchomo/po/zh_Hant/fchomo.po @@ -12,30 +12,30 @@ msgstr "" msgid "%s log" msgstr "%s 日誌" -#: htdocs/luci-static/resources/fchomo.js:239 #: htdocs/luci-static/resources/fchomo.js:240 #: htdocs/luci-static/resources/fchomo.js:241 #: htdocs/luci-static/resources/fchomo.js:242 #: htdocs/luci-static/resources/fchomo.js:243 #: htdocs/luci-static/resources/fchomo.js:244 +#: htdocs/luci-static/resources/fchomo.js:245 msgid "%s ports" msgstr "%s 連接埠" -#: htdocs/luci-static/resources/fchomo.js:604 -#: htdocs/luci-static/resources/fchomo.js:607 +#: htdocs/luci-static/resources/fchomo.js:605 +#: htdocs/luci-static/resources/fchomo.js:608 #: htdocs/luci-static/resources/view/fchomo/client.js:315 msgid "(Imported)" msgstr "(已導入)" -#: htdocs/luci-static/resources/fchomo/listeners.js:858 -#: htdocs/luci-static/resources/fchomo/listeners.js:866 -#: htdocs/luci-static/resources/fchomo/listeners.js:875 +#: htdocs/luci-static/resources/fchomo/listeners.js:947 +#: htdocs/luci-static/resources/fchomo/listeners.js:955 +#: htdocs/luci-static/resources/fchomo/listeners.js:964 #: htdocs/luci-static/resources/view/fchomo/global.js:543 #: htdocs/luci-static/resources/view/fchomo/global.js:549 -#: htdocs/luci-static/resources/view/fchomo/node.js:1059 -#: htdocs/luci-static/resources/view/fchomo/node.js:1065 -#: htdocs/luci-static/resources/view/fchomo/node.js:1073 -#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/view/fchomo/node.js:1094 +#: htdocs/luci-static/resources/view/fchomo/node.js:1100 +#: htdocs/luci-static/resources/view/fchomo/node.js:1108 +#: htdocs/luci-static/resources/view/fchomo/node.js:1114 msgid "(mTLS)" msgstr "" @@ -46,19 +46,19 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1056 #: htdocs/luci-static/resources/view/fchomo/client.js:1057 #: htdocs/luci-static/resources/view/fchomo/client.js:1278 -#: htdocs/luci-static/resources/view/fchomo/node.js:1862 -#: htdocs/luci-static/resources/view/fchomo/node.js:1868 -#: htdocs/luci-static/resources/view/fchomo/node.js:1882 -#: htdocs/luci-static/resources/view/fchomo/node.js:1888 +#: htdocs/luci-static/resources/view/fchomo/node.js:1897 +#: htdocs/luci-static/resources/view/fchomo/node.js:1903 +#: htdocs/luci-static/resources/view/fchomo/node.js:1917 +#: htdocs/luci-static/resources/view/fchomo/node.js:1923 msgid "-- Please choose --" msgstr "-- 請選擇 --" -#: htdocs/luci-static/resources/fchomo.js:391 +#: htdocs/luci-static/resources/fchomo.js:392 msgid "0-RTT reuse." msgstr "0-RTT 重用。" -#: htdocs/luci-static/resources/fchomo.js:388 -#: htdocs/luci-static/resources/fchomo.js:392 +#: htdocs/luci-static/resources/fchomo.js:389 +#: htdocs/luci-static/resources/fchomo.js:393 msgid "1-RTT only." msgstr "僅限 1-RTT。" @@ -66,15 +66,15 @@ msgstr "僅限 1-RTT。" msgid "163Music" msgstr "網易雲音樂" -#: htdocs/luci-static/resources/fchomo.js:338 +#: htdocs/luci-static/resources/fchomo.js:339 msgid "2022-blake3-aes-128-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:339 +#: htdocs/luci-static/resources/fchomo.js:340 msgid "2022-blake3-aes-256-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:340 +#: htdocs/luci-static/resources/fchomo.js:341 msgid "2022-blake3-chacha20-poly1305" msgstr "" @@ -82,16 +82,16 @@ msgstr "" msgid "0 or 1 only." msgstr "僅限 01。" -#: htdocs/luci-static/resources/fchomo/listeners.js:836 -#: htdocs/luci-static/resources/fchomo/listeners.js:851 -#: htdocs/luci-static/resources/fchomo/listeners.js:876 -#: htdocs/luci-static/resources/view/fchomo/node.js:1066 -#: htdocs/luci-static/resources/view/fchomo/node.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:925 +#: htdocs/luci-static/resources/fchomo/listeners.js:940 +#: htdocs/luci-static/resources/fchomo/listeners.js:965 +#: htdocs/luci-static/resources/view/fchomo/node.js:1101 +#: htdocs/luci-static/resources/view/fchomo/node.js:1115 msgid "Save your configuration before uploading files!" msgstr "上傳文件前請先保存配置!" -#: htdocs/luci-static/resources/fchomo/listeners.js:244 -#: htdocs/luci-static/resources/view/fchomo/node.js:379 +#: htdocs/luci-static/resources/fchomo/listeners.js:275 +#: htdocs/luci-static/resources/view/fchomo/node.js:380 msgid "" "A base64 string is used to fine-tune network behavior.
Please refer to " "the document" msgid "All allowed" msgstr "允許所有" -#: htdocs/luci-static/resources/fchomo.js:236 +#: htdocs/luci-static/resources/fchomo.js:237 msgid "All ports" msgstr "所有連接埠" @@ -255,7 +255,7 @@ msgid "" msgstr "" "允許從私有網路訪問。
要從公共網站訪問私有網路上的 API,則必須啟用。" -#: htdocs/luci-static/resources/view/fchomo/node.js:768 +#: htdocs/luci-static/resources/view/fchomo/node.js:769 msgid "Allowed IPs" msgstr "允許的 IP" @@ -267,13 +267,13 @@ msgstr "已是最新版本。" msgid "Already in updating." msgstr "已在更新中。" -#: htdocs/luci-static/resources/fchomo/listeners.js:482 -#: htdocs/luci-static/resources/view/fchomo/node.js:638 +#: htdocs/luci-static/resources/fchomo/listeners.js:513 +#: htdocs/luci-static/resources/view/fchomo/node.js:639 msgid "Alter ID" msgstr "額外 ID" #: htdocs/luci-static/resources/fchomo.js:162 -#: htdocs/luci-static/resources/fchomo.js:196 +#: htdocs/luci-static/resources/fchomo.js:197 msgid "AnyTLS" msgstr "" @@ -290,24 +290,24 @@ msgstr "作為 dnsmasq 的最優先上游" msgid "As the TOP upstream of dnsmasq." msgstr "作為 dnsmasq 的最優先上游。" -#: htdocs/luci-static/resources/fchomo/listeners.js:432 +#: htdocs/luci-static/resources/fchomo/listeners.js:463 msgid "Auth timeout" msgstr "認證超時" -#: htdocs/luci-static/resources/view/fchomo/node.js:660 +#: htdocs/luci-static/resources/view/fchomo/node.js:661 msgid "Authenticated length" msgstr "認證長度" -#: htdocs/luci-static/resources/fchomo/listeners.js:397 -#: htdocs/luci-static/resources/fchomo/listeners.js:1030 +#: htdocs/luci-static/resources/fchomo/listeners.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:1119 #: htdocs/luci-static/resources/view/fchomo/global.js:402 -#: htdocs/luci-static/resources/view/fchomo/node.js:459 -#: htdocs/luci-static/resources/view/fchomo/node.js:483 -#: htdocs/luci-static/resources/view/fchomo/node.js:1261 +#: htdocs/luci-static/resources/view/fchomo/node.js:460 +#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:1296 msgid "Auto" msgstr "自動" -#: htdocs/luci-static/resources/fchomo/listeners.js:137 +#: htdocs/luci-static/resources/fchomo/listeners.js:138 msgid "Auto configure firewall" msgstr "自動配置防火牆" @@ -319,8 +319,8 @@ msgstr "自動更新" msgid "Auto update resources." msgstr "自動更新資源文件。" -#: htdocs/luci-static/resources/fchomo/listeners.js:553 -#: htdocs/luci-static/resources/view/fchomo/node.js:865 +#: htdocs/luci-static/resources/fchomo/listeners.js:591 +#: htdocs/luci-static/resources/view/fchomo/node.js:866 msgid "BBR profile" msgstr "BBR 設定檔" @@ -328,11 +328,11 @@ msgstr "BBR 設定檔" msgid "Baidu" msgstr "百度" -#: htdocs/luci-static/resources/view/fchomo/node.js:675 +#: htdocs/luci-static/resources/view/fchomo/node.js:676 msgid "Base64 encoded ECDSA private key on the NIST P-256 curve." msgstr "基於 NIST P-256 曲線的 Base64 編碼 ECDSA 私鑰。" -#: htdocs/luci-static/resources/view/fchomo/node.js:683 +#: htdocs/luci-static/resources/view/fchomo/node.js:684 msgid "Base64 encoded ECDSA public key on the NIST P-256 curve." msgstr "基於 NIST P-256 曲線的 Base64 編碼 ECDSA 公鑰。" @@ -354,13 +354,13 @@ msgid "Binary mrs" msgstr "二進位 mrs" #: htdocs/luci-static/resources/view/fchomo/global.js:734 -#: htdocs/luci-static/resources/view/fchomo/node.js:1420 -#: htdocs/luci-static/resources/view/fchomo/node.js:1736 +#: htdocs/luci-static/resources/view/fchomo/node.js:1455 +#: htdocs/luci-static/resources/view/fchomo/node.js:1771 msgid "Bind interface" msgstr "綁定介面" -#: htdocs/luci-static/resources/view/fchomo/node.js:1421 -#: htdocs/luci-static/resources/view/fchomo/node.js:1737 +#: htdocs/luci-static/resources/view/fchomo/node.js:1456 +#: htdocs/luci-static/resources/view/fchomo/node.js:1772 msgid "Bind outbound interface.
" msgstr "綁定出站介面。
" @@ -398,14 +398,14 @@ msgstr "繞過 CN 流量" msgid "Bypass DSCP" msgstr "繞過 DSCP" -#: htdocs/luci-static/resources/fchomo/listeners.js:395 -#: htdocs/luci-static/resources/fchomo/listeners.js:396 -#: htdocs/luci-static/resources/fchomo/listeners.js:397 -#: htdocs/luci-static/resources/fchomo/listeners.js:398 -#: htdocs/luci-static/resources/view/fchomo/node.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:426 +#: htdocs/luci-static/resources/fchomo/listeners.js:427 +#: htdocs/luci-static/resources/fchomo/listeners.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:429 #: htdocs/luci-static/resources/view/fchomo/node.js:458 #: htdocs/luci-static/resources/view/fchomo/node.js:459 #: htdocs/luci-static/resources/view/fchomo/node.js:460 +#: htdocs/luci-static/resources/view/fchomo/node.js:461 msgid "CDN support" msgstr "CDN 支援" @@ -421,21 +421,21 @@ msgstr "CORS 允許私有網路" msgid "CORS allowed origins, * will be used if empty." msgstr "CORS 允許的來源,留空則使用 *。" -#: htdocs/luci-static/resources/fchomo.js:720 +#: htdocs/luci-static/resources/fchomo.js:721 msgid "Cancel" msgstr "取消" -#: htdocs/luci-static/resources/view/fchomo/node.js:1038 +#: htdocs/luci-static/resources/view/fchomo/node.js:1073 msgid "Cert fingerprint" msgstr "憑證指紋" -#: htdocs/luci-static/resources/view/fchomo/node.js:1039 +#: htdocs/luci-static/resources/view/fchomo/node.js:1074 msgid "" "Certificate fingerprint. Used to implement SSL Pinning and prevent MitM." msgstr "憑證指紋。用於實現 SSL憑證固定 並防止 MitM。" -#: htdocs/luci-static/resources/fchomo/listeners.js:828 -#: htdocs/luci-static/resources/view/fchomo/node.js:1059 +#: htdocs/luci-static/resources/fchomo/listeners.js:917 +#: htdocs/luci-static/resources/view/fchomo/node.js:1094 msgid "Certificate path" msgstr "憑證路徑" @@ -464,16 +464,16 @@ msgstr "大陸 IPv6 庫版本" msgid "China list version" msgstr "大陸網域清單版本" -#: htdocs/luci-static/resources/fchomo/listeners.js:213 -#: htdocs/luci-static/resources/fchomo/listeners.js:311 -#: htdocs/luci-static/resources/view/fchomo/node.js:332 -#: htdocs/luci-static/resources/view/fchomo/node.js:391 -#: htdocs/luci-static/resources/view/fchomo/node.js:644 +#: htdocs/luci-static/resources/fchomo/listeners.js:244 +#: htdocs/luci-static/resources/fchomo/listeners.js:342 +#: htdocs/luci-static/resources/view/fchomo/node.js:333 +#: htdocs/luci-static/resources/view/fchomo/node.js:392 +#: htdocs/luci-static/resources/view/fchomo/node.js:645 msgid "Chipher" msgstr "加密方法" -#: htdocs/luci-static/resources/fchomo/listeners.js:320 -#: htdocs/luci-static/resources/view/fchomo/node.js:400 +#: htdocs/luci-static/resources/fchomo/listeners.js:351 +#: htdocs/luci-static/resources/view/fchomo/node.js:401 msgid "Chipher must be enabled if obfuscate downlink is disabled." msgstr "如果下行鏈路混淆功能已停用,則必須啟用加密。" @@ -489,29 +489,29 @@ msgstr "" "點擊
此處下載" "最新的初始包。" -#: htdocs/luci-static/resources/fchomo/listeners.js:651 -#: htdocs/luci-static/resources/fchomo/listeners.js:867 +#: htdocs/luci-static/resources/fchomo/listeners.js:689 +#: htdocs/luci-static/resources/fchomo/listeners.js:956 #: htdocs/luci-static/resources/view/fchomo/global.js:550 -#: htdocs/luci-static/resources/view/fchomo/node.js:928 -#: htdocs/luci-static/resources/view/fchomo/node.js:1060 -#: htdocs/luci-static/resources/view/fchomo/node.js:1074 +#: htdocs/luci-static/resources/view/fchomo/node.js:929 +#: htdocs/luci-static/resources/view/fchomo/node.js:1095 +#: htdocs/luci-static/resources/view/fchomo/node.js:1109 #: root/usr/share/luci/menu.d/luci-app-fchomo.json:22 msgid "Client" msgstr "客戶端" -#: htdocs/luci-static/resources/fchomo/listeners.js:866 +#: htdocs/luci-static/resources/fchomo/listeners.js:955 msgid "Client Auth Certificate path" msgstr "客戶端認證憑證路徑" -#: htdocs/luci-static/resources/fchomo/listeners.js:858 +#: htdocs/luci-static/resources/fchomo/listeners.js:947 msgid "Client Auth type" msgstr "客戶端認證類型" -#: htdocs/luci-static/resources/view/fchomo/node.js:1105 +#: htdocs/luci-static/resources/view/fchomo/node.js:1140 msgid "Client fingerprint" msgstr "客戶端指紋" -#: htdocs/luci-static/resources/fchomo/listeners.js:307 +#: htdocs/luci-static/resources/fchomo/listeners.js:338 msgid "Client key" msgstr "客戶端密鑰" @@ -523,21 +523,21 @@ msgstr "客戶端狀態" msgid "Collecting data..." msgstr "收集資料中..." -#: htdocs/luci-static/resources/fchomo.js:237 #: htdocs/luci-static/resources/fchomo.js:238 +#: htdocs/luci-static/resources/fchomo.js:239 msgid "Common ports (bypass P2P traffic)" msgstr "常用連接埠(繞過 P2P 流量)" -#: htdocs/luci-static/resources/fchomo.js:1367 +#: htdocs/luci-static/resources/fchomo.js:1368 msgid "Complete" msgstr "完成" -#: htdocs/luci-static/resources/view/fchomo/node.js:1680 +#: htdocs/luci-static/resources/view/fchomo/node.js:1715 msgid "Configuration Items" msgstr "配置項" -#: htdocs/luci-static/resources/fchomo/listeners.js:545 -#: htdocs/luci-static/resources/view/fchomo/node.js:857 +#: htdocs/luci-static/resources/fchomo/listeners.js:583 +#: htdocs/luci-static/resources/view/fchomo/node.js:858 msgid "Congestion controller" msgstr "擁塞控制器" @@ -549,19 +549,19 @@ msgstr "連接檢查" msgid "Conservative" msgstr "保守" -#: htdocs/luci-static/resources/fchomo.js:589 +#: htdocs/luci-static/resources/fchomo.js:590 msgid "Content copied to clipboard!" msgstr "內容已複製到剪貼簿!" #: htdocs/luci-static/resources/view/fchomo/client.js:670 -#: htdocs/luci-static/resources/view/fchomo/node.js:1590 -#: htdocs/luci-static/resources/view/fchomo/node.js:1616 +#: htdocs/luci-static/resources/view/fchomo/node.js:1625 +#: htdocs/luci-static/resources/view/fchomo/node.js:1651 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:339 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:365 msgid "Content will not be verified, Please make sure you enter it correctly." msgstr "內容將不會被驗證,請確保輸入正確。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1589 +#: htdocs/luci-static/resources/view/fchomo/node.js:1624 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:338 msgid "Contents" msgstr "內容" @@ -570,7 +570,7 @@ msgstr "內容" msgid "Contents have been saved." msgstr "" -#: htdocs/luci-static/resources/fchomo.js:591 +#: htdocs/luci-static/resources/fchomo.js:592 msgid "Copy" msgstr "複製" @@ -586,7 +586,7 @@ msgstr "Cron 表達式" msgid "Custom Direct List" msgstr "自訂直連清單" -#: htdocs/luci-static/resources/view/fchomo/node.js:1651 +#: htdocs/luci-static/resources/view/fchomo/node.js:1686 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:400 msgid "Custom HTTP header." msgstr "自訂 HTTP header。" @@ -595,8 +595,8 @@ msgstr "自訂 HTTP header。" msgid "Custom Proxy List" msgstr "自訂代理清單" -#: htdocs/luci-static/resources/fchomo/listeners.js:335 -#: htdocs/luci-static/resources/view/fchomo/node.js:415 +#: htdocs/luci-static/resources/fchomo/listeners.js:366 +#: htdocs/luci-static/resources/view/fchomo/node.js:416 msgid "Custom byte layout" msgstr "自訂位元組佈局" @@ -605,7 +605,7 @@ msgid "" "Custom internal hosts. Support yaml or json format." msgstr "自訂內部 hosts。支援 yamljson 格式。" -#: htdocs/luci-static/resources/fchomo.js:185 +#: htdocs/luci-static/resources/fchomo.js:186 msgid "DIRECT" msgstr "" @@ -621,8 +621,8 @@ msgstr " DNS 連接埠" #: htdocs/luci-static/resources/view/fchomo/client.js:873 #: htdocs/luci-static/resources/view/fchomo/client.js:1428 #: htdocs/luci-static/resources/view/fchomo/client.js:1437 -#: htdocs/luci-static/resources/view/fchomo/node.js:715 -#: htdocs/luci-static/resources/view/fchomo/node.js:798 +#: htdocs/luci-static/resources/view/fchomo/node.js:716 +#: htdocs/luci-static/resources/view/fchomo/node.js:799 msgid "DNS server" msgstr "DNS 伺服器" @@ -650,24 +650,24 @@ msgstr "預設 DNS(由 WAN 下發)" msgid "Default DNS server" msgstr "預設 DNS 伺服器" -#: htdocs/luci-static/resources/view/fchomo/node.js:769 +#: htdocs/luci-static/resources/view/fchomo/node.js:770 msgid "Destination addresses allowed to be forwarded via Wireguard." msgstr "允許通過 WireGuard 轉發的目的位址" -#: htdocs/luci-static/resources/view/fchomo/node.js:1861 +#: htdocs/luci-static/resources/view/fchomo/node.js:1896 msgid "Destination provider" msgstr "落地供應商" -#: htdocs/luci-static/resources/view/fchomo/node.js:1867 +#: htdocs/luci-static/resources/view/fchomo/node.js:1902 msgid "Destination proxy node" msgstr "落地代理節點" -#: htdocs/luci-static/resources/view/fchomo/node.js:227 +#: htdocs/luci-static/resources/view/fchomo/node.js:228 msgid "Dial fields" msgstr "撥號欄位" -#: htdocs/luci-static/resources/view/fchomo/node.js:1874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1894 +#: htdocs/luci-static/resources/view/fchomo/node.js:1909 +#: htdocs/luci-static/resources/view/fchomo/node.js:1929 msgid "Different chain head/tail" msgstr "不同的鏈頭/鏈尾" @@ -687,9 +687,9 @@ msgstr "直連 IPv6 位址" msgid "Direct MAC-s" msgstr "直連 MAC 位址" -#: htdocs/luci-static/resources/fchomo/listeners.js:193 +#: htdocs/luci-static/resources/fchomo/listeners.js:194 #: htdocs/luci-static/resources/view/fchomo/global.js:403 -#: htdocs/luci-static/resources/view/fchomo/node.js:298 +#: htdocs/luci-static/resources/view/fchomo/node.js:299 msgid "Disable" msgstr "停用" @@ -705,7 +705,7 @@ msgstr "停用 quic-go 的 通用分段卸載(GSO)" msgid "Disable ICMP Forwarding" msgstr "禁用 ICMP 轉發" -#: htdocs/luci-static/resources/view/fchomo/node.js:979 +#: htdocs/luci-static/resources/view/fchomo/node.js:1014 msgid "Disable SNI" msgstr "停用 SNI" @@ -733,46 +733,46 @@ msgstr "" msgid "Domain" msgstr "網域" -#: htdocs/luci-static/resources/view/fchomo/node.js:980 +#: htdocs/luci-static/resources/view/fchomo/node.js:1015 msgid "Donot send server name in ClientHello." msgstr "不要在 ClientHello 中傳送伺服器名稱。" #: htdocs/luci-static/resources/view/fchomo/client.js:1577 -#: htdocs/luci-static/resources/view/fchomo/node.js:1052 -#: htdocs/luci-static/resources/view/fchomo/node.js:1720 +#: htdocs/luci-static/resources/view/fchomo/node.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1755 msgid "Donot verifying server certificate." msgstr "不驗證伺服器憑證。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1399 +#: htdocs/luci-static/resources/view/fchomo/node.js:1434 msgid "Download bandwidth" msgstr "下載頻寬" -#: htdocs/luci-static/resources/view/fchomo/node.js:1400 +#: htdocs/luci-static/resources/view/fchomo/node.js:1435 msgid "Download bandwidth in Mbps." msgstr "下載頻寬(單位:Mbps)。" -#: htdocs/luci-static/resources/fchomo.js:1246 +#: htdocs/luci-static/resources/fchomo.js:1247 msgid "Download failed: %s" msgstr "下載失敗: %s" -#: htdocs/luci-static/resources/fchomo.js:1244 +#: htdocs/luci-static/resources/fchomo.js:1245 msgid "Download successful." msgstr "下載成功。" -#: htdocs/luci-static/resources/fchomo.js:171 +#: htdocs/luci-static/resources/fchomo.js:172 msgid "Dual stack" msgstr "雙棧" -#: htdocs/luci-static/resources/view/fchomo/node.js:1099 +#: htdocs/luci-static/resources/view/fchomo/node.js:1134 msgid "ECH HTTPS record query servername" msgstr "ECH HTTPS 記錄查詢網域" -#: htdocs/luci-static/resources/fchomo/listeners.js:924 -#: htdocs/luci-static/resources/view/fchomo/node.js:1093 +#: htdocs/luci-static/resources/fchomo/listeners.js:1013 +#: htdocs/luci-static/resources/view/fchomo/node.js:1128 msgid "ECH config" msgstr "ECH 配置" -#: htdocs/luci-static/resources/fchomo/listeners.js:883 +#: htdocs/luci-static/resources/fchomo/listeners.js:972 msgid "ECH key" msgstr "ECH 密鑰" @@ -788,11 +788,11 @@ msgstr "" msgid "ETag support" msgstr "ETag 支援" -#: htdocs/luci-static/resources/view/fchomo/node.js:1239 +#: htdocs/luci-static/resources/view/fchomo/node.js:1274 msgid "Early Data first packet length limit." msgstr "前置數據長度閾值" -#: htdocs/luci-static/resources/view/fchomo/node.js:1245 +#: htdocs/luci-static/resources/view/fchomo/node.js:1280 msgid "Early Data header name" msgstr "前置數據標頭" @@ -808,16 +808,16 @@ msgstr "編輯節點" msgid "Edit ruleset" msgstr "編輯規則集" -#: htdocs/luci-static/resources/view/fchomo/node.js:1587 +#: htdocs/luci-static/resources/view/fchomo/node.js:1622 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:336 msgid "Editer" msgstr "編輯器" -#: htdocs/luci-static/resources/fchomo.js:382 +#: htdocs/luci-static/resources/fchomo.js:383 msgid "Eliminate encryption header characteristics" msgstr "消除加密頭特徵" -#: htdocs/luci-static/resources/fchomo/listeners.js:132 +#: htdocs/luci-static/resources/fchomo/listeners.js:133 #: htdocs/luci-static/resources/view/fchomo/client.js:931 #: htdocs/luci-static/resources/view/fchomo/client.js:1024 #: htdocs/luci-static/resources/view/fchomo/client.js:1262 @@ -827,16 +827,16 @@ msgstr "消除加密頭特徵" #: htdocs/luci-static/resources/view/fchomo/client.js:1780 #: htdocs/luci-static/resources/view/fchomo/global.js:401 #: htdocs/luci-static/resources/view/fchomo/global.js:680 -#: htdocs/luci-static/resources/view/fchomo/node.js:234 -#: htdocs/luci-static/resources/view/fchomo/node.js:1560 -#: htdocs/luci-static/resources/view/fchomo/node.js:1759 -#: htdocs/luci-static/resources/view/fchomo/node.js:1848 +#: htdocs/luci-static/resources/view/fchomo/node.js:235 +#: htdocs/luci-static/resources/view/fchomo/node.js:1595 +#: htdocs/luci-static/resources/view/fchomo/node.js:1794 +#: htdocs/luci-static/resources/view/fchomo/node.js:1883 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:264 #: htdocs/luci-static/resources/view/fchomo/server.js:49 msgid "Enable" msgstr "啟用" -#: htdocs/luci-static/resources/view/fchomo/node.js:553 +#: htdocs/luci-static/resources/view/fchomo/node.js:554 msgid "" "Enable 0-RTT QUIC connection handshake on the client side. This is not " "impacting much on the performance, as the protocol is fully multiplexed.
強烈建議停用此功能,因為它容易受到重放攻擊。" -#: htdocs/luci-static/resources/view/fchomo/node.js:552 +#: htdocs/luci-static/resources/view/fchomo/node.js:553 msgid "Enable 0-RTT handshake" msgstr "啟用 0-RTT 握手" @@ -857,53 +857,53 @@ msgstr "" "為出站連線啟用 IP4P 轉換" -#: htdocs/luci-static/resources/view/fchomo/node.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1122 msgid "Enable ECH" msgstr "啟用 ECH" -#: htdocs/luci-static/resources/view/fchomo/node.js:1387 +#: htdocs/luci-static/resources/view/fchomo/node.js:1422 msgid "Enable TCP Brutal" msgstr "啟用 TCP Brutal" -#: htdocs/luci-static/resources/view/fchomo/node.js:1388 +#: htdocs/luci-static/resources/view/fchomo/node.js:1423 msgid "Enable TCP Brutal congestion control algorithm" msgstr "啟用 TCP Brutal 擁塞控制演算法。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1376 +#: htdocs/luci-static/resources/view/fchomo/node.js:1411 msgid "Enable multiplexing only for TCP." msgstr "僅為 TCP 啟用多路復用。" -#: htdocs/luci-static/resources/fchomo/listeners.js:381 -#: htdocs/luci-static/resources/view/fchomo/node.js:443 +#: htdocs/luci-static/resources/fchomo/listeners.js:412 +#: htdocs/luci-static/resources/view/fchomo/node.js:444 msgid "Enable obfuscate for downlink" msgstr "啟用下行鏈路混淆" -#: htdocs/luci-static/resources/view/fchomo/node.js:1370 +#: htdocs/luci-static/resources/view/fchomo/node.js:1405 msgid "Enable padding" msgstr "啟用填充" -#: htdocs/luci-static/resources/view/fchomo/node.js:1381 +#: htdocs/luci-static/resources/view/fchomo/node.js:1416 msgid "Enable statistic" msgstr "啟用統計" -#: htdocs/luci-static/resources/view/fchomo/node.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:1702 +#: htdocs/luci-static/resources/view/fchomo/node.js:881 +#: htdocs/luci-static/resources/view/fchomo/node.js:1737 msgid "" "Enable the SUoT protocol, requires server support. Conflict with Multiplex." msgstr "啟用 SUoT 協議,需要服務端支援。與多路復用衝突。" -#: htdocs/luci-static/resources/fchomo/listeners.js:199 -#: htdocs/luci-static/resources/view/fchomo/node.js:304 +#: htdocs/luci-static/resources/fchomo/listeners.js:200 +#: htdocs/luci-static/resources/view/fchomo/node.js:305 msgid "" "Enabling obfuscation will make the server incompatible with standard QUIC " "connections, losing the ability to masquerade with HTTP/3." msgstr "啟用混淆將使伺服器與標準的 QUIC 連線不相容,失去 HTTP/3 偽裝的能力。" -#: htdocs/luci-static/resources/fchomo/listeners.js:614 +#: htdocs/luci-static/resources/fchomo/listeners.js:652 msgid "Encryption method" msgstr "加密方法" -#: htdocs/luci-static/resources/view/fchomo/node.js:682 +#: htdocs/luci-static/resources/view/fchomo/node.js:683 msgid "Endpoint pubkic key" msgstr "端點公鑰" @@ -926,7 +926,7 @@ msgid "" "if empty." msgstr "超過此限制將會觸發強制健康檢查。留空則使用 5。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1817 +#: htdocs/luci-static/resources/view/fchomo/node.js:1852 msgid "Exclude matched node types." msgstr "排除匹配的節點類型。" @@ -939,7 +939,7 @@ msgstr "" "rel=\"noreferrer noopener\">此處。" #: htdocs/luci-static/resources/view/fchomo/client.js:1161 -#: htdocs/luci-static/resources/view/fchomo/node.js:1810 +#: htdocs/luci-static/resources/view/fchomo/node.js:1845 msgid "Exclude nodes that meet keywords or regexps." msgstr "排除匹配關鍵字或表達式的節點。" @@ -948,66 +948,66 @@ msgid "Expand/Collapse result" msgstr "展開/收起 結果" #: htdocs/luci-static/resources/view/fchomo/client.js:1121 -#: htdocs/luci-static/resources/view/fchomo/node.js:1795 +#: htdocs/luci-static/resources/view/fchomo/node.js:1830 msgid "Expected HTTP code. 204 will be used if empty." msgstr "預期的 HTTP code。留空則使用 204。" #: htdocs/luci-static/resources/view/fchomo/client.js:1123 -#: htdocs/luci-static/resources/view/fchomo/node.js:1797 +#: htdocs/luci-static/resources/view/fchomo/node.js:1832 msgid "Expected status" msgstr "預期狀態" -#: htdocs/luci-static/resources/fchomo.js:439 -#: htdocs/luci-static/resources/fchomo.js:442 -#: htdocs/luci-static/resources/fchomo.js:445 -#: htdocs/luci-static/resources/fchomo.js:1384 -#: htdocs/luci-static/resources/fchomo.js:1392 -#: htdocs/luci-static/resources/fchomo.js:1400 -#: htdocs/luci-static/resources/fchomo.js:1423 -#: htdocs/luci-static/resources/fchomo.js:1426 -#: htdocs/luci-static/resources/fchomo.js:1433 -#: htdocs/luci-static/resources/fchomo.js:1449 -#: htdocs/luci-static/resources/fchomo.js:1458 -#: htdocs/luci-static/resources/fchomo.js:1470 -#: htdocs/luci-static/resources/fchomo.js:1473 -#: htdocs/luci-static/resources/fchomo.js:1483 -#: htdocs/luci-static/resources/fchomo.js:1495 -#: htdocs/luci-static/resources/fchomo.js:1498 -#: htdocs/luci-static/resources/fchomo.js:1508 -#: htdocs/luci-static/resources/fchomo.js:1518 -#: htdocs/luci-static/resources/fchomo.js:1553 -#: htdocs/luci-static/resources/fchomo.js:1555 -#: htdocs/luci-static/resources/fchomo.js:1568 -#: htdocs/luci-static/resources/fchomo.js:1574 -#: htdocs/luci-static/resources/fchomo.js:1581 -#: htdocs/luci-static/resources/fchomo.js:1590 -#: htdocs/luci-static/resources/fchomo/listeners.js:320 -#: htdocs/luci-static/resources/fchomo/listeners.js:367 -#: htdocs/luci-static/resources/fchomo/listeners.js:643 -#: htdocs/luci-static/resources/fchomo/listeners.js:674 -#: htdocs/luci-static/resources/fchomo/listeners.js:775 +#: htdocs/luci-static/resources/fchomo.js:440 +#: htdocs/luci-static/resources/fchomo.js:443 +#: htdocs/luci-static/resources/fchomo.js:446 +#: htdocs/luci-static/resources/fchomo.js:1385 +#: htdocs/luci-static/resources/fchomo.js:1393 +#: htdocs/luci-static/resources/fchomo.js:1401 +#: htdocs/luci-static/resources/fchomo.js:1424 +#: htdocs/luci-static/resources/fchomo.js:1427 +#: htdocs/luci-static/resources/fchomo.js:1434 +#: htdocs/luci-static/resources/fchomo.js:1450 +#: htdocs/luci-static/resources/fchomo.js:1459 +#: htdocs/luci-static/resources/fchomo.js:1471 +#: htdocs/luci-static/resources/fchomo.js:1474 +#: htdocs/luci-static/resources/fchomo.js:1484 +#: htdocs/luci-static/resources/fchomo.js:1496 +#: htdocs/luci-static/resources/fchomo.js:1499 +#: htdocs/luci-static/resources/fchomo.js:1509 +#: htdocs/luci-static/resources/fchomo.js:1519 +#: htdocs/luci-static/resources/fchomo.js:1554 +#: htdocs/luci-static/resources/fchomo.js:1556 +#: htdocs/luci-static/resources/fchomo.js:1569 +#: htdocs/luci-static/resources/fchomo.js:1575 +#: htdocs/luci-static/resources/fchomo.js:1582 +#: htdocs/luci-static/resources/fchomo.js:1591 +#: htdocs/luci-static/resources/fchomo/listeners.js:351 +#: htdocs/luci-static/resources/fchomo/listeners.js:398 +#: htdocs/luci-static/resources/fchomo/listeners.js:681 +#: htdocs/luci-static/resources/fchomo/listeners.js:712 +#: htdocs/luci-static/resources/fchomo/listeners.js:813 #: htdocs/luci-static/resources/view/fchomo/client.js:68 #: htdocs/luci-static/resources/view/fchomo/client.js:1018 #: htdocs/luci-static/resources/view/fchomo/client.js:1508 #: htdocs/luci-static/resources/view/fchomo/global.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:400 -#: htdocs/luci-static/resources/view/fchomo/node.js:436 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:491 -#: htdocs/luci-static/resources/view/fchomo/node.js:951 -#: htdocs/luci-static/resources/view/fchomo/node.js:1044 -#: htdocs/luci-static/resources/view/fchomo/node.js:1874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1894 +#: htdocs/luci-static/resources/view/fchomo/node.js:401 +#: htdocs/luci-static/resources/view/fchomo/node.js:437 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 +#: htdocs/luci-static/resources/view/fchomo/node.js:952 +#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/view/fchomo/node.js:1909 +#: htdocs/luci-static/resources/view/fchomo/node.js:1929 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:291 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:305 msgid "Expecting: %s" msgstr "請輸入:%s" -#: htdocs/luci-static/resources/fchomo/listeners.js:991 -#: htdocs/luci-static/resources/fchomo/listeners.js:998 -#: htdocs/luci-static/resources/view/fchomo/node.js:1154 -#: htdocs/luci-static/resources/view/fchomo/node.js:1161 -#: htdocs/luci-static/resources/view/fchomo/node.js:1169 +#: htdocs/luci-static/resources/fchomo/listeners.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1189 +#: htdocs/luci-static/resources/view/fchomo/node.js:1196 +#: htdocs/luci-static/resources/view/fchomo/node.js:1204 msgid "Expecting: only support %s." msgstr "請輸入:僅支援 %s." @@ -1026,24 +1026,24 @@ msgstr "實驗性" msgid "Factor" msgstr "條件" -#: htdocs/luci-static/resources/fchomo.js:1325 +#: htdocs/luci-static/resources/fchomo.js:1326 msgid "Failed to execute \"/etc/init.d/fchomo %s %s\" reason: %s" msgstr "無法執行 \"/etc/init.d/fchomo %s %s\" 原因: %s" -#: htdocs/luci-static/resources/fchomo.js:1278 +#: htdocs/luci-static/resources/fchomo.js:1279 msgid "Failed to generate %s, error: %s." msgstr "生成 %s 失敗,錯誤:%s。" -#: htdocs/luci-static/resources/fchomo.js:1690 +#: htdocs/luci-static/resources/fchomo.js:1691 msgid "Failed to upload %s, error: %s." msgstr "上傳 %s 失敗,錯誤:%s。" -#: htdocs/luci-static/resources/fchomo.js:1709 +#: htdocs/luci-static/resources/fchomo.js:1710 msgid "Failed to upload, error: %s." msgstr "上傳失敗,錯誤:%s。" -#: htdocs/luci-static/resources/fchomo.js:229 -#: htdocs/luci-static/resources/fchomo/listeners.js:406 +#: htdocs/luci-static/resources/fchomo.js:230 +#: htdocs/luci-static/resources/fchomo/listeners.js:437 msgid "Fallback" msgstr "自動回退" @@ -1057,7 +1057,7 @@ msgid "Fallback filter" msgstr "後備過濾器" #: htdocs/luci-static/resources/view/fchomo/client.js:1156 -#: htdocs/luci-static/resources/view/fchomo/node.js:1804 +#: htdocs/luci-static/resources/view/fchomo/node.js:1839 msgid "Filter nodes that meet keywords or regexps." msgstr "過濾匹配關鍵字或表達式的節點。" @@ -1082,12 +1082,12 @@ msgstr "兜底 DNS 伺服器 (用於未被投毒汙染的網域)" msgid "Final DNS server (For poisoned domains)" msgstr "兜底 DNS 伺服器 (用於已被投毒汙染的網域)" -#: htdocs/luci-static/resources/fchomo/listeners.js:136 +#: htdocs/luci-static/resources/fchomo/listeners.js:137 msgid "Firewall" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:474 -#: htdocs/luci-static/resources/view/fchomo/node.js:630 +#: htdocs/luci-static/resources/fchomo/listeners.js:505 +#: htdocs/luci-static/resources/view/fchomo/node.js:631 msgid "Flow" msgstr "流控" @@ -1100,8 +1100,8 @@ msgstr "" "noopener\">%s." #: htdocs/luci-static/resources/view/fchomo/client.js:1122 -#: htdocs/luci-static/resources/view/fchomo/node.js:1670 -#: htdocs/luci-static/resources/view/fchomo/node.js:1796 +#: htdocs/luci-static/resources/view/fchomo/node.js:1705 +#: htdocs/luci-static/resources/view/fchomo/node.js:1831 msgid "" "For format see %s." @@ -1109,8 +1109,8 @@ msgstr "" "格式請參閱 %s." -#: htdocs/luci-static/resources/view/fchomo/node.js:710 -#: htdocs/luci-static/resources/view/fchomo/node.js:793 +#: htdocs/luci-static/resources/view/fchomo/node.js:711 +#: htdocs/luci-static/resources/view/fchomo/node.js:794 msgid "Force DNS remote resolution." msgstr "強制 DNS 遠端解析。" @@ -1129,7 +1129,7 @@ msgstr "格式" msgid "FullCombo Shark!" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1194 +#: htdocs/luci-static/resources/view/fchomo/node.js:1229 msgid "GET" msgstr "" @@ -1144,7 +1144,7 @@ msgstr "常規" #: htdocs/luci-static/resources/fchomo/listeners.js:119 #: htdocs/luci-static/resources/view/fchomo/client.js:1009 #: htdocs/luci-static/resources/view/fchomo/node.js:222 -#: htdocs/luci-static/resources/view/fchomo/node.js:1550 +#: htdocs/luci-static/resources/view/fchomo/node.js:1585 msgid "General fields" msgstr "常規欄位" @@ -1152,15 +1152,15 @@ msgstr "常規欄位" msgid "General settings" msgstr "常規設定" -#: htdocs/luci-static/resources/fchomo.js:540 -#: htdocs/luci-static/resources/fchomo.js:542 -#: htdocs/luci-static/resources/fchomo.js:556 -#: htdocs/luci-static/resources/fchomo.js:558 -#: htdocs/luci-static/resources/fchomo/listeners.js:298 -#: htdocs/luci-static/resources/fchomo/listeners.js:342 -#: htdocs/luci-static/resources/fchomo/listeners.js:344 -#: htdocs/luci-static/resources/fchomo/listeners.js:747 -#: htdocs/luci-static/resources/fchomo/listeners.js:916 +#: htdocs/luci-static/resources/fchomo.js:541 +#: htdocs/luci-static/resources/fchomo.js:543 +#: htdocs/luci-static/resources/fchomo.js:557 +#: htdocs/luci-static/resources/fchomo.js:559 +#: htdocs/luci-static/resources/fchomo/listeners.js:329 +#: htdocs/luci-static/resources/fchomo/listeners.js:373 +#: htdocs/luci-static/resources/fchomo/listeners.js:375 +#: htdocs/luci-static/resources/fchomo/listeners.js:785 +#: htdocs/luci-static/resources/fchomo/listeners.js:1005 #: htdocs/luci-static/resources/view/fchomo/global.js:587 msgid "Generate" msgstr "生成" @@ -1204,7 +1204,7 @@ msgstr "全域" msgid "Global Authentication" msgstr "全域認證" -#: htdocs/luci-static/resources/view/fchomo/node.js:654 +#: htdocs/luci-static/resources/view/fchomo/node.js:655 msgid "Global padding" msgstr "全域填充" @@ -1212,7 +1212,7 @@ msgstr "全域填充" msgid "Google" msgstr "Google" -#: htdocs/luci-static/resources/fchomo.js:242 +#: htdocs/luci-static/resources/fchomo.js:243 msgid "Google FCM" msgstr "" @@ -1225,48 +1225,49 @@ msgid "Group" msgstr "組" #: htdocs/luci-static/resources/fchomo.js:153 -#: htdocs/luci-static/resources/fchomo.js:186 -#: htdocs/luci-static/resources/view/fchomo/node.js:816 -#: htdocs/luci-static/resources/view/fchomo/node.js:1143 -#: htdocs/luci-static/resources/view/fchomo/node.js:1154 -#: htdocs/luci-static/resources/view/fchomo/node.js:1161 +#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo/listeners.js:539 +#: htdocs/luci-static/resources/view/fchomo/node.js:817 +#: htdocs/luci-static/resources/view/fchomo/node.js:1178 +#: htdocs/luci-static/resources/view/fchomo/node.js:1189 +#: htdocs/luci-static/resources/view/fchomo/node.js:1196 msgid "HTTP" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:267 -#: htdocs/luci-static/resources/view/fchomo/node.js:1216 -#: htdocs/luci-static/resources/view/fchomo/node.js:1650 +#: htdocs/luci-static/resources/view/fchomo/node.js:268 +#: htdocs/luci-static/resources/view/fchomo/node.js:1251 +#: htdocs/luci-static/resources/view/fchomo/node.js:1685 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:399 msgid "HTTP header" msgstr "HTTP header" -#: htdocs/luci-static/resources/fchomo/listeners.js:387 -#: htdocs/luci-static/resources/view/fchomo/node.js:449 +#: htdocs/luci-static/resources/fchomo/listeners.js:418 +#: htdocs/luci-static/resources/view/fchomo/node.js:450 msgid "HTTP mask" msgstr "HTTP 偽裝" -#: htdocs/luci-static/resources/fchomo/listeners.js:392 -#: htdocs/luci-static/resources/view/fchomo/node.js:454 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/fchomo/listeners.js:423 +#: htdocs/luci-static/resources/view/fchomo/node.js:455 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "HTTP mask mode" msgstr "HTTP 偽裝模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:479 +#: htdocs/luci-static/resources/view/fchomo/node.js:480 msgid "HTTP mask multiplex" msgstr "HTTP 偽裝多路復用" -#: htdocs/luci-static/resources/view/fchomo/node.js:464 -#: htdocs/luci-static/resources/view/fchomo/node.js:469 +#: htdocs/luci-static/resources/view/fchomo/node.js:465 +#: htdocs/luci-static/resources/view/fchomo/node.js:470 msgid "HTTP mask: %s" msgstr "HTTP 偽裝: %s" -#: htdocs/luci-static/resources/view/fchomo/node.js:1193 +#: htdocs/luci-static/resources/view/fchomo/node.js:1228 msgid "HTTP request method" msgstr "HTTP 請求方法" -#: htdocs/luci-static/resources/fchomo/listeners.js:402 -#: htdocs/luci-static/resources/view/fchomo/node.js:475 +#: htdocs/luci-static/resources/fchomo/listeners.js:433 +#: htdocs/luci-static/resources/view/fchomo/node.js:476 msgid "HTTP root path" msgstr "HTTP 根路徑" @@ -1274,15 +1275,15 @@ msgstr "HTTP 根路徑" msgid "HTTP/3" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:207 +#: htdocs/luci-static/resources/fchomo/listeners.js:208 msgid "" "HTTP3 server behavior when authentication fails.
A 404 page will be " "returned if empty." msgstr "身份驗證失敗時的 HTTP3 伺服器回應。預設回傳 404 頁面。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1144 -#: htdocs/luci-static/resources/view/fchomo/node.js:1155 -#: htdocs/luci-static/resources/view/fchomo/node.js:1162 +#: htdocs/luci-static/resources/view/fchomo/node.js:1179 +#: htdocs/luci-static/resources/view/fchomo/node.js:1190 +#: htdocs/luci-static/resources/view/fchomo/node.js:1197 msgid "HTTPUpgrade" msgstr "" @@ -1290,48 +1291,52 @@ msgstr "" msgid "Handle domain" msgstr "處理網域" -#: htdocs/luci-static/resources/view/fchomo/node.js:371 +#: htdocs/luci-static/resources/view/fchomo/node.js:372 msgid "Handshake mode" msgstr "握手模式" -#: htdocs/luci-static/resources/fchomo/listeners.js:506 +#: htdocs/luci-static/resources/fchomo/listeners.js:544 msgid "Handshake target that supports TLS 1.3" msgstr "握手目標 (支援 TLS 1.3)" -#: htdocs/luci-static/resources/fchomo/listeners.js:374 +#: htdocs/luci-static/resources/fchomo/listeners.js:405 msgid "Handshake timeout" msgstr "握手超時" -#: htdocs/luci-static/resources/view/fchomo/node.js:721 +#: htdocs/luci-static/resources/fchomo/listeners.js:233 +msgid "Header to read real client IP from (e.g. X-Forwarded-For)" +msgstr "" + +#: htdocs/luci-static/resources/view/fchomo/node.js:722 msgid "Health check" msgstr "健康檢查" #: htdocs/luci-static/resources/view/fchomo/client.js:1091 -#: htdocs/luci-static/resources/view/fchomo/node.js:1764 +#: htdocs/luci-static/resources/view/fchomo/node.js:1799 msgid "Health check URL" msgstr "健康檢查 URL" #: htdocs/luci-static/resources/view/fchomo/client.js:1120 -#: htdocs/luci-static/resources/view/fchomo/node.js:1794 +#: htdocs/luci-static/resources/view/fchomo/node.js:1829 msgid "Health check expected status" msgstr "健康檢查预期状态" #: htdocs/luci-static/resources/view/fchomo/client.js:1100 -#: htdocs/luci-static/resources/view/fchomo/node.js:1774 +#: htdocs/luci-static/resources/view/fchomo/node.js:1809 msgid "Health check interval" msgstr "健康檢查間隔" #: htdocs/luci-static/resources/view/fchomo/client.js:1107 -#: htdocs/luci-static/resources/view/fchomo/node.js:1781 +#: htdocs/luci-static/resources/view/fchomo/node.js:1816 msgid "Health check timeout" msgstr "健康檢查超时" #: htdocs/luci-static/resources/view/fchomo/client.js:1011 -#: htdocs/luci-static/resources/view/fchomo/node.js:1552 +#: htdocs/luci-static/resources/view/fchomo/node.js:1587 msgid "Health fields" msgstr "健康欄位" -#: htdocs/luci-static/resources/view/fchomo/node.js:559 +#: htdocs/luci-static/resources/view/fchomo/node.js:560 msgid "Heartbeat interval" msgstr "心跳間隔" @@ -1339,19 +1344,19 @@ msgstr "心跳間隔" msgid "Hidden" msgstr "隱藏" -#: htdocs/luci-static/resources/view/fchomo/node.js:822 +#: htdocs/luci-static/resources/view/fchomo/node.js:823 msgid "Host that supports TLS 1.3" msgstr "主機名稱 (支援 TLS 1.3)" -#: htdocs/luci-static/resources/view/fchomo/node.js:326 +#: htdocs/luci-static/resources/view/fchomo/node.js:327 msgid "Host-key" msgstr "主機金鑰" -#: htdocs/luci-static/resources/view/fchomo/node.js:321 +#: htdocs/luci-static/resources/view/fchomo/node.js:322 msgid "Host-key algorithms" msgstr "主機金鑰演算法" -#: htdocs/luci-static/resources/view/fchomo/node.js:469 +#: htdocs/luci-static/resources/view/fchomo/node.js:470 msgid "Host/SNI override" msgstr "主機/SNI 覆蓋" @@ -1361,10 +1366,19 @@ msgid "Hosts" msgstr "" #: htdocs/luci-static/resources/fchomo.js:164 -#: htdocs/luci-static/resources/fchomo.js:198 +#: htdocs/luci-static/resources/fchomo.js:199 msgid "Hysteria2" msgstr "" +#: htdocs/luci-static/resources/fchomo.js:165 +msgid "Hysteria2 Realm" +msgstr "Hysteria2 Realm" + +#: htdocs/luci-static/resources/fchomo/listeners.js:121 +#: htdocs/luci-static/resources/view/fchomo/node.js:224 +msgid "Hysteria2 Realm fields" +msgstr "Hysteria2 Realm 欄位" + #: htdocs/luci-static/resources/view/fchomo/client.js:1806 #: htdocs/luci-static/resources/view/fchomo/client.js:1819 msgid "IP" @@ -1374,20 +1388,20 @@ msgstr "" msgid "IP CIDR" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:521 +#: htdocs/luci-static/resources/view/fchomo/node.js:522 msgid "IP override" msgstr "IP 覆寫" -#: htdocs/luci-static/resources/view/fchomo/node.js:1432 -#: htdocs/luci-static/resources/view/fchomo/node.js:1750 +#: htdocs/luci-static/resources/view/fchomo/node.js:1467 +#: htdocs/luci-static/resources/view/fchomo/node.js:1785 msgid "IP version" msgstr "IP 版本" -#: htdocs/luci-static/resources/fchomo.js:172 +#: htdocs/luci-static/resources/fchomo.js:173 msgid "IPv4 only" msgstr "僅 IPv4" -#: htdocs/luci-static/resources/fchomo.js:173 +#: htdocs/luci-static/resources/fchomo.js:174 msgid "IPv6 only" msgstr "僅 IPv6" @@ -1400,19 +1414,19 @@ msgstr "IPv6 支援" msgid "Icon" msgstr "圖標" -#: htdocs/luci-static/resources/view/fchomo/node.js:603 +#: htdocs/luci-static/resources/view/fchomo/node.js:604 msgid "Idle session check interval" msgstr "閒置會話檢查間隔" -#: htdocs/luci-static/resources/view/fchomo/node.js:610 +#: htdocs/luci-static/resources/view/fchomo/node.js:611 msgid "Idle session timeout" msgstr "閒置會話逾時" -#: htdocs/luci-static/resources/fchomo/listeners.js:425 +#: htdocs/luci-static/resources/fchomo/listeners.js:456 msgid "Idle timeout" msgstr "閒置逾時" -#: htdocs/luci-static/resources/fchomo.js:1426 +#: htdocs/luci-static/resources/fchomo.js:1427 msgid "If All ports is selected, uncheck others" msgstr "如果選擇了“所有連接埠”,則取消選取“其他”" @@ -1420,11 +1434,11 @@ msgstr "如果選擇了“所有連接埠”,則取消選取“其他”" msgid "If Block is selected, uncheck others" msgstr "如果選擇了“封鎖”,則取消選取“其他”" -#: htdocs/luci-static/resources/fchomo/listeners.js:186 +#: htdocs/luci-static/resources/fchomo/listeners.js:187 msgid "Ignore client bandwidth" msgstr "忽略客戶端頻寬" -#: htdocs/luci-static/resources/fchomo.js:725 +#: htdocs/luci-static/resources/fchomo.js:726 msgid "Import" msgstr "導入" @@ -1440,8 +1454,8 @@ msgstr "導入" #: htdocs/luci-static/resources/view/fchomo/client.js:1713 #: htdocs/luci-static/resources/view/fchomo/client.js:1748 #: htdocs/luci-static/resources/view/fchomo/client.js:1769 -#: htdocs/luci-static/resources/view/fchomo/node.js:1457 -#: htdocs/luci-static/resources/view/fchomo/node.js:1538 +#: htdocs/luci-static/resources/view/fchomo/node.js:1492 +#: htdocs/luci-static/resources/view/fchomo/node.js:1573 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:153 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:241 msgid "Import mihomo config" @@ -1453,41 +1467,41 @@ msgstr "導入 mihomo 配置" msgid "Import rule-set links" msgstr "導入規則集連結" -#: htdocs/luci-static/resources/fchomo/listeners.js:175 -#: htdocs/luci-static/resources/fchomo/listeners.js:181 -#: htdocs/luci-static/resources/view/fchomo/node.js:286 -#: htdocs/luci-static/resources/view/fchomo/node.js:292 -#: htdocs/luci-static/resources/view/fchomo/node.js:1708 -#: htdocs/luci-static/resources/view/fchomo/node.js:1714 +#: htdocs/luci-static/resources/fchomo/listeners.js:176 +#: htdocs/luci-static/resources/fchomo/listeners.js:182 +#: htdocs/luci-static/resources/view/fchomo/node.js:287 +#: htdocs/luci-static/resources/view/fchomo/node.js:293 +#: htdocs/luci-static/resources/view/fchomo/node.js:1743 +#: htdocs/luci-static/resources/view/fchomo/node.js:1749 msgid "In Mbps." msgstr "單位為 Mbps。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1628 +#: htdocs/luci-static/resources/view/fchomo/node.js:1663 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:377 msgid "In bytes. %s will be used if empty." msgstr "單位為位元組。留空則使用 %s。" -#: htdocs/luci-static/resources/view/fchomo/node.js:560 -#: htdocs/luci-static/resources/view/fchomo/node.js:567 +#: htdocs/luci-static/resources/view/fchomo/node.js:561 +#: htdocs/luci-static/resources/view/fchomo/node.js:568 msgid "In millisecond." msgstr "單位為毫秒。" #: htdocs/luci-static/resources/view/fchomo/client.js:1108 #: htdocs/luci-static/resources/view/fchomo/client.js:1137 -#: htdocs/luci-static/resources/view/fchomo/node.js:1782 +#: htdocs/luci-static/resources/view/fchomo/node.js:1817 msgid "In millisecond. %s will be used if empty." msgstr "單位為毫秒。留空則使用 %s。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1285 +#: htdocs/luci-static/resources/view/fchomo/node.js:1320 msgid "In milliseconds." msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:375 -#: htdocs/luci-static/resources/fchomo/listeners.js:426 -#: htdocs/luci-static/resources/fchomo/listeners.js:433 -#: htdocs/luci-static/resources/view/fchomo/node.js:604 -#: htdocs/luci-static/resources/view/fchomo/node.js:611 -#: htdocs/luci-static/resources/view/fchomo/node.js:1232 +#: htdocs/luci-static/resources/fchomo/listeners.js:406 +#: htdocs/luci-static/resources/fchomo/listeners.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:464 +#: htdocs/luci-static/resources/view/fchomo/node.js:605 +#: htdocs/luci-static/resources/view/fchomo/node.js:612 +#: htdocs/luci-static/resources/view/fchomo/node.js:1267 msgid "In seconds." msgstr "單位為秒。" @@ -1495,15 +1509,15 @@ msgstr "單位為秒。" #: htdocs/luci-static/resources/view/fchomo/global.js:425 #: htdocs/luci-static/resources/view/fchomo/global.js:430 #: htdocs/luci-static/resources/view/fchomo/global.js:515 -#: htdocs/luci-static/resources/view/fchomo/node.js:280 -#: htdocs/luci-static/resources/view/fchomo/node.js:1634 -#: htdocs/luci-static/resources/view/fchomo/node.js:1775 +#: htdocs/luci-static/resources/view/fchomo/node.js:281 +#: htdocs/luci-static/resources/view/fchomo/node.js:1669 +#: htdocs/luci-static/resources/view/fchomo/node.js:1810 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:383 msgid "In seconds. %s will be used if empty." msgstr "單位為秒。留空則使用 %s。" -#: htdocs/luci-static/resources/fchomo/listeners.js:663 -#: htdocs/luci-static/resources/view/fchomo/node.js:940 +#: htdocs/luci-static/resources/fchomo/listeners.js:701 +#: htdocs/luci-static/resources/view/fchomo/node.js:941 msgid "" "In the order of one Padding-Length and one Padding-" "Interval, infinite concatenation." @@ -1545,7 +1559,7 @@ msgstr "引入所有代理節點。" msgid "Info" msgstr "訊息" -#: htdocs/luci-static/resources/view/fchomo/node.js:1567 +#: htdocs/luci-static/resources/view/fchomo/node.js:1602 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:279 msgid "Inline" msgstr "內嵌" @@ -1556,55 +1570,55 @@ msgstr "介面控制" #: htdocs/luci-static/resources/fchomo.js:52 #: htdocs/luci-static/resources/fchomo.js:59 -#: htdocs/luci-static/resources/fchomo.js:170 -#: htdocs/luci-static/resources/fchomo.js:364 -#: htdocs/luci-static/resources/view/fchomo/node.js:1724 +#: htdocs/luci-static/resources/fchomo.js:171 +#: htdocs/luci-static/resources/fchomo.js:365 +#: htdocs/luci-static/resources/view/fchomo/node.js:1759 msgid "Keep default" msgstr "保持預設" -#: htdocs/luci-static/resources/view/fchomo/node.js:1321 +#: htdocs/luci-static/resources/view/fchomo/node.js:1356 msgid "Keep-alive period" msgstr "Keep-alive 週期" -#: htdocs/luci-static/resources/fchomo/listeners.js:254 -#: htdocs/luci-static/resources/view/fchomo/node.js:385 +#: htdocs/luci-static/resources/fchomo/listeners.js:285 +#: htdocs/luci-static/resources/view/fchomo/node.js:386 msgid "Key" msgstr "密鑰" -#: htdocs/luci-static/resources/fchomo/listeners.js:843 -#: htdocs/luci-static/resources/view/fchomo/node.js:1073 +#: htdocs/luci-static/resources/fchomo/listeners.js:932 +#: htdocs/luci-static/resources/view/fchomo/node.js:1108 msgid "Key path" msgstr "憑證路徑" -#: htdocs/luci-static/resources/fchomo/listeners.js:682 +#: htdocs/luci-static/resources/fchomo/listeners.js:720 msgid "Keypairs" msgstr "密鑰對" -#: htdocs/luci-static/resources/fchomo/listeners.js:127 +#: htdocs/luci-static/resources/fchomo/listeners.js:128 #: htdocs/luci-static/resources/view/fchomo/client.js:1014 #: htdocs/luci-static/resources/view/fchomo/client.js:1257 #: htdocs/luci-static/resources/view/fchomo/client.js:1349 #: htdocs/luci-static/resources/view/fchomo/client.js:1488 #: htdocs/luci-static/resources/view/fchomo/client.js:1719 #: htdocs/luci-static/resources/view/fchomo/client.js:1775 -#: htdocs/luci-static/resources/view/fchomo/node.js:229 -#: htdocs/luci-static/resources/view/fchomo/node.js:1555 -#: htdocs/luci-static/resources/view/fchomo/node.js:1843 +#: htdocs/luci-static/resources/view/fchomo/node.js:230 +#: htdocs/luci-static/resources/view/fchomo/node.js:1590 +#: htdocs/luci-static/resources/view/fchomo/node.js:1878 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:259 msgid "Label" msgstr "標籤" #: htdocs/luci-static/resources/view/fchomo/client.js:1114 -#: htdocs/luci-static/resources/view/fchomo/node.js:1788 +#: htdocs/luci-static/resources/view/fchomo/node.js:1823 msgid "Lazy" msgstr "懶惰狀態" -#: htdocs/luci-static/resources/fchomo/listeners.js:394 -#: htdocs/luci-static/resources/view/fchomo/node.js:456 +#: htdocs/luci-static/resources/fchomo/listeners.js:425 +#: htdocs/luci-static/resources/view/fchomo/node.js:457 msgid "Legacy" msgstr "傳統" -#: htdocs/luci-static/resources/fchomo/listeners.js:483 +#: htdocs/luci-static/resources/fchomo/listeners.js:514 msgid "" "Legacy protocol support (VMess MD5 Authentication) is provided for " "compatibility purposes only, use of alterId > 1 is not recommended." @@ -1616,16 +1630,16 @@ msgstr "" msgid "Less compatibility and sometimes better performance." msgstr "有時效能較好。" -#: htdocs/luci-static/resources/fchomo/listeners.js:824 -#: htdocs/luci-static/resources/view/fchomo/node.js:992 +#: htdocs/luci-static/resources/fchomo/listeners.js:913 +#: htdocs/luci-static/resources/view/fchomo/node.js:1027 msgid "List of supported application level protocols, in order of preference." msgstr "支援的應用層協議協商清單,依序排列。" -#: htdocs/luci-static/resources/fchomo/listeners.js:147 +#: htdocs/luci-static/resources/fchomo/listeners.js:148 msgid "Listen address" msgstr "監聽位址" -#: htdocs/luci-static/resources/fchomo/listeners.js:124 +#: htdocs/luci-static/resources/fchomo/listeners.js:125 msgid "Listen fields" msgstr "監聽欄位" @@ -1633,7 +1647,7 @@ msgstr "監聽欄位" msgid "Listen interfaces" msgstr "監聽介面" -#: htdocs/luci-static/resources/fchomo/listeners.js:152 +#: htdocs/luci-static/resources/fchomo/listeners.js:153 #: htdocs/luci-static/resources/view/fchomo/client.js:1374 msgid "Listen port" msgstr "監聽埠" @@ -1642,22 +1656,22 @@ msgstr "監聽埠" msgid "Listen ports" msgstr "監聽埠" -#: htdocs/luci-static/resources/fchomo.js:231 +#: htdocs/luci-static/resources/fchomo.js:232 msgid "Load balance" msgstr "負載均衡" -#: htdocs/luci-static/resources/view/fchomo/node.js:1565 +#: htdocs/luci-static/resources/view/fchomo/node.js:1600 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:277 msgid "Local" msgstr "本地" -#: htdocs/luci-static/resources/view/fchomo/node.js:697 -#: htdocs/luci-static/resources/view/fchomo/node.js:740 +#: htdocs/luci-static/resources/view/fchomo/node.js:698 +#: htdocs/luci-static/resources/view/fchomo/node.js:741 msgid "Local IPv6 address" msgstr "本地 IPv6 位址" -#: htdocs/luci-static/resources/view/fchomo/node.js:689 -#: htdocs/luci-static/resources/view/fchomo/node.js:732 +#: htdocs/luci-static/resources/view/fchomo/node.js:690 +#: htdocs/luci-static/resources/view/fchomo/node.js:733 msgid "Local address" msgstr "本地位址" @@ -1677,32 +1691,32 @@ msgstr "日誌為空。" msgid "Log level" msgstr "日誌等級" -#: htdocs/luci-static/resources/fchomo/listeners.js:329 -#: htdocs/luci-static/resources/fchomo/listeners.js:330 -#: htdocs/luci-static/resources/fchomo/listeners.js:331 -#: htdocs/luci-static/resources/fchomo/listeners.js:336 -#: htdocs/luci-static/resources/view/fchomo/node.js:409 +#: htdocs/luci-static/resources/fchomo/listeners.js:360 +#: htdocs/luci-static/resources/fchomo/listeners.js:361 +#: htdocs/luci-static/resources/fchomo/listeners.js:362 +#: htdocs/luci-static/resources/fchomo/listeners.js:367 #: htdocs/luci-static/resources/view/fchomo/node.js:410 #: htdocs/luci-static/resources/view/fchomo/node.js:411 -#: htdocs/luci-static/resources/view/fchomo/node.js:416 +#: htdocs/luci-static/resources/view/fchomo/node.js:412 +#: htdocs/luci-static/resources/view/fchomo/node.js:417 msgid "Low-entropy data stream" msgstr "低熵資料流" -#: htdocs/luci-static/resources/fchomo.js:439 +#: htdocs/luci-static/resources/fchomo.js:440 msgid "Lowercase only" msgstr "僅限小寫" #: htdocs/luci-static/resources/view/fchomo/global.js:502 -#: htdocs/luci-static/resources/view/fchomo/node.js:703 -#: htdocs/luci-static/resources/view/fchomo/node.js:786 +#: htdocs/luci-static/resources/view/fchomo/node.js:704 +#: htdocs/luci-static/resources/view/fchomo/node.js:787 msgid "MTU" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:200 +#: htdocs/luci-static/resources/fchomo.js:201 msgid "Masque" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:206 +#: htdocs/luci-static/resources/fchomo/listeners.js:207 msgid "Masquerade" msgstr "偽裝" @@ -1734,24 +1748,24 @@ msgstr "匹配回應通過 ipcidr
" msgid "Match rule set." msgstr "匹配規則集。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1238 +#: htdocs/luci-static/resources/view/fchomo/node.js:1273 msgid "Max Early Data" msgstr "前置數據最大值" -#: htdocs/luci-static/resources/fchomo/listeners.js:419 -#: htdocs/luci-static/resources/view/fchomo/node.js:546 +#: htdocs/luci-static/resources/fchomo/listeners.js:450 +#: htdocs/luci-static/resources/view/fchomo/node.js:547 msgid "Max UDP relay packet size" msgstr "UDP 中繼數據包最大尺寸" -#: htdocs/luci-static/resources/fchomo/listeners.js:1042 +#: htdocs/luci-static/resources/fchomo/listeners.js:1131 msgid "Max buffered posts" msgstr "POST 最大緩衝" -#: htdocs/luci-static/resources/view/fchomo/node.js:1296 +#: htdocs/luci-static/resources/view/fchomo/node.js:1331 msgid "Max concurrency" msgstr "最大並發" -#: htdocs/luci-static/resources/view/fchomo/node.js:1301 +#: htdocs/luci-static/resources/view/fchomo/node.js:1336 msgid "Max connections" msgstr "最大連線數" @@ -1759,43 +1773,51 @@ msgstr "最大連線數" msgid "Max count of failures" msgstr "最大失敗次數" -#: htdocs/luci-static/resources/fchomo/listeners.js:180 -#: htdocs/luci-static/resources/view/fchomo/node.js:291 +#: htdocs/luci-static/resources/fchomo/listeners.js:181 +#: htdocs/luci-static/resources/view/fchomo/node.js:292 msgid "Max download speed" msgstr "最大下載速度" -#: htdocs/luci-static/resources/fchomo/listeners.js:1053 -#: htdocs/luci-static/resources/view/fchomo/node.js:1278 +#: htdocs/luci-static/resources/fchomo/listeners.js:1142 +#: htdocs/luci-static/resources/view/fchomo/node.js:1313 msgid "Max each POST bytes" msgstr "POST 最大位元組數" -#: htdocs/luci-static/resources/view/fchomo/node.js:573 +#: htdocs/luci-static/resources/view/fchomo/node.js:574 msgid "Max open streams" msgstr "限制打開流的數量" -#: htdocs/luci-static/resources/view/fchomo/node.js:1311 +#: htdocs/luci-static/resources/fchomo/listeners.js:220 +msgid "Max realms" +msgstr "最大 Realms 數量" + +#: htdocs/luci-static/resources/fchomo/listeners.js:226 +msgid "Max realms per client IP" +msgstr "每客戶端 IP 最大 Realms 數量" + +#: htdocs/luci-static/resources/view/fchomo/node.js:1346 msgid "Max request times" msgstr "最大請求次數" -#: htdocs/luci-static/resources/view/fchomo/node.js:1316 +#: htdocs/luci-static/resources/view/fchomo/node.js:1351 msgid "Max reusable seconds" msgstr "最大可重用秒數" -#: htdocs/luci-static/resources/view/fchomo/node.js:1306 +#: htdocs/luci-static/resources/view/fchomo/node.js:1341 msgid "Max reuse times" msgstr "最大重用次數" -#: htdocs/luci-static/resources/fchomo/listeners.js:174 -#: htdocs/luci-static/resources/view/fchomo/node.js:285 +#: htdocs/luci-static/resources/fchomo/listeners.js:175 +#: htdocs/luci-static/resources/view/fchomo/node.js:286 msgid "Max upload speed" msgstr "最大上傳速度" -#: htdocs/luci-static/resources/view/fchomo/node.js:1342 -#: htdocs/luci-static/resources/view/fchomo/node.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1377 +#: htdocs/luci-static/resources/view/fchomo/node.js:1397 msgid "Maximum connections" msgstr "最大連線數" -#: htdocs/luci-static/resources/view/fchomo/node.js:1360 +#: htdocs/luci-static/resources/view/fchomo/node.js:1395 msgid "" "Maximum multiplexed streams in a connection before opening a new connection." "
Conflict with %s and %s." @@ -1803,24 +1825,24 @@ msgstr "" "在開啟新連線之前,連線中的最大多路復用流數量。
%s 和 " "%s 衝突。" -#: htdocs/luci-static/resources/fchomo/listeners.js:359 -#: htdocs/luci-static/resources/view/fchomo/node.js:428 +#: htdocs/luci-static/resources/fchomo/listeners.js:390 +#: htdocs/luci-static/resources/view/fchomo/node.js:429 msgid "Maximum padding rate" msgstr "最大填充率" -#: htdocs/luci-static/resources/fchomo/listeners.js:367 -#: htdocs/luci-static/resources/view/fchomo/node.js:436 +#: htdocs/luci-static/resources/fchomo/listeners.js:398 +#: htdocs/luci-static/resources/view/fchomo/node.js:437 msgid "" "Maximum padding rate must be greater than or equal to the minimum padding " "rate." msgstr "最大填充率必須大於等于最小填充率。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1359 +#: htdocs/luci-static/resources/view/fchomo/node.js:1394 msgid "Maximum streams" msgstr "最大流數量" #: htdocs/luci-static/resources/fchomo.js:157 -#: htdocs/luci-static/resources/fchomo.js:190 +#: htdocs/luci-static/resources/fchomo.js:191 msgid "Mieru" msgstr "" @@ -1836,26 +1858,26 @@ msgstr "Mihomo 客戶端" msgid "Mihomo server" msgstr "Mihomo 服務端" -#: htdocs/luci-static/resources/view/fchomo/node.js:617 +#: htdocs/luci-static/resources/view/fchomo/node.js:618 msgid "Min of idle sessions to keep" msgstr "要保留的最少閒置會話數" -#: htdocs/luci-static/resources/view/fchomo/node.js:1284 +#: htdocs/luci-static/resources/view/fchomo/node.js:1319 msgid "Min posts interval" msgstr "POST 請求最小間隔時間" -#: htdocs/luci-static/resources/view/fchomo/node.js:1351 +#: htdocs/luci-static/resources/view/fchomo/node.js:1386 msgid "" "Minimum multiplexed streams in a connection before opening a new connection." msgstr "在開啟新連線之前,連線中的最小多路復用流數量。" -#: htdocs/luci-static/resources/fchomo/listeners.js:352 -#: htdocs/luci-static/resources/view/fchomo/node.js:421 +#: htdocs/luci-static/resources/fchomo/listeners.js:383 +#: htdocs/luci-static/resources/view/fchomo/node.js:422 msgid "Minimum padding rate" msgstr "最小填充率" -#: htdocs/luci-static/resources/view/fchomo/node.js:1350 -#: htdocs/luci-static/resources/view/fchomo/node.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1385 +#: htdocs/luci-static/resources/view/fchomo/node.js:1397 msgid "Minimum streams" msgstr "最小流數量" @@ -1872,16 +1894,16 @@ msgstr "混合 系統 TCP 堆栈和 gVisor UDP 堆栈 msgid "Mixed port" msgstr "混合連接埠" -#: htdocs/luci-static/resources/view/fchomo/node.js:1328 +#: htdocs/luci-static/resources/view/fchomo/node.js:1363 msgid "Multiplex" msgstr "多路復用" -#: htdocs/luci-static/resources/fchomo/listeners.js:123 -#: htdocs/luci-static/resources/view/fchomo/node.js:226 +#: htdocs/luci-static/resources/fchomo/listeners.js:124 +#: htdocs/luci-static/resources/view/fchomo/node.js:227 msgid "Multiplex fields" msgstr "多路復用欄位" -#: htdocs/luci-static/resources/view/fchomo/node.js:362 +#: htdocs/luci-static/resources/view/fchomo/node.js:363 msgid "Multiplexing" msgstr "多路復用" @@ -1890,11 +1912,11 @@ msgstr "多路復用" msgid "NOT" msgstr "NOT" -#: htdocs/luci-static/resources/fchomo/listeners.js:536 +#: htdocs/luci-static/resources/fchomo/listeners.js:574 msgid "Name of the Proxy group as outbound." msgstr "出站代理組的名稱。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1640 +#: htdocs/luci-static/resources/view/fchomo/node.js:1675 msgid "Name of the Proxy group to download provider." msgstr "用於下載供應商訂閱的代理組名稱。" @@ -1902,23 +1924,23 @@ msgstr "用於下載供應商訂閱的代理組名稱。" msgid "Name of the Proxy group to download rule set." msgstr "用於下載規則集訂閱的代理組名稱。" -#: htdocs/luci-static/resources/fchomo/listeners.js:530 +#: htdocs/luci-static/resources/fchomo/listeners.js:568 msgid "Name of the Sub rule used for inbound matching." msgstr "用於入站匹配的子規則名稱。" -#: htdocs/luci-static/resources/view/fchomo/node.js:530 +#: htdocs/luci-static/resources/view/fchomo/node.js:531 msgid "Native UDP" msgstr "原生 UDP" -#: htdocs/luci-static/resources/fchomo.js:381 +#: htdocs/luci-static/resources/fchomo.js:382 msgid "Native appearance" msgstr "原生外觀" -#: htdocs/luci-static/resources/fchomo/listeners.js:562 +#: htdocs/luci-static/resources/fchomo/listeners.js:600 msgid "Network type" msgstr "網路類型" -#: htdocs/luci-static/resources/view/fchomo/node.js:1726 +#: htdocs/luci-static/resources/view/fchomo/node.js:1761 msgid "No" msgstr "" @@ -1926,7 +1948,7 @@ msgstr "" msgid "No Authentication IP ranges" msgstr "無需認證的 IP 範圍" -#: htdocs/luci-static/resources/fchomo/listeners.js:1037 +#: htdocs/luci-static/resources/fchomo/listeners.js:1126 msgid "No SSE header" msgstr "無 SSE header" @@ -1934,16 +1956,16 @@ msgstr "無 SSE header" msgid "No add'l params" msgstr "無附加參數" -#: htdocs/luci-static/resources/view/fchomo/node.js:1268 +#: htdocs/luci-static/resources/view/fchomo/node.js:1303 msgid "No gRPC header" msgstr "無 gRPC header" #: htdocs/luci-static/resources/view/fchomo/client.js:1115 -#: htdocs/luci-static/resources/view/fchomo/node.js:1789 +#: htdocs/luci-static/resources/view/fchomo/node.js:1824 msgid "No testing is performed when this provider node is not in use." msgstr "當此供應商的節點未使用時,不執行任何測試。" -#: htdocs/luci-static/resources/fchomo.js:686 +#: htdocs/luci-static/resources/fchomo.js:687 msgid "No valid %s found." msgstr "未找到有效的%s。" @@ -1958,17 +1980,17 @@ msgid "Node" msgstr "節點" #: htdocs/luci-static/resources/view/fchomo/client.js:1160 -#: htdocs/luci-static/resources/view/fchomo/node.js:1809 +#: htdocs/luci-static/resources/view/fchomo/node.js:1844 msgid "Node exclude filter" msgstr "排除節點" #: htdocs/luci-static/resources/view/fchomo/client.js:1165 -#: htdocs/luci-static/resources/view/fchomo/node.js:1816 +#: htdocs/luci-static/resources/view/fchomo/node.js:1851 msgid "Node exclude type" msgstr "排除節點類型" #: htdocs/luci-static/resources/view/fchomo/client.js:1155 -#: htdocs/luci-static/resources/view/fchomo/node.js:1803 +#: htdocs/luci-static/resources/view/fchomo/node.js:1838 msgid "Node filter" msgstr "過濾節點" @@ -1976,7 +1998,7 @@ msgstr "過濾節點" msgid "Node switch tolerance" msgstr "節點切換容差" -#: htdocs/luci-static/resources/fchomo.js:408 +#: htdocs/luci-static/resources/fchomo.js:409 msgid "None" msgstr "無" @@ -1984,38 +2006,39 @@ msgstr "無" msgid "Not Installed" msgstr "未安裝" -#: htdocs/luci-static/resources/fchomo.js:1204 +#: htdocs/luci-static/resources/fchomo.js:1205 msgid "Not Running" msgstr "未在運作" -#: htdocs/luci-static/resources/view/fchomo/node.js:482 +#: htdocs/luci-static/resources/view/fchomo/node.js:483 msgid "OFF" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:485 msgid "ON" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:815 +#: htdocs/luci-static/resources/fchomo/listeners.js:538 +#: htdocs/luci-static/resources/view/fchomo/node.js:816 msgid "Obfs Mode" msgstr "Obfs 模式" -#: htdocs/luci-static/resources/fchomo/listeners.js:198 -#: htdocs/luci-static/resources/view/fchomo/node.js:303 +#: htdocs/luci-static/resources/fchomo/listeners.js:199 +#: htdocs/luci-static/resources/view/fchomo/node.js:304 msgid "Obfuscate password" msgstr "混淆密碼" -#: htdocs/luci-static/resources/fchomo/listeners.js:192 -#: htdocs/luci-static/resources/fchomo/listeners.js:327 -#: htdocs/luci-static/resources/view/fchomo/node.js:297 -#: htdocs/luci-static/resources/view/fchomo/node.js:407 +#: htdocs/luci-static/resources/fchomo/listeners.js:193 +#: htdocs/luci-static/resources/fchomo/listeners.js:358 +#: htdocs/luci-static/resources/view/fchomo/node.js:298 +#: htdocs/luci-static/resources/view/fchomo/node.js:408 msgid "Obfuscate type" msgstr "混淆類型" -#: htdocs/luci-static/resources/fchomo/listeners.js:328 -#: htdocs/luci-static/resources/fchomo/listeners.js:329 -#: htdocs/luci-static/resources/view/fchomo/node.js:408 +#: htdocs/luci-static/resources/fchomo/listeners.js:359 +#: htdocs/luci-static/resources/fchomo/listeners.js:360 #: htdocs/luci-static/resources/view/fchomo/node.js:409 +#: htdocs/luci-static/resources/view/fchomo/node.js:410 msgid "Obfuscated as %s" msgstr "混淆為%s" @@ -2023,8 +2046,8 @@ msgstr "混淆為%s" msgid "One or more numbers in the range 0-63 separated by commas" msgstr "0-63 範圍內的一個或多個數字,以逗號分隔" -#: htdocs/luci-static/resources/fchomo/listeners.js:336 -#: htdocs/luci-static/resources/view/fchomo/node.js:416 +#: htdocs/luci-static/resources/fchomo/listeners.js:367 +#: htdocs/luci-static/resources/view/fchomo/node.js:417 msgid "Only applies to the %s." msgstr "只對%s生效。" @@ -2032,7 +2055,7 @@ msgstr "只對%s生效。" msgid "Only process traffic from specific interfaces. Leave empty for all." msgstr "只處理來自指定介面的流量。留空表示全部。" -#: htdocs/luci-static/resources/fchomo.js:1198 +#: htdocs/luci-static/resources/fchomo.js:1199 msgid "Open Dashboard" msgstr "打開面板" @@ -2046,11 +2069,11 @@ msgid "Override destination" msgstr "覆蓋目標位址" #: htdocs/luci-static/resources/view/fchomo/client.js:1010 -#: htdocs/luci-static/resources/view/fchomo/node.js:1551 +#: htdocs/luci-static/resources/view/fchomo/node.js:1586 msgid "Override fields" msgstr "覆蓋欄位" -#: htdocs/luci-static/resources/view/fchomo/node.js:522 +#: htdocs/luci-static/resources/view/fchomo/node.js:523 msgid "Override the IP address of the server that DNS response." msgstr "覆蓋 DNS 回應的伺服器的 IP 位址。" @@ -2066,7 +2089,7 @@ msgstr "使用嗅探到的網域覆寫連線目標。" msgid "Override the existing ECS in original request." msgstr "覆蓋原始請求中已有的 ECS。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1100 +#: htdocs/luci-static/resources/view/fchomo/node.js:1135 msgid "Overrides the domain name used for HTTPS record queries." msgstr "覆蓋用於 HTTPS 記錄查詢的網域。" @@ -2074,47 +2097,47 @@ msgstr "覆蓋用於 HTTPS 記錄查詢的網域。" msgid "Overview" msgstr "概覽" -#: htdocs/luci-static/resources/view/fchomo/node.js:1195 +#: htdocs/luci-static/resources/view/fchomo/node.js:1230 msgid "POST" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1196 +#: htdocs/luci-static/resources/view/fchomo/node.js:1231 msgid "PUT" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:666 +#: htdocs/luci-static/resources/view/fchomo/node.js:667 msgid "Packet encoding" msgstr "數據包編碼" -#: htdocs/luci-static/resources/view/fchomo/node.js:1273 +#: htdocs/luci-static/resources/view/fchomo/node.js:1308 msgid "Padding bytes" msgstr "填充位元組" -#: htdocs/luci-static/resources/fchomo/listeners.js:463 +#: htdocs/luci-static/resources/fchomo/listeners.js:494 msgid "Padding scheme" msgstr "填充方案" -#: htdocs/luci-static/resources/fchomo/listeners.js:661 -#: htdocs/luci-static/resources/view/fchomo/node.js:938 +#: htdocs/luci-static/resources/fchomo/listeners.js:699 +#: htdocs/luci-static/resources/view/fchomo/node.js:939 msgid "Paddings" msgstr "填充 (Paddings)" -#: htdocs/luci-static/resources/fchomo/listeners.js:165 -#: htdocs/luci-static/resources/fchomo/listeners.js:221 -#: htdocs/luci-static/resources/fchomo/listeners.js:513 -#: htdocs/luci-static/resources/view/fchomo/node.js:261 -#: htdocs/luci-static/resources/view/fchomo/node.js:340 -#: htdocs/luci-static/resources/view/fchomo/node.js:830 +#: htdocs/luci-static/resources/fchomo/listeners.js:166 +#: htdocs/luci-static/resources/fchomo/listeners.js:252 +#: htdocs/luci-static/resources/fchomo/listeners.js:551 +#: htdocs/luci-static/resources/view/fchomo/node.js:262 +#: htdocs/luci-static/resources/view/fchomo/node.js:341 +#: htdocs/luci-static/resources/view/fchomo/node.js:831 msgid "Password" msgstr "密碼" -#: htdocs/luci-static/resources/fchomo/listeners.js:601 -#: htdocs/luci-static/resources/view/fchomo/node.js:1615 +#: htdocs/luci-static/resources/fchomo/listeners.js:639 +#: htdocs/luci-static/resources/view/fchomo/node.js:1650 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:364 msgid "Payload" msgstr "Payload" -#: htdocs/luci-static/resources/view/fchomo/node.js:754 +#: htdocs/luci-static/resources/view/fchomo/node.js:755 msgid "Peer pubkic key" msgstr "對端公鑰" @@ -2124,11 +2147,11 @@ msgid "" "it is not needed." msgstr "效能可能會略有下降,建議僅在需要時開啟。" -#: htdocs/luci-static/resources/view/fchomo/node.js:781 +#: htdocs/luci-static/resources/view/fchomo/node.js:782 msgid "Periodically sends data packets to maintain connection persistence." msgstr "定期發送資料包以維持連線持久性。" -#: htdocs/luci-static/resources/view/fchomo/node.js:780 +#: htdocs/luci-static/resources/view/fchomo/node.js:781 msgid "Persistent keepalive" msgstr "持久連接" @@ -2151,8 +2174,8 @@ msgid "" "standards." msgstr "連結格式標準請參考
%s。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1588 -#: htdocs/luci-static/resources/view/fchomo/node.js:1614 +#: htdocs/luci-static/resources/view/fchomo/node.js:1623 +#: htdocs/luci-static/resources/view/fchomo/node.js:1649 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:337 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:363 msgid "" @@ -2167,41 +2190,42 @@ msgstr "" #: htdocs/luci-static/resources/view/fchomo/client.js:1445 #: htdocs/luci-static/resources/view/fchomo/client.js:1697 #: htdocs/luci-static/resources/view/fchomo/client.js:1749 -#: htdocs/luci-static/resources/view/fchomo/node.js:1458 +#: htdocs/luci-static/resources/view/fchomo/node.js:1493 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:154 msgid "Please type %s fields of mihomo config.
" msgstr "請輸入 mihomo 配置的 %s 欄位。
" -#: htdocs/luci-static/resources/fchomo/listeners.js:499 -#: htdocs/luci-static/resources/view/fchomo/node.js:804 +#: htdocs/luci-static/resources/fchomo/listeners.js:530 +#: htdocs/luci-static/resources/view/fchomo/node.js:805 msgid "Plugin" msgstr "插件" -#: htdocs/luci-static/resources/fchomo/listeners.js:506 -#: htdocs/luci-static/resources/fchomo/listeners.js:513 -#: htdocs/luci-static/resources/fchomo/listeners.js:519 -#: htdocs/luci-static/resources/view/fchomo/node.js:815 -#: htdocs/luci-static/resources/view/fchomo/node.js:822 -#: htdocs/luci-static/resources/view/fchomo/node.js:830 -#: htdocs/luci-static/resources/view/fchomo/node.js:836 -#: htdocs/luci-static/resources/view/fchomo/node.js:844 -#: htdocs/luci-static/resources/view/fchomo/node.js:850 +#: htdocs/luci-static/resources/fchomo/listeners.js:538 +#: htdocs/luci-static/resources/fchomo/listeners.js:544 +#: htdocs/luci-static/resources/fchomo/listeners.js:551 +#: htdocs/luci-static/resources/fchomo/listeners.js:557 +#: htdocs/luci-static/resources/view/fchomo/node.js:816 +#: htdocs/luci-static/resources/view/fchomo/node.js:823 +#: htdocs/luci-static/resources/view/fchomo/node.js:831 +#: htdocs/luci-static/resources/view/fchomo/node.js:837 +#: htdocs/luci-static/resources/view/fchomo/node.js:845 +#: htdocs/luci-static/resources/view/fchomo/node.js:851 msgid "Plugin:" msgstr "插件:" -#: htdocs/luci-static/resources/view/fchomo/node.js:249 +#: htdocs/luci-static/resources/view/fchomo/node.js:250 msgid "Port" msgstr "連接埠" -#: htdocs/luci-static/resources/fchomo.js:1435 +#: htdocs/luci-static/resources/fchomo.js:1436 msgid "Port %s alrealy exists!" msgstr "連接埠 %s 已存在!" -#: htdocs/luci-static/resources/view/fchomo/node.js:279 +#: htdocs/luci-static/resources/view/fchomo/node.js:280 msgid "Port hop interval" msgstr "連接埠跳躍間隔" -#: htdocs/luci-static/resources/view/fchomo/node.js:350 +#: htdocs/luci-static/resources/view/fchomo/node.js:351 msgid "Port range" msgstr "連接埠範圍" @@ -2209,21 +2233,27 @@ msgstr "連接埠範圍" msgid "Ports" msgstr "連接埠" -#: htdocs/luci-static/resources/fchomo/listeners.js:152 -#: htdocs/luci-static/resources/view/fchomo/node.js:274 +#: htdocs/luci-static/resources/fchomo/listeners.js:153 +#: htdocs/luci-static/resources/view/fchomo/node.js:275 msgid "Ports pool" msgstr "連接埠池" -#: htdocs/luci-static/resources/view/fchomo/node.js:499 -#: htdocs/luci-static/resources/view/fchomo/node.js:761 +#: htdocs/luci-static/resources/fchomo/listeners.js:214 +#: htdocs/luci-static/resources/view/fchomo/node.js:500 +#: htdocs/luci-static/resources/view/fchomo/node.js:762 msgid "Pre-shared key" msgstr "預先共用金鑰" -#: htdocs/luci-static/resources/fchomo.js:174 +#: htdocs/luci-static/resources/fchomo/listeners.js:837 +#: htdocs/luci-static/resources/view/fchomo/node.js:974 +msgid "Pre-shared key of rendezvous server" +msgstr "牽線伺服器的預先共用金鑰" + +#: htdocs/luci-static/resources/fchomo.js:175 msgid "Prefer IPv4" msgstr "優先 IPv4" -#: htdocs/luci-static/resources/fchomo.js:175 +#: htdocs/luci-static/resources/fchomo.js:176 msgid "Prefer IPv6" msgstr "優先 IPv6" @@ -2234,23 +2264,23 @@ msgstr "防止某些情況下的 ICMP 環回問題。 Ping 不會顯示實際延 #: htdocs/luci-static/resources/view/fchomo/global.js:736 #: htdocs/luci-static/resources/view/fchomo/global.js:753 -#: htdocs/luci-static/resources/view/fchomo/node.js:1422 -#: htdocs/luci-static/resources/view/fchomo/node.js:1428 -#: htdocs/luci-static/resources/view/fchomo/node.js:1738 -#: htdocs/luci-static/resources/view/fchomo/node.js:1745 +#: htdocs/luci-static/resources/view/fchomo/node.js:1457 +#: htdocs/luci-static/resources/view/fchomo/node.js:1463 +#: htdocs/luci-static/resources/view/fchomo/node.js:1773 +#: htdocs/luci-static/resources/view/fchomo/node.js:1780 msgid "Priority: Proxy Node > Global." msgstr "優先權: 代理節點 > 全域。" -#: htdocs/luci-static/resources/view/fchomo/node.js:312 +#: htdocs/luci-static/resources/view/fchomo/node.js:313 msgid "Priv-key" msgstr "金鑰" -#: htdocs/luci-static/resources/view/fchomo/node.js:316 +#: htdocs/luci-static/resources/view/fchomo/node.js:317 msgid "Priv-key passphrase" msgstr "金鑰密碼" -#: htdocs/luci-static/resources/view/fchomo/node.js:674 -#: htdocs/luci-static/resources/view/fchomo/node.js:746 +#: htdocs/luci-static/resources/view/fchomo/node.js:675 +#: htdocs/luci-static/resources/view/fchomo/node.js:747 msgid "Private key" msgstr "私鑰" @@ -2259,28 +2289,28 @@ msgid "Process matching mode" msgstr "進程匹配模式" #: htdocs/luci-static/resources/view/fchomo/global.js:684 -#: htdocs/luci-static/resources/view/fchomo/node.js:1334 +#: htdocs/luci-static/resources/view/fchomo/node.js:1369 msgid "Protocol" msgstr "協議" -#: htdocs/luci-static/resources/view/fchomo/node.js:661 +#: htdocs/luci-static/resources/view/fchomo/node.js:662 msgid "Protocol parameter. Enable length block encryption." msgstr "協議參數。啟用長度塊加密。" -#: htdocs/luci-static/resources/view/fchomo/node.js:655 +#: htdocs/luci-static/resources/view/fchomo/node.js:656 msgid "" "Protocol parameter. Will waste traffic randomly if enabled (enabled by " "default in v2ray and cannot be disabled)." msgstr "協議參數。 如啟用會隨機浪費流量(在 v2ray 中預設為啟用且無法停用)。" #: htdocs/luci-static/resources/view/fchomo/client.js:1055 -#: htdocs/luci-static/resources/view/fchomo/node.js:1441 -#: htdocs/luci-static/resources/view/fchomo/node.js:1450 -#: htdocs/luci-static/resources/view/fchomo/node.js:1854 +#: htdocs/luci-static/resources/view/fchomo/node.js:1476 +#: htdocs/luci-static/resources/view/fchomo/node.js:1485 +#: htdocs/luci-static/resources/view/fchomo/node.js:1889 msgid "Provider" msgstr "供應商" -#: htdocs/luci-static/resources/view/fchomo/node.js:1621 +#: htdocs/luci-static/resources/view/fchomo/node.js:1656 msgid "Provider URL" msgstr "供應商訂閱 URL" @@ -2303,19 +2333,19 @@ msgid "Proxy MAC-s" msgstr "代理 MAC 位址" #: htdocs/luci-static/resources/view/fchomo/node.js:208 -#: htdocs/luci-static/resources/view/fchomo/node.js:1853 +#: htdocs/luci-static/resources/view/fchomo/node.js:1888 msgid "Proxy Node" msgstr "代理節點" -#: htdocs/luci-static/resources/view/fchomo/node.js:1829 -#: htdocs/luci-static/resources/view/fchomo/node.js:1838 +#: htdocs/luci-static/resources/view/fchomo/node.js:1864 +#: htdocs/luci-static/resources/view/fchomo/node.js:1873 msgid "Proxy chain" msgstr "代理鏈" -#: htdocs/luci-static/resources/fchomo/listeners.js:535 +#: htdocs/luci-static/resources/fchomo/listeners.js:573 #: htdocs/luci-static/resources/view/fchomo/client.js:783 #: htdocs/luci-static/resources/view/fchomo/client.js:1543 -#: htdocs/luci-static/resources/view/fchomo/node.js:1639 +#: htdocs/luci-static/resources/view/fchomo/node.js:1674 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:388 msgid "Proxy group" msgstr "代理組" @@ -2332,8 +2362,8 @@ msgstr "代理模式" msgid "Proxy routerself" msgstr "代理路由器自身" -#: htdocs/luci-static/resources/view/fchomo/node.js:531 -#: htdocs/luci-static/resources/view/fchomo/node.js:726 +#: htdocs/luci-static/resources/view/fchomo/node.js:532 +#: htdocs/luci-static/resources/view/fchomo/node.js:727 msgid "QUIC" msgstr "" @@ -2342,44 +2372,44 @@ msgstr "" msgid "Quick Reload" msgstr "快速重載" -#: htdocs/luci-static/resources/fchomo/listeners.js:931 -#: htdocs/luci-static/resources/view/fchomo/node.js:1114 +#: htdocs/luci-static/resources/fchomo/listeners.js:1020 +#: htdocs/luci-static/resources/view/fchomo/node.js:1149 msgid "REALITY" msgstr "REALITY" -#: htdocs/luci-static/resources/view/fchomo/node.js:1129 +#: htdocs/luci-static/resources/view/fchomo/node.js:1164 msgid "REALITY X25519MLKEM768 PQC support" msgstr "REALITY X25519MLKEM768 後量子加密支援" -#: htdocs/luci-static/resources/fchomo/listeners.js:968 +#: htdocs/luci-static/resources/fchomo/listeners.js:1057 msgid "REALITY certificate issued to" msgstr "REALITY 證書頒發給" -#: htdocs/luci-static/resources/fchomo/listeners.js:936 +#: htdocs/luci-static/resources/fchomo/listeners.js:1025 msgid "REALITY handshake server" msgstr "REALITY 握手伺服器" -#: htdocs/luci-static/resources/fchomo/listeners.js:943 +#: htdocs/luci-static/resources/fchomo/listeners.js:1032 msgid "REALITY private key" msgstr "REALITY 私鑰" -#: htdocs/luci-static/resources/fchomo/listeners.js:958 -#: htdocs/luci-static/resources/view/fchomo/node.js:1119 +#: htdocs/luci-static/resources/fchomo/listeners.js:1047 +#: htdocs/luci-static/resources/view/fchomo/node.js:1154 msgid "REALITY public key" msgstr "REALITY 公鑰" -#: htdocs/luci-static/resources/fchomo/listeners.js:962 -#: htdocs/luci-static/resources/view/fchomo/node.js:1124 +#: htdocs/luci-static/resources/fchomo/listeners.js:1051 +#: htdocs/luci-static/resources/view/fchomo/node.js:1159 msgid "REALITY short ID" msgstr "REALITY 標識符" -#: htdocs/luci-static/resources/fchomo/listeners.js:632 -#: htdocs/luci-static/resources/fchomo/listeners.js:651 -#: htdocs/luci-static/resources/view/fchomo/node.js:928 +#: htdocs/luci-static/resources/fchomo/listeners.js:670 +#: htdocs/luci-static/resources/fchomo/listeners.js:689 +#: htdocs/luci-static/resources/view/fchomo/node.js:929 msgid "RTT" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:373 +#: htdocs/luci-static/resources/fchomo.js:374 msgid "Random" msgstr "隨機" @@ -2387,10 +2417,24 @@ msgstr "隨機" msgid "Random will be used if empty." msgstr "留空將使用隨機令牌。" -#: htdocs/luci-static/resources/fchomo.js:383 +#: htdocs/luci-static/resources/fchomo.js:384 msgid "Randomized traffic characteristics" msgstr "隨機化流量特徵" +#: htdocs/luci-static/resources/fchomo/listeners.js:826 +#: htdocs/luci-static/resources/view/fchomo/node.js:963 +msgid "Realm" +msgstr "Realm" + +#: htdocs/luci-static/resources/fchomo/listeners.js:842 +#: htdocs/luci-static/resources/view/fchomo/node.js:979 +msgid "Realm ID" +msgstr "Realm ID" + +#: htdocs/luci-static/resources/fchomo/listeners.js:237 +msgid "Realm name pattern" +msgstr "Realm 名稱模式" + #: htdocs/luci-static/resources/view/fchomo/global.js:460 msgid "Redir port" msgstr "Redir 連接埠" @@ -2411,7 +2455,7 @@ msgstr "Redirect TCP + Tun UDP" msgid "Refresh every %s seconds." msgstr "每 %s 秒刷新。" -#: htdocs/luci-static/resources/fchomo.js:1191 +#: htdocs/luci-static/resources/fchomo.js:1192 #: htdocs/luci-static/resources/view/fchomo/client.js:927 #: htdocs/luci-static/resources/view/fchomo/global.js:193 #: htdocs/luci-static/resources/view/fchomo/server.js:45 @@ -2422,64 +2466,69 @@ msgstr "重載" msgid "Reload All" msgstr "重載所有" -#: htdocs/luci-static/resources/view/fchomo/node.js:1566 +#: htdocs/luci-static/resources/view/fchomo/node.js:1601 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:278 msgid "Remote" msgstr "遠端" -#: htdocs/luci-static/resources/view/fchomo/node.js:709 -#: htdocs/luci-static/resources/view/fchomo/node.js:792 +#: htdocs/luci-static/resources/view/fchomo/node.js:710 +#: htdocs/luci-static/resources/view/fchomo/node.js:793 msgid "Remote DNS resolve" msgstr "遠端 DNS 解析" -#: htdocs/luci-static/resources/fchomo.js:1356 +#: htdocs/luci-static/resources/fchomo.js:1357 msgid "Remove" msgstr "移除" -#: htdocs/luci-static/resources/fchomo.js:1361 -#: htdocs/luci-static/resources/view/fchomo/node.js:1542 -#: htdocs/luci-static/resources/view/fchomo/node.js:1544 +#: htdocs/luci-static/resources/fchomo.js:1362 +#: htdocs/luci-static/resources/view/fchomo/node.js:1577 +#: htdocs/luci-static/resources/view/fchomo/node.js:1579 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:251 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:253 msgid "Remove idles" msgstr "移除閒置" -#: htdocs/luci-static/resources/view/fchomo/node.js:1668 +#: htdocs/luci-static/resources/fchomo/listeners.js:831 +#: htdocs/luci-static/resources/view/fchomo/node.js:968 +msgid "Rendezvous server" +msgstr "牽線伺服器" + +#: htdocs/luci-static/resources/view/fchomo/node.js:1703 msgid "Replace name" msgstr "名稱替換" -#: htdocs/luci-static/resources/view/fchomo/node.js:1669 +#: htdocs/luci-static/resources/view/fchomo/node.js:1704 msgid "Replace node name." msgstr "替換節點名稱" -#: htdocs/luci-static/resources/fchomo.js:357 +#: htdocs/luci-static/resources/fchomo.js:358 msgid "Request" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1016 -#: htdocs/luci-static/resources/view/fchomo/node.js:1202 -#: htdocs/luci-static/resources/view/fchomo/node.js:1209 +#: htdocs/luci-static/resources/fchomo/listeners.js:1105 +#: htdocs/luci-static/resources/view/fchomo/node.js:1237 +#: htdocs/luci-static/resources/view/fchomo/node.js:1244 msgid "Request path" msgstr "請求路徑" -#: htdocs/luci-static/resources/view/fchomo/node.js:566 +#: htdocs/luci-static/resources/view/fchomo/node.js:567 msgid "Request timeout" msgstr "請求逾時" -#: htdocs/luci-static/resources/fchomo.js:360 +#: htdocs/luci-static/resources/fchomo.js:361 msgid "Require and verify" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:358 +#: htdocs/luci-static/resources/fchomo.js:359 msgid "Require any" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:391 -#: htdocs/luci-static/resources/view/fchomo/node.js:1130 +#: htdocs/luci-static/resources/fchomo.js:392 +#: htdocs/luci-static/resources/view/fchomo/node.js:1165 msgid "Requires server support." msgstr "需要伺服器支援。" -#: htdocs/luci-static/resources/view/fchomo/node.js:775 +#: htdocs/luci-static/resources/view/fchomo/node.js:776 msgid "Reserved field bytes" msgstr "保留字段位元組" @@ -2487,7 +2536,7 @@ msgstr "保留字段位元組" msgid "Resources management" msgstr "資源管理" -#: htdocs/luci-static/resources/view/fchomo/node.js:850 +#: htdocs/luci-static/resources/view/fchomo/node.js:851 msgid "Restls script" msgstr "Restls 劇本" @@ -2501,12 +2550,12 @@ msgid "" "Returns the string input for icon in the API to display in this proxy group." msgstr "在 API 傳回 icon 所輸入的字串,以在該代理組顯示。" -#: htdocs/luci-static/resources/view/fchomo/node.js:483 +#: htdocs/luci-static/resources/view/fchomo/node.js:484 msgid "Reuse HTTP connections to reduce RTT for each connection establishment." msgstr "重用 HTTP 連接以減少每次建立連接的 RTT。" -#: htdocs/luci-static/resources/view/fchomo/node.js:480 -#: htdocs/luci-static/resources/view/fchomo/node.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:481 +#: htdocs/luci-static/resources/view/fchomo/node.js:485 msgid "Reusing a single tunnel to carry multiple target connections within it." msgstr "複用單條隧道使其內部承載多條目標連線。" @@ -2523,8 +2572,8 @@ msgstr "路由 DSCP" msgid "Routing GFW" msgstr "路由 GFW 流量" -#: htdocs/luci-static/resources/view/fchomo/node.js:1427 -#: htdocs/luci-static/resources/view/fchomo/node.js:1744 +#: htdocs/luci-static/resources/view/fchomo/node.js:1462 +#: htdocs/luci-static/resources/view/fchomo/node.js:1779 msgid "Routing mark" msgstr "路由標記" @@ -2584,11 +2633,11 @@ msgstr "規則集" msgid "Ruleset-URI-Scheme" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1204 +#: htdocs/luci-static/resources/fchomo.js:1205 msgid "Running" msgstr "正在運作" -#: htdocs/luci-static/resources/fchomo.js:239 +#: htdocs/luci-static/resources/fchomo.js:240 msgid "SMTP" msgstr "" @@ -2596,36 +2645,41 @@ msgstr "" msgid "SOCKS" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo.js:188 msgid "SOCKS5" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:203 +#: htdocs/luci-static/resources/fchomo.js:204 msgid "SSH" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:240 +#: htdocs/luci-static/resources/fchomo.js:241 msgid "STUN" msgstr "" +#: htdocs/luci-static/resources/fchomo/listeners.js:848 +#: htdocs/luci-static/resources/view/fchomo/node.js:985 +msgid "STUN servers" +msgstr "STUN 伺服器" + #: htdocs/luci-static/resources/view/fchomo/client.js:1276 msgid "SUB-RULE" msgstr "SUB-RULE" -#: htdocs/luci-static/resources/view/fchomo/node.js:885 +#: htdocs/luci-static/resources/view/fchomo/node.js:886 msgid "SUoT version" msgstr "SUoT 版本" -#: htdocs/luci-static/resources/fchomo/listeners.js:194 -#: htdocs/luci-static/resources/view/fchomo/node.js:299 +#: htdocs/luci-static/resources/fchomo/listeners.js:195 +#: htdocs/luci-static/resources/view/fchomo/node.js:300 msgid "Salamander" msgstr "Salamander" -#: htdocs/luci-static/resources/fchomo.js:180 +#: htdocs/luci-static/resources/fchomo.js:181 msgid "Same dstaddr requests. Same node" msgstr "相同 目標位址 請求。相同節點" -#: htdocs/luci-static/resources/fchomo.js:181 +#: htdocs/luci-static/resources/fchomo.js:182 msgid "Same srcaddr and dstaddr requests. Same node" msgstr "相同 來源位址 和 目標位址 請求。相同節點" @@ -2633,7 +2687,7 @@ msgstr "相同 來源位址 和 目標位址 請求。相同節點" msgid "Segment maximum size" msgstr "分段最大尺寸" -#: htdocs/luci-static/resources/fchomo.js:228 +#: htdocs/luci-static/resources/fchomo.js:229 msgid "Select" msgstr "手動選擇" @@ -2641,30 +2695,30 @@ msgstr "手動選擇" msgid "Select Dashboard" msgstr "選擇面板" -#: htdocs/luci-static/resources/fchomo.js:397 +#: htdocs/luci-static/resources/fchomo.js:398 msgid "Send padding randomly 0-3333 bytes with 50% probability." msgstr "以 50% 的機率發送隨機 0 到 3333 位元組的填充。" -#: htdocs/luci-static/resources/fchomo.js:386 #: htdocs/luci-static/resources/fchomo.js:387 +#: htdocs/luci-static/resources/fchomo.js:388 msgid "Send random ticket of 300s-600s duration for client 0-RTT reuse." msgstr "發送 300-600 秒的隨機票證,以供客戶端 0-RTT 重用。" -#: htdocs/luci-static/resources/fchomo/listeners.js:632 -#: htdocs/luci-static/resources/fchomo/listeners.js:829 -#: htdocs/luci-static/resources/fchomo/listeners.js:844 +#: htdocs/luci-static/resources/fchomo/listeners.js:670 +#: htdocs/luci-static/resources/fchomo/listeners.js:918 +#: htdocs/luci-static/resources/fchomo/listeners.js:933 #: htdocs/luci-static/resources/view/fchomo/server.js:58 #: root/usr/share/luci/menu.d/luci-app-fchomo.json:62 msgid "Server" msgstr "服務端" -#: htdocs/luci-static/resources/view/fchomo/node.js:244 +#: htdocs/luci-static/resources/view/fchomo/node.js:245 msgid "Server address" msgstr "伺服器位址" -#: htdocs/luci-static/resources/fchomo/listeners.js:1010 -#: htdocs/luci-static/resources/view/fchomo/node.js:1181 -#: htdocs/luci-static/resources/view/fchomo/node.js:1187 +#: htdocs/luci-static/resources/fchomo/listeners.js:1099 +#: htdocs/luci-static/resources/view/fchomo/node.js:1216 +#: htdocs/luci-static/resources/view/fchomo/node.js:1222 msgid "Server hostname" msgstr "伺服器主機名稱" @@ -2677,26 +2731,26 @@ msgid "Service status" msgstr "服務狀態" #: htdocs/luci-static/resources/fchomo.js:156 -#: htdocs/luci-static/resources/fchomo.js:188 +#: htdocs/luci-static/resources/fchomo.js:189 msgid "Shadowsocks" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:445 -#: htdocs/luci-static/resources/view/fchomo/node.js:585 +#: htdocs/luci-static/resources/fchomo/listeners.js:476 +#: htdocs/luci-static/resources/view/fchomo/node.js:586 msgid "Shadowsocks chipher" msgstr "Shadowsocks 加密方法" -#: htdocs/luci-static/resources/fchomo/listeners.js:440 -#: htdocs/luci-static/resources/view/fchomo/node.js:580 +#: htdocs/luci-static/resources/fchomo/listeners.js:471 +#: htdocs/luci-static/resources/view/fchomo/node.js:581 msgid "Shadowsocks encrypt" msgstr "Shadowsocks 加密" -#: htdocs/luci-static/resources/fchomo/listeners.js:453 -#: htdocs/luci-static/resources/view/fchomo/node.js:593 +#: htdocs/luci-static/resources/fchomo/listeners.js:484 +#: htdocs/luci-static/resources/view/fchomo/node.js:594 msgid "Shadowsocks password" msgstr "Shadowsocks 密碼" -#: htdocs/luci-static/resources/view/fchomo/node.js:1382 +#: htdocs/luci-static/resources/view/fchomo/node.js:1417 msgid "Show connections in the dashboard for breaking connections easier." msgstr "在面板中顯示連線以便於打斷連線。" @@ -2704,18 +2758,18 @@ msgstr "在面板中顯示連線以便於打斷連線。" msgid "Silent" msgstr "靜音" -#: htdocs/luci-static/resources/fchomo.js:179 +#: htdocs/luci-static/resources/fchomo.js:180 msgid "Simple round-robin all nodes" msgstr "簡單輪替所有節點" -#: htdocs/luci-static/resources/view/fchomo/node.js:1627 +#: htdocs/luci-static/resources/view/fchomo/node.js:1662 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:376 msgid "Size limit" msgstr "大小限制" #: htdocs/luci-static/resources/view/fchomo/client.js:1576 -#: htdocs/luci-static/resources/view/fchomo/node.js:1051 -#: htdocs/luci-static/resources/view/fchomo/node.js:1719 +#: htdocs/luci-static/resources/view/fchomo/node.js:1086 +#: htdocs/luci-static/resources/view/fchomo/node.js:1754 msgid "Skip cert verify" msgstr "跳過憑證驗證" @@ -2731,7 +2785,7 @@ msgstr "跳過嗅探目標位址" msgid "Skiped sniffing src address" msgstr "跳過嗅探來源位址" -#: htdocs/luci-static/resources/fchomo.js:192 +#: htdocs/luci-static/resources/fchomo.js:193 msgid "Snell" msgstr "" @@ -2747,7 +2801,7 @@ msgstr "嗅探器" msgid "Sniffer settings" msgstr "嗅探器設定" -#: htdocs/luci-static/resources/fchomo.js:429 +#: htdocs/luci-static/resources/fchomo.js:430 msgid "Specify a ID" msgstr "指定一個ID" @@ -2766,11 +2820,11 @@ msgstr "堆栈" msgid "Standard" msgstr "標準" -#: htdocs/luci-static/resources/fchomo.js:243 +#: htdocs/luci-static/resources/fchomo.js:244 msgid "Steam Client" msgstr "Steam 客戶端" -#: htdocs/luci-static/resources/fchomo.js:244 +#: htdocs/luci-static/resources/fchomo.js:245 msgid "Steam P2P" msgstr "" @@ -2779,7 +2833,7 @@ msgstr "" msgid "Strategy" msgstr "策略" -#: htdocs/luci-static/resources/fchomo/listeners.js:529 +#: htdocs/luci-static/resources/fchomo/listeners.js:567 #: htdocs/luci-static/resources/view/fchomo/client.js:1303 #: htdocs/luci-static/resources/view/fchomo/client.js:1312 msgid "Sub rule" @@ -2789,7 +2843,7 @@ msgstr "子規則" msgid "Sub rule group" msgstr "子規則組" -#: htdocs/luci-static/resources/fchomo.js:689 +#: htdocs/luci-static/resources/fchomo.js:690 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:223 msgid "Successfully imported %s %s of total %s." msgstr "已成功匯入 %s 個%s (共 %s 個)。" @@ -2798,12 +2852,12 @@ msgstr "已成功匯入 %s 個%s (共 %s 個)。" msgid "Successfully updated." msgstr "更新成功。" -#: htdocs/luci-static/resources/fchomo.js:1706 +#: htdocs/luci-static/resources/fchomo.js:1707 msgid "Successfully uploaded." msgstr "已成功上傳。" #: htdocs/luci-static/resources/fchomo.js:158 -#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:192 msgid "Sudoku" msgstr "" @@ -2829,15 +2883,15 @@ msgstr "系統 DNS" #: htdocs/luci-static/resources/fchomo.js:160 #: htdocs/luci-static/resources/fchomo.js:161 #: htdocs/luci-static/resources/fchomo.js:162 -#: htdocs/luci-static/resources/fchomo.js:186 -#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:187 #: htdocs/luci-static/resources/fchomo.js:192 #: htdocs/luci-static/resources/fchomo.js:193 #: htdocs/luci-static/resources/fchomo.js:194 #: htdocs/luci-static/resources/fchomo.js:195 #: htdocs/luci-static/resources/fchomo.js:196 -#: htdocs/luci-static/resources/fchomo.js:203 -#: htdocs/luci-static/resources/fchomo/listeners.js:563 +#: htdocs/luci-static/resources/fchomo.js:197 +#: htdocs/luci-static/resources/fchomo.js:204 +#: htdocs/luci-static/resources/fchomo/listeners.js:601 #: htdocs/luci-static/resources/view/fchomo/client.js:589 #: htdocs/luci-static/resources/view/fchomo/client.js:679 msgid "TCP" @@ -2847,7 +2901,7 @@ msgstr "TCP" msgid "TCP concurrency" msgstr "TCP 併發" -#: htdocs/luci-static/resources/view/fchomo/node.js:1375 +#: htdocs/luci-static/resources/view/fchomo/node.js:1410 msgid "TCP only" msgstr "僅 TCP" @@ -2865,92 +2919,94 @@ msgstr "TCP-Keep-Alive 間隔" #: htdocs/luci-static/resources/fchomo.js:157 #: htdocs/luci-static/resources/fchomo.js:165 #: htdocs/luci-static/resources/fchomo.js:166 -#: htdocs/luci-static/resources/fchomo.js:185 -#: htdocs/luci-static/resources/fchomo.js:187 +#: htdocs/luci-static/resources/fchomo.js:167 +#: htdocs/luci-static/resources/fchomo.js:186 #: htdocs/luci-static/resources/fchomo.js:188 -#: htdocs/luci-static/resources/fchomo.js:190 -#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:189 +#: htdocs/luci-static/resources/fchomo.js:191 +#: htdocs/luci-static/resources/fchomo.js:202 msgid "TCP/UDP" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1406 -#: htdocs/luci-static/resources/view/fchomo/node.js:1686 +#: htdocs/luci-static/resources/view/fchomo/node.js:1441 +#: htdocs/luci-static/resources/view/fchomo/node.js:1721 msgid "TFO" msgstr "TCP 快速開啟 (TFO)" -#: htdocs/luci-static/resources/fchomo/listeners.js:786 +#: htdocs/luci-static/resources/fchomo/listeners.js:540 +#: htdocs/luci-static/resources/fchomo/listeners.js:858 #: htdocs/luci-static/resources/view/fchomo/global.js:529 -#: htdocs/luci-static/resources/view/fchomo/node.js:464 -#: htdocs/luci-static/resources/view/fchomo/node.js:817 -#: htdocs/luci-static/resources/view/fchomo/node.js:960 +#: htdocs/luci-static/resources/view/fchomo/node.js:465 +#: htdocs/luci-static/resources/view/fchomo/node.js:818 +#: htdocs/luci-static/resources/view/fchomo/node.js:995 msgid "TLS" msgstr "TLS" -#: htdocs/luci-static/resources/fchomo/listeners.js:823 -#: htdocs/luci-static/resources/view/fchomo/node.js:991 +#: htdocs/luci-static/resources/fchomo/listeners.js:912 +#: htdocs/luci-static/resources/view/fchomo/node.js:1026 msgid "TLS ALPN" msgstr "TLS ALPN" -#: htdocs/luci-static/resources/view/fchomo/node.js:985 +#: htdocs/luci-static/resources/view/fchomo/node.js:1020 msgid "TLS SNI" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:121 -#: htdocs/luci-static/resources/view/fchomo/node.js:224 +#: htdocs/luci-static/resources/fchomo/listeners.js:122 +#: htdocs/luci-static/resources/view/fchomo/node.js:225 msgid "TLS fields" msgstr "TLS欄位" #: htdocs/luci-static/resources/fchomo.js:163 -#: htdocs/luci-static/resources/fchomo.js:199 +#: htdocs/luci-static/resources/fchomo.js:200 msgid "TUIC" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:241 +#: htdocs/luci-static/resources/fchomo.js:242 msgid "TURN" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:492 +#: htdocs/luci-static/resources/fchomo/listeners.js:523 msgid "Target address" msgstr "目標位址" -#: htdocs/luci-static/resources/fchomo/listeners.js:187 +#: htdocs/luci-static/resources/fchomo/listeners.js:188 msgid "" "Tell the client to use the BBR flow control algorithm instead of Hysteria CC." msgstr "讓客戶端使用 BBR 流控演算法。" -#: htdocs/luci-static/resources/view/fchomo/node.js:690 -#: htdocs/luci-static/resources/view/fchomo/node.js:698 +#: htdocs/luci-static/resources/view/fchomo/node.js:691 +#: htdocs/luci-static/resources/view/fchomo/node.js:699 msgid "The %s address used by local machine in the Cloudflare WARP network." msgstr "Cloudflare WARP 網路中使用的本機 %s 位址。" -#: htdocs/luci-static/resources/view/fchomo/node.js:733 -#: htdocs/luci-static/resources/view/fchomo/node.js:741 +#: htdocs/luci-static/resources/view/fchomo/node.js:734 +#: htdocs/luci-static/resources/view/fchomo/node.js:742 msgid "The %s address used by local machine in the Wireguard network." msgstr "WireGuard 網路中使用的本機 %s 位址。" -#: htdocs/luci-static/resources/fchomo/listeners.js:844 -#: htdocs/luci-static/resources/view/fchomo/node.js:1074 +#: htdocs/luci-static/resources/fchomo/listeners.js:933 +#: htdocs/luci-static/resources/view/fchomo/node.js:1109 msgid "The %s private key, in PEM format." msgstr "%s私鑰,需要 PEM 格式。" -#: htdocs/luci-static/resources/fchomo/listeners.js:829 -#: htdocs/luci-static/resources/fchomo/listeners.js:867 +#: htdocs/luci-static/resources/fchomo/listeners.js:918 +#: htdocs/luci-static/resources/fchomo/listeners.js:956 #: htdocs/luci-static/resources/view/fchomo/global.js:550 -#: htdocs/luci-static/resources/view/fchomo/node.js:1060 +#: htdocs/luci-static/resources/view/fchomo/node.js:1095 msgid "The %s public key, in PEM format." msgstr "%s公鑰,需要 PEM 格式。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1094 +#: htdocs/luci-static/resources/view/fchomo/node.js:1129 msgid "" "The ECH parameter of the HTTPS record for the domain. Leave empty to resolve " "via DNS." msgstr "網域的 HTTPS 記錄的 ECH 參數。留空則透過 DNS 解析。" -#: htdocs/luci-static/resources/view/fchomo/node.js:386 +#: htdocs/luci-static/resources/view/fchomo/node.js:387 msgid "The ED25519 available private key or UUID provided by Sudoku server." msgstr "Sudoku 伺服器提供的 ED25519 可用私鑰 或 UUID。" -#: htdocs/luci-static/resources/fchomo/listeners.js:255 +#: htdocs/luci-static/resources/fchomo/listeners.js:286 msgid "The ED25519 master public key or UUID generated by Sudoku." msgstr "Sudoku 產生的 ED25519 主公鑰 或 UUID。" @@ -2958,8 +3014,8 @@ msgstr "Sudoku 產生的 ED25519 主公鑰 或 UUID。" msgid "The default value is 2:00 every day." msgstr "預設值為每天 2:00。" -#: htdocs/luci-static/resources/fchomo/listeners.js:664 -#: htdocs/luci-static/resources/view/fchomo/node.js:941 +#: htdocs/luci-static/resources/fchomo/listeners.js:702 +#: htdocs/luci-static/resources/view/fchomo/node.js:942 msgid "" "The first padding must have a probability of 100% and at least 35 bytes." msgstr "首個填充必須為 100% 的機率並且至少 35 位元組。" @@ -2974,26 +3030,26 @@ msgstr "匹配 %s 的將被視為未被投毒汙染。" msgid "The matching %s will be deemed as poisoned." msgstr "匹配 %s 的將被視為已被投毒汙染。" -#: htdocs/luci-static/resources/fchomo/listeners.js:662 -#: htdocs/luci-static/resources/view/fchomo/node.js:939 +#: htdocs/luci-static/resources/fchomo/listeners.js:700 +#: htdocs/luci-static/resources/view/fchomo/node.js:940 msgid "The server and client can set different padding parameters." msgstr "伺服器和客戶端可以設定不同的填充參數。" -#: htdocs/luci-static/resources/fchomo/listeners.js:925 +#: htdocs/luci-static/resources/fchomo/listeners.js:1014 #: htdocs/luci-static/resources/view/fchomo/global.js:594 msgid "This ECH parameter needs to be added to the HTTPS record of the domain." msgstr "此 ECH 參數需要加入到網域的 HTTPS 記錄中。" #: htdocs/luci-static/resources/view/fchomo/client.js:1579 -#: htdocs/luci-static/resources/view/fchomo/node.js:1054 -#: htdocs/luci-static/resources/view/fchomo/node.js:1722 +#: htdocs/luci-static/resources/view/fchomo/node.js:1089 +#: htdocs/luci-static/resources/view/fchomo/node.js:1757 msgid "" "This is DANGEROUS, your traffic is almost like " "PLAIN TEXT! Use at your own risk!" msgstr "" "這是危險行為,您的流量將幾乎等同於明文!使用風險自負!" -#: htdocs/luci-static/resources/view/fchomo/node.js:536 +#: htdocs/luci-static/resources/view/fchomo/node.js:537 msgid "" "This is the TUIC port of the SUoT protocol, designed to provide a QUIC " "stream based UDP relay mode that TUIC does not provide." @@ -3025,33 +3081,33 @@ msgstr "Tproxy Fwmark/fwmask" msgid "Tproxy port" msgstr "Tproxy 連接埠" -#: htdocs/luci-static/resources/fchomo/listeners.js:243 -#: htdocs/luci-static/resources/view/fchomo/node.js:378 +#: htdocs/luci-static/resources/fchomo/listeners.js:274 +#: htdocs/luci-static/resources/view/fchomo/node.js:379 msgid "Traffic pattern" msgstr "流量模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1881 +#: htdocs/luci-static/resources/view/fchomo/node.js:1916 msgid "Transit proxy group" msgstr "中轉代理組" -#: htdocs/luci-static/resources/view/fchomo/node.js:1887 +#: htdocs/luci-static/resources/view/fchomo/node.js:1922 msgid "Transit proxy node" msgstr "中轉代理節點" -#: htdocs/luci-static/resources/fchomo/listeners.js:231 -#: htdocs/luci-static/resources/fchomo/listeners.js:976 -#: htdocs/luci-static/resources/view/fchomo/node.js:355 -#: htdocs/luci-static/resources/view/fchomo/node.js:1136 +#: htdocs/luci-static/resources/fchomo/listeners.js:262 +#: htdocs/luci-static/resources/fchomo/listeners.js:1065 +#: htdocs/luci-static/resources/view/fchomo/node.js:356 +#: htdocs/luci-static/resources/view/fchomo/node.js:1171 msgid "Transport" msgstr "傳輸層" -#: htdocs/luci-static/resources/fchomo/listeners.js:122 -#: htdocs/luci-static/resources/view/fchomo/node.js:225 +#: htdocs/luci-static/resources/fchomo/listeners.js:123 +#: htdocs/luci-static/resources/view/fchomo/node.js:226 msgid "Transport fields" msgstr "傳輸層欄位" -#: htdocs/luci-static/resources/fchomo/listeners.js:981 -#: htdocs/luci-static/resources/view/fchomo/node.js:1141 +#: htdocs/luci-static/resources/fchomo/listeners.js:1070 +#: htdocs/luci-static/resources/view/fchomo/node.js:1176 msgid "Transport type" msgstr "傳輸層類型" @@ -3060,15 +3116,19 @@ msgid "Treat the destination IP as the source IP." msgstr "將 目標 IP 視為 來源 IP。" #: htdocs/luci-static/resources/fchomo.js:161 -#: htdocs/luci-static/resources/fchomo.js:195 +#: htdocs/luci-static/resources/fchomo.js:196 msgid "Trojan" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:165 -#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:166 +#: htdocs/luci-static/resources/fchomo.js:202 msgid "TrustTunnel" msgstr "" +#: htdocs/luci-static/resources/fchomo/listeners.js:232 +msgid "Trusted proxy header" +msgstr "可信代理 Header" + #: htdocs/luci-static/resources/view/fchomo/global.js:764 msgid "Tun Fwmark/fwmask" msgstr "Tun Fwmark/fwmask" @@ -3085,35 +3145,35 @@ msgstr "Tun 設定" msgid "Tun stack." msgstr "Tun 堆栈" -#: htdocs/luci-static/resources/fchomo.js:166 +#: htdocs/luci-static/resources/fchomo.js:167 msgid "Tunnel" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:141 +#: htdocs/luci-static/resources/fchomo/listeners.js:142 #: htdocs/luci-static/resources/view/fchomo/client.js:530 #: htdocs/luci-static/resources/view/fchomo/client.js:643 #: htdocs/luci-static/resources/view/fchomo/client.js:737 #: htdocs/luci-static/resources/view/fchomo/client.js:842 #: htdocs/luci-static/resources/view/fchomo/client.js:1028 -#: htdocs/luci-static/resources/view/fchomo/node.js:238 -#: htdocs/luci-static/resources/view/fchomo/node.js:1564 -#: htdocs/luci-static/resources/view/fchomo/node.js:1852 +#: htdocs/luci-static/resources/view/fchomo/node.js:239 +#: htdocs/luci-static/resources/view/fchomo/node.js:1599 +#: htdocs/luci-static/resources/view/fchomo/node.js:1887 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:276 msgid "Type" msgstr "類型" #: htdocs/luci-static/resources/fchomo.js:163 #: htdocs/luci-static/resources/fchomo.js:164 -#: htdocs/luci-static/resources/fchomo.js:198 #: htdocs/luci-static/resources/fchomo.js:199 #: htdocs/luci-static/resources/fchomo.js:200 -#: htdocs/luci-static/resources/fchomo.js:202 -#: htdocs/luci-static/resources/fchomo/listeners.js:564 -#: htdocs/luci-static/resources/fchomo/listeners.js:569 +#: htdocs/luci-static/resources/fchomo.js:201 +#: htdocs/luci-static/resources/fchomo.js:203 +#: htdocs/luci-static/resources/fchomo/listeners.js:602 +#: htdocs/luci-static/resources/fchomo/listeners.js:607 #: htdocs/luci-static/resources/view/fchomo/client.js:588 #: htdocs/luci-static/resources/view/fchomo/client.js:678 -#: htdocs/luci-static/resources/view/fchomo/node.js:874 -#: htdocs/luci-static/resources/view/fchomo/node.js:1696 +#: htdocs/luci-static/resources/view/fchomo/node.js:875 +#: htdocs/luci-static/resources/view/fchomo/node.js:1731 msgid "UDP" msgstr "UDP" @@ -3121,42 +3181,42 @@ msgstr "UDP" msgid "UDP NAT expiration time" msgstr "UDP NAT 過期時間" -#: htdocs/luci-static/resources/view/fchomo/node.js:535 +#: htdocs/luci-static/resources/view/fchomo/node.js:536 msgid "UDP over stream" msgstr "UDP over stream" -#: htdocs/luci-static/resources/view/fchomo/node.js:541 +#: htdocs/luci-static/resources/view/fchomo/node.js:542 msgid "UDP over stream version" msgstr "UDP over stream 版本" -#: htdocs/luci-static/resources/view/fchomo/node.js:528 +#: htdocs/luci-static/resources/view/fchomo/node.js:529 msgid "UDP packet relay mode." msgstr "UDP 包中繼模式。" -#: htdocs/luci-static/resources/view/fchomo/node.js:527 +#: htdocs/luci-static/resources/view/fchomo/node.js:528 msgid "UDP relay mode" msgstr "UDP 中繼模式" -#: htdocs/luci-static/resources/fchomo/listeners.js:330 -#: htdocs/luci-static/resources/fchomo/listeners.js:331 -#: htdocs/luci-static/resources/view/fchomo/node.js:410 +#: htdocs/luci-static/resources/fchomo/listeners.js:361 +#: htdocs/luci-static/resources/fchomo/listeners.js:362 #: htdocs/luci-static/resources/view/fchomo/node.js:411 +#: htdocs/luci-static/resources/view/fchomo/node.js:412 msgid "UP: %s; DOWN: %s" msgstr "上傳: %s; 下載: %s" -#: htdocs/luci-static/resources/fchomo.js:230 +#: htdocs/luci-static/resources/fchomo.js:231 msgid "URL test" msgstr "自動選擇" -#: htdocs/luci-static/resources/fchomo/listeners.js:252 -#: htdocs/luci-static/resources/fchomo/listeners.js:413 -#: htdocs/luci-static/resources/fchomo/listeners.js:468 -#: htdocs/luci-static/resources/view/fchomo/node.js:515 -#: htdocs/luci-static/resources/view/fchomo/node.js:624 +#: htdocs/luci-static/resources/fchomo/listeners.js:283 +#: htdocs/luci-static/resources/fchomo/listeners.js:444 +#: htdocs/luci-static/resources/fchomo/listeners.js:499 +#: htdocs/luci-static/resources/view/fchomo/node.js:516 +#: htdocs/luci-static/resources/view/fchomo/node.js:625 msgid "UUID" msgstr "UUID" -#: htdocs/luci-static/resources/fchomo.js:1249 +#: htdocs/luci-static/resources/fchomo.js:1250 msgid "Unable to download unsupported type: %s" msgstr "無法下載不支援的類型: %s" @@ -3181,8 +3241,8 @@ msgstr "未知錯誤。" msgid "Unknown error: %s" msgstr "未知錯誤:%s" -#: htdocs/luci-static/resources/view/fchomo/node.js:879 -#: htdocs/luci-static/resources/view/fchomo/node.js:1701 +#: htdocs/luci-static/resources/view/fchomo/node.js:880 +#: htdocs/luci-static/resources/view/fchomo/node.js:1736 msgid "UoT" msgstr "UDP over TCP (UoT)" @@ -3190,22 +3250,22 @@ msgstr "UDP over TCP (UoT)" msgid "Update failed." msgstr "更新失敗。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1633 +#: htdocs/luci-static/resources/view/fchomo/node.js:1668 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:382 msgid "Update interval" msgstr "更新間隔" -#: htdocs/luci-static/resources/view/fchomo/node.js:1393 +#: htdocs/luci-static/resources/view/fchomo/node.js:1428 msgid "Upload bandwidth" msgstr "上傳頻寬" -#: htdocs/luci-static/resources/view/fchomo/node.js:1394 +#: htdocs/luci-static/resources/view/fchomo/node.js:1429 msgid "Upload bandwidth in Mbps." msgstr "上傳頻寬(單位:Mbps)。" -#: htdocs/luci-static/resources/fchomo/listeners.js:835 -#: htdocs/luci-static/resources/fchomo/listeners.js:875 -#: htdocs/luci-static/resources/view/fchomo/node.js:1065 +#: htdocs/luci-static/resources/fchomo/listeners.js:924 +#: htdocs/luci-static/resources/fchomo/listeners.js:964 +#: htdocs/luci-static/resources/view/fchomo/node.js:1100 msgid "Upload certificate" msgstr "上傳憑證" @@ -3213,17 +3273,17 @@ msgstr "上傳憑證" msgid "Upload initial package" msgstr "上傳初始資源包" -#: htdocs/luci-static/resources/fchomo/listeners.js:850 -#: htdocs/luci-static/resources/view/fchomo/node.js:1079 +#: htdocs/luci-static/resources/fchomo/listeners.js:939 +#: htdocs/luci-static/resources/view/fchomo/node.js:1114 msgid "Upload key" msgstr "上傳金鑰" -#: htdocs/luci-static/resources/fchomo/listeners.js:838 -#: htdocs/luci-static/resources/fchomo/listeners.js:853 -#: htdocs/luci-static/resources/fchomo/listeners.js:878 +#: htdocs/luci-static/resources/fchomo/listeners.js:927 +#: htdocs/luci-static/resources/fchomo/listeners.js:942 +#: htdocs/luci-static/resources/fchomo/listeners.js:967 #: htdocs/luci-static/resources/view/fchomo/global.js:306 -#: htdocs/luci-static/resources/view/fchomo/node.js:1068 -#: htdocs/luci-static/resources/view/fchomo/node.js:1082 +#: htdocs/luci-static/resources/view/fchomo/node.js:1103 +#: htdocs/luci-static/resources/view/fchomo/node.js:1117 msgid "Upload..." msgstr "上傳..." @@ -3247,7 +3307,7 @@ msgstr "用於解析 DNS 伺服器的網域。必須是 IP。" msgid "Used to resolve the domain of the Proxy node." msgstr "用於解析代理節點的網域。" -#: htdocs/luci-static/resources/view/fchomo/node.js:986 +#: htdocs/luci-static/resources/view/fchomo/node.js:1021 msgid "Used to verify the hostname on the returned certificates." msgstr "用於驗證傳回的憑證上的主機名稱。" @@ -3255,12 +3315,12 @@ msgstr "用於驗證傳回的憑證上的主機名稱。" msgid "User Authentication" msgstr "使用者認證" -#: htdocs/luci-static/resources/fchomo/listeners.js:238 +#: htdocs/luci-static/resources/fchomo/listeners.js:269 msgid "User-hint is mandatory" msgstr "User-hint 是必填項" -#: htdocs/luci-static/resources/fchomo/listeners.js:160 -#: htdocs/luci-static/resources/view/fchomo/node.js:256 +#: htdocs/luci-static/resources/fchomo/listeners.js:161 +#: htdocs/luci-static/resources/view/fchomo/node.js:257 msgid "Username" msgstr "使用者名稱" @@ -3268,41 +3328,41 @@ msgstr "使用者名稱" msgid "Users filter mode" msgstr "使用者過濾模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1250 +#: htdocs/luci-static/resources/view/fchomo/node.js:1285 msgid "V2ray HTTPUpgrade" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1255 +#: htdocs/luci-static/resources/view/fchomo/node.js:1290 msgid "V2ray HTTPUpgrade fast open" msgstr "" #: htdocs/luci-static/resources/fchomo.js:160 -#: htdocs/luci-static/resources/fchomo.js:194 +#: htdocs/luci-static/resources/fchomo.js:195 msgid "VLESS" msgstr "" #: htdocs/luci-static/resources/fchomo.js:159 -#: htdocs/luci-static/resources/fchomo.js:193 +#: htdocs/luci-static/resources/fchomo.js:194 msgid "VMess" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1570 -#: htdocs/luci-static/resources/view/fchomo/node.js:1858 +#: htdocs/luci-static/resources/view/fchomo/node.js:1605 +#: htdocs/luci-static/resources/view/fchomo/node.js:1893 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:319 msgid "Value" msgstr "可視化值" -#: htdocs/luci-static/resources/fchomo.js:359 +#: htdocs/luci-static/resources/fchomo.js:360 msgid "Verify if given" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:519 -#: htdocs/luci-static/resources/view/fchomo/node.js:506 -#: htdocs/luci-static/resources/view/fchomo/node.js:836 +#: htdocs/luci-static/resources/fchomo/listeners.js:557 +#: htdocs/luci-static/resources/view/fchomo/node.js:507 +#: htdocs/luci-static/resources/view/fchomo/node.js:837 msgid "Version" msgstr "版本" -#: htdocs/luci-static/resources/view/fchomo/node.js:844 +#: htdocs/luci-static/resources/view/fchomo/node.js:845 msgid "Version hint" msgstr "" @@ -3311,7 +3371,7 @@ msgstr "" msgid "Vless Encryption fields" msgstr "Vless Encryption 欄位" -#: htdocs/luci-static/resources/fchomo.js:396 +#: htdocs/luci-static/resources/fchomo.js:397 msgid "Wait a random 0-111 milliseconds with 75% probability." msgstr "以 75% 的機率等待隨機 0-111 毫秒。" @@ -3319,16 +3379,16 @@ msgstr "以 75% 的機率等待隨機 0-111 毫秒。" msgid "Warning" msgstr "警告" -#: htdocs/luci-static/resources/fchomo/listeners.js:398 -#: htdocs/luci-static/resources/fchomo/listeners.js:983 -#: htdocs/luci-static/resources/fchomo/listeners.js:992 -#: htdocs/luci-static/resources/fchomo/listeners.js:999 -#: htdocs/luci-static/resources/view/fchomo/node.js:460 -#: htdocs/luci-static/resources/view/fchomo/node.js:489 -#: htdocs/luci-static/resources/view/fchomo/node.js:1146 -#: htdocs/luci-static/resources/view/fchomo/node.js:1157 -#: htdocs/luci-static/resources/view/fchomo/node.js:1164 -#: htdocs/luci-static/resources/view/fchomo/node.js:1170 +#: htdocs/luci-static/resources/fchomo/listeners.js:429 +#: htdocs/luci-static/resources/fchomo/listeners.js:1072 +#: htdocs/luci-static/resources/fchomo/listeners.js:1081 +#: htdocs/luci-static/resources/fchomo/listeners.js:1088 +#: htdocs/luci-static/resources/view/fchomo/node.js:461 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 +#: htdocs/luci-static/resources/view/fchomo/node.js:1181 +#: htdocs/luci-static/resources/view/fchomo/node.js:1192 +#: htdocs/luci-static/resources/view/fchomo/node.js:1199 +#: htdocs/luci-static/resources/view/fchomo/node.js:1205 msgid "WebSocket" msgstr "" @@ -3340,52 +3400,52 @@ msgstr "用作服務端時,HomeProxy 是更好的選擇。" msgid "White list" msgstr "白名單" -#: htdocs/luci-static/resources/fchomo.js:202 +#: htdocs/luci-static/resources/fchomo.js:203 msgid "WireGuard" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:755 +#: htdocs/luci-static/resources/view/fchomo/node.js:756 msgid "WireGuard peer public key." msgstr "WireGuard 對端公鑰。" -#: htdocs/luci-static/resources/view/fchomo/node.js:762 +#: htdocs/luci-static/resources/view/fchomo/node.js:763 msgid "WireGuard pre-shared key." msgstr "WireGuard 預先共用金鑰。" -#: htdocs/luci-static/resources/view/fchomo/node.js:747 +#: htdocs/luci-static/resources/view/fchomo/node.js:748 msgid "WireGuard requires base64-encoded private keys." msgstr "WireGuard 要求 base64 編碼的私鑰。" -#: htdocs/luci-static/resources/fchomo/listeners.js:984 -#: htdocs/luci-static/resources/fchomo/listeners.js:993 -#: htdocs/luci-static/resources/view/fchomo/node.js:1147 -#: htdocs/luci-static/resources/view/fchomo/node.js:1165 +#: htdocs/luci-static/resources/fchomo/listeners.js:1073 +#: htdocs/luci-static/resources/fchomo/listeners.js:1082 +#: htdocs/luci-static/resources/view/fchomo/node.js:1182 +#: htdocs/luci-static/resources/view/fchomo/node.js:1200 msgid "XHTTP" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1029 -#: htdocs/luci-static/resources/view/fchomo/node.js:1260 +#: htdocs/luci-static/resources/fchomo/listeners.js:1118 +#: htdocs/luci-static/resources/view/fchomo/node.js:1295 msgid "XHTTP mode" msgstr "XHTTP 模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1291 +#: htdocs/luci-static/resources/view/fchomo/node.js:1326 msgid "XMUX" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1296 -#: htdocs/luci-static/resources/view/fchomo/node.js:1301 -#: htdocs/luci-static/resources/view/fchomo/node.js:1306 -#: htdocs/luci-static/resources/view/fchomo/node.js:1311 -#: htdocs/luci-static/resources/view/fchomo/node.js:1316 -#: htdocs/luci-static/resources/view/fchomo/node.js:1321 +#: htdocs/luci-static/resources/view/fchomo/node.js:1331 +#: htdocs/luci-static/resources/view/fchomo/node.js:1336 +#: htdocs/luci-static/resources/view/fchomo/node.js:1341 +#: htdocs/luci-static/resources/view/fchomo/node.js:1346 +#: htdocs/luci-static/resources/view/fchomo/node.js:1351 +#: htdocs/luci-static/resources/view/fchomo/node.js:1356 msgid "XMUX:" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:623 +#: htdocs/luci-static/resources/fchomo/listeners.js:661 msgid "XOR mode" msgstr "XOR 模式" -#: htdocs/luci-static/resources/view/fchomo/node.js:669 +#: htdocs/luci-static/resources/view/fchomo/node.js:670 msgid "Xudp (Xray-core)" msgstr "" @@ -3393,7 +3453,7 @@ msgstr "" msgid "Yaml text" msgstr "Yaml 格式文本" -#: htdocs/luci-static/resources/view/fchomo/node.js:1725 +#: htdocs/luci-static/resources/view/fchomo/node.js:1760 msgid "Yes" msgstr "" @@ -3401,27 +3461,27 @@ msgstr "" msgid "YouTube" msgstr "YouTube" -#: htdocs/luci-static/resources/fchomo.js:1688 +#: htdocs/luci-static/resources/fchomo.js:1689 msgid "Your %s was successfully uploaded. Size: %sB." msgstr "您的 %s 已成功上傳。大小:%sB。" -#: htdocs/luci-static/resources/fchomo.js:332 -#: htdocs/luci-static/resources/fchomo.js:345 -#: htdocs/luci-static/resources/fchomo.js:350 -#: htdocs/luci-static/resources/view/fchomo/node.js:649 +#: htdocs/luci-static/resources/fchomo.js:333 +#: htdocs/luci-static/resources/fchomo.js:346 +#: htdocs/luci-static/resources/fchomo.js:351 +#: htdocs/luci-static/resources/view/fchomo/node.js:650 msgid "aes-128-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:333 +#: htdocs/luci-static/resources/fchomo.js:334 msgid "aes-192-gcm" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:334 -#: htdocs/luci-static/resources/fchomo.js:351 +#: htdocs/luci-static/resources/fchomo.js:335 +#: htdocs/luci-static/resources/fchomo.js:352 msgid "aes-256-gcm" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:646 +#: htdocs/luci-static/resources/view/fchomo/node.js:647 msgid "auto" msgstr "自動" @@ -3429,19 +3489,19 @@ msgstr "自動" msgid "bbr" msgstr "bbr" -#: htdocs/luci-static/resources/fchomo/listeners.js:840 -#: htdocs/luci-static/resources/fchomo/listeners.js:880 -#: htdocs/luci-static/resources/view/fchomo/node.js:1070 +#: htdocs/luci-static/resources/fchomo/listeners.js:929 +#: htdocs/luci-static/resources/fchomo/listeners.js:969 +#: htdocs/luci-static/resources/view/fchomo/node.js:1105 msgid "certificate" msgstr "憑證" -#: htdocs/luci-static/resources/fchomo.js:335 -#: htdocs/luci-static/resources/fchomo.js:346 -#: htdocs/luci-static/resources/fchomo.js:352 +#: htdocs/luci-static/resources/fchomo.js:336 +#: htdocs/luci-static/resources/fchomo.js:347 +#: htdocs/luci-static/resources/fchomo.js:353 msgid "chacha20-ietf-poly1305" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:650 +#: htdocs/luci-static/resources/view/fchomo/node.js:651 msgid "chacha20-poly1305" msgstr "" @@ -3449,8 +3509,8 @@ msgstr "" msgid "cubic" msgstr "cubic" -#: htdocs/luci-static/resources/fchomo/listeners.js:575 -#: htdocs/luci-static/resources/fchomo/listeners.js:606 +#: htdocs/luci-static/resources/fchomo/listeners.js:613 +#: htdocs/luci-static/resources/fchomo/listeners.js:644 msgid "decryption" msgstr "decryption" @@ -3458,41 +3518,41 @@ msgstr "decryption" msgid "dnsmasq selects upstream on its own. (may affect CDN accuracy)" msgstr "dnsmasq 自行選擇上游服務器。 (可能影響 CDN 準確性)" -#: htdocs/luci-static/resources/view/fchomo/node.js:1713 +#: htdocs/luci-static/resources/view/fchomo/node.js:1748 msgid "down" msgstr "Hysteria 下載速率" -#: htdocs/luci-static/resources/fchomo/listeners.js:610 -#: htdocs/luci-static/resources/view/fchomo/node.js:893 -#: htdocs/luci-static/resources/view/fchomo/node.js:916 +#: htdocs/luci-static/resources/fchomo/listeners.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:894 +#: htdocs/luci-static/resources/view/fchomo/node.js:917 msgid "encryption" msgstr "encryption" -#: htdocs/luci-static/resources/fchomo/listeners.js:382 -#: htdocs/luci-static/resources/view/fchomo/node.js:444 +#: htdocs/luci-static/resources/fchomo/listeners.js:413 +#: htdocs/luci-static/resources/view/fchomo/node.js:445 msgid "false = bandwidth optimized downlink; true = pure Sudoku downlink." msgstr "false = 頻寬最佳化下行 true = 純 Sudoku 下行。" -#: htdocs/luci-static/resources/fchomo/listeners.js:982 -#: htdocs/luci-static/resources/fchomo/listeners.js:991 -#: htdocs/luci-static/resources/fchomo/listeners.js:998 -#: htdocs/luci-static/resources/view/fchomo/node.js:1145 -#: htdocs/luci-static/resources/view/fchomo/node.js:1156 -#: htdocs/luci-static/resources/view/fchomo/node.js:1163 -#: htdocs/luci-static/resources/view/fchomo/node.js:1169 +#: htdocs/luci-static/resources/fchomo/listeners.js:1071 +#: htdocs/luci-static/resources/fchomo/listeners.js:1080 +#: htdocs/luci-static/resources/fchomo/listeners.js:1087 +#: htdocs/luci-static/resources/view/fchomo/node.js:1180 +#: htdocs/luci-static/resources/view/fchomo/node.js:1191 +#: htdocs/luci-static/resources/view/fchomo/node.js:1198 +#: htdocs/luci-static/resources/view/fchomo/node.js:1204 msgid "gRPC" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1226 +#: htdocs/luci-static/resources/view/fchomo/node.js:1261 msgid "gRPC User-Agent" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1231 +#: htdocs/luci-static/resources/view/fchomo/node.js:1266 msgid "gRPC ping interval" msgstr "gRPC ping 間隔" -#: htdocs/luci-static/resources/fchomo/listeners.js:1023 -#: htdocs/luci-static/resources/view/fchomo/node.js:1222 +#: htdocs/luci-static/resources/fchomo/listeners.js:1112 +#: htdocs/luci-static/resources/view/fchomo/node.js:1257 msgid "gRPC service name" msgstr "gRPC 服務名稱" @@ -3500,11 +3560,11 @@ msgstr "gRPC 服務名稱" msgid "gVisor" msgstr "gVisor" -#: htdocs/luci-static/resources/view/fchomo/node.js:1338 +#: htdocs/luci-static/resources/view/fchomo/node.js:1373 msgid "h2mux" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:775 +#: htdocs/luci-static/resources/fchomo/listeners.js:813 msgid "least one keypair required" msgstr "至少需要一對密鑰" @@ -3518,17 +3578,17 @@ msgstr "metacubexd" #: htdocs/luci-static/resources/view/fchomo/client.js:1480 #: htdocs/luci-static/resources/view/fchomo/client.js:1711 #: htdocs/luci-static/resources/view/fchomo/client.js:1767 -#: htdocs/luci-static/resources/view/fchomo/node.js:1536 +#: htdocs/luci-static/resources/view/fchomo/node.js:1571 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:239 msgid "mihomo config" msgstr "mihomo 配置" -#: htdocs/luci-static/resources/fchomo.js:378 +#: htdocs/luci-static/resources/fchomo.js:379 msgid "mlkem768x25519plus" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1410 -#: htdocs/luci-static/resources/view/fchomo/node.js:1691 +#: htdocs/luci-static/resources/view/fchomo/node.js:1445 +#: htdocs/luci-static/resources/view/fchomo/node.js:1726 msgid "mpTCP" msgstr "多路徑 TCP (mpTCP)" @@ -3540,20 +3600,20 @@ msgstr "new_reno" msgid "no-resolve" msgstr "no-resolve" -#: htdocs/luci-static/resources/fchomo.js:1423 -#: htdocs/luci-static/resources/fchomo.js:1518 -#: htdocs/luci-static/resources/fchomo.js:1553 -#: htdocs/luci-static/resources/fchomo.js:1581 +#: htdocs/luci-static/resources/fchomo.js:1424 +#: htdocs/luci-static/resources/fchomo.js:1519 +#: htdocs/luci-static/resources/fchomo.js:1554 +#: htdocs/luci-static/resources/fchomo.js:1582 msgid "non-empty value" msgstr "非空值" -#: htdocs/luci-static/resources/fchomo.js:330 -#: htdocs/luci-static/resources/fchomo.js:344 -#: htdocs/luci-static/resources/fchomo.js:356 -#: htdocs/luci-static/resources/fchomo/listeners.js:500 -#: htdocs/luci-static/resources/view/fchomo/node.js:647 -#: htdocs/luci-static/resources/view/fchomo/node.js:667 -#: htdocs/luci-static/resources/view/fchomo/node.js:805 +#: htdocs/luci-static/resources/fchomo.js:331 +#: htdocs/luci-static/resources/fchomo.js:345 +#: htdocs/luci-static/resources/fchomo.js:357 +#: htdocs/luci-static/resources/fchomo/listeners.js:531 +#: htdocs/luci-static/resources/view/fchomo/node.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:668 +#: htdocs/luci-static/resources/view/fchomo/node.js:806 #: htdocs/luci-static/resources/view/fchomo/ruleset.js:315 msgid "none" msgstr "無" @@ -3566,44 +3626,45 @@ msgstr "未找到" msgid "not included \",\"" msgstr "不包含 \",\"" -#: htdocs/luci-static/resources/fchomo.js:216 -#: htdocs/luci-static/resources/fchomo/listeners.js:531 -#: htdocs/luci-static/resources/fchomo/listeners.js:532 +#: htdocs/luci-static/resources/fchomo.js:217 +#: htdocs/luci-static/resources/fchomo/listeners.js:569 +#: htdocs/luci-static/resources/fchomo/listeners.js:570 msgid "null" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:806 +#: htdocs/luci-static/resources/fchomo/listeners.js:532 +#: htdocs/luci-static/resources/view/fchomo/node.js:807 msgid "obfs-simple" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "only applies when %s is %s." msgstr "僅當 %s 為 %s 時適用。" -#: htdocs/luci-static/resources/view/fchomo/node.js:489 +#: htdocs/luci-static/resources/view/fchomo/node.js:490 msgid "only applies when %s is not %s." msgstr "僅當 %s 不為 %s 時適用。" -#: htdocs/luci-static/resources/view/fchomo/node.js:1671 +#: htdocs/luci-static/resources/view/fchomo/node.js:1706 msgid "override.proxy-name" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:668 +#: htdocs/luci-static/resources/view/fchomo/node.js:669 msgid "packet addr (v2ray-core v5+)" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1033 -#: htdocs/luci-static/resources/view/fchomo/node.js:1264 +#: htdocs/luci-static/resources/fchomo/listeners.js:1122 +#: htdocs/luci-static/resources/view/fchomo/node.js:1299 msgid "packet-up" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:396 -#: htdocs/luci-static/resources/view/fchomo/node.js:458 +#: htdocs/luci-static/resources/fchomo/listeners.js:427 +#: htdocs/luci-static/resources/view/fchomo/node.js:459 msgid "poll" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:855 -#: htdocs/luci-static/resources/view/fchomo/node.js:1084 +#: htdocs/luci-static/resources/fchomo/listeners.js:944 +#: htdocs/luci-static/resources/view/fchomo/node.js:1119 msgid "private key" msgstr "私鑰" @@ -3616,7 +3677,7 @@ msgstr "razord-meta" msgid "requires front-end adaptation using the API." msgstr "需要使用 API 的前端適配。" -#: htdocs/luci-static/resources/view/fchomo/node.js:810 +#: htdocs/luci-static/resources/view/fchomo/node.js:811 msgid "restls" msgstr "" @@ -3624,17 +3685,17 @@ msgstr "" msgid "rule-set" msgstr "規則集" -#: htdocs/luci-static/resources/fchomo/listeners.js:501 -#: htdocs/luci-static/resources/view/fchomo/node.js:809 +#: htdocs/luci-static/resources/fchomo/listeners.js:533 +#: htdocs/luci-static/resources/view/fchomo/node.js:810 msgid "shadow-tls" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:1336 +#: htdocs/luci-static/resources/view/fchomo/node.js:1371 msgid "smux" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:395 -#: htdocs/luci-static/resources/view/fchomo/node.js:457 +#: htdocs/luci-static/resources/fchomo/listeners.js:426 +#: htdocs/luci-static/resources/view/fchomo/node.js:458 msgid "split-stream" msgstr "" @@ -3642,25 +3703,25 @@ msgstr "" msgid "src" msgstr "src" -#: htdocs/luci-static/resources/fchomo/listeners.js:1031 -#: htdocs/luci-static/resources/view/fchomo/node.js:1262 +#: htdocs/luci-static/resources/fchomo/listeners.js:1120 +#: htdocs/luci-static/resources/view/fchomo/node.js:1297 msgid "stream-one" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1032 -#: htdocs/luci-static/resources/view/fchomo/node.js:1263 +#: htdocs/luci-static/resources/fchomo/listeners.js:1121 +#: htdocs/luci-static/resources/view/fchomo/node.js:1298 msgid "stream-up" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:1048 +#: htdocs/luci-static/resources/fchomo/listeners.js:1137 msgid "stream-up server seconds" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:491 +#: htdocs/luci-static/resources/view/fchomo/node.js:492 msgid "stream/poll/auto" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:251 +#: htdocs/luci-static/resources/fchomo/listeners.js:282 msgid "sudoku-keypair" msgstr "" @@ -3668,87 +3729,87 @@ msgstr "" msgid "unchecked" msgstr "未檢查" -#: htdocs/luci-static/resources/fchomo.js:442 +#: htdocs/luci-static/resources/fchomo.js:443 msgid "unique UCI identifier" msgstr "獨立 UCI 識別" -#: htdocs/luci-static/resources/fchomo.js:445 +#: htdocs/luci-static/resources/fchomo.js:446 msgid "unique identifier" msgstr "獨立標識" -#: htdocs/luci-static/resources/fchomo.js:1590 +#: htdocs/luci-static/resources/fchomo.js:1591 msgid "unique value" msgstr "獨立值" -#: htdocs/luci-static/resources/view/fchomo/node.js:1707 +#: htdocs/luci-static/resources/view/fchomo/node.js:1742 msgid "up" msgstr "Hysteria 上傳速率" -#: htdocs/luci-static/resources/fchomo/listeners.js:520 -#: htdocs/luci-static/resources/view/fchomo/node.js:507 -#: htdocs/luci-static/resources/view/fchomo/node.js:542 -#: htdocs/luci-static/resources/view/fchomo/node.js:837 -#: htdocs/luci-static/resources/view/fchomo/node.js:886 +#: htdocs/luci-static/resources/fchomo/listeners.js:558 +#: htdocs/luci-static/resources/view/fchomo/node.js:508 +#: htdocs/luci-static/resources/view/fchomo/node.js:543 +#: htdocs/luci-static/resources/view/fchomo/node.js:838 +#: htdocs/luci-static/resources/view/fchomo/node.js:887 msgid "v1" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:521 -#: htdocs/luci-static/resources/view/fchomo/node.js:508 -#: htdocs/luci-static/resources/view/fchomo/node.js:838 -#: htdocs/luci-static/resources/view/fchomo/node.js:887 +#: htdocs/luci-static/resources/fchomo/listeners.js:559 +#: htdocs/luci-static/resources/view/fchomo/node.js:509 +#: htdocs/luci-static/resources/view/fchomo/node.js:839 +#: htdocs/luci-static/resources/view/fchomo/node.js:888 msgid "v2" msgstr "" -#: htdocs/luci-static/resources/fchomo/listeners.js:522 -#: htdocs/luci-static/resources/view/fchomo/node.js:509 -#: htdocs/luci-static/resources/view/fchomo/node.js:839 +#: htdocs/luci-static/resources/fchomo/listeners.js:560 +#: htdocs/luci-static/resources/view/fchomo/node.js:510 +#: htdocs/luci-static/resources/view/fchomo/node.js:840 msgid "v3" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1470 -#: htdocs/luci-static/resources/fchomo.js:1473 +#: htdocs/luci-static/resources/fchomo.js:1471 +#: htdocs/luci-static/resources/fchomo.js:1474 msgid "valid JSON format" msgstr "有效的 JSON 格式" -#: htdocs/luci-static/resources/view/fchomo/node.js:1044 +#: htdocs/luci-static/resources/view/fchomo/node.js:1079 msgid "valid SHA256 string with %d characters" msgstr "包含 %d 個字元的有效 SHA256 字串" -#: htdocs/luci-static/resources/fchomo.js:1495 -#: htdocs/luci-static/resources/fchomo.js:1498 +#: htdocs/luci-static/resources/fchomo.js:1496 +#: htdocs/luci-static/resources/fchomo.js:1499 msgid "valid URL" msgstr "有效網址" -#: htdocs/luci-static/resources/fchomo.js:1508 +#: htdocs/luci-static/resources/fchomo.js:1509 msgid "valid base64 key with %d characters" msgstr "包含 %d 個字元的有效 base64 金鑰" -#: htdocs/luci-static/resources/fchomo.js:1568 -#: htdocs/luci-static/resources/fchomo.js:1574 +#: htdocs/luci-static/resources/fchomo.js:1569 +#: htdocs/luci-static/resources/fchomo.js:1575 msgid "valid format: 2x, 2p, 4v" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1555 +#: htdocs/luci-static/resources/fchomo.js:1556 msgid "valid key length with %d characters" msgstr "包含 %d 個字元的有效金鑰" -#: htdocs/luci-static/resources/fchomo.js:1433 +#: htdocs/luci-static/resources/fchomo.js:1434 msgid "valid port value" msgstr "有效連接埠值" -#: htdocs/luci-static/resources/fchomo.js:1483 +#: htdocs/luci-static/resources/fchomo.js:1484 msgid "valid uuid" msgstr "有效 uuid" -#: htdocs/luci-static/resources/fchomo.js:402 +#: htdocs/luci-static/resources/fchomo.js:403 msgid "vless-mlkem768" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:401 +#: htdocs/luci-static/resources/fchomo.js:402 msgid "vless-x25519" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:336 +#: htdocs/luci-static/resources/fchomo.js:337 msgid "xchacha20-ietf-poly1305" msgstr "" @@ -3756,7 +3817,7 @@ msgstr "" msgid "yacd-meta" msgstr "yacd-meta" -#: htdocs/luci-static/resources/view/fchomo/node.js:1337 +#: htdocs/luci-static/resources/view/fchomo/node.js:1372 msgid "yamux" msgstr "" @@ -3764,11 +3825,11 @@ msgstr "" msgid "zashboard" msgstr "" -#: htdocs/luci-static/resources/view/fchomo/node.js:648 +#: htdocs/luci-static/resources/view/fchomo/node.js:649 msgid "zero" msgstr "" -#: htdocs/luci-static/resources/fchomo.js:1251 +#: htdocs/luci-static/resources/fchomo.js:1252 msgid "🡇" msgstr "" diff --git a/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc b/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc index 5408bd87..4cba4232 100644 --- a/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc +++ b/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc @@ -511,6 +511,20 @@ uci.foreach(uciconf, ucinode, (cfg) => { down: cfg.hysteria_down_mbps ? cfg.hysteria_down_mbps + ' Mbps' : null, obfs: cfg.hysteria_obfs_type, "obfs-password": cfg.hysteria_obfs_password, + "realm-opts": cfg.hysteria2_realm === '1' ? { + enable: true, + "server-url": cfg.hysteria2_realm_server_url, + token: cfg.hysteria2_realm_token, + "realm-id": cfg.hysteria2_realm_id, + "stun-servers": cfg.hysteria2_realm_stun_servers, + // @TLS of server-url + //sni, + //alpn, + //"skip-cert-verify", + //fingerprint, + //certificate, + //"private-key" + } : null, /* SSH */ "private-key-passphrase": cfg.ssh_priv_key_passphrase, @@ -680,6 +694,7 @@ uci.foreach(uciconf, ucinode, (cfg) => { "h-max-request-times": cfg.transport_xhttp_xmux_max_request_times, "h-max-reusable-secs": cfg.transport_xhttp_xmux_max_reusable_secs, "h-keep-alive-period": strToInt(cfg.transport_xhttp_xmux_keep_alive_period) + // @download-settings } : null } : null } : {}), diff --git a/luci-app-fchomo/root/usr/share/ucode/fchomo.uc b/luci-app-fchomo/root/usr/share/ucode/fchomo.uc index 23beed85..3bc690a9 100644 --- a/luci-app-fchomo/root/usr/share/ucode/fchomo.uc +++ b/luci-app-fchomo/root/usr/share/ucode/fchomo.uc @@ -251,6 +251,27 @@ export function parseListener(cfg, isClient, label) { obfs: cfg.hysteria_obfs_type, "obfs-password": cfg.hysteria_obfs_password, masquerade: cfg.hysteria_masquerade, + "realm-opts": cfg.hysteria2_realm === '1' ? { + enable: true, + "server-url": cfg.hysteria2_realm_server_url, + token: cfg.hysteria2_realm_token, + "realm-id": cfg.hysteria2_realm_id, + "stun-servers": cfg.hysteria2_realm_stun_servers, + // @TLS of server-url + //sni, + //alpn, + //"skip-cert-verify", + //fingerprint, + //certificate, + //"private-key" + } : null, + + /* Hysteria2 Realmserver */ + token: cfg.hysteria2_realmserver_token, + "max-realms": strToInt(cfg.hysteria2_realmserver_max_realms), + "max-realms-per-ip": strToInt(cfg.hysteria2_realmserver_max_realms_per_ip), + "trusted-proxy-header": cfg.hysteria2_realmserver_trusted_proxy_header, + "realm-name-pattern": cfg.hysteria2_realmserver_realm_name_pattern, /* Shadowsocks */ cipher: cfg.shadowsocks_chipher, @@ -302,6 +323,11 @@ export function parseListener(cfg, isClient, label) { /* Plugin fields */ ...(cfg.plugin ? { + // obfs-simple + "simple-obfs": cfg.plugin === 'obfs' ? { + enable: true, + mode: cfg.plugin_opts_obfsmode + } : null, // shadow-tls "shadow-tls": cfg.plugin === 'shadow-tls' ? { enable: true, @@ -357,6 +383,7 @@ export function parseListener(cfg, isClient, label) { "sc-max-buffered-posts": strToInt(cfg.transport_xhttp_sc_max_buffered_posts) || null, "sc-stream-up-server-secs": cfg.transport_xhttp_sc_stream_up_server_secs, "sc-max-each-post-bytes": strToInt(cfg.transport_xhttp_sc_max_each_post_bytes) || null, + // @其他的配置 } : null } : {}) } diff --git a/luci-app-modeminfo/Makefile b/luci-app-modeminfo/Makefile index f9ac6368..7daea3a1 100644 --- a/luci-app-modeminfo/Makefile +++ b/luci-app-modeminfo/Makefile @@ -3,8 +3,8 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Information dashboard for 3G/LTE dongle LUCI_DEPENDS:=+modeminfo PKG_LICENSE:=GPLv3 -PKG_VERSION:=0.4.6 -PKG_RELEASE:=2 +PKG_VERSION:=0.4.7 +PKG_RELEASE:=3 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-modeminfo/htdocs/luci-static/resources/modem-indicator.js b/luci-app-modeminfo/htdocs/luci-static/resources/modem-indicator.js new file mode 100644 index 00000000..043930e7 --- /dev/null +++ b/luci-app-modeminfo/htdocs/luci-static/resources/modem-indicator.js @@ -0,0 +1,115 @@ +'use strict'; +'require ui'; +'require poll'; +'require fs'; +'require uci'; + +function getSignalColor(percent) { + if (percent === null || percent === undefined || percent < 5) { + return '#000000'; + } + + let p = percent; + + if (p >= 80) return '#00cc00'; + + if (p >= 67) { + const ratio = (p - 50) / 30; + const r = Math.floor(255 * (1 - ratio)); + const g = 255; + return `rgb(${r}, ${g}, 0)`; + } + + if (p >= 35) { + const ratio = (p - 25) / 25; + const r = 255; + const g = Math.floor(165 + (90 * ratio)); + return `rgb(${r}, ${g}, 0)`; + } + + const ratio = (p - 5) / 20; + const r = 255; + const g = Math.floor(165 * ratio); + return `rgb(${r}, ${g}, 0)`; +} + + +function getSignalState(percent) { + const p = percent || 0; + if (p < 10) return 'error'; + if (p < 25) return 'warning'; + if (p < 50) return 'warning'; + return 'active'; +} + +function isUciIndexTwo() { + return L.resolveDefault(fs.exec_direct('/sbin/uci', ['get', 'modeminfo.@general[0].index']), '') + .then(function(value) { + return value.trim() === '2'; + }) + .catch(function() { + return false; + }); +} + +function updateIndicator() { + + + + isUciIndexTwo().then(function(ok) { + if (!ok) { + ui.hideIndicator('modem-status'); + return; + } + + if (window.location.pathname.includes('/cgi-bin/luci/admin/modem/main')) { + ui.hideIndicator('modem-status'); + return; + } + L.resolveDefault(fs.exec_direct('/usr/bin/modeminfo'), '{"modem":[]}') + .then(function(res) { + var data = JSON.parse(res); + if (!data.modem || !data.modem.length) { + ui.hideIndicator('modem-status'); + return; + } + + var parts = data.modem.map(function(modem) { + var percent = parseInt(modem.csq_per); + var cops = modem.cops || ''; + var mode = modem.mode + (parseInt(modem.lteca) > 0 ? '+' : ''); + return { mode: mode, cops: cops, percent: percent }; + }); + + var minPercent = Math.min.apply(null, parts.map(function(p) { return p.percent; })); + var state = getSignalState(minPercent); + + var status = parts.map(function(p) { + return p.mode + ' ' + p.cops; + }).join(' | '); + + ui.showIndicator('modem-status', status, null, state); + + var indicator = document.querySelector('[data-indicator="modem-status"]'); + if (indicator) { + var html = parts.map(function(p) { + var color = getSignalColor(p.percent); + return ' ' + p.mode + ' ' + p.cops; + }).join(' | '); + indicator.innerHTML = html; + } + }) + .catch(function() { + ui.hideIndicator('modem-status'); + }); + }); +} + +setTimeout(function() { + updateIndicator(); + poll.add(updateIndicator, 10); +}, 500); + +return L.Class.extend({ + __name__: 'ModemIndicator' +}); diff --git a/luci-app-modeminfo/htdocs/luci-static/resources/preload/modem-indicator.js b/luci-app-modeminfo/htdocs/luci-static/resources/preload/modem-indicator.js new file mode 100644 index 00000000..48b3febd --- /dev/null +++ b/luci-app-modeminfo/htdocs/luci-static/resources/preload/modem-indicator.js @@ -0,0 +1,6 @@ +'use strict'; +'require modem-indicator'; + +return L.Class.extend({ + __name__: 'preload.modem-indicator' +}); diff --git a/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/setup.js b/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/setup.js index f5077f0d..6ccf3e93 100644 --- a/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/setup.js +++ b/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/setup.js @@ -60,7 +60,7 @@ var qdesc = _('Select qmi port.'); var lacdec = _('Show LAC and CID in decimal.'); var mmdesc = _('Get device hardware name via mmcli utility if aviable.'); var qmidesc = _('Set qmi mode.'); -var idesc = _('Short info on Overview page'); +var idesc = _('Show short info.
Overview: show info on main page \"Cellular Network\" section
MenuBar: show info on menubar all pages
NOTICE: Don\'t add too many modems in menubar, it may break the theme display.'); var portplace = _('Please select a port'); return view.extend({ @@ -88,8 +88,12 @@ return view.extend({ s = m.section(form.TypedSection, 'general', _('General option'), null); s.anonymous = true; - o = s.option(form.Flag, 'index', _('Index page'), idesc); - s.anonymous = true; + o = s.option(form.ListValue, 'index', _('Short info'), idesc); + o.widget="radio"; + o.value(0,_('none')); + o.value(1,_('overview')); + o.value(2,_('menubar')); + o.default = '0'; o.rmempty = true; o = s.option(form.Flag, 'decimail', _('Show decimal'), lacdec); diff --git a/luci-app-modeminfo/htdocs/luci-static/resources/view/status/include/26_modeminfo.js b/luci-app-modeminfo/htdocs/luci-static/resources/view/status/include/26_modeminfo.js index c39480a9..b0bcee8d 100644 --- a/luci-app-modeminfo/htdocs/luci-static/resources/view/status/include/26_modeminfo.js +++ b/luci-app-modeminfo/htdocs/luci-static/resources/view/status/include/26_modeminfo.js @@ -19,7 +19,11 @@ return baseclass.extend({ title: _('Cellular network'), load: async function() { - uci.load('modeminfo'); + await uci.load('modeminfo'); + var index = uci.sections('modeminfo', 'general'); + if (!index || !index[0] || index[0].index !== "1") { + return null; + }; return new Promise((resolve, reject) => { const timeout = setTimeout(() => { @@ -43,10 +47,15 @@ return baseclass.extend({ render: function(data){ if (!data || data.trim() === '') { - return E('div', { - 'class': 'cbi-section', - 'style': 'color: #999; text-align: center;' - }, _('Wait devices information')); + var index = uci.sections('modeminfo', 'general'); + if (!index || !index[0] || index[0].index !== "1") { + return null; + } else { + return E('div', { + 'class': 'cbi-section', + 'style': 'color: #999; text-align: center;' + }, _('Wait devices information')); + } } try { diff --git a/luci-app-modeminfo/po/ru/modeminfo.po b/luci-app-modeminfo/po/ru/modeminfo.po index 08afc781..385d69a4 100644 --- a/luci-app-modeminfo/po/ru/modeminfo.po +++ b/luci-app-modeminfo/po/ru/modeminfo.po @@ -132,11 +132,23 @@ msgstr "Только QMI" msgid "QMI over MBIM" msgstr "QMI через MBIM" -msgid "Index page" -msgstr "На главную" +msgid "Short info" +msgstr "Краткая информация" -msgid "Short info on Overview page" -msgstr "Краткая информация о сети на главной странице" +msgid "Show short info.
Overview: show info on main page \"Cellular Network\" section
MenuBar: show info on menubar all pages
NOTICE: Don\'t add too many modems in menubar, it may break the theme display." +msgstr "Показвать краткую информацию
На главной: показывать главной странице раздел \"Сотовая сеть\"
Меню: показывать в строке меню на всех страницах
ВНИМАНИЕ: не добавляйте слишком много устройств в строку меню, это может сломать отображение." + +msgid "none" +msgstr "не отображать" + +msgid "overview" +msgid "на главной" + +msgid "menubar" +msgstr "в строке меню" + +msgid "Wait devices information" +msgstr "Ожидаются данные устройств" msgid "sec" msgstr "сек" diff --git a/luci-app-modeminfo/root/usr/share/rpcd/acl.d/luci-app-modeminfo.json b/luci-app-modeminfo/root/usr/share/rpcd/acl.d/luci-app-modeminfo.json index becd7583..8a2723f8 100644 --- a/luci-app-modeminfo/root/usr/share/rpcd/acl.d/luci-app-modeminfo.json +++ b/luci-app-modeminfo/root/usr/share/rpcd/acl.d/luci-app-modeminfo.json @@ -8,7 +8,8 @@ }, "file": { "/usr/bin/modeminfo": [ "exec" ], - "/usr/share/modeminfo/scripts/rmtmp": [ "exec" ] + "/usr/share/modeminfo/scripts/rmtmp": [ "exec" ], + "/sbin/uci": [ "exec" ] }, "uci": [ "modeminfo" ] }, diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index f8dab539..ea571836 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=26.5.11 -PKG_RELEASE:=126 +PKG_RELEASE:=127 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ @@ -18,8 +18,6 @@ PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \ - CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client \ - CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Server \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \ @@ -43,9 +41,6 @@ LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \ +PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy:haproxy \ +PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria:hysteria \ +PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-local \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-redir \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server:shadowsocks-libev-ss-server \ +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client:shadowsocks-rust-sslocal \ +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Server:shadowsocks-rust-ssserver \ +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-local \ @@ -106,14 +101,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy select PACKAGE_naiveproxy default n -config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client - bool "Include Shadowsocks Libev Client" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server - bool "Include Shadowsocks Libev Server" - default y if aarch64||arm||i386||x86_64 - config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client bool "Include Shadowsocks Rust Client" depends on !i386 diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua index 63ff804d..481477aa 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua @@ -1,7 +1,6 @@ local api = require "luci.passwall.api" local uci = api.uci local appname = "passwall" -local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_singbox = api.finded_com("sing-box") local has_xray = api.finded_com("xray") @@ -12,10 +11,6 @@ local vmess_type = {} local vless_type = {} local hysteria2_type = {} local xray_version = api.get_app_version("xray") -if has_ss then - local s = "shadowsocks-libev" - table.insert(ss_type, s) -end if has_ss_rust then local s = "shadowsocks-rust" table.insert(ss_type, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua index 3cbaf4cf..80f4a4ef 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua @@ -16,7 +16,6 @@ end m:append(Template(appname .. "/cbi/nodes_listvalue_com")) -local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_singbox = api.finded_com("sing-box") local has_xray = api.finded_com("xray") @@ -27,10 +26,6 @@ local vmess_type = {} local vless_type = {} local hysteria2_type = {} local xray_version = api.get_app_version("xray") -if has_ss then - local s = "shadowsocks-libev" - table.insert(ss_type, s) -end if has_ss_rust then local s = "shadowsocks-rust" table.insert(ss_type, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua index 1ee689e7..e1afc603 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua @@ -262,6 +262,13 @@ if load_balancing_options then -- [[ Load balancing Start ]] 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.datatype = "uinteger" + o.default = "10" + o.placeholder = "10" + o.description = translate("The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate.") end -- [[ 负载均衡 End ]] if load_iface_options then -- [[ 自定义接口 Start ]] diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua index 712b68ab..2f8cade7 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua @@ -43,6 +43,8 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'") +local singbox_version = api.get_app_version("sing-box"):match("[^v]+") + o = s:option(ListValue, _n("protocol"), translate("Protocol")) o:value("socks", "Socks") o:value("http", "HTTP") @@ -351,13 +353,28 @@ end if singbox_tags:find("with_quic") then o = s:option(Value, _n("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" }) + o:depends({ [_n("protocol")] = "hysteria2", [_n("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.datatype = "or(uinteger,portrange)" o.placeholder = "30" o.default = "30" - o:depends({ [_n("protocol")] = "hysteria2" }) + o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) + + o = s:option(Flag, _n("hysteria2_realms"), translate("Realms")) + o.default = "0" + if api.compare_versions(singbox_version, ">=", "1.14.0") then + o:depends({ [_n("protocol")] = "hysteria2"}) + else + o:depends({ [_n("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(DynamicList, _n("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 = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o.password = true @@ -479,7 +496,7 @@ 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" }) +o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) o:depends({ [_n("protocol")] = "naive" }) o = s:option(TextValue, _n("ech_config"), translate("ECH Config")) @@ -787,10 +804,14 @@ local protocols = s.fields[_n("protocol")].keylist if #protocols > 0 then for i, v in ipairs(protocols) do if not v:find("^_") then - s.fields[_n("address")]:depends({ [_n("protocol")] = v }) - s.fields[_n("port")]:depends({ [_n("protocol")] = v }) - s.fields[_n("domain_resolver")]:depends({ [_n("protocol")] = v }) - s.fields[_n("domain_strategy")]:depends({ [_n("protocol")] = v }) + local depends_condition = { [_n("protocol")] = v } + if v == "hysteria2" then + depends_condition[_n("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) end end end @@ -805,6 +826,7 @@ if not load_shunt_options then o:value("1", translate("Preproxy Node")) end o:value("2", translate("Landing Node")) + o:depends({ [_n("hysteria2_realms")] = false }) o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy.")) o1:depends({ [_n("chain_proxy")] = "1" }) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ss.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ss.lua deleted file mode 100644 index 5be6a281..00000000 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ss.lua +++ /dev/null @@ -1,66 +0,0 @@ -local m, s = ... - -if not api.is_finded("ss-local") and not api.is_finded("ss-redir") then - return -end - -type_name = "SS" - --- [[ Shadowsocks Libev ]] - -s.fields["type"]:value(type_name, "Shadowsocks Libev") - -if s.val["type"] ~= type_name then - return -end - -local option_prefix = "ss_" - -local function _n(name) - return option_prefix .. name -end - -local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "salsa20", "chacha20", "chacha20-ietf", - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" -} - -o = s:option(ListValue, _n("del_protocol")) --始终隐藏,用于删除 protocol -o:depends({ [_n("__hide")] = "1" }) -o.rewrite_option = "protocol" - -o = s:option(Value, _n("address"), translate("Address (Support Domain Name)")) - -o = s:option(Value, _n("port"), translate("Port")) -o.datatype = "port" - -o = s:option(Value, _n("password"), translate("Password")) -o.password = true - -o = s:option(Value, _n("method"), translate("Encrypt Method")) -for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end - -o = s:option(Value, _n("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.default = 0 - -o = s:option(Flag, _n("plugin_enabled"), translate("plugin")) -o.default = 0 - -o = s:option(ListValue, _n("plugin"), "SIP003 " .. translate("plugin")) -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 -o:depends({ [_n("plugin_enabled")] = true }) - -o = s:option(Value, _n("plugin_opts"), translate("opts")) -o:depends({ [_n("plugin_enabled")] = true }) - -api.luci_types(arg[1], m, s, type_name, option_prefix) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/hysteria2.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/hysteria2.lua index 89135cd6..d015a8af 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/hysteria2.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/hysteria2.lua @@ -24,6 +24,7 @@ o = s:option(Flag, _n("custom"), translate("Use Custom Config")) o = s:option(Value, _n("port"), translate("Listen Port")) o.datatype = "port" +o.rmempty = false o:depends({ [_n("custom")] = false }) o = s:option(Flag, _n("realms"), translate("Realms")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/sing-box.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/sing-box.lua index d018f625..5fafd25b 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/sing-box.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/sing-box.lua @@ -55,6 +55,7 @@ o:depends({ [_n("custom")] = false }) o = s:option(Value, _n("port"), translate("Listen Port")) o.datatype = "port" +o.rmempty = false o:depends({ [_n("custom")] = false }) o = s:option(Flag, _n("auth"), translate("Auth")) @@ -154,6 +155,17 @@ if singbox_tags:find("with_quic") then end if singbox_tags:find("with_quic") then + o = s:option(Flag, _n("hysteria2_realms"), translate("Realms")) + o.default = "0" + o:depends({ [_n("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(DynamicList, _n("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 = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o.password = true o:depends({ [_n("protocol")] = "hysteria2"}) @@ -321,7 +333,7 @@ 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" }) +o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) o = s:option(TextValue, _n("ech_key"), translate("ECH Key")) o.default = "" diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ss.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ss.lua deleted file mode 100644 index f8a2b58b..00000000 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ss.lua +++ /dev/null @@ -1,78 +0,0 @@ -local m, s = ... - -local api = require "luci.passwall.api" - -if not api.is_finded("ss-server") then - return -end - -local type_name = "SS" - -local option_prefix = "ss_" - -local function _n(name) - return option_prefix .. name -end - -local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", - "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", - "chacha20-ietf", -- aead - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" -} - --- [[ Shadowsocks ]] - -s.fields["type"]:value(type_name, translate("Shadowsocks")) - -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(Value, _n("password"), translate("Password")) -o.password = true -o:depends({ [_n("custom")] = false }) - -o = s:option(ListValue, _n("method"), translate("Encrypt Method")) -for a, t in ipairs(ss_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")) -o.rows = 10 -o.wrap = "off" -o:depends({ [_n("custom")] = true }) -o.validate = function(self, value, t) - if value and api.jsonc.parse(value) then - return value - else - return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!") - end -end -o.custom_cfgvalue = function(self, section, value) - local config_str = m:get(section, "config_str") - if config_str then - return api.base64Decode(config_str) - end -end -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.default = "1" -o.rmempty = false - -api.luci_types(arg[1], m, s, type_name, option_prefix) diff --git a/luci-app-passwall/luasrc/passwall/api.lua b/luci-app-passwall/luasrc/passwall/api.lua index c4d84bd1..a4e1cb6b 100644 --- a/luci-app-passwall/luasrc/passwall/api.lua +++ b/luci-app-passwall/luasrc/passwall/api.lua @@ -472,9 +472,10 @@ function get_valid_nodes() end end local port = e.port or e.hysteria_hop or e.hysteria2_hop - if (port and e.address) or e.hysteria2_realms then + local is_realm = (e.type == "Hysteria2" or e.protocol == 'hysteria2') and e.hysteria2_realms or nil + if (port and e.address) or is_realm then local address = e.address - if is_ip(address) or datatypes.hostname(address) or e.hysteria2_realms then + if is_ip(address) or datatypes.hostname(address) or is_realm then if (e.type == "sing-box" or e.type == "Xray") and e.protocol then local protocol = e.protocol if protocol == "vmess" then @@ -501,10 +502,11 @@ function get_valid_nodes() type_name = type_name .. " " .. protocol end if is_ipv6(address) then address = get_ipv6_full(address) end + type_name = is_realm and type_name .. " Realm" or type_name e["remark"] = trim("%s:[%s]" % {type_name, e.remarks}) if show_node_info == "1" then port = (port or ""):gsub(":", "-") - if not e.hysteria2_realms then + if not is_realm then e["remark"] = trim("%s:[%s] %s:%s" % {type_name, e.remarks, address, port}) end end @@ -596,6 +598,9 @@ function get_node_remarks(n) end type_name = type_name .. " " .. protocol end + if (n.type == "Hysteria2" or n.protocol == 'hysteria2') and n.hysteria2_realms then + type_name = type_name .. " Realm" + end remarks = trim("%s:[%s]" % {type_name, n.remarks}) end end @@ -1595,3 +1600,29 @@ function vps_domain_exclude(domain) if map[domain] then return true end return false end + +function parse_realm_uri(uri) + if type(uri) ~= "string" then return nil end + -- realm://token@server/realm_id?query + local token, server_url, realm_id, query = trim(uri):match("^realm://([^@]+)@([^/]+)/([^?]*)%??(.*)$") + if not token or not server_url or not realm_id then return nil end + realm_id = realm_id:gsub("/+$", "") + local realm = { + token = token, + server_url = server_url, + realm_id = realm_id + } + -- 解析 query 中的 stun= + if query and query ~= "" then + local stun_servers = {} + for key, value in query:gmatch("([^&=?]+)=([^&]+)") do + if key == "stun" and value ~= "" then + stun_servers[#stun_servers + 1] = value + end + end + if #stun_servers > 0 then + realm.stun_servers = stun_servers + end + end + return realm +end diff --git a/luci-app-passwall/luasrc/passwall/server_app.lua b/luci-app-passwall/luasrc/passwall/server_app.lua index 639b7119..bec17f8e 100644 --- a/luci-app-passwall/luasrc/passwall/server_app.lua +++ b/luci-app-passwall/luasrc/passwall/server_app.lua @@ -132,7 +132,7 @@ local function start() end end bin = ln_run("/usr/bin/microsocks", "microsocks_" .. id, string.format("-i :: -p %s %s", port, auth), log_path) - elseif type == "SS" or type == "SSR" then + elseif type == "SSR" then if user.custom == "1" and user.config_str then config = jsonc.parse(api.base64Decode(user.config_str)) else diff --git a/luci-app-passwall/luasrc/passwall/util_hysteria2.lua b/luci-app-passwall/luasrc/passwall/util_hysteria2.lua index d6be50df..98127324 100644 --- a/luci-app-passwall/luasrc/passwall/util_hysteria2.lua +++ b/luci-app-passwall/luasrc/passwall/util_hysteria2.lua @@ -67,11 +67,7 @@ function gen_config(var) server_host = api.get_ipv6_full(server_host) end - local server = server_host .. (server_port and ":" .. server_port or "") - - if node.hysteria2_hop then - server = server .. (server_port and "," or ":") .. string.gsub(node.hysteria2_hop, ":", "-") - end + local server = server_host .. ":" .. ((server_port or "") .. "," .. (node.hysteria2_hop or "")):gsub("^[%s,]+", ""):gsub("[%s,]+$", ""):gsub(":", "-") local config = { server = (function() diff --git a/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua b/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua index 6012ac6b..819b8278 100644 --- a/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua +++ b/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua @@ -80,11 +80,7 @@ function gen_config(var) tcp_tproxy = var["tcp_tproxy"] and true or nil } - if node.type == "SS" then - config.plugin = plugin_file or nil - config.plugin_opts = (plugin_file) and node.plugin_opts or nil - config.mode = mode - elseif node.type == "SSR" then + if node.type == "SSR" then config.protocol = node.protocol config.protocol_param = node.protocol_param config.obfs = node.obfs diff --git a/luci-app-passwall/luasrc/passwall/util_sing-box.lua b/luci-app-passwall/luasrc/passwall/util_sing-box.lua index 28832533..d98e1905 100644 --- a/luci-app-passwall/luasrc/passwall/util_sing-box.lua +++ b/luci-app-passwall/luasrc/passwall/util_sing-box.lua @@ -103,8 +103,8 @@ function gen_outbound(flag, node, tag, proxy_table) local run_socks_instance = true if proxy_table ~= nil and type(proxy_table) == "table" then proxy_tag = proxy_table.tag or nil - fragment = (proxy_table.fragment and node.protocol ~= "naive") and true or nil - record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive") and true or nil + fragment = (proxy_table.fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil + record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil run_socks_instance = proxy_table.run_socks_instance end @@ -472,6 +472,7 @@ function gen_outbound(flag, node, tag, proxy_table) table.insert(server_ports, range) end end + result.server_port = nil end protocol_table = { server_ports = next(server_ports) and server_ports or nil, @@ -528,6 +529,10 @@ function gen_outbound(flag, node, tag, proxy_table) table.insert(server_ports, range) end end + result.server_port = nil + end + if node.hysteria2_realms then + server_ports = {} end local interval, interval_max if next(server_ports) then @@ -571,7 +576,18 @@ function gen_outbound(flag, node, tag, proxy_table) return (t and t >= 2 and t <= 60) and t or nil end)(node.hysteria2_keep_alive_period), disable_path_mtu_discovery = version_ge_1_14_0 and (tonumber(node.hysteria2_disable_mtu_discovery) == 1) or nil, - tls = tls + tls = tls, + realm = node.hysteria2_realms and (function() + result.server = nil + result.server_port = nil + local realm = api.parse_realm_uri(node.hysteria2_realm_url) + if realm then + realm.server_url = realm.server_url and "https://" .. realm.server_url or nil + realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun + return realm + end + return nil + end)() or nil } end @@ -908,7 +924,17 @@ function gen_config_server(node) } }, ignore_client_bandwidth = (node.hysteria2_ignore_client_bandwidth == "1") and true or false, - tls = tls + tls = tls, + realm = node.hysteria2_realms and (function() + local realm = api.parse_realm_uri(node.hysteria2_realm_url) + if realm then + realm.server_url = realm.server_url and "https://" .. realm.server_url or nil + realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun + realm.stun_domain_resolver = "direct" + return realm + end + return nil + end)() or nil } end @@ -2088,7 +2114,7 @@ function gen_config(var) if not value.detour and value.server then value.detour = "direct" end - if value.server and not api.datatypes.hostname(value.server) then + if (value.server and not api.datatypes.hostname(value.server)) and not value.realm then value.domain_resolver = nil end for k, v in pairs(config.outbounds[index]) do diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index 4cc49322..7e04f06c 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -1072,7 +1072,13 @@ function gen_config(var) type = _node.balancingStrategy, settings = { expected = _node.expected and tonumber(_node.expected) and tonumber(_node.expected) or 2, - maxRTT = "1s" + maxRTT = "1s", + tolerance = (function(t) + t = tonumber(t) or 0 + if t < 1 then return nil end + if t > 100 then t = 100 end + return t / 100 + end)(_node.tolerance) } } else diff --git a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm index ad283988..3d7fac55 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm @@ -4,13 +4,12 @@ local api = require "luci.passwall.api" local appname = api.appname local map = self.map -local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_singbox = api.finded_com("sing-box") local has_xray = api.finded_com("xray") local has_hysteria2 = api.finded_com("hysteria") -local ss_type = api.get_core("ss_type", {{has_ss,"shadowsocks-libev"},{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}}) +local ss_type = api.get_core("ss_type", {{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}}) local trojan_type = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}}) local vmess_type = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}}) local vless_type = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}}) @@ -165,10 +164,7 @@ local current_node = map:get(section) var dom_prefix = null var protocol = "" - if (v_type === "SS") { - dom_prefix = "ss_" - protocol = "ss" - } else if (v_type === "SS-Rust") { + if (v_type === "SS-Rust") { dom_prefix = "ssrust_" protocol = "ss" } else if (v_type === "SSR") { @@ -196,7 +192,7 @@ local current_node = map:get(section) } } var url = null; - if (v_type === "SS" || v_type === "SS-Rust" || ((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "shadowsocks")) { + if (v_type === "SS-Rust" || ((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "shadowsocks")) { protocol = "ss" var v_port = opt.get(dom_prefix + "port"); var v_method = opt.get(dom_prefix + "method") || opt.get(dom_prefix + "ss_method"); @@ -1000,17 +996,9 @@ local current_node = map:get(section) dom_prefix = "singbox_" opt.set('type', "sing-box"); opt.set(dom_prefix + 'protocol', "shadowsocks"); - } else if (ss_type == "shadowsocks-rust") { + } else { dom_prefix = "ssrust_" opt.set('type', "SS-Rust"); - } else { - if (["2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"].includes(method)) { - dom_prefix = "ssrust_" - opt.set('type', "SS-Rust"); - } else { - dom_prefix = "ss_" - opt.set('type', "SS"); - } } const _method = (method || "none").toLowerCase(); diff --git a/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm index d385df68..77f77c5b 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm @@ -910,7 +910,11 @@ table td, .table .td { } else { port_s = o["hysteria_hop"] || o["hysteria2_hop"]; } - str += type + ":" + remarks; + if ((o.type === "Hysteria2" || o.protocol === 'hysteria2') && o.hysteria2_realms) { + str += type + " Realm:" + remarks; + } else { + str += type + ":" + remarks; + } return str; } @@ -952,7 +956,7 @@ table td, .table .td { var newDom = node_template.cloneNode(true); newDom.classList.add("cbi-rowstyle-" + (i % 2 + 1)); var innerHTML = newDom.innerHTML; - if (auto_detection_time != "icmp" && o["address"] && o["port"]) { + if (auto_detection_time != "icmp" && o["address"]) { innerHTML = innerHTML.split("{{ping}}").join('<%:Test%>'); } else { innerHTML = innerHTML.split("{{ping}}").join('---'); @@ -962,7 +966,8 @@ table td, .table .td { } else { innerHTML = innerHTML.split("{{tcping}}").join('---'); } - if (o["protocol"] && o["protocol"] === '_shunt') { + let is_realm = (o.type === "Hysteria2" || o.protocol === 'hysteria2') && o.hysteria2_realms || false; + if (o["protocol"] === '_shunt' || is_realm) { innerHTML = innerHTML.split("{{url_test}}").join('---'); } else { innerHTML = innerHTML.split("{{url_test}}").join('<%:Test%>'); @@ -971,11 +976,13 @@ table td, .table .td { innerHTML = innerHTML.split("{{group}}").join(o["group"] || ""); let node_remarks = get_remarks_name(o); if (show_node_info == "1") { - if (o["address"] && o["port"]) { + let _port = o["port"] || o["hysteria_hop"] || o["hysteria2_hop"]; + if (_port) _port = _port.replace(/:/g, '-'); + if (o["address"] && _port) { let _address = o["address"] if (o["full_address"]) _address = o["full_address"] - node_remarks += "
" + _address + ":" + o["port"] + node_remarks += "
" + _address + ":" + _port } } innerHTML = innerHTML.split("{{remarks}}").join(node_remarks); diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index 9212eb04..008e796a 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -577,6 +577,12 @@ msgstr "优选节点数量" msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them." msgstr "负载均衡器选出最优节点的个数,流量将在这几个节点中随机分配。" +msgid "Failure Tolerance (%)" +msgstr "测速失败率容忍度(%)" + +msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate." +msgstr "最多可接受的测速失败率,例如 1 表示允许 1% 的测速失败率。" + msgid "Shunt" msgstr "分流" diff --git a/luci-app-passwall/root/usr/share/passwall/app.sh b/luci-app-passwall/root/usr/share/passwall/app.sh index 3c2521b5..002df99d 100755 --- a/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/luci-app-passwall/root/usr/share/passwall/app.sh @@ -374,7 +374,7 @@ run_socks() { fi fi - if [ -n "${error_msg}" ] && [ "$(config_n_get $node hysteria2_realms)" = "1" ]; then + if [ -n "${error_msg}" ] && ([ -n "$(config_n_get $node hysteria_hop)" ] || [ -n "$(config_n_get $node hysteria2_hop)" ] || [ "$(config_n_get $node hysteria2_realms)" = "1" ]); then unset error_msg fi @@ -463,17 +463,6 @@ run_socks() { lua $UTIL_SS gen_config "$(json_dump)" > $config_file [ -n "$no_run" ] || ln_run "$(first_type ssr-local)" "ssr-local" $log_file -c "$config_file" -v -u ;; - ss) - [ -n "$no_run" ] || { - local plugin_sh="${config_file%.json}_plugin.sh" - json_add_string "plugin_sh" "$plugin_sh" - } - json_add_string "local_addr" "$bind" - json_add_string "local_port" "$socks_port" - json_add_string "mode" "tcp_and_udp" - lua $UTIL_SS gen_config "$(json_dump)" > $config_file - [ -n "$no_run" ] || ln_run "$(first_type ss-local)" "ss-local" $log_file -c "$config_file" -v - ;; ss-rust) [ "$http_port" != "0" ] && { http_flag=1 @@ -632,15 +621,6 @@ run_redir() { lua $UTIL_SS gen_config "$(json_dump)" > $config_file ln_run "$(first_type ssr-redir)" "ssr-redir" $log_file -c "$config_file" -v -U ;; - ss) - local plugin_sh="${config_file%.json}_plugin.sh" - json_add_string "plugin_sh" "$plugin_sh" - json_add_string "local_addr" "0.0.0.0" - json_add_string "local_port" "$local_port" - json_add_string "mode" "udp_only" - lua $UTIL_SS gen_config "$(json_dump)" > $config_file - ln_run "$(first_type ss-redir)" "ss-redir" $log_file -c "$config_file" -v - ;; ss-rust) local plugin_sh="${config_file%.json}_plugin.sh" json_add_string "plugin_sh" "$plugin_sh" @@ -889,23 +869,6 @@ run_redir() { lua $UTIL_SS gen_config "$(json_dump)" > $config_file ln_run "$(first_type ssr-redir)" "ssr-redir" $log_file -c "$config_file" -v ${_extra_param} ;; - ss) - [ "${TCP_PROXY_WAY}" = "tproxy" ] && json_add_string "tcp_tproxy" "true" - if [ "$TCP_UDP" = "1" ]; then - config_file="${config_file//TCP/TCP_UDP}" - UDP_REDIR_PORT=$TCP_REDIR_PORT - unset UDP_NODE - json_add_string "mode" "tcp_and_udp" - else - json_add_string "mode" "tcp_only" - fi - local plugin_sh="${config_file%.json}_plugin.sh" - json_add_string "plugin_sh" "$plugin_sh" - json_add_string "local_addr" "0.0.0.0" - json_add_string "local_port" "$local_port" - lua $UTIL_SS gen_config "$(json_dump)" > $config_file - ln_run "$(first_type ss-redir)" "ss-redir" $log_file -c "$config_file" -v - ;; ss-rust) json_add_string "local_tcp_redir_port" "$local_port" [ "${TCP_PROXY_WAY}" = "tproxy" ] && json_add_string "tcp_tproxy" "true" @@ -2049,8 +2012,8 @@ get_config() { FILTER_PROXY_IPV6=$(config_t_get global filter_proxy_ipv6 0) DNS_REDIRECT=$(config_t_get global dns_redirect 1) - REDIRECT_LIST="socks ss ss-rust ssr sing-box xray naiveproxy hysteria2" - TPROXY_LIST="socks ss ss-rust ssr sing-box xray hysteria2" + REDIRECT_LIST="socks ss-rust ssr sing-box xray naiveproxy hysteria2" + TPROXY_LIST="socks ss-rust ssr sing-box xray hysteria2" NEXT_DNS_LISTEN_PORT=15353 TUN_DNS="127.0.0.1#${NEXT_DNS_LISTEN_PORT}" diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index ee3d8eed..52f0b0d2 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -24,7 +24,6 @@ local UrlDecode = api.UrlDecode local uci = api.uci local fs = api.fs -local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_ssr = api.is_finded("ssr-local") and api.is_finded("ssr-redir") local has_singbox = api.finded_com("sing-box") @@ -35,7 +34,7 @@ local DEFAULT_FILTER_KEYWORD_MODE = uci:get(appname, "@global_subscribe[0]", "fi local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {} -- 取节点使用core类型(节点订阅页面未设置时,自动取默认) -local DEFAULT_SS_TYPE = api.get_core("ss_type", {{has_ss,"shadowsocks-libev"},{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}}) +local DEFAULT_SS_TYPE = api.get_core("ss_type", {{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}}) local DEFAULT_TROJAN_TYPE = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}}) local DEFAULT_VMESS_TYPE = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}}) local DEFAULT_VLESS_TYPE = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}}) @@ -43,7 +42,6 @@ local DEFAULT_HYSTERIA2_TYPE = api.get_core("hysteria2_type", {{has_hysteria2,"h local core_has = { ["xray"] = has_xray, ["sing-box"] = has_singbox, - ["shadowsocks-libev"] = has_ss, ["shadowsocks-rust"] = has_ss_rust, ["hysteria2"] = has_hysteria2 } @@ -482,9 +480,7 @@ end -- 设置 ss 协议实现类型 local function set_ss_implementation(ss_type, result) - if ss_type == "shadowsocks-libev" and has_ss then - result.type = "SS" - elseif ss_type == "shadowsocks-rust" and has_ss_rust then + if ss_type == "shadowsocks-rust" and has_ss_rust then result.type = 'SS-Rust' elseif ss_type == "xray" and has_xray then result.type = 'Xray' @@ -835,20 +831,6 @@ local function processData(szType, content, add_mode, group, sub_cfg) end end - if result.type == "SS" then - local aead2022_methods = { "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" } - local aead2022 = false - for k, v in ipairs(aead2022_methods) do - if method:lower() == v:lower() then - aead2022 = true - end - end - if aead2022 then - -- shadowsocks-libev 不支持2022加密 - result.error_msg = "shadowsocks-libev 不支持2022加密。" - end - end - if params.type then params.type = string.lower(params.type) if result.type == "sing-box" and params.type == "raw" then @@ -862,7 +844,7 @@ local function processData(szType, content, add_mode, group, sub_cfg) else result.transport = params.type end - if result.type ~= "SS-Rust" and result.type ~= "SS" then + if result.type ~= "SS-Rust" then if params.type == 'ws' then result.ws_host = params.host result.ws_path = params.path diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index f31464fd..db211ad6 100644 --- a/luci-app-passwall2/Makefile +++ b/luci-app-passwall2/Makefile @@ -6,8 +6,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=26.5.1 -PKG_RELEASE:=43 +PKG_VERSION:=26.5.18 +PKG_RELEASE:=44 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall2/luasrc/controller/passwall2.lua b/luci-app-passwall2/luasrc/controller/passwall2.lua index 40a868c1..480d1d33 100644 --- a/luci-app-passwall2/luasrc/controller/passwall2.lua +++ b/luci-app-passwall2/luasrc/controller/passwall2.lua @@ -52,7 +52,7 @@ function index() entry({"admin", "services", appname, "socks_config"}, cbi(appname .. "/client/socks_config")).leaf = true entry({"admin", "services", appname, "acl"}, cbi(appname .. "/client/acl"), _("Access control"), 98).leaf = true entry({"admin", "services", appname, "acl_config"}, cbi(appname .. "/client/acl_config")).leaf = true - entry({"admin", "services", appname, "log"}, form(appname .. "/client/log"), _("Watch Logs"), 999).leaf = true + entry({"admin", "services", appname, "log"}, form(appname .. "/client/log"), _("Runtime Logs"), 999).leaf = true --[[ Server ]] entry({"admin", "services", appname, "server"}, cbi(appname .. "/server/index"), _("Server-Side"), 99).leaf = true @@ -508,13 +508,17 @@ function delete_select_nodes() if t["node"] == w then uci:delete(appname, t[".name"]) end + local changed = false local auto_switch_node_list = uci:get(appname, t[".name"], "autoswitch_backup_node") or {} for i = #auto_switch_node_list, 1, -1 do if w == auto_switch_node_list[i] then table.remove(auto_switch_node_list, i) + changed = true end end - uci:set_list(appname, t[".name"], "autoswitch_backup_node", auto_switch_node_list) + if changed then + uci:set_list(appname, t[".name"], "autoswitch_backup_node", auto_switch_node_list) + end end) uci:foreach(appname, "haproxy_config", function(t) if t["lbss"] == w then 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 9d05dbbb..f5c66225 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 @@ -21,27 +21,50 @@ local function _n(name) end 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.datatype = "port" +o:depends({ [_n("realms")] = false }) o = s:option(Value, _n("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 = 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.datatype = "or(uinteger,portrange)" o.placeholder = "30" o.default = "30" o.rewrite_option = o.option +o:depends({ [_n("realms")] = false }) -o = s:option(Value, _n("obfs"), translate("Obfs Password")) +o = s:option(Flag, _n("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(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(Value, _n("auth_password"), translate("Auth Password")) o.password = true o.rewrite_option = o.option +o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type")) +o:value("", translate("Disable")) +o:value("salamander") +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 = s:option(Flag, _n("fast_open"), translate("Fast Open")) o.default = "0" 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 cba6733b..012f4952 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 @@ -164,28 +164,66 @@ if load_balancing_options then -- [[ Load balancing Start ]] -- Fallback Node o = s:option(ListValue, _n("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.template = appname .. "/cbi/nodes_listvalue" - o.group = {""} - local function check_fallback_chain(fb) - for k, v in pairs(fallback_list) do - if v.fallback == fb then - fallback_list[k] = nil - check_fallback_chain(v.id) + -- Maximum number of fallback nesting layers + local MAX_FALLBACK_DEPTH = 3 + -- Check if a loop will form. + local function will_loop(start_id, target_id, depth) + depth = depth or 0 + -- Recursion stops after the maximum depth is exceeded. + if depth >= MAX_FALLBACK_DEPTH then + return false + end + for _, v in ipairs(fallback_list) do + if v.id == target_id then + local fb = v.fallback + -- No fallback + if not fb or fb == "" or fb == "_direct" then + return false + end + -- Loopback detected + if fb == start_id then + return true + end + -- Continue recursive checking + return will_loop(start_id, fb, depth + 1) end end + return false end - -- Check the fallback chain and remove the balancer node that would form a closed loop. - if is_balancer then - check_fallback_chain(arg[1]) + -- Get fallback chain depth + local function get_fallback_depth(id, depth) + depth = depth or 0 + if depth >= MAX_FALLBACK_DEPTH then + return depth + end + for _, v in ipairs(fallback_list) do + if v.id == id then + local fb = v.fallback + if not fb or fb == "" or fb == "_direct" then + return depth + end + return get_fallback_depth(fb, depth + 1) + end + end + return depth end - for i, v in ipairs(fallback_list) do - o:value(v.id, v.remark) - o.group[#o.group+1] = (v.group and v.group ~= "") and v.group or translate("default") + for _, v in ipairs(fallback_list) do + local depth = get_fallback_depth(v.id) + -- Once the maximum number of nested doll layers is exceeded, further selection of the balancer is not allowed. + if depth < MAX_FALLBACK_DEPTH + and not will_loop(arg[1], v.id) + then + o:value(v.id, v.remark) + o.group[#o.group + 1] = (v.group and v.group ~= "") and v.group or translate("default") + end end for k1, v1 in pairs(node_list) do - if k1 == "socks_list" or k1 == "normal_list" then + if k1 == "socks_list" or k1 == "normal_list" or k1 == "urltest_list" then for i, v in ipairs(v1) do o:value(v.id, v.remark) o.group[#o.group+1] = (v.group and v.group ~= "") and v.group or translate("default") @@ -221,6 +259,13 @@ if load_balancing_options then -- [[ Load balancing Start ]] 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.datatype = "uinteger" + o.default = "10" + o.placeholder = "10" + o.description = translate("The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate.") end -- [[ Load balancing End ]] if load_iface_options then -- [[ Custom Interface Start ]] @@ -299,11 +344,9 @@ o.placeholder = "30" o.default = "30" o:depends({ [_n("protocol")] = "hysteria2" }) -o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) -o:depends({ [_n("protocol")] = "hysteria2" }) - -o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps")) -o:depends({ [_n("protocol")] = "hysteria2" }) +o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) +o.password = true +o:depends({ [_n("protocol")] = "hysteria2"}) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) o:value("", translate("Disable")) @@ -313,9 +356,11 @@ o:depends({ [_n("protocol")] = "hysteria2" }) o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) -o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) -o.password = true -o:depends({ [_n("protocol")] = "hysteria2"}) +o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) +o:depends({ [_n("protocol")] = "hysteria2" }) + +o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps")) +o:depends({ [_n("protocol")] = "hysteria2" }) o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s~120s)") o:depends({ [_n("protocol")] = "hysteria2"}) 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 f45ee300..cfb5fb61 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 @@ -43,6 +43,8 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'") +local singbox_version = api.get_app_version("sing-box"):match("[^v]+") + o = s:option(ListValue, _n("protocol"), translate("Protocol")) o:value("socks", "Socks") o:value("http", "HTTP") @@ -388,19 +390,32 @@ end if singbox_tags:find("with_quic") then o = s:option(Value, _n("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" }) + o:depends({ [_n("protocol")] = "hysteria2", [_n("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, _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.datatype = "or(uinteger,portrange)" o.placeholder = "30" o.default = "30" - o:depends({ [_n("protocol")] = "hysteria2" }) + o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) - o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) - o:depends({ [_n("protocol")] = "hysteria2" }) + o = s:option(Flag, _n("hysteria2_realms"), translate("Realms")) + o.default = "0" + if api.compare_versions(singbox_version, ">=", "1.14.0") then + o:depends({ [_n("protocol")] = "hysteria2"}) + else + o:depends({ [_n("protocol")] = "__hide"}) + end - o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps")) - o:depends({ [_n("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(DynamicList, _n("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 = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) + o.password = true + o:depends({ [_n("protocol")] = "hysteria2"}) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) o:value("", translate("Disable")) @@ -410,8 +425,20 @@ if singbox_tags:find("with_quic") then o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) - o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) - o.password = true + o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) + o:depends({ [_n("protocol")] = "hysteria2" }) + + o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps")) + o:depends({ [_n("protocol")] = "hysteria2" }) + + o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s~120s)") + o:depends({ [_n("protocol")] = "hysteria2"}) + + o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Example:") .. "10s (2s~60s)") + o:depends({ [_n("protocol")] = "hysteria2"}) + + o = s:option(Flag, _n("hysteria2_disable_mtu_discovery"), translate("Disable MTU detection")) + o.default = "0" o:depends({ [_n("protocol")] = "hysteria2"}) end @@ -506,7 +533,7 @@ 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" }) +o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) o:depends({ [_n("protocol")] = "naive" }) o = s:option(TextValue, _n("ech_config"), translate("ECH Config")) @@ -818,10 +845,14 @@ local protocols = s.fields[_n("protocol")].keylist if #protocols > 0 then for i, v in ipairs(protocols) do if not v:find("^_") then - s.fields[_n("address")]:depends({ [_n("protocol")] = v }) - s.fields[_n("port")]:depends({ [_n("protocol")] = v }) - s.fields[_n("domain_resolver")]:depends({ [_n("protocol")] = v }) - s.fields[_n("domain_strategy")]:depends({ [_n("protocol")] = v }) + local depends_condition = { [_n("protocol")] = v } + if v == "hysteria2" then + depends_condition[_n("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) end end end @@ -834,16 +865,21 @@ if not load_shunt_options then if not (load_iface_options or load_urltest_options) then -- Special node cannot be use pre-proxy. o:value("1", translate("Preproxy Node")) + o:value("3", translate("Outbound Interface")) 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" }) + o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false }) o1.template = appname .. "/cbi/nodes_listvalue" o1.group = {} + o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface")) + o3.default = "eth1" + o3:depends({ [_n("chain_proxy")] = "3" }) + o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) - o2:depends({ [_n("chain_proxy")] = "2" }) + o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false }) o2.template = appname .. "/cbi/nodes_listvalue" o2.group = {} 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 6983d0d5..74f5a37d 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 @@ -22,17 +22,38 @@ o = s:option(Flag, _n("custom"), translate("Use Custom Config")) o = s:option(Value, _n("port"), translate("Listen Port")) o.datatype = "port" +o.rmempty = false o:depends({ [_n("custom")] = false }) -o = s:option(Value, _n("obfs"), translate("Obfs Password")) +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 = 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(Value, _n("auth_password"), translate("Auth Password")) o.password = true o.rewrite_option = o.option o:depends({ [_n("custom")] = false }) +o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type")) +o:value("", translate("Disable")) +o:value("salamander") +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 = s:option(Flag, _n("udp"), translate("UDP")) o.default = "1" o.rewrite_option = o.option 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 a20b03bb..3a4d9ba3 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 @@ -129,6 +129,14 @@ o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o.password = true o:depends({ [_n("protocol")] = "hysteria2"}) +o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) +o:value("", translate("Disable")) +o:value("salamander") +o:depends({ [_n("protocol")] = "hysteria2" }) + +o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) +o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) + o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control")) o.default = 0 o:depends({ [_n("protocol")] = "hysteria2" }) @@ -139,14 +147,6 @@ o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwid 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(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) -o:value("", translate("Disable")) -o:value("salamander") -o:depends({ [_n("protocol")] = "hysteria2" }) - -o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) -o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) - ---- [[ TLS ]] o = s:option(Flag, _n("tls"), translate("TLS")) o.default = 0 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 3455bc8b..96beede8 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 @@ -58,6 +58,7 @@ o:depends({ [_n("custom")] = false }) o = s:option(Value, _n("port"), translate("Listen Port")) o.datatype = "port" +o.rmempty = false o:depends({ [_n("custom")] = false }) o = s:option(Flag, _n("auth"), translate("Auth")) @@ -157,10 +158,29 @@ if singbox_tags:find("with_quic") then end if singbox_tags:find("with_quic") then + o = s:option(Flag, _n("hysteria2_realms"), translate("Realms")) + o.default = "0" + o:depends({ [_n("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(DynamicList, _n("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 = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o.password = true o:depends({ [_n("protocol")] = "hysteria2"}) + o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) + o:value("", translate("Disable")) + o:value("salamander") + o:depends({ [_n("protocol")] = "hysteria2" }) + + o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) + o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) + 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.default = 0 o:depends({ [_n("protocol")] = "hysteria2" }) @@ -170,14 +190,6 @@ if singbox_tags:find("with_quic") then 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(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) - o:value("", translate("Disable")) - o:value("salamander") - o:depends({ [_n("protocol")] = "hysteria2" }) - - o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) - o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) end o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol")) @@ -324,7 +336,7 @@ 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" }) +o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) o = s:option(TextValue, _n("ech_key"), translate("ECH Key")) o.default = "" diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua index eae4eb92..a5dc64a9 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua @@ -31,7 +31,11 @@ local type_table = {} for filename in fs.dir(types_dir) do table.insert(type_table, filename) end -table.sort(type_table) +table.sort(type_table, function(a, b) + if a == "socks.lua" then return true end + if b == "socks.lua" then return false end + return a < b +end) for index, value in ipairs(type_table) do local p_func = loadfile(types_dir .. value) diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index 5bcfcfbe..71a59821 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -377,11 +377,13 @@ function is_special_node(e) end function is_ip(val) + val = trim(val):lower() local str = val:match("%[(.-)%]") or val return datatypes.ipaddr(str) or false end function is_ipv6(val) + val = trim(val):lower() local str = val:match("%[(.-)%]") or val return datatypes.ip6addr(str) or false end @@ -497,9 +499,10 @@ function get_valid_nodes() end end local port = e.port or e.hysteria_hop or e.hysteria2_hop - if port and e.address then + local is_realm = (e.type == "Hysteria2" or e.protocol == 'hysteria2') and e.hysteria2_realms or nil + if (port and e.address) or is_realm then local address = e.address - if is_ip(address) or datatypes.hostname(address) then + if is_ip(address) or datatypes.hostname(address) or is_realm then if (e.type == "sing-box" or e.type == "Xray") and e.protocol then local protocol = e.protocol if protocol == "vmess" then @@ -526,10 +529,13 @@ function get_valid_nodes() type_name = type_name .. " " .. protocol end if is_ipv6(address) then address = get_ipv6_full(address) end + type_name = is_realm and type_name .. " Realm" or type_name e["remark"] = trim("%s:[%s]" % {type_name, e.remarks}) if show_node_info == "1" then - port = port:gsub(":", "-") - e["remark"] = trim("%s:[%s] %s:%s" % {type_name, e.remarks, address, port}) + port = (port or ""):gsub(":", "-") + if not is_realm then + e["remark"] = trim("%s:[%s] %s:%s" % {type_name, e.remarks, address, port}) + end end e.node_type = "normal" if not e.group or e.group == "" then @@ -619,7 +625,10 @@ function get_node_remarks(n) end type_name = type_name .. " " .. protocol end - remarks = trim("%s:[%s]" % {type_name, n.remarks}) + if (n.type == "Hysteria2" or n.protocol == 'hysteria2') and n.hysteria2_realms then + type_name = type_name .. " Realm" + end + remarks = trim("%s:[%s]" % {type_name, n.remarks}) end end return remarks @@ -1204,7 +1213,7 @@ function to_move(app_name,file) } end - local flag = sys.call('pgrep -af "passwall2/.*'.. app_name ..'" >/dev/null') + local flag = sys.call('busybox pgrep -af "passwall2/.*'.. app_name ..'" >/dev/null') if flag == 0 then sys.call("/etc/init.d/passwall2 stop") end @@ -1587,4 +1596,30 @@ function get_dnsmasq_server_domain() end end return dnsmasq_server_t -end \ No newline at end of file +end + +function parse_realm_uri(uri) + if type(uri) ~= "string" then return nil end + -- realm://token@server/realm_id?query + local token, server_url, realm_id, query = trim(uri):match("^realm://([^@]+)@([^/]+)/([^?]*)%??(.*)$") + if not token or not server_url or not realm_id then return nil end + realm_id = realm_id:gsub("/+$", "") + local realm = { + token = token, + server_url = server_url, + realm_id = realm_id + } + -- 解析 query 中的 stun= + if query and query ~= "" then + local stun_servers = {} + for key, value in query:gmatch("([^&=?]+)=([^&]+)") do + if key == "stun" and value ~= "" then + stun_servers[#stun_servers + 1] = value + end + end + if #stun_servers > 0 then + realm.stun_servers = stun_servers + end + end + return realm +end diff --git a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua index 1b8ef901..7075dd11 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua @@ -5,15 +5,24 @@ local jsonc = api.jsonc function gen_config_server(node) local config = { - listen = ":" .. node.port, + listen = (function() + if node.hysteria2_realms and node.hysteria2_realm_url then + local url = node.hysteria2_realm_url:gsub("/+$", "") + if node.port then + url = url .. (url:find("?") and "&lport=" or "?lport=") .. node.port + end + return url + end + return ":" .. (node.port or "0") + end)(), tls = { cert = node.tls_certificateFile, key = node.tls_keyFile, }, - obfs = (node.hysteria2_obfs) and { + obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and { type = "salamander", salamander = { - password = node.hysteria2_obfs + password = node.hysteria2_obfs_password } } or nil, auth = { @@ -26,6 +35,9 @@ function gen_config_server(node) } 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 + } or nil } return config end @@ -51,14 +63,19 @@ function gen_config(var) if api.is_ipv6(server_host) then server_host = api.get_ipv6_full(server_host) end - local server = server_host .. ":" .. server_port - if (node.hysteria2_hop) then - server = server .. "," .. string.gsub(node.hysteria2_hop, ":", "-") - end + local server = server_host .. ":" .. ((server_port or "") .. "," .. (node.hysteria2_hop or "")):gsub("^[%s,]+", ""):gsub("[%s,]+$", ""):gsub(":", "-") local config = { - server = server, + server = (function() + if node.hysteria2_realms and node.hysteria2_realm_url then + return node.hysteria2_realm_url:gsub("/+$", "") + end + return server + end)(), + realm = (node.hysteria2_realms and node.hysteria2_realm_stun) and { + stunServers = node.hysteria2_realm_stun + } or nil, transport = { type = "udp", udp = node.hysteria2_hop and (function() @@ -83,10 +100,10 @@ function gen_config(var) return udp end)() or nil }, - obfs = (node.hysteria2_obfs) and { + obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and { type = "salamander", salamander = { - password = node.hysteria2_obfs + password = node.hysteria2_obfs_password } } or nil, auth = node.hysteria2_auth_password, diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index 0116accb..8080b147 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -134,8 +134,8 @@ function gen_outbound(flag, node, tag, proxy_table) local run_socks_instance = true if proxy_table ~= nil and type(proxy_table) == "table" then proxy_tag = proxy_table.tag or nil - fragment = proxy_table.fragment or nil - record_fragment = proxy_table.record_fragment or nil + fragment = (proxy_table.fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil + record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil run_socks_instance = proxy_table.run_socks_instance end @@ -250,7 +250,7 @@ function gen_outbound(flag, node, tag, proxy_table) enabled = true, disable_sni = (node.tls_disable_sni == "1") and true or false, -- Do not send the server name in ClientHello. server_name = node.tls_serverName, -- Used to verify the hostname on the returned certificate, unless the settings are insecure. It is also included in ClientHello to support virtual hosts, unless it is an IP address. - insecure = (node.tls_allowInsecure == "1") and true or false, -- Accepts any server certificate. + insecure = node.tls_allowInsecure == "1" or (node.tls_pinSHA256 and node.tls_pinSHA256 ~= ""), -- Accepts any server certificate. (Also compatible with xray's pinnedPeerCertSha256) alpn = alpn, -- A list of supported application layer protocols, arranged in order of priority. If both peers support ALPN, the protocol selected will be one of these protocols; otherwise, the connection will fail. --max_version = "1.3", fragment = fragment, @@ -506,6 +506,7 @@ function gen_outbound(flag, node, tag, proxy_table) table.insert(server_ports, range) end end + result.server_port = nil end protocol_table = { server_ports = next(server_ports) and server_ports or nil, @@ -519,9 +520,9 @@ function gen_outbound(flag, node, tag, proxy_table) obfs = node.hysteria_obfs, auth = (node.hysteria_auth_type == "base64") and node.hysteria_auth_password or nil, auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil, - recv_window_conn = tonumber(node.hysteria_recv_window_conn), - recv_window = tonumber(node.hysteria_recv_window), - disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false, + recv_window_conn = tonumber(node.hysteria_recv_window_conn), --1.14 将变更为 stream_receive_window + recv_window = tonumber(node.hysteria_recv_window), --1.14 将变更为 connection_receive_window + disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false, --1.14 将变更为 disable_path_mtu_discovery tls = tls } end @@ -545,13 +546,12 @@ function gen_outbound(flag, node, tag, proxy_table) heartbeat = (tonumber(node.tuic_heartbeat) or 3) .. "s", tls = tls } - if node.tuic_alpn and node.tuic_alpn ~= "default" then - local alpn = {} - string.gsub(node.tuic_alpn, '[^,]+', function(w) - table.insert(alpn, w) - end) - if #alpn > 0 then protocol_table.tls.alpn = alpn end - end + node.tuic_alpn = (node.tuic_alpn and node.tuic_alpn ~= "default") and node.tuic_alpn or "h3" + local alpn = {} + string.gsub(node.tuic_alpn, '[^,]+', function(w) + table.insert(alpn, w) + end) + if #alpn > 0 then protocol_table.tls.alpn = alpn end end if node.protocol == "hysteria2" then @@ -563,6 +563,10 @@ function gen_outbound(flag, node, tag, proxy_table) table.insert(server_ports, range) end end + result.server_port = nil + end + if node.hysteria2_realms then + server_ports = {} end local interval, interval_max if next(server_ports) then @@ -595,7 +599,29 @@ function gen_outbound(flag, node, tag, proxy_table) password = node.hysteria2_obfs_password } or nil, password = node.hysteria2_auth_password or nil, - tls = tls + idle_timeout = (function(t) + if not version_ge_1_14_0 then return nil end + t = tonumber(tostring(t or "30"):match("^%d+")) + return (t and t >= 4 and t <= 120) and t or 30 + end)(node.hysteria2_idle_timeout), + keep_alive_period = (function(t) + if not version_ge_1_14_0 then return nil end + t = tonumber(tostring(t or "0"):match("^%d+")) + return (t and t >= 2 and t <= 60) and t or nil + end)(node.hysteria2_keep_alive_period), + disable_path_mtu_discovery = version_ge_1_14_0 and (tonumber(node.hysteria2_disable_mtu_discovery) == 1) or nil, + tls = tls, + realm = node.hysteria2_realms and (function() + result.server = nil + result.server_port = nil + local realm = api.parse_realm_uri(node.hysteria2_realm_url) + if realm then + realm.server_url = realm.server_url and "https://" .. realm.server_url or nil + realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun + return realm + end + return nil + end)() or nil } end @@ -881,10 +907,10 @@ function gen_config_server(node) auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil, } }, - recv_window_conn = node.hysteria_recv_window_conn and tonumber(node.hysteria_recv_window_conn) or nil, - recv_window_client = node.hysteria_recv_window_client and tonumber(node.hysteria_recv_window_client) or nil, - max_conn_client = node.hysteria_max_conn_client and tonumber(node.hysteria_max_conn_client) or nil, - disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false, + recv_window_conn = node.hysteria_recv_window_conn and tonumber(node.hysteria_recv_window_conn) or nil, --1.14 to stream_receive_window + recv_window_client = node.hysteria_recv_window_client and tonumber(node.hysteria_recv_window_client) or nil, --1.14 to connection_receive_window + max_conn_client = node.hysteria_max_conn_client and tonumber(node.hysteria_max_conn_client) or nil, --1.14 to max_concurrent_streams + disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false, --1.14 to disable_path_mtu_discover tls = tls } end @@ -928,7 +954,17 @@ function gen_config_server(node) } }, ignore_client_bandwidth = (node.hysteria2_ignore_client_bandwidth == "1") and true or false, - tls = tls + tls = tls, + realm = node.hysteria2_realms and (function() + local realm = api.parse_realm_uri(node.hysteria2_realm_url) + if realm then + realm.server_url = realm.server_url and "https://" .. realm.server_url or nil + realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun + realm.stun_domain_resolver = "direct" + return realm + end + return nil + end)() or nil } end @@ -1312,7 +1348,6 @@ function gen_config(var) else ut_nodes = _node.urltest_node end - if #ut_nodes == 0 then return nil end local valid_nodes = {} for i = 1, #(ut_nodes or {}) do local ut_node_id = ut_nodes[i] @@ -1444,6 +1479,10 @@ function gen_config(var) end end end + if node.chain_proxy == "3" and node.outbound_iface then + outbound.detour = nil + outbound.bind_interface = node.outbound_iface + end return default_outTag, last_insert_outbound end @@ -1775,6 +1814,10 @@ function gen_config(var) tag = "local" }) + route.default_domain_resolver = { + server = "local" + } + if direct_dns_udp_server then table.insert(dns.servers, { tag = "direct", @@ -2051,7 +2094,7 @@ function gen_config(var) string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w) sys.call("ipset -q -F " .. w) end) - local ipset_prefix_name = "passwall2_" .. node_id .. "_" + local ipset_prefix_name = "psw2_" .. node_id .. "_" local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'") string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w) sys.call("ipset -q -F " .. w) @@ -2070,7 +2113,7 @@ function gen_config(var) end) local family = "inet" local table_name = "passwall2" - local nftset_prefix_name = "passwall2_" .. node_id .. "_" + local nftset_prefix_name = "psw2_" .. node_id .. "_" local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'") string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w) sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w)) @@ -2126,19 +2169,15 @@ function gen_config(var) type = "direct", tag = "direct", routing_mark = 255, - domain_resolver = { - server = "local", - strategy = "prefer_ipv6" - } }) for index, value in ipairs(config.outbounds) do if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and value.server_port and not no_run then sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list")) end - if not value.detour and value.server then + if not value.detour and not value.bind_interface and value.server then value.detour = "direct" end - if value.server and not api.datatypes.hostname(value.server) then + if (value.server and not api.datatypes.hostname(value.server)) and not value.realm then value.domain_resolver = nil end for k, v in pairs(config.outbounds[index]) do @@ -2290,10 +2329,6 @@ function gen_front_dns_config(var) type = "direct", tag = "direct", routing_mark = 255, - domain_resolver = { - server = "direct", - strategy = direct_strategy - } }) local direct_dns_shunt = uci:get(appname, "@global[0]", "direct_dns_shunt") or "" @@ -2363,6 +2398,10 @@ function gen_front_dns_config(var) domain = node_domain }) end + route.default_domain_resolver = { + server = "direct", + strategy = direct_strategy + } end if default_dns_udp_server then diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 27c7c9f0..cf9fd5f6 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -794,6 +794,9 @@ function gen_config_server(node) config.outbounds[index][k] = nil end end + if value.protocol == "freedom" and api.compare_versions(xray_version, "<", "26.5.3") then -- Todo is to remove it + value.settings = nil + end end return config @@ -1049,10 +1052,10 @@ function gen_config(var) if #valid_nodes == 0 then return nil end -- fallback node - local fallback_node_tag = nil local fallback_node_id = _node.fallback_node - if not fallback_node_id or fallback_node_id == "" then fallback_node_id = nil end - if fallback_node_id then + fallback_node_id = (fallback_node_id and fallback_node_id ~= "") and fallback_node_id or nil + local fallback_node_tag = (fallback_node_id == "_direct") and "direct" or "blackhole" + if fallback_node_id and fallback_node_id ~= "_direct" then local is_new_node = true for _, outbound in ipairs(outbounds) do if string.sub(outbound.tag, 1, #fallback_node_id) == fallback_node_id then @@ -1082,7 +1085,13 @@ function gen_config(var) type = _node.balancingStrategy, settings = { expected = _node.expected and tonumber(_node.expected) and tonumber(_node.expected) or 2, - maxRTT = "1s" + maxRTT = "1s", + tolerance = (function(t) + t = tonumber(t) or 0 + if t < 1 then return nil end + if t > 100 then t = 100 end + return t / 100 + end)(_node.tolerance) } } else @@ -1264,9 +1273,9 @@ function gen_config(var) interface = node.iface } }, - settings = { + settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check finalRules = {{ action = "allow" }} - } + } or nil } sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface)) end @@ -1763,15 +1772,22 @@ function gen_config(var) end end end - local dns_block_mode = "host" - dns_block_mode = "" - if dns_block_mode == "host" and dns_outboundTag == "blackhole" then - for d_i, d_k in ipairs(value.domain) do - dns.hosts[d_k] = "0.0.0.0" + local dns_block = true -- If you do not want the blackhole rule to use DNS routing, please change it to `nil` or do not assign a value. + if dns_outboundTag == "blackhole" then + if dns_block then + local dns_block_mode = "Hosts" -- use the Hosts mode to block. + if dns_block_mode == "Hosts" then + for d_i, d_k in ipairs(value.domain) do + dns.hosts[d_k] = "0.0.0.0" + end + dns_server = nil + end + else + dns_server = nil end - dns_server = nil end if dns_server then + dns_server.finalQuery = true dns_server.domains = value.domain if value.shunt_rule_name then dns_server.tag = "dns-in-" .. value.shunt_rule_name @@ -1806,7 +1822,7 @@ function gen_config(var) string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w) sys.call("ipset -q -F " .. w) end) - local ipset_prefix_name = "passwall2_" .. node_id .. "_" + local ipset_prefix_name = "psw2_" .. node_id .. "_" local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'") string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w) sys.call("ipset -q -F " .. w) @@ -1825,7 +1841,7 @@ function gen_config(var) end) local family = "inet" local table_name = "passwall2" - local nftset_prefix_name = "passwall2_" .. node_id .. "_" + local nftset_prefix_name = "psw2_" .. node_id .. "_" local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'") string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w) sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w)) @@ -2080,7 +2096,12 @@ function gen_proto_config(var) end table.insert(outbounds, { - protocol = "freedom", tag = "direct", settings = {finalRules = {{ action = "allow" }}}, sockopt = {mark = 255} + protocol = "freedom", + tag = "direct", + settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check + finalRules = {{ action = "allow" }} + } or nil, + sockopt = {mark = 255} }) local config = { diff --git a/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm b/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm index 590e45a4..e1ba5c58 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm @@ -35,22 +35,48 @@ local appname = api.appname \ No newline at end of file diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm b/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm index e6c4a5d2..655b0be6 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm @@ -602,10 +602,10 @@ local current_node = map:get(section) if (v_type === "Hysteria2") { v_password = opt.get("hysteria2_auth_password"); - var dom_obfs = opt.get("hysteria2_obfs"); + var dom_obfs = opt.get("hysteria2_obfs_password"); if (dom_obfs && dom_obfs.value != "") { params += "&obfs=" + "salamander"; - params += opt.query("obfs-password", "hysteria2_obfs"); + params += opt.query("obfs-password", "hysteria2_obfs_password"); } params += opt.query("mport", "hysteria2_hop"); } else { @@ -1621,7 +1621,8 @@ local current_node = map:get(section) dom_prefix = "hysteria2_" opt.set(dom_prefix + 'auth_password', decodeURIComponent(password)); if (queryParam["obfs-password"] || queryParam["obfs_password"]) { - opt.set(dom_prefix + 'obfs', queryParam["obfs-password"] || queryParam["obfs_password"]); + opt.set(dom_prefix + 'obfs_type', "salamander"); + opt.set(dom_prefix + 'obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]); } opt.set(dom_prefix + 'hop', queryParam.mport || ""); } @@ -1678,7 +1679,7 @@ local current_node = map:get(section) } opt.set(dom_prefix + 'tuic_congestion_control', queryParam.congestion_control || 'cubic'); opt.set(dom_prefix + 'tuic_udp_relay_mode', queryParam.udp_relay_mode || 'native'); - opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'default'); + opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'h3'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_disable_sni', queryParam.disable_sni === "1"); opt.set( diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm b/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm index 09121425..115186f4 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm @@ -875,6 +875,8 @@ table td, .table .td { p = "URLTest"; } else if (protocol == "_shunt") { p = "<%:Shunt%>"; + } else if (protocol == "_iface") { + p = "<%:Interface%>"; } else if (protocol == "vmess") { p = "VMess"; } else if (protocol == "vless") { @@ -911,7 +913,11 @@ table td, .table .td { } else { port_s = o["hysteria_hop"] || o["hysteria2_hop"]; } - str += type + ":" + remarks; + if ((o.type === "Hysteria2" || o.protocol === 'hysteria2') && o.hysteria2_realms) { + str += type + " Realm:" + remarks; + } else { + str += type + ":" + remarks; + } return str; } @@ -953,7 +959,7 @@ table td, .table .td { var newDom = node_template.cloneNode(true); newDom.classList.add("cbi-rowstyle-" + (i % 2 + 1)); var innerHTML = newDom.innerHTML; - if (auto_detection_time != "icmp" && o["address"] && o["port"]) { + if (auto_detection_time != "icmp" && o["address"]) { innerHTML = innerHTML.split("{{ping}}").join('<%:Test%>'); } else { innerHTML = innerHTML.split("{{ping}}").join('---'); @@ -972,11 +978,13 @@ table td, .table .td { innerHTML = innerHTML.split("{{group}}").join(o["group"] || ""); let node_remarks = get_remarks_name(o); if (show_node_info == "1") { - if (o["address"] && o["port"]) { + let _port = o["port"] || o["hysteria_hop"] || o["hysteria2_hop"]; + if (_port) _port = _port.replace(/:/g, '-'); + if (o["address"] && _port) { let _address = o["address"] if (o["full_address"]) _address = o["full_address"] - node_remarks += "
" + _address + ":" + o["port"] + node_remarks += "
" + _address + ":" + _port } } innerHTML = innerHTML.split("{{remarks}}").join(node_remarks); diff --git a/luci-app-passwall2/po/fa/passwall2.po b/luci-app-passwall2/po/fa/passwall2.po index 36738e51..bd98dfe7 100644 --- a/luci-app-passwall2/po/fa/passwall2.po +++ b/luci-app-passwall2/po/fa/passwall2.po @@ -46,8 +46,8 @@ msgstr "لیست قوانین" msgid "Access control" msgstr "کنترل دسترسی" -msgid "Watch Logs" -msgstr "مشاهده گزارش‌ها" +msgid "Runtime Logs" +msgstr "گزارش‌های زمان اجرا" msgid "Node Config" msgstr "پیکربندی گره" @@ -437,6 +437,12 @@ msgstr "تعداد گره‌های ترجیحی" msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them." msgstr "توزیع‌کننده بار تعداد بهینه‌ای از گره‌ها را انتخاب می‌کند و ترافیک به طور تصادفی بین آن‌ها توزیع می‌شود." +msgid "Failure Tolerance (%)" +msgstr "تحمل شکست (%)" + +msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate." +msgstr "حداکثر نرخ شکست قابل قبول در تست سرعت. برای مثال، عدد ۱ به معنای مجاز بودن نرخ شکست ۱٪ است. + msgid "Shunt" msgstr "شنت (Shunt)" @@ -1782,6 +1788,9 @@ msgstr "فقط گره‌های نوع Xray یا Sing-box پشتیبانی می msgid "Chain Proxy" msgstr "پروکسی زنجیره‌ای" +msgid "Outbound Interface" +msgstr "رابط خروجی" + msgid "Landing Node" msgstr "گره فرود (Landing Node)" diff --git a/luci-app-passwall2/po/ru/passwall2.po b/luci-app-passwall2/po/ru/passwall2.po index ee82c72c..3e814ff5 100644 --- a/luci-app-passwall2/po/ru/passwall2.po +++ b/luci-app-passwall2/po/ru/passwall2.po @@ -46,8 +46,8 @@ msgstr "Список правил" msgid "Access control" msgstr "Контроль доступа" -msgid "Watch Logs" -msgstr "Просмотр журнала" +msgid "Runtime Logs" +msgstr "Журналы выполнения" msgid "Node Config" msgstr "Параметры узла" @@ -433,6 +433,12 @@ msgstr "Количество предпочтительных узлов" msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them." msgstr "Балансировщик выбирает указанное количество наилучших узлов и распределяет трафик между ними случайным образом." +msgid "Failure Tolerance (%)" +msgstr "Допуск на отказ (%)" + +msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate." +msgstr "Максимально допустимый процент отказов при проверке скорости. Например, 1 означает допустимый процент отказов в 1%." + msgid "Shunt" msgstr "Shunt (разделение трафика)" @@ -1783,6 +1789,9 @@ msgstr "Поддерживаются только узлы типа Xray или msgid "Chain Proxy" msgstr "Цепочка прокси" +msgid "Outbound Interface" +msgstr "Исходящий интерфейс" + msgid "Landing Node" msgstr "Сервер выхода" diff --git a/luci-app-passwall2/po/zh-cn/passwall2.po b/luci-app-passwall2/po/zh-cn/passwall2.po index baa0ec3e..36492fcb 100644 --- a/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/luci-app-passwall2/po/zh-cn/passwall2.po @@ -46,8 +46,8 @@ msgstr "规则列表" msgid "Access control" msgstr "访问控制" -msgid "Watch Logs" -msgstr "查看日志" +msgid "Runtime Logs" +msgstr "运行日志" msgid "Node Config" msgstr "节点配置" @@ -433,6 +433,12 @@ msgstr "优选节点数量" msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them." msgstr "负载均衡器选出最优节点的个数,流量将在这几个节点中随机分配。" +msgid "Failure Tolerance (%)" +msgstr "测速失败率容忍度(%)" + +msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate." +msgstr "最多可接受的测速失败率,例如 1 表示允许 1% 的测速失败率。" + msgid "Shunt" msgstr "分流" @@ -1768,6 +1774,9 @@ msgstr "仅支持 Xray 或 Sing-box 类型节点。" msgid "Chain Proxy" msgstr "链式代理" +msgid "Outbound Interface" +msgstr "出站接口" + msgid "Landing Node" msgstr "落地节点" diff --git a/luci-app-passwall2/po/zh-tw/passwall2.po b/luci-app-passwall2/po/zh-tw/passwall2.po index 87449b17..ab40100e 100644 --- a/luci-app-passwall2/po/zh-tw/passwall2.po +++ b/luci-app-passwall2/po/zh-tw/passwall2.po @@ -46,8 +46,8 @@ msgstr "規則列表" msgid "Access control" msgstr "訪問控制" -msgid "Watch Logs" -msgstr "查看日誌" +msgid "Runtime Logs" +msgstr "運行日誌" msgid "Node Config" msgstr "節點配置" @@ -433,6 +433,12 @@ msgstr "優選節點數量" msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them." msgstr "負載均衡器選出最優節點的個數,流量將在這几個節點中随機分配。" +msgid "Failure Tolerance (%)" +msgstr "測速失敗率容忍度(%)" + +msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate." +msgstr "最多可接受的測速失敗率,例如 1 表示允許 1% 的測速失敗率。" + msgid "Shunt" msgstr "分流" @@ -1774,6 +1780,9 @@ msgstr "僅支援 Xray 或 Sing-box 類型節點。" msgid "Chain Proxy" msgstr "鏈式代理" +msgid "Outbound Interface" +msgstr "出站接口" + msgid "Landing Node" msgstr "落地節點" diff --git a/luci-app-passwall2/root/etc/hotplug.d/iface/98-passwall2 b/luci-app-passwall2/root/etc/hotplug.d/iface/98-passwall2 index 06921225..f80354d1 100644 --- a/luci-app-passwall2/root/etc/hotplug.d/iface/98-passwall2 +++ b/luci-app-passwall2/root/etc/hotplug.d/iface/98-passwall2 @@ -12,7 +12,7 @@ if [ "$ACTION" = "ifupdate" ]; then USE_TABLES=$(get_cache_var "USE_TABLES") - [ -n "$USE_TABLES" ] && ${APP_PATH}/${USE_TABLES}.sh update_wan_sets >/dev/null 2>&1 & + [ -n "$USE_TABLES" ] && { ${APP_PATH}/${USE_TABLES}.sh update_wan_sets >/dev/null 2>&1 & } exit 0 fi diff --git a/luci-app-passwall2/root/usr/share/passwall2/app.sh b/luci-app-passwall2/root/usr/share/passwall2/app.sh index dbe5234a..75dff526 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -84,7 +84,7 @@ run_xray() { json_add_string "loglevel" "${loglevel}" [ -n "$flag" ] && { - pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1 + busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1 json_add_string "flag" "${flag}" } [ -n "$socks_address" ] && [ -n "$socks_port" ] && { @@ -112,12 +112,12 @@ run_xray() { local direct_ipset_conf=${GLOBAL_ACL_PATH}/dns_${flag}_direct.conf [ -n "$(echo ${flag} | grep '^acl')" ] && direct_ipset_conf=${TMP_ACL_PATH}/${sid}/dns_${flag}_direct.conf if [ "${nftflag}" = "1" ]; then - local direct_nftset4="passwall2_${node}_white" - local direct_nftset6="passwall2_${node}_white6" + local direct_nftset4="psw2_${node}_white" + local direct_nftset6="psw2_${node}_white6" local direct_nftset="4#inet#passwall2#${direct_nftset4},6#inet#passwall2#${direct_nftset6}" else - local direct_ipset4="passwall2_${node}_white" - local direct_ipset6="passwall2_${node}_white6" + local direct_ipset4="psw2_${node}_white" + local direct_ipset6="psw2_${node}_white6" local direct_ipset="${direct_ipset4},${direct_ipset6}" fi run_ipset_dns_server listen_port=${direct_dnsmasq_listen_port} server_dns=${AUTO_DNS} ipset="${direct_ipset}" nftset="${direct_nftset}" config_file=${direct_ipset_conf} @@ -225,7 +225,7 @@ run_singbox() { json_add_string "loglevel" "${loglevel}" [ -n "$flag" ] && { - pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1 + busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1 json_add_string "flag" "${flag}" } [ -n "$socks_address" ] && [ -n "$socks_port" ] && { @@ -251,12 +251,12 @@ run_singbox() { local direct_ipset_conf=${GLOBAL_ACL_PATH}/dns_${flag}_direct.conf [ -n "$(echo ${flag} | grep '^acl')" ] && direct_ipset_conf=${TMP_ACL_PATH}/${sid}/dns_${flag}_direct.conf if [ "${nftflag}" = "1" ]; then - local direct_nftset4="passwall2_${node}_white" - local direct_nftset6="passwall2_${node}_white6" + local direct_nftset4="psw2_${node}_white" + local direct_nftset6="psw2_${node}_white6" local direct_nftset="4#inet#passwall2#${direct_nftset4},6#inet#passwall2#${direct_nftset6}" else - local direct_ipset4="passwall2_${node}_white" - local direct_ipset6="passwall2_${node}_white6" + local direct_ipset4="psw2_${node}_white" + local direct_ipset6="psw2_${node}_white6" local direct_ipset="${direct_ipset4},${direct_ipset6}" fi run_ipset_dns_server listen_port=${direct_dnsmasq_listen_port} server_dns=${AUTO_DNS} ipset="${direct_ipset}" nftset="${direct_nftset}" config_file=${direct_ipset_conf} @@ -386,6 +386,10 @@ run_socks() { fi fi + if [ -n "${error_msg}" ] && ([ -n "$(config_n_get $node hysteria_hop)" ] || [ -n "$(config_n_get $node hysteria2_hop)" ] || [ "$(config_n_get $node hysteria2_realms)" = "1" ]); then + unset error_msg + fi + [ -n "${error_msg}" ] && { [ "$bind" != "127.0.0.1" ] && log 1 "$(i18n "Socks node: [%s]%s, start failed %s:%s %s" "${remarks}" "${tmp}" "${bind}" "${socks_port}" "${error_msg}")" return 1 @@ -555,7 +559,7 @@ socks_node_switch() { [ -s "$pf" ] && kill -9 "$(head -n1 "$pf")" >/dev/null 2>&1 done - pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1 && !/acl\/|acl_/{print $1}' | xargs kill -9 >/dev/null 2>&1 + busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1 && !/acl\/|acl_/{print $1}' | xargs kill -9 >/dev/null 2>&1 for prefix in "" "HTTP_" "HTTP2"; do rm -rf "$TMP_PATH/${prefix}SOCKS_${flag}"* done @@ -791,7 +795,7 @@ start_socks() { # Auto switch logic local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) - [ "$enable_autoswitch" = "1" ] && $APP_PATH/socks_auto_switch.sh ${id} > /dev/null 2>&1 & + [ "$enable_autoswitch" = "1" ] && { $APP_PATH/socks_auto_switch.sh ${id} > /dev/null 2>&1 & } done } } @@ -805,14 +809,14 @@ clean_crontab() { sed -i "/$(echo "lua ${APP_PATH}/rule_update.lua log" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1 sed -i "/$(echo "lua ${APP_PATH}/subscribe.lua start" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1 - pgrep -af "${CONFIG}/" | awk '/tasks\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 + busybox pgrep -af "${CONFIG}/" | awk '/tasks\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 rm -rf /tmp/lock/${CONFIG}_tasks.lock } start_crontab() { if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then start_daemon=$(config_t_get global_delay start_daemon 0) - [ "$start_daemon" = "1" ] && $APP_PATH/monitor.sh > /dev/null 2>&1 & + [ "$start_daemon" = "1" ] && { $APP_PATH/monitor.sh > /dev/null 2>&1 & } fi [ -f "/tmp/lock/${CONFIG}_cron.lock" ] && { @@ -982,11 +986,11 @@ run_ipset_chinadns_ng() { [ -n "${ipset}" ] && { set_names=$ipset - vps_set_names="passwall2_vps,passwall2_vps6" + vps_set_names="psw2_vps,psw2_vps6" } [ -n "${nftset}" ] && { set_names=$(echo ${nftset} | awk -F, '{printf "%s,%s", substr($1,3), substr($2,3)}' | sed 's/#/@/g') - vps_set_names="inet@passwall2@passwall2_vps,inet@passwall2@passwall2_vps6" + vps_set_names="inet@passwall2@psw2_vps,inet@passwall2@psw2_vps6" } cat <<-EOF > $config_file bind-addr 127.0.0.1 @@ -1162,7 +1166,7 @@ acl_app() { } start() { - pgrep -f /tmp/etc/passwall2/bin > /dev/null 2>&1 && { + busybox pgrep -f /tmp/etc/passwall2/bin > /dev/null 2>&1 && { #log_i18n 0 "The program has started. Please stop it and then restart it!" stop } @@ -1241,8 +1245,8 @@ stop() { kill -9 "$pid" >/dev/null 2>&1 fi done - pgrep -f "sleep.*(6s|9s|58s)" | xargs kill -9 >/dev/null 2>&1 - pgrep -af "${CONFIG}/" | awk '! /app\.sh|subscribe\.lua|rule_update\.lua|tasks\.sh|server_app\.lua|ujail/{print $1}' | xargs kill -9 >/dev/null 2>&1 + busybox pgrep -f "sleep.*(6s|9s|58s)" | xargs kill -9 >/dev/null 2>&1 + busybox pgrep -af "${CONFIG}/" | awk '! /app\.sh|subscribe\.lua|rule_update\.lua|tasks\.sh|server_app\.lua|ujail/{print $1}' | xargs kill -9 >/dev/null 2>&1 unset V2RAY_LOCATION_ASSET unset XRAY_LOCATION_ASSET unset SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN diff --git a/luci-app-passwall2/root/usr/share/passwall2/haproxy_check.sh b/luci-app-passwall2/root/usr/share/passwall2/haproxy_check.sh index 79376d69..106b4cf0 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/haproxy_check.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/haproxy_check.sh @@ -8,7 +8,8 @@ listen_port=$2 server_address=$3 server_port=$4 -pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null && { +busybox pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null && { + # No detection during specific task execution exit 0 } diff --git a/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua b/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua index 44fa7fd8..5ddbb744 100644 --- a/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua +++ b/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua @@ -274,7 +274,7 @@ function add_rule(var) if address == "engage.cloudflareclient.com" then return end if datatypes.hostname(address) then set_domain_dns(address, fwd_dns) - set_domain_ipset(address, setflag_4 .. "passwall2_vps," .. setflag_6 .. "passwall2_vps6") + set_domain_ipset(address, setflag_4 .. "psw2_vps," .. setflag_6 .. "psw2_vps6") end end process_address(t.address) diff --git a/luci-app-passwall2/root/usr/share/passwall2/iptables.sh b/luci-app-passwall2/root/usr/share/passwall2/iptables.sh index 160318a0..61318230 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/iptables.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/iptables.sh @@ -3,17 +3,17 @@ DIR="$(cd "$(dirname "$0")" && pwd)" MY_PATH=$DIR/iptables.sh UTILS_PATH=$DIR/utils.sh -IPSET_LOCAL="passwall2_local" -IPSET_PROXY_LAN="passwall2_proxy_lan" -IPSET_LAN="passwall2_lan" -IPSET_VPS="passwall2_vps" -IPSET_WAN="passwall2_wan" +IPSET_LOCAL="psw2_local" +IPSET_PROXY_LAN="psw2_proxy_lan" +IPSET_LAN="psw2_lan" +IPSET_VPS="psw2_vps" +IPSET_WAN="psw2_wan" -IPSET_LOCAL6="passwall2_local6" -IPSET_PROXY_LAN6="passwall2_proxy_lan6" -IPSET_LAN6="passwall2_lan6" -IPSET_VPS6="passwall2_vps6" -IPSET_WAN6="passwall2_wan6" +IPSET_LOCAL6="psw2_local6" +IPSET_PROXY_LAN6="psw2_proxy_lan6" +IPSET_LAN6="psw2_lan6" +IPSET_VPS6="psw2_vps6" +IPSET_WAN6="psw2_wan6" FWMARK="0x50535732" @@ -194,8 +194,8 @@ gen_shunt_list() { for shunt_id in $shunt_ids; do local shunt_node=$(config_n_get ${node} "${shunt_id}") [ -n "$shunt_node" ] && { - local ipset_v4="passwall2_${node}_${shunt_id}" - local ipset_v6="passwall2_${node}_${shunt_id}6" + local ipset_v4="psw2_${node}_${shunt_id}" + local ipset_v6="psw2_${node}_${shunt_id}6" ipset -! create $ipset_v4 nethash maxelem 1048576 ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576 local outbound="redirect" @@ -219,22 +219,14 @@ gen_shunt_list() { } local direct_ipset4=$(get_cache_var "node_${node}_direct_ipset4") [ -n "${direct_ipset4}" ] && { - ipset -! create ${direct_ipset4} nethash maxelem 1048576 timeout 259200 + ipset -! create ${direct_ipset4} iphash maxelem 1048576 timeout 259200 _SHUNT_LIST4="${_SHUNT_LIST4} ${direct_ipset4}:direct" } local direct_ipset6=$(get_cache_var "node_${node}_direct_ipset6") [ -n "${direct_ipset6}" ] && { - ipset -! create ${direct_ipset6} nethash family inet6 maxelem 1048576 timeout 259200 + ipset -! create ${direct_ipset6} iphash family inet6 maxelem 1048576 timeout 259200 _SHUNT_LIST6="${_SHUNT_LIST6} ${direct_ipset6}:direct" } - [ "${preloading}" = "1" ] && [ -n "$default_node" ] && { - local ipset_v4="passwall2_${node}_default" - local ipset_v6="passwall2_${node}_default6" - ipset -! create $ipset_v4 nethash maxelem 1048576 - ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576 - _SHUNT_LIST4="${_SHUNT_LIST4} ${ipset_v4}:${default_outbound}" - _SHUNT_LIST6="${_SHUNT_LIST6} ${ipset_v6}:${default_outbound}" - } } [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" @@ -618,6 +610,8 @@ filter_direct_node_list() { } update_wan_sets() { + [ -z "$(command -v get_wan_ips)" ] && . "$UTILS_PATH" + local WAN_IP=$(get_wan_ips ip4) [ -n "$WAN_IP" ] && { ipset -F "$IPSET_WAN" @@ -641,13 +635,13 @@ add_firewall_rule() { ipset -! create $IPSET_LOCAL nethash maxelem 1048576 ipset -! create $IPSET_PROXY_LAN nethash maxelem 1048576 ipset -! create $IPSET_LAN nethash maxelem 1048576 - ipset -! create $IPSET_VPS nethash maxelem 1048576 + ipset -! create $IPSET_VPS iphash maxelem 1048576 ipset -! create $IPSET_WAN nethash maxelem 1048576 ipset -! create $IPSET_LOCAL6 nethash family inet6 maxelem 1048576 ipset -! create $IPSET_PROXY_LAN6 nethash family inet6 maxelem 1048576 ipset -! create $IPSET_LAN6 nethash family inet6 maxelem 1048576 - ipset -! create $IPSET_VPS6 nethash family inet6 maxelem 1048576 + ipset -! create $IPSET_VPS6 iphash family inet6 maxelem 1048576 ipset -! create $IPSET_WAN6 nethash family inet6 maxelem 1048576 get_local_ips ip4 | sed "s/^/add $IPSET_LOCAL /" | ipset -! -R @@ -1025,7 +1019,7 @@ del_firewall_rule() { flush_ipset() { log_i18n 0 "Clear %s." "IPSet" - for _name in $(ipset list | grep "Name: " | grep "passwall2_" | awk '{print $2}'); do + for _name in $(ipset list | grep "Name: " | grep "psw2_" | awk '{print $2}'); do destroy_ipset ${_name} done } @@ -1105,7 +1099,7 @@ start() { } stop() { - [ -z "$(command -v log_i18n)" ] && . /usr/share/passwall2/utils.sh + [ -z "$(command -v log_i18n)" ] && . "$UTILS_PATH" del_firewall_rule destroy_ipset $IPSET_PROXY_LAN destroy_ipset $IPSET_PROXY_LAN6 diff --git a/luci-app-passwall2/root/usr/share/passwall2/monitor.sh b/luci-app-passwall2/root/usr/share/passwall2/monitor.sh index 80e61cae..e072465a 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/monitor.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/monitor.sh @@ -18,7 +18,7 @@ while [ "$ENABLED" -eq 1 ]; do for filename in $(ls ${TMP_SCRIPT_FUNC_PATH} | grep -v "^_"); do cmd=$(cat ${TMP_SCRIPT_FUNC_PATH}/${filename}) cmd_check=$(echo $cmd | awk -F '>' '{print $1}') - icount=$(pgrep -f "$(echo $cmd_check)" | wc -l) + icount=$(busybox pgrep -f "$(echo $cmd_check)" | wc -l) if [ $icount = 0 ]; then #echo "${cmd} crashed, restarting." >> /tmp/log/passwall2.log eval $(echo "nohup ${cmd} 2>&1 &") >/dev/null 2>&1 & diff --git a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh index f0a11ce1..be3146a8 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh @@ -4,17 +4,17 @@ DIR="$(cd "$(dirname "$0")" && pwd)" MY_PATH=$DIR/nftables.sh UTILS_PATH=$DIR/utils.sh NFTABLE_NAME="inet passwall2" -NFTSET_LOCAL="passwall2_local" -NFTSET_PROXY_LAN="passwall2_proxy_lan" -NFTSET_LAN="passwall2_lan" -NFTSET_VPS="passwall2_vps" -NFTSET_WAN="passwall2_wan" +NFTSET_LOCAL="psw2_local" +NFTSET_PROXY_LAN="psw2_proxy_lan" +NFTSET_LAN="psw2_lan" +NFTSET_VPS="psw2_vps" +NFTSET_WAN="psw2_wan" -NFTSET_LOCAL6="passwall2_local6" -NFTSET_PROXY_LAN6="passwall2_proxy_lan6" -NFTSET_LAN6="passwall2_lan6" -NFTSET_VPS6="passwall2_vps6" -NFTSET_WAN6="passwall2_wan6" +NFTSET_LOCAL6="psw2_local6" +NFTSET_PROXY_LAN6="psw2_proxy_lan6" +NFTSET_LAN6="psw2_lan6" +NFTSET_VPS6="psw2_vps6" +NFTSET_WAN6="psw2_wan6" FWMARK="0x50535732" @@ -231,8 +231,8 @@ gen_shunt_list() { for shunt_id in $shunt_ids; do local shunt_node=$(config_n_get ${node} "${shunt_id}") [ -n "$shunt_node" ] && { - local nftset_v4="passwall2_${node}_${shunt_id}" - local nftset_v6="passwall2_${node}_${shunt_id}6" + local nftset_v4="psw2_${node}_${shunt_id}" + local nftset_v6="psw2_${node}_${shunt_id}6" gen_nftset $nftset_v4 ipv4_addr 0 0 gen_nftset $nftset_v6 ipv6_addr 0 0 local outbound="redirect" @@ -263,14 +263,6 @@ gen_shunt_list() { gen_nftset $direct_nftset6 ipv6_addr 0 0 _SHUNT_LIST6="${_SHUNT_LIST6} ${direct_nftset6}:direct" } - [ "${preloading}" = "1" ] && [ -n "$default_node" ] && { - local nftset_v4="passwall2_${node}_default" - local nftset_v6="passwall2_${node}_default6" - gen_nftset $nftset_v4 ipv4_addr 0 0 - gen_nftset $nftset_v6 ipv6_addr 0 0 - _SHUNT_LIST4="${_SHUNT_LIST4} ${nftset_v4}:${default_outbound}" - _SHUNT_LIST6="${_SHUNT_LIST6} ${nftset_v6}:${default_outbound}" - } } [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" @@ -681,6 +673,8 @@ mwan3_start() { } update_wan_sets() { + [ -z "$(command -v get_wan_ips)" ] && . "$UTILS_PATH" + local WAN_IP=$(get_wan_ips ip4) [ -n "$WAN_IP" ] && { nft flush set $NFTABLE_NAME $NFTSET_WAN @@ -1073,7 +1067,7 @@ del_firewall_rule() { flush_nftset() { log_i18n 0 "Clear %s." "NFTSet" - for _name in $(nft -a list sets | grep -E "passwall2_" | awk -F 'set ' '{print $2}' | awk '{print $1}'); do + for _name in $(nft -a list sets | grep -E "psw2_" | awk -F 'set ' '{print $2}' | awk '{print $1}'); do destroy_nftset ${_name} done } @@ -1116,7 +1110,7 @@ start() { } stop() { - [ -z "$(command -v log_i18n)" ] && . /usr/share/passwall2/utils.sh + [ -z "$(command -v log_i18n)" ] && . "$UTILS_PATH" del_firewall_rule destroy_nftset $NFTSET_PROXY_LAN destroy_nftset $NFTSET_PROXY_LAN6 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 b009002b..310a2070 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 @@ -6,7 +6,7 @@ APP_FILE=${APP_PATH}/app.sh flag=0 check_process() { - while pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null; do + while busybox pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null; do sleep 6s done } @@ -63,7 +63,7 @@ test_node() { # Kill the SS plugin process local pid_file="/tmp/etc/${CONFIG}/test_node_${node_id}_plugin.pid" [ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1 - pgrep -af "test_node_${node_id}" | awk '! /socks_auto_switch\.sh/{print $1}' | xargs kill -9 >/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}*.* if [ "${_proxy_status}" -eq 200 ]; then return 0 diff --git a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index ab9aa6e5..a1dd677b 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -1688,22 +1688,19 @@ local function processData(szType, content, add_mode, group, sub_cfg) local insecure = params.allowinsecure or params.insecure result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") result.hysteria2_hop = params.mport + if params["obfs-password"] or params["obfs_password"] then + result.hysteria2_obfs_type = "salamander" + result.hysteria2_obfs_password = params["obfs-password"] or params["obfs_password"] + end if (sub_hysteria2_type == "sing-box" and has_singbox) or (sub_hysteria2_type == "xray" and has_xray) then local is_singbox = sub_hysteria2_type == "sing-box" and has_singbox result.type = is_singbox and 'sing-box' or 'Xray' result.protocol = "hysteria2" - if params["obfs-password"] or params["obfs_password"] then - result.hysteria2_obfs_type = "salamander" - result.hysteria2_obfs_password = params["obfs-password"] or params["obfs_password"] - end result.use_finalmask = (params.fm and params.fm ~= "") and "1" or nil result.finalmask = (params.fm and params.fm ~= "") and api.base64Encode(params.fm) or nil elseif has_hysteria2 then result.type = "Hysteria2" - if params["obfs-password"] or params["obfs_password"] then - result.hysteria2_obfs = params["obfs-password"] or params["obfs_password"] - end else log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "Hysteria2", "Hysteria2")) return nil @@ -1761,7 +1758,7 @@ local function processData(szType, content, add_mode, group, sub_cfg) end result.tls_serverName = params.sni result.tls_disable_sni = params.disable_sni - result.tuic_alpn = params.alpn or "default" + result.tuic_alpn = params.alpn or "h3" result.tuic_congestion_control = params.congestion_control or "cubic" result.tuic_udp_relay_mode = params.udp_relay_mode or "native" local insecure = params.allowinsecure or params.insecure or params.allow_insecure @@ -2049,12 +2046,12 @@ local function select_node(nodes, config, parentConfig) end end end - -- First priority: Type + Notes + IP + Port + -- First priority: Type + Notes + IP + Port + Group if not server then for index, node in pairs(nodes) do if config.currentNode.type and config.currentNode.remarks and config.currentNode.address and config.currentNode.port then if node.type and node.remarks and node.address and node.port then - if node.type == config.currentNode.type and node.remarks == config.currentNode.remarks and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) then + if node.type == config.currentNode.type and node.remarks == config.currentNode.remarks and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) and node.group == config.currentNode.group then if config.log == nil or config.log == true then log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("First Matching node:") .. " " .. node.remarks) end @@ -2065,12 +2062,12 @@ local function select_node(nodes, config, parentConfig) end end end - -- Second priority: Type + IP + Port + -- Second priority: Type + IP + Port + Group if not server then for index, node in pairs(nodes) do if config.currentNode.type and config.currentNode.address and config.currentNode.port then if node.type and node.address and node.port then - if node.type == config.currentNode.type and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) then + if node.type == config.currentNode.type and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) and node.group == config.currentNode.group then if config.log == nil or config.log == true then log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Second Matching node:") .. " " .. node.remarks) end @@ -2081,12 +2078,12 @@ local function select_node(nodes, config, parentConfig) end end end - -- Third priority: IP + Port + -- Third priority: IP + Port + Group if not server then for index, node in pairs(nodes) do if config.currentNode.address and config.currentNode.port then if node.address and node.port then - if node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port then + if node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port and node.group == config.currentNode.group then if config.log == nil or config.log == true then log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Third Matching node:") .. " " .. node.remarks) end @@ -2097,12 +2094,12 @@ local function select_node(nodes, config, parentConfig) end end end - -- Fourth priority: IP + -- Fourth priority: IP + Group if not server then for index, node in pairs(nodes) do if config.currentNode.address then if node.address then - if node.address == config.currentNode.address then + if node.address == config.currentNode.address and node.group == config.currentNode.group then if config.log == nil or config.log == true then log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Fourth Matching node:") .. " " .. node.remarks) end @@ -2113,12 +2110,12 @@ local function select_node(nodes, config, parentConfig) end end end - -- Fifth priority: remarks + -- Fifth priority: remarks + Group if not server then for index, node in pairs(nodes) do if config.currentNode.remarks then if node.remarks then - if node.remarks == config.currentNode.remarks then + if node.remarks == config.currentNode.remarks and node.group == config.currentNode.group then if config.log == nil or config.log == true then log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Fifth Matching node:") .. " " .. node.remarks) end diff --git a/luci-app-passwall2/root/usr/share/passwall2/tasks.sh b/luci-app-passwall2/root/usr/share/passwall2/tasks.sh index 56b1f143..90d14512 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/tasks.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/tasks.sh @@ -22,7 +22,7 @@ do stop_interval_mode=$(expr "$stop_interval_mode" \* 60) if [ -n "$stop_week_mode" ]; then [ "$stop_week_mode" = "8" ] && { - [ "$(expr "$CFG_UPDATE_INT" % "$stop_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG stop > /dev/null 2>&1 & + [ "$(expr "$CFG_UPDATE_INT" % "$stop_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG stop > /dev/null 2>&1 & } } fi @@ -31,7 +31,7 @@ do start_interval_mode=$(expr "$start_interval_mode" \* 60) if [ -n "$start_week_mode" ]; then [ "$start_week_mode" = "8" ] && { - [ "$(expr "$CFG_UPDATE_INT" % "$start_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG start > /dev/null 2>&1 & + [ "$(expr "$CFG_UPDATE_INT" % "$start_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG start > /dev/null 2>&1 & } } fi @@ -40,7 +40,7 @@ do restart_interval_mode=$(expr "$restart_interval_mode" \* 60) if [ -n "$restart_week_mode" ]; then [ "$restart_week_mode" = "8" ] && { - [ "$(expr "$CFG_UPDATE_INT" % "$restart_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG restart > /dev/null 2>&1 & + [ "$(expr "$CFG_UPDATE_INT" % "$restart_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG restart > /dev/null 2>&1 & } } fi @@ -50,7 +50,7 @@ do hourupdate=$(expr "$hourupdate" \* 60) if [ "$autoupdate" = "1" ]; then [ "$weekupdate" = "8" ] && { - [ "$(expr "$CFG_UPDATE_INT" % "$hourupdate")" -eq 0 ] && lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 & + [ "$(expr "$CFG_UPDATE_INT" % "$hourupdate")" -eq 0 ] && { lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 & } } fi @@ -73,7 +73,7 @@ do hour_update=$(expr "$hour_update" \* 60) cfgids=$(echo -n $(cat ${TMP_SUB_PATH}/${name}) | sed 's# #,#g') [ "$week_update" = "8" ] && { - [ "$(expr "$CFG_UPDATE_INT" % "$hour_update")" -eq 0 ] && lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 & + [ "$(expr "$CFG_UPDATE_INT" % "$hour_update")" -eq 0 ] && { lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 & } } done diff --git a/luci-app-passwall2/root/usr/share/passwall2/test.sh b/luci-app-passwall2/root/usr/share/passwall2/test.sh index f83f4a24..cd1084e9 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/test.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/test.sh @@ -50,10 +50,13 @@ url_test_node() { NO_REC_PROCESS=1 /usr/share/${CONFIG}/app.sh run_socks flag="url_test_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=url_test_${node_id}.json sleep 2s local curlx="socks5h://127.0.0.1:${_tmp_port}" - local url=$(config_t_get global_other url_test_url https://www.google.com/generate_204) - result=$(curl --connect-timeout 3 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" -x $curlx "${url}") - 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}*.json + 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" + [ -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}*.* } echo $result } diff --git a/luci-app-passwall2/root/usr/share/passwall2/utils.sh b/luci-app-passwall2/root/usr/share/passwall2/utils.sh index 0770d326..b345c7ee 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/utils.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/utils.sh @@ -412,7 +412,7 @@ run_process_queue() { for filename in $(ls ${TMP_PROCESS_LIST_PATH}); do cmd=$(cat ${TMP_PROCESS_LIST_PATH}/${filename}) cmd_check=$(echo $cmd | awk -F '>' '{print $1}') - icount=$(pgrep -f "$(echo $cmd_check)" | wc -l) + icount=$(busybox pgrep -f "$(echo $cmd_check)" | wc -l) if [ $icount = 0 ]; then eval $(echo "nohup ${cmd} 2>&1 &") >/dev/null 2>&1 & fi diff --git a/luci-app-xray/Makefile b/luci-app-xray/Makefile index a1ece2d5..b7aaffa3 100644 --- a/luci-app-xray/Makefile +++ b/luci-app-xray/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-xray PKG_VERSION:=3.7.1 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_LICENSE:=MPLv2 PKG_LICENSE_FILES:=LICENSE diff --git a/luci-app-xray/root/usr/share/xray/gen_config.uc b/luci-app-xray/root/usr/share/xray/gen_config.uc index 98fd47cd..3e214391 100644 --- a/luci-app-xray/root/usr/share/xray/gen_config.uc +++ b/luci-app-xray/root/usr/share/xray/gen_config.uc @@ -261,7 +261,7 @@ function gen_config() { const general = filter(values(config), k => k[".type"] == "general")[0] || {}; const custom_configuration_hook = loadstring(general["custom_configuration_hook"] || "return i => i;")(); - return custom_configuration_hook({ + let result = { inbounds: inbounds(general, config, extra_inbound), outbounds: outbounds(general, config, manual_tproxy, bridge, extra_inbound, fakedns), dns: dns_conf(general, config, manual_tproxy, fakedns), @@ -274,15 +274,19 @@ function gen_config() { place: "holder" } : null, observatory: observatory(general, manual_tproxy), - reverse: { - bridges: bridges(bridge) - }, routing: { domainStrategy: general["routing_domain_strategy"] || "AsIs", rules: rules(general, bridge, manual_tproxy, extra_inbound, fakedns), balancers: balancers(general, extra_inbound, fakedns) } - }); + }; + const bridges_deprecated = bridges(bridge); + if (length(bridges_deprecated) > 0) { + result["reverse"] = { + bridges: bridges_deprecated + }; + }; + return custom_configuration_hook(result); } printf("%.4J", gen_config()); diff --git a/luci-theme-routerich/htdocs/luci-static/resources/menu-routerich.js b/luci-theme-routerich/htdocs/luci-static/resources/menu-routerich.js index 33240f97..3c7d2c92 100644 --- a/luci-theme-routerich/htdocs/luci-static/resources/menu-routerich.js +++ b/luci-theme-routerich/htdocs/luci-static/resources/menu-routerich.js @@ -1,17 +1,176 @@ -'use strict';'require baseclass';'require ui';return baseclass.extend({__init__:function(){ui.menu.load().then(L.bind(this.render,this));},render:function(tree){var node=tree,url='',children=ui.menu.getChildren(tree);for(var i=0;i=3){for(var i=0;i<3&&node;i++){node=node.children[L.env.dispatchpath[i]];url=url+(url?'/':'')+L.env.dispatchpath[i];} -if(node) -this.renderTabMenu(node,url);} -document.querySelector('a.showSide').addEventListener('click',ui.createHandlerFn(this,'handleSidebarToggle'));document.querySelector('.darkMask').addEventListener('click',ui.createHandlerFn(this,'handleSidebarToggle'));},handleMenuExpand:function(ev){var a=ev.target,slide=a.parentNode,slide_menu=a.nextElementSibling;var collapse=false;document.querySelectorAll('.main .main-left .nav > li >ul.active').forEach(function(ul){$(ul).stop(true).slideUp("fast",function(){ul.classList.remove('active');ul.previousElementSibling.classList.remove('active');});if(!collapse&&ul===slide_menu){collapse=true;}});if(!slide_menu) -return;if(!collapse){$(slide).find(".slide-menu").slideDown("fast",function(){slide_menu.classList.add('active');a.classList.add('active');});a.blur();} -ev.preventDefault();ev.stopPropagation();},renderMainMenu:function(tree,url,level){var l=(level||0)+1,ul=E('ul',{'class':level?'slide-menu':'nav'}),children=ui.menu.getChildren(tree);if(children.length==0||l>2) -return E([]);for(var i=0;i= 3) { + for (var i = 0; i < 3 && node; i++) { + node = node.children[L.env.dispatchpath[i]]; + url = url + (url ? '/' : '') + L.env.dispatchpath[i]; + } + if (node) this.renderTabMenu(node, url); + } + + document + .querySelector('a.showSide') + .addEventListener('click', ui.createHandlerFn(this, 'handleSidebarToggle')); + document + .querySelector('.darkMask') + .addEventListener('click', ui.createHandlerFn(this, 'handleSidebarToggle')); + }, + + handleMenuExpand: function (ev) { + var a = ev.target, + slide = a.parentNode, + slide_menu = a.nextElementSibling; + var collapse = false; + + document + .querySelectorAll('.main .main-left .nav > li >ul.active') + .forEach(function (ul) { + $(ul).stop(true).slideUp('fast', function () { + ul.classList.remove('active'); + ul.previousElementSibling.classList.remove('active'); + }); + if (!collapse && ul === slide_menu) { + collapse = true; + } + }); + + if (!slide_menu) return; + + if (!collapse) { + $(slide) + .find('.slide-menu') + .slideDown('fast', function () { + slide_menu.classList.add('active'); + a.classList.add('active'); + }); + a.blur(); + } + + ev.preventDefault(); + ev.stopPropagation(); + }, + + renderMainMenu: function (tree, url, level) { + var l = (level || 0) + 1, + ul = E('ul', { class: level ? 'slide-menu' : 'nav' }), + children = ui.menu.getChildren(tree); + + if (children.length == 0 || l > 2) return E([]); + + for (var i = 0; i < children.length; i++) { + var isActive = + L.env.dispatchpath[l] == children[i].name && + L.env.dispatchpath[l - 1] == tree.name, + submenu = this.renderMainMenu(children[i], url + '/' + children[i].name, l), + hasChildren = submenu.children.length, + slideClass = hasChildren ? 'slide' : null, + menuClass = hasChildren ? 'menu' : 'food'; + + if (isActive) { + ul.classList.add('active'); + slideClass += ' active'; + menuClass += ' active'; + } + + ul.appendChild( + E( + 'li', + { class: slideClass }, + [ + E( + 'a', + { + href: L.url(url, children[i].name), + click: l == 1 ? ui.createHandlerFn(this, 'handleMenuExpand') : null, + class: menuClass, + 'data-title': hasChildren + ? children[i].title.replace(' ', '_') + : children[i].title.replace(' ', '_'), + }, + [_(children[i].title)] + ), + submenu, + ] + ) + ); + } + + if (l == 1) { + document.querySelector('#mainmenu').appendChild(ul); + document.querySelector('#mainmenu').style.display = ''; + } + + return ul; + }, + + renderTabMenu: function (tree, url, level) { + var container = document.querySelector('#tabmenu'), + l = (level || 0) + 1, + ul = E('ul', { class: 'tabs' }), + children = ui.menu.getChildren(tree), + activeNode = null; + + if (children.length == 0) return E([]); + + for (var i = 0; i < children.length; i++) { + var isActive = L.env.dispatchpath[l + 2] == children[i].name, + activeClass = isActive ? ' active' : '', + className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass); + + ul.appendChild( + E('li', { class: className }, [ + E('a', { href: L.url(url, children[i].name) }, [_(children[i].title)]), + ]) + ); + + if (isActive) activeNode = children[i]; + } + + container.appendChild(ul); + container.style.display = ''; + + if (activeNode) + container.appendChild(this.renderTabMenu(activeNode, url + '/' + activeNode.name, l)); + + return ul; + }, + + handleSidebarToggle: function (ev) { + var showside = document.querySelector('a.showSide'), + sidebar = document.querySelector('#mainmenu'), + darkmask = document.querySelector('.darkMask'), + scrollbar = document.querySelector('.main-right'); + + if (showside.classList.contains('active')) { + showside.classList.remove('active'); + sidebar.classList.remove('active'); + scrollbar.classList.remove('active'); + darkmask.classList.remove('active'); + } else { + showside.classList.add('active'); + sidebar.classList.add('active'); + scrollbar.classList.add('active'); + darkmask.classList.add('active'); + } + }, +}); \ No newline at end of file diff --git a/luci-theme-routerich/htdocs/luci-static/routerich/css/cascade.css b/luci-theme-routerich/htdocs/luci-static/routerich/css/cascade.css index 4a98860f..6acc1082 100644 --- a/luci-theme-routerich/htdocs/luci-static/routerich/css/cascade.css +++ b/luci-theme-routerich/htdocs/luci-static/routerich/css/cascade.css @@ -3,7 +3,4836 @@ Pure v2.0.3 Copyright 2013 Yahoo! Licensed under the BSD License. https://github.com/pure-css/pure/blob/master/LICENSE.md -*//*! +*/ /*! normalize.css v | MIT License | git.io/normalize Copyright (c) Nicolas Gallagher and Jonathan Neal -*//*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none !important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-0.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-0.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-0.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-0.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(40%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.1)));background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,0.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width:480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@font-face{font-family:'Google Sans';src:url('data:application/font-woff2;charset=utf-8;base64,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') format('woff2'),url('data:application/font-woff;charset=utf-8;base64,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') format('woff');font-weight:normal;font-style:normal}@font-face{font-family:'TypoGraphica';src:url('../fonts/TypoGraphica.eot?#iefix') format('embedded-opentype'),url('../fonts/TypoGraphica.woff') format('woff'),url('../fonts/TypoGraphica.ttf') format('truetype'),url('../fonts/TypoGraphica.svg#TypoGraphica') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'argon';src:url('../fonts/argon.eot?u6kthm');src:url('../fonts/argon.eot?u6kthm#iefix') format('embedded-opentype'),url('../fonts/argon.ttf?u6kthm') format('truetype'),url('../fonts/argon.woff?u6kthm') format('woff'),url('../fonts/argon.svg?u6kthm#argon') format('svg');font-weight:normal;font-style:normal;font-display:block}[class^="icon-"],[class*=" icon-"]{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-expand_more:before{content:"\e20b"}.icon-menu:before{content:"\e20e"}.icon-favorite:before{content:"\e291"}.icon-spinner:before{content:"\e603"}.icon-delete:before{content:"\e900"}.icon-edit:before{content:"\e901"}.icon-use:before{content:"\e902"}.icon-loading:before{content:"\e903"}.icon-switch:before{content:"\e904"}.icon-error:before{content:"\e905"}.icon-dashboard:before{content:"\e906"}.icon-logout:before{content:"\e907"}.icon-Network:before{content:"\e908"}.icon-services:before{content:"\e909"}.icon-system:before{content:"\e90a"}.icon-vpn:before{content:"\e90b"}.icon-storage:before{content:"\e90c"}.icon-statistics:before{content:"\e90d"}.icon-hello-world:before{content:"\e90e"}.icon-angle-right:before{content:"\e90f"}.icon-password:before{content:"\e910"}.icon-user:before{content:"\e971"}.icon-question:before{content:"\f059"}.icon-docker:before{content:"\e911"}.icon-control:before{content:"\e912"}.icon-statistics1:before{content:"\e913"}.icon-asterisk:before{content:"\e914"}.icon-app:before{content:"\e915"}:root{--primary:#5e72e4;--dark-primary:#483d8b;--main-color:#09c;--header-bg:#09c;--header-color:#fff;--bar-bg:#5e72e4;--menu-bg-color:#fff;--menu-color:#5f6368;--menu-color-hover:#202124;--main-menu-color:#202124;--submenu-bg-hover:#d4d4d4;--submenu-bg-hover-active:#09c;--blue:#5e72e4;--indigo:#5603ad;--purple:#8965e0;--pink:#f3a4b5;--red:#f5365c;--orange:#fb6340;--yellow:#ffd600;--green:#2dce89;--teal:#11cdef;--cyan:#2bffc6;--gray:#8898aa;--gray-dark:#32325d;--light:#ced4da;--lighter:#e9ecef;--secondary:#f7fafc;--success:#2dce89;--info:#11cdef;--warning:#fb6340;--danger:#f5365c;--light:#adb5bd;--dark:#212529;--default:#172b4d;--white:#fff;--neutral:#fff;--darker:black;--background-color:#f4f5f7;--login-form-bg-color:rgba(244,245,247,0.8);--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--blur-radius:10px;--blur-opacity:.5;--blur-radius-dark:10px;--blur-opacity-dark:.5;--font-family-sans-serif:"Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;--font-family-normal:Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif}*{margin:0px;padding:0px;box-sizing:border-box}html,body{margin:0px;padding:0px;height:100%;font-size:16px;font-family:"Google Sans","Microsoft Yahei","WenQuanYi Micro Hei","sans-serif","Helvetica Neue","Helvetica","Hiragino Sans GB";font-family:var(--font-family-sans-serif)}html{-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{font-size:.875rem;background-color:#f4f5f7;background-color:var(--background-color);color:#32325d;color:var(--gray-dark);-webkit-tap-highlight-color:transparent}textarea{padding:.2rem}textarea:focus-visible{outline:none;border:1px solid var(--primary)}::selection{background-color:#5e72e4;background-color:var(--primary);color:#ffffff;color:var(--white)}::placeholder{color:var(--lighter)}a:link,a:visited,a:active{color:#5e72e4;color:var(--primary);text-decoration:none}a:hover{text-decoration:underline}li{list-style-type:none}.table{position:relative;display:table}.tr{display:table-row}.thead{display:table-header-group}.tbody{display:table-row-group}.tfoot{display:table-footer-group}.td,.th{line-height:normal;display:table-cell;padding:.5em;text-align:center;vertical-align:middle}.th{font-weight:bold;white-space:nowrap}.tr.placeholder{height:4em}.tr.placeholder>.td{line-height:3;position:absolute;right:0;bottom:0;left:0;padding:.4rem 0 !important;text-align:center !important;background:inherit}.td[width="33%"]{padding:1.1em 1.5rem}.table[width="33%"],.th[width="33%"],.td[width="33%"]{width:33%}.table[width="100%"],.th[width="100%"],.td[width="100%"]{width:100%}.col-1{flex:1 1 30px !important}.col-2{flex:2 2 60px !important}.col-3{flex:3 3 90px !important}.col-4{flex:4 4 120px !important}.col-5{flex:5 5 150px !important}.col-6{flex:6 6 180px !important}.col-7{flex:7 7 210px !important}.col-8{flex:8 8 240px !important}.col-9{flex:9 9 270px !important}.col-10{flex:10 10 300px !important}*{box-sizing:border-box;margin:0;padding:0}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:normal;line-height:1.1 !important;color:inherit}select{padding:.36rem .8rem;color:#555;border:thin solid #ccc;background-color:#fff;background-image:none}.btn,button,select,input,.cbi-dropdown{line-height:1.5em;padding:.5rem .75rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;transition:box-shadow .15s ease}select,.cbi-dropdown{width:inherit;cursor:default}select:not([multiple="multiple"]):focus,input:not(.cbi-button):focus,.cbi-dropdown:focus{border-color:#5e72e4;border-color:var(--primary);box-shadow:0 3px 9px rgba(50,50,9,0),3px 4px 8px rgba(94,114,228,0.1)}.cbi-dropdown,select[multiple="multiple"]{height:auto}pre{overflow:auto}code{font-size:.875rem;padding:1px 3px;color:#101010;border-radius:2px;background:#ddd}abbr{cursor:help;text-decoration:underline;color:#5e72e4;color:var(--primary)}hr{margin:1rem 0;opacity:.1;border-color:#eee}ul{line-height:normal}li{list-style-type:none}h1{font-size:2rem;padding-bottom:10px;border-bottom:thin solid #eee}h2{margin:0 0 1rem 0;font-size:1.25rem;letter-spacing:.1rem;padding:1rem 1.25rem;color:#32325d;border-radius:.25rem;background:#fff;box-shadow:0 4px 8px rgba(0,0,0,0.03);font-weight:bold}h3{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark);border-radius:.25rem;background:#fff;font-weight:bold}h4{margin:0;padding:.75rem 1.25rem;font-size:.875rem;font-weight:600;color:#525f7f;font-weight:bold}h4 em{padding:0 .5rem}h5{font-size:1rem;margin:2rem 0 0 0;padding-bottom:10px}.pull-right{float:right}.pull-left{float:left}.nowrap:not(.td){white-space:nowrap}[disabled="disabled"]{pointer-events:none}.login-page{height:100%}.login-page .video{position:absolute;width:100%;height:100%;display:flex;align-items:center;justify-content:center;background-color:#000;background-color:var(--darker);overflow:hidden}.login-page .video video{width:100%;height:auto}.login-page .volume-control{position:fixed;right:1rem;top:1rem;width:1.5rem;height:1.5rem;z-index:5000;cursor:pointer;background-size:contain;background-image:url(../img/volume_high.svg)}.login-page .volume-control.mute{background-image:url(../img/volume_off.svg)}.login-page .main-bg{position:absolute;width:100%;height:100%;left:0;top:0;background-image:url(../img/blank.png);background-repeat:no-repeat;background-position:center;background-size:cover;transition:all .5s}.login-page .login-container{height:100%;margin-left:4.5rem;position:absolute;top:0px;display:flex;flex-direction:column;-webkit-box-pack:center;justify-content:center;align-items:flex-start;min-height:100%;z-index:2;width:420px;box-shadow:rgba(0,0,0,0.75) 0 0 35px -5px;margin-left:5%;background:transparent}.login-page .login-container .login-form{display:flex;flex-direction:column;-webkit-box-align:center;align-items:center;position:absolute;top:0px;width:100%;min-height:100%;max-width:420px;background-color:#fff;background-color:var(--white);-webkit-backdrop-filter:blur(var(--blur-radius));backdrop-filter:blur(var(--blur-radius));background-color:rgba(244, 245, 247, var(--blur-opacity))}.login-page .login-container .login-form .brand{display:flex;-webkit-box-align:center;align-items:center;margin:50px auto 100px 50px;color:#525461;color:var(--default);justify-content:center}.login-page .login-container .login-form .brand .icon{width:50px;height:auto;margin-right:25px}.login-page .login-container .login-form .brand .brand-text{font-size:1.25rem;font-weight:700;font-family:"TypoGraphica"}.login-page .login-container .login-form .brand:hover{text-decoration:none}.login-page .login-container .login-form .form-login{width:100%;padding:20px 50px;box-sizing:border-box}.login-page .login-container .login-form .form-login .errorbox{text-align:center;color:#fb6340;color:var(--warning);padding-bottom:2rem}.login-page .login-container .login-form .form-login .input-group{margin-bottom:1.25rem;position:relative}.login-page .login-container .login-form .form-login .input-group::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#525461;color:var(--default);font-size:1.5rem;position:absolute;z-index:100;left:10px;top:10px}.login-page .login-container .login-form .form-login .input-group .border{position:absolute;width:100%;height:1px;bottom:0;border-bottom:1px #5e72e4 solid;border-bottom:1px var(--primary) solid;transform:scaleX(0);transition:transform .3s}.login-page .login-container .login-form .form-login .input-group input{font-size:1rem;line-height:1.5em;display:block;width:100%;padding:.5rem .75rem .5rem 3rem;margin:.825rem 0;box-sizing:border-box;transition:all .3s cubic-bezier(.68, -0.55, .265, 1.55);color:#525461;color:var(--default);border:0;border-radius:0;border-bottom:1px solid #fff;border-bottom:1px solid var(--white);background-color:transparent;background-clip:padding-box;box-shadow:0 3px 2px rgba(233,236,239,0.05);outline:none}.login-page .login-container .login-form .form-login .input-group input:focus+.border{transform:scaleX(1)}.login-page .login-container .login-form .form-login .input-group .cbi-input-password{margin-bottom:2rem;position:relative}.login-page .login-container .login-form .form-login .user-icon::before{content:"\e971"}.login-page .login-container .login-form .form-login .pass-icon::before{content:"\e910"}.login-page .login-container .login-form .cbi-button-apply{width:100% !important;box-shadow:rgba(0,0,0,0.1) 0 0 50px 0;font-weight:600;font-size:15px;color:#fff;color:var(--white);text-align:center;width:100%;cursor:pointer;min-height:50px;background-color:#5e72e4 !important;background-color:var(--primary) !important;border-radius:6px;outline:none;border-width:initial;border-style:none;border-color:initial;border-image:initial;padding:10px 0px;margin:30px 0px 100px;transition:all .3s !important;letter-spacing:.8rem}.login-page .login-container .login-form .cbi-button-apply:hover,.login-page .login-container .login-form .cbi-button-apply :focus{opacity:.9}.login-page .login-container footer{box-sizing:border-box;width:100%;text-align:center;line-height:1.6rem;display:flex;justify-content:space-evenly;margin-top:auto;padding:0px 0px 30px;z-index:10;color:#525461;color:var(--default);position:absolute;bottom:0}.login-page .login-container footer .ftc{position:absolute;bottom:30px;width:100%}.login-page .login-container footer .luci-link{display:block}header,.main{width:100%}footer{font-size:.875rem;overflow:hidden;padding:1rem;text-align:right;white-space:nowrap;color:#aaa}footer>a{text-decoration:none;color:#aaa}small{font-size:90%;line-height:1.42857143;white-space:normal}.main{position:relative;top:0;bottom:0;overflow-y:auto;height:100%;display:flex;flex-direction:row}.main-left{flex-shrink:0;width:15rem;height:100%;background-color:var(--menu-bg-color);box-shadow:rgba(0,0,0,0.75) 0 0 15px -5px;overflow-x:auto;z-index:100}.main-left .sidenav-header{padding:1.5rem .5rem;text-align:center}.main-left .sidenav-header .brand{display:block;font-size:1.8rem;color:#5e72e4;color:var(--primary);font-family:"TypoGraphica";text-decoration:none;text-align:center;cursor:default;margin:0 2rem}.main-left .sidenav-header .brand .logo{max-width:100%;height:auto}.main-left::-webkit-scrollbar{width:5px;height:1px}.main-left::-webkit-scrollbar-thumb{background-color:#f6f9fc}.main-left::-webkit-scrollbar-track{background-color:#fff}.main-right{flex-grow:1;height:100%;transition:all .2s;overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column}.main-right>#maincontent{position:relative;z-index:50;flex:1;display:flex;flex-direction:column}.main-right>#maincontent>.container{margin:0 1.25rem 1rem 1.25rem;flex-grow:1}.main-right>#maincontent .Dashboard{color:var(--gray-dark) !important}.main-right>#maincontent .Dashboard h3{color:var(--gray-dark)}.main-right>#maincontent .Dashboard p{margin-bottom:3px;margin-top:3px}.main-right>#maincontent .Dashboard hr{border-top:1px solid #000}.main-right>#maincontent .Dashboard .dashboard-bg{background-color:#fff}.main-right>#maincontent .Dashboard .settings-info{padding-top:1em;padding-bottom:1em}.main-right>#maincontent .Dashboard .settings-info p span:nth-child(2){max-height:18.5px;top:4px}.main-right>#maincontent .Dashboard .settings-info .label{font-size:.7rem;padding:.2rem .6rem}header{color:#fff;color:var(--header-color);padding:0;position:relative}header.bg-primary{background-color:#5e72e4 !important;background-color:var(--primary) !important}header::after{content:"";position:absolute;height:2rem;width:100%;background-color:#5e72e4 !important;background-color:var(--primary) !important}header .fill{padding:.8rem 0;border-bottom:0 solid rgba(255,255,255,0.08) !important;display:flex}header .fill .container{height:2rem;padding:0 1.25rem;display:flex;align-items:center;width:100%}header .fill .container .flex1{flex:1}header .fill .container .flex1 .showSide{display:none;color:#fff;font-size:1.4rem}header .fill .container .flex1 .showSide:hover{text-decoration:none}header .fill .container .flex1 .brand{font-size:1.5rem;color:#fff;font-family:"TypoGraphica";text-decoration:none;padding-left:1rem;cursor:default;vertical-align:text-bottom;display:none}header .fill .container .pull-right{float:right;margin-top:0rem;display:flex}header .fill .status span{display:inline-block;font-size:.875rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;text-shadow:none;border-radius:4px;cursor:pointer;transition:all .3s;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);margin:0 .25rem}header .fill .status span:last-child{margin-right:0}header .fill .status span[data-indicator="poll-status"]{color:#fff}header .fill .status span[data-style="active"]{background-color:var(--green)}header .fill .status span[data-style="inactive"]{color:#ffffff !important;background-color:#32325d}#xhr_poll_status{display:flex;margin-left:.5rem}#xhr_poll_status *{color:#fff}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{border:0 !important}.danger{background-color:#ff7d60 !important}.warning{background-color:#f0e68c !important}.success{background-color:#5cb85c !important}.notice{background-color:#11cdef !important;color:#fff}.error{color:#f00}.alert,.alert-message{font-weight:bold;margin-bottom:1.25rem;margin-left:1.25rem;margin-right:1.25rem;padding:1rem 1.25rem;border:0;border-radius:.25rem !important;background-color:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);text-shadow:none}.alert.error,.alert-message.error{background-color:#ffd600}.alert h4,.alert-message h4{padding:.25rem 0;border-radius:4px;background-color:#ffd600}.alert .btn,.alert-message .btn{height:auto}.alert-message>h4{font-size:110%;font-weight:bold}.alert-message>*{margin:.5rem 0}.alert-message .btn{padding:.3rem .6rem}.container .alert,.container .alert-message{margin-left:0;margin-right:0;margin-top:0rem}.main .main-left{transition:all .2s}.main .main-left .nav{margin-top:.5rem}.main .main-left .nav>li>a:first-child{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.25rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav>li>a:first-child.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child.active::before{color:#fff !important}.main .main-left .nav>li>a:first-child.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav>li>a:first-child:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child:hover::before{color:#fff !important}.main .main-left .nav>li>a:first-child::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li{padding:.5rem 1rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:0}.main .main-left .nav li a{display:block;color:#5f6368;color:var(--menu-color)}.main .main-left .nav li.slide{padding:0}.main .main-left .nav li.slide ul{display:none;overflow:hidden}.main .main-left .nav li.slide:hover{background:none}.main .main-left .nav li.slide .slide-menu{margin:0 .5rem 0 2.5rem;padding:0 .5rem}.main .main-left .nav li.slide .slide-menu.active{display:block}.main .main-left .nav li.slide .slide-menu li{position:relative;border-radius:.25rem;margin:0;background:none;list-style:none}.main .main-left .nav li.slide .slide-menu li a{text-decoration:none;padding:.5rem 0}.main .main-left .nav li.slide .slide-menu li::after{content:"";position:absolute;left:0;bottom:0;width:0;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu li:hover{background:none}.main .main-left .nav li.slide .slide-menu li:hover::after{width:100%}.main .main-left .nav li.slide .slide-menu .active{background:none;color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active a{color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu .active:hover{background:none}.main .main-left .nav li.slide .slide-menu .active:hover::after{width:100%}.main .main-left .nav li .menu{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.25rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav li .menu.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu.active::before{color:#fff !important}.main .main-left .nav li .menu.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav li .menu:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu:hover::before{color:#fff !important}.main .main-left .nav li .menu::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu::after{position:absolute;right:.5rem;top:.8rem;font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-moz-osx-font-smoothing:grayscale;content:'\e90f';transition:all .15s ease;color:#ced4da;text-rendering:auto;-webkit-font-smoothing:antialiased;transition:all .3s}.main .main-left .nav li .menu[data-title=Status]:before{content:"\e906";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=System]:before{content:"\e90a";color:#fb6340}.main .main-left .nav li .menu[data-title=Services]:before{content:"\e909";color:#11cdef}.main .main-left .nav li .menu[data-title=NAS]:before{content:"\e90c";color:#f3a4b5}.main .main-left .nav li .menu[data-title=VPN]:before{content:"\e90b";color:#8965e0}.main .main-left .nav li .menu[data-title=Network]:before{content:"\e908";color:#8965e0}.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before{content:"\e90d";color:#2dce89}.main .main-left .nav li .menu[data-title=Docker]:before{content:"\e911";color:#6699ff}.main .main-left .nav li .menu[data-title=Statistics]:before{content:"\e913";color:#8965e0}.main .main-left .nav li .menu[data-title=Control]:before{content:"\e912";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=Asterisk]:before{content:"\e914";color:#fb6340}.main .main-left .nav li a[data-title=Log_out]::before,.main .main-left .nav li .food[data-title=Log_out]::before{content:"\e907";color:#adb5bd}.lg{margin:0;padding:0 !important}.logout{display:block;margin:.8rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.25rem;text-decoration:none;font-size:1rem;transition:all .2s;position:relative}.logout:before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e907";color:#32325d !important}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before{transition:transform .1s ease-in-out}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before{transition:transform .2s ease-in-out}.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before{display:none}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{font-family:inherit;font-weight:normal;font-style:normal;line-height:normal;min-width:inherit;margin:1.25rem 0;padding:0;border:0;border-radius:.25rem;background-color:#fff;box-shadow:0 0 1rem 0 rgba(136,152,170,0.15)}.cbi-section:last-child,.cbi-section-error:last-child,#iptables:last-child,.Firewall form:last-child,#cbi-network>.cbi-section-node:last-child,#cbi-wireless>.cbi-section-node:last-child,#cbi-wireless>#wifi_assoclist_table:last-child,[data-tab-title]:last-child,[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear):last-child,[data-page="admin-system-opkg"] #maincontent>.container:last-child{margin:0;border:0}.cbi-modal .cbi-section,.cbi-section .cbi-section{padding:0;box-shadow:none}.cbi-modal .cbi-tabmenu{margin-left:0}.cbi-map:not(:first-child){margin-top:1rem}.cbi-map-descr{font-size:small;line-height:1.5;padding:0 1.25rem 1rem 1.25rem}.cbi-section>.cbi-section-descr{padding-top:1rem !important;padding-bottom:1rem !important}.cbi-section>.cbi-section-descr:empty{padding-top:0 !important;padding-bottom:0rem !important}.cbi-section-descr:not(:empty){font-size:small;line-height:1.5;padding:0rem 1rem}.cbi-map-descr+fieldset{margin-top:1rem}.cbi-map-descr>abbr{cursor:help;text-decoration:underline}.cbi-section>legend{display:none !important}fieldset>fieldset,.cbi-section>.cbi-section{margin:0;padding:0;border:0;box-shadow:none}.cbi-section>h3:first-child,.panel-title{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark)}.cbi-section>h3:first-child,.cbi-section>h4:first-child,.cbi-section>p:first-child,[data-tab-title]>h3:first-child,[data-tab-title]>h4:first-child,[data-tab-title]>p:first-child{padding:1rem 1.25rem}.cbi-section p{padding:1rem}.cbi-tblsection{overflow-x:auto}table{border-spacing:0;border-collapse:collapse}table,.table{overflow-y:hidden;width:100%;font-size:90%}.table .table-titles th{background-color:#e9ecef;background-color:var(--lighter)}table>tbody>tr>td,table>tbody>tr>th,table>tfoot>tr>td,table>tfoot>tr>th,table>thead>tr>td,table>thead>tr>th,.table>.tbody>.tr>.td,.table>.tbody>.tr>.th,.table>.tfoot>.tr>.td,.table>.tfoot>.tr>.th,.table>.thead>.tr>.td,.table>.thead>.tr>.th,.table>.tr>.td.cbi-value-field,.table>.tr>.th.cbi-section-table-cell{padding:.5rem}.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td{padding:.6rem}.cbi-section-table-cell{line-height:1.1;align-self:flex-end;flex:1 1 auto}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:thin solid #ddd;padding:1.1em 1.25rem}#cbi-wireless .td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{border-top:0 !important;background-color:#f6f9fc;padding:1.1em 1.25rem;line-height:1.3rem}[data-page="admin-network-network"] .cbi-value-field .cbi-dynlist{padding:0 !important}#cbi-network .tr:first-child>.td{border-top:0}.table[width="100%"]>.tr:first-child>.td{margin:auto 0}.cbi-section-table-row{margin-bottom:1rem;text-align:center !important;background:#f4f4f4}.cbi-section-table-row:last-child{margin-bottom:0}.cbi-section-table-row>.cbi-value-field .cbi-dropdown,.cbi-section-table-row>.cbi-value-field .cbi-input-select,.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{width:100%}.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{min-width:80px}.cbi-section-table-row>.cbi-value-field [data-dynlist]>input,.cbi-section-table-row>.cbi-value-field input.cbi-input-password{width:calc(100% - 1.5rem)}.cbi-section-table-row .td{text-align:center !important}.cbi-section-table-row .td .cbi-checkbox input[type="checkbox"]{margin:0}.control-group{display:inline-flex;width:100%;flex-wrap:wrap;gap:0px}.control-group input{border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;margin-right:0}.control-group input+button{border-bottom-left-radius:0;border-top-left-radius:0;margin-left:0;border-left-width:0}.control-group>*{vertical-align:middle}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n){background-color:#f9f9f9}table table,.table .table,.cbi-value-field table,.cbi-value-field .table,td>table>tbody>tr>td,.td>.table>.tbody>.tr>.td,.cbi-value-field>table>tbody>tr>td,.cbi-value-field>.table>.tbody>.tr>.td{border:0}.btn,.cbi-button,.item::after{font-size:.875rem;display:inline-block;width:auto !important;padding:.5rem .75rem;margin-left:5px;margin-right:5px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition:all .2s ease-in-out;text-align:center;vertical-align:middle;white-space:nowrap;text-decoration:none;border:0;border-radius:.25rem;background-color:#f0f0f0;background-image:none;appearance:none;-ms-touch-action:manipulation;touch-action:manipulation}.btn:last-child,.cbi-button:last-child{margin-right:0 !important}.btn:first-child,.cbi-button:first-child{margin-left:0 !important}.btn:only-child,.cbi-button:only-child{margin-left:5px !important;margin-right:5px !important}.btn:not(button) ul:not(.dropdown) li{padding:0}.cbi-button-up,.cbi-button-down{display:inline-block;min-width:0;padding:.2rem 1rem;font-size:0;color:transparent !important;background:url(../icon/arrow.svg) no-repeat center;background-size:12px 20px}.cbi-button-up{transform:scaleY(-1)}.cbi-button:not(select){appearance:none !important}.btn:hover,.btn:focus,.btn:active,.cbi-button:hover,.cbi-button:focus,.cbi-button:active,.item:hover::after,.item:focus::after,.item:active::after,.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover,.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus,.cbi-page-actions .cbi-button-apply+.cbi-button-save:active{text-decoration:none;outline:0}.btn:hover,.btn:focus,.cbi-button:hover,.cbi-button:focus,.item:hover::after,.item:focus::after{box-shadow:0 0 2px rgba(0,0,0,0.12),0 2px 2px rgba(0,0,0,0.2)}.btn:active,.cbi-button:active,.item:active::after{box-shadow:0 10px 20px rgba(0,0,0,0.19),0 6px 6px rgba(0,0,0,0.23)}.cbi-button-up:hover,.cbi-button-up:focus{box-shadow:0 0 2px rgba(0,0,0,0.12),0 -2px 2px rgba(0,0,0,0.2)}.cbi-button-up:active{box-shadow:0 -10px 20px rgba(0,0,0,0.19),0 -6px 6px rgba(0,0,0,0.23)}.btn:disabled,.cbi-button:disabled{cursor:not-allowed;pointer-events:none;opacity:.5;box-shadow:none}.alert-message [class="btn"],.modal div[class="btn"],.cbi-button-find,.cbi-button-link,.cbi-button-up,.cbi-button-down,.cbi-button-neutral,.cbi-button[name="zero"],.cbi-button[name="restart"],.cbi-button[onclick="hide_empty(this)"]{color:#fff;border:thin solid #8898aa;background-color:#8898aa}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"]{font-weight:normal;color:#fff;border:thin solid #f5365c;border:thin solid var(--red);background-color:#f5365c;background-color:var(--red)}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:normal;color:#fff;border:thin solid #eea236;background-color:#f0ad4e}.cbi-button-success,.cbi-button-download{font-weight:normal;color:#fff;border:thin solid #4cae4c;background-color:#5cb85c}.cbi-page-actions .cbi-button-link:first-child{float:left}.a-to-btn{text-decoration:none}.cbi-value-field .cbi-button-add{font-weight:bold;padding:1px 6px;display:inline-block;align-items:center}.tabs{margin:0 0 1rem 0;padding:0 1rem;background-color:#FFFFFF;border-radius:.25rem;box-shadow:0 4px 8px rgba(0,0,0,0.03);white-space:nowrap;overflow-x:auto}.tabs::-webkit-scrollbar{width:1px;height:5px}.tabs::-webkit-scrollbar-thumb{background-color:#f6f9fc}.tabs::-webkit-scrollbar-track{background-color:#fff}.tabs li[class~="active"],.tabs li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#e4e9ee;margin-bottom:0;border-radius:0}.tabs li[class~="active"] a,.tabs li:hover a{color:#5e72e4;color:var(--primary)}.tabs li{font-size:.875rem;display:inline-block;padding:.875rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0;transition:all .2s}.tabs li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.tabs li:hover{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary)}.cbi-tabmenu{color:white;padding:.5rem 1rem 0 1rem;white-space:nowrap;overflow-x:auto}.cbi-tabmenu::-webkit-scrollbar{width:1px;height:5px}.cbi-tabmenu::-webkit-scrollbar-thumb{background-color:#f6f9fc}.cbi-tabmenu::-webkit-scrollbar-track{background-color:#fff}.cbi-tabmenu li{background:#dce3e9;display:inline-block;font-size:.875rem;border-top-left-radius:.25rem;border-top-right-radius:.25rem;padding:.5rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0 .2rem}.cbi-tabmenu li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.cbi-tabmenu li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#e4e9ee;margin-bottom:0}.cbi-tabmenu li:hover a{color:#525f7f}.cbi-tabmenu li[class~="cbi-tab"]{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#e4e9ee;margin-bottom:0}.cbi-tabmenu li[class~="cbi-tab"] a{color:#5e72e4;color:var(--primary)}.cbi-tab-descr{padding:.5rem 1.5rem}.cbi-section-node{padding:0}.cbi-section .cbi-section-remove:nth-of-type(2n),.container>.cbi-section .cbi-section-node:nth-of-type(2n){background-color:#f9f9f9}[data-tab-title]{overflow:hidden;height:0;opacity:0;margin:0;padding:0rem 0rem !important}[data-tab-title] p{margin-left:1rem;margin-bottom:1rem}[data-tab-active="true"]{overflow:visible;height:auto;opacity:1;transition:opacity .25s ease-in;margin:inherit !important}.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3),.cbi-section[id] .cbi-section-node:nth-of-type(4n+4){background-color:#f9f9f9}.cbi-section-node-tabbed{margin-top:0;padding:0;border:0 solid #d4d4d4;border-radius:.25rem}.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#f9f9f9}.cbi-value-field{display:table-cell}.cbi-value-description{line-height:1.25;display:table-cell}.cbi-value-description abbr{color:#32325d;color:var(--gray-dark)}.cbi-value-description{font-size:small;padding:.5rem;opacity:.5}.cbi-value-title{display:table-cell;float:left;width:23rem;padding-right:2rem;text-align:right;word-wrap:break-word}.cbi-value{display:inline-block;width:100%;padding:.35rem 1rem .2rem 1rem;line-height:2.4rem}.cbi-value:first-child{padding-top:1rem}.cbi-value:last-child{padding-bottom:1rem}.cbi-value ul{line-height:1.25}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"],.cbi-value textarea{min-width:18rem}.cbi-value input[type="password"]{border-bottom-right-radius:0;border-top-right-radius:0;font-size:.875rem;margin:.25rem 0 .25rem .1rem}.cbi-value input[type="password"]+.cbi-button-neutral{display:flex;align-items:center;justify-content:center;width:2.5rem !important;padding:.5rem 0;margin:.25rem 0;font-weight:normal;font-size:1.2rem;line-height:1.5rem;color:#fff;outline:0;background-color:#8898aa;box-shadow:none;border:1px solid #8898aa;border-radius:.25rem;border-top-left-radius:0;border-bottom-left-radius:0}#cbi-firewall-zone .cbi-input-select,#cbi-network-switch_vlan .cbi-input-select{min-width:11rem}#cbi-network-switch_vlan .cbi-input-text{max-width:3rem}.cbi-input-invalid{color:#f5365c !important;border-color:#f5365c !important}.cbi-section-error{font-weight:bold;line-height:1.42857143;margin:18px;padding:6px;border:thin solid #f5365c;border-radius:3px;background-color:#fce6e6}.cbi-section-error ul{margin:0 0 0 20px}.cbi-section-error ul li{font-weight:bold;color:#f5365c}.td[data-title]::before{font-weight:bold;display:none;padding:.25rem 0;content:attr(data-title) ":\20";text-align:left;white-space:nowrap}.tr.placeholder .td[data-title]::before{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-weight:bold;display:table-cell;align-self:center;flex:1 1 5%;padding:.25rem;content:attr(data-title) "\20";text-align:center;vertical-align:middle;white-space:normal;word-wrap:break-word}.cbi-rowstyle-1{background-color:#f9f9f9}.cbi-rowstyle-2{background-color:#eee}.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#fff !important}.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{width:auto !important}.td.cbi-section-actions{text-align:right !important;vertical-align:middle}.td.cbi-section-actions>*{display:inline-flex}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:0 5px;display:flex;align-items:center}.td.cbi-section-actions>*>form{display:inline-flex;margin:0}.cbi-checkbox{margin:0 .25rem}.cbi-dynlist{line-height:1.3;flex-direction:column;min-height:30px;cursor:text}.cbi-dynlist>.item{display:inline-flex;flex-wrap:nowrap;margin:.25rem 0;position:relative;max-width:25rem;pointer-events:none;color:#8898aa;outline:0}.cbi-dynlist>.item::after{content:"\00D7";pointer-events:auto;display:flex;align-items:center;justify-content:center;width:2.5rem !important;margin:0;font-weight:normal;font-size:1.2rem;line-height:1.5rem;color:#fff;border:1px solid #f5365c;border-radius:0 .25rem .25rem 0;outline:0;background-color:var(--red);background-image:none;box-shadow:none;box-sizing:border-box}.cbi-dynlist>.item>span{display:block;padding:.5rem .75rem;min-width:15.5rem;width:15.5rem;transition:box-shadow .15s ease;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-break:break-word;font-size:.875rem;line-height:24px;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem 0 0 .25rem;outline:0;background-image:none;box-shadow:none;box-sizing:border-box}.cbi-dynlist>.add-item{display:inline-flex;align-items:center;width:100%;min-width:16rem;margin:.25rem 0;gap:0;flex-wrap:nowrap}.cbi-dynlist>.add-item input{display:block;padding:.5rem .75rem;box-sizing:border-box;min-width:15.5rem;width:15.5rem;transition:box-shadow .15s ease;white-space:nowrap;word-break:break-word;font-size:.875rem;line-height:1.5rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem 0 0 .25rem;border-right-width:0;outline:0;background-image:none;box-shadow:none}.cbi-dynlist>.add-item .cbi-button{display:flex;width:auto !important;padding-left:.8rem;padding-right:.8rem;margin-left:0;align-items:center;justify-content:center;font-size:.875rem;line-height:1.5rem;outline:0;background-image:none;background-color:var(--gray);box-shadow:none;color:var(--white);border-color:var(--gray);border-radius:.25rem;border-top-left-radius:0;border-bottom-left-radius:0}.cbi-dynlist>.add-item .cbi-button-add{width:2.5rem !important;padding:.5rem 0 !important;font-weight:normal;font-size:1.2rem;color:#fff;background-color:var(--primary);border:1px solid var(--primary)}.cbi-dynlist>.add-item:not([ondrop])>input{overflow:hidden;min-width:15.5rem;width:15.5rem;white-space:nowrap;text-overflow:ellipsis}.cbi-dynlist[name="sshkeys"]>.item{max-width:none}.cbi-dynlist>.cbi-dynlist>.add-item[ondrop]>input{min-width:13rem}.cbi-dynlist,.cbi-dropdown{position:relative;display:inline-flex;min-height:2.1875rem}.cbi-dropdown[placeholder*="select"]{max-width:25rem;height:auto;margin-top:-3px}.cbi-dropdown>ul{display:flex;overflow-x:hidden;overflow-y:auto;width:100%;margin:0 !important;padding:0;list-style:none;outline:0}.cbi-dropdown>ul.preview{display:none}.cbi-button-apply>ul.preview{display:none}.cbi-button-apply>ul.preview li{color:#fff}.cbi-button-apply>ul:first-child li{color:#fff}.cbi-dropdown>.open{flex-basis:15px}.cbi-dropdown>.open,.cbi-dropdown>.more{font-size:1rem;font-weight:900;line-height:1em;display:flex;flex-direction:column;flex-grow:0;flex-shrink:0;justify-content:center;padding:0 .25em;cursor:default;text-align:center;outline:0}.cbi-dropdown>.more,.cbi-dropdown>ul>li[placeholder]{font-weight:bold;display:none;color:#777;text-shadow:none}.cbi-dropdown>ul>li{display:none;overflow:hidden;align-items:center;align-self:center;flex-grow:1;flex-shrink:1;min-height:20px;padding:.125rem .25em;white-space:nowrap;text-overflow:ellipsis}.cbi-dropdown>ul>li .hide-open{display:initial}.cbi-dropdown>ul>li .hide-close{display:none}.cbi-dropdown>ul>li[display]:not([display="0"]){border-left:thin solid #ccc}.cbi-dropdown[empty]>ul{max-width:1px}.cbi-dropdown>ul>li>form{display:none;margin:0;padding:0;pointer-events:none}.cbi-dropdown>ul>li img{margin-right:.25em;vertical-align:middle}.cbi-dropdown>ul>li>form>input[type="checkbox"]{height:auto;margin:0}.cbi-dropdown>ul>li input[type="text"]{height:20px}.cbi-dropdown[open]>ul.dropdown{position:absolute;z-index:1100;display:block;width:auto;min-width:100%;max-width:none;max-height:200px !important;border:0 solid #918e8c;background:#ffffff;box-shadow:0 0 4px #918e8c;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;color:var(--main-menu-color);margin-left:0 !important;left:0}.cbi-dropdown[open]>ul.dropdown li{color:#000}.cbi-dropdown>ul>li[display],.cbi-dropdown[open]>ul.preview,.cbi-dropdown[open]>ul.dropdown>li,.cbi-dropdown[multiple]>ul>li>label,.cbi-dropdown[multiple][open]>ul.dropdown>li,.cbi-dropdown[multiple][more]>.more,.cbi-dropdown[multiple][empty]>.more{display:flex;align-items:center;flex-grow:1}.cbi-dropdown[empty]>ul>li,.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder],.cbi-dropdown[multiple][open]>ul.dropdown>li>form{display:block}.cbi-dropdown[open]>ul.dropdown>li .hide-open{display:none}.cbi-dropdown[open]>ul.dropdown>li .hide-close{display:initial}.cbi-dropdown[open]>ul.dropdown>li{border-bottom:thin solid #ccc;padding:.5rem .8rem}.cbi-dropdown[open]>ul.dropdown>li label{margin-left:.5rem}.cbi-dropdown[open]>ul.dropdown>li[selected]{background:#e4e9ee}.cbi-dropdown[open]>ul.dropdown>li.focus{background:#e4e9ee;outline:none}.cbi-dropdown[open]>ul.dropdown>li:last-child{margin-bottom:0;border-bottom:0}.cbi-dropdown[open]>ul.dropdown>li[unselectable]{opacity:.7}.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child{width:100%}.cbi-dropdown[disabled]{pointer-events:none;opacity:.6}.cbi-dropdown .zonebadge{width:100%}.cbi-dropdown[open] .zonebadge{width:auto}.cbi-progressbar{position:relative;display:flex;width:100%;font-size:.75rem;background-color:#e9ecef;border-radius:.5rem;height:1rem;overflow:hidden}.cbi-progressbar>div{display:block;position:absolute;height:100%;background-color:var(--bar-bg);border-radius:.5rem;transition:width .3s}.cbi-progressbar::after{content:attr(title);position:absolute;font-size:.75rem;color:var(--bs-heading-color);width:100%;height:100%;text-align:center;line-height:1rem;z-index:2}#modal_overlay{position:fixed;z-index:900;top:0;right:10000px;bottom:0;left:-10000px;overflow-y:scroll;transition:opacity .125s ease-in;opacity:0;background:rgba(0,0,0,0.7);-webkit-overflow-scrolling:touch}.modal{display:flex;align-items:center;flex-wrap:wrap;width:90%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1rem;border-radius:.25rem !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>*{line-height:normal;flex-basis:100%;margin-bottom:.5em;max-width:100%}.modal>pre,.modal>textarea{font-size:1rem;font-size-adjust:.35;overflow:auto;margin-bottom:.5em;padding:8.5px;cursor:auto;white-space:pre-wrap;color:#eee;outline:0;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>h4{display:block;flex-grow:1;max-width:none;padding:1rem;margin:-1rem -1rem 0 -1rem;font-size:1rem;box-shadow:0 4px 8px rgba(0,0,0,0.03);border-radius:.25rem 0 0 .25rem}.modal h5{margin-top:1rem;font-weight:600}.modal label>input[type="checkbox"]{top:0}.modal ul{margin-left:2.2em}.modal ul:not(.cbi-tabmenu){margin-top:1rem}.modal ul li{list-style-type:square;color:#808080}.modal p{word-break:break-word;margin-top:1rem}.modal .label{font-size:.6rem;font-weight:normal;padding:.1rem .3rem;padding-bottom:0;cursor:default;border-radius:0}.modal .label.warning{background-color:#f0ad4e !important}.modal .btn{padding:.45rem .8rem}.modal.cbi-modal{max-width:90%;max-height:none}body.modal-overlay-active{overflow:hidden;height:100vh}body.modal-overlay-active #modal_overlay{right:0;left:0;opacity:1}.spinning{position:relative;padding-left:32px !important}.spinning::before{position:absolute;top:0;bottom:0;left:.2em;width:32px;content:"";background:url(/luci-static/resources/icons/loading.gif) no-repeat center;background-size:16px}#view{border-radius:.25rem;overflow:hidden}#view>.spinning{position:fixed;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);padding:1rem;border-radius:.5rem;background:#ffffff;box-shadow:0 0 1rem 0 rgba(136,152,170,0.15)}.hidden{display:none}.left,.left::before{text-align:left !important}.right,.right::before{text-align:right !important}.center,.center::before{text-align:center !important}.top{align-self:flex-start !important;vertical-align:top !important}.bottom{align-self:flex-end !important;vertical-align:bottom !important}.inline{display:inline}.cbi-page-actions{padding:1rem;text-align:right;justify-content:flex-end}.cbi-page-actions>form[method="post"]{display:inline-block}.th[data-type="button"],.td[data-type="button"],.th[data-type="fvalue"],.td[data-type="fvalue"]{flex:1 1 2em;text-align:center}.ifacebadge{display:inline-flex;align-items:center;gap:.2rem;padding:.25rem .8rem;background:#eee;border-radius:4px}td>.ifacebadge,.td>.ifacebadge{font-size:.875rem;background-color:#f0f0f0}.ifacebadge>em,.ifacebadge>img{display:inline-block;margin:0 .75rem}.ifacebadge>img+img{margin:0 .2rem 0 0}.network-status-table{display:flex;flex-wrap:wrap}.network-status-table .ifacebox{flex-grow:1;border-radius:.25rem;overflow:hidden;margin:1rem}.network-status-table .ifacebox-body{display:flex;flex-direction:column;height:100%;gap:.5em}.network-status-table .ifacebox-body>span{flex:10 10 auto}.network-status-table .ifacebox-body>div{display:flex;flex-wrap:wrap;gap:.5rem;height:100%}.network-status-table .ifacebox-body .ifacebadge{align-items:center;flex:1 1 auto;min-width:220px;padding:.5em;background-color:#fff}.network-status-table .ifacebox-body .ifacebadge>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cbi-input-textarea{font-family:inherit;width:100%;font-size:.875rem;min-height:14rem;padding:.8rem;color:#8898aa;border-radius:.25rem;border:1px solid #dee2e6;min-width:16rem}#content_syslog{box-shadow:0 4px 8px rgba(0,0,0,0.03)}#syslog{font-size:small;font-family:'argon';line-height:1.25;overflow-y:hidden;width:100%;min-height:15rem;padding:1rem;resize:none;color:#242424;border:0;border-radius:.25rem;background-color:#ffffff}#syslog:focus{outline:0}.uci-change-list{font-family:inherit;overflow:scroll;width:100%;display:flex;flex-direction:column;flex-wrap:wrap}.uci-change-list ins,.uci-change-legend-label ins{display:block;padding:2px;text-decoration:none;border:thin solid #0f0;background-color:#cfc}.uci-change-list del,.uci-change-legend-label del{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #f00;background-color:#fcc}.uci-change-list var,.uci-change-legend-label var{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #ccc;background-color:#eee}.uci-change-list var ins,.uci-change-list var del{font-style:normal;padding:0;white-space:pre;border:0}.uci-change-legend{padding:5px}.uci-change-legend-label{float:left;width:150px}.uci-change-legend-label>ins,.uci-change-legend-label>del,.uci-change-legend-label>var{display:block;float:left;width:10px;height:10px;margin-right:4px}.uci-change-legend-label var ins,.uci-change-legend-label var del{line-height:.4;border:0}.uci-change-list var,.uci-change-list del,.uci-change-list ins{padding:.5rem}.uci-dialog .cbi-section{padding:.5rem}.uci-dialog .cbi-section .uci-change-legend{line-height:15px;padding:10px 20px 0 20px}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label{padding:0;margin:0;position:relative;float:none;display:inline-block;width:25%}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>ins,.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>del{width:14px;height:14px}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var{position:relative;width:14px;height:14px}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var ins,.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var del{position:absolute;left:2px;top:2px;right:2px;bottom:2px}.uci-dialog .cbi-section .uci-change-list{overflow:auto}.uci-dialog .cbi-section .uci-change-list+.right .btn{color:#333}.uci-dialog .cbi-section .uci-change-list+.right .cbi-dropdown ul:not(.dropdown) li{color:#fff}.uci-dialog .cbi-section .uci-change-list+.right .cbi-button{padding:.45rem .8rem}#iwsvg,#iwsvg2,#bwsvg{border:thin solid #d4d4d4 !important}#iwsvg,[data-page="admin-status-realtime-bandwidth"] #bwsvg{border-top:0 !important}.ifacebox{line-height:1.25;display:inline-flex;overflow:hidden;flex-direction:column;border-radius:4px;min-width:100px;background-color:#f9f9f9}.ifacebox-head{padding:.25em;background:#eee}.ifacebox-head.active{background:#5e72e4;background:var(--primary)}.ifacebox-head.active *{color:#fff;color:var(--white)}.ifacebox-body{padding:.875rem 1rem;line-height:1.6em}.cbi-image-button{margin-left:.5rem}.zonebadge{display:inline-block;padding:.2rem .5rem;border-radius:4px}.zonebadge .ifacebadge{margin:.1rem .2rem;padding:.2rem .3rem;border:thin solid #6c6c6c}.zonebadge>input[type="text"]{min-width:10rem;margin-top:.3rem;padding:.16rem 1rem}.zonebadge>em,.zonebadge>strong{display:inline-block;margin:0 .2rem}.cbi-value-field .cbi-input-checkbox,.cbi-value-field .cbi-input-radio{margin-top:.1rem}.cbi-value-field>ul>li{display:flex}.cbi-value-field>ul>li>label{margin-top:.5rem}.cbi-value-field>ul>li .ifacebadge{margin-top:-0.5rem;margin-left:.4rem;background-color:#eee}.cbi-section-table-row>.cbi-value-field .cbi-dropdown{min-width:3rem}.cbi-section-create{display:inline-flex;align-items:center;padding:.5rem 1rem}.cbi-section-remove{padding:.5rem 1rem}div.cbi-value var,td.cbi-value-field var,.td.cbi-value-field var{font-style:italic;color:#0069d6}.cbi-optionals{padding:1rem 1rem 0 1rem;border-top:thin solid #ccc}.cbi-dropdown-container{position:relative}.cbi-tooltip-container,span[data-tooltip],span[data-tooltip] .label{cursor:help !important}.cbi-tooltip{position:absolute;z-index:1000;left:-1000px;padding:2px 5px;transition:opacity .25s ease-out;white-space:pre;pointer-events:none;opacity:0;border-radius:3px;background:#fff;box-shadow:0 0 2px #444}.cbi-tooltip-container:hover .cbi-tooltip{left:auto;transition:opacity .25s ease-in;opacity:1}.zonebadge .cbi-tooltip{margin:-1.5rem 0 0 -0.5rem;padding:.25rem;background:inherit}.zonebadge-empty{color:#404040;background:repeating-linear-gradient(45deg, rgba(204,204,204,0.5), rgba(204,204,204,0.5) 5px, rgba(255,255,255,0.5) 5px, rgba(255,255,255,0.5) 10px)}.zone-forwards{display:flex;min-width:10rem}.zone-forwards>*{flex:1 1 45%}.zone-forwards>span{flex-basis:10%;padding:0 .25rem;text-align:center}.zone-forwards .zone-src,.zone-forwards .zone-dest{display:flex;flex-direction:column}.label{font-size:.875rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;color:#fff !important;border-radius:3px;background-color:#bfbfbf;text-shadow:none}label>input[type="checkbox"],label>input[type="radio"]{position:relative;top:.4rem;right:.2rem;margin:0;vertical-align:bottom}label[data-index][data-depends]{padding-right:2em}.showSide{display:none}.darkMask{position:fixed;z-index:99;display:none;width:100%;height:100%;content:"";top:0;background-color:rgba(0,0,0,0.56);transition:all .2s}.darkMask.active{display:block}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1.2rem;font-size-adjust:.35;line-height:normal;display:block;overflow-y:hidden;width:100%;padding:8.5px;white-space:pre;color:#eee;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}[data-page="admin-network-diagnostics"] .table{box-shadow:none}[data-page="admin-network-diagnostics"] .cbi-section{padding:1rem;font-family:monospace;background:#fff !important}[data-page="admin-network-diagnostics"] textarea{background:transparent;border-radius:.25rem;font-family:'argon' !important;color:#8898aa;border:1px solid #dee2e6;padding:.5rem}[data-page="admin-network-diagnostics"] .tr>.td{background-color:#fff !important;border-bottom:1px solid #dee2e6 !important}input[name="ping"],input[name="traceroute"],input[name="nslookup"]{width:80%}.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2),.node-status-processes>.main .table .tr .td:nth-child(3){white-space:normal}div[style*="display:grid;grid-template-columns:repeat"]{display:flex !important;justify-content:space-evenly !important;padding-bottom:1rem;flex-wrap:wrap;font-family:'argon'}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox{text-align:center;flex-basis:100px}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body{font-size:.7rem;padding:.875rem}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body .cbi-tooltip-container{font-size:inherit !important}@media screen and (max-width:484px){div[style*="display:grid;grid-template-columns:repeat"] .ifacebox{flex-basis:80px}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body{padding:.875rem .5rem;font-size:.6rem}}[data-page="admin-system-attendedsysupgrade"] #view .cbi-button{margin-left:0 !important;margin-top:1rem !important}[data-page="admin-system-reboot"] p{padding-left:1.5rem}[data-page="admin-system-reboot"] p>span{position:relative;top:.1rem;left:1rem}[data-page="admin-system-reboot"] .cbi-button{background:#fb6340 !important;border-color:#fb6340 !important;margin-left:0 !important}[data-page="admin-system-reboot"] #view>h2:first-child+p{margin-bottom:1rem}[data-page="admin-system-poweroff"] .container h2+br+p{margin-bottom:1rem;padding-left:1.5rem}[data-page="admin-vpn-passwall"] h4{background:transparent}[data-page="admin-system-filetransfer"] #cbi-upload{margin-top:0}[data-page="admin-system-filetransfer"] .cbi-section-table{box-shadow:0 4px 8px rgba(0,0,0,0.03)}#cbi-samba [data-tab="template"] .cbi-value-field{display:block}#cbi-samba [data-tab="template"] .cbi-value-title{width:auto;padding-bottom:.6rem}[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr{margin-left:0;color:#32325d;color:var(--gray-dark)}[data-page="admin-system-admin-sshkeys"] .cbi-dynlist{margin-left:1rem}[data-page="admin-system-opkg"] h2{margin-left:0;color:#32325d;color:var(--gray-dark)}.controls{margin:.5em 1rem 1em 1rem !important}.controls>*>.btn:not([aria-label$="page"]){flex-grow:initial !important;margin-top:.25rem}.controls>#pager>.btn[aria-label$="page"]{font-size:1.4rem;font-weight:bold}.controls>*>label{margin-bottom:.2rem}[data-page="admin-system-opkg"] div.btn{line-height:3;display:inline;padding:.3rem .6rem}[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{margin-top:1rem;padding-top:.01rem}[data-page="admin-system-opkg"] #maincontent>.container{margin:0 1.25rem 1rem 1.25rem;margin-bottom:1rem}.td.version,.td.size{white-space:normal !important;word-break:break-word}.cbi-tabmenu+.cbi-section{margin-top:0}[data-page="admin-system-system"] .control-group{margin-top:.5rem}[data-page="admin-system-system"] .cbi-dynlist{margin:.25rem 0}[data-page="admin-system-startup"] [data-tab-title] p{margin-left:0;margin-bottom:0;position:relative}[data-page="admin-system-startup"] textarea{line-height:1.25;overflow-y:auto;width:100%;min-height:15rem;padding:1rem;resize:none;color:#8898aa;border-radius:.25rem;border:1px solid #dee2e6}[data-page="admin-system-startup"] textarea:focus-visible{outline:none;box-shadow:none;border:1px solid var(--primary)}[data-page="admin-system-crontab"] #view p{margin-bottom:1rem}[data-page="admin-system-crontab"] #view p:last-child{margin-bottom:0}[data-page="admin-system-crontab"] #view p textarea{line-height:1.25;overflow-y:hidden;width:100%;min-height:15rem;padding:1rem;resize:none;background-color:transparent;background:var(--white);outline:none;color:#8898aa;border-radius:.25rem;border:1px solid #dee2e6}[data-page="admin-system-attendedsysupgrade-configuration"] .cbi-map .cbi-map-descr{padding-bottom:0}[data-page="admin-system-flash"] .cbi-value{padding:0}[data-page="admin-system-flash"] .cbi-section .cbi-section{margin-top:0}[data-page="admin-system-flash"] .cbi-map-tabbed{border-radius:.25rem}[data-page="admin-system-flash"] .cbi-section-node{padding-top:0;padding-bottom:.5rem}[data-page="admin-system-flash"] legend{display:block !important;font-size:1.2rem;width:100%;display:block;margin-bottom:0;padding:1rem 0 1rem 1.5rem;border-bottom:1px solid rgba(0,0,0,0.05);line-height:1.5;margin-bottom:0rem;letter-spacing:.1rem;color:#32325d;font-weight:bold}[data-page="admin-system-flash"] .cbi-section-descr{font-weight:600;padding:1rem 0 1rem 1.5rem;color:#525f7f}[data-page="admin-system-flash"] .cbi-page-actions{padding:0rem 1rem 1rem 0rem}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.25rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal !important}#cbi-wireless>#wifi_assoclist_table>.tr{box-shadow:inset 1px -1px 0 #ddd,inset -1px -1px 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td{right:33px;bottom:33px;left:33px;border-top:thin solid #ddd !important}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles{box-shadow:inset 1px 0 0 #ddd,inset -1px 0 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th{border-bottom:thin solid #ddd;box-shadow:0 -1px 0 0 #ddd}#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"]{width:23rem}[data-page="admin-network-dhcp"] .cbi-value{padding:0}[data-page="admin-network-dhcp"] [data-tab-active="true"]{padding:1rem 0 !important}#iptables{margin:0}.Firewall form{margin:2rem 2rem 0 0;padding:0;box-shadow:none}#cbi-firewall-redirect table *,#cbi-network-switch_vlan table *,#cbi-firewall-zone table *{font-size:small}#cbi-firewall-redirect table input[type="text"],#cbi-network-switch_vlan table input[type="text"],#cbi-firewall-zone table input[type="text"]{width:5rem}#cbi-firewall-redirect table select,#cbi-network-switch_vlan table select,#cbi-firewall-zone table select{min-width:3.5rem}#cbi-network-switch_vlan .th,#cbi-network-switch_vlan .td{flex-basis:12%}#cbi-firewall-zone .table,#cbi-network-switch_vlan .table{display:block}#cbi-firewall-zone .td,#cbi-network-switch_vlan .td{width:100%}[data-page="admin-network-firewall-custom"] #view p,[data-page="admin-status-routes"] #view p{padding:0 1.5rem;margin-bottom:1rem}[data-page="admin-network-firewall-custom"] #view p textarea,[data-page="admin-status-routes"] #view p textarea{padding:1rem;border-radius:.25rem}[data-page="admin-network-firewall-custom"] #view>h3,[data-page="admin-status-routes"] #view>h3{border-radius:.25rem .25rem 0 0}#applyreboot-container{margin:2rem}#applyreboot-section{line-height:300%;margin:2rem}.OpenVPN a{line-height:initial !important}.commandbox{width:24% !important;margin:10px 0 0 10px !important;padding:.5rem 1rem;border-bottom:thin solid #ccc;background:#eee;box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.commandbox h3{line-height:normal !important;overflow:hidden;margin:6px 0 !important;white-space:nowrap;text-overflow:ellipsis}.commandbox div{left:auto !important}.commandbox code{position:absolute;overflow:hidden;max-width:60%;margin-left:4px;padding:2px 3px;white-space:nowrap;text-overflow:ellipsis}.commandbox code:hover{overflow-y:auto;max-height:50px;white-space:normal}.commandbox p:first-of-type{margin-top:-6px}.commandbox p:nth-of-type(2){margin-top:2px}[data-page^="admin-system-commands"] .panel-title,[data-page^="command-cfg"] .mobile-hide,[data-page^="command-cfg"] .showSide{display:none}#command-rc-output .alert-message{line-height:1.42857143;position:absolute;top:40px;right:32px;max-width:40%;margin:0;animation:anim-fade-in 1.5s forwards;word-break:break-word;opacity:0}@keyframes anim-fade-in{100%{opacity:1}}input[type="checkbox"]{appearance:none !important;-webkit-appearance:none !important;border:1px solid var(--primary);width:16px !important;height:16px !important;padding:0;cursor:pointer;transition:all .2s;margin:.75rem 0 0 0}input[type="checkbox"]:checked{border:1px solid #5e72e4;border:1px solid var(--primary);background-image:url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important;background-color:#5e72e4;background-color:var(--primary);background-size:70%;background-repeat:no-repeat;background-position:center}.fb-container .cbi-button{height:auto !important}#cbi-usb_printer-printer em{display:block;padding:1rem;text-align:center}pre.command-output{padding:1.5rem}[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"]{padding:1.5rem !important}[data-page="admin-nlbw-backup"] form{padding-left:1.5rem}[data-page="admin-status-iptables"] .right{margin-bottom:0 !important}[data-page="admin-services-ttyd"] .container{display:flex;flex-direction:column}[data-page="admin-services-ttyd"] #view{flex:1}[data-page="admin-services-ttyd"] #view iframe{height:100%}[data-page="admin-system-fileassistant"] .fb-container .panel-title{padding:.5rem .75rem !important}[data-page="admin-system-fileassistant"] .cbi-section.fb-container{padding:.5rem}[data-page="admin-system-fileassistant"] .fb-container .panel-container{border-bottom-color:#dee2e6}[data-page^="admin-services-openclash"] .cbi-tabmenu>li{border-right:none !important;margin:0 .4rem 0 0 !important}[data-page^="admin-services-openclash"] .cbi-tabmenu>li:last-child{margin-right:0 !important}[data-page^="admin-services-openclash"] #tab-content .dom{padding:0 1rem 1rem 1rem}[data-page^="admin-services-openclash"] .cbi-input-file{padding:.2813rem;box-sizing:content-box;width:15rem !important}[data-page^="admin-services-openclash"] [id="container.openclash.config.debug"] fieldset{border:none !important;padding:1rem !important}[data-page^="admin-services-openclash"] #diag-rc-output>pre,[data-page^="admin-services-openclash"] #dns-rc-output>pre{font-size:.875rem;color:#8898aa;border:1px solid #dee2e6;background-color:transparent;border-radius:.25rem;font-family:'argon' !important;box-shadow:none}[data-page^="admin-services-openclash"] #debug-rc-output>textarea{font-family:'argon' !important}[data-page^="admin-services-openclash"] .CodeMirror{font-size:inherit;font-family:'argon' !important}[data-page^="admin-services-openclash"] .cbi-button-up,[data-page^="admin-services-openclash"] .cbi-button-down{padding:.8rem 1.5rem;background-color:#f1f1f1;font-size:0}[data-page^="admin-services-openclash"] select#CORE_VERSION,[data-page^="admin-services-openclash"] select#RELEASE_BRANCH{width:auto}@media all and (-ms-high-contrast:none){.main>.main-left>.nav>.slide>.menu::before{top:30.25%}.main>.main-left>.nav>li:last-child::before{top:20%}.showSide::before{top:-12px}}@media screen and (max-width:1600px){header>.fill>.container>#logo{margin:0 2.5rem 0 .5rem}.main-left{width:calc(0% + 13rem)}.btn:not(button),.label{padding:.5rem .75rem}.cbi-value-title{width:15rem;padding-right:.6rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"],.cbi-value textarea{min-width:18rem}#cbi-firewall-zone .cbi-input-select{min-width:9rem}.cbi-input-textarea{font-size:small}.node-admin-status>.main fieldset li>a{padding:.3rem .6rem}}@media screen and (max-width:1366px){header>.fill>.container{cursor:default}.main-left{width:calc(0% + 13rem)}.tabs>li>a,.cbi-tabmenu>li>a{padding:.2rem .8rem}.panel-title{font-size:1.1rem;padding-bottom:1rem}table{font-size:.875rem !important;width:100% !important}.table .cbi-input-text{width:100%}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:16rem}#cbi-firewall-zone .cbi-input-select{min-width:4rem}.main>.main-left>.nav>li,.main>.main-left>.nav>li>a,.main .main-left .nav>li>a:first-child,.main>.main-left>.nav>.slide>.menu,.main>.main-left>.nav>li>[data-title="Log_out"]{font-size:.9rem}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.875rem}#modal_overlay{top:0rem}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table){display:block}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table),[data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table),[data-page="admin-network-hosts"] .table,[data-page="admin-network-routes"] .table{overflow-y:visible}.commandbox{width:32% !important}.btn:not(button),.cbi-button{font-size:.875rem}}@media screen and (max-width:1152px){header>.fill>.container>#logo{display:none}header>.fill>.container>.brand{position:relative}html,.main{overflow-y:visible}.main>.loading>span{top:25%}.main-left{width:calc(0% + 13rem)}body:not(.logged-in) .showSide{visibility:hidden;width:0;margin:0}.node-main-login>.main .cbi-value-title{text-align:left}.cbi-value-title{width:12rem;padding-right:1rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"]{width:16rem;min-width:16rem}.cbi-value input[name^="pw"],.cbi-value input[data-update="change"]:nth-child(2){width:13rem !important;min-width:13rem}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1rem}.table{display:block}.Interfaces .table{overflow-x:hidden}#packages.table{display:grid}.tr{display:flex;flex-direction:row;flex-wrap:wrap}.Overview .table[width="100%"]>.tr{flex-wrap:nowrap}.tr.placeholder{border-bottom:thin solid #ddd}.tr.placeholder>.td,#cbi-firewall .tr>.td,#cbi-network .tr:nth-child(2)>.td,.cbi-section #wifi_assoclist_table .tr>.td{border-top:0}.th,.td{display:inline-block;align-self:flex-start;flex:2 2 10%;text-overflow:ellipsis;word-wrap:break-word}.td select,.td input[type="text"]{width:100%;word-wrap:normal}.td [data-dynlist]>input,.td input.cbi-input-password{width:calc(100% - 1.5rem)}.td[data-type="button"],.td[data-type="fvalue"]{flex:1 1 12.5%;text-align:left}.th.cbi-value-field,.td.cbi-value-field,.th.cbi-section-table-cell,.td.cbi-section-table-cell{flex-basis:auto;padding-top:1rem}.cbi-section-table-row{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.td.cbi-value-field,.cbi-section-table-cell{display:inline-block;flex:10 10 auto;flex-basis:50%;text-align:center}.td.cbi-section-actions{vertical-align:bottom}.tr.table-titles,.tr.cbi-section-table-titles,.tr.cbi-section-table-descr{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-size:.9rem;display:block;flex:1 1 100%;border-bottom:thin solid rgba(0,0,0,0.26);background:#e9ecef}.td[data-title],[data-page^="admin-status-realtime"] .td[id]{text-align:left}.td[data-title]::before{display:block}.cbi-button+.cbi-button{margin-left:0}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:2.1px 3px}.Firewall form{position:static !important;margin:0 0 2rem 0;padding:2rem;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.Firewall form input{width:100% !important;margin:0;margin-top:1rem}.Firewall .center,.Firewall .center::before{text-align:left !important}.commandbox{width:100% !important;margin-left:0 !important}.btn:not(button),.cbi-button{font-size:.875rem}}@media screen and (max-width:768px){body{font-size:.875rem}.cbi-progressbar::after{font-size:.6rem}.main-left{position:fixed;z-index:100;width:0}.main-left.active{width:13rem}.main-right{width:100%}.main-right.active{overflow-y:hidden}.darkMask.active{display:block}.showSide{padding:.1rem;position:relative;z-index:99;display:inline-block !important}.showSide::before{font-family:'argon' !important;font-style:normal !important;font-weight:normal !important;font-variant:normal !important;text-transform:none !important;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\e20e";font-size:1.7rem}header>.fill>.container>.flex1>.brand{display:inline-block}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.875rem}}@media screen and (max-width:600px){.mobile-hide{display:none}#maincontent>.container{margin:0 1rem 1rem 1rem}.cbi-value-title{text-align:left}[data-page="admin-system-flash"] legend{padding:1rem 0 1rem 1rem}[data-page="admin-system-flash"] .cbi-section-descr{padding:1rem 0 1rem 1rem}[data-page="admin-system-flash"] .cbi-value{padding:0 1rem}[data-page="admin-network-dhcp"] [data-tab-active="true"]{padding:1rem 1rem !important}.cbi-dynlist p{padding:.5rem 1rem}body{overflow-x:hidden}.node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field{width:16rem}.node-main-login footer{display:none}.tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar{width:0px;height:0px}.cbi-value-field,.cbi-value-description{display:block !important;padding-left:0 !important;padding-right:0 !important}[data-page="admin-system-admin-password"] .cbi-value-field{display:table-cell !important}.modal.cbi-modal{max-width:100%;max-height:none}.modal{display:flex;align-items:center;flex-wrap:wrap;width:100%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1em;border-radius:3px !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.cbi-dropdown[open]>ul.dropdown{margin-bottom:1rem}.login-page .login-container footer{display:none}}@media screen and (min-width:600px){::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar,::-webkit-scrollbar-corner{background:transparent}::-webkit-scrollbar-thumb{background:var(--primary);border-radius:10px}::-webkit-scrollbar-thumb:hover{background:var(--primary)}::-webkit-scrollbar-thumb:active{background:var(--primary)}}@media screen and (max-width:480px){.mobile-hide{display:none}.login-page .login-container{margin-left:0rem !important;width:100%}.login-page .login-container .login-form .form-login .input-group::before{color:#525461}.login-page .login-container .login-form .form-login .input-group input{color:#525461;border-bottom:white 1px solid;border-bottom:var(--white) 1px solid;border-radius:0}} \ No newline at end of file +*/ /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html { + line-height: 1.15; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +main { + display: block; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +hr { + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0; + overflow: visible; +} +pre { + font-family: monospace, monospace; + font-size: 1em; +} +a { + background-color: transparent; +} +abbr[title] { + border-bottom: none; + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} +b, +strong { + font-weight: bolder; +} +code, +kbd, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +img { + border-style: none; +} +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + font-size: 100%; + line-height: 1.15; + margin: 0; +} +button, +input { + overflow: visible; +} +button, +select { + text-transform: none; +} +[type="button"], +[type="reset"], +[type="submit"], +button { + -webkit-appearance: button; +} +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner, +button::-moz-focus-inner { + border-style: none; + padding: 0; +} +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring, +button:-moz-focusring { + outline: 1px dotted ButtonText; +} +fieldset { + padding: 0.35em 0.75em 0.625em; +} +legend { + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal; +} +progress { + vertical-align: baseline; +} +textarea { + overflow: auto; +} +[type="checkbox"], +[type="radio"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; +} +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} +details { + display: block; +} +summary { + display: list-item; +} +template { + display: none; +} +[hidden] { + display: none; +} +html { + font-family: sans-serif; +} +.hidden, +[hidden] { + display: none !important; +} +.pure-img { + max-width: 100%; + height: auto; +} +.pure-g { + letter-spacing: -0.31em; + text-rendering: optimizespeed; + font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-line-pack: start; + align-content: flex-start; +} +@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { + table .pure-g { + display: block; + } +} +.opera-only :-o-prefocus, +.pure-g { + word-spacing: -0.43em; +} +.pure-u { + display: inline-block; + letter-spacing: normal; + word-spacing: normal; + vertical-align: top; + text-rendering: auto; +} +.pure-g [class*="pure-u"] { + font-family: sans-serif; +} +.pure-u-1, +.pure-u-1-1, +.pure-u-1-12, +.pure-u-1-2, +.pure-u-1-24, +.pure-u-1-3, +.pure-u-1-4, +.pure-u-1-5, +.pure-u-1-6, +.pure-u-1-8, +.pure-u-10-24, +.pure-u-11-12, +.pure-u-11-24, +.pure-u-12-24, +.pure-u-13-24, +.pure-u-14-24, +.pure-u-15-24, +.pure-u-16-24, +.pure-u-17-24, +.pure-u-18-24, +.pure-u-19-24, +.pure-u-2-24, +.pure-u-2-3, +.pure-u-2-5, +.pure-u-20-24, +.pure-u-21-24, +.pure-u-22-24, +.pure-u-23-24, +.pure-u-24-24, +.pure-u-3-24, +.pure-u-3-4, +.pure-u-3-5, +.pure-u-3-8, +.pure-u-4-24, +.pure-u-4-5, +.pure-u-5-12, +.pure-u-5-24, +.pure-u-5-5, +.pure-u-5-6, +.pure-u-5-8, +.pure-u-6-24, +.pure-u-7-12, +.pure-u-7-24, +.pure-u-7-8, +.pure-u-8-24, +.pure-u-9-24 { + display: inline-block; + letter-spacing: normal; + word-spacing: normal; + vertical-align: top; + text-rendering: auto; +} +.pure-u-1-24 { + width: 4.1667%; +} +.pure-u-1-12, +.pure-u-2-24 { + width: 8.3333%; +} +.pure-u-1-8, +.pure-u-3-24 { + width: 12.5%; +} +.pure-u-1-6, +.pure-u-4-24 { + width: 16.6667%; +} +.pure-u-1-5 { + width: 20%; +} +.pure-u-5-24 { + width: 20.8333%; +} +.pure-u-1-4, +.pure-u-6-24 { + width: 25%; +} +.pure-u-7-24 { + width: 29.1667%; +} +.pure-u-1-3, +.pure-u-8-24 { + width: 33.3333%; +} +.pure-u-3-8, +.pure-u-9-24 { + width: 37.5%; +} +.pure-u-2-5 { + width: 40%; +} +.pure-u-10-24, +.pure-u-5-12 { + width: 41.6667%; +} +.pure-u-11-24 { + width: 45.8333%; +} +.pure-u-1-2, +.pure-u-12-24 { + width: 50%; +} +.pure-u-13-24 { + width: 54.1667%; +} +.pure-u-14-24, +.pure-u-7-12 { + width: 58.3333%; +} +.pure-u-3-5 { + width: 60%; +} +.pure-u-15-24, +.pure-u-5-8 { + width: 62.5%; +} +.pure-u-16-24, +.pure-u-2-3 { + width: 66.6667%; +} +.pure-u-17-24 { + width: 70.8333%; +} +.pure-u-18-24, +.pure-u-3-4 { + width: 75%; +} +.pure-u-19-24 { + width: 79.1667%; +} +.pure-u-4-5 { + width: 80%; +} +.pure-u-20-24, +.pure-u-5-6 { + width: 83.3333%; +} +.pure-u-21-24, +.pure-u-7-8 { + width: 87.5%; +} +.pure-u-11-12, +.pure-u-22-24 { + width: 91.6667%; +} +.pure-u-23-24 { + width: 95.8333%; +} +.pure-u-1, +.pure-u-1-1, +.pure-u-24-24, +.pure-u-5-5 { + width: 100%; +} +.pure-button { + display: inline-block; + line-height: normal; + white-space: nowrap; + vertical-align: middle; + text-align: center; + cursor: pointer; + -webkit-user-drag: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.pure-button::-moz-focus-inner { + padding: 0; + border: 0; +} +.pure-button-group { + letter-spacing: -0.31em; + text-rendering: optimizespeed; +} +.opera-only :-o-prefocus, +.pure-button-group { + word-spacing: -0.43em; +} +.pure-button-group .pure-button { + letter-spacing: normal; + word-spacing: normal; + vertical-align: top; + text-rendering: auto; +} +.pure-button { + font-family: inherit; + font-size: 100%; + padding: 0.5em 1em; + color: rgba(0, 0, 0, 0.8); + border: none transparent; + background-color: #e6e6e6; + text-decoration: none; + border-radius: 2px; +} +.pure-button-hover, +.pure-button:focus, +.pure-button:hover { + background-image: -webkit-gradient( + linear, + left top, + left bottom, + from(transparent), + color-stop(40%, rgba(0, 0, 0, 0.05)), + to(rgba(0, 0, 0, 0.1)) + ); + background-image: linear-gradient( + transparent, + rgba(0, 0, 0, 0.05) 40%, + rgba(0, 0, 0, 0.1) + ); +} +.pure-button:focus { + outline: 0; +} +.pure-button-active, +.pure-button:active { + -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15) inset, + 0 0 6px rgba(0, 0, 0, 0.2) inset; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15) inset, + 0 0 6px rgba(0, 0, 0, 0.2) inset; + border-color: #000; +} +.pure-button-disabled, +.pure-button-disabled:active, +.pure-button-disabled:focus, +.pure-button-disabled:hover, +.pure-button[disabled] { + border: none; + background-image: none; + opacity: 0.4; + cursor: not-allowed; + -webkit-box-shadow: none; + box-shadow: none; + pointer-events: none; +} +.pure-button-hidden { + display: none; +} +.pure-button-primary, +.pure-button-selected, +a.pure-button-primary, +a.pure-button-selected { + background-color: #0078e7; + color: #fff; +} +.pure-button-group .pure-button { + margin: 0; + border-radius: 0; + border-right: 1px solid rgba(0, 0, 0, 0.2); +} +.pure-button-group .pure-button:first-child { + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} +.pure-button-group .pure-button:last-child { + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; + border-right: none; +} +.pure-form input[type="color"], +.pure-form input[type="date"], +.pure-form input[type="datetime-local"], +.pure-form input[type="datetime"], +.pure-form input[type="email"], +.pure-form input[type="month"], +.pure-form input[type="number"], +.pure-form input[type="password"], +.pure-form input[type="search"], +.pure-form input[type="tel"], +.pure-form input[type="text"], +.pure-form input[type="time"], +.pure-form input[type="url"], +.pure-form input[type="week"], +.pure-form select, +.pure-form textarea { + padding: 0.5em 0.6em; + display: inline-block; + border: 1px solid #ccc; + -webkit-box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px #ddd; + border-radius: 4px; + vertical-align: middle; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.pure-form input:not([type]) { + padding: 0.5em 0.6em; + display: inline-block; + border: 1px solid #ccc; + -webkit-box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px #ddd; + border-radius: 4px; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.pure-form input[type="color"] { + padding: 0.2em 0.5em; +} +.pure-form input[type="color"]:focus, +.pure-form input[type="date"]:focus, +.pure-form input[type="datetime-local"]:focus, +.pure-form input[type="datetime"]:focus, +.pure-form input[type="email"]:focus, +.pure-form input[type="month"]:focus, +.pure-form input[type="number"]:focus, +.pure-form input[type="password"]:focus, +.pure-form input[type="search"]:focus, +.pure-form input[type="tel"]:focus, +.pure-form input[type="text"]:focus, +.pure-form input[type="time"]:focus, +.pure-form input[type="url"]:focus, +.pure-form input[type="week"]:focus, +.pure-form select:focus, +.pure-form textarea:focus { + outline: 0; + border-color: #129fea; +} +.pure-form input:not([type]):focus { + outline: 0; + border-color: #129fea; +} +.pure-form input[type="checkbox"]:focus, +.pure-form input[type="file"]:focus, +.pure-form input[type="radio"]:focus { + outline: thin solid #129fea; + outline: 1px auto #129fea; +} +.pure-form .pure-checkbox, +.pure-form .pure-radio { + margin: 0.5em 0; + display: block; +} +.pure-form input[type="color"][disabled], +.pure-form input[type="date"][disabled], +.pure-form input[type="datetime-local"][disabled], +.pure-form input[type="datetime"][disabled], +.pure-form input[type="email"][disabled], +.pure-form input[type="month"][disabled], +.pure-form input[type="number"][disabled], +.pure-form input[type="password"][disabled], +.pure-form input[type="search"][disabled], +.pure-form input[type="tel"][disabled], +.pure-form input[type="text"][disabled], +.pure-form input[type="time"][disabled], +.pure-form input[type="url"][disabled], +.pure-form input[type="week"][disabled], +.pure-form select[disabled], +.pure-form textarea[disabled] { + cursor: not-allowed; + background-color: #eaeded; + color: #cad2d3; +} +.pure-form input:not([type])[disabled] { + cursor: not-allowed; + background-color: #eaeded; + color: #cad2d3; +} +.pure-form input[readonly], +.pure-form select[readonly], +.pure-form textarea[readonly] { + background-color: #eee; + color: #777; + border-color: #ccc; +} +.pure-form input:focus:invalid, +.pure-form select:focus:invalid, +.pure-form textarea:focus:invalid { + color: #b94a48; + border-color: #e9322d; +} +.pure-form input[type="checkbox"]:focus:invalid:focus, +.pure-form input[type="file"]:focus:invalid:focus, +.pure-form input[type="radio"]:focus:invalid:focus { + outline-color: #e9322d; +} +.pure-form select { + height: 2.25em; + border: 1px solid #ccc; + background-color: #fff; +} +.pure-form select[multiple] { + height: auto; +} +.pure-form label { + margin: 0.5em 0 0.2em; +} +.pure-form fieldset { + margin: 0; + padding: 0.35em 0 0.75em; + border: 0; +} +.pure-form legend { + display: block; + width: 100%; + padding: 0.3em 0; + margin-bottom: 0.3em; + color: #333; + border-bottom: 1px solid #e5e5e5; +} +.pure-form-stacked input[type="color"], +.pure-form-stacked input[type="date"], +.pure-form-stacked input[type="datetime-local"], +.pure-form-stacked input[type="datetime"], +.pure-form-stacked input[type="email"], +.pure-form-stacked input[type="file"], +.pure-form-stacked input[type="month"], +.pure-form-stacked input[type="number"], +.pure-form-stacked input[type="password"], +.pure-form-stacked input[type="search"], +.pure-form-stacked input[type="tel"], +.pure-form-stacked input[type="text"], +.pure-form-stacked input[type="time"], +.pure-form-stacked input[type="url"], +.pure-form-stacked input[type="week"], +.pure-form-stacked label, +.pure-form-stacked select, +.pure-form-stacked textarea { + display: block; + margin: 0.25em 0; +} +.pure-form-stacked input:not([type]) { + display: block; + margin: 0.25em 0; +} +.pure-form-aligned input, +.pure-form-aligned select, +.pure-form-aligned textarea, +.pure-form-message-inline { + display: inline-block; + vertical-align: middle; +} +.pure-form-aligned textarea { + vertical-align: top; +} +.pure-form-aligned .pure-control-group { + margin-bottom: 0.5em; +} +.pure-form-aligned .pure-control-group label { + text-align: right; + display: inline-block; + vertical-align: middle; + width: 10em; + margin: 0 1em 0 0; +} +.pure-form-aligned .pure-controls { + margin: 1.5em 0 0 11em; +} +.pure-form .pure-input-rounded, +.pure-form input.pure-input-rounded { + border-radius: 2em; + padding: 0.5em 1em; +} +.pure-form .pure-group fieldset { + margin-bottom: 10px; +} +.pure-form .pure-group input, +.pure-form .pure-group textarea { + display: block; + padding: 10px; + margin: 0 0 -1px; + border-radius: 0; + position: relative; + top: -1px; +} +.pure-form .pure-group input:focus, +.pure-form .pure-group textarea:focus { + z-index: 3; +} +.pure-form .pure-group input:first-child, +.pure-form .pure-group textarea:first-child { + top: 1px; + border-radius: 4px 4px 0 0; + margin: 0; +} +.pure-form .pure-group input:first-child:last-child, +.pure-form .pure-group textarea:first-child:last-child { + top: 1px; + border-radius: 4px; + margin: 0; +} +.pure-form .pure-group input:last-child, +.pure-form .pure-group textarea:last-child { + top: -2px; + border-radius: 0 0 4px 4px; + margin: 0; +} +.pure-form .pure-group button { + margin: 0.35em 0; +} +.pure-form .pure-input-1 { + width: 100%; +} +.pure-form .pure-input-3-4 { + width: 75%; +} +.pure-form .pure-input-2-3 { + width: 66%; +} +.pure-form .pure-input-1-2 { + width: 50%; +} +.pure-form .pure-input-1-3 { + width: 33%; +} +.pure-form .pure-input-1-4 { + width: 25%; +} +.pure-form-message-inline { + display: inline-block; + padding-left: 0.3em; + color: #666; + vertical-align: middle; + font-size: 0.875em; +} +.pure-form-message { + display: block; + color: #666; + font-size: 0.875em; +} +@media only screen and (max-width: 480px) { + .pure-form button[type="submit"] { + margin: 0.7em 0 0; + } + .pure-form input:not([type]), + .pure-form input[type="color"], + .pure-form input[type="date"], + .pure-form input[type="datetime-local"], + .pure-form input[type="datetime"], + .pure-form input[type="email"], + .pure-form input[type="month"], + .pure-form input[type="number"], + .pure-form input[type="password"], + .pure-form input[type="search"], + .pure-form input[type="tel"], + .pure-form input[type="text"], + .pure-form input[type="time"], + .pure-form input[type="url"], + .pure-form input[type="week"], + .pure-form label { + margin-bottom: 0.3em; + display: block; + } + .pure-group input:not([type]), + .pure-group input[type="color"], + .pure-group input[type="date"], + .pure-group input[type="datetime-local"], + .pure-group input[type="datetime"], + .pure-group input[type="email"], + .pure-group input[type="month"], + .pure-group input[type="number"], + .pure-group input[type="password"], + .pure-group input[type="search"], + .pure-group input[type="tel"], + .pure-group input[type="text"], + .pure-group input[type="time"], + .pure-group input[type="url"], + .pure-group input[type="week"] { + margin-bottom: 0; + } + .pure-form-aligned .pure-control-group label { + margin-bottom: 0.3em; + text-align: left; + display: block; + width: 100%; + } + .pure-form-aligned .pure-controls { + margin: 1.5em 0 0 0; + } + .pure-form-message, + .pure-form-message-inline { + display: block; + font-size: 0.75em; + padding: 0.2em 0 0.8em; + } +} +.pure-menu { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.pure-menu-fixed { + position: fixed; + left: 0; + top: 0; + z-index: 3; +} +.pure-menu-item, +.pure-menu-list { + position: relative; +} +.pure-menu-list { + list-style: none; + margin: 0; + padding: 0; +} +.pure-menu-item { + padding: 0; + margin: 0; + height: 100%; +} +.pure-menu-heading, +.pure-menu-link { + display: block; + text-decoration: none; + white-space: nowrap; +} +.pure-menu-horizontal { + width: 100%; + white-space: nowrap; +} +.pure-menu-horizontal .pure-menu-list { + display: inline-block; +} +.pure-menu-horizontal .pure-menu-heading, +.pure-menu-horizontal .pure-menu-item, +.pure-menu-horizontal .pure-menu-separator { + display: inline-block; + vertical-align: middle; +} +.pure-menu-item .pure-menu-item { + display: block; +} +.pure-menu-children { + display: none; + position: absolute; + left: 100%; + top: 0; + margin: 0; + padding: 0; + z-index: 3; +} +.pure-menu-horizontal .pure-menu-children { + left: 0; + top: auto; + width: inherit; +} +.pure-menu-active > .pure-menu-children, +.pure-menu-allow-hover:hover > .pure-menu-children { + display: block; + position: absolute; +} +.pure-menu-has-children > .pure-menu-link:after { + padding-left: 0.5em; + content: "\25B8"; + font-size: small; +} +.pure-menu-horizontal .pure-menu-has-children > .pure-menu-link:after { + content: "\25BE"; +} +.pure-menu-scrollable { + overflow-y: scroll; + overflow-x: hidden; +} +.pure-menu-scrollable .pure-menu-list { + display: block; +} +.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list { + display: inline-block; +} +.pure-menu-horizontal.pure-menu-scrollable { + white-space: nowrap; + overflow-y: hidden; + overflow-x: auto; + padding: 0.5em 0; +} +.pure-menu-horizontal .pure-menu-children .pure-menu-separator, +.pure-menu-separator { + background-color: #ccc; + height: 1px; + margin: 0.3em 0; +} +.pure-menu-horizontal .pure-menu-separator { + width: 1px; + height: 1.3em; + margin: 0 0.3em; +} +.pure-menu-horizontal .pure-menu-children .pure-menu-separator { + display: block; + width: auto; +} +.pure-menu-heading { + text-transform: uppercase; + color: #565d64; +} +.pure-menu-link { + color: #777; +} +.pure-menu-children { + background-color: #fff; +} +.pure-menu-disabled, +.pure-menu-heading, +.pure-menu-link { + padding: 0.5em 1em; +} +.pure-menu-disabled { + opacity: 0.5; +} +.pure-menu-disabled .pure-menu-link:hover { + background-color: transparent; +} +.pure-menu-active > .pure-menu-link, +.pure-menu-link:focus, +.pure-menu-link:hover { + background-color: #eee; +} +.pure-menu-selected > .pure-menu-link, +.pure-menu-selected > .pure-menu-link:visited { + color: #000; +} +.pure-table { + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + border: 1px solid #cbcbcb; +} +.pure-table caption { + color: #000; + font: italic 85%/1 arial, sans-serif; + padding: 1em 0; + text-align: center; +} +.pure-table td, +.pure-table th { + border-left: 1px solid #cbcbcb; + border-width: 0 0 0 1px; + font-size: inherit; + margin: 0; + overflow: visible; + padding: 0.5em 1em; +} +.pure-table thead { + background-color: #e0e0e0; + color: #000; + text-align: left; + vertical-align: bottom; +} +.pure-table td { + background-color: transparent; +} +.pure-table-odd td { + background-color: #f2f2f2; +} +.pure-table-striped tr:nth-child(2n-1) td { + background-color: #f2f2f2; +} +.pure-table-bordered td { + border-bottom: 1px solid #cbcbcb; +} +.pure-table-bordered tbody > tr:last-child > td { + border-bottom-width: 0; +} +.pure-table-horizontal td, +.pure-table-horizontal th { + border-width: 0 0 1px 0; + border-bottom: 1px solid #cbcbcb; +} +.pure-table-horizontal tbody > tr:last-child > td { + border-bottom-width: 0; +} +@font-face { + font-family: "Google Sans"; + src: url("data:application/font-woff2;charset=utf-8;base64,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") + format("woff2"), + url("data:application/font-woff;charset=utf-8;base64,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") + format("woff"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "TypoGraphica"; + src: url("../fonts/TypoGraphica.eot?#iefix") format("embedded-opentype"), + url("../fonts/TypoGraphica.woff") format("woff"), + url("../fonts/TypoGraphica.ttf") format("truetype"), + url("../fonts/TypoGraphica.svg#TypoGraphica") format("svg"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "argon"; + src: url("../fonts/argon.eot?u6kthm"); + src: url("../fonts/argon.eot?u6kthm#iefix") format("embedded-opentype"), + url("../fonts/argon.ttf?u6kthm") format("truetype"), + url("../fonts/argon.woff?u6kthm") format("woff"), + url("../fonts/argon.svg?u6kthm#argon") format("svg"); + font-weight: normal; + font-style: normal; + font-display: block; +} +[class^="icon-"], +[class*=" icon-"] { + font-family: "argon" !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.icon-expand_more:before { + content: "\e20b"; +} +.icon-menu:before { + content: "\e20e"; +} +.icon-favorite:before { + content: "\e291"; +} +.icon-spinner:before { + content: "\e603"; +} +.icon-delete:before { + content: "\e900"; +} +.icon-edit:before { + content: "\e901"; +} +.icon-use:before { + content: "\e902"; +} +.icon-loading:before { + content: "\e903"; +} +.icon-switch:before { + content: "\e904"; +} +.icon-error:before { + content: "\e905"; +} +.icon-dashboard:before { + content: "\e906"; +} +.icon-logout:before { + content: "\e907"; +} +.icon-Network:before { + content: "\e908"; +} +.icon-services:before { + content: "\e909"; +} +.icon-system:before { + content: "\e90a"; +} +.icon-vpn:before { + content: "\e90b"; +} +.icon-storage:before { + content: "\e90c"; +} +.icon-statistics:before { + content: "\e90d"; +} +.icon-hello-world:before { + content: "\e90e"; +} +.icon-angle-right:before { + content: "\e90f"; +} +.icon-password:before { + content: "\e910"; +} +.icon-user:before { + content: "\e971"; +} +.icon-question:before { + content: "\f059"; +} +.icon-docker:before { + content: "\e911"; +} +.icon-control:before { + content: "\e912"; +} +.icon-statistics1:before { + content: "\e913"; +} +.icon-asterisk:before { + content: "\e914"; +} +.icon-app:before { + content: "\e915"; +} +:root { + --primary: #5e72e4; + --dark-primary: #483d8b; + --main-color: #09c; + --header-bg: #09c; + --header-color: #fff; + --bar-bg: #5e72e4; + --menu-bg-color: #fff; + --menu-color: #5f6368; + --menu-color-hover: #202124; + --main-menu-color: #202124; + --submenu-bg-hover: #d4d4d4; + --submenu-bg-hover-active: #09c; + --blue: #5e72e4; + --indigo: #5603ad; + --purple: #8965e0; + --pink: #f3a4b5; + --red: #f5365c; + --orange: #fb6340; + --yellow: #ffd600; + --green: #2dce89; + --teal: #11cdef; + --cyan: #2bffc6; + --gray: #8898aa; + --gray-dark: #32325d; + --light: #ced4da; + --lighter: #e9ecef; + --secondary: #f7fafc; + --success: #2dce89; + --info: #11cdef; + --warning: #fb6340; + --danger: #f5365c; + --light: #adb5bd; + --dark: #212529; + --default: #172b4d; + --white: #fff; + --neutral: #fff; + --darker: black; + --background-color: #f4f5f7; + --login-form-bg-color: rgba(244, 245, 247, 0.8); + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --blur-radius: 10px; + --blur-opacity: 0.5; + --blur-radius-dark: 10px; + --blur-opacity-dark: 0.5; + --font-family-sans-serif: "Google Sans", "Microsoft Yahei", + "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", + "Hiragino Sans GB"; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, + "Liberation Mono", "Courier New", monospace; + --font-family-normal: Open Sans, PingFangSC-Regular, Microsoft Yahei, + WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, + sans-serif; +} +* { + margin: 0px; + padding: 0px; + box-sizing: border-box; +} +html, +body { + margin: 0px; + padding: 0px; + height: 100%; + font-size: 16px; + font-family: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", + "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; + font-family: var(--font-family-sans-serif); +} +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + font-size: 0.875rem; + background-color: #f4f5f7; + background-color: var(--background-color); + color: #32325d; + color: var(--gray-dark); + -webkit-tap-highlight-color: transparent; +} +textarea { + padding: 0.2rem; +} +textarea:focus-visible { + outline: none; + border: 1px solid var(--primary); +} +::selection { + background-color: #5e72e4; + background-color: var(--primary); + color: #ffffff; + color: var(--white); +} +::placeholder { + color: var(--lighter); +} +a:link, +a:visited, +a:active { + color: #5e72e4; + color: var(--primary); + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +li { + list-style-type: none; +} +.table { + position: relative; + display: table; +} +.tr { + display: table-row; +} +.thead { + display: table-header-group; +} +.tbody { + display: table-row-group; +} +.tfoot { + display: table-footer-group; +} +.td, +.th { + line-height: normal; + display: table-cell; + padding: 0.5em; + text-align: center; + vertical-align: middle; +} +.th { + font-weight: bold; + white-space: nowrap; +} +.tr.placeholder { + height: 4em; +} +.tr.placeholder > .td { + line-height: 3; + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 0.4rem 0 !important; + text-align: center !important; + background: inherit; +} +.td[width="33%"] { + padding: 1.1em 1.5rem; +} +.table[width="33%"], +.th[width="33%"], +.td[width="33%"] { + width: 33%; +} +.table[width="100%"], +.th[width="100%"], +.td[width="100%"] { + width: 100%; +} +.col-1 { + flex: 1 1 30px !important; +} +.col-2 { + flex: 2 2 60px !important; +} +.col-3 { + flex: 3 3 90px !important; +} +.col-4 { + flex: 4 4 120px !important; +} +.col-5 { + flex: 5 5 150px !important; +} +.col-6 { + flex: 6 6 180px !important; +} +.col-7 { + flex: 7 7 210px !important; +} +.col-8 { + flex: 8 8 240px !important; +} +.col-9 { + flex: 9 9 270px !important; +} +.col-10 { + flex: 10 10 300px !important; +} +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: inherit; + font-weight: normal; + line-height: 1.1 !important; + color: inherit; +} +select { + padding: 0.36rem 0.8rem; + color: #555; + border: thin solid #ccc; + background-color: #fff; + background-image: none; +} +.btn, +button, +select, +input, +.cbi-dropdown { + line-height: 1.5em; + padding: 0.5rem 0.75rem; + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + outline: 0; + background-image: none; + box-shadow: none; + transition: box-shadow 0.15s ease; +} +select, +.cbi-dropdown { + width: inherit; + cursor: default; +} +select:not([multiple="multiple"]):focus, +input:not(.cbi-button):focus, +.cbi-dropdown:focus { + border-color: #5e72e4; + border-color: var(--primary); + box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, 0.1); +} +.cbi-dropdown, +select[multiple="multiple"] { + height: auto; +} +pre { + overflow: auto; +} +code { + font-size: 0.875rem; + padding: 1px 3px; + color: #101010; + border-radius: 2px; + background: #ddd; +} +abbr { + cursor: help; + text-decoration: underline; + color: #5e72e4; + color: var(--primary); +} +hr { + margin: 1rem 0; + opacity: 0.1; + border-color: #eee; +} +ul { + line-height: normal; +} +li { + list-style-type: none; +} +h1 { + font-size: 2rem; + padding-bottom: 10px; + border-bottom: thin solid #eee; +} +h2 { + margin: 0 0 1rem 0; + font-size: 1.25rem; + letter-spacing: 0.1rem; + padding: 1rem 1.25rem; + color: #32325d; + border-radius: 0.25rem; + background: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); + font-weight: bold; +} +h3 { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + margin: 0; + margin-bottom: 0; + padding: 0.8755rem 1.25rem; + color: #32325d; + color: var(--gray-dark); + border-radius: 0.25rem; + background: #fff; + font-weight: bold; +} +h4 { + margin: 0; + padding: 0.75rem 1.25rem; + font-size: 0.875rem; + font-weight: 600; + color: #525f7f; + font-weight: bold; +} +h4 em { + padding: 0 0.5rem; +} +h5 { + font-size: 1rem; + margin: 2rem 0 0 0; + padding-bottom: 10px; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.nowrap:not(.td) { + white-space: nowrap; +} +[disabled="disabled"] { + pointer-events: none; +} +.login-page { + height: 100%; +} +.login-page .video { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #000; + background-color: var(--darker); + overflow: hidden; +} +.login-page .video video { + width: 100%; + height: auto; +} +.login-page .volume-control { + position: fixed; + right: 1rem; + top: 1rem; + width: 1.5rem; + height: 1.5rem; + z-index: 5000; + cursor: pointer; + background-size: contain; + background-image: url(../img/volume_high.svg); +} +.login-page .volume-control.mute { + background-image: url(../img/volume_off.svg); +} +.login-page .main-bg { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + background-image: url(../img/blank.png); + background-repeat: no-repeat; + background-position: center; + background-size: cover; + transition: all 0.5s; +} +.login-page .login-container { + height: 100%; + margin-left: 4.5rem; + position: absolute; + top: 0px; + display: flex; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + align-items: flex-start; + min-height: 100%; + z-index: 2; + width: 420px; + box-shadow: rgba(0, 0, 0, 0.75) 0 0 35px -5px; + margin-left: 5%; + background: transparent; +} +.login-page .login-container .login-form { + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: center; + position: absolute; + top: 0px; + width: 100%; + min-height: 100%; + max-width: 420px; + background-color: #fff; + background-color: var(--white); + -webkit-backdrop-filter: blur(var(--blur-radius)); + backdrop-filter: blur(var(--blur-radius)); + background-color: rgba(244, 245, 247, var(--blur-opacity)); +} +.login-page .login-container .login-form .brand { + display: flex; + -webkit-box-align: center; + align-items: center; + margin: 50px auto 100px 50px; + color: #525461; + color: var(--default); + justify-content: center; +} +.login-page .login-container .login-form .brand .icon { + width: 50px; + height: auto; + margin-right: 25px; +} +.login-page .login-container .login-form .brand .brand-text { + font-size: 1.25rem; + font-weight: 700; + font-family: "TypoGraphica"; +} +.login-page .login-container .login-form .brand:hover { + text-decoration: none; +} +.login-page .login-container .login-form .form-login { + width: 100%; + padding: 20px 50px; + box-sizing: border-box; +} +.login-page .login-container .login-form .form-login .errorbox { + text-align: center; + color: #fb6340; + color: var(--warning); + padding-bottom: 2rem; +} +.login-page .login-container .login-form .form-login .input-group { + margin-bottom: 1.25rem; + position: relative; +} +.login-page .login-container .login-form .form-login .input-group::before { + font-family: "argon" !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #525461; + color: var(--default); + font-size: 1.5rem; + position: absolute; + z-index: 100; + left: 10px; + top: 10px; +} +.login-page .login-container .login-form .form-login .input-group .border { + position: absolute; + width: 100%; + height: 1px; + bottom: 0; + border-bottom: 1px #5e72e4 solid; + border-bottom: 1px var(--primary) solid; + transform: scaleX(0); + transition: transform 0.3s; +} +.login-page .login-container .login-form .form-login .input-group input { + font-size: 1rem; + line-height: 1.5em; + display: block; + width: 100%; + padding: 0.5rem 0.75rem 0.5rem 3rem; + margin: 0.825rem 0; + box-sizing: border-box; + transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); + color: #525461; + color: var(--default); + border: 0; + border-radius: 0; + border-bottom: 1px solid #fff; + border-bottom: 1px solid var(--white); + background-color: transparent; + background-clip: padding-box; + box-shadow: 0 3px 2px rgba(233, 236, 239, 0.05); + outline: none; +} +.login-page + .login-container + .login-form + .form-login + .input-group + input:focus + + .border { + transform: scaleX(1); +} +.login-page + .login-container + .login-form + .form-login + .input-group + .cbi-input-password { + margin-bottom: 2rem; + position: relative; +} +.login-page .login-container .login-form .form-login .user-icon::before { + content: "\e971"; +} +.login-page .login-container .login-form .form-login .pass-icon::before { + content: "\e910"; +} +.login-page .login-container .login-form .cbi-button-apply { + width: 100% !important; + box-shadow: rgba(0, 0, 0, 0.1) 0 0 50px 0; + font-weight: 600; + font-size: 15px; + color: #fff; + color: var(--white); + text-align: center; + width: 100%; + cursor: pointer; + min-height: 50px; + background-color: #5e72e4 !important; + background-color: var(--primary) !important; + border-radius: 6px; + outline: none; + border-width: initial; + border-style: none; + border-color: initial; + border-image: initial; + padding: 10px 0px; + margin: 30px 0px 100px; + transition: all 0.3s !important; + letter-spacing: 0.8rem; +} +.login-page .login-container .login-form .cbi-button-apply:hover, +.login-page .login-container .login-form .cbi-button-apply :focus { + opacity: 0.9; +} +.login-page .login-container footer { + box-sizing: border-box; + width: 100%; + text-align: center; + line-height: 1.6rem; + display: flex; + justify-content: space-evenly; + margin-top: auto; + padding: 0px 0px 30px; + z-index: 10; + color: #525461; + color: var(--default); + position: absolute; + bottom: 0; +} +.login-page .login-container footer .ftc { + position: absolute; + bottom: 30px; + width: 100%; +} +.login-page .login-container footer .luci-link { + display: block; +} +header, +.main { + width: 100%; +} +footer { + font-size: 0.875rem; + overflow: hidden; + padding: 1rem; + text-align: right; + white-space: nowrap; + color: #aaa; +} +footer > a { + text-decoration: none; + color: #aaa; +} +small { + font-size: 90%; + line-height: 1.42857143; + white-space: normal; +} +.main { + position: relative; + top: 0; + bottom: 0; + overflow-y: auto; + height: 100%; + display: flex; + flex-direction: row; +} +.main-left { + flex-shrink: 0; + width: 15rem; + height: 100%; + background-color: var(--menu-bg-color); + box-shadow: rgba(0, 0, 0, 0.75) 0 0 15px -5px; + overflow-x: auto; + z-index: 100; +} +.main-left .sidenav-header { + padding: 1.5rem 0.5rem; + text-align: center; +} +.main-left .sidenav-header .brand { + display: block; + font-size: 1.8rem; + color: #5e72e4; + color: var(--primary); + font-family: "TypoGraphica"; + text-decoration: none; + text-align: center; + cursor: default; + margin: 0 2rem; +} +.main-left .sidenav-header .brand .logo { + max-width: 100%; + height: auto; +} +.main-left::-webkit-scrollbar { + width: 5px; + height: 1px; +} +.main-left::-webkit-scrollbar-thumb { + background-color: #f6f9fc; +} +.main-left::-webkit-scrollbar-track { + background-color: #fff; +} +.main-right { + flex-grow: 1; + height: 100%; + transition: all 0.2s; + overflow-x: hidden; + overflow-y: auto; + display: flex; + flex-direction: column; +} +.main-right > #maincontent { + position: relative; + z-index: 50; + flex: 1; + display: flex; + flex-direction: column; +} +.main-right > #maincontent > .container { + margin: 0 1.25rem 1rem 1.25rem; + flex-grow: 1; +} +.main-right > #maincontent .Dashboard { + color: var(--gray-dark) !important; +} +.main-right > #maincontent .Dashboard h3 { + color: var(--gray-dark); +} +.main-right > #maincontent .Dashboard p { + margin-bottom: 3px; + margin-top: 3px; +} +.main-right > #maincontent .Dashboard hr { + border-top: 1px solid #000; +} +.main-right > #maincontent .Dashboard .dashboard-bg { + background-color: #fff; +} +.main-right > #maincontent .Dashboard .settings-info { + padding-top: 1em; + padding-bottom: 1em; +} +.main-right > #maincontent .Dashboard .settings-info p span:nth-child(2) { + max-height: 18.5px; + top: 4px; +} +.main-right > #maincontent .Dashboard .settings-info .label { + font-size: 0.7rem; + padding: 0.2rem 0.6rem; +} +header { + color: #fff; + color: var(--header-color); + padding: 0; + position: relative; +} +header.bg-primary { + background-color: #5e72e4 !important; + background-color: var(--primary) !important; +} +header::after { + content: ""; + position: absolute; + height: 2rem; + width: 100%; + background-color: #5e72e4 !important; + background-color: var(--primary) !important; +} +header .fill { + padding: 0.8rem 0; + border-bottom: 0 solid rgba(255, 255, 255, 0.08) !important; + display: flex; +} +header .fill .container { + height: 2rem; + padding: 0 1.25rem; + display: flex; + align-items: center; + width: 100%; +} +header .fill .container .flex1 { + flex: 1; +} +header .fill .container .flex1 .showSide { + display: none; + color: #fff; + font-size: 1.4rem; +} +header .fill .container .flex1 .showSide:hover { + text-decoration: none; +} +header .fill .container .flex1 .brand { + font-size: 1.5rem; + color: #fff; + font-family: "TypoGraphica"; + text-decoration: none; + padding-left: 1rem; + cursor: default; + vertical-align: text-bottom; + display: none; +} +header .fill .container .pull-right { + float: right; + margin-top: 0rem; + display: flex; +} +header .fill .status span { + display: inline-block; + font-size: 0.875rem; + font-weight: bold; + padding: 0.3rem 0.8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + text-shadow: none; + border-radius: 4px; + cursor: pointer; + transition: all 0.3s; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + margin: 0 0.25rem; +} +header .fill .status span:last-child { + margin-right: 0; +} +header .fill .status span[data-indicator="poll-status"] { + color: #fff; +} +header .fill .status span[data-style="active"] { + background-color: var(--green); +} +header .fill .status span[data-style="inactive"] { + color: #ffffff !important; + background-color: #32325d; +} +#xhr_poll_status { + display: flex; + margin-left: 0.5rem; +} +#xhr_poll_status * { + color: #fff; +} +div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { + border: 0 !important; +} +.danger { + background-color: #ff7d60 !important; +} +.warning { + background-color: #f0e68c !important; +} +.success { + background-color: #5cb85c !important; +} +.notice { + background-color: #11cdef !important; + color: #fff; +} +.error { + color: #f00; +} +.alert, +.alert-message { + font-weight: bold; + margin-bottom: 1.25rem; + margin-left: 1.25rem; + margin-right: 1.25rem; + padding: 1rem 1.25rem; + border: 0; + border-radius: 0.25rem !important; + background-color: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + text-shadow: none; +} +.alert.error, +.alert-message.error { + background-color: #ffd600; +} +.alert h4, +.alert-message h4 { + padding: 0.25rem 0; + border-radius: 4px; + background-color: #ffd600; +} +.alert .btn, +.alert-message .btn { + height: auto; +} +.alert-message > h4 { + font-size: 110%; + font-weight: bold; +} +.alert-message > * { + margin: 0.5rem 0; +} +.alert-message .btn { + padding: 0.3rem 0.6rem; +} +.container .alert, +.container .alert-message { + margin-left: 0; + margin-right: 0; + margin-top: 0rem; +} +.main .main-left { + transition: all 0.2s; +} +.main .main-left .nav { + margin-top: 0.5rem; +} +.main .main-left .nav > li > a:first-child { + display: block; + margin: 0.1rem 0.5rem 0.1rem 0.5rem; + padding: 0.675rem 0 0.675rem 2.5rem; + border-radius: 0.25rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; +} +.main .main-left .nav > li > a:first-child.active { + color: #fff; + background: #5e72e4; + background: var(--primary); +} +.main .main-left .nav > li > a:first-child.active::before { + color: #fff !important; +} +.main .main-left .nav > li > a:first-child.active::after { + transform: rotate(90deg); + color: #fff !important; +} +.main .main-left .nav > li > a:first-child:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); +} +.main .main-left .nav > li > a:first-child:hover::before { + color: #fff !important; +} +.main .main-left .nav > li > a:first-child::before { + font-family: "argon" !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); +} +.main .main-left .nav li { + padding: 0.5rem 1rem; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0; +} +.main .main-left .nav li a { + display: block; + color: #5f6368; + color: var(--menu-color); +} +.main .main-left .nav li.slide { + padding: 0; +} +.main .main-left .nav li.slide ul { + display: none; + overflow: hidden; +} +.main .main-left .nav li.slide:hover { + background: none; +} +.main .main-left .nav li.slide .slide-menu { + margin: 0 0.5rem 0 2.5rem; + padding: 0 0.5rem; +} +.main .main-left .nav li.slide .slide-menu.active { + display: block; +} +.main .main-left .nav li.slide .slide-menu li { + position: relative; + border-radius: 0.25rem; + margin: 0; + background: none; + list-style: none; +} +.main .main-left .nav li.slide .slide-menu li a { + text-decoration: none; + padding: 0.5rem 0; +} +.main .main-left .nav li.slide .slide-menu li::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 0; + height: 2px; + background-color: #5e72e4; + background-color: var(--primary); + transition: all 0.2s; +} +.main .main-left .nav li.slide .slide-menu li:hover { + background: none; +} +.main .main-left .nav li.slide .slide-menu li:hover::after { + width: 100%; +} +.main .main-left .nav li.slide .slide-menu .active { + background: none; + color: var(--menu-color); +} +.main .main-left .nav li.slide .slide-menu .active a { + color: var(--menu-color); +} +.main .main-left .nav li.slide .slide-menu .active::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background-color: #5e72e4; + background-color: var(--primary); + transition: all 0.2s; +} +.main .main-left .nav li.slide .slide-menu .active:hover { + background: none; +} +.main .main-left .nav li.slide .slide-menu .active:hover::after { + width: 100%; +} +.main .main-left .nav li .menu { + display: block; + margin: 0.1rem 0.5rem 0.1rem 0.5rem; + padding: 0.675rem 0 0.675rem 2.5rem; + border-radius: 0.25rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; +} +.main .main-left .nav li .menu.active { + color: #fff; + background: #5e72e4; + background: var(--primary); +} +.main .main-left .nav li .menu.active::before { + color: #fff !important; +} +.main .main-left .nav li .menu.active::after { + transform: rotate(90deg); + color: #fff !important; +} +.main .main-left .nav li .menu:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); +} +.main .main-left .nav li .menu:hover::before { + color: #fff !important; +} +.main .main-left .nav li .menu::before { + font-family: "argon" !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); +} +.main .main-left .nav li .menu::after { + position: absolute; + right: 0.5rem; + top: 0.8rem; + font-family: "argon" !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -moz-osx-font-smoothing: grayscale; + content: "\e90f"; + transition: all 0.15s ease; + color: #ced4da; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} +.main .main-left .nav li .menu[data-title="Status"]:before { + content: "\e906"; + color: #5e72e4; + color: var(--primary); +} +.main .main-left .nav li .menu[data-title="System"]:before { + content: "\e90a"; + color: #fb6340; +} +.main .main-left .nav li .menu[data-title="Services"]:before { + content: "\e909"; + color: #11cdef; +} +.main .main-left .nav li .menu[data-title="NAS"]:before { + content: "\e90c"; + color: #f3a4b5; +} +.main .main-left .nav li .menu[data-title="VPN"]:before { + content: "\e90b"; + color: #8965e0; +} +.main .main-left .nav li .menu[data-title="Network"]:before { + content: "\e908"; + color: #8965e0; +} +.main .main-left .nav li .menu[data-title="Bandwidth_Monitor"]:before { + content: "\e90d"; + color: #2dce89; +} +.main .main-left .nav li .menu[data-title="Docker"]:before { + content: "\e911"; + color: #6699ff; +} +.main .main-left .nav li .menu[data-title="Statistics"]:before { + content: "\e913"; + color: #8965e0; +} +.main .main-left .nav li .menu[data-title="Control"]:before { + content: "\e912"; + color: #5e72e4; + color: var(--primary); +} +.main .main-left .nav li .menu[data-title="Asterisk"]:before { + content: "\e914"; + color: #fb6340; +} +.main .main-left .nav li a[data-title="Log_out"]::before, +.main .main-left .nav li .food[data-title="Log_out"]::before { + content: "\e907"; + color: #adb5bd; +} +.lg { + margin: 0; + padding: 0 !important; +} +.logout { + display: block; + margin: 0.8rem 0.5rem 0.1rem 0.5rem; + padding: 0.675rem 0 0.675rem 2.5rem; + border-radius: 0.25rem; + text-decoration: none; + font-size: 1rem; + transition: all 0.2s; + position: relative; +} +.logout:before { + font-family: "argon" !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e907"; + color: #32325d !important; +} +body[class*="node-"] > .main > .main-left > .nav > .slide > .menu::before { + transition: transform 0.1s ease-in-out; +} +body[class*="node-"] + > .main + > .main-left + > .nav + > .slide + > .menu.active::before { + transition: transform 0.2s ease-in-out; +} +.main > .main-left[style*="overflow: hidden"] > .nav > .slide > .menu::before { + display: none; +} +.cbi-section, +.cbi-section-error, +#iptables, +.Firewall form, +#cbi-network > .cbi-section-node, +#cbi-wireless > .cbi-section-node, +#cbi-wireless > #wifi_assoclist_table, +[data-tab-title], +[data-page^="admin-system-admin"]:not(.node-main-login) + .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent > .container { + font-family: inherit; + font-weight: normal; + font-style: normal; + line-height: normal; + min-width: inherit; + margin: 1.25rem 0; + padding: 0; + border: 0; + border-radius: 0.25rem; + background-color: #fff; + box-shadow: 0 0 1rem 0 rgba(136, 152, 170, 0.15); +} +.cbi-section:last-child, +.cbi-section-error:last-child, +#iptables:last-child, +.Firewall form:last-child, +#cbi-network > .cbi-section-node:last-child, +#cbi-wireless > .cbi-section-node:last-child, +#cbi-wireless > #wifi_assoclist_table:last-child, +[data-tab-title]:last-child, +[data-page^="admin-system-admin"]:not(.node-main-login) + .cbi-map:not(#cbi-dropbear):last-child, +[data-page="admin-system-opkg"] #maincontent > .container:last-child { + margin: 0; + border: 0; +} +.cbi-modal .cbi-section, +.cbi-section .cbi-section { + padding: 0; + box-shadow: none; +} +.cbi-modal .cbi-tabmenu { + margin-left: 0; +} +.cbi-map:not(:first-child) { + margin-top: 1rem; +} +.cbi-map-descr { + font-size: small; + line-height: 1.5; + padding: 0 1.25rem 1rem 1.25rem; +} +.cbi-section > .cbi-section-descr { + padding-top: 1rem !important; + padding-bottom: 1rem !important; +} +.cbi-section > .cbi-section-descr:empty { + padding-top: 0 !important; + padding-bottom: 0rem !important; +} +.cbi-section-descr:not(:empty) { + font-size: small; + line-height: 1.5; + padding: 0rem 1rem; +} +.cbi-map-descr + fieldset { + margin-top: 1rem; +} +.cbi-map-descr > abbr { + cursor: help; + text-decoration: underline; +} +.cbi-section > legend { + display: none !important; +} +fieldset > fieldset, +.cbi-section > .cbi-section { + margin: 0; + padding: 0; + border: 0; + box-shadow: none; +} +.cbi-section > h3:first-child, +.panel-title { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + margin: 0; + margin-bottom: 0; + padding: 0.8755rem 1.25rem; + color: #32325d; + color: var(--gray-dark); +} +.cbi-section > h3:first-child, +.cbi-section > h4:first-child, +.cbi-section > p:first-child, +[data-tab-title] > h3:first-child, +[data-tab-title] > h4:first-child, +[data-tab-title] > p:first-child { + padding: 1rem 1.25rem; +} +.cbi-section p { + padding: 1rem; +} +.cbi-tblsection { + overflow-x: auto; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +table, +.table { + overflow-y: hidden; + width: 100%; + font-size: 90%; +} +.table .table-titles th { + background-color: #e9ecef; + background-color: var(--lighter); +} +table > tbody > tr > td, +table > tbody > tr > th, +table > tfoot > tr > td, +table > tfoot > tr > th, +table > thead > tr > td, +table > thead > tr > th, +.table > .tbody > .tr > .td, +.table > .tbody > .tr > .th, +.table > .tfoot > .tr > .td, +.table > .tfoot > .tr > .th, +.table > .thead > .tr > .td, +.table > .thead > .tr > .th, +.table > .tr > .td.cbi-value-field, +.table > .tr > .th.cbi-section-table-cell { + padding: 0.5rem; +} +.container > .cbi-section:first-of-type > .table[width="100%"] > .tr > .td { + padding: 0.6rem; +} +.cbi-section-table-cell { + line-height: 1.1; + align-self: flex-end; + flex: 1 1 auto; +} +tr > td, +tr > th, +.tr > .td, +.tr > .th, +.cbi-section-table-row::before, +#cbi-wireless > #wifi_assoclist_table > .tr:nth-child(2) { + border-top: thin solid #ddd; + padding: 1.1em 1.25rem; +} +#cbi-wireless .td, +.table[width="100%"] > .tr:first-child > .td, +[data-page="admin-network-diagnostics"] .tr > .td, +.tr.table-titles > .th, +.tr.cbi-section-table-titles > .th { + border-top: 0 !important; + background-color: #f6f9fc; + padding: 1.1em 1.25rem; + line-height: 1.3rem; +} +[data-page="admin-network-network"] .cbi-value-field .cbi-dynlist { + padding: 0 !important; +} +#cbi-network .tr:first-child > .td { + border-top: 0; +} +.table[width="100%"] > .tr:first-child > .td { + margin: auto 0; +} +.cbi-section-table-row { + margin-bottom: 1rem; + text-align: center !important; + background: #f4f4f4; +} +.cbi-section-table-row:last-child { + margin-bottom: 0; +} +.cbi-section-table-row > .cbi-value-field .cbi-dropdown, +.cbi-section-table-row > .cbi-value-field .cbi-input-select, +.cbi-section-table-row > .cbi-value-field .cbi-input-text, +.cbi-section-table-row > .cbi-value-field .cbi-input-password { + width: 100%; +} +.cbi-section-table-row > .cbi-value-field .cbi-input-text, +.cbi-section-table-row > .cbi-value-field .cbi-input-password { + min-width: 80px; +} +.cbi-section-table-row > .cbi-value-field [data-dynlist] > input, +.cbi-section-table-row > .cbi-value-field input.cbi-input-password { + width: calc(100% - 1.5rem); +} +.cbi-section-table-row .td { + text-align: center !important; +} +.cbi-section-table-row .td .cbi-checkbox input[type="checkbox"] { + margin: 0; +} +.control-group { + display: inline-flex; + width: 100%; + flex-wrap: wrap; + gap: 0px; +} +.control-group input { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-right-width: 0; + margin-right: 0; +} +.control-group input + button { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin-left: 0; + border-left-width: 0; +} +.control-group > * { + vertical-align: middle; +} +div > table > tbody > tr:nth-of-type(2n), +div > .table > .tr:nth-of-type(2n) { + background-color: #f9f9f9; +} +table table, +.table .table, +.cbi-value-field table, +.cbi-value-field .table, +td > table > tbody > tr > td, +.td > .table > .tbody > .tr > .td, +.cbi-value-field > table > tbody > tr > td, +.cbi-value-field > .table > .tbody > .tr > .td { + border: 0; +} +.btn, +.cbi-button, +.item::after { + font-size: 0.875rem; + display: inline-block; + width: auto !important; + padding: 0.5rem 0.75rem; + margin-left: 5px; + margin-right: 5px; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all 0.2s ease-in-out; + text-align: center; + vertical-align: middle; + white-space: nowrap; + text-decoration: none; + border: 0; + border-radius: 0.25rem; + background-color: #f0f0f0; + background-image: none; + appearance: none; + -ms-touch-action: manipulation; + touch-action: manipulation; +} +.btn:last-child, +.cbi-button:last-child { + margin-right: 0 !important; +} +.btn:first-child, +.cbi-button:first-child { + margin-left: 0 !important; +} +.btn:only-child, +.cbi-button:only-child { + margin-left: 5px !important; + margin-right: 5px !important; +} +.btn:not(button) ul:not(.dropdown) li { + padding: 0; +} +.cbi-button-up, +.cbi-button-down { + display: inline-block; + min-width: 0; + padding: 0.2rem 1rem; + font-size: 0; + color: transparent !important; + background: url(../icon/arrow.svg) no-repeat center; + background-size: 12px 20px; +} +.cbi-button-up { + transform: scaleY(-1); +} +.cbi-button:not(select) { + appearance: none !important; +} +.btn:hover, +.btn:focus, +.btn:active, +.cbi-button:hover, +.cbi-button:focus, +.cbi-button:active, +.item:hover::after, +.item:focus::after, +.item:active::after, +.cbi-page-actions .cbi-button-apply + .cbi-button-save:hover, +.cbi-page-actions .cbi-button-apply + .cbi-button-save:focus, +.cbi-page-actions .cbi-button-apply + .cbi-button-save:active { + text-decoration: none; + outline: 0; +} +.btn:hover, +.btn:focus, +.cbi-button:hover, +.cbi-button:focus, +.item:hover::after, +.item:focus::after { + box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 2px rgba(0, 0, 0, 0.2); +} +.btn:active, +.cbi-button:active, +.item:active::after { + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); +} +.cbi-button-up:hover, +.cbi-button-up:focus { + box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 -2px 2px rgba(0, 0, 0, 0.2); +} +.cbi-button-up:active { + box-shadow: 0 -10px 20px rgba(0, 0, 0, 0.19), 0 -6px 6px rgba(0, 0, 0, 0.23); +} +.btn:disabled, +.cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: 0.5; + box-shadow: none; +} +.alert-message [class="btn"], +.modal div[class="btn"], +.cbi-button-find, +.cbi-button-link, +.cbi-button-up, +.cbi-button-down, +.cbi-button-neutral, +.cbi-button[name="zero"], +.cbi-button[name="restart"], +.cbi-button[onclick="hide_empty(this)"] { + color: #fff; + border: thin solid #8898aa; + background-color: #8898aa; +} +.btn.primary, +.cbi-page-actions .cbi-button-save, +.cbi-page-actions .cbi-button-apply + .cbi-button-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-positive, +.cbi-button-link, +.cbi-button[value="Enable"], +.cbi-button[value="Scan"], +.cbi-button[value^="Back"], +.cbi-button-neutral[onclick="handleConfig(event)"] { + font-weight: normal; + color: #fff !important; + border: thin solid #5e72e4; + border: thin solid var(--primary); + background-color: #5e72e4; + background-color: var(--primary); +} +.cbi-page-actions .cbi-button-apply, +.cbi-section-actions .cbi-button-edit, +.cbi-button-edit, +.cbi-button-apply, +.cbi-button-reload, +.cbi-button-action, +.cbi-button[value="Submit"], +.cbi-button[value="Upload"], +.cbi-button[value$="Apply"], +.cbi-button[onclick="addKey(event)"] { + font-weight: normal; + color: #fff !important; + border: thin solid #5e72e4; + border: thin solid var(--primary); + background-color: #5e72e4; + background-color: var(--primary); +} +.btn.danger, +.cbi-section-remove > .cbi-button, +.cbi-button-remove, +.cbi-button-reset, +.cbi-button-negative, +.cbi-button[value="Stop"], +.cbi-button[value="Kill"], +.cbi-button[onclick="reboot(this)"], +.cbi-button-neutral[value="Restart"] { + font-weight: normal; + color: #fff; + border: thin solid #f5365c; + border: thin solid var(--red); + background-color: #f5365c; + background-color: var(--red); +} +.btn[value="Dismiss"], +.cbi-button[value="Terminate"], +.cbi-button[value="Reset"], +.cbi-button[value="Disabled"], +.cbi-button[onclick^="iface_reconnect"], +.cbi-button[onclick="handleReset(event)"], +.cbi-button-neutral[value="Disable"] { + font-weight: normal; + color: #fff; + border: thin solid #eea236; + background-color: #f0ad4e; +} +.cbi-button-success, +.cbi-button-download { + font-weight: normal; + color: #fff; + border: thin solid #4cae4c; + background-color: #5cb85c; +} +.cbi-page-actions .cbi-button-link:first-child { + float: left; +} +.a-to-btn { + text-decoration: none; +} +.cbi-value-field .cbi-button-add { + font-weight: bold; + padding: 1px 6px; + display: inline-block; + align-items: center; +} +.tabs { + margin: 0 0 1rem 0; + padding: 0 1rem; + background-color: #ffffff; + border-radius: 0.25rem; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); + white-space: nowrap; + overflow-x: auto; +} +.tabs::-webkit-scrollbar { + width: 1px; + height: 5px; +} +.tabs::-webkit-scrollbar-thumb { + background-color: #f6f9fc; +} +.tabs::-webkit-scrollbar-track { + background-color: #fff; +} +.tabs li[class~="active"], +.tabs li:hover { + cursor: pointer; + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #e4e9ee; + margin-bottom: 0; + border-radius: 0; +} +.tabs li[class~="active"] a, +.tabs li:hover a { + color: #5e72e4; + color: var(--primary); +} +.tabs li { + font-size: 0.875rem; + display: inline-block; + padding: 0.875rem 0; + border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); + margin: 0; + transition: all 0.2s; +} +.tabs li a { + text-decoration: none; + color: #404040; + padding: 0.5rem 0.8rem; +} +.tabs li:hover { + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); +} +.cbi-tabmenu { + color: white; + padding: 0.5rem 1rem 0 1rem; + white-space: nowrap; + overflow-x: auto; +} +.cbi-tabmenu::-webkit-scrollbar { + width: 1px; + height: 5px; +} +.cbi-tabmenu::-webkit-scrollbar-thumb { + background-color: #f6f9fc; +} +.cbi-tabmenu::-webkit-scrollbar-track { + background-color: #fff; +} +.cbi-tabmenu li { + background: #dce3e9; + display: inline-block; + font-size: 0.875rem; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + padding: 0.5rem 0; + border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); + margin: 0 0.2rem; +} +.cbi-tabmenu li a { + text-decoration: none; + color: #404040; + padding: 0.5rem 0.8rem; +} +.cbi-tabmenu li:hover { + cursor: pointer; + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #e4e9ee; + margin-bottom: 0; +} +.cbi-tabmenu li:hover a { + color: #525f7f; +} +.cbi-tabmenu li[class~="cbi-tab"] { + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #e4e9ee; + margin-bottom: 0; +} +.cbi-tabmenu li[class~="cbi-tab"] a { + color: #5e72e4; + color: var(--primary); +} +.cbi-tab-descr { + padding: 0.5rem 1.5rem; +} +.cbi-section-node { + padding: 0; +} +.cbi-section .cbi-section-remove:nth-of-type(2n), +.container > .cbi-section .cbi-section-node:nth-of-type(2n) { + background-color: #f9f9f9; +} +[data-tab-title] { + overflow: hidden; + height: 0; + opacity: 0; + margin: 0; + padding: 0rem 0rem !important; +} +[data-tab-title] p { + margin-left: 1rem; + margin-bottom: 1rem; +} +[data-tab-active="true"] { + overflow: visible; + height: auto; + opacity: 1; + transition: opacity 0.25s ease-in; + margin: inherit !important; +} +.cbi-section[id] .cbi-section-remove:nth-of-type(4n + 3), +.cbi-section[id] .cbi-section-node:nth-of-type(4n + 4) { + background-color: #f9f9f9; +} +.cbi-section-node-tabbed { + margin-top: 0; + padding: 0; + border: 0 solid #d4d4d4; + border-radius: 0.25rem; +} +.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + background-color: #f9f9f9; +} +.cbi-value-field { + display: table-cell; +} +.cbi-value-description { + line-height: 1.25; + display: table-cell; +} +.cbi-value-description abbr { + color: #32325d; + color: var(--gray-dark); +} +.cbi-value-description { + font-size: small; + padding: 0.5rem; + opacity: 0.5; +} +.cbi-value-title { + display: table-cell; + float: left; + width: 23rem; + padding-right: 2rem; + text-align: right; + word-wrap: break-word; +} +.cbi-value { + display: inline-block; + width: 100%; + padding: 0.35rem 1rem 0.2rem 1rem; + line-height: 2.4rem; +} +.cbi-value:first-child { + padding-top: 1rem; +} +.cbi-value:last-child { + padding-bottom: 1rem; +} +.cbi-value ul { + line-height: 1.25; +} +.cbi-value-field .cbi-dropdown, +.cbi-value-field .cbi-input-select, +.cbi-value input[type="text"], +.cbi-value input[type="password"], +.cbi-value textarea { + min-width: 18rem; +} +.cbi-value input[type="password"] { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + font-size: 0.875rem; + margin: 0.25rem 0 0.25rem 0.1rem; +} +.cbi-value input[type="password"] + .cbi-button-neutral { + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem !important; + padding: 0.5rem 0; + margin: 0.25rem 0; + font-weight: normal; + font-size: 1.2rem; + line-height: 1.5rem; + color: #fff; + outline: 0; + background-color: #8898aa; + box-shadow: none; + border: 1px solid #8898aa; + border-radius: 0.25rem; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +#cbi-firewall-zone .cbi-input-select, +#cbi-network-switch_vlan .cbi-input-select { + min-width: 11rem; +} +#cbi-network-switch_vlan .cbi-input-text { + max-width: 3rem; +} +.cbi-input-invalid { + color: #f5365c !important; + border-color: #f5365c !important; +} +.cbi-section-error { + font-weight: bold; + line-height: 1.42857143; + margin: 18px; + padding: 6px; + border: thin solid #f5365c; + border-radius: 3px; + background-color: #fce6e6; +} +.cbi-section-error ul { + margin: 0 0 0 20px; +} +.cbi-section-error ul li { + font-weight: bold; + color: #f5365c; +} +.td[data-title]::before { + font-weight: bold; + display: none; + padding: 0.25rem 0; + content: attr(data-title) ":\20"; + text-align: left; + white-space: nowrap; +} +.tr.placeholder .td[data-title]::before { + display: none; +} +.tr[data-title]::before, +.tr.cbi-section-table-titles.named::before { + font-weight: bold; + display: table-cell; + align-self: center; + flex: 1 1 5%; + padding: 0.25rem; + content: attr(data-title) "\20"; + text-align: center; + vertical-align: middle; + white-space: normal; + word-wrap: break-word; +} +.cbi-rowstyle-1 { + background-color: #f9f9f9; +} +.cbi-rowstyle-2 { + background-color: #eee; +} +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down, +body:not(.Interfaces) .cbi-rowstyle-2:first-child { + background-color: #fff !important; +} +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; +} +.td.cbi-section-actions { + text-align: right !important; + vertical-align: middle; +} +.td.cbi-section-actions > * { + display: inline-flex; +} +.td.cbi-section-actions > * > *, +.td.cbi-section-actions > * > form > * { + margin: 0 5px; + display: flex; + align-items: center; +} +.td.cbi-section-actions > * > form { + display: inline-flex; + margin: 0; +} +.cbi-checkbox { + margin: 0 0.25rem; +} +.cbi-dynlist { + line-height: 1.3; + flex-direction: column; + min-height: 30px; + cursor: text; +} +.cbi-dynlist > .item { + display: inline-flex; + flex-wrap: nowrap; + margin: 0.25rem 0; + position: relative; + max-width: 25rem; + pointer-events: none; + color: #8898aa; + outline: 0; +} +.cbi-dynlist > .item::after { + content: "\00D7"; + pointer-events: auto; + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem !important; + margin: 0; + font-weight: normal; + font-size: 1.2rem; + line-height: 1.5rem; + color: #fff; + border: 1px solid #f5365c; + border-radius: 0 0.25rem 0.25rem 0; + outline: 0; + background-color: var(--red); + background-image: none; + box-shadow: none; + box-sizing: border-box; +} +.cbi-dynlist > .item > span { + display: block; + padding: 0.5rem 0.75rem; + min-width: 15.5rem; + width: 15.5rem; + transition: box-shadow 0.15s ease; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-break: break-word; + font-size: 0.875rem; + line-height: 24px; + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: 0.25rem 0 0 0.25rem; + outline: 0; + background-image: none; + box-shadow: none; + box-sizing: border-box; +} +.cbi-dynlist > .add-item { + display: inline-flex; + align-items: center; + width: 100%; + min-width: 16rem; + margin: 0.25rem 0; + gap: 0; + flex-wrap: nowrap; +} +.cbi-dynlist > .add-item input { + display: block; + padding: 0.5rem 0.75rem; + box-sizing: border-box; + min-width: 15.5rem; + width: 15.5rem; + transition: box-shadow 0.15s ease; + white-space: nowrap; + word-break: break-word; + font-size: 0.875rem; + line-height: 1.5rem; + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: 0.25rem 0 0 0.25rem; + border-right-width: 0; + outline: 0; + background-image: none; + box-shadow: none; +} +.cbi-dynlist > .add-item .cbi-button { + display: flex; + width: auto !important; + padding-left: 0.8rem; + padding-right: 0.8rem; + margin-left: 0; + align-items: center; + justify-content: center; + font-size: 0.875rem; + line-height: 1.5rem; + outline: 0; + background-image: none; + background-color: var(--gray); + box-shadow: none; + color: var(--white); + border-color: var(--gray); + border-radius: 0.25rem; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.cbi-dynlist > .add-item .cbi-button-add { + width: 2.5rem !important; + padding: 0.5rem 0 !important; + font-weight: normal; + font-size: 1.2rem; + color: #fff; + background-color: var(--primary); + border: 1px solid var(--primary); +} +.cbi-dynlist > .add-item:not([ondrop]) > input { + overflow: hidden; + min-width: 15.5rem; + width: 15.5rem; + white-space: nowrap; + text-overflow: ellipsis; +} +.cbi-dynlist[name="sshkeys"] > .item { + max-width: none; +} +.cbi-dynlist > .cbi-dynlist > .add-item[ondrop] > input { + min-width: 13rem; +} +.cbi-dynlist, +.cbi-dropdown { + position: relative; + display: inline-flex; + min-height: 2.1875rem; +} +.cbi-dropdown[placeholder*="select"] { + max-width: 25rem; + height: auto; + margin-top: -3px; +} +.cbi-dropdown > ul { + display: flex; + overflow-x: hidden; + overflow-y: auto; + width: 100%; + margin: 0 !important; + padding: 0; + list-style: none; + outline: 0; +} +.cbi-dropdown > ul.preview { + display: none; +} +.cbi-button-apply > ul.preview { + display: none; +} +.cbi-button-apply > ul.preview li { + color: #fff; +} +.cbi-button-apply > ul:first-child li { + color: #fff; +} +.cbi-dropdown > .open { + flex-basis: 15px; +} +.cbi-dropdown > .open, +.cbi-dropdown > .more { + font-size: 1rem; + font-weight: 900; + line-height: 1em; + display: flex; + flex-direction: column; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + padding: 0 0.25em; + cursor: default; + text-align: center; + outline: 0; +} +.cbi-dropdown > .more, +.cbi-dropdown > ul > li[placeholder] { + font-weight: bold; + display: none; + color: #777; + text-shadow: none; +} +.cbi-dropdown > ul > li { + display: none; + overflow: hidden; + align-items: center; + align-self: center; + flex-grow: 1; + flex-shrink: 1; + min-height: 20px; + padding: 0.125rem 0.25em; + white-space: nowrap; + text-overflow: ellipsis; +} +.cbi-dropdown > ul > li .hide-open { + display: initial; +} +.cbi-dropdown > ul > li .hide-close { + display: none; +} +.cbi-dropdown > ul > li[display]:not([display="0"]) { + border-left: thin solid #ccc; +} +.cbi-dropdown[empty] > ul { + max-width: 1px; +} +.cbi-dropdown > ul > li > form { + display: none; + margin: 0; + padding: 0; + pointer-events: none; +} +.cbi-dropdown > ul > li img { + margin-right: 0.25em; + vertical-align: middle; +} +.cbi-dropdown > ul > li > form > input[type="checkbox"] { + height: auto; + margin: 0; +} +.cbi-dropdown > ul > li input[type="text"] { + height: 20px; +} +.cbi-dropdown[open] > ul.dropdown { + position: absolute; + z-index: 1100; + display: block; + width: auto; + min-width: 100%; + max-width: none; + max-height: 200px !important; + border: 0 solid #918e8c; + background: #ffffff; + box-shadow: 0 0 4px #918e8c; + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + color: var(--main-menu-color); + margin-left: 0 !important; + left: 0; +} +.cbi-dropdown[open] > ul.dropdown li { + color: #000; +} +.cbi-dropdown > ul > li[display], +.cbi-dropdown[open] > ul.preview, +.cbi-dropdown[open] > ul.dropdown > li, +.cbi-dropdown[multiple] > ul > li > label, +.cbi-dropdown[multiple][open] > ul.dropdown > li, +.cbi-dropdown[multiple][more] > .more, +.cbi-dropdown[multiple][empty] > .more { + display: flex; + align-items: center; + flex-grow: 1; +} +.cbi-dropdown[empty] > ul > li, +.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], +.cbi-dropdown[multiple][open] > ul.dropdown > li > form { + display: block; +} +.cbi-dropdown[open] > ul.dropdown > li .hide-open { + display: none; +} +.cbi-dropdown[open] > ul.dropdown > li .hide-close { + display: initial; +} +.cbi-dropdown[open] > ul.dropdown > li { + border-bottom: thin solid #ccc; + padding: 0.5rem 0.8rem; +} +.cbi-dropdown[open] > ul.dropdown > li label { + margin-left: 0.5rem; +} +.cbi-dropdown[open] > ul.dropdown > li[selected] { + background: #e4e9ee; +} +.cbi-dropdown[open] > ul.dropdown > li.focus { + background: #e4e9ee; + outline: none; +} +.cbi-dropdown[open] > ul.dropdown > li:last-child { + margin-bottom: 0; + border-bottom: 0; +} +.cbi-dropdown[open] > ul.dropdown > li[unselectable] { + opacity: 0.7; +} +.cbi-dropdown[open] + > ul.dropdown + > li + > input.create-item-input:first-child:last-child { + width: 100%; +} +.cbi-dropdown[disabled] { + pointer-events: none; + opacity: 0.6; +} +.cbi-dropdown .zonebadge { + width: 100%; +} +.cbi-dropdown[open] .zonebadge { + width: auto; +} +.cbi-progressbar { + position: relative; + display: flex; + width: 100%; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.5rem; + height: 1rem; + overflow: hidden; +} +.cbi-progressbar > div { + display: block; + position: absolute; + height: 100%; + background-color: var(--bar-bg); + border-radius: 0.5rem; + transition: width 0.3s; +} +.cbi-progressbar::after { + content: attr(title); + position: absolute; + font-size: 0.75rem; + color: var(--bs-heading-color); + width: 100%; + height: 100%; + text-align: center; + line-height: 1rem; + z-index: 2; +} +#modal_overlay { + position: fixed; + z-index: 900; + top: 0; + right: 10000px; + bottom: 0; + left: -10000px; + overflow-y: scroll; + transition: opacity 0.125s ease-in; + opacity: 0; + background: rgba(0, 0, 0, 0.7); + -webkit-overflow-scrolling: touch; +} +.modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 90%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + margin: 5em auto; + padding: 1rem; + border-radius: 0.25rem !important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); +} +.modal > * { + line-height: normal; + flex-basis: 100%; + margin-bottom: 0.5em; + max-width: 100%; +} +.modal > pre, +.modal > textarea { + font-size: 1rem; + font-size-adjust: 0.35; + overflow: auto; + margin-bottom: 0.5em; + padding: 8.5px; + cursor: auto; + white-space: pre-wrap; + color: #eee; + outline: 0; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); +} +.modal > h4 { + display: block; + flex-grow: 1; + max-width: none; + padding: 1rem; + margin: -1rem -1rem 0 -1rem; + font-size: 1rem; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); + border-radius: 0.25rem 0 0 0.25rem; +} +.modal h5 { + margin-top: 1rem; + font-weight: 600; +} +.modal label > input[type="checkbox"] { + top: 0; +} +.modal ul { + margin-left: 2.2em; +} +.modal ul:not(.cbi-tabmenu) { + margin-top: 1rem; +} +.modal ul li { + list-style-type: square; + color: #808080; +} +.modal p { + word-break: break-word; + margin-top: 1rem; +} +.modal .label { + font-size: 0.6rem; + font-weight: normal; + padding: 0.1rem 0.3rem; + padding-bottom: 0; + cursor: default; + border-radius: 0; +} +.modal .label.warning { + background-color: #f0ad4e !important; +} +.modal .btn { + padding: 0.45rem 0.8rem; +} +.modal.cbi-modal { + max-width: 90%; + max-height: none; +} +body.modal-overlay-active { + overflow: hidden; + height: 100vh; +} +body.modal-overlay-active #modal_overlay { + right: 0; + left: 0; + opacity: 1; +} +.spinning { + position: relative; + padding-left: 32px !important; +} +.spinning::before { + position: absolute; + top: 0; + bottom: 0; + left: 0.2em; + width: 32px; + content: ""; + background: url(/luci-static/resources/icons/loading.gif) no-repeat center; + background-size: 16px; +} +#view { + border-radius: 0.25rem; + overflow: hidden; +} +#view > .spinning { + position: fixed; + top: 50%; + left: 50%; + transform: translateX(-50%) translateY(-50%); + padding: 1rem; + border-radius: 0.5rem; + background: #ffffff; + box-shadow: 0 0 1rem 0 rgba(136, 152, 170, 0.15); +} +.hidden { + display: none; +} +.left, +.left::before { + text-align: left !important; +} +.right, +.right::before { + text-align: right !important; +} +.center, +.center::before { + text-align: center !important; +} +.top { + align-self: flex-start !important; + vertical-align: top !important; +} +.bottom { + align-self: flex-end !important; + vertical-align: bottom !important; +} +.inline { + display: inline; +} +.cbi-page-actions { + padding: 1rem; + text-align: right; + justify-content: flex-end; +} +.cbi-page-actions > form[method="post"] { + display: inline-block; +} +.th[data-type="button"], +.td[data-type="button"], +.th[data-type="fvalue"], +.td[data-type="fvalue"] { + flex: 1 1 2em; + text-align: center; +} +.ifacebadge { + display: inline-flex; + align-items: center; + gap: 0.2rem; + padding: 0.25rem 0.8rem; + background: #eee; + border-radius: 4px; +} +td > .ifacebadge, +.td > .ifacebadge { + font-size: 0.875rem; + background-color: #f0f0f0; +} +.ifacebadge > em, +.ifacebadge > img { + display: inline-block; + margin: 0 0.75rem; +} +.ifacebadge > img + img { + margin: 0 0.2rem 0 0; +} +.network-status-table { + display: flex; + flex-wrap: wrap; +} +.network-status-table .ifacebox { + flex-grow: 1; + border-radius: 0.25rem; + overflow: hidden; + margin: 1rem; +} +.network-status-table .ifacebox-body { + display: flex; + flex-direction: column; + height: 100%; + gap: 0.5em; +} +.network-status-table .ifacebox-body > span { + flex: 10 10 auto; +} +.network-status-table .ifacebox-body > div { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + height: 100%; +} +.network-status-table .ifacebox-body .ifacebadge { + align-items: center; + flex: 1 1 auto; + min-width: 220px; + padding: 0.5em; + background-color: #fff; +} +.network-status-table .ifacebox-body .ifacebadge > span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.cbi-input-textarea { + font-family: inherit; + width: 100%; + font-size: 0.875rem; + min-height: 14rem; + padding: 0.8rem; + color: #8898aa; + border-radius: 0.25rem; + border: 1px solid #dee2e6; + min-width: 16rem; +} +#content_syslog { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); +} +#syslog { + font-size: small; + font-family: "argon"; + line-height: 1.25; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + padding: 1rem; + resize: none; + color: #242424; + border: 0; + border-radius: 0.25rem; + background-color: #ffffff; +} +#syslog:focus { + outline: 0; +} +.uci-change-list { + font-family: inherit; + overflow: scroll; + width: 100%; + display: flex; + flex-direction: column; + flex-wrap: wrap; +} +.uci-change-list ins, +.uci-change-legend-label ins { + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #0f0; + background-color: #cfc; +} +.uci-change-list del, +.uci-change-legend-label del { + font-style: normal; + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #f00; + background-color: #fcc; +} +.uci-change-list var, +.uci-change-legend-label var { + font-style: normal; + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #ccc; + background-color: #eee; +} +.uci-change-list var ins, +.uci-change-list var del { + font-style: normal; + padding: 0; + white-space: pre; + border: 0; +} +.uci-change-legend { + padding: 5px; +} +.uci-change-legend-label { + float: left; + width: 150px; +} +.uci-change-legend-label > ins, +.uci-change-legend-label > del, +.uci-change-legend-label > var { + display: block; + float: left; + width: 10px; + height: 10px; + margin-right: 4px; +} +.uci-change-legend-label var ins, +.uci-change-legend-label var del { + line-height: 0.4; + border: 0; +} +.uci-change-list var, +.uci-change-list del, +.uci-change-list ins { + padding: 0.5rem; +} +.uci-dialog .cbi-section { + padding: 0.5rem; +} +.uci-dialog .cbi-section .uci-change-legend { + line-height: 15px; + padding: 10px 20px 0 20px; +} +.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label { + padding: 0; + margin: 0; + position: relative; + float: none; + display: inline-block; + width: 25%; +} +.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label > ins, +.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label > del { + width: 14px; + height: 14px; +} +.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label > var { + position: relative; + width: 14px; + height: 14px; +} +.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label > var ins, +.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label > var del { + position: absolute; + left: 2px; + top: 2px; + right: 2px; + bottom: 2px; +} +.uci-dialog .cbi-section .uci-change-list { + overflow: auto; +} +.uci-dialog .cbi-section .uci-change-list + .right .btn { + color: #333; +} +.uci-dialog + .cbi-section + .uci-change-list + + .right + .cbi-dropdown + ul:not(.dropdown) + li { + color: #fff; +} +.uci-dialog .cbi-section .uci-change-list + .right .cbi-button { + padding: 0.45rem 0.8rem; +} +#iwsvg, +#iwsvg2, +#bwsvg { + border: thin solid #d4d4d4 !important; +} +#iwsvg, +[data-page="admin-status-realtime-bandwidth"] #bwsvg { + border-top: 0 !important; +} +.ifacebox { + line-height: 1.25; + display: inline-flex; + overflow: hidden; + flex-direction: column; + border-radius: 4px; + min-width: 100px; + background-color: #f9f9f9; +} +.ifacebox-head { + padding: 0.25em; + background: #eee; +} +.ifacebox-head.active { + background: #5e72e4; + background: var(--primary); +} +.ifacebox-head.active * { + color: #fff; + color: var(--white); +} +.ifacebox-body { + padding: 0.875rem 1rem; + line-height: 1.6em; +} +.cbi-image-button { + margin-left: 0.5rem; +} +.zonebadge { + display: inline-block; + padding: 0.2rem 0.5rem; + border-radius: 4px; +} +.zonebadge .ifacebadge { + margin: 0.1rem 0.2rem; + padding: 0.2rem 0.3rem; + border: thin solid #6c6c6c; +} +.zonebadge > input[type="text"] { + min-width: 10rem; + margin-top: 0.3rem; + padding: 0.16rem 1rem; +} +.zonebadge > em, +.zonebadge > strong { + display: inline-block; + margin: 0 0.2rem; +} +.cbi-value-field .cbi-input-checkbox, +.cbi-value-field .cbi-input-radio { + margin-top: 0.1rem; +} +.cbi-value-field > ul > li { + display: flex; +} +.cbi-value-field > ul > li > label { + margin-top: 0.5rem; +} +.cbi-value-field > ul > li .ifacebadge { + margin-top: -0.5rem; + margin-left: 0.4rem; + background-color: #eee; +} +.cbi-section-table-row > .cbi-value-field .cbi-dropdown { + min-width: 3rem; +} +.cbi-section-create { + display: inline-flex; + align-items: center; + padding: 0.5rem 1rem; +} +.cbi-section-remove { + padding: 0.5rem 1rem; +} +div.cbi-value var, +td.cbi-value-field var, +.td.cbi-value-field var { + font-style: italic; + color: #0069d6; +} +.cbi-optionals { + padding: 1rem 1rem 0 1rem; + border-top: thin solid #ccc; +} +.cbi-dropdown-container { + position: relative; +} +.cbi-tooltip-container, +span[data-tooltip], +span[data-tooltip] .label { + cursor: help !important; +} +.cbi-tooltip { + position: absolute; + z-index: 1000; + left: -1000px; + padding: 2px 5px; + transition: opacity 0.25s ease-out; + white-space: pre; + pointer-events: none; + opacity: 0; + border-radius: 3px; + background: #fff; + box-shadow: 0 0 2px #444; +} +.cbi-tooltip-container:hover .cbi-tooltip { + left: auto; + transition: opacity 0.25s ease-in; + opacity: 1; +} +.zonebadge .cbi-tooltip { + margin: -1.5rem 0 0 -0.5rem; + padding: 0.25rem; + background: inherit; +} +.zonebadge-empty { + color: #404040; + background: repeating-linear-gradient( + 45deg, + rgba(204, 204, 204, 0.5), + rgba(204, 204, 204, 0.5) 5px, + rgba(255, 255, 255, 0.5) 5px, + rgba(255, 255, 255, 0.5) 10px + ); +} +.zone-forwards { + display: flex; + min-width: 10rem; +} +.zone-forwards > * { + flex: 1 1 45%; +} +.zone-forwards > span { + flex-basis: 10%; + padding: 0 0.25rem; + text-align: center; +} +.zone-forwards .zone-src, +.zone-forwards .zone-dest { + display: flex; + flex-direction: column; +} +.label { + font-size: 0.875rem; + font-weight: bold; + padding: 0.3rem 0.8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: #fff !important; + border-radius: 3px; + background-color: #bfbfbf; + text-shadow: none; +} +label > input[type="checkbox"], +label > input[type="radio"] { + position: relative; + top: 0.4rem; + right: 0.2rem; + margin: 0; + vertical-align: bottom; +} +label[data-index][data-depends] { + padding-right: 2em; +} +.showSide { + display: none; +} +.darkMask { + position: fixed; + z-index: 99; + display: none; + width: 100%; + height: 100%; + content: ""; + top: 0; + background-color: rgba(0, 0, 0, 0.56); + transition: all 0.2s; +} +.darkMask.active { + display: block; +} +#diag-rc-output > pre, +#command-rc-output > pre, +[data-page="admin-services-wol"] .notice code { + font-size: 1.2rem; + font-size-adjust: 0.35; + line-height: normal; + display: block; + overflow-y: hidden; + width: 100%; + padding: 8.5px; + white-space: pre; + color: #eee; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); +} +[data-page="admin-network-diagnostics"] .table { + box-shadow: none; +} +[data-page="admin-network-diagnostics"] .cbi-section { + padding: 1rem; + font-family: monospace; + background: #fff !important; +} +[data-page="admin-network-diagnostics"] textarea { + background: transparent; + border-radius: 0.25rem; + font-family: "argon" !important; + color: #8898aa; + border: 1px solid #dee2e6; + padding: 0.5rem; +} +[data-page="admin-network-diagnostics"] .tr > .td { + background-color: #fff !important; + border-bottom: 1px solid #dee2e6 !important; +} +input[name="ping"], +input[name="traceroute"], +input[name="nslookup"] { + width: 80%; +} +.node-status-overview > .main fieldset:nth-child(4) .td:nth-child(2), +.node-status-processes > .main .table .tr .td:nth-child(3) { + white-space: normal; +} +div[style*="display:grid;grid-template-columns:repeat"] { + display: flex !important; + justify-content: space-evenly !important; + padding-bottom: 1rem; + flex-wrap: wrap; + font-family: "argon"; +} +div[style*="display:grid;grid-template-columns:repeat"] .ifacebox { + text-align: center; + flex-basis: 100px; +} +div[style*="display:grid;grid-template-columns:repeat"] + .ifacebox + .ifacebox-body { + font-size: 0.7rem; + padding: 0.875rem; +} +div[style*="display:grid;grid-template-columns:repeat"] + .ifacebox + .ifacebox-body + .cbi-tooltip-container { + font-size: inherit !important; +} +@media screen and (max-width: 484px) { + div[style*="display:grid;grid-template-columns:repeat"] .ifacebox { + flex-basis: 80px; + } + div[style*="display:grid;grid-template-columns:repeat"] + .ifacebox + .ifacebox-body { + padding: 0.875rem 0.5rem; + font-size: 0.6rem; + } +} +[data-page="admin-system-attendedsysupgrade"] #view .cbi-button { + margin-left: 0 !important; + margin-top: 1rem !important; +} +[data-page="admin-system-reboot"] p { + padding-left: 1.5rem; +} +[data-page="admin-system-reboot"] p > span { + position: relative; + top: 0.1rem; + left: 1rem; +} +[data-page="admin-system-reboot"] .cbi-button { + background: #fb6340 !important; + border-color: #fb6340 !important; + margin-left: 0 !important; +} +[data-page="admin-system-reboot"] #view > h2:first-child + p { + margin-bottom: 1rem; +} +[data-page="admin-system-poweroff"] .container h2 + br + p { + margin-bottom: 1rem; + padding-left: 1.5rem; +} +[data-page="admin-vpn-passwall"] h4 { + background: transparent; +} +[data-page="admin-system-filetransfer"] #cbi-upload { + margin-top: 0; +} +[data-page="admin-system-filetransfer"] .cbi-section-table { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); +} +#cbi-samba [data-tab="template"] .cbi-value-field { + display: block; +} +#cbi-samba [data-tab="template"] .cbi-value-title { + width: auto; + padding-bottom: 0.6rem; +} +[data-page="admin-system-admin"] .cbi-map h2, +[data-page="admin-system-admin-password"] .cbi-map h2, +[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, +[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { + margin-left: 0; + color: #32325d; + color: var(--gray-dark); +} +[data-page="admin-system-admin-sshkeys"] .cbi-dynlist { + margin-left: 1rem; +} +[data-page="admin-system-opkg"] h2 { + margin-left: 0; + color: #32325d; + color: var(--gray-dark); +} +.controls { + margin: 0.5em 1rem 1em 1rem !important; +} +.controls > * > .btn:not([aria-label$="page"]) { + flex-grow: initial !important; + margin-top: 0.25rem; +} +.controls > #pager > .btn[aria-label$="page"] { + font-size: 1.4rem; + font-weight: bold; +} +.controls > * > label { + margin-bottom: 0.2rem; +} +[data-page="admin-system-opkg"] div.btn { + line-height: 3; + display: inline; + padding: 0.3rem 0.6rem; +} +[data-page^="admin-system-admin"]:not(.node-main-login) + .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent > .container { + margin-top: 1rem; + padding-top: 0.01rem; +} +[data-page="admin-system-opkg"] #maincontent > .container { + margin: 0 1.25rem 1rem 1.25rem; + margin-bottom: 1rem; +} +.td.version, +.td.size { + white-space: normal !important; + word-break: break-word; +} +.cbi-tabmenu + .cbi-section { + margin-top: 0; +} +[data-page="admin-system-system"] .control-group { + margin-top: 0.5rem; +} +[data-page="admin-system-system"] .cbi-dynlist { + margin: 0.25rem 0; +} +[data-page="admin-system-startup"] [data-tab-title] p { + margin-left: 0; + margin-bottom: 0; + position: relative; +} +[data-page="admin-system-startup"] textarea { + line-height: 1.25; + overflow-y: auto; + width: 100%; + min-height: 15rem; + padding: 1rem; + resize: none; + color: #8898aa; + border-radius: 0.25rem; + border: 1px solid #dee2e6; +} +[data-page="admin-system-startup"] textarea:focus-visible { + outline: none; + box-shadow: none; + border: 1px solid var(--primary); +} +[data-page="admin-system-crontab"] #view p { + margin-bottom: 1rem; +} +[data-page="admin-system-crontab"] #view p:last-child { + margin-bottom: 0; +} +[data-page="admin-system-crontab"] #view p textarea { + line-height: 1.25; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + padding: 1rem; + resize: none; + background-color: transparent; + background: var(--white); + outline: none; + color: #8898aa; + border-radius: 0.25rem; + border: 1px solid #dee2e6; +} +[data-page="admin-system-attendedsysupgrade-configuration"] + .cbi-map + .cbi-map-descr { + padding-bottom: 0; +} +[data-page="admin-system-flash"] .cbi-value { + padding: 0; +} +[data-page="admin-system-flash"] .cbi-section .cbi-section { + margin-top: 0; +} +[data-page="admin-system-flash"] .cbi-map-tabbed { + border-radius: 0.25rem; +} +[data-page="admin-system-flash"] .cbi-section-node { + padding-top: 0; + padding-bottom: 0.5rem; +} +[data-page="admin-system-flash"] legend { + display: block !important; + font-size: 1.2rem; + width: 100%; + display: block; + margin-bottom: 0; + padding: 1rem 0 1rem 1.5rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + line-height: 1.5; + margin-bottom: 0rem; + letter-spacing: 0.1rem; + color: #32325d; + font-weight: bold; +} +[data-page="admin-system-flash"] .cbi-section-descr { + font-weight: 600; + padding: 1rem 0 1rem 1.5rem; + color: #525f7f; +} +[data-page="admin-system-flash"] .cbi-page-actions { + padding: 0rem 1rem 1rem 0rem; +} +[data-page="admin-system-flash"] .modal label > input[type="checkbox"] { + top: -0.25rem; +} +[data-page="admin-system-flash"] .modal .btn { + white-space: normal !important; +} +#cbi-wireless > #wifi_assoclist_table > .tr { + box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; +} +#cbi-wireless > #wifi_assoclist_table > .tr.placeholder > .td { + right: 33px; + bottom: 33px; + left: 33px; + border-top: thin solid #ddd !important; +} +#cbi-wireless > #wifi_assoclist_table > .tr.table-titles { + box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; +} +#cbi-wireless > #wifi_assoclist_table > .tr.table-titles > .th { + border-bottom: thin solid #ddd; + box-shadow: 0 -1px 0 0 #ddd; +} +#wifi_assoclist_table > .tr > .td[data-title="RX Rate / TX Rate"] { + width: 23rem; +} +[data-page="admin-network-dhcp"] .cbi-value { + padding: 0; +} +[data-page="admin-network-dhcp"] [data-tab-active="true"] { + padding: 1rem 0 !important; +} +#iptables { + margin: 0; +} +.Firewall form { + margin: 2rem 2rem 0 0; + padding: 0; + box-shadow: none; +} +#cbi-firewall-redirect table *, +#cbi-network-switch_vlan table *, +#cbi-firewall-zone table * { + font-size: small; +} +#cbi-firewall-redirect table input[type="text"], +#cbi-network-switch_vlan table input[type="text"], +#cbi-firewall-zone table input[type="text"] { + width: 5rem; +} +#cbi-firewall-redirect table select, +#cbi-network-switch_vlan table select, +#cbi-firewall-zone table select { + min-width: 3.5rem; +} +#cbi-network-switch_vlan .th, +#cbi-network-switch_vlan .td { + flex-basis: 12%; +} +#cbi-firewall-zone .table, +#cbi-network-switch_vlan .table { + display: block; +} +#cbi-firewall-zone .td, +#cbi-network-switch_vlan .td { + width: 100%; +} +[data-page="admin-network-firewall-custom"] #view p, +[data-page="admin-status-routes"] #view p { + padding: 0 1.5rem; + margin-bottom: 1rem; +} +[data-page="admin-network-firewall-custom"] #view p textarea, +[data-page="admin-status-routes"] #view p textarea { + padding: 1rem; + border-radius: 0.25rem; +} +[data-page="admin-network-firewall-custom"] #view > h3, +[data-page="admin-status-routes"] #view > h3 { + border-radius: 0.25rem 0.25rem 0 0; +} +#applyreboot-container { + margin: 2rem; +} +#applyreboot-section { + line-height: 300%; + margin: 2rem; +} +.OpenVPN a { + line-height: initial !important; +} +.commandbox { + width: 24% !important; + margin: 10px 0 0 10px !important; + padding: 0.5rem 1rem; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), + 0 1px 2px rgba(0, 0, 0, 0.05); +} +.commandbox h3 { + line-height: normal !important; + overflow: hidden; + margin: 6px 0 !important; + white-space: nowrap; + text-overflow: ellipsis; +} +.commandbox div { + left: auto !important; +} +.commandbox code { + position: absolute; + overflow: hidden; + max-width: 60%; + margin-left: 4px; + padding: 2px 3px; + white-space: nowrap; + text-overflow: ellipsis; +} +.commandbox code:hover { + overflow-y: auto; + max-height: 50px; + white-space: normal; +} +.commandbox p:first-of-type { + margin-top: -6px; +} +.commandbox p:nth-of-type(2) { + margin-top: 2px; +} +[data-page^="admin-system-commands"] .panel-title, +[data-page^="command-cfg"] .mobile-hide, +[data-page^="command-cfg"] .showSide { + display: none; +} +#command-rc-output .alert-message { + line-height: 1.42857143; + position: absolute; + top: 40px; + right: 32px; + max-width: 40%; + margin: 0; + animation: anim-fade-in 1.5s forwards; + word-break: break-word; + opacity: 0; +} +@keyframes anim-fade-in { + 100% { + opacity: 1; + } +} +input[type="checkbox"] { + appearance: none !important; + -webkit-appearance: none !important; + border: 1px solid var(--primary); + width: 16px !important; + height: 16px !important; + padding: 0; + cursor: pointer; + transition: all 0.2s; + margin: 0.75rem 0 0 0; +} +input[type="checkbox"]:checked { + border: 1px solid #5e72e4; + border: 1px solid var(--primary); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e") !important; + background-color: #5e72e4; + background-color: var(--primary); + background-size: 70%; + background-repeat: no-repeat; + background-position: center; +} +.fb-container .cbi-button { + height: auto !important; +} +#cbi-usb_printer-printer em { + display: block; + padding: 1rem; + text-align: center; +} +pre.command-output { + padding: 1.5rem; +} +[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { + padding: 1.5rem !important; +} +[data-page="admin-nlbw-backup"] form { + padding-left: 1.5rem; +} +[data-page="admin-status-iptables"] .right { + margin-bottom: 0 !important; +} +[data-page="admin-services-ttyd"] .container { + display: flex; + flex-direction: column; +} +[data-page="admin-services-ttyd"] #view { + flex: 1; +} +[data-page="admin-services-ttyd"] #view iframe { + height: 100%; +} +[data-page="admin-system-fileassistant"] .fb-container .panel-title { + padding: 0.5rem 0.75rem !important; +} +[data-page="admin-system-fileassistant"] .cbi-section.fb-container { + padding: 0.5rem; +} +[data-page="admin-system-fileassistant"] .fb-container .panel-container { + border-bottom-color: #dee2e6; +} +[data-page^="admin-services-openclash"] .cbi-tabmenu > li { + border-right: none !important; + margin: 0 0.4rem 0 0 !important; +} +[data-page^="admin-services-openclash"] .cbi-tabmenu > li:last-child { + margin-right: 0 !important; +} +[data-page^="admin-services-openclash"] #tab-content .dom { + padding: 0 1rem 1rem 1rem; +} +[data-page^="admin-services-openclash"] .cbi-input-file { + padding: 0.2813rem; + box-sizing: content-box; + width: 15rem !important; +} +[data-page^="admin-services-openclash"] + [id="container.openclash.config.debug"] + fieldset { + border: none !important; + padding: 1rem !important; +} +[data-page^="admin-services-openclash"] #diag-rc-output > pre, +[data-page^="admin-services-openclash"] #dns-rc-output > pre { + font-size: 0.875rem; + color: #8898aa; + border: 1px solid #dee2e6; + background-color: transparent; + border-radius: 0.25rem; + font-family: "argon" !important; + box-shadow: none; +} +[data-page^="admin-services-openclash"] #debug-rc-output > textarea { + font-family: "argon" !important; +} +[data-page^="admin-services-openclash"] .CodeMirror { + font-size: inherit; + font-family: "argon" !important; +} +[data-page^="admin-services-openclash"] .cbi-button-up, +[data-page^="admin-services-openclash"] .cbi-button-down { + padding: 0.8rem 1.5rem; + background-color: #f1f1f1; + font-size: 0; +} +[data-page^="admin-services-openclash"] select#CORE_VERSION, +[data-page^="admin-services-openclash"] select#RELEASE_BRANCH { + width: auto; +} +@media all and (-ms-high-contrast: none) { + .main > .main-left > .nav > .slide > .menu::before { + top: 30.25%; + } + .main > .main-left > .nav > li:last-child::before { + top: 20%; + } + .showSide::before { + top: -12px; + } +} +@media screen and (max-width: 1600px) { + header > .fill > .container > #logo { + margin: 0 2.5rem 0 0.5rem; + } + .main-left { + width: calc(0% + 13rem); + } + .btn:not(button), + .label { + padding: 0.5rem 0.75rem; + } + .cbi-value-title { + width: 15rem; + padding-right: 0.6rem; + } + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"], + .cbi-value textarea { + min-width: 18rem; + } + #cbi-firewall-zone .cbi-input-select { + min-width: 9rem; + } + .cbi-input-textarea { + font-size: small; + } + .node-admin-status > .main fieldset li > a { + padding: 0.3rem 0.6rem; + } +} +@media screen and (max-width: 1366px) { + header > .fill > .container { + cursor: default; + } + .main-left { + width: calc(0% + 13rem); + } + .tabs > li > a, + .cbi-tabmenu > li > a { + padding: 0.2rem 0.8rem; + } + .panel-title { + font-size: 1.1rem; + padding-bottom: 1rem; + } + table { + font-size: 0.875rem !important; + width: 100% !important; + } + .table .cbi-input-text { + width: 100%; + } + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 16rem; + } + #cbi-firewall-zone .cbi-input-select { + min-width: 4rem; + } + .main > .main-left > .nav > li, + .main > .main-left > .nav > li > a, + .main .main-left .nav > li > a:first-child, + .main > .main-left > .nav > .slide > .menu, + .main > .main-left > .nav > li > [data-title="Log_out"] { + font-size: 0.9rem; + } + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: 0.875rem; + } + #modal_overlay { + top: 0rem; + } + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { + display: block; + } + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), + [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), + [data-page="admin-network-hosts"] .table, + [data-page="admin-network-routes"] .table { + overflow-y: visible; + } + .commandbox { + width: 32% !important; + } + .btn:not(button), + .cbi-button { + font-size: 0.875rem; + } +} +@media screen and (max-width: 1152px) { + header > .fill > .container > #logo { + display: none; + } + header > .fill > .container > .brand { + position: relative; + } + html, + .main { + overflow-y: visible; + } + .main > .loading > span { + top: 25%; + } + .main-left { + width: calc(0% + 13rem); + } + body:not(.logged-in) .showSide { + visibility: hidden; + width: 0; + margin: 0; + } + .node-main-login > .main .cbi-value-title { + text-align: left; + } + .cbi-value-title { + width: 12rem; + padding-right: 1rem; + } + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"] { + width: 16rem; + min-width: 16rem; + } + .cbi-value input[name^="pw"], + .cbi-value input[data-update="change"]:nth-child(2) { + width: 13rem !important; + min-width: 13rem; + } + #diag-rc-output > pre, + #command-rc-output > pre, + [data-page="admin-services-wol"] .notice code { + font-size: 1rem; + } + .table { + display: block; + } + .Interfaces .table { + overflow-x: hidden; + } + #packages.table { + display: grid; + } + .tr { + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + .Overview .table[width="100%"] > .tr { + flex-wrap: nowrap; + } + .tr.placeholder { + border-bottom: thin solid #ddd; + } + .tr.placeholder > .td, + #cbi-firewall .tr > .td, + #cbi-network .tr:nth-child(2) > .td, + .cbi-section #wifi_assoclist_table .tr > .td { + border-top: 0; + } + .th, + .td { + display: inline-block; + align-self: flex-start; + flex: 2 2 10%; + text-overflow: ellipsis; + word-wrap: break-word; + } + .td select, + .td input[type="text"] { + width: 100%; + word-wrap: normal; + } + .td [data-dynlist] > input, + .td input.cbi-input-password { + width: calc(100% - 1.5rem); + } + .td[data-type="button"], + .td[data-type="fvalue"] { + flex: 1 1 12.5%; + text-align: left; + } + .th.cbi-value-field, + .td.cbi-value-field, + .th.cbi-section-table-cell, + .td.cbi-section-table-cell { + flex-basis: auto; + padding-top: 1rem; + } + .cbi-section-table-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + } + .td.cbi-value-field, + .cbi-section-table-cell { + display: inline-block; + flex: 10 10 auto; + flex-basis: 50%; + text-align: center; + } + .td.cbi-section-actions { + vertical-align: bottom; + } + .tr.table-titles, + .tr.cbi-section-table-titles, + .tr.cbi-section-table-descr { + display: none; + } + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-size: 0.9rem; + display: block; + flex: 1 1 100%; + border-bottom: thin solid rgba(0, 0, 0, 0.26); + background: #e9ecef; + } + .td[data-title], + [data-page^="admin-status-realtime"] .td[id] { + text-align: left; + } + .td[data-title]::before { + display: block; + } + .cbi-button + .cbi-button { + margin-left: 0; + } + .td.cbi-section-actions > * > *, + .td.cbi-section-actions > * > form > * { + margin: 2.1px 3px; + } + .Firewall form { + position: static !important; + margin: 0 0 2rem 0; + padding: 2rem; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + } + .Firewall form input { + width: 100% !important; + margin: 0; + margin-top: 1rem; + } + .Firewall .center, + .Firewall .center::before { + text-align: left !important; + } + .commandbox { + width: 100% !important; + margin-left: 0 !important; + } + .btn:not(button), + .cbi-button { + font-size: 0.875rem; + } +} +@media screen and (max-width: 768px) { + body { + font-size: 0.875rem; + } + .cbi-progressbar::after { + font-size: 0.6rem; + } + .main-left { + position: fixed; + z-index: 100; + width: 0; + } + .main-left.active { + width: 13rem; + } + .main-right { + width: 100%; + } + .main-right.active { + overflow-y: hidden; + } + .darkMask.active { + display: block; + } + .showSide { + padding: 0.1rem; + position: relative; + z-index: 99; + display: inline-block !important; + } + .showSide::before { + font-family: "argon" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\e20e"; + font-size: 1.7rem; + } + header > .fill > .container > .flex1 > .brand { + display: inline-block; + } + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: 0.875rem; + } +} +@media screen and (max-width: 600px) { + .mobile-hide { + display: none; + } + #maincontent > .container { + margin: 0 1rem 1rem 1rem; + } + .cbi-value-title { + text-align: left; + } + [data-page="admin-system-flash"] legend { + padding: 1rem 0 1rem 1rem; + } + [data-page="admin-system-flash"] .cbi-section-descr { + padding: 1rem 0 1rem 1rem; + } + [data-page="admin-system-flash"] .cbi-value { + padding: 0 1rem; + } + [data-page="admin-network-dhcp"] [data-tab-active="true"] { + padding: 1rem 1rem !important; + } + .cbi-dynlist p { + padding: 0.5rem 1rem; + } + body { + overflow-x: hidden; + } + .node-main-login + .main + .main-right + #maincontent + .container + .cbi-map + .cbi-section + .cbi-section-node + .cbi-value + .cbi-value-field { + width: 16rem; + } + .node-main-login footer { + display: none; + } + .tabs::-webkit-scrollbar, + .cbi-tabmenu::-webkit-scrollbar { + width: 0px; + height: 0px; + } + .cbi-value-field, + .cbi-value-description { + display: block !important; + padding-left: 0 !important; + padding-right: 0 !important; + } + [data-page="admin-system-admin-password"] .cbi-value-field { + display: table-cell !important; + } + .modal.cbi-modal { + max-width: 100%; + max-height: none; + } + .modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 100%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + margin: 5em auto; + padding: 1em; + border-radius: 3px !important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + } + .cbi-dropdown[open] > ul.dropdown { + margin-bottom: 1rem; + } + .login-page .login-container footer { + display: none; + } +} +@media screen and (min-width: 600px) { + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + ::-webkit-scrollbar, + ::-webkit-scrollbar-corner { + background: transparent; + } + ::-webkit-scrollbar-thumb { + background: var(--primary); + border-radius: 10px; + } + ::-webkit-scrollbar-thumb:hover { + background: var(--primary); + } + ::-webkit-scrollbar-thumb:active { + background: var(--primary); + } +} +@media screen and (max-width: 480px) { + .mobile-hide { + display: none; + } + .login-page .login-container { + margin-left: 0rem !important; + width: 100%; + } + .login-page .login-container .login-form .form-login .input-group::before { + color: #525461; + } + .login-page .login-container .login-form .form-login .input-group input { + color: #525461; + border-bottom: white 1px solid; + border-bottom: var(--white) 1px solid; + border-radius: 0; + } +} diff --git a/luci-theme-routerich/htdocs/luci-static/routerich/js/jquery.min.js b/luci-theme-routerich/htdocs/luci-static/routerich/js/jquery.min.js index eeb0dff4..0d28d663 100644 --- a/luci-theme-routerich/htdocs/luci-static/routerich/js/jquery.min.js +++ b/luci-theme-routerich/htdocs/luci-static/routerich/js/jquery.min.js @@ -1,2 +1,3231 @@ +! function(e, t) { + "use strict"; + "object" == typeof module && "object" == typeof module.exports ? module.exports = e.document ? t(e, !0) : function(e) { + if (!e.document) throw new Error("jQuery requires a window with a document"); + return t(e) + } : t(e) +}("undefined" != typeof window ? window : this, function(C, e) { + "use strict"; + var t = [], + r = Object.getPrototypeOf, + s = t.slice, + g = t.flat ? function(e) { + return t.flat.call(e) + } : function(e) { + return t.concat.apply([], e) + }, + u = t.push, + i = t.indexOf, + n = {}, + o = n.toString, + v = n.hasOwnProperty, + a = v.toString, + l = a.call(Object), + y = {}, + m = function(e) { + return "function" == typeof e && "number" != typeof e.nodeType + }, + x = function(e) { + return null != e && e === e.window + }, + E = C.document, + c = { + type: !0, + src: !0, + nonce: !0, + noModule: !0 + }; -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0+~]|" + M + ")" + M + "*"), + U = new RegExp(M + "|>"), + X = new RegExp(F), + V = new RegExp("^" + I + "$"), + G = { + ID: new RegExp("^#(" + I + ")"), + CLASS: new RegExp("^\\.(" + I + ")"), + TAG: new RegExp("^(" + I + "|[*])"), + ATTR: new RegExp("^" + W), + PSEUDO: new RegExp("^" + F), + CHILD: new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + M + "*(even|odd|(([+-]|)(\\d*)n|)" + M + "*(?:([+-]|)" + M + "*(\\d+)|))" + M + "*\\)|)", "i"), + bool: new RegExp("^(?:" + R + ")$", "i"), + needsContext: new RegExp("^" + M + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + M + "*((?:-\\d)?\\d*)" + M + "*\\)|)(?=[^-]|$)", "i") + }, + Y = /HTML$/i, + Q = /^(?:input|select|textarea|button)$/i, + J = /^h\d$/i, + K = /^[^{]+\{\s*\[native \w/, + Z = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + ee = /[+~]/, + te = new RegExp("\\\\[\\da-fA-F]{1,6}" + M + "?|\\\\([^\\r\\n\\f])", "g"), + ne = function(e, t) { + var n = "0x" + e.slice(1) - 65536; + return t || (n < 0 ? String.fromCharCode(n + 65536) : String.fromCharCode(n >> 10 | 55296, 1023 & n | 56320)) + }, + re = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + ie = function(e, t) { + return t ? "\0" === e ? "\ufffd" : e.slice(0, -1) + "\\" + e.charCodeAt(e.length - 1).toString(16) + " " : "\\" + e + }, + oe = function() { + T() + }, + ae = be(function(e) { + return !0 === e.disabled && "fieldset" === e.nodeName.toLowerCase() + }, { + dir: "parentNode", + next: "legend" + }); + try { + H.apply(t = O.call(p.childNodes), p.childNodes), t[p.childNodes.length].nodeType + } catch (e) { + H = { + apply: t.length ? function(e, t) { + L.apply(e, O.call(t)) + } : function(e, t) { + var n = e.length, + r = 0; + while (e[n++] = t[r++]); + e.length = n - 1 + } + } + } + + function se(t, e, n, r) { + var i, o, a, s, u, l, c, f = e && e.ownerDocument, + p = e ? e.nodeType : 9; + if (n = n || [], "string" != typeof t || !t || 1 !== p && 9 !== p && 11 !== p) return n; + if (!r && (T(e), e = e || C, E)) { + if (11 !== p && (u = Z.exec(t))) + if (i = u[1]) { + if (9 === p) { + if (!(a = e.getElementById(i))) return n; + if (a.id === i) return n.push(a), n + } else if (f && (a = f.getElementById(i)) && y(e, a) && a.id === i) return n.push(a), n + } else { + if (u[2]) return H.apply(n, e.getElementsByTagName(t)), n; + if ((i = u[3]) && d.getElementsByClassName && e.getElementsByClassName) return H.apply(n, e.getElementsByClassName(i)), n + } if (d.qsa && !N[t + " "] && (!v || !v.test(t)) && (1 !== p || "object" !== e.nodeName.toLowerCase())) { + if (c = t, f = e, 1 === p && (U.test(t) || z.test(t))) { + (f = ee.test(t) && ye(e.parentNode) || e) === e && d.scope || ((s = e.getAttribute("id")) ? s = s.replace(re, ie) : e.setAttribute("id", s = S)), o = (l = h(t)).length; + while (o--) l[o] = (s ? "#" + s : ":scope") + " " + xe(l[o]); + c = l.join(",") + } + try { + return H.apply(n, f.querySelectorAll(c)), n + } catch (e) { + N(t, !0) + } finally { + s === S && e.removeAttribute("id") + } + } + } + return g(t.replace($, "$1"), e, n, r) + } + + function ue() { + var r = []; + return function e(t, n) { + return r.push(t + " ") > b.cacheLength && delete e[r.shift()], e[t + " "] = n + } + } + + function le(e) { + return e[S] = !0, e + } + + function ce(e) { + var t = C.createElement("fieldset"); + try { + return !!e(t) + } catch (e) { + return !1 + } finally { + t.parentNode && t.parentNode.removeChild(t), t = null + } + } + + function fe(e, t) { + var n = e.split("|"), + r = n.length; + while (r--) b.attrHandle[n[r]] = t + } + + function pe(e, t) { + var n = t && e, + r = n && 1 === e.nodeType && 1 === t.nodeType && e.sourceIndex - t.sourceIndex; + if (r) return r; + if (n) + while (n = n.nextSibling) + if (n === t) return -1; + return e ? 1 : -1 + } + + function de(t) { + return function(e) { + return "input" === e.nodeName.toLowerCase() && e.type === t + } + } + + function he(n) { + return function(e) { + var t = e.nodeName.toLowerCase(); + return ("input" === t || "button" === t) && e.type === n + } + } + + function ge(t) { + return function(e) { + return "form" in e ? e.parentNode && !1 === e.disabled ? "label" in e ? "label" in e.parentNode ? e.parentNode.disabled === t : e.disabled === t : e.isDisabled === t || e.isDisabled !== !t && ae(e) === t : e.disabled === t : "label" in e && e.disabled === t + } + } + + function ve(a) { + return le(function(o) { + return o = +o, le(function(e, t) { + var n, r = a([], e.length, o), + i = r.length; + while (i--) e[n = r[i]] && (e[n] = !(t[n] = e[n])) + }) + }) + } + + function ye(e) { + return e && "undefined" != typeof e.getElementsByTagName && e + } + for (e in d = se.support = {}, i = se.isXML = function(e) { + var t = e.namespaceURI, + n = (e.ownerDocument || e).documentElement; + return !Y.test(t || n && n.nodeName || "HTML") + }, T = se.setDocument = function(e) { + var t, n, r = e ? e.ownerDocument || e : p; + return r != C && 9 === r.nodeType && r.documentElement && (a = (C = r).documentElement, E = !i(C), p != C && (n = C.defaultView) && n.top !== n && (n.addEventListener ? n.addEventListener("unload", oe, !1) : n.attachEvent && n.attachEvent("onunload", oe)), d.scope = ce(function(e) { + return a.appendChild(e).appendChild(C.createElement("div")), "undefined" != typeof e.querySelectorAll && !e.querySelectorAll(":scope fieldset div").length + }), d.attributes = ce(function(e) { + return e.className = "i", !e.getAttribute("className") + }), d.getElementsByTagName = ce(function(e) { + return e.appendChild(C.createComment("")), !e.getElementsByTagName("*").length + }), d.getElementsByClassName = K.test(C.getElementsByClassName), d.getById = ce(function(e) { + return a.appendChild(e).id = S, !C.getElementsByName || !C.getElementsByName(S).length + }), d.getById ? (b.filter.ID = function(e) { + var t = e.replace(te, ne); + return function(e) { + return e.getAttribute("id") === t + } + }, b.find.ID = function(e, t) { + if ("undefined" != typeof t.getElementById && E) { + var n = t.getElementById(e); + return n ? [n] : [] + } + }) : (b.filter.ID = function(e) { + var n = e.replace(te, ne); + return function(e) { + var t = "undefined" != typeof e.getAttributeNode && e.getAttributeNode("id"); + return t && t.value === n + } + }, b.find.ID = function(e, t) { + if ("undefined" != typeof t.getElementById && E) { + var n, r, i, o = t.getElementById(e); + if (o) { + if ((n = o.getAttributeNode("id")) && n.value === e) return [o]; + i = t.getElementsByName(e), r = 0; + while (o = i[r++]) + if ((n = o.getAttributeNode("id")) && n.value === e) return [o] + } + return [] + } + }), b.find.TAG = d.getElementsByTagName ? function(e, t) { + return "undefined" != typeof t.getElementsByTagName ? t.getElementsByTagName(e) : d.qsa ? t.querySelectorAll(e) : void 0 + } : function(e, t) { + var n, r = [], + i = 0, + o = t.getElementsByTagName(e); + if ("*" === e) { + while (n = o[i++]) 1 === n.nodeType && r.push(n); + return r + } + return o + }, b.find.CLASS = d.getElementsByClassName && function(e, t) { + if ("undefined" != typeof t.getElementsByClassName && E) return t.getElementsByClassName(e) + }, s = [], v = [], (d.qsa = K.test(C.querySelectorAll)) && (ce(function(e) { + var t; + a.appendChild(e).innerHTML = "", e.querySelectorAll("[msallowcapture^='']").length && v.push("[*^$]=" + M + "*(?:''|\"\")"), e.querySelectorAll("[selected]").length || v.push("\\[" + M + "*(?:value|" + R + ")"), e.querySelectorAll("[id~=" + S + "-]").length || v.push("~="), (t = C.createElement("input")).setAttribute("name", ""), e.appendChild(t), e.querySelectorAll("[name='']").length || v.push("\\[" + M + "*name" + M + "*=" + M + "*(?:''|\"\")"), e.querySelectorAll(":checked").length || v.push(":checked"), e.querySelectorAll("a#" + S + "+*").length || v.push(".#.+[+~]"), e.querySelectorAll("\\\f"), v.push("[\\r\\n\\f]") + }), ce(function(e) { + e.innerHTML = ""; + var t = C.createElement("input"); + t.setAttribute("type", "hidden"), e.appendChild(t).setAttribute("name", "D"), e.querySelectorAll("[name=d]").length && v.push("name" + M + "*[*^$|!~]?="), 2 !== e.querySelectorAll(":enabled").length && v.push(":enabled", ":disabled"), a.appendChild(e).disabled = !0, 2 !== e.querySelectorAll(":disabled").length && v.push(":enabled", ":disabled"), e.querySelectorAll("*,:x"), v.push(",.*:") + })), (d.matchesSelector = K.test(c = a.matches || a.webkitMatchesSelector || a.mozMatchesSelector || a.oMatchesSelector || a.msMatchesSelector)) && ce(function(e) { + d.disconnectedMatch = c.call(e, "*"), c.call(e, "[s!='']:x"), s.push("!=", F) + }), v = v.length && new RegExp(v.join("|")), s = s.length && new RegExp(s.join("|")), t = K.test(a.compareDocumentPosition), y = t || K.test(a.contains) ? function(e, t) { + var n = 9 === e.nodeType ? e.documentElement : e, + r = t && t.parentNode; + return e === r || !(!r || 1 !== r.nodeType || !(n.contains ? n.contains(r) : e.compareDocumentPosition && 16 & e.compareDocumentPosition(r))) + } : function(e, t) { + if (t) + while (t = t.parentNode) + if (t === e) return !0; + return !1 + }, D = t ? function(e, t) { + if (e === t) return l = !0, 0; + var n = !e.compareDocumentPosition - !t.compareDocumentPosition; + return n || (1 & (n = (e.ownerDocument || e) == (t.ownerDocument || t) ? e.compareDocumentPosition(t) : 1) || !d.sortDetached && t.compareDocumentPosition(e) === n ? e == C || e.ownerDocument == p && y(p, e) ? -1 : t == C || t.ownerDocument == p && y(p, t) ? 1 : u ? P(u, e) - P(u, t) : 0 : 4 & n ? -1 : 1) + } : function(e, t) { + if (e === t) return l = !0, 0; + var n, r = 0, + i = e.parentNode, + o = t.parentNode, + a = [e], + s = [t]; + if (!i || !o) return e == C ? -1 : t == C ? 1 : i ? -1 : o ? 1 : u ? P(u, e) - P(u, t) : 0; + if (i === o) return pe(e, t); + n = e; + while (n = n.parentNode) a.unshift(n); + n = t; + while (n = n.parentNode) s.unshift(n); + while (a[r] === s[r]) r++; + return r ? pe(a[r], s[r]) : a[r] == p ? -1 : s[r] == p ? 1 : 0 + }), C + }, se.matches = function(e, t) { + return se(e, null, null, t) + }, se.matchesSelector = function(e, t) { + if (T(e), d.matchesSelector && E && !N[t + " "] && (!s || !s.test(t)) && (!v || !v.test(t))) try { + var n = c.call(e, t); + if (n || d.disconnectedMatch || e.document && 11 !== e.document.nodeType) return n + } catch (e) { + N(t, !0) + } + return 0 < se(t, C, null, [e]).length + }, se.contains = function(e, t) { + return (e.ownerDocument || e) != C && T(e), y(e, t) + }, se.attr = function(e, t) { + (e.ownerDocument || e) != C && T(e); + var n = b.attrHandle[t.toLowerCase()], + r = n && j.call(b.attrHandle, t.toLowerCase()) ? n(e, t, !E) : void 0; + return void 0 !== r ? r : d.attributes || !E ? e.getAttribute(t) : (r = e.getAttributeNode(t)) && r.specified ? r.value : null + }, se.escape = function(e) { + return (e + "").replace(re, ie) + }, se.error = function(e) { + throw new Error("Syntax error, unrecognized expression: " + e) + }, se.uniqueSort = function(e) { + var t, n = [], + r = 0, + i = 0; + if (l = !d.detectDuplicates, u = !d.sortStable && e.slice(0), e.sort(D), l) { + while (t = e[i++]) t === e[i] && (r = n.push(i)); + while (r--) e.splice(n[r], 1) + } + return u = null, e + }, o = se.getText = function(e) { + var t, n = "", + r = 0, + i = e.nodeType; + if (i) { + if (1 === i || 9 === i || 11 === i) { + if ("string" == typeof e.textContent) return e.textContent; + for (e = e.firstChild; e; e = e.nextSibling) n += o(e) + } else if (3 === i || 4 === i) return e.nodeValue + } else + while (t = e[r++]) n += o(t); + return n + }, (b = se.selectors = { + cacheLength: 50, + createPseudo: le, + match: G, + attrHandle: {}, + find: {}, + relative: { + ">": { + dir: "parentNode", + first: !0 + }, + " ": { + dir: "parentNode" + }, + "+": { + dir: "previousSibling", + first: !0 + }, + "~": { + dir: "previousSibling" + } + }, + preFilter: { + ATTR: function(e) { + return e[1] = e[1].replace(te, ne), e[3] = (e[3] || e[4] || e[5] || "").replace(te, ne), "~=" === e[2] && (e[3] = " " + e[3] + " "), e.slice(0, 4) + }, + CHILD: function(e) { + return e[1] = e[1].toLowerCase(), "nth" === e[1].slice(0, 3) ? (e[3] || se.error(e[0]), e[4] = +(e[4] ? e[5] + (e[6] || 1) : 2 * ("even" === e[3] || "odd" === e[3])), e[5] = +(e[7] + e[8] || "odd" === e[3])) : e[3] && se.error(e[0]), e + }, + PSEUDO: function(e) { + var t, n = !e[6] && e[2]; + return G.CHILD.test(e[0]) ? null : (e[3] ? e[2] = e[4] || e[5] || "" : n && X.test(n) && (t = h(n, !0)) && (t = n.indexOf(")", n.length - t) - n.length) && (e[0] = e[0].slice(0, t), e[2] = n.slice(0, t)), e.slice(0, 3)) + } + }, + filter: { + TAG: function(e) { + var t = e.replace(te, ne).toLowerCase(); + return "*" === e ? function() { + return !0 + } : function(e) { + return e.nodeName && e.nodeName.toLowerCase() === t + } + }, + CLASS: function(e) { + var t = m[e + " "]; + return t || (t = new RegExp("(^|" + M + ")" + e + "(" + M + "|$)")) && m(e, function(e) { + return t.test("string" == typeof e.className && e.className || "undefined" != typeof e.getAttribute && e.getAttribute("class") || "") + }) + }, + ATTR: function(n, r, i) { + return function(e) { + var t = se.attr(e, n); + return null == t ? "!=" === r : !r || (t += "", "=" === r ? t === i : "!=" === r ? t !== i : "^=" === r ? i && 0 === t.indexOf(i) : "*=" === r ? i && -1 < t.indexOf(i) : "$=" === r ? i && t.slice(-i.length) === i : "~=" === r ? -1 < (" " + t.replace(B, " ") + " ").indexOf(i) : "|=" === r && (t === i || t.slice(0, i.length + 1) === i + "-")) + } + }, + CHILD: function(h, e, t, g, v) { + var y = "nth" !== h.slice(0, 3), + m = "last" !== h.slice(-4), + x = "of-type" === e; + return 1 === g && 0 === v ? function(e) { + return !!e.parentNode + } : function(e, t, n) { + var r, i, o, a, s, u, l = y !== m ? "nextSibling" : "previousSibling", + c = e.parentNode, + f = x && e.nodeName.toLowerCase(), + p = !n && !x, + d = !1; + if (c) { + if (y) { + while (l) { + a = e; + while (a = a[l]) + if (x ? a.nodeName.toLowerCase() === f : 1 === a.nodeType) return !1; + u = l = "only" === h && !u && "nextSibling" + } + return !0 + } + if (u = [m ? c.firstChild : c.lastChild], m && p) { + d = (s = (r = (i = (o = (a = c)[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] || [])[0] === k && r[1]) && r[2], a = s && c.childNodes[s]; + while (a = ++s && a && a[l] || (d = s = 0) || u.pop()) + if (1 === a.nodeType && ++d && a === e) { + i[h] = [k, s, d]; + break + } + } else if (p && (d = s = (r = (i = (o = (a = e)[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] || [])[0] === k && r[1]), !1 === d) + while (a = ++s && a && a[l] || (d = s = 0) || u.pop()) + if ((x ? a.nodeName.toLowerCase() === f : 1 === a.nodeType) && ++d && (p && ((i = (o = a[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] = [k, d]), a === e)) break; + return (d -= v) === g || d % g == 0 && 0 <= d / g + } + } + }, + PSEUDO: function(e, o) { + var t, a = b.pseudos[e] || b.setFilters[e.toLowerCase()] || se.error("unsupported pseudo: " + e); + return a[S] ? a(o) : 1 < a.length ? (t = [e, e, "", o], b.setFilters.hasOwnProperty(e.toLowerCase()) ? le(function(e, t) { + var n, r = a(e, o), + i = r.length; + while (i--) e[n = P(e, r[i])] = !(t[n] = r[i]) + }) : function(e) { + return a(e, 0, t) + }) : a + } + }, + pseudos: { + not: le(function(e) { + var r = [], + i = [], + s = f(e.replace($, "$1")); + return s[S] ? le(function(e, t, n, r) { + var i, o = s(e, null, r, []), + a = e.length; + while (a--)(i = o[a]) && (e[a] = !(t[a] = i)) + }) : function(e, t, n) { + return r[0] = e, s(r, null, n, i), r[0] = null, !i.pop() + } + }), + has: le(function(t) { + return function(e) { + return 0 < se(t, e).length + } + }), + contains: le(function(t) { + return t = t.replace(te, ne), + function(e) { + return -1 < (e.textContent || o(e)).indexOf(t) + } + }), + lang: le(function(n) { + return V.test(n || "") || se.error("unsupported lang: " + n), n = n.replace(te, ne).toLowerCase(), + function(e) { + var t; + do { + if (t = E ? e.lang : e.getAttribute("xml:lang") || e.getAttribute("lang")) return (t = t.toLowerCase()) === n || 0 === t.indexOf(n + "-") + } while ((e = e.parentNode) && 1 === e.nodeType); + return !1 + } + }), + target: function(e) { + var t = n.location && n.location.hash; + return t && t.slice(1) === e.id + }, + root: function(e) { + return e === a + }, + focus: function(e) { + return e === C.activeElement && (!C.hasFocus || C.hasFocus()) && !!(e.type || e.href || ~e.tabIndex) + }, + enabled: ge(!1), + disabled: ge(!0), + checked: function(e) { + var t = e.nodeName.toLowerCase(); + return "input" === t && !!e.checked || "option" === t && !!e.selected + }, + selected: function(e) { + return e.parentNode && e.parentNode.selectedIndex, !0 === e.selected + }, + empty: function(e) { + for (e = e.firstChild; e; e = e.nextSibling) + if (e.nodeType < 6) return !1; + return !0 + }, + parent: function(e) { + return !b.pseudos.empty(e) + }, + header: function(e) { + return J.test(e.nodeName) + }, + input: function(e) { + return Q.test(e.nodeName) + }, + button: function(e) { + var t = e.nodeName.toLowerCase(); + return "input" === t && "button" === e.type || "button" === t + }, + text: function(e) { + var t; + return "input" === e.nodeName.toLowerCase() && "text" === e.type && (null == (t = e.getAttribute("type")) || "text" === t.toLowerCase()) + }, + first: ve(function() { + return [0] + }), + last: ve(function(e, t) { + return [t - 1] + }), + eq: ve(function(e, t, n) { + return [n < 0 ? n + t : n] + }), + even: ve(function(e, t) { + for (var n = 0; n < t; n += 2) e.push(n); + return e + }), + odd: ve(function(e, t) { + for (var n = 1; n < t; n += 2) e.push(n); + return e + }), + lt: ve(function(e, t, n) { + for (var r = n < 0 ? n + t : t < n ? t : n; 0 <= --r;) e.push(r); + return e + }), + gt: ve(function(e, t, n) { + for (var r = n < 0 ? n + t : n; ++r < t;) e.push(r); + return e + }) + } + }).pseudos.nth = b.pseudos.eq, { + radio: !0, + checkbox: !0, + file: !0, + password: !0, + image: !0 + }) b.pseudos[e] = de(e); + for (e in { + submit: !0, + reset: !0 + }) b.pseudos[e] = he(e); + + function me() {} + + function xe(e) { + for (var t = 0, n = e.length, r = ""; t < n; t++) r += e[t].value; + return r + } + + function be(s, e, t) { + var u = e.dir, + l = e.next, + c = l || u, + f = t && "parentNode" === c, + p = r++; + return e.first ? function(e, t, n) { + while (e = e[u]) + if (1 === e.nodeType || f) return s(e, t, n); + return !1 + } : function(e, t, n) { + var r, i, o, a = [k, p]; + if (n) { + while (e = e[u]) + if ((1 === e.nodeType || f) && s(e, t, n)) return !0 + } else + while (e = e[u]) + if (1 === e.nodeType || f) + if (i = (o = e[S] || (e[S] = {}))[e.uniqueID] || (o[e.uniqueID] = {}), l && l === e.nodeName.toLowerCase()) e = e[u] || e; + else { + if ((r = i[c]) && r[0] === k && r[1] === p) return a[2] = r[2]; + if ((i[c] = a)[2] = s(e, t, n)) return !0 + } return !1 + } + } + + function we(i) { + return 1 < i.length ? function(e, t, n) { + var r = i.length; + while (r--) + if (!i[r](e, t, n)) return !1; + return !0 + } : i[0] + } + + function Te(e, t, n, r, i) { + for (var o, a = [], s = 0, u = e.length, l = null != t; s < u; s++)(o = e[s]) && (n && !n(o, r, i) || (a.push(o), l && t.push(s))); + return a + } + + function Ce(d, h, g, v, y, e) { + return v && !v[S] && (v = Ce(v)), y && !y[S] && (y = Ce(y, e)), le(function(e, t, n, r) { + var i, o, a, s = [], + u = [], + l = t.length, + c = e || function(e, t, n) { + for (var r = 0, i = t.length; r < i; r++) se(e, t[r], n); + return n + }(h || "*", n.nodeType ? [n] : n, []), + f = !d || !e && h ? c : Te(c, s, d, n, r), + p = g ? y || (e ? d : l || v) ? [] : t : f; + if (g && g(f, p, n, r), v) { + i = Te(p, u), v(i, [], n, r), o = i.length; + while (o--)(a = i[o]) && (p[u[o]] = !(f[u[o]] = a)) + } + if (e) { + if (y || d) { + if (y) { + i = [], o = p.length; + while (o--)(a = p[o]) && i.push(f[o] = a); + y(null, p = [], i, r) + } + = p.length; + while (o--)(a = p[o]) && -1 < (i = y ? P(e, a) : s[o]) && (e[i] = !(t[i] = a)) + } + } else p = Te(p === t ? p.splice(l, p.length) : p), y ? y(null, t, p, r) : H.apply(t, p) + }) + } + + function Ee(e) { + for (var i, t, n, r = e.length, o = b.relative[e[0].type], a = o || b.relative[" "], s = o ? 1 : 0, u = be(function(e) { + return e === i + }, a, !0), l = be(function(e) { + return -1 < P(i, e) + }, a, !0), c = [function(e, t, n) { + var r = !o && (n || t !== w) || ((i = t).nodeType ? u(e, t, n) : l(e, t, n)); + return i = null, r + }]; s < r; s++) + if (t = b.relative[e[s].type]) c = [be(we(c), t)]; + else { + if ((t = b.filter[e[s].type].apply(null, e[s].matches))[S]) { + for (n = ++s; n < r; n++) + if (b.relative[e[n].type]) break; + return Ce(1 < s && we(c), 1 < s && xe(e.slice(0, s - 1).concat({ + value: " " === e[s - 2].type ? "*" : "" + })).replace($, "$1"), t, s < n && Ee(e.slice(s, n)), n < r && Ee(e = e.slice(n)), n < r && xe)) + } + c.push(t) + } return we(c) + } + return me.prototype = b.filters = b.pseudos, b.setFilters = new me, h = se.tokenize = function(e, t) { + var n, r, i, o, a, s, u, l = x[e + " "]; + if (l) return t ? 0 : l.slice(0); + a = e, s = [], u = b.preFilter; + while (a) { + for (o in n && !(r = _.exec(a)) || (r && (a = a.slice(r[0].length) || a), s.push(i = [])), n = !1, (r = z.exec(a)) && (n = r.shift(), i.push({ + value: n, + type: r[0].replace($, " ") + }), a = a.slice(n.length)), b.filter) !(r = G[o].exec(a)) || u[o] && !(r = u[o](r)) || (n = r.shift(), i.push({ + value: n, + type: o, + matches: r + }), a = a.slice(n.length)); + if (!n) break + } + return t ? a.length : a ? se.error(e) : x(e, s).slice(0) + }, f = se.compile = function(e, t) { + var n, v, y, m, x, r, i = [], + o = [], + a = A[e + " "]; + if (!a) { + t || (t = h(e)), n = t.length; + while (n--)(a = Ee(t[n]))[S] ? i.push(a) : o.push(a); + (a = A(e, (v = o, m = 0 < (y = i).length, x = 0 < v.ngth, r = function(e, t, n, r, i) { + var o, a, s, u = 0, + l = "0", + c = e && [], + f = [], + p = w, + d = e || x && b.find.TAG("*", i), + h = k += null == p ? 1 : Math.random() || .1, + g = d.length; + for (i && (w = t == C || t || i); l !== g && null != (o = d[l]); l++) { + if (x && o) { + a = 0, t || o.ownerDocument == C || (T(o), n = !E); + while (s = v[a++]) + if (s(o, t || C, n)) { + r.push(o); + break + } i && (k = h) + } m && ((o = !s && o) && u--, e && c.push(o)) + } + if (u += l, m && l !== u) { + a = 0; + while (s = y[a++]) s(c, f, t, n); + if (e) { + if (0 < u) + while (l--) c[l] || f[l] || (f[l] = q.call(r)); + f = Te(f) + } + H.apply(r, f), i && !e && 0 < f.length && 1 < u + y.length && se.uniqueSort(r) + } + return i && (k = h, w = p), c + }, m ? le(r) : r))).selector = e + } + return a + }, g = se.select = function(e, t, n, r) { + var i, o, a, s, u, l = "functn" == typeof e && e, + c = !r && h(e = l.selector || e); + if (n = n || [], 1 === c.length) { + if (2 < (o = c[0] = c[0].slice(0)).length && "ID" === (a = o[0]).type && 9 === t.nodeType && E && b.relative[o[1].type]) { + if (!(t = (b.find.ID(a.matches[0].replace(te, ne), t) || [])[0])) return n; + l && (t = t.parentNode), e = e.slice(o.shift().value.length) + } + i = G.needsContext.test(e) ? 0 : o.length; + while (i--) { + if (a = o[i], b.relative[s = a.type]) break; + if ((u = b.find) && (r = u(a.matches[0].replace(te, ne), ee.test(o[0].type) && ye(t.parentNode) || t))) { + if (o.splice(i, 1), !(e = r.length && xe(o))) return H.apply(n, r), n; + break + } + } + } + return (l || f(e, c))(r, t, !E, n, !t || ee.test(e) && ye(t.parentNode) || t), n + }, d.sortStable = S.split("").sort(D).join("") === S, d.detectDuplicates = !!l, T(), d.sortDetached = ce(function(e) { + return 1 & e.compareDocumentPosition(C.createElement("fieldset")) + }), ce(function(e) { + return e.innerTML = "", "#" === e.firstChild.getAttribute("href") + }) || fe("type|href|height|width", function(e, t, n) { + if (!n) return e.getAttribute(t, "type" === t.toLowerCase() ? 1 : 2) + }), d.attributes && ce(function(e) { + return e.innerHTML = "", e.firstChild.setAttribute("value", ""), "" === e.firstChild.getAttribute("value") + }) || fe("value", function(e, t, n) { + if (!n && "input" === e.nodeName.toLowerCase()) return e.defaultValue + }), ce(function(e) { + return null == e.geribute("disabled") + }) || fe(R, function(e, t, n) { + var r; + if (!n) return !0 === e[t] ? t.toLowerCase() : (r = e.getAttributeNode(t)) && r.specified ? r.value : null + }), se + }(C); + S.find = d, S.expr = d.selectors, S.expr[":"] = S.expr.pseudos, S.uniqueSort = S.unique = d.uniqueSort, S.text = d.getText, S.isXMLDoc = d.isXML, S.contains = d.contains, S.escapeSelector = d.escape; + var h = function(e, t, n) { + var r = [], + i = void 0 !== n; + while ((e = e[t]) && 9 !== e.nodeType) + if (1 === deType) { + if (i && S(e).is(n)) break; + r.push(e) + } return r + }, + T = function(e, t) { + for (var n = []; e; e = e.nextSibling) 1 === e.nodeType && e !== t && n.push(e); + return n + }, + k = S.expr.match.needsContext; + + function A(e, t) { + return e.nodeName && e.nodeName.toLowerCase() === t.toLowerCase() + } + var N = /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i; + + function D(e, n, r) { + return m(n) ? S.grep(e, function(e, t) { + return !!n.call(e, t, e) !== r + }) : nType ? S.grep(e, function(e) { + return e === n !== r + }) : "string" != typeof n ? S.grep(e, function(e) { + return -1 < i.call(n, e) !== r + }) : S.filter(n, e, r) + } + S.filter = function(e, t, n) { + var r = t[0]; + return n && (e = ":not(" + e + ")"), 1 === t.length && 1 === r.nodeType ? S.find.matchesSelector(r, e) ? [r] : [] : S.find.matches(e, S.grep(t, function(e) { + return 1 === e.nodeType + })) + }, S.fn.extend({ + find: function(e) { + var t, n, r = this.length, + i = this; + if ("string" eof e) return this.pushStack(S(e).filter(function() { + for (t = 0; t < r; t++) + if (S.contains(i[t], this)) return !0 + })); + for (n = this.pushStack([]), t = 0; t < r; t++) S.find(e, i[t], n); + return 1 < r ? S.uniqueSort(n) : n + }, + filter: function(e) { + return this.pushStack(D(this, e || [], !1)) + }, + not: function(e) { + return this.pushStack(D(this, e || [], !0)) + }, + is: function(e) { + return !!D(this, "string" == typeof e && k.test(e) ? S(e) : e || [], !1).length + } + }); + var /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/; + (S.fn.init = function(e, t, n) { + var r, i; + if (!e) return this; + if (n = n || j, "string" == typeof e) { + if (!(r = "<" === e[0] && ">" === e[e.length - 1] && 3 <= e.length ? [null, e, null] : q.exec(e)) || !r[1] && t) return !t || t.jquery ? (t || n).find(e) : this.constructor(t).find(e); + if (r[1]) { + if (t = t instanceof S ? t[0] : t, S.merge(this, S.parseHTML(r[1], t && t.nodeType ? t.ownerDocument || t : E, !0)), N.test(r[1]) && S.isPlainObject(t)) + r (r in t) m(this[r]) ? this[r](t[r]) : this.attr(r, t[r]); + return this + } + return (i = E.getElementById(r[2])) && (this[0] = i, this.length = 1), this + } + return e.nodeType ? (this[0] = e, this.length = 1, this) : m(e) ? void 0 !== n.ready ? n.ready(e) : e(S) : S.makeArray(e, this) + }).prototype = S.fn, j = S(E); + var L = /^(?:parents|prev(?:Until|All))/, + H = { + children: !0, + contents: !0, + next: !0, + prev: !0 + }; + + function O(e, t) { + while ((e = e[t]) && 1 !== e.nodeType); + return S.fn.extend({ + has: function(e) { + var t = S(e, this), + n = t.length; + return this.filter(function() { + for (var e = 0; e < n; e++) + if (S.contains(this, t[e])) return !0 + }) + }, + closest: function(e, t) { + var n, r = 0, + i = this.length, + o = [], + a = "string" != typeof e && S(e); + if (!k.test(e)) + for (; r < i; r++) + for (n = this[r]; n && n !== t; n = n.parentNode) + if (n.nodeType < 11 && (a ? -1 < a.index(n) : 1 === n.nodeType && S.find.matchesSelector(n, e)) + o.push(n); + break + } return this.pushStack(1 < o.length ? S.uniqueSort(o) : o) + }, + index: function(e) { + return e ? "string" == typeof e ? i.call(S(e), this[0]) : i.call(this, e.jquery ? e[0] : e) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1 + }, + add: function(e, t) { + return this.pushStack(S.uniqueSort(S.merge(this.get(), S(e, t)))) + }, + addBack: function(e) { + return this.add(null == e ? this.prevObject : this.prevObject.filter(e)) + } + }), S.each({ +ent: function(e) { + var t = e.parentNode; + return t && 11 !== t.nodeType ? t : null + }, + parents: function(e) { + return h(e, "parentNode") + }, + parentsUntil: function(e, t, n) { + return h(e, "parentNode", n) + }, + next: function(e) { + return O(e, "nextSibling") + }, + prev: function(e) { + return O(e, "previousSibling") + }, + nextAll: function(e) { + return h(e, "nextSibling") + }, + prevAll: function(e) { + return h(e, "previousSibling") + }, + nextUntil: function(e, t, n) { + return h(nextSibling", n) + }, + prevUntil: function(e, t, n) { + return h(e, "previousSibling", n) + }, + siblings: function(e) { + return T((e.parentNode || {}).firstChild, e) + }, + children: function(e) { + return T(e.firstChild) + }, + contents: function(e) { + return null != e.contentDocument && r(e.contentDocument) ? e.contentDocument : (A(e, "template") && (e = e.content || e), S.merge([], e.childNodes)) + } + }, function(r, i) { + S.fn[r] = function(e, t) { + var n = S.map(this, i, e); + return "Until"== r.slice(-5) && (t = e), t && "string" == typeof t && (n = S.filter(t, n)), 1 < this.length && (H[r] || S.uniqueSort(n), L.test(r) && n.reverse()), this.pushStack(n) + } + }); + var P = /[^\x20\t\r\n\f]+/g; + + function R(e) { + return e + } + + function M(e) { + throw e + } + + function I(e, t, n, r) { + var i; + try { + e && m(i = e.promise) ? i.call(e).done(t).fail(n) : e && m(i = e.then) ? i.call(e, t, n) : t.apply(void 0, [e].slice(r)) + } catch (e) { + n.apply(void 0, [e]) + } + } + S.Callbacks = function(r) r e, n; + r = "string" == typeof r ? (e = r, n = {}, S.each(e.match(P) || [], function(e, t) { + n[t] = !0 + }), n) : S.extend({}, r); + var i, t, o, a, s = [], + u = [], + l = -1, + c = function() { + for (a = a || r.once, o = i = !0; u.length; l = -1) { + t = u.shift(); + while (++l < s.length) !1 === s[l].apply(t[0], t[1]) && r.stopOnFalse && (l = s.length, t = !1) + } + r.memory || (t = !1), i = !1, a && (s = t ? [] : "") + }, + f = { + add: function() { + return s && (t && !i && s.length - 1, u.push(t)), function n(e) { + S.each(e, function(e, t) { + m(t) ? r.unique && f.has(t) || s.push(t) : t && t.length && "string" !== w(t) && n(t) + }) + }(arguments), t && !i && c()), this + }, + remove: function() { + return S.each(arguments, function(e, t) { + var n; + while (-1 < (n = S.inArray(t, s, n))) s.splice(n, 1), n <= l && l-- + }), this + }, + has: function(e) { + return e ? -1 < S.inArray(e, s) : 0 < s.length + }, + empty: function() { + return s && (s = []), this + }, + disable: function() { + return a = u = [], s = t = "", this + }, + disabled: function() { + return !s + }, + lock: function() { + return a = u = [], t || i || (s = t = ""), this + }, + locked: function() { + return !!a + }, + fireWith: function(e, t) { + return a || (t = [e, (t = t || []).slice ? t.slice() : t], u.push(t), i || c()), this + }, + fire: function() { + return f.fireWith(this, arguments), this + }, + fired: functin() { + return !!o + } + }; + return f + }, S.extend({ + Deferred: function(e) { + var o = [ + ["notify", "progress", S.Callbacks("memory"), S.Callbacks("memory"), 2], + ["resolve", "done", S.Callbacks("once memory"), S.Callbacks("once memory"), 0, "resolved"], + ["reject", "fail", S.Callbacks("once memory"), S.Callbacks("once memory"), 1, "rejected"] + ], + i = "pending", + a = { + state: function() { + return i + }, + always: function() { + return s.done(arguments).faguments), this + }, + "catch": function(e) { + return a.then(null, e) + }, + pipe: function() { + var i = arguments; + return S.Deferred(function(r) { + S.each(o, function(e, t) { + var n = m(i[t[4]]) && i[t[4]]; + s[t[1]](function() { + var e = n && n.apply(this, arguments); + e && m(e.promise) ? e.promise().progress(r.notify).done(r.resolve).fail(r.reject) : r[t[0] + "With"](this, n ? [e] : arguments) + }) + }), i = null + }).promise() + }, + then: function(t, n, r) { + var u = 0; + + function l(i, o, a, s) { + return function() { + var n = this, + r = arguments, + e = function() { + var e, t; + if (!(i < u)) { + if ((e = a.apply(n, r)) === o.promise()) throw new TypeError("Thenable self-resolution"); + t = e && ("object" == typeof e || "function" == typeof e) && e.then, m(t) ? s ? t.call(e, l(u, o, R, s), l(u, o, M, s)) : (u++, t.call(e, l(u, o, R, s), l(u, o, M, s), l(u, o, R, o.notifyWith))) : (a !== R && (n = void 0, r = [e]), (s || o.resolveWith)(n, r)) + } + }, + t = s ? e : function() { + try { + e() + } catch (e) { + S.Deferred.exceptionHook && S.Deferred.exceptionHook(e, t.stackTrace), u <= i + 1 && (a !== M && (n = void 0, r = [e]), o.rejectWith(n, r)) + } + }; + i ? t() : (S.Deferred.getStackHook && (t.stackTrace = S.Deferred.getStackHook()), C.setTimeout(t)) + } + } + retureferred(function(e) { + o[0][3].add(l(0, e, m(r) ? r : R, e.notifyWith)), o[1][3].add(l(0, e, m(t) ? t : R)), o[2][3].add(l(0, e, m(n) ? n : M)) + }).promise() + }, + promise: function(e) { + return null != e ? S.extend(e, a) : a + } + }, + s = {}; + return S.each(o, function(e, t) { + var n = t[2], + r = t[5]; + a[t[1]] = n.add, r && n.add(function() { + i = r + }, o[3 - e][2].disable, o[3 - e][3].disable, o[0][2].lock, o[0][3].lock), n.add(t[3].fire), s[t[0]] = funct) { + return s[t[0] + "With"](this === s ? void 0 : this, arguments), this + }, s[t[0] + "With"] = n.fireWith + }), a.promise(s), e && e.call(s, s), s + }, + when: function(e) { + var n = arguments.length, + t = n, + r = Array(t), + i = s.call(arguments), + o = S.Deferred(), + a = function(t) { + return function(e) { + r[t] = this, i[t] = 1 < arguments.length ? s.call(arguments) : e, --n || o.resolveWith(r, i) + } + }; + if (n <= 1 && (I(e, o.done(a(t)).resolve, o.reject, !n), ending" === o.state() || m(i[t] && i[t].then))) return o.then(); + while (t--) I(i[t], a(t), o.reject); + return o.promise() + } + }); + var W = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + S.Deferred.exceptionHook = function(e, t) { + C.console && C.console.warn && e && W.test(e.name) && C.console.warn("jQuery.Deferred exception: " + e.message, e.stack, t) + }, S.readyException = function(e) { + C.setTimeout(function() { + throw e + }) + }; + var F = S.Deferred(); + + function B() { + E.removeEveistener("DOMContentLoaded", B), C.removeEventListener("load", B), S.ready() + } + S.fn.ready = function(e) { + return F.then(e)["catch"](function(e) { + S.readyException(e) + }), this + }, S.extend({ + isReady: !1, + readyWait: 1, + ready: function(e) { + (!0 === e ? --S.readyWait : S.isReady) || (S.isReady = !0) !== e && 0 < --S.readyWait || F.resolveWith(E, [S]) + } + }), S.ready.then = F.then, "complete" === E.readyState || "loading" !== E.readyState && !E.documentElement.doScroll ? C.setTimeout(S.ready) : (E.addEventListener("DOMContentLoaded", B), C.addEventListener("load", B)); + var $ = function(e, t, n, r, i, o, a) { + var s = 0, + u = e.length, + l = null == n; + if ("object" === w(n)) + for (s in i = !0, n) $(e, t, s, n[s], !0, o, a); + else if (void 0 !== r && (i = !0, m(r) || (a = !0), l && (a ? (t.call(e, r), t = null) : (l = t, t = function(e, t, n) { + return l.call(S(e), n) + })), t)) + for (; s < u; s++) t(e[s], n, a ? r : r.call(e[s], s, t(e[s], n))); + return i ? e : l ? t.cale) : u ? t(e[0], n) : o + }, + _ = /^-ms-/, + z = /-([a-z])/g; + + function U(e, t) { + return t.toUpperCase() + } + + function X(e) { + return e.replace(_, "ms-").replace(z, U) + } + var V = function(e) { + return 1 === e.nodeType || 9 === e.nodeType || !+e.nodeType + }; + + function G() { + this.expando = S.expando + G.uid++ + } + G.uid = 1, G.prototype = { + cache: function(e) { + var t = e[this.expando]; + return t || (t = {}, V(e) && (e.nodeType ? e[this.expando] = t : Object.defineProperty(e, this.expando, { + e: t, + configurable: !0 + }))), t + }, + set: function(e, t, n) { + var r, i = this.cache(e); + if ("string" == typeof t) i[X(t)] = n; + else + for (r in t) i[X(r)] = t[r]; + return i + }, + get: function(e, t) { + return void 0 === t ? this.cache(e) : e[this.expando] && e[this.expando][X(t)] + }, + access: function(e, t, n) { + return void 0 === t || t && "string" == typeof t && void 0 === n ? this.get(e, t) : (this.set(e, t, n), void 0 !== n ? n : t) + }, + remove: function(e, t) { + var n, re[this.expando]; + if (void 0 !== r) { + if (void 0 !== t) { + n = (t = Array.isArray(t) ? t.map(X) : (t = X(t)) in r ? [t] : t.match(P) || []).length; + while (n--) delete r[t[n]] + }(void 0 === t || S.isEmptyObject(r)) && (e.nodeType ? e[this.expando] = void 0 : delete e[this.expando]) + } + }, + hasData: function(e) { + var t = e[this.expando]; + return void 0 !== t && !S.isEmptyObject(t) + } + }; + var Y = new G, + Q = new G, + J = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + K = /[A-Z]/g; + + function t, n) { + var r, i; + if (void 0 === n && 1 === e.nodeType) + if (r = "data-" + t.replace(K, "-$&").toLowerCase(), "string" == typeof(n = e.getAttribute(r))) { + try { + n = "true" === (i = n) || "false" !== i && ("null" === i ? null : i === +i + "" ? +i : J.test(i) ? JSON.parse(i) : i) + } catch (e) {} + Q.set(e, t, n) + } else n = void 0; + return n + } + S.extend({ + hasData: function(e) { + return Q.hasData(e) || Y.hasData(e) + }, + data: function(e, t, n) { + return Q.access(e, t, n) + }, + removeData: function(e, t) { + Q.remove(e, t) + }, + _data: function(e, t, n) { + return Y.access(e, t, n) + }, + _removeData: function(e, t) { + Y.remove(e, t) + } + }), S.fn.extend({ + data: function(n, e) { + var t, r, i, o = this[0], + a = o && o.attributes; + if (void 0 === n) { + if (this.length && (i = Q.get(o), 1 === o.nodeType && !Y.get(o, "hasDataAttrs"))) { + t = a.length; + while (t--) a[t] && 0 === (r = a[t].name).indexOf("data-") && (r = X(r.slice(5)), Z(o, r, i[r])); + Y.set(o, "hasDataAttrs", !0) + } + return i + } + return "object" == typeof n ? this.each(function() { + Q.set(this, n) + }) : $(this, function(e) { + var t; + if (o && void 0 === e) return void 0 !== (t = Q.get(o, n)) ? t : void 0 !== (t = Z(o, n)) ? t : void 0; + this.each(function() { + Q.set(this, n, e) + }) + }, null, e, 1 < arguments.length, null, !0) + }, + removeData: function(e) { + return this.each(function() { + Q.remove(this, e) + }) + } + }), S.extend({ + queue: function(e, t, + var r; + if (e) return t = (t || "fx") + "queue", r = Y.get(e, t), n && (!r || Array.isArray(n) ? r = Y.access(e, t, S.makeArray(n)) : r.push(n)), r || [] + }, + dequeue: function(e, t) { + t = t || "fx"; + var n = S.queue(e, t), + r = n.length, + i = n.shift(), + o = S._queueHooks(e, t); + "inprogress" === i && (i = n.shift(), r--), i && ("fx" === t && n.unshift("inprogress"), delete o.stop, i.call(e, function() { + S.dequeue(e, t) + }, o)), !r && o && o.empty.fire() + }, + _queueHooks: fu(e, t) { + var n = t + "queueHooks"; + return Y.get(e, n) || Y.access(e, n, { + empty: S.Callbacks("once memory").add(function() { + Y.remove(e, [t + "queue", n]) + }) + }) + } + }), S.fn.extend({ + queue: function(t, n) { + var e = 2; + return "string" != typeof t && (n = t, t = "fx", e--), arguments.length < e ? S.queue(this[0], t) : void 0 === n ? this : this.each(function() { + var e = S.queue(this, t, n); + S._queueHooks(this, t), "fx" === t && "inprogress" !== e[0] && S.dequeue(this, t) }) + }, + dequeue: function(e) { + return this.each(function() { + S.dequeue(this, e) + }) + }, + clearQueue: function(e) { + return this.queue(e || "fx", []) + }, + promise: function(e, t) { + var n, r = 1, + i = S.Deferred(), + o = this, + a = this.length, + s = function() { + --r || i.resolveWith(o, [o]) + }; + "string" != typeof e && (t = e, e = void 0), e = e || "fx"; + while (a--)(n = Y.get(o[a], e + "queueHooks")) && n.empty && (r++, n.empty.add(s)); + return s(), i.promise(t + }); + var ee = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + te = new RegExp("^(?:([+-])=|)(" + ee + ")([a-z%]*)$", "i"), + ne = ["Top", "Right", "Bottom", "Left"], + re = E.documentElement, + ie = function(e) { + return S.contains(e.ownerDocument, e) + }, + oe = { + composed: !0 + }; + re.getRootNode && (ie = function(e) { + return S.contains(e.ownerDocument, e) || e.getRootNode(oe) === e.ownerDocument + }); + var ae = function(e, t) { + return "none" === (e = t || e).style.display || "" === e.style.disp&& ie(e) && "none" === S.css(e, "display") + }; + + function se(e, t, n, r) { + var i, o, a = 20, + s = r ? function() { + return r.cur() + } : function() { + return S.css(e, t, "") + }, + u = s(), + l = n && n[3] || (S.cssNumber[t] ? "" : "px"), + c = e.nodeType && (S.cssNumber[t] || "px" !== l && +u) && te.exec(S.css(e, t)); + if (c && c[3] !== l) { + u /= 2, l = l || c[3], c = +u || 1; + while (a--) S.style(e, t, c + l), (1 - o) * (1 - (o = s() / u || .5)) <= 0 && (a = 0), c /= o; + c *= 2, S.se, t, c + l), n = n || [] + } + return n && (c = +c || +u || 0, i = n[1] ? c + (n[1] + 1) * n[2] : +n[2], r && (r.unit = l, r.start = c, r.end = i)), i + } + var ue = {}; + + function le(e, t) { + for (var n, r, i, o, a, s, u, l = [], c = 0, f = e.length; c < f; c++)(r = e[c]).style && (n = r.style.display, t ? ("none" === n && (l[c] = Y.get(r, "display") || null, l[c] || (r.style.display = "")), "" === r.style.display && ae(r) && (l[c] = (u = a = o = void 0, a = (i = r).ownerDocument, s = i.nodeName, (u = ue[s]) || (o = a.body.appendChild(a.createElement(s)), u = S.css(o, "display"), o.parentNode.removeChild(o), "none" === u && (u = "block"), ue[s] = u)))) : "none" !== n && (l[c] = "none", Y.set(r, "display", n))); + for (c = 0; c < f; c++) null != l[c] && (e[c].style.display = l[c]); + return e + } + S.fn.extend({ + show: function() { + return le(this, !0) + }, + hide: function() { + return le(this) + }, + toggle: function(e) { + return "boolean" == typeof e ? e ? this.show() : this.hide() : this.each(function{ + ae(this) ? S(this).show() : S(this).hide() + }) + } + }); + var ce, fe, pe = /^(?:checkbox|radio)$/i, + de = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i, + he = /^$|^module$|\/(?:java|ecma)script/i; + ce = E.createDocumentFragment().appendChild(E.createElement("div")), (fe = E.createElement("input")).setAttribute("type", "radio"), fe.setAttribute("checked", "checked"), fe.setAttribute("name", "t"), ce.appendChild(fe), y.checkClone = ce.cloneNode(!0).cloneNode(!0).lastChild.checked, ce.innerHTML = "