From fe313e7d23e9ffa2a2105c06d92b6e743b616ad1 Mon Sep 17 00:00:00 2001 From: action Date: Wed, 9 Sep 2026 16:33:06 +0800 Subject: [PATCH] update 2026-09-09 16:33:06 --- clashoo/Makefile | 6 +- .../luasrc/controller/passwall.lua | 16 +- .../model/cbi/passwall/client/global.lua | 22 ++- .../passwall/client/include/shunt_options.lua | 69 +++++-- .../model/cbi/passwall/client/node_config.lua | 29 --- .../cbi/passwall/client/type/0_socks.lua | 35 ++++ .../cbi/passwall/client/type/1_sing-box.lua | 45 ++--- .../model/cbi/passwall/client/type/2_xray.lua | 57 +++--- .../cbi/passwall/client/type/3_ss-rust.lua | 6 +- .../model/cbi/passwall/client/type/4_ssr.lua | 6 +- .../cbi/passwall/client/type/5_hysteria2.lua | 48 +++-- .../cbi/passwall/client/type/6_naive.lua | 6 +- .../cbi/passwall/server/type/0_socks.lua | 6 +- .../cbi/passwall/server/type/1_sing-box.lua | 10 +- .../model/cbi/passwall/server/type/2_xray.lua | 22 ++- .../cbi/passwall/server/type/3_ss-rust.lua | 10 +- .../model/cbi/passwall/server/type/4_ssr.lua | 10 +- .../cbi/passwall/server/type/5_hysteria2.lua | 38 ++-- luci-app-passwall/luasrc/passwall/api.lua | 174 ++++++++---------- .../luasrc/passwall/util_xray.lua | 28 ++- .../luasrc/view/passwall/global/footer.htm | 48 ----- .../view/passwall/include/node_change.htm | 73 ++++++++ .../view/passwall/include/shunt_options.htm | 122 ++++++++---- .../view/passwall/node_config/footer.htm | 37 ++-- .../root/usr/share/passwall/app.sh | 6 +- luci-app-passwall2/Makefile | 2 +- .../luasrc/passwall2/util_xray.lua | 28 ++- 27 files changed, 528 insertions(+), 431 deletions(-) create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/type/0_socks.lua create mode 100644 luci-app-passwall/luasrc/view/passwall/include/node_change.htm diff --git a/clashoo/Makefile b/clashoo/Makefile index ddb5515f..e6b49d1d 100644 --- a/clashoo/Makefile +++ b/clashoo/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=clashoo -PKG_SHORT_SHA:=a91201f +PKG_SHORT_SHA:=d5f57a5 PKG_COMMIT_DATE:=2026.09.08 PKG_VERSION:=$(PKG_COMMIT_DATE)~$(PKG_SHORT_SHA) @@ -11,8 +11,8 @@ PKG_SOURCE:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-alpha-$(PKG_SHORT_SHA) PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-clashoo/releases/download/mihomo-src -PKG_SOURCE_VERSION:=a91201f1fc1eb9576f284a4655d819326662fb61 -PKG_HASH:=ca9c09031531332890ceadab7748ad33a24e391eac1b8a6de929c38151eeca7e +PKG_SOURCE_VERSION:=d5f57a5e290eafd77a2b28d8db36e3bd70071398 +PKG_HASH:=1c657c4abdf3f87b51a1f1af1cc9c97b71c1d8a498fd3d9ef31cb9db63b12214 PKG_BUILD_VERSION:=alpha-$(PKG_SHORT_SHA) PKG_LICENSE:=GPL3.0+ diff --git a/luci-app-passwall/luasrc/controller/passwall.lua b/luci-app-passwall/luasrc/controller/passwall.lua index e9fa889f..71ec33ca 100644 --- a/luci-app-passwall/luasrc/controller/passwall.lua +++ b/luci-app-passwall/luasrc/controller/passwall.lua @@ -479,7 +479,21 @@ function add_node() uci_set(uid, "group", group) end - uci_set(uid, "type", "Socks") + if api.is_finded("ipt2socks") then + uci_set(uid, "type", "Socks") + elseif api.finded_com("sing-box") then + uci_set(uid, "type", "sing-box") + elseif api.finded_com("xray") then + uci_set(uid, "type", "Xray") + elseif api.is_finded("sslocal") then + uci_set(uid, "type", "SS-Rust") + elseif api.is_finded("ssr-local") then + uci_set(uid, "type", "SSR") + elseif api.finded_com("hysteria") then + uci_set(uid, "type", "Hysteria2") + elseif api.is_finded("naive") then + uci_set(uid, "type", "Naiveproxy") + end if redirect == "1" then uci_save() diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index 12752c54..032a989e 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -112,6 +112,10 @@ o:value("", translate("Close")) o.group = {""} current_node_id = m:get(s.section, "node") +local node_value = s.fields["node"]:formvalue(s.section) +if node_value then + current_node_id = node_value +end current_node = current_node_id and m:get(current_node_id) or {} -- Shunt Start @@ -120,17 +124,10 @@ if (has_singbox or has_xray) and #nodes_table > 0 then if current_node.protocol == "_shunt" then local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua") setfenv(shunt_lua, getfenv(1))(m, s, { - s_cfgid = s.section, - node_id = current_node_id, node = current_node, - socks_list = socks_list, - urltest_list = urltest_list, - balancing_list = balancing_list, - iface_list = iface_list, - normal_list = normal_list, verify_option = s.fields["node"], tab = "Shunt", - tab_desc = translate("Shunt Rule") + tab_desc = translate("Shunt Rule"), }) end else @@ -165,6 +162,11 @@ o = s:taboption("Main", Flag, "node_socks_bind_local", translate("Node") .. " So o.default = "1" o:depends("_node", "1") +o = s:taboption("Main", DummyValue, "node_save_before", "") +o.template = m:template_path("/cbi/hidevalue") +o.value = current_node[".name"] +o.cbid = function(self, section) return "node_save_before" end + o = s:taboption("Main", DummyValue, "_node", "") o.template = m:template_path("/cbi/hidevalue") o.value = "1" @@ -647,6 +649,8 @@ s:tab("maintain", translate("Maintain")) o = s:taboption("maintain", DummyValue, "") o.template = m:template_path("/global/backup") +m:appendTemplate("/include/node_change", { verify_option = s.fields["node"], shunt_list = api.jsonc.stringify(shunt_list) }) + -- [[ Socks Server ]]-- o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch")) o.rmempty = false @@ -784,7 +788,7 @@ for k, v in pairs(nodes_table) do end end -m:appendTemplate("/global/footer", {shunt_list = api.jsonc.stringify(shunt_list)}) +m:appendTemplate("/global/footer") m:appendTemplate("/cbi/sortable", {sectiontype = s2.sectiontype}) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/include/shunt_options.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/include/shunt_options.lua index 0528992a..22d5bac6 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/include/shunt_options.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/include/shunt_options.lua @@ -1,13 +1,28 @@ local m, s, data = ... -if not data.node_id or not data.node then +if not data.node or not data.node[".name"] then return end local api = m.api -local s_cfgid = data.s_cfgid -local current_node_id = data.node_id +local section_id = s.section +local current_node = data.node +local current_node_id = current_node[".name"] +local verify_option = data.verify_option local node_list = data.node_list or api.get_node_list() +local shunt_section_type = "shunt_option_list" + +if data.tab then + if #s.tab_names > 0 then + table.insert(s.tab_names, 2, data.tab) + s.tabs[data.tab] = { + title = data.tab_desc, + childs = { } + } + else + s:tab(data.tab, data.tab_desc) + end +end local groups = {} m:foreach("shunt_rules", function(s) @@ -16,6 +31,9 @@ m:foreach("shunt_rules", function(s) end end) +local node_save_before = luci.http.formvalue("node_save_before") +local load_shunt = luci.http.formvalue("load_shunt") + local function get_cfgvalue() return function(self, section) return m:get(current_node_id, self.option) @@ -23,8 +41,10 @@ local function get_cfgvalue() end local function get_write() return function(self, section, value) - if data.verify_option then - if data.verify_option:formvalue(section) == current_node_id then + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end + if verify_option then + if verify_option:formvalue(section) == current_node_id then m:set(current_node_id, self.option, value) end else @@ -34,8 +54,10 @@ local function get_write() end local function get_remove() return function(self, section) - if data.verify_option then - if data.verify_option:formvalue(section) == current_node_id then + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end + if verify_option then + if verify_option:formvalue(section) == current_node_id then m:del(current_node_id, self.option) end else @@ -44,10 +66,6 @@ local function get_remove() end end -if data.tab then - s:tab(data.tab, data.tab_desc) -end - local function add_option(class, option_name, option_title, option_desc) local a if data.tab then @@ -63,8 +81,8 @@ local function add_option(class, option_name, option_title, option_desc) a.write = get_write() a.remove = get_remove() end - if data.verify_option then - a:depends(data.verify_option.option, current_node_id) + if verify_option then + a:depends(verify_option.option, current_node_id) end return a end @@ -81,7 +99,7 @@ local function add_depends(o, deps) end end -if data.node.type == "Xray" then +if current_node.type == "Xray" then o = add_option(ListValue, "domainStrategy", translate("Domain Strategy")) o:value("AsIs") o:value("IPIfNonMatch") @@ -134,7 +152,7 @@ table.insert(shunt_rules, { s2 = m:section(Table, shunt_rules, " ") s2.config = m.config -s2.sectiontype = "shunt_option_list" +s2.sectiontype = shunt_section_type o = s2:option(DummyValue, "remarks", translate("Rule")) o.rawhtml = true @@ -157,9 +175,13 @@ _node.cfgvalue = function(self, section) return m:get(current_node_id, shunt_rules[section]["_node_option"]) or shunt_rules[section]["_node_default"] end _node.write = function(self, section, value) + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end return m:set(current_node_id, shunt_rules[section]["_node_option"], value) end _node.remove = function(self, section) + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end return m:del(current_node_id, shunt_rules[section]["_node_option"]) end @@ -170,9 +192,13 @@ o.cfgvalue = function(self, section) return m:get(current_node_id, shunt_rules[section]["_fakedns_option"]) end o.write = function(self, section, value) + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end return m:set(current_node_id, shunt_rules[section]["_fakedns_option"], value) end o.remove = function(self, section) + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end return m:del(current_node_id, shunt_rules[section]["_fakedns_option"]) end @@ -186,9 +212,13 @@ proxy_tag_node.cfgvalue = function(self, section) return m:get(current_node_id, shunt_rules[section]["_proxy_tag_option"]) end proxy_tag_node.write = function(self, section, value) + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end return m:set(current_node_id, shunt_rules[section]["_proxy_tag_option"], value) end proxy_tag_node.remove = function(self, section) + if node_save_before and node_save_before ~= current_node_id then return end + if load_shunt == "1" then return end return m:del(current_node_id, shunt_rules[section]["_proxy_tag_option"]) end @@ -204,4 +234,11 @@ for k1, v1 in pairs(node_list) do end end -m:appendTemplate("/include/shunt_options", {id = current_node_id, s_cfgid = s_cfgid or current_node_id, normal_list = api.jsonc.stringify(node_list.normal_list)}) +m:appendTemplate("/include/shunt_options", { + node_id = current_node_id, + section_id = section_id or current_node_id, + section_type = shunt_section_type, + tab_name = data.tab, + normal_list = api.jsonc.stringify(node_list.normal_list), + shunt_list = api.jsonc.stringify(node_list.shunt_list) +}) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua index 20f8ff3f..9c4315d0 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua @@ -61,7 +61,6 @@ end local types_dir = "/usr/lib/lua/luci/model/cbi/" .. api.appname .. "/client/type/" s.val = {} s.val["type"] = m:get(arg[1], "type") -s.val["protocol"] = m:get(arg[1], "protocol") if luci.http.formvalue("cbi.submit") == "1" then local formvalue_type = luci.http.formvalue(formvalue_key .. "type") @@ -72,34 +71,6 @@ end o = s:option(ListValue, "type", translate("Type")) -if api.is_finded("ipt2socks") then - local type_name = "Socks" - - s.fields["type"]:value(type_name, "Socks") - - if s.val["type"] == type_name then - local s2 = NamedSection(m, arg[1], "server") - s2.type_name = type_name - s2.option_prefix = "socks_" - - o = s2:option(ListValue, "del_protocol", " ") --始终隐藏,用于删除 protocol - o:depends({ __hide = "1" }) - o.rewrite_option = "protocol" - - o = s2:option(Value, "address", translate("Address (Support Domain Name)")) - - o = s2:option(Value, "port", translate("Port")) - o.datatype = "port" - - o = s2:option(Value, "username", translate("Username")) - - o = s2:option(Value, "password", translate("Password")) - o.password = true - - api.luci_types(s, s2) - end -end - local type_table = {} for filename in api.fs.dir(types_dir) do table.insert(type_table, filename) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/0_socks.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/0_socks.lua new file mode 100644 index 00000000..23856bad --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/0_socks.lua @@ -0,0 +1,35 @@ +if not api.is_finded("ipt2socks") then + return +end + +-- [[ Socks ]] +local m, s1 = ... +local type_name = "Socks" + +s1.fields["type"]:value(type_name, "Socks") + +if s1.val["type"] and s1.val["type"] ~= type_name then + return +end + +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 +s.type_name = type_name +s.option_prefix = "socks_" +api.set_type_cbi(s) + +o = s:option(ListValue, "del_protocol", "¡¡") --ʼÖÕÒþ²أ¬ÓÃÓÚɾ³ý protocol +o:depends({ __hide = "1" }) +o.rewrite_option = "protocol" + +o = s:option(Value, "address", translate("Address (Support Domain Name)")) + +o = s:option(Value, "port", translate("Port")) +o.datatype = "port" + +o = s:option(Value, "username", translate("Username")) + +o = s:option(Value, "password", translate("Password")) +o.password = true + +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/1_sing-box.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/1_sing-box.lua index a4c032a7..3008a514 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/1_sing-box.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/1_sing-box.lua @@ -17,15 +17,11 @@ if s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "singbox_" - -local formvalue_proto = luci.http.formvalue(formvalue_key .. "protocol") - -if formvalue_proto then s1.val["protocol"] = formvalue_proto end - -local arg_select_proto = luci.http.formvalue("select_proto") or "" +api.set_type_cbi(s) local ss_method_new_list = { "none", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" @@ -72,24 +68,20 @@ end o:value("_urltest", translate("URLTest")) o:value("_shunt", translate("Shunt")) o:value("_iface", translate("Custom Interface")) -function o.custom_cfgvalue(self, section) - if arg_select_proto ~= "" then - return arg_select_proto - else - return m:get(section, self.config_option) - end + +local protocol_val = m:get(s.section, "protocol") +local formvalue_proto = s.fields["protocol"]:formvalue(s.section) +if formvalue_proto then + protocol_val = formvalue_proto end -local load_urltest_options = s1.val["protocol"] == "_urltest" or arg_select_proto == "_urltest" -local load_shunt_options = s1.val["protocol"] == "_shunt" or arg_select_proto == "_shunt" -local load_iface_options = s1.val["protocol"] == "_iface" or arg_select_proto == "_iface" +local load_urltest_options = protocol_val == "_urltest" +local load_shunt_options = protocol_val == "_shunt" +local load_iface_options = protocol_val == "_iface" local load_normal_options = true if load_urltest_options or load_shunt_options or load_iface_options then load_normal_options = nil end -if not arg_select_proto:find("_") then - load_normal_options = true -end local netdev_list = api.get_network_devices() local node_list = api.get_node_list() @@ -115,11 +107,11 @@ if load_urltest_options then -- [[ URLTest Start ]] end end -- 读取旧 DynamicList - function o.custom_cfgvalue(self, section) + function o.cfgvalue(self, section) return table.concat(m:get(section, "urltest_node") or {}, " ") end -- 写入保持 DynamicList - function o.custom_write(self, section, value) + function o.write(self, section, value) local old = m:get(section, "urltest_node") or {} local new, set = {}, {} for v in value:gmatch("%S+") do @@ -935,7 +927,7 @@ if not load_shunt_options then for k1, v1 in pairs(node_list) do if k1 ~= "shunt_list" and k1 ~= "iface_list" then for i, v in ipairs(v1) do - if v.id ~= arg[1] then + if v.id ~= s.section then o1:value(v.id, v.remark) o1.group[#o1.group+1] = (v.group and v.group ~= "") and v.group or translate("default") if k1 == "normal_list" then @@ -949,14 +941,15 @@ if not load_shunt_options then end end -api.luci_types(s1, s) +api.type_cbi_section(s1, s) if load_shunt_options then - local current_node = m:get(arg[1]) or {} local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua") setfenv(shunt_lua, getfenv(1))(m, s1, { - node_id = arg[1], - node = current_node, + node = { + [".name"] = s.section, + type = type_name, + }, node_list = node_list, }) end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/2_xray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/2_xray.lua index 6ff9f508..5684127d 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/2_xray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/2_xray.lua @@ -15,15 +15,11 @@ if s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "xray_" - -local formvalue_proto = luci.http.formvalue(formvalue_key .. "protocol") - -if formvalue_proto then s1.val["protocol"] = formvalue_proto end - -local arg_select_proto = luci.http.formvalue("select_proto") or "" +api.set_type_cbi(s) local ss_method_list = { "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" @@ -53,31 +49,26 @@ if api.compare_versions(xray_version, ">=", "1.8.12") then end o:value("_shunt", translate("Shunt")) o:value("_iface", translate("Custom Interface")) -function o.custom_cfgvalue(self, section) - if arg_select_proto ~= "" then - return arg_select_proto - else - return m:get(section, self.config_option) - end +local protocol_val = m:get(s.section, "protocol") +local formvalue_proto = s.fields["protocol"]:formvalue(s.section) +if formvalue_proto then + protocol_val = formvalue_proto end -local load_balancing_options = s1.val["protocol"] == "_balancing" or arg_select_proto == "_balancing" -local load_shunt_options = s1.val["protocol"] == "_shunt" or arg_select_proto == "_shunt" -local load_iface_options = s1.val["protocol"] == "_iface" or arg_select_proto == "_iface" +local load_balancing_options = protocol_val == "_balancing" +local load_shunt_options = protocol_val == "_shunt" +local load_iface_options = protocol_val == "_iface" local load_normal_options = true if load_balancing_options or load_shunt_options or load_iface_options then load_normal_options = nil end -if not arg_select_proto:find("_") then - load_normal_options = true -end local netdev_list = api.get_network_devices() local node_list = api.get_node_list() local fallback_list = {} local is_balancer = nil for k, e in ipairs(node_list.balancing_list or {}) do - if e.id ~= arg[1] then + if e.id ~= s.section then fallback_list[#fallback_list + 1] = { id = e["id"], remark = e["remark"], @@ -110,11 +101,11 @@ if load_balancing_options then -- [[ Load balancing Start ]] end end -- 读取旧 DynamicList - function o.custom_cfgvalue(self, section) + function o.cfgvalue(self, section) return table.concat(m:get(section, "balancing_node") or {}, " ") end -- 写入保持 DynamicList - function o.custom_write(self, section, value) + function o.write(self, section, value) local old = m:get(section, "balancing_node") or {} local new, set = {}, {} for v in value:gmatch("%S+") do @@ -213,7 +204,7 @@ if load_balancing_options then -- [[ Load balancing Start ]] local depth = get_fallback_depth(v.id) -- 超过最大套娃层数后,不允许继续选择 balancer if depth < MAX_FALLBACK_DEPTH - and not will_loop(arg[1], v.id) + and not will_loop(s.section, 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") @@ -678,13 +669,13 @@ o.validate = function(self, value) if v then return v end return nil, "XHTTP Extra " .. translate("Must be JSON text!") end -o.custom_cfgvalue = function(self, section, value) +o.cfgvalue = function(self, section, value) local raw = m:get(section, "xhttp_extra") if raw then return api.base64Decode(raw) end end -o.custom_write = function(self, section, value) +o.write = function(self, section, value) m:set(section, "xhttp_extra", api.base64Encode(value) or "") local success, data = pcall(api.jsonc.parse, value) if success and data then @@ -700,7 +691,7 @@ o.custom_write = function(self, section, value) m:del(section, "download_address") end end -o.custom_remove = function(self, section, value) +o.remove = function(self, section, value) m:del(section, "xhttp_extra") m:del(section, "download_address") end @@ -763,13 +754,13 @@ o.validate = function(self, value) if v then return v end return nil, "FinalMask " .. translate("Must be JSON text!") end -o.custom_cfgvalue = function(self, section, value) +o.cfgvalue = function(self, section, value) local raw = m:get(section, "finalmask") if raw then return api.base64Decode(raw) end end -o.custom_write = function(self, section, value) +o.write = function(self, section, value) m:set(section, "finalmask", api.base64Encode(value) or "") end @@ -871,7 +862,7 @@ if not load_shunt_options then for k1, v1 in pairs(node_list) do if k1 ~= "shunt_list" and k1 ~= "iface_list" then for i, v in ipairs(v1) do - if v.id ~= arg[1] then + if v.id ~= s.section then o1:value(v.id, v.remark) o1.group[#o1.group+1] = (v.group and v.group ~= "") and v.group or translate("default") if k1 == "normal_list" then @@ -885,14 +876,16 @@ if not load_shunt_options then end end -api.luci_types(s1, s) +api.type_cbi_section(s1, s) if load_shunt_options then local current_node = m:get(arg[1]) or {} local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua") setfenv(shunt_lua, getfenv(1))(m, s1, { - node_id = arg[1], - node = current_node, + node = { + [".name"] = s.section, + type = type_name, + }, node_list = node_list, }) end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/3_ss-rust.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/3_ss-rust.lua index 1c7562dc..30f63d71 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/3_ss-rust.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/3_ss-rust.lua @@ -12,9 +12,11 @@ if s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "ssrust_" +api.set_type_cbi(s) local ssrust_encrypt_method_list = { "none", "plain", @@ -69,4 +71,4 @@ end o = s:option(Value, "plugin_opts", translate("opts")) o:depends({ plugin_enabled = true }) -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/4_ssr.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/4_ssr.lua index e86e470b..542ee14d 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/4_ssr.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/4_ssr.lua @@ -12,9 +12,11 @@ if s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "ssr_" +api.set_type_cbi(s) local ssr_encrypt_method_list = { "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", @@ -63,4 +65,4 @@ o.default = 300 o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"), translate("Need node support required")) o.default = 0 -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/5_hysteria2.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/5_hysteria2.lua index d9b4d600..1ec43518 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/5_hysteria2.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/5_hysteria2.lua @@ -12,13 +12,11 @@ if s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "hysteria2_" - -local function _n(name) - return s.option_prefix .. name -end +api.set_type_cbi(s) o = s:option(ListValue, "protocol", translate("Protocol")) o:value("udp", "UDP") @@ -32,22 +30,22 @@ o:depends({ realms = false }) o = s:option(Value, "hop", translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = false }) o = s:option(Value, "hop_interval", translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) o.datatype = "or(uinteger,portrange)" o.placeholder = "30" o.default = "30" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = false }) o = s:option(Flag, "realms", translate("Realms")) o.default = "0" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name") -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = "1" }) o.validate = function(self, value) value = api.trim(value) @@ -58,26 +56,26 @@ end o = s:option(DynamicList, "realm_stun", translate("Realm STUN")) o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" } -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = "1" }) o = s:option(Flag, "realm_upnp", translate("Enable") .. " UPnP/NAT-PMP", translate("Enable UPnP/NAT-PMP port mapping on your gateway to improve hole punching success.")) o.default = "0" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = "1" }) o = s:option(Value, "auth_password", translate("Auth Password")) o.password = true -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(ListValue, "obfs_type", translate("Obfs Type")) o:value("", translate("Disable")) o:value("salamander") o:value("gecko") -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "obfs_password", translate("Obfs Password")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ obfs_type = "salamander" }) o:depends({ obfs_type = "gecko" }) @@ -86,14 +84,14 @@ o.datatype = "uinteger" o.placeholder = "512" o.default = "512" o:depends({ obfs_type = "gecko" }) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "obfs_MaxPacketSize", translate("Gecko Packet Size (max)")) o.datatype = "uinteger" o.placeholder = "1200" o.default = "1200" o:depends({ obfs_type = "gecko" }) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Flag, "fast_open", translate("Fast Open")) o.default = "0" @@ -106,28 +104,28 @@ o.default = "0" o = s:option(Value, "tls_pinSHA256", translate("PinSHA256"),translate("Certificate fingerprint")) o = s:option(Value, "up_mbps", translate("Max upload Mbps")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "down_mbps", translate("Max download Mbps")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "recv_window", translate("QUIC stream receive window")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "recv_window_conn", translate("QUIC connection receive window")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)") o.datatype = "range(4,120)" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "keep_alive_period", translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)") o.datatype = "range(2,60)" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Flag, "disable_mtu_discovery", translate("Disable MTU detection")) o.default = "0" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Flag, "ech", translate("ECH")) @@ -145,6 +143,6 @@ end o = s:option(Flag, "lazy_start", translate("Lazy Start")) o.default = "0" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua index b00c0c3f..83dc7d91 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua @@ -12,9 +12,11 @@ if s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "naive_" +api.set_type_cbi(s) o = s:option(ListValue, "protocol", translate("Protocol")) o:value("https", translate("HTTPS")) @@ -30,4 +32,4 @@ o = s:option(Value, "username", translate("Username")) o = s:option(Value, "password", translate("Password")) o.password = true -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/0_socks.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/0_socks.lua index 3b267d62..91acbf79 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/0_socks.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/0_socks.lua @@ -15,9 +15,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "socks_" +api.set_type_cbi(s) o = s:option(Value, "port", translate("Listen Port")) o.datatype = "port" @@ -44,4 +46,4 @@ o:depends({ firewall_allow = true }) o = s:option(Flag, "log", translate("Log")) o.default = "1" -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/1_sing-box.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/1_sing-box.lua index 592028c3..05fb9724 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/1_sing-box.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/1_sing-box.lua @@ -21,9 +21,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "singbox_" +api.set_type_cbi(s) local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'") @@ -48,13 +50,13 @@ o.validate = function(self, value) if v then return v end return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!") end -o.custom_cfgvalue = function(self, section, value) +o.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) +o.write = function(self, section, value) m:set(section, "config_str", api.base64Encode(value) or "") end @@ -562,4 +564,4 @@ o:value("warn") o:value("error") o:depends({ log = true }) -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/2_xray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/2_xray.lua index 11ec4fab..02dfc68d 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/2_xray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/2_xray.lua @@ -19,9 +19,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "xray_" +api.set_type_cbi(s) local ss_method_list = { "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" @@ -44,13 +46,13 @@ o.validate = function(self, value) if v then return v end return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!") end -o.custom_cfgvalue = function(self, section, value) +o.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) +o.write = function(self, section, value) m:set(section, "config_str", api.base64Encode(value) or "") end @@ -257,8 +259,8 @@ end -- [[ TLS部分 ]] -- o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") -o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem" -if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end +o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. s.section .. ".pem" +if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end o:depends({ tls = true, reality = false }) o:depends({ protocol = "hysteria2"}) o.validate = function(self, value, t) @@ -273,8 +275,8 @@ o.validate = function(self, value, t) end o = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") -o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key" -if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end +o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. s.section .. ".key" +if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end o:depends({ tls = true, reality = false }) o:depends({ protocol = "hysteria2"}) o.validate = function(self, value, t) @@ -396,13 +398,13 @@ o:depends({ use_finalmask = true }) o.rows = 10 o.wrap = "off" o.datatype = "json" -o.custom_cfgvalue = function(self, section, value) +o.cfgvalue = function(self, section, value) local raw = m:get(section, "finalmask") if raw then return api.base64Decode(raw) end end -o.custom_write = function(self, section, value) +o.write = function(self, section, value) m:set(section, "finalmask", api.base64Encode(value) or "") end @@ -549,4 +551,4 @@ o:value("warning") o:value("error") o:depends({ log = true }) -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/3_ss-rust.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/3_ss-rust.lua index 851247af..9c7f4cc2 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/3_ss-rust.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/3_ss-rust.lua @@ -16,9 +16,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "ssrust_" +api.set_type_cbi(s) local ssrust_encrypt_method_list = { "plain", "none", @@ -39,13 +41,13 @@ o.validate = function(self, value) if v then return v end return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!") end -o.custom_cfgvalue = function(self, section, value) +o.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) +o.write = function(self, section, value) m:set(section, "config_str", api.base64Encode(value) or "") end @@ -88,4 +90,4 @@ o = s:option(Flag, "log", translate("Log")) o.default = "1" o.rmempty = false -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/4_ssr.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/4_ssr.lua index 8e54f6fd..9453bdf4 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/4_ssr.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/4_ssr.lua @@ -16,9 +16,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "ssr_" +api.set_type_cbi(s) local ssr_encrypt_method_list = { "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", @@ -52,13 +54,13 @@ o.validate = function(self, value) if v then return v end return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!") end -o.custom_cfgvalue = function(self, section, value) +o.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) +o.write = function(self, section, value) m:set(section, "config_str", api.base64Encode(value) or "") end @@ -119,4 +121,4 @@ o = s:option(Flag, "log", translate("Log")) o.default = "1" o.rmempty = false -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/5_hysteria2.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/5_hysteria2.lua index 9a037ff7..c7147f50 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/5_hysteria2.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/5_hysteria2.lua @@ -12,13 +12,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then return end -local s = NamedSection(m, arg[1], "server") +local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype) +s.parent = s1 s.type_name = type_name s.option_prefix = "hysteria2_" - -local function _n(name) - return s.option_prefix .. name -end +api.set_type_cbi(s) o = s:option(Flag, "custom", translate("Use Custom Config")) @@ -33,13 +31,13 @@ o.validate = function(self, value) if v then return v end return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!") end -o.custom_cfgvalue = function(self, section, value) +o.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) +o.write = function(self, section, value) m:set(section, "config_str", api.base64Encode(value) or "") end @@ -55,11 +53,11 @@ o:depends({ custom = false }) o = s:option(Flag, "realms", translate("Realms")) o.default = "0" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ custom = false }) o = s:option(Value, "realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name") -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = "1" }) o.validate = function(self, value) value = api.trim(value) @@ -70,23 +68,23 @@ end o = s:option(DynamicList, "realm_stun", translate("Realm STUN")) o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" } -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = "1" }) o = s:option(Flag, "realm_upnp", translate("Enable") .. " UPnP/NAT-PMP", translate("Enable UPnP/NAT-PMP port mapping on your gateway to improve hole punching success.")) o.default = "0" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ realms = "1" }) o = s:option(ListValue, "obfs_type", translate("Obfs Type")) o:value("", translate("Disable")) o:value("salamander") o:value("gecko") -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ custom = false }) o = s:option(Value, "obfs_password", translate("Obfs Password")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ obfs_type = "salamander" }) o:depends({ obfs_type = "gecko" }) @@ -95,31 +93,31 @@ o.datatype = "uinteger" o.placeholder = "512" o.default = "512" o:depends({ obfs_type = "gecko" }) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Value, "obfs_MaxPacketSize", translate("Gecko Packet Size (max)")) o.datatype = "uinteger" o.placeholder = "1200" o.default = "1200" o:depends({ obfs_type = "gecko" }) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o = s:option(Flag, "udp", translate("UDP")) o.default = "1" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ custom = false }) o = s:option(Value, "up_mbps", translate("Max upload Mbps")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ custom = false }) o = s:option(Value, "down_mbps", translate("Max download Mbps")) -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ custom = false }) o = s:option(Flag, "ignoreClientBandwidth", translate("ignoreClientBandwidth")) o.default = "0" -o.rewrite_option = _n(o.option) +o.rewrite_option = o.option o:depends({ custom = false }) o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") @@ -181,4 +179,4 @@ o = s:option(Flag, "log", translate("Log")) o.default = "1" o.rmempty = false -api.luci_types(s1, s) +api.type_cbi_section(s1, s) diff --git a/luci-app-passwall/luasrc/passwall/api.lua b/luci-app-passwall/luasrc/passwall/api.lua index d9d3cf8f..c0f60b46 100644 --- a/luci-app-passwall/luasrc/passwall/api.lua +++ b/luci-app-passwall/luasrc/passwall/api.lua @@ -1537,110 +1537,88 @@ function return_map(map) return map end -function luci_types(s, s2) +function set_type_cbi(s) local cbi = require "luci.cbi" - local m = s.map - local id = s2.section - local type_name = s2.type_name - local option_prefix = s2.option_prefix - local fv_type - local field_type = s.fields["type"] - if field_type then - fv_type = field_type:formvalue(id) + local s1 = s.parent + function s.option(self, class, option, ...) + local obj = class(self.map, self, option, ...) + obj.config_option = option + obj.option_prefix = self.option_prefix + obj.option = self.option_prefix .. option + obj.cfgvalue = function(o_self, section) + if o_self.rewrite_option then + return o_self.map:get(section, o_self.rewrite_option) + else + return o_self.map:get(section, o_self.config_option) + end + end + obj.write = function(o_self, section, value) + if s1.fields["type"]:formvalue(self.section) == self.type_name then + local new_val = value + if util.instanceof(o_self, cbi.DynamicList) then + local new_t = {} + if type(value) == "table" then + new_t = table_remove_duplicates(value) + else + new_t = { value } + end + if o_self.cast == "string" then + new_val = table.concat(new_t, " ") + else + new_val = new_t + end + end + if o_self.rewrite_option then + o_self.map:set(section, o_self.rewrite_option, new_val) + else + o_self.map:set(section, o_self.config_option, new_val) + end + end + end + obj.remove = function(o_self, section) + if s1.fields["type"]:formvalue(self.section) == self.type_name then + if o_self.rewrite_option then + o_self.map:del(section, o_self.rewrite_option) + else + o_self.map:del(section, o_self.config_option) + end + end + end + obj.depends = function(o_self, field, value) + local deps + if type(field) == "string" then + deps = {} + deps[field] = value + else + deps = field + end + local new_deps = {} + for k, v in pairs(deps) do + local n_k = k + if self.fields[k] then + n_k = self.fields[k].option + end + new_deps[n_k] = v + end + new_deps["type"] = self.type_name + if next(new_deps) then + table.insert(o_self.deps, new_deps) + end + end + self:append(obj) + self.fields[option] = obj + return obj end +end + +function type_cbi_section(s, s2) for i, v in ipairs(s2.children) do local o = s2.children[i] - o.config_option = o.option - o.option_prefix = option_prefix - o.option = option_prefix .. o.option - if not o.not_rewrite then - o.cfgvalue = function(self, section) - -- Add a custom `custom_cfgvalue` attribute. If a custom `custom_cfgvalue` function exists, the custom `cfgvalue` logic will be used. - if self.custom_cfgvalue then - return self:custom_cfgvalue(section) - else - if self.rewrite_option then - return m:get(section, self.rewrite_option) - else - return m:get(section, self.config_option) - end - end - end - o.write = function(self, section, value) - if s.fields["type"]:formvalue(id) == type_name then - -- Add a custom `custom_write` attribute; if a custom `custom_write` function exists, then use the custom write logic. - if self.custom_write then - self:custom_write(section, value) - else - local new_val = value - if util.instanceof(self, cbi.DynamicList) then - local new_t = {} - if type(value) == "table" then - new_t = table_remove_duplicates(value) - else - new_t = { value } - end - if self.cast == "string" then - new_val = table.concat(new_t, " ") - else - new_val = new_t - end - end - if self.rewrite_option then - m:set(section, self.rewrite_option, new_val) - else - m:set(section, self.config_option, new_val) - end - end - end - end - o.remove = function(self, section) - if s.fields["type"]:formvalue(id) == type_name then - -- Add a custom `custom_remove` attribute; if a custom `custom_remove` function exists, use the custom remove logic. - if self.custom_remove then - self:custom_remove(section) - else - if self.rewrite_option then - m:del(section, self.rewrite_option) - else - m:del(section, self.config_option) - end - end - end - end + if #o.deps == 0 then + o:depends({ type = s2.type_name }) end - - local deps = o.deps - if #deps > 0 then - local function process_deps(dep) - local rewrite_deps = {} - for k, v in pairs(dep) do - if k:find("!") then - rewrite_deps[k] = v - else - rewrite_deps[option_prefix .. k] = v - end - end - if not rewrite_deps['!reverse'] then - rewrite_deps["type"] = type_name - end - return rewrite_deps - end - for index, value in ipairs(deps) do - local rewrite_deps = process_deps(value) - if rewrite_deps then - deps[index] = rewrite_deps - end - end - else - o:depends({ type = type_name }) - end - - if fv_type and fv_type ~= type_name then - o.rmempty = true - end - s:append(o) + s.fields[o.option] = o end end diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index 80d0d275..519497dd 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -44,6 +44,7 @@ function gen_outbound(flag, node, tag, proxy_table) local remarks = node.remarks local proxy_tag = nil + local dialer_proxy_tag = nil local fragment = nil local noise = nil local run_socks_instance = true @@ -86,12 +87,7 @@ function gen_outbound(flag, node, tag, proxy_table) node.stream_security = "none" proxy_tag = "socks <- " .. node_id else - if proxy_tag then - node.proxySettings = { - tag = proxy_tag, - transportLayer = true - } - end + dialer_proxy_tag = proxy_tag end if node.type == "Xray" then @@ -135,7 +131,6 @@ function gen_outbound(flag, node, tag, proxy_table) _flag = flag, _flag_proxy_tag = proxy_tag, tag = tag, - proxySettings = node.proxySettings or nil, protocol = node.protocol, mux = { enabled = (node.mux == "1") and true or false, @@ -143,7 +138,7 @@ function gen_outbound(flag, node, tag, proxy_table) xudpConcurrency = (node.mux == "1" and ((node.xudp_concurrency) and tonumber(node.xudp_concurrency) or 8)) or nil } or nil, -- 底层传输配置 - streamSettings = (node.streamSettings or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan" or node.protocol == "hysteria") and { + streamSettings = (node.streamSettings or dialer_proxy_tag or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan" or node.protocol == "hysteria") and { sockopt = { mark = 255, domainStrategy = node.domain_strategy or "UseIP", @@ -154,7 +149,8 @@ function gen_outbound(flag, node, tag, proxy_table) PrioritizeIPv6 = false, Interleave = 1, MaxConcurrentTry = 4 - } or nil + } or nil, + dialerProxy = dialer_proxy_tag, }, [(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network" security = node.stream_security, @@ -1209,10 +1205,9 @@ function gen_config(var) end if preproxy_outbound then outbound.tag = preproxy_outbound.tag .. " -> " .. outbound.tag - outbound.proxySettings = { - tag = preproxy_outbound.tag, - transportLayer = true - } + outbound.streamSettings = outbound.streamSettings or {} + outbound.streamSettings.sockopt = outbound.streamSettings.sockopt or {} + outbound.streamSettings.sockopt.dialerProxy = preproxy_outbound.tag if not exist then last_insert_outbound = preproxy_outbound end @@ -1260,10 +1255,9 @@ function gen_config(var) if to_outbound then to_outbound.tag = outbound.tag .. " -> " .. to_outbound.tag if to_node.type == "Xray" then - to_outbound.proxySettings = { - tag = outbound.tag, - transportLayer = true - } + to_outbound.streamSettings = to_outbound.streamSettings or {} + to_outbound.streamSettings.sockopt = to_outbound.streamSettings.sockopt or {} + to_outbound.streamSettings.sockopt.dialerProxy = outbound.tag end table.insert(outbounds_table, to_outbound) default_outTag = to_outbound.tag diff --git a/luci-app-passwall/luasrc/view/passwall/global/footer.htm b/luci-app-passwall/luasrc/view/passwall/global/footer.htm index d122cedd..bdacc409 100644 --- a/luci-app-passwall/luasrc/view/passwall/global/footer.htm +++ b/luci-app-passwall/luasrc/view/passwall/global/footer.htm @@ -14,11 +14,6 @@ local sid = "@global[0]" } } -.shunt-tab-hidden { - display: none !important; - visibility: hidden !important; -} - @media screen and (max-width: 1152px) { #cbi-<%=appname%>-socks .cbi-section-table-titles { display: none !important; @@ -28,7 +23,6 @@ local sid = "@global[0]" diff --git a/luci-app-passwall/luasrc/view/passwall/include/node_change.htm b/luci-app-passwall/luasrc/view/passwall/include/node_change.htm new file mode 100644 index 00000000..862649de --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/include/node_change.htm @@ -0,0 +1,73 @@ +<% +local map = self.map +local api = map.api +local config = map.config +local verify_option = self.verify_option +local section_id = verify_option.section.section +-%> +<% if verify_option then -%> + +<%- end %> \ No newline at end of file diff --git a/luci-app-passwall/luasrc/view/passwall/include/shunt_options.htm b/luci-app-passwall/luasrc/view/passwall/include/shunt_options.htm index 20d081a6..53e9a5f9 100644 --- a/luci-app-passwall/luasrc/view/passwall/include/shunt_options.htm +++ b/luci-app-passwall/luasrc/view/passwall/include/shunt_options.htm @@ -2,18 +2,22 @@ local map = self.map local api = map.api local config = map.config -local id = self.id -local s_cfgid = self.s_cfgid +local node_id = self.node_id +local verify_option = self.verify_option +local section_id = self.section_id +local section_type = self.section_type +local tab_name = self.tab_name -%> \ No newline at end of file diff --git a/luci-app-passwall/luasrc/view/passwall/node_config/footer.htm b/luci-app-passwall/luasrc/view/passwall/node_config/footer.htm index e6a9da82..cfe03b1c 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_config/footer.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_config/footer.htm @@ -35,27 +35,30 @@ local config = map.config }); waitForElement('select[name*="<%=config%>"][name*="protocol"]', function(el) { let o_val = el.value; + const name_split = el.name.split("."); + const name = name_split[name_split.length - 1]; el.addEventListener("change", () => { el.blur(); if (el.value.startsWith("_") || (o_val.startsWith("_") && !el.value.startsWith("_"))) { - let name_split = el.name.split("."); - let name = name_split[name_split.length - 1]; - let save = true; - if (save) { - /* - const saveBtn = document.getElementsByClassName('cbi-button-save'); - if (saveBtn && saveBtn.length > 0) { - saveBtn[saveBtn.length - 1].click(); - } - */ - update_config(node_id, { - remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value, - group: getOption("<%=config%>", "<%=sid%>", "group").value, - protocol: getOption("<%=config%>", "<%=sid%>", name).value, - }, node_config_url); - } else { - window.location.href = node_config_url + "?select_proto=" + encodeURIComponent(el.value); + if (el.value.startsWith("_")) { + const map = document.getElementById("cbi-<%=config%>"); + const hiddenInput = document.createElement('input'); + hiddenInput.type = 'hidden'; + hiddenInput.name = 'load' + el.value; + hiddenInput.value = '1'; + map.appendChild(hiddenInput); } + const saveBtn = document.getElementsByClassName('cbi-button-save'); + if (saveBtn && saveBtn.length > 0) { + saveBtn[saveBtn.length - 1].click(); + } + /* + update_config(node_id, { + remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value, + group: getOption("<%=config%>", "<%=sid%>", "group").value, + protocol: getOption("<%=config%>", "<%=sid%>", name).value, + }, node_config_url); + */ } }); }); diff --git a/luci-app-passwall/root/usr/share/passwall/app.sh b/luci-app-passwall/root/usr/share/passwall/app.sh index 36c4052b..52069949 100755 --- a/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/luci-app-passwall/root/usr/share/passwall/app.sh @@ -566,11 +566,7 @@ start_global() { local node_socks_bind_local=$(config_n_get @global[0] node_socks_bind_local 1) local node_socks_bind="127.0.0.1" [ "${node_socks_bind_local}" != "1" ] && node_socks_bind="0.0.0.0" - local global_socks_port=$(config_n_get @global[0] node_socks_port 1070) - GLOBAL_SOCKS_port=$(get_new_port $global_socks_port) - if [ "$GLOBAL_SOCKS_port" != "$global_socks_port" ]; then - echolog "注意:全局节点 Socks 端口冲突,原端口 ${global_socks_port} 已自动更改为 ${GLOBAL_SOCKS_port}!" - fi + GLOBAL_SOCKS_port=$(config_n_get @global[0] node_socks_port 1070) GLOBAL_HTTP_port=$(config_n_get @global[0] node_http_port 0) [ "$GLOBAL_HTTP_port" != "0" ] && local on_node_http=1 if [ $PROXY_IPV6 = "1" ]; then diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index 4fe9ce4b..e787e41c 100644 --- a/luci-app-passwall2/Makefile +++ b/luci-app-passwall2/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 PKG_VERSION:=26.9.9 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index f006efae..6befb203 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -59,6 +59,7 @@ function gen_outbound(flag, node, tag, proxy_table) local remarks = node.remarks local proxy_tag = nil + local dialer_proxy_tag = nil local fragment = nil local noise = nil local run_socks_instance = true @@ -97,12 +98,7 @@ function gen_outbound(flag, node, tag, proxy_table) node.stream_security = "none" proxy_tag = "socks <- " .. node_id else - if proxy_tag then - node.proxySettings = { - tag = proxy_tag, - transportLayer = true - } - end + dialer_proxy_tag = proxy_tag end if node.type == "Xray" then @@ -146,14 +142,13 @@ function gen_outbound(flag, node, tag, proxy_table) _flag = flag, _flag_proxy_tag = proxy_tag, tag = tag, - proxySettings = node.proxySettings or nil, protocol = node.protocol, mux = { enabled = (node.mux == "1") and true or false, concurrency = (node.mux == "1" and ((node.mux_concurrency) and tonumber(node.mux_concurrency) or -1)) or nil, xudpConcurrency = (node.mux == "1" and ((node.xudp_concurrency) and tonumber(node.xudp_concurrency) or 8)) or nil } or nil, - streamSettings = (node.streamSettings or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan" or node.protocol == "hysteria") and { + streamSettings = (node.streamSettings or dialer_proxy_tag or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan" or node.protocol == "hysteria") and { sockopt = { mark = 255, domainStrategy = node.domain_strategy or "UseIP", @@ -164,7 +159,8 @@ function gen_outbound(flag, node, tag, proxy_table) PrioritizeIPv6 = false, Interleave = 1, MaxConcurrentTry = 4 - } or nil + } or nil, + dialerProxy = dialer_proxy_tag, }, [(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network" security = node.stream_security, @@ -1208,10 +1204,9 @@ function gen_config(var) end if preproxy_outbound then outbound.tag = preproxy_outbound.tag .. " -> " .. outbound.tag - outbound.proxySettings = { - tag = preproxy_outbound.tag, - transportLayer = true - } + outbound.streamSettings = outbound.streamSettings or {} + outbound.streamSettings.sockopt = outbound.streamSettings.sockopt or {} + outbound.streamSettings.sockopt.dialerProxy = preproxy_outbound.tag if not exist then last_insert_outbound = preproxy_outbound end @@ -1259,10 +1254,9 @@ function gen_config(var) if to_outbound then to_outbound.tag = outbound.tag .. " -> " .. to_outbound.tag if to_node.type == "Xray" then - to_outbound.proxySettings = { - tag = outbound.tag, - transportLayer = true - } + to_outbound.streamSettings = to_outbound.streamSettings or {} + to_outbound.streamSettings.sockopt = to_outbound.streamSettings.sockopt or {} + to_outbound.streamSettings.sockopt.dialerProxy = outbound.tag end table.insert(outbounds_table, to_outbound) default_outTag = to_outbound.tag