update 2026-08-15 00:44:02

This commit is contained in:
action committed 2026-08-15 00:44:02 +08:00
1 parent 58e04d6ceb
commit a59171002f
84 files changed
+919 -835

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@ PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=8d37150fd674731c4a5931cb82937d3c57a09301 PKG_SOURCE_VERSION:=04569ccae1bc6c926e59da5c70949010ffb55ba9
PKG_SOURCE_URL:=https://github.com/olicesx/dae.git PKG_SOURCE_URL:=https://github.com/olicesx/dae.git
PKG_MIRROR_HASH:=skip PKG_MIRROR_HASH:=skip
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

+136 -136
View File
@@ -4,8 +4,10 @@
module("luci.controller.passwall", package.seeall) module("luci.controller.passwall", package.seeall)
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall" -- not available local appname = api.appname -- not available
local uci = api.uci -- in funtion index() local c_config = api.c_config -- not available
local s_config = api.s_config -- not available
local uci = api.uci -- in funtion index()
local fs = api.fs local fs = api.fs
local http = require "luci.http" local http = require "luci.http"
local util = require "luci.util" local util = require "luci.util"
@@ -20,14 +22,16 @@ function index()
else return end else return end
end end
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall" -- global definitions not available local appname = api.appname -- global definitions not available
local uci = api.uci -- in function index() local c_config = api.c_config -- not available
local s_config = api.s_config -- not available
local uci = api.uci -- in function index()
local fs = api.fs local fs = api.fs
entry({"admin", "services", appname}).dependent = true entry({"admin", "services", appname}).dependent = true
entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true
entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true
local e local e
if uci:get(appname, "@global[0]", "hide_from_luci") ~= "1" then if uci:get(c_config, "@global[0]", "hide_from_luci") ~= "1" then
e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), _("Pass Wall"), -1) e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), _("Pass Wall"), -1)
else else
e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), nil, -1) e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), nil, -1)
@@ -140,7 +144,7 @@ local function http_write_json_error(data)
end end
function reset_config() function reset_config()
uci:revert(appname) uci:revert(c_config)
luci.sys.call("echo '' > /tmp/log/passwall.log") luci.sys.call("echo '' > /tmp/log/passwall.log")
luci.sys.call('/etc/init.d/passwall stop') luci.sys.call('/etc/init.d/passwall stop')
if luci.sys.call('[ -s "/usr/share/passwall/0_default_config" ]') == 0 then if luci.sys.call('[ -s "/usr/share/passwall/0_default_config" ]') == 0 then
@@ -152,14 +156,14 @@ function reset_config()
end end
function show_menu() function show_menu()
api.sh_uci_del(appname, "@global[0]", "hide_from_luci", true) api.sh_uci_del(c_config, "@global[0]", "hide_from_luci", true)
luci.sys.call("rm -rf /tmp/luci-*") luci.sys.call("rm -rf /tmp/luci-*")
luci.sys.call("/etc/init.d/rpcd restart >/dev/null") luci.sys.call("/etc/init.d/rpcd restart >/dev/null")
http.redirect(api.url()) http.redirect(api.url())
end end
function hide_menu() function hide_menu()
api.sh_uci_set(appname, "@global[0]", "hide_from_luci", "1", true) api.sh_uci_set(c_config, "@global[0]", "hide_from_luci", "1", true)
luci.sys.call("rm -rf /tmp/luci-*") luci.sys.call("rm -rf /tmp/luci-*")
luci.sys.call("/etc/init.d/rpcd restart >/dev/null") luci.sys.call("/etc/init.d/rpcd restart >/dev/null")
http.redirect(luci.dispatcher.build_url("admin", "status", "overview")) http.redirect(luci.dispatcher.build_url("admin", "status", "overview"))
@@ -195,10 +199,10 @@ function socks_autoswitch_add_node()
local id = http.formvalue("id") local id = http.formvalue("id")
local key = http.formvalue("key") local key = http.formvalue("key")
if id and id ~= "" and key and key ~= "" then if id and id ~= "" and key and key ~= "" then
uci:set(appname, id, "enable_autoswitch", "1") uci:set(c_config, id, "enable_autoswitch", "1")
local new_list = uci:get(appname, id, "autoswitch_backup_node") or {} local new_list = uci:get(c_config, id, "autoswitch_backup_node") or {}
for i = #new_list, 1, -1 do for i = #new_list, 1, -1 do
if (uci:get(appname, new_list[i], "remarks") or ""):find(key) then if (uci:get(c_config, new_list[i], "remarks") or ""):find(key) then
table.remove(new_list, i) table.remove(new_list, i)
end end
end end
@@ -207,8 +211,8 @@ function socks_autoswitch_add_node()
table.insert(new_list, e.id) table.insert(new_list, e.id)
end end
end end
uci:set_list(appname, id, "autoswitch_backup_node", new_list) uci:set_list(c_config, id, "autoswitch_backup_node", new_list)
api.uci_save(uci, appname) api.uci_save(uci, c_config)
end end
http.redirect(api.url("socks_config", id)) http.redirect(api.url("socks_config", id))
end end
@@ -217,15 +221,15 @@ function socks_autoswitch_remove_node()
local id = http.formvalue("id") local id = http.formvalue("id")
local key = http.formvalue("key") local key = http.formvalue("key")
if id and id ~= "" and key and key ~= "" then if id and id ~= "" and key and key ~= "" then
uci:set(appname, id, "enable_autoswitch", "1") uci:set(c_config, id, "enable_autoswitch", "1")
local new_list = uci:get(appname, id, "autoswitch_backup_node") or {} local new_list = uci:get(c_config, id, "autoswitch_backup_node") or {}
for i = #new_list, 1, -1 do for i = #new_list, 1, -1 do
if (uci:get(appname, new_list[i], "remarks") or ""):find(key) then if (uci:get(c_config, new_list[i], "remarks") or ""):find(key) then
table.remove(new_list, i) table.remove(new_list, i)
end end
end end
uci:set_list(appname, id, "autoswitch_backup_node", new_list) uci:set_list(c_config, id, "autoswitch_backup_node", new_list)
api.uci_save(uci, appname) api.uci_save(uci, c_config)
end end
http.redirect(api.url("socks_config", id)) http.redirect(api.url("socks_config", id))
end end
@@ -389,7 +393,7 @@ function socks_status()
local id = http.formvalue("id") local id = http.formvalue("id")
e.index = index e.index = index
e.socks_status = luci.sys.call(string.format("/bin/busybox top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep '%s' > /dev/null", appname, id)) == 0 e.socks_status = luci.sys.call(string.format("/bin/busybox top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep '%s' > /dev/null", appname, id)) == 0
local use_http = uci:get(appname, id, "http_port") or 0 local use_http = uci:get(c_config, id, "http_port") or 0
e.use_http = 0 e.use_http = 0
if tonumber(use_http) > 0 then if tonumber(use_http) > 0 then
e.use_http = 1 e.use_http = 1
@@ -481,9 +485,9 @@ function update_config()
local data_t = jsonParse(data) or {} local data_t = jsonParse(data) or {}
if next(data_t) then if next(data_t) then
for k, v in pairs(data_t) do for k, v in pairs(data_t) do
uci:set(appname, id, k, v) uci:set(c_config, id, k, v)
end end
api.uci_save(uci, appname) api.uci_save(uci, c_config)
http_write_json_ok() http_write_json_ok()
return return
end end
@@ -495,20 +499,20 @@ function add_node()
local redirect = http.formvalue("redirect") local redirect = http.formvalue("redirect")
local uid = api.gen_random_char() local uid = api.gen_random_char()
uci:section(appname, "nodes", uid) uci:section(c_config, "nodes", uid)
local group = http.formvalue("group") local group = http.formvalue("group")
if group and group ~= "default" then if group and group ~= "default" then
uci:set(appname, uid, "group", group) uci:set(c_config, uid, "group", group)
end end
uci:set(appname, uid, "type", "Socks") uci:set(c_config, uid, "type", "Socks")
if redirect == "1" then if redirect == "1" then
api.uci_save(uci, appname) api.uci_save(uci, c_config)
http.redirect(api.url("node_config", uid)) http.redirect(api.url("node_config", uid))
else else
api.uci_save(uci, appname, true, true) api.uci_save(uci, c_config, true, true)
http_write_json({result = uid}) http_write_json({result = uid})
end end
end end
@@ -516,82 +520,80 @@ end
function set_node() function set_node()
local protocol = http.formvalue("protocol") local protocol = http.formvalue("protocol")
local section = http.formvalue("section") local section = http.formvalue("section")
uci:set(appname, "@global[0]", protocol .. "_node", section) uci:set(c_config, "@global[0]", protocol .. "_node", section)
if protocol == "tcp" then if protocol == "tcp" then
local node_protocol = uci:get(appname, section, "protocol") local node_protocol = uci:get(c_config, section, "protocol")
if node_protocol == "_shunt" then if node_protocol == "_shunt" then
local type = uci:get(appname, section, "type") local type = uci:get(c_config, section, "type")
local dns_shunt = uci:get(appname, "@global[0]", "dns_shunt") local dns_shunt = uci:get(c_config, "@global[0]", "dns_shunt")
local dns_key = (dns_shunt == "smartdns") and "smartdns_dns_mode" or "dns_mode" local dns_key = (dns_shunt == "smartdns") and "smartdns_dns_mode" or "dns_mode"
local dns_mode = uci:get(appname, "@global[0]", dns_key) local dns_mode = uci:get(c_config, "@global[0]", dns_key)
local new_dns_mode = (type == "Xray") and "xray" or "sing-box" local new_dns_mode = (type == "Xray") and "xray" or "sing-box"
if dns_mode ~= new_dns_mode then if dns_mode ~= new_dns_mode then
uci:set(appname, "@global[0]", dns_key, new_dns_mode) uci:set(c_config, "@global[0]", dns_key, new_dns_mode)
uci:set(appname, "@global[0]", "v2ray_dns_mode", "tcp") uci:set(c_config, "@global[0]", "v2ray_dns_mode", "tcp")
end end
end end
end end
api.uci_save(uci, appname, true, true) api.uci_save(uci, c_config, true, true)
http.redirect(api.url("log")) http.redirect(api.url("log"))
end end
function copy_node() function copy_node()
local section = http.formvalue("section") local section = http.formvalue("section")
local uid = api.gen_random_char() local uid = api.gen_random_char()
uci:section(appname, "nodes", uid) uci:section(c_config, "nodes", uid)
for k, v in pairs(uci:get_all(appname, section)) do for k, v in pairs(uci:get_all(c_config, section)) do
if not k:match("^%.") and k ~= "group" then if not k:match("^%.") and k ~= "group" then
if k == "remarks" then v = (v or "") .. "(1)" end if k == "remarks" then v = (v or "") .. "(1)" end
uci:set(appname, uid, k, v) uci:set(c_config, uid, k, v)
end end
end end
uci:set(appname, uid, "add_mode", 1) uci:set(c_config, uid, "add_mode", 1)
api.uci_save(uci, appname) api.uci_save(uci, c_config)
http.redirect(api.url("node_config", uid)) http.redirect(api.url("node_config", uid))
end end
function clear_all_nodes() function clear_all_nodes()
uci:set(appname, '@global[0]', "enabled", "0") uci:set(c_config, '@global[0]', "enabled", "0")
uci:set(appname, '@global[0]', "socks_enabled", "0") uci:set(c_config, '@global[0]', "socks_enabled", "0")
uci:set(appname, '@global_haproxy[0]', "balancing_enable", "0") uci:set(c_config, '@global_haproxy[0]', "balancing_enable", "0")
uci:delete(appname, '@global[0]', "tcp_node") uci:delete(c_config, '@global[0]', "tcp_node")
uci:delete(appname, '@global[0]', "udp_node") uci:delete(c_config, '@global[0]', "udp_node")
uci:foreach(appname, "socks", function(t) uci:foreach(c_config, "socks", function(t)
uci:delete(appname, t[".name"]) uci:delete(c_config, t[".name"])
uci:set_list(appname, t[".name"], "autoswitch_backup_node", {}) uci:set_list(c_config, t[".name"], "autoswitch_backup_node", {})
end) end)
uci:foreach(appname, "haproxy_config", function(t) uci:foreach(c_config, "haproxy_config", function(t)
uci:delete(appname, t[".name"]) uci:delete(c_config, t[".name"])
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(appname, "acl_rule", function(t)
uci:delete(appname, t[".name"], "tcp_node") uci:delete(c_config, t[".name"], "tcp_node")
uci:delete(appname, t[".name"], "udp_node") uci:delete(c_config, t[".name"], "udp_node")
end) end)
uci:foreach(appname, "nodes", function(node) uci:foreach(c_config, "nodes", function(node)
uci:delete(appname, node['.name']) uci:delete(c_config, node['.name'])
end) end)
uci:foreach(appname, "subscribe_list", function(t) uci:foreach(c_config, "subscribe_list", function(t)
uci:delete(appname, t[".name"], "md5") uci:delete(c_config, t[".name"], "md5")
uci:delete(appname, t[".name"], "chain_proxy") uci:delete(c_config, t[".name"], "chain_proxy")
uci:delete(appname, t[".name"], "preproxy_node") uci:delete(c_config, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "to_node") uci:delete(c_config, t[".name"], "to_node")
end) end)
api.uci_save(uci, appname, true, true) api.uci_save(uci, c_config, true, true)
end end
function delete_select_nodes() function delete_select_nodes()
local ids = http.formvalue("ids") local ids = http.formvalue("ids")
local redirect = http.formvalue("redirect") local redirect = http.formvalue("redirect")
string.gsub(ids, '[^' .. "," .. ']+', function(w) string.gsub(ids, '[^' .. "," .. ']+', function(w)
local socks uci:foreach(c_config, "socks", function(t)
uci:foreach(appname, "socks", function(t)
if t["node"] == w then if t["node"] == w then
uci:delete(appname, t[".name"]) uci:delete(c_config, t[".name"])
socks = "Socks_" .. t[".name"]
end end
local changed = false local changed = false
local auto_switch_node_list = uci:get(appname, t[".name"], "autoswitch_backup_node") or {} local auto_switch_node_list = uci:get(c_config, t[".name"], "autoswitch_backup_node") or {}
for i = #auto_switch_node_list, 1, -1 do for i = #auto_switch_node_list, 1, -1 do
if w == auto_switch_node_list[i] then if w == auto_switch_node_list[i] then
table.remove(auto_switch_node_list, i) table.remove(auto_switch_node_list, i)
@@ -599,42 +601,40 @@ function delete_select_nodes()
end end
end end
if changed then if changed then
uci:set_list(appname, t[".name"], "autoswitch_backup_node", auto_switch_node_list) uci:set_list(c_config, t[".name"], "autoswitch_backup_node", auto_switch_node_list)
end end
end) end)
local tcp_node = uci:get(appname, "@global[0]", "tcp_node") or "" if (uci:get(c_config, "@global[0]", "tcp_node") or "") == w then
if tcp_node == w or tcp_node == socks then uci:delete(c_config, '@global[0]', "tcp_node")
uci:delete(appname, '@global[0]', "tcp_node")
end end
local udp_node = uci:get(appname, "@global[0]", "udp_node") or "" if (uci:get(c_config, "@global[0]", "udp_node") or "") == w then
if udp_node == w or udp_node == socks then uci:delete(c_config, '@global[0]', "udp_node")
uci:delete(appname, '@global[0]', "udp_node")
end end
uci:foreach(appname, "haproxy_config", function(t) uci:foreach(c_config, "haproxy_config", function(t)
if t["lbss"] == w then if t["lbss"] == w then
uci:delete(appname, t[".name"]) uci:delete(c_config, t[".name"])
end end
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(c_config, "acl_rule", function(t)
if t["tcp_node"] == w or t["tcp_node"] == socks then if t["tcp_node"] == w then
uci:delete(appname, t[".name"], "tcp_node") uci:delete(c_config, t[".name"], "tcp_node")
end end
if t["udp_node"] == w or t["udp_node"] == socks then if t["udp_node"] == w then
uci:delete(appname, t[".name"], "udp_node") uci:delete(c_config, t[".name"], "udp_node")
end end
end) end)
uci:foreach(appname, "nodes", function(t) uci:foreach(c_config, "nodes", function(t)
if t["preproxy_node"] == w then if t["preproxy_node"] == w then
uci:delete(appname, t[".name"], "preproxy_node") uci:delete(c_config, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "chain_proxy") uci:delete(c_config, t[".name"], "chain_proxy")
end end
if t["to_node"] == w then if t["to_node"] == w then
uci:delete(appname, t[".name"], "to_node") uci:delete(c_config, t[".name"], "to_node")
uci:delete(appname, t[".name"], "chain_proxy") uci:delete(c_config, t[".name"], "chain_proxy")
end end
local list_name = t["urltest_node"] and "urltest_node" or (t["balancing_node"] and "balancing_node") local list_name = t["urltest_node"] and "urltest_node" or (t["balancing_node"] and "balancing_node")
if list_name then if list_name then
local nodes = uci:get_list(appname, t[".name"], list_name) local nodes = uci:get_list(c_config, t[".name"], list_name)
if nodes then if nodes then
local changed = false local changed = false
local new_nodes = {} local new_nodes = {}
@@ -646,48 +646,48 @@ function delete_select_nodes()
end end
end end
if changed then if changed then
uci:set_list(appname, t[".name"], list_name, new_nodes) uci:set_list(c_config, t[".name"], list_name, new_nodes)
end end
end end
end end
if t["fallback_node"] == w or t["fallback_node"] == socks then if t["fallback_node"] == w then
uci:delete(appname, t[".name"], "fallback_node") uci:delete(c_config, t[".name"], "fallback_node")
end end
end) end)
uci:foreach(appname, "subscribe_list", function(t) uci:foreach(c_config, "subscribe_list", function(t)
if t["preproxy_node"] == w then if t["preproxy_node"] == w then
uci:delete(appname, t[".name"], "preproxy_node") uci:delete(c_config, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "chain_proxy") uci:delete(c_config, t[".name"], "chain_proxy")
end end
if t["to_node"] == w then if t["to_node"] == w then
uci:delete(appname, t[".name"], "to_node") uci:delete(c_config, t[".name"], "to_node")
uci:delete(appname, t[".name"], "chain_proxy") uci:delete(c_config, t[".name"], "chain_proxy")
end end
end) end)
if (uci:get(appname, w, "add_mode") or "0") == "2" then if (uci:get(c_config, w, "add_mode") or "0") == "2" then
local group = uci:get(appname, w, "group") or "" local group = uci:get(c_config, w, "group") or ""
if group ~= "" then if group ~= "" then
uci:foreach(appname, "subscribe_list", function(t) uci:foreach(c_config, "subscribe_list", function(t)
if t["remark"] == group then if t["remark"] == group then
uci:delete(appname, t[".name"], "md5") uci:delete(c_config, t[".name"], "md5")
end end
end) end)
end end
end end
uci:delete(appname, w) uci:delete(c_config, w)
end) end)
if redirect == "1" then if redirect == "1" then
api.uci_save(uci, appname) api.uci_save(uci, c_config)
http.redirect(api.url("node_list")) http.redirect(api.url("node_list"))
else else
api.uci_save(uci, appname, true, true) api.uci_save(uci, c_config, true, true)
end end
end end
function get_node() function get_node()
local id = http.formvalue("id") local id = http.formvalue("id")
local result = {} local result = {}
local show_node_info = api.uci_get_type("global_other", "show_node_info", "0") local show_node_info = uci:get(c_config, "@global_other[0]", "show_node_info") or "0"
local function add_is_ipv6_key(o) local function add_is_ipv6_key(o)
if o and o.address and show_node_info == "1" then if o and o.address and show_node_info == "1" then
@@ -700,12 +700,12 @@ function get_node()
end end
if id then if id then
result = uci:get_all(appname, id) result = uci:get_all(c_config, id)
add_is_ipv6_key(result) add_is_ipv6_key(result)
else else
local default_nodes = {} local default_nodes = {}
local other_nodes = {} local other_nodes = {}
uci:foreach(appname, "nodes", function(t) uci:foreach(c_config, "nodes", function(t)
add_is_ipv6_key(t) add_is_ipv6_key(t)
if not t.group or t.group == "" then if not t.group or t.group == "" then
default_nodes[#default_nodes + 1] = t default_nodes[#default_nodes + 1] = t
@@ -724,12 +724,12 @@ function reassign_group()
local group = http.formvalue("group") or "default" local group = http.formvalue("group") or "default"
for id in ids:gmatch("([^,]+)") do for id in ids:gmatch("([^,]+)") do
if group ~="" and group ~= "default" then if group ~="" and group ~= "default" then
api.sh_uci_set(appname, id, "group", group) api.sh_uci_set(c_config, id, "group", group)
else else
api.sh_uci_del(appname, id, "group") api.sh_uci_del(c_config, id, "group")
end end
end end
api.sh_uci_commit(appname) api.sh_uci_commit(c_config)
http_write_json({ status = "ok" }) http_write_json({ status = "ok" })
end end
@@ -737,7 +737,7 @@ function save_node_list_opt()
local option = http.formvalue("option") or "" local option = http.formvalue("option") or ""
local value = http.formvalue("value") or "" local value = http.formvalue("value") or ""
if option ~= "" then if option ~= "" then
api.sh_uci_set(appname, "@global_other[0]", option, value, true) api.sh_uci_set(c_config, "@global_other[0]", option, value, true)
end end
http_write_json({ status = "ok" }) http_write_json({ status = "ok" })
end end
@@ -760,8 +760,8 @@ function rollback_rules()
return return
end end
local bak_dir = "/tmp/bak_v2ray/" local bak_dir = "/tmp/bak_v2ray/"
local geo_dir = (uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/") local geo_dir = (uci:get(c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/")
local geo2rule = uci:get(appname, "@global_rules[0]", "geo2rule") or "0" local geo2rule = uci:get(c_config, "@global_rules[0]", "geo2rule") or "0"
fs.move(bak_dir .. arg_type .. ".dat", geo_dir .. arg_type .. ".dat") fs.move(bak_dir .. arg_type .. ".dat", geo_dir .. arg_type .. ".dat")
fs.rmdir(bak_dir) fs.rmdir(bak_dir)
if geo2rule == "1" and rules ~= "" then if geo2rule == "1" and rules ~= "" then
@@ -777,9 +777,9 @@ function server_update_config()
local data_t = jsonParse(data) or {} local data_t = jsonParse(data) or {}
if next(data_t) then if next(data_t) then
for k, v in pairs(data_t) do for k, v in pairs(data_t) do
uci:set(appname .. "_server", id, k, v) uci:set(c_config .. "_server", id, k, v)
end end
api.uci_save(uci, appname .. "_server") api.uci_save(uci, c_config .. "_server")
http_write_json_ok() http_write_json_ok()
return return
end end
@@ -914,7 +914,7 @@ function restore_backup()
fp:write(decoded) fp:write(decoded)
fp:close() fp:close()
if chunk_index + 1 == total_chunks then if chunk_index + 1 == total_chunks then
uci:revert(appname) uci:revert(c_config)
luci.sys.call("echo '' > /tmp/log/passwall.log") luci.sys.call("echo '' > /tmp/log/passwall.log")
api.log(" * PassWall 配置文件上传成功…") api.log(" * PassWall 配置文件上传成功…")
local temp_dir = '/tmp/passwall_bak' local temp_dir = '/tmp/passwall_bak'
@@ -957,7 +957,7 @@ function geo_view()
end end
local function get_rules(str, type) local function get_rules(str, type)
local rules_id = {} local rules_id = {}
uci:foreach(appname, "shunt_rules", function(s) uci:foreach(c_config, "shunt_rules", function(s)
local list local list
if type == "geoip" then list = s.ip_list else list = s.domain_list end if type == "geoip" then list = s.ip_list else list = s.domain_list end
for line in string.gmatch((list or ""), "[^\r\n]+") do for line in string.gmatch((list or ""), "[^\r\n]+") do
@@ -974,7 +974,7 @@ function geo_view()
end) end)
return rules_id return rules_id
end end
local geo_dir = (uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/") local geo_dir = (uci:get(c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/")
local geosite_path = geo_dir .. "/geosite.dat" local geosite_path = geo_dir .. "/geosite.dat"
local geoip_path = geo_dir .. "/geoip.dat" local geoip_path = geo_dir .. "/geoip.dat"
local geo_type, file_path, cmd local geo_type, file_path, cmd
@@ -1046,13 +1046,13 @@ function subscribe_manual()
http_write_json({ success = false, msg = "Missing section or URL, skip." }) http_write_json({ success = false, msg = "Missing section or URL, skip." })
return return
end end
local uci_url = api.sh_uci_get(appname, section, "url") local uci_url = api.sh_uci_get(c_config, section, "url")
if not uci_url or uci_url == "" then if not uci_url or uci_url == "" then
http_write_json({ success = false, msg = i18n.translate("Please save and apply before manually subscribing.") }) http_write_json({ success = false, msg = i18n.translate("Please save and apply before manually subscribing.") })
return return
end end
if uci_url ~= current_url then if uci_url ~= current_url then
api.sh_uci_set(appname, section, "url", current_url, true) api.sh_uci_set(c_config, section, "url", current_url, true)
end end
luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start " .. section .. " manual >/dev/null 2>&1 &") luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start " .. section .. " manual >/dev/null 2>&1 &")
http_write_json({ success = true, msg = "Subscribe triggered." }) http_write_json({ success = true, msg = "Subscribe triggered." })
@@ -1069,7 +1069,7 @@ function subscribe_manual_all()
local url_list = util.split(urls, ",") local url_list = util.split(urls, ",")
-- 检查是否存在未保存配置 -- 检查是否存在未保存配置
for i, section in ipairs(section_list) do for i, section in ipairs(section_list) do
local uci_url = api.sh_uci_get(appname, section, "url") local uci_url = api.sh_uci_get(c_config, section, "url")
if not uci_url or uci_url == "" then if not uci_url or uci_url == "" then
http_write_json({ success = false, msg = i18n.translate("Please save and apply before manually subscribing.") }) http_write_json({ success = false, msg = i18n.translate("Please save and apply before manually subscribing.") })
return return
@@ -1078,9 +1078,9 @@ function subscribe_manual_all()
-- 保存有变动的url -- 保存有变动的url
for i, section in ipairs(section_list) do for i, section in ipairs(section_list) do
local current_url = url_list[i] or "" local current_url = url_list[i] or ""
local uci_url = api.sh_uci_get(appname, section, "url") local uci_url = api.sh_uci_get(c_config, section, "url")
if current_url ~= "" and uci_url ~= current_url then if current_url ~= "" and uci_url ~= current_url then
api.sh_uci_set(appname, section, "url", current_url, true) api.sh_uci_set(c_config, section, "url", current_url, true)
end end
end end
luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start all manual >/dev/null 2>&1 &") luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start all manual >/dev/null 2>&1 &")
@@ -1091,10 +1091,10 @@ function flush_set()
local redirect = http.formvalue("redirect") or "0" local redirect = http.formvalue("redirect") or "0"
local reload = http.formvalue("reload") or "0" local reload = http.formvalue("reload") or "0"
if reload == "1" then if reload == "1" then
uci:set(appname, '@global[0]', "flush_set", "1") uci:set(c_config, '@global[0]', "flush_set", "1")
api.uci_save(uci, appname, true, true) api.uci_save(uci, c_config, true, true)
else else
api.sh_uci_set(appname, "@global[0]", "flush_set", "1", true) api.sh_uci_set(c_config, "@global[0]", "flush_set", "1", true)
end end
if redirect == "1" then if redirect == "1" then
http.redirect(api.url("log")) http.redirect(api.url("log"))
@@ -1103,9 +1103,9 @@ end
function fetch_certsha256() function fetch_certsha256()
local id = http.formvalue("id") or "" local id = http.formvalue("id") or ""
local address = (id ~= "") and uci:get(appname, id, "address") or "" local address = (id ~= "") and uci:get(c_config, id, "address") or ""
local port = (id ~= "") and uci:get(appname, id, "port") or 0 local port = (id ~= "") and uci:get(c_config, id, "port") or 0
local sni = (id ~= "") and uci:get(appname, id, "tls_serverName") or "" local sni = (id ~= "") and uci:get(c_config, id, "tls_serverName") or ""
sni = (sni ~= "") and sni or address sni = (sni ~= "") and sni or address
local protocol = uci:get(appname, id, "protocol") local protocol = uci:get(appname, id, "protocol")
local h3, timeout = false, 10 local h3, timeout = false, 10
@@ -1130,11 +1130,11 @@ function get_shunt_rules()
local result = {} local result = {}
if id then if id then
result = uci:get_all(appname, id) result = uci:get_all(c_config, id)
else else
local default_items = {} local default_items = {}
local other_items = {} local other_items = {}
uci:foreach(appname, "shunt_rules", function(t) uci:foreach(c_config, "shunt_rules", function(t)
if not t.group or t.group == "" then if not t.group or t.group == "" then
default_items[#default_items + 1] = t default_items[#default_items + 1] = t
else else
@@ -1153,7 +1153,7 @@ function add_shunt_rule()
local uid = add_name local uid = add_name
if add_name then if add_name then
local has = uci:get(appname, uid) local has = uci:get(c_config, uid)
if has then if has then
http_write_json_error({ message = i18n.translate("This ID already exists.") }) http_write_json_error({ message = i18n.translate("This ID already exists.") })
return return
@@ -1161,18 +1161,18 @@ function add_shunt_rule()
else else
uid = api.gen_random_char() uid = api.gen_random_char()
end end
uci:section(appname, "shunt_rules", uid) uci:section(c_config, "shunt_rules", uid)
local group = http.formvalue("group") local group = http.formvalue("group")
if group and group ~= "default" then if group and group ~= "default" then
uci:set(appname, uid, "group", group) uci:set(c_config, uid, "group", group)
end end
if redirect == "1" then if redirect == "1" then
api.uci_save(uci, appname) api.uci_save(uci, c_config)
http.redirect(api.url("shunt_rules", uid)) http.redirect(api.url("shunt_rules", uid))
else else
api.uci_save(uci, appname) api.uci_save(uci, c_config)
http_write_json_ok({uid = uid, redirect_url = api.url("shunt_rules", uid)}) http_write_json_ok({uid = uid, redirect_url = api.url("shunt_rules", uid)})
end end
end end
@@ -1181,17 +1181,17 @@ function delete_select_shunt_rules()
local ids = http.formvalue("ids") local ids = http.formvalue("ids")
local redirect = http.formvalue("redirect") local redirect = http.formvalue("redirect")
string.gsub(ids, '[^' .. "," .. ']+', function(w) string.gsub(ids, '[^' .. "," .. ']+', function(w)
uci:foreach(appname, "nodes", function(s) uci:foreach(c_config, "nodes", function(s)
if s["protocol"] and s["protocol"] == "_shunt" then if s["protocol"] and s["protocol"] == "_shunt" then
uci:delete(appname, s[".name"], w) uci:delete(c_config, s[".name"], w)
end end
end) end)
uci:delete(appname, w) uci:delete(c_config, w)
end) end)
if redirect == "1" then if redirect == "1" then
api.uci_save(uci, appname) api.uci_save(uci, c_config)
http.redirect(api.url("rule")) http.redirect(api.url("rule"))
else else
api.uci_save(uci, appname, true, true) api.uci_save(uci, c_config, true, true)
end end
end end
@@ -1,22 +1,17 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall"
local sys = api.sys
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
api.set_apply_on_parse(m)
s = m:section(TypedSection, "global", translate("ACLs"), "<font color='red'>" .. translate("ACLs is a tools which used to designate specific IP proxy mode.") .. "</font>") s = m:section(NamedSection, "@global[0]", "global", translate("ACLs"), "<font color='red'>" .. translate("ACLs is a tools which used to designate specific IP proxy mode.") .. "</font>")
s.anonymous = true
o = s:option(Flag, "acl_enable", translate("Main switch")) o = s:option(Flag, "acl_enable", translate("Main switch"))
o.rmempty = false o.rmempty = false
o.default = false o.default = false
-- [[ ACLs Settings ]]-- -- [[ ACLs Settings ]]--
local cfgname = "acl_rule" s = m:section(TypedSection, "acl_rule")
s = m:section(TypedSection, cfgname)
s.template = "cbi/tblsection" s.template = "cbi/tblsection"
s.sortable = true s.sortable = true
s.anonymous = true s.anonymous = true
@@ -28,7 +23,7 @@ function s.create(e, t)
luci.http.redirect(e.extedit:format(uid)) luci.http.redirect(e.extedit:format(uid))
end end
function s.remove(e, t) function s.remove(e, t)
sys.call("rm -rf /tmp/etc/passwall_tmp/dns_" .. t .. "*") api.sys.call("rm -rf /tmp/etc/passwall_tmp/dns_" .. t .. "*")
TypedSection.remove(e, t) TypedSection.remove(e, t)
end end
@@ -42,7 +37,7 @@ o = s:option(Value, "remarks", translate("Remarks"))
o.rmempty = true o.rmempty = true
local mac_t = {} local mac_t = {}
sys.net.mac_hints(function(e, t) api.sys.net.mac_hints(function(e, t)
mac_t[e] = { mac_t[e] = {
ip = t, ip = t,
mac = e mac = e
@@ -85,41 +80,6 @@ i.cfgvalue = function(t, n)
return translate("No Proxy") return translate("No Proxy")
end end
--[[ m:appendTemplate("/cbi/sortable", {sectiontype = s.sectiontype})
---- TCP No Redir Ports
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
---- UDP No Redir Ports
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"))
o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("80,443", "80,443")
o:value("80:65535", "80 " .. translate("or more"))
o:value("1:443", "443 " .. translate("or less"))
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("53", "53")
]]--
local sortable = Template(appname .. "/cbi/sortable")
sortable.api = api
sortable.target_cfgname = cfgname
m:append(sortable)
return api.return_map(m) return api.return_map(m)
@@ -1,26 +1,20 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall"
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
m.redirect = api.url("acl") m.redirect = api.url("acl")
api.set_apply_on_parse(m)
local cfgid = arg[1] if not arg[1] or not m:get(arg[1]) then
if not cfgid or not m:get(cfgid) then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
end end
m:append(Template(appname .. "/cbi/nodes_listvalue_com")) m:appendTemplate("/cbi/nodes_listvalue_com")
local fs = api.fs
local sys = api.sys
local has_singbox = api.finded_com("sing-box") local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
local has_gfwlist = fs.access("/usr/share/passwall/rules/gfwlist") local has_gfwlist = api.fs.access("/usr/share/passwall/rules/gfwlist")
local has_chnlist = fs.access("/usr/share/passwall/rules/chnlist") local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist")
local has_chnroute = fs.access("/usr/share/passwall/rules/chnroute") local has_chnroute = api.fs.access("/usr/share/passwall/rules/chnroute")
local port_validate = function(self, value, t) local port_validate = function(self, value, t)
return value:gsub("-", ":") return value:gsub("-", ":")
@@ -39,10 +33,10 @@ for _, v in pairs(nodes_table) do
end end
local socks_list = {} local socks_list = {}
m.uci:foreach(appname, "socks", function(s) m:foreach("socks", function(s)
if s.enabled == "1" and s.node then if s.enabled == "1" and s.node then
socks_list[#socks_list + 1] = { socks_list[#socks_list + 1] = {
id = "Socks_" .. s[".name"], id = s[".name"],
remark = translate("Socks Config") .. " " .. string.format("[%s %s]", s.port, translate("Port")), remark = translate("Socks Config") .. " " .. string.format("[%s %s]", s.port, translate("Port")),
group = "Socks" group = "Socks"
} }
@@ -50,7 +44,7 @@ m.uci:foreach(appname, "socks", function(s)
end) end)
-- [[ ACLs Settings ]]-- -- [[ ACLs Settings ]]--
s = m:section(NamedSection, cfgid, translate("ACLs"), translate("ACLs")) s = m:section(NamedSection, arg[1], translate("ACLs"), translate("ACLs"))
s.addremove = false s.addremove = false
s.dynamic = false s.dynamic = false
@@ -61,7 +55,7 @@ o.rmempty = false
---- Remarks ---- Remarks
o = s:option(Value, "remarks", translate("Remarks")) o = s:option(Value, "remarks", translate("Remarks"))
o.default = cfgid o.default = arg[1]
o.rmempty = false o.rmempty = false
o = s:option(Value, "interface", translate("Source Interface")) o = s:option(Value, "interface", translate("Source Interface"))
@@ -78,7 +72,7 @@ o.validate = function(self, value, section)
end end
local mac_t = {} local mac_t = {}
sys.net.mac_hints(function(e, t) api.sys.net.mac_hints(function(e, t)
mac_t[#mac_t + 1] = { mac_t[#mac_t + 1] = {
ip = t, ip = t,
mac = e mac = e
@@ -188,7 +182,7 @@ o:depends("mode", "1")
o.validate = port_validate o.validate = port_validate
o = s:option(DummyValue, "_hide_node_option", "") o = s:option(DummyValue, "_hide_node_option", "")
o.template = "passwall/cbi/hidevalue" o.template = m:template_path("/cbi/hidevalue")
o.value = "1" o.value = "1"
o:depends("mode", "0") o:depends("mode", "0")
o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" }) o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" })
@@ -204,7 +198,7 @@ o:depends({ _hide_node_option = "1", ['!reverse'] = true })
o = s:option(ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>") o = s:option(ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
o.default = "" o.default = ""
o:depends({ _hide_node_option = false, use_global_config = false }) o:depends({ _hide_node_option = false, use_global_config = false })
o.template = appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {} o.group = {}
o.remove = function(self, section) o.remove = function(self, section)
m:del(section, self.option) m:del(section, self.option)
@@ -212,7 +206,7 @@ o.remove = function(self, section)
end end
o = s:option(DummyValue, "_tcp_node_bool", "") o = s:option(DummyValue, "_tcp_node_bool", "")
o.template = "passwall/cbi/hidevalue" o.template = m:template_path("/cbi/hidevalue")
o.value = "1" o.value = "1"
o:depends({ tcp_node = "", ['!reverse'] = true }) o:depends({ tcp_node = "", ['!reverse'] = true })
@@ -221,7 +215,7 @@ o.default = ""
o:value("", translate("Close")) o:value("", translate("Close"))
o:value("tcp", translate("Same as the tcp node")) o:value("tcp", translate("Same as the tcp node"))
o:depends({ _tcp_node_bool = "1", _node_sel_other = "1" }) o:depends({ _tcp_node_bool = "1", _node_sel_other = "1" })
o.template = appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {"",""} o.group = {"",""}
o.remove = function(self, section) o.remove = function(self, section)
local v = s.fields["shunt_udp_node"]:formvalue(section) local v = s.fields["shunt_udp_node"]:formvalue(section)
@@ -248,7 +242,7 @@ o.write = function(self, section, value)
end end
o = s:option(DummyValue, "_udp_node_bool", "") o = s:option(DummyValue, "_udp_node_bool", "")
o.template = "passwall/cbi/hidevalue" o.template = m:template_path("/cbi/hidevalue")
o.value = "1" o.value = "1"
o:depends({ udp_node = "", ['!reverse'] = true }) o:depends({ udp_node = "", ['!reverse'] = true })
o:depends({ shunt_udp_node = "tcp" }) o:depends({ shunt_udp_node = "tcp" })
@@ -355,17 +349,17 @@ o:value("proxy", translate("Proxy"))
o:depends({ _udp_node_bool = "1" }) o:depends({ _udp_node_bool = "1" })
o = s:option(DummyValue, "switch_mode", " ") o = s:option(DummyValue, "switch_mode", " ")
o.template = appname .. "/global/proxy" o.template = m:template_path("/global/proxy")
o:depends({ _tcp_node_bool = "1" }) o:depends({ _tcp_node_bool = "1" })
-- Node → DNS Depends Settings -- Node → DNS Depends Settings
o = s:option(DummyValue, "_node_sel_shunt", "") o = s:option(DummyValue, "_node_sel_shunt", "")
o.template = appname .. "/cbi/hidevalue" o.template = m:template_path("/cbi/hidevalue")
o.value = "1" o.value = "1"
o:depends({ tcp_node = "__always__" }) o:depends({ tcp_node = "__always__" })
o = s:option(DummyValue, "_node_sel_other", "") o = s:option(DummyValue, "_node_sel_other", "")
o.template = appname .. "/cbi/hidevalue" o.template = m:template_path("/cbi/hidevalue")
o.value = "1" o.value = "1"
o:depends({ _node_sel_shunt = "1", ['!reverse'] = true }) o:depends({ _node_sel_shunt = "1", ['!reverse'] = true })
@@ -603,9 +597,6 @@ for k, v in pairs(nodes_table) do
end end
end end
local footer = Template(appname .. "/acl/config_footer") m:appendTemplate("/acl/config_footer", {section = arg[1]})
footer.api = api
footer.cfgid = cfgid
m:append(footer)
return api.return_map(m) return api.return_map(m)
@@ -1,21 +1,15 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local com = require "luci.passwall.com"
local appname = "passwall"
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) local com = require "luci.passwall.com"
api.set_apply_on_parse(m)
m = Map()
-- [[ App Settings ]]-- -- [[ App Settings ]]--
s = m:section(TypedSection, "global_app", translate("App Update")) s = m:section(NamedSection, "@global_app[0]", "global_app", translate("App Update"))
s.anonymous = true
local app_version = Template(appname .. "/app_update/app_version") s:appendTemplate("/app_update/app_version", {com = com})
app_version.api = api
app_version.config = m.config
app_version.com = com
s:append(app_version)
o = s:option(Flag, "github_proxy", translate("GitHub Proxy"), translate("Use gh-proxy instead of proxy nodes for component updates.")) o = s:option(Flag, "github_proxy", translate("GitHub Proxy"), translate("Use gh-proxy instead of proxy nodes for component updates."))
o.default = 0 o.default = 0
@@ -1,5 +1,4 @@
api = require "luci.passwall.api" api = require "luci.passwall.api"
appname = "passwall"
datatypes = api.datatypes datatypes = api.datatypes
local fs = api.fs local fs = api.fs
has_singbox = api.finded_com("sing-box") has_singbox = api.finded_com("sing-box")
@@ -10,10 +9,9 @@ local has_chnroute = fs.access("/usr/share/passwall/rules/chnroute")
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
api.set_apply_on_parse(m)
m:append(Template(appname .. "/cbi/nodes_listvalue_com")) m:appendTemplate("/cbi/nodes_listvalue_com")
local nodes_table = {} local nodes_table = {}
for _, e in ipairs(api.get_valid_nodes()) do for _, e in ipairs(api.get_valid_nodes()) do
@@ -51,7 +49,7 @@ socks_table[#socks_table + 1] = {
id = tcp_socks_server, id = tcp_socks_server,
remark = tcp_socks_server .. " - " .. translate("TCP Node") remark = tcp_socks_server .. " - " .. translate("TCP Node")
} }
m.uci:foreach(appname, "socks", function(s) m:foreach("socks", function(s)
if s.enabled == "1" and s.node then if s.enabled == "1" and s.node then
local id, remark local id, remark
for k, n in pairs(nodes_table) do for k, n in pairs(nodes_table) do
@@ -95,13 +93,9 @@ local doh_validate = function(self, value, t)
return nil, translatef("%s request address","DoH") .. " " .. translate("Format must be:") .. " URL,IP" return nil, translatef("%s request address","DoH") .. " " .. translate("Format must be:") .. " URL,IP"
end end
m:append(Template(appname .. "/global/status")) m:appendTemplate("/global/status")
global_cfgid = (m:get("@global[0]") or {})[".name"] or "" s = m:section(NamedSection, "@global[0]", "global")
s = m:section(TypedSection, "global")
s.anonymous = true
s.addremove = false
s:tab("Main", translate("Main")) s:tab("Main", translate("Main"))
@@ -111,13 +105,13 @@ o.rmempty = false
---- TCP Node ---- TCP Node
o = s:taboption("Main", ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>") o = s:taboption("Main", ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
o.template = appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
o:value("", translate("Close")) o:value("", translate("Close"))
o.group = {""} o.group = {""}
---- UDP Node ---- UDP Node
o = s:taboption("Main", ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>") o = s:taboption("Main", ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
o.template = appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
o:value("", translate("Close")) o:value("", translate("Close"))
o:value("tcp", translate("Same as the tcp node")) o:value("tcp", translate("Same as the tcp node"))
o.group = {"",""} o.group = {"",""}
@@ -146,15 +140,16 @@ o.write = function(self, section, value)
return m:set(section, "udp_node", value) return m:set(section, "udp_node", value)
end end
current_node_id = m:get(s.section, "tcp_node")
current_node = current_node_id and m:get(current_node_id) or {}
-- Shunt Start -- Shunt Start
if (has_singbox or has_xray) and #nodes_table > 0 then if (has_singbox or has_xray) and #nodes_table > 0 then
if #normal_list > 0 or #iface_list > 0 then if #normal_list > 0 or #iface_list > 0 then
current_node_id = m.uci:get(appname, global_cfgid, "tcp_node")
current_node = current_node_id and m.uci:get_all(appname, current_node_id) or {}
if current_node.protocol == "_shunt" then if current_node.protocol == "_shunt" then
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua") local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, { setfenv(shunt_lua, getfenv(1))(m, s, {
s_cfgid = s:cfgsections()[1], s_cfgid = s.section,
node_id = current_node_id, node_id = current_node_id,
node = current_node, node = current_node,
socks_list = socks_list, socks_list = socks_list,
@@ -200,12 +195,12 @@ o:depends({ tcp_node = "", ["!reverse"] = true })
-- Node → DNS Depends Settings -- Node → DNS Depends Settings
o = s:taboption("Main", DummyValue, "_node_sel_shunt", "") o = s:taboption("Main", DummyValue, "_node_sel_shunt", "")
o.template = appname .. "/cbi/hidevalue" o.template = m:template_path("/cbi/hidevalue")
o.value = "1" o.value = "1"
o:depends({ tcp_node = "__always__" }) o:depends({ tcp_node = "__always__" })
o = s:taboption("Main", DummyValue, "_node_sel_other", "") o = s:taboption("Main", DummyValue, "_node_sel_other", "")
o.template = appname .. "/cbi/hidevalue" o.template = m:template_path("/cbi/hidevalue")
o.value = "1" o.value = "1"
o:depends({ _node_sel_shunt = "1", ['!reverse'] = true }) o:depends({ _node_sel_shunt = "1", ['!reverse'] = true })
@@ -583,7 +578,7 @@ o:value("proxy", translate("Proxy"))
o.default = "proxy" o.default = "proxy"
o = s:taboption("Proxy", DummyValue, "switch_mode", " ") o = s:taboption("Proxy", DummyValue, "switch_mode", " ")
o.template = appname .. "/global/proxy" o.template = m:template_path("/global/proxy")
---- Check the transparent proxy component ---- Check the transparent proxy component
local handle = io.popen("lsmod") local handle = io.popen("lsmod")
@@ -662,11 +657,11 @@ end
s:tab("faq", "FAQ") s:tab("faq", "FAQ")
o = s:taboption("faq", DummyValue, "") o = s:taboption("faq", DummyValue, "")
o.template = appname .. "/global/faq" o.template = m:template_path("/global/faq")
s:tab("maintain", translate("Maintain")) s:tab("maintain", translate("Maintain"))
o = s:taboption("maintain", DummyValue, "") o = s:taboption("maintain", DummyValue, "")
o.template = appname .. "/global/backup" o.template = m:template_path("/global/backup")
-- [[ Socks Server ]]-- -- [[ Socks Server ]]--
o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch")) o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch"))
@@ -683,27 +678,26 @@ function s2.create(e, t)
luci.http.redirect(e.extedit:format(uid)) luci.http.redirect(e.extedit:format(uid))
end end
function s2.remove(e, t) function s2.remove(e, t)
local socks = "Socks_" .. t
local new_node = "" local new_node = ""
local node0 = m:get("@nodes[0]") or nil local node0 = m:get("@nodes[0]") or nil
if node0 then if node0 then
new_node = node0[".name"] new_node = node0[".name"]
end end
if (m:get("@global[0]", "tcp_node") or "") == socks then if (m:get("@global[0]", "tcp_node") or "") == t then
m:set('@global[0]', "tcp_node", new_node) m:set('@global[0]', "tcp_node", new_node)
end end
if (m:get("@global[0]", "udp_node") or "") == socks then if (m:get("@global[0]", "udp_node") or "") == t then
m:set('@global[0]', "udp_node", new_node) m:set('@global[0]', "udp_node", new_node)
end end
m.uci:foreach(appname, "acl_rule", function(s) m:foreach("acl_rule", function(s)
if s["tcp_node"] and s["tcp_node"] == socks then if s["tcp_node"] and s["tcp_node"] == t then
m:set(s[".name"], "tcp_node", "default") m:set(s[".name"], "tcp_node", "default")
end end
if s["udp_node"] and s["udp_node"] == socks then if s["udp_node"] and s["udp_node"] == t then
m:set(s[".name"], "udp_node", "default") m:set(s[".name"], "udp_node", "default")
end end
end) end)
m.uci:foreach(appname, "nodes", function(s) m:foreach("nodes", function(s)
local list_name = s["urltest_node"] and "urltest_node" or (s["balancing_node"] and "balancing_node") local list_name = s["urltest_node"] and "urltest_node" or (s["balancing_node"] and "balancing_node")
if list_name then if list_name then
local nodes = m.uci:get_list(appname, s[".name"], list_name) local nodes = m.uci:get_list(appname, s[".name"], list_name)
@@ -711,7 +705,7 @@ function s2.remove(e, t)
local changed = false local changed = false
local new_nodes = {} local new_nodes = {}
for _, node in ipairs(nodes) do for _, node in ipairs(nodes) do
if node ~= socks then if node ~= t then
table.insert(new_nodes, node) table.insert(new_nodes, node)
else else
changed = true changed = true
@@ -722,7 +716,7 @@ function s2.remove(e, t)
end end
end end
end end
if s["fallback_node"] == socks then if s["fallback_node"] == t then
m:del(s[".name"], "fallback_node") m:del(s[".name"], "fallback_node")
end end
end) end)
@@ -741,7 +735,7 @@ o.default = 1
o.rmempty = false o.rmempty = false
o = s2:option(ListValue, "node", translate("Socks Node")) o = s2:option(ListValue, "node", translate("Socks Node"))
o.template = appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {} o.group = {}
o = s2:option(DummyValue, "now_node", translate("Current Node")) o = s2:option(DummyValue, "now_node", translate("Current Node"))
@@ -757,7 +751,7 @@ o.cfgvalue = function(_, n)
end end
local n = 1 local n = 1
m.uci:foreach(appname, "socks", function(s) m:foreach("socks", function(s)
if s[".name"] == section then if s[".name"] == section then
return false return false
end end
@@ -819,10 +813,6 @@ for k, v in pairs(nodes_table) do
end end
end end
local footer = Template(appname .. "/global/footer") m:appendTemplate("/global/footer", {shunt_list = api.jsonc.stringify(shunt_list)})
footer.api = api
footer.global_cfgid = global_cfgid
footer.shunt_list = api.jsonc.stringify(shunt_list)
m:append(footer)
return api.return_map(m) return api.return_map(m)
@@ -1,7 +1,6 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = api.appname
local datatypes = api.datatypes local datatypes = api.datatypes
local net = require "luci.model.network".init() api.set_default_cbi()
local nodes_table = {} local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do for k, e in ipairs(api.get_valid_nodes()) do
@@ -15,18 +14,14 @@ for k, e in ipairs(api.get_valid_nodes()) do
end end
end end
api.set_default_cbi() m = Map(api.c_config, "HAPROXY " .. translate("Load Balancing"))
m = Map(appname, "HAPROXY " .. translate("Load Balancing")) m:appendTemplate("/cbi/nodes_value_com")
api.set_apply_on_parse(m)
m:append(Template(appname .. "/cbi/nodes_value_com"))
-- [[ Haproxy Settings ]]-- -- [[ Haproxy Settings ]]--
s = m:section(TypedSection, "global_haproxy", translate("Basic Settings")) s = m:section(NamedSection, "@global_haproxy[0]", "global_haproxy", translate("Basic Settings"))
s.anonymous = true
s:append(Template(appname .. "/haproxy/status")) s:appendTemplate("/haproxy/status")
---- Balancing Enable ---- Balancing Enable
o = s:option(Flag, "balancing_enable", translate("Enable Load Balancing")) o = s:option(Flag, "balancing_enable", translate("Enable Load Balancing"))
@@ -69,9 +64,9 @@ o:depends("balancing_enable", true)
---- Health Check Type ---- Health Check Type
o = s:option(ListValue, "health_check_type", translate("Health Check Type")) o = s:option(ListValue, "health_check_type", translate("Health Check Type"))
o.default = "passwall_logic" o.default = "script_logic"
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("passwall_logic", translate("URL Test") .. string.format("(passwall %s)", translate("Inner implement"))) o:value("script_logic", translate("URL Test") .. string.format("(passwall %s)", translate("Inner implement")))
o:depends("balancing_enable", true) o:depends("balancing_enable", true)
---- Passwall Inner implement Probe URL ---- Passwall Inner implement Probe URL
@@ -85,7 +80,7 @@ o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud
o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)") o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3] o.default = o.keylist[3]
o.description = translate("The URL used to detect the connection status.") o.description = translate("The URL used to detect the connection status.")
o:depends("health_check_type", "passwall_logic") o:depends("health_check_type", "script_logic")
---- Health Check Inter ---- Health Check Inter
o = s:option(Value, "health_check_inter", translate("Health Check Inter")) o = s:option(Value, "health_check_inter", translate("Health Check Inter"))
@@ -100,11 +95,10 @@ o.rawhtml = true
o.cfgvalue = function(t, n) o.cfgvalue = function(t, n)
return string.format('<span style="color: red">%s</span>', translate("When the URL test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid.")) return string.format('<span style="color: red">%s</span>', translate("When the URL test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid."))
end end
o:depends("health_check_type", "passwall_logic") o:depends("health_check_type", "script_logic")
-- [[ Balancing Settings ]]-- -- [[ Balancing Settings ]]--
local cfgname = "haproxy_config" s = m:section(TypedSection, "haproxy_config", translate("Node List"))
s = m:section(TypedSection, cfgname, translate("Node List"))
s.description = "<font color='red'>" .. s.description = "<font color='red'>" ..
translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") .. "<br>" .. translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") .. "<br>" ..
translate("Note that the node configuration parameters for load balancing must be consistent when use TCP health check type, otherwise it cannot be used normally!") .. "</font>" translate("Note that the node configuration parameters for load balancing must be consistent when use TCP health check type, otherwise it cannot be used normally!") .. "</font>"
@@ -133,7 +127,7 @@ o.rmempty = false
---- Node Address ---- Node Address
o = s:option(Value, "lbss", translate("Node Address")) o = s:option(Value, "lbss", translate("Node Address"))
o.template = appname .. "/cbi/nodes_value" o.template = m:template_path("/cbi/nodes_value")
o.group = {} o.group = {}
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
@@ -181,11 +175,8 @@ o:value(0, translate("Primary"))
o:value(1, translate("Standby")) o:value(1, translate("Standby"))
o.rmempty = false o.rmempty = false
local sortable = Template(appname .. "/cbi/sortable") m:appendTemplate("/cbi/sortable", {sectiontype = s.sectiontype})
sortable.api = api
sortable.target_cfgname = cfgname
m:append(sortable)
m:append(Template(appname .. "/haproxy/js")) m:appendTemplate("/haproxy/js")
return api.return_map(m) return api.return_map(m)
@@ -9,7 +9,7 @@ local current_node_id = data.node_id
local node_list = data.node_list or api.get_node_list() local node_list = data.node_list or api.get_node_list()
local groups = {} local groups = {}
m.uci:foreach(appname, "shunt_rules", function(s) m:foreach("shunt_rules", function(s)
if s.group and s.group ~= "" then if s.group and s.group ~= "" then
groups[s.group] = true groups[s.group] = true
end end
@@ -109,7 +109,7 @@ end
local shunt_group_val = m:get(current_node_id, "shunt_group") or "" local shunt_group_val = m:get(current_node_id, "shunt_group") or ""
shunt_group_val = shunt_group_val:lower() shunt_group_val = shunt_group_val:lower()
local shunt_rules = {} local shunt_rules = {}
m.uci:foreach(appname, "shunt_rules", function(e) m:foreach("shunt_rules", function(e)
local group = e.group or "" local group = e.group or ""
group = group:lower() group = group:lower()
if group == shunt_group_val then if group == shunt_group_val then
@@ -132,7 +132,7 @@ table.insert(shunt_rules, {
}) })
s2 = m:section(Table, shunt_rules, " ") s2 = m:section(Table, shunt_rules, " ")
s2.config = appname s2.config = m.config
s2.sectiontype = "shunt_option_list" s2.sectiontype = "shunt_option_list"
o = s2:option(DummyValue, "remarks", translate("Rule")) o = s2:option(DummyValue, "remarks", translate("Rule"))
@@ -146,7 +146,7 @@ o.cfgvalue = function(self, section)
end end
_node = s2:option(Value, "_node", translate("Node")) _node = s2:option(Value, "_node", translate("Node"))
_node.template = appname .. "/cbi/nodes_listvalue" _node.template = m:template_path("/cbi/nodes_listvalue")
_node.group = {"","","",""} _node.group = {"","","",""}
_node:value("", translate("Close (Not use)")) _node:value("", translate("Close (Not use)"))
_node:value("_default", translate("Use default node")) _node:value("_default", translate("Use default node"))
@@ -178,7 +178,7 @@ end
proxy_tag_node = s2:option(ListValue, "_proxy_tag", string.format('<a style="color:red" title="%s">%s</a>', proxy_tag_node = s2:option(ListValue, "_proxy_tag", string.format('<a style="color:red" title="%s">%s</a>',
translate("Set the node to be used as a pre-proxy.") .. "\n" .. translate("Each rule has a separate switch that controls whether this rule uses the pre-proxy or not."), translate("Set the node to be used as a pre-proxy.") .. "\n" .. translate("Each rule has a separate switch that controls whether this rule uses the pre-proxy or not."),
translate("Preproxy"))) translate("Preproxy")))
proxy_tag_node.template = appname .. "/cbi/nodes_listvalue" proxy_tag_node.template = m:template_path("/cbi/nodes_listvalue")
proxy_tag_node.group = {""} proxy_tag_node.group = {""}
proxy_tag_node:value("", translate("Close (Not use)")) proxy_tag_node:value("", translate("Close (Not use)"))
proxy_tag_node.cfgvalue = function(self, section) proxy_tag_node.cfgvalue = function(self, section)
@@ -203,10 +203,4 @@ for k1, v1 in pairs(node_list) do
end end
end end
local footer = Template(appname .. "/include/shunt_options") 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)})
footer.api = api
footer.config = m.config
footer.id = current_node_id
footer.s_cfgid = s_cfgid or current_node_id
footer.normal_list = api.jsonc.stringify(node_list.normal_list)
m:append(footer)
@@ -1,30 +1,22 @@
api = require "luci.passwall.api" api = require "luci.passwall.api"
appname = "passwall"
api.set_default_cbi() api.set_default_cbi()
m = Map(appname, translate("Node Config")) m = Map()
m.redirect = api.url("node_list") m.redirect = api.url("node_list")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
end end
fs = require "nixio.fs" fs = require "nixio.fs"
formvalue_key = "cbid." .. appname .. "." .. arg[1] .. "." formvalue_key = "cbid." .. m.config .. "." .. arg[1] .. "."
local header = Template(appname .. "/node_config/header") m:appendTemplate("/node_config/header", {section = arg[1]})
header.api = api m:appendTemplate("/cbi/nodes_multivalue_com")
header.config = m.config m:appendTemplate("/cbi/nodes_listvalue_com")
header.section = arg[1]
m:append(header)
m:append(Template(appname .. "/cbi/nodes_multivalue_com"))
m:append(Template(appname .. "/cbi/nodes_listvalue_com"))
groups = {} groups = {}
m.uci:foreach(appname, "nodes", function(s) m:foreach("nodes", function(s)
if s[".name"] ~= arg[1] then if s[".name"] ~= arg[1] then
if s.group and s.group ~= "" then if s.group and s.group ~= "" then
groups[s.group] = true groups[s.group] = true
@@ -32,13 +24,13 @@ m.uci:foreach(appname, "nodes", function(s)
end end
end) end)
s = m:section(NamedSection, arg[1], "nodes", "") s = m:section(NamedSection, arg[1], "nodes", translate("Node Config"))
s.addremove = false s.addremove = false
s.dynamic = false s.dynamic = false
o = s:option(DummyValue, "passwall", " ") o = s:option(DummyValue, "passwall", " ")
o.rawhtml = true o.rawhtml = true
o.template = "passwall/node_config/link_share_man" o.template = m:template_path("/node_config/link_share_man")
o.value = arg[1] o.value = arg[1]
o = s:option(Value, "remarks", translate("Node Remarks")) o = s:option(Value, "remarks", translate("Node Remarks"))
@@ -67,10 +59,10 @@ o.write = function(self, section, value)
m:set(section, self.option, value) m:set(section, self.option, value)
end end
local types_dir = "/usr/lib/lua/luci/model/cbi/passwall/client/type/" local types_dir = "/usr/lib/lua/luci/model/cbi/" .. api.appname .. "/client/type/"
s.val = {} s.val = {}
s.val["type"] = m.uci:get(appname, arg[1], "type") s.val["type"] = m:get(arg[1], "type")
s.val["protocol"] = m.uci:get(appname, arg[1], "protocol") s.val["protocol"] = m:get(arg[1], "protocol")
if luci.http.formvalue("cbi.submit") == "1" then if luci.http.formvalue("cbi.submit") == "1" then
local formvalue_type = luci.http.formvalue(formvalue_key .. "type") local formvalue_type = luci.http.formvalue(formvalue_key .. "type")
@@ -118,10 +110,6 @@ for index, value in ipairs(type_table) do
setfenv(p_func, getfenv(1))(m, s) setfenv(p_func, getfenv(1))(m, s)
end end
local footer = Template(appname .. "/node_config/footer") m:appendTemplate("/node_config/footer", {section = arg[1]})
footer.api = api
footer.config = m.config
footer.section = arg[1]
m:append(footer)
return api.return_map(m) return api.return_map(m)
@@ -1,14 +1,10 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall"
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
api.set_apply_on_parse(m)
-- [[ Other Settings ]]-- -- [[ Other Settings ]]--
s = m:section(TypedSection, "global_other") s = m:section(NamedSection, "@global_other[0]", "global_other")
s.anonymous = true
o = s:option(ListValue, "auto_detection_time", translate("Automatic detection delay")) o = s:option(ListValue, "auto_detection_time", translate("Automatic detection delay"))
o:value("0", translate("Close")) o:value("0", translate("Close"))
@@ -29,10 +25,7 @@ o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3] o.default = o.keylist[3]
if true then if true then
local o = Template(appname .. "/node_list/node_list") m:appendTemplate("/node_list/node_list")
o.map = m
o.api = api
m:append(o)
if luci.http.formvalue("cbi.submit") == "1" then if luci.http.formvalue("cbi.submit") == "1" then
local group_order = {} local group_order = {}
@@ -45,7 +38,7 @@ if true then
new_order[#new_order + 1] = w new_order[#new_order + 1] = w
end) end)
for idx, name in ipairs(new_order) do for idx, name in ipairs(new_order) do
m.uci:reorder(appname, name, idx - 1) m.uci:reorder(m.config, name, idx - 1)
end end
end end
end end
@@ -1,6 +1,6 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local uci = api.uci api.set_default_cbi()
local appname = "passwall"
local has_ss_rust = api.is_finded("sslocal") local has_ss_rust = api.is_finded("sslocal")
local has_singbox = api.finded_com("sing-box") local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
@@ -38,23 +38,16 @@ if has_hysteria2 then
table.insert(hysteria2_type, s) table.insert(hysteria2_type, s)
end end
api.set_default_cbi() m = Map()
m = Map(appname)
api.set_apply_on_parse(m)
function m.on_before_save(self) function m.on_before_save(self)
if self.no_commit then self:foreach("subscribe_list", function(e)
return
end
self.uci:foreach(appname, "subscribe_list", function(e)
self:del(e[".name"], "md5") self:del(e[".name"], "md5")
end) end)
end end
-- [[ Subscribe Settings ]]-- -- [[ Subscribe Settings ]]--
s = m:section(TypedSection, "global_subscribe", "") s = m:section(NamedSection, "@global_subscribe[0]", "global_subscribe")
s.anonymous = true
o = s:option(ListValue, "filter_keyword_mode", translate("Filter keyword Mode")) o = s:option(ListValue, "filter_keyword_mode", translate("Filter keyword Mode"))
o:value("0", translate("Close")) o:value("0", translate("Close"))
@@ -129,15 +122,13 @@ o.cfgvalue = function(self, section)
translate("Manual subscription All")) translate("Manual subscription All"))
end end
local cfgname = "subscribe_list" s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>")
s = m:section(TypedSection, cfgname, "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>")
s.addremove = true s.addremove = true
s.anonymous = true s.anonymous = true
s.sortable = true s.sortable = true
s.template = "cbi/tblsection" s.template = "cbi/tblsection"
s.extedit = api.url("node_subscribe_config", "%s") s.extedit = api.url("node_subscribe_config", "%s")
function s.create(e, t) function s.create(e, t)
m.no_commit = true
local uid = "sub_" .. api.gen_random_char(5) local uid = "sub_" .. api.gen_random_char(5)
TypedSection.create(e, uid) TypedSection.create(e, uid)
m:set(uid, "hysteria_up_mbps", "100") m:set(uid, "hysteria_up_mbps", "100")
@@ -154,7 +145,7 @@ o.validate = function(self, value, section)
return nil, translate("Remark cannot be empty.") return nil, translate("Remark cannot be empty.")
end end
local duplicate = false local duplicate = false
m.uci:foreach(appname, cfgname, function(e) m:foreach(s.sectiontype, function(e)
if e[".name"] ~= section and e["remark"] and e["remark"]:lower() == value:lower() then if e[".name"] ~= section and e["remark"] and e["remark"]:lower() == value:lower() then
duplicate = true duplicate = true
return false return false
@@ -168,9 +159,9 @@ end
o.write = function(self, section, value) o.write = function(self, section, value)
local old = m:get(section, self.option) or "" local old = m:get(section, self.option) or ""
if old ~= value then if old ~= value then
m.uci:foreach(appname, "nodes", function(e) m:foreach("nodes", function(e)
if e["group"] and e["group"]:lower() == old:lower() then if e["group"] and e["group"]:lower() == old:lower() then
m.uci:set(appname, e[".name"], "group", value) m:set(e[".name"], "group", value)
end end
if e["protocol"] and (e["protocol"] == "_balancing" or e["protocol"] == "_urltest") and e["node_group"] then if e["protocol"] and (e["protocol"] == "_balancing" or e["protocol"] == "_urltest") and e["node_group"] then
local gs = "" local gs = ""
@@ -182,7 +173,7 @@ o.write = function(self, section, value)
end end
end end
gs = api.trim(gs) gs = api.trim(gs)
m.uci:set(appname, e[".name"], "node_group", gs) m:set(e[".name"], "node_group", gs)
end end
end) end)
end end
@@ -200,7 +191,7 @@ o.cfgvalue = function(t, n)
end end
str = str ~= "" and "<br>" .. str or "" str = str ~= "" and "<br>" .. str or ""
local num = 0 local num = 0
m.uci:foreach(appname, "nodes", function(s) m:foreach("nodes", function(s)
if s["group"] and s["group"]:lower() == remark:lower() then if s["group"] and s["group"]:lower() == remark:lower() then
num = num + 1 num = num + 1
end end
@@ -229,11 +220,8 @@ o.cfgvalue = function(self, section)
section, translate("Manual subscription")) section, translate("Manual subscription"))
end end
local sortable = Template(appname .. "/cbi/sortable") m:appendTemplate("/cbi/sortable", {sectiontype = s.sectiontype})
sortable.api = api
sortable.target_cfgname = cfgname
m:append(sortable)
m:append(Template(appname .. "/node_subscribe/js")) m:appendTemplate("/node_subscribe/js")
return api.return_map(m) return api.return_map(m)
@@ -1,12 +1,8 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local uci = api.uci
local appname = "passwall"
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
m.redirect = api.url("node_subscribe") m.redirect = api.url("node_subscribe")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
@@ -16,7 +12,7 @@ function m.on_before_save(self)
self:del(arg[1], "md5") self:del(arg[1], "md5")
end end
m:append(Template(appname .. "/cbi/nodes_listvalue_com")) m:appendTemplate("/cbi/nodes_listvalue_com")
local has_ss_rust = api.is_finded("sslocal") local has_ss_rust = api.is_finded("sslocal")
local has_singbox = api.finded_com("sing-box") local has_singbox = api.finded_com("sing-box")
@@ -80,7 +76,7 @@ o.validate = function(self, value, section)
return nil, translate("Remark cannot be empty.") return nil, translate("Remark cannot be empty.")
end end
local duplicate = false local duplicate = false
m.uci:foreach(appname, "subscribe_list", function(e) m:foreach("subscribe_list", function(e)
if e[".name"] ~= section and e["remark"] and e["remark"]:lower() == value:lower() then if e[".name"] ~= section and e["remark"] and e["remark"]:lower() == value:lower() then
duplicate = true duplicate = true
return false return false
@@ -94,9 +90,9 @@ end
o.write = function(self, section, value) o.write = function(self, section, value)
local old = m:get(section, self.option) or "" local old = m:get(section, self.option) or ""
if old ~= value then if old ~= value then
m.uci:foreach(appname, "nodes", function(e) m:foreach("nodes", function(e)
if e["group"] and e["group"]:lower() == old:lower() then if e["group"] and e["group"]:lower() == old:lower() then
m.uci:set(appname, e[".name"], "group", value) self:set(e[".name"], "group", value)
end end
if e["protocol"] and (e["protocol"] == "_balancing" or e["protocol"] == "_urltest") and e["node_group"] then if e["protocol"] and (e["protocol"] == "_balancing" or e["protocol"] == "_urltest") and e["node_group"] then
local gs = "" local gs = ""
@@ -108,7 +104,7 @@ o.write = function(self, section, value)
end end
end end
gs = api.trim(gs) gs = api.trim(gs)
m.uci:set(appname, e[".name"], "node_group", gs) self:set(e[".name"], "node_group", gs)
end end
end) end)
end end
@@ -295,13 +291,13 @@ descrStr = translate(descrStr) .. "<br>" .. translate("Only support a layer of p
o1 = s:option(ListValue, "preproxy_node", translate("Preproxy Node")) o1 = s:option(ListValue, "preproxy_node", translate("Preproxy Node"))
o1:depends({ ["chain_proxy"] = "1" }) o1:depends({ ["chain_proxy"] = "1" })
o1.description = descrStr o1.description = descrStr
o1.template = appname .. "/cbi/nodes_listvalue" o1.template = m:template_path("/cbi/nodes_listvalue")
o1.group = {} o1.group = {}
o2 = s:option(ListValue, "to_node", translate("Landing Node")) o2 = s:option(ListValue, "to_node", translate("Landing Node"))
o2:depends({ ["chain_proxy"] = "2" }) o2:depends({ ["chain_proxy"] = "2" })
o2.description = descrStr o2.description = descrStr
o2.template = appname .. "/cbi/nodes_listvalue" o2.template = m:template_path("/cbi/nodes_listvalue")
o2.group = {} o2.group = {}
o3 = s:option(Value, "outbound_iface", translate("Outbound Interface")) o3 = s:option(Value, "outbound_iface", translate("Outbound Interface"))
@@ -1,5 +1,6 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall" api.set_default_cbi()
local fs = api.fs local fs = api.fs
local has_singbox = api.finded_com("sing-box") local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
@@ -8,15 +9,10 @@ local port_validate = function(self, value, t)
return value:gsub("-", ":") return value:gsub("-", ":")
end end
api.set_default_cbi() m = Map()
m = Map(appname)
api.set_apply_on_parse(m)
-- [[ Delay Settings ]]-- -- [[ Delay Settings ]]--
s = m:section(TypedSection, "global_delay", translate("Delay Settings")) s = m:section(NamedSection, "@global_delay[0]", "global_delay", translate("Delay Settings"))
s.anonymous = true
s.addremove = false
---- Open and close Daemon ---- Open and close Daemon
o = s:option(Flag, "start_daemon", translate("Open and close Daemon")) o = s:option(Flag, "start_daemon", translate("Open and close Daemon"))
@@ -61,9 +57,7 @@ for index, value in ipairs({"stop", "start", "restart"}) do
end end
-- [[ Forwarding Settings ]]-- -- [[ Forwarding Settings ]]--
s = m:section(TypedSection, "global_forwarding", translate("Forwarding Settings")) s = m:section(NamedSection, "@global_forwarding[0]", "global_forwarding", translate("Forwarding Settings"))
s.anonymous = true
s.addremove = false
---- TCP No Redir Ports ---- TCP No Redir Ports
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports")) o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
@@ -168,9 +162,7 @@ o:depends("ipv6_tproxy", true)
o.default = 0 o.default = 0
if has_xray then if has_xray then
s_xray = m:section(TypedSection, "global_xray", "Xray " .. translate("Settings")) s_xray = m:section(NamedSection, "@global_xray[0]", "global_xray", "Xray " .. translate("Settings"))
s_xray.anonymous = true
s_xray.addremove = false
o = s_xray:option(Flag, "fragment", translate("Fragment"), translate("TCP fragments, which can deceive the censorship system in some cases, such as bypassing SNI blacklists.")) o = s_xray:option(Flag, "fragment", translate("Fragment"), translate("TCP fragments, which can deceive the censorship system in some cases, such as bypassing SNI blacklists."))
o.default = 0 o.default = 0
@@ -204,7 +196,7 @@ if has_xray then
o.default = 0 o.default = 0
o.description = translate("Override the connection destination address with the sniffed domain.<br />Otherwise use sniffed domain for routing only.<br />If using shunt nodes, configure the domain shunt rules correctly.") o.description = translate("Override the connection destination address with the sniffed domain.<br />Otherwise use sniffed domain for routing only.<br />If using shunt nodes, configure the domain shunt rules correctly.")
local domains_excluded = string.format("/usr/share/%s/rules/domains_excluded", appname) local domains_excluded = string.format("/usr/share/%s/domains_excluded", m.config)
o = s_xray:option(TextValue, "excluded_domains", translate("Excluded Domains"), translate("If the traffic sniffing result is in this list, the destination address will not be overridden.")) o = s_xray:option(TextValue, "excluded_domains", translate("Excluded Domains"), translate("If the traffic sniffing result is in this list, the destination address will not be overridden."))
o.rows = 15 o.rows = 15
o.wrap = "off" o.wrap = "off"
@@ -227,11 +219,14 @@ if has_xray then
end end
s_xray_noise.remove = function(self, section) s_xray_noise.remove = function(self, section)
for k, v in pairs(self.children) do local o = m:get(section) or {}
v.rmempty = true if o[".type"] == self.sectiontype then
v.validate = nil for k, v in pairs(self.children) do
v.rmempty = true
v.validate = nil
end
TypedSection.remove(self, section)
end end
TypedSection.remove(self, section)
end end
o = s_xray_noise:option(Flag, "enabled", translate("Enable")) o = s_xray_noise:option(Flag, "enabled", translate("Enable"))
@@ -255,9 +250,7 @@ if has_xray then
end end
if has_singbox then if has_singbox then
s = m:section(TypedSection, "global_singbox", "Sing-Box " .. translate("Settings")) s = m:section(NamedSection, "@global_singbox[0]", "global_singbox", "Sing-Box " .. translate("Settings"))
s.anonymous = true
s.addremove = false
o = s:option(Flag, "record_fragment", "TLS Record " .. translate("Fragment"), o = s:option(Flag, "record_fragment", "TLS Record " .. translate("Fragment"),
translate("Split handshake data into multiple TLS records for better censorship evasion. Low overhead. Recommended to enable first.")) translate("Split handshake data into multiple TLS records for better censorship evasion. Low overhead. Recommended to enable first."))
@@ -1,16 +1,12 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall"
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
local has_singbox = api.finded_com("sing-box") local has_singbox = api.finded_com("sing-box")
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
api.set_apply_on_parse(m)
-- [[ Rule Settings ]]-- -- [[ Rule Settings ]]--
s = m:section(TypedSection, "global_rules", translate("Rule status")) s = m:section(NamedSection, "@global_rules[0]", "global_rules", translate("Rule status"))
s.anonymous = true
--[[ --[[
o = s:option(Flag, "adblock", translate("Enable adblock")) o = s:option(Flag, "adblock", translate("Enable adblock"))
@@ -143,12 +139,10 @@ for _, f in ipairs(flags) do
o.rmempty = false o.rmempty = false
end end
s:append(Template(appname .. "/rule/rule_version")) s:appendTemplate("/rule/rule_version")
if has_xray or has_singbox then if has_xray or has_singbox then
local o = Template(appname .. "/rule/shunt_rule_list") m:appendTemplate("/rule/shunt_rule_list")
o.api = api
m:append(o)
if luci.http.formvalue("cbi.submit") == "1" then if luci.http.formvalue("cbi.submit") == "1" then
local group_order = luci.http.formvaluetable("group.order") local group_order = luci.http.formvaluetable("group.order")
@@ -160,7 +154,7 @@ if has_xray or has_singbox then
new_order[#new_order + 1] = w new_order[#new_order + 1] = w
end) end)
for idx, name in ipairs(new_order) do for idx, name in ipairs(new_order) do
m.uci:reorder(appname, name, idx - 1) m.uci:reorder(m.config, name, idx - 1)
end end
end end
end end
@@ -1,18 +1,16 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = api.appname
local fs = api.fs local fs = api.fs
local sys = api.sys local sys = api.sys
local uci = api.uci local uci = api.uci
local datatypes = api.datatypes local datatypes = api.datatypes
local path = string.format("/usr/share/%s/rules/", appname) local path = string.format("/usr/share/%s/rules/", api.c_config)
local gfwlist_path = "/usr/share/passwall/rules/gfwlist" local gfwlist_path = "/usr/share/passwall/rules/gfwlist"
local chnlist_path = "/usr/share/passwall/rules/chnlist" local chnlist_path = "/usr/share/passwall/rules/chnlist"
local chnroute_path = "/usr/share/passwall/rules/chnroute" local chnroute_path = "/usr/share/passwall/rules/chnroute"
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
api.set_apply_on_parse(m)
function clean_text(text) function clean_text(text)
local nbsp = string.char(0xC2, 0xA0) -- 不间断空格(U+00A0) local nbsp = string.char(0xC2, 0xA0) -- 不间断空格(U+00A0)
@@ -319,9 +317,9 @@ if fs.access(chnroute_path) then
]], translate("Read List")) ]], translate("Read List"))
end end
m:append(Template(appname .. "/rule_list/js")) m:appendTemplate("/rule_list/js")
local geo_dir = (uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/") local geo_dir = (uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/")
local geosite_path = geo_dir .. "/geosite.dat" local geosite_path = geo_dir .. "/geosite.dat"
local geoip_path = geo_dir .. "/geoip.dat" local geoip_path = geo_dir .. "/geoip.dat"
if api.finded_com("geoview") and fs.access(geosite_path) and fs.access(geoip_path) then if api.finded_com("geoview") and fs.access(geosite_path) and fs.access(geoip_path) then
@@ -329,7 +327,7 @@ if api.finded_com("geoview") and fs.access(geosite_path) and fs.access(geoip_pat
s:tab("geoview", translate("Geo View")) s:tab("geoview", translate("Geo View"))
o = s:taboption("geoview", DummyValue, "_geoview_fieldset") o = s:taboption("geoview", DummyValue, "_geoview_fieldset")
o.rawhtml = true o.rawhtml = true
o.template = appname .. "/rule_list/geoview" o.template = m:template_path("/rule_list/geoview")
end end
end end
@@ -1,19 +1,17 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall"
local datatypes = api.datatypes
api.set_default_cbi() api.set_default_cbi()
m = Map(appname, "Sing-Box/Xray " .. translate("Shunt Rule")) local datatypes = api.datatypes
m = Map()
m.redirect = api.url("rule") m.redirect = api.url("rule")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
end end
m.on_before_save = function(self) function m.on_before_save(self)
m:set("@global[0]", "flush_set", "1") self:set("@global[0]", "flush_set", "1")
end end
-- Add inline CSS to map description -- Add inline CSS to map description
@@ -46,7 +44,7 @@ end
local remarks_lookup = {} local remarks_lookup = {}
local groups = {} local groups = {}
m.uci:foreach(appname, "shunt_rules", function(s) m:foreach("shunt_rules", function(s)
if s[".name"] ~= arg[1] then if s[".name"] ~= arg[1] then
if s.remarks then if s.remarks then
remarks_lookup[s.remarks] = s[".name"] remarks_lookup[s.remarks] = s[".name"]
@@ -57,7 +55,7 @@ m.uci:foreach(appname, "shunt_rules", function(s)
end end
end) end)
s = m:section(NamedSection, arg[1], "shunt_rules", "") s = m:section(NamedSection, arg[1], "shunt_rules", "Sing-Box/Xray " .. translate("Shunt Rule"))
s.addremove = false s.addremove = false
s.dynamic = false s.dynamic = false
@@ -1,18 +1,14 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = "passwall"
api.set_default_cbi() api.set_default_cbi()
m = Map(appname) m = Map()
m.redirect = api.url()
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
end end
m:append(Template(appname .. "/cbi/nodes_dynamiclist_com")) m:appendTemplate("/cbi/nodes_dynamiclist_com")
m:append(Template(appname .. "/cbi/nodes_listvalue_com")) m:appendTemplate("/cbi/nodes_listvalue_com")
local has_singbox = api.finded_com("sing-box") local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
@@ -50,14 +46,14 @@ socks_node = s:option(ListValue, "node", translate("Node"))
if auto_switch_tip then if auto_switch_tip then
socks_node.description = auto_switch_tip socks_node.description = auto_switch_tip
end end
socks_node.template = appname .. "/cbi/nodes_listvalue" socks_node.template = m:template_path("/cbi/nodes_listvalue")
socks_node.group = {} socks_node.group = {}
o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost.")) o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
o.default = "0" o.default = "0"
local n = 1 local n = 1
m.uci:foreach(appname, "socks", function(s) m:foreach("socks", function(s)
if s[".name"] == section then if s[".name"] == section then
return false return false
end end
@@ -91,7 +87,7 @@ o:value("batch", translate("Batch"))
o = s:option(DynamicList, "autoswitch_backup_node", translate("List of backup nodes")) o = s:option(DynamicList, "autoswitch_backup_node", translate("List of backup nodes"))
o:depends("backup_node_add_mode", "manual") o:depends("backup_node_add_mode", "manual")
o.template = appname .. "/cbi/nodes_dynamiclist" o.template = m:template_path("/cbi/nodes_dynamiclist")
o.group = {} o.group = {}
o.write = function(self, section, value) o.write = function(self, section, value)
local n = s.fields["node"]:formvalue(section) local n = s.fields["node"]:formvalue(section)
@@ -117,7 +113,7 @@ o:depends("backup_node_add_mode", "batch")
o.widget = "checkbox" o.widget = "checkbox"
o:value("default", translate("default")) o:value("default", translate("default"))
local groups = {} local groups = {}
m.uci:foreach(appname, "nodes", function(s) m:foreach("nodes", function(s)
if s.group and s.group ~= "" then if s.group and s.group ~= "" then
groups[s.group] = true groups[s.group] = true
end end
@@ -165,7 +161,7 @@ o.default = o.keylist[3]
o:depends("enable_autoswitch", true) o:depends("enable_autoswitch", true)
o = s:option(DummyValue, "btn") o = s:option(DummyValue, "btn")
o.template = appname .. "/socks_auto_switch/btn" o.template = m:template_path("/socks_auto_switch/btn")
o:depends("backup_node_add_mode", "manual") o:depends("backup_node_add_mode", "manual")
return api.return_map(m) return api.return_map(m)
@@ -105,7 +105,7 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o = s:option(MultiValue, _n("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://xtls.github.io/config/routing.html#balancerobject'>document</a>")) o = s:option(MultiValue, _n("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://xtls.github.io/config/routing.html#balancerobject'>document</a>"))
o:depends({ [_n("node_add_mode")] = "manual" }) o:depends({ [_n("node_add_mode")] = "manual" })
o.widget = "checkbox" o.widget = "checkbox"
o.template = appname .. "/cbi/nodes_multivalue" o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {} o.group = {}
for k1, v1 in pairs(node_list) do 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" then
@@ -171,7 +171,7 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o:value("", translate("Close(Not use)")) o:value("", translate("Close(Not use)"))
o:value("_direct", translate("Direct Connection")) o:value("_direct", translate("Direct Connection"))
o:depends({ [_n("protocol")] = "_balancing" }) o:depends({ [_n("protocol")] = "_balancing" })
o.template = appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
-- 最大 fallback 套娃层数 -- 最大 fallback 套娃层数
local MAX_FALLBACK_DEPTH = 3 local MAX_FALLBACK_DEPTH = 3
-- 检查是否会形成回环 -- 检查是否会形成回环
@@ -855,7 +855,7 @@ if not load_shunt_options then
o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy.")) o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false }) o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false })
o1.template = appname .. "/cbi/nodes_listvalue" o1.template = m:template_path("/cbi/nodes_listvalue")
o1.group = {} o1.group = {}
o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface")) o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface"))
@@ -867,7 +867,7 @@ if not load_shunt_options then
o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false }) o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false })
o2.template = appname .. "/cbi/nodes_listvalue" o2.template = m:template_path("/cbi/nodes_listvalue")
o2.group = {} o2.group = {}
for k1, v1 in pairs(node_list) do for k1, v1 in pairs(node_list) do
@@ -890,7 +890,7 @@ end
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)
if load_shunt_options then if load_shunt_options then
local current_node = m.uci:get_all(appname, arg[1]) or {} local current_node = m:get(arg[1]) or {}
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua") local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, { setfenv(shunt_lua, getfenv(1))(m, s, {
node_id = arg[1], node_id = arg[1],
@@ -104,7 +104,7 @@ if load_urltest_options then -- [[ URLTest Start ]]
o = s:option(MultiValue, _n("urltest_node"), translate("URLTest node list"), translate("List of nodes to test, <a target='_blank' href='https://sing-box.sagernet.org/configuration/outbound/urltest'>document</a>")) o = s:option(MultiValue, _n("urltest_node"), translate("URLTest node list"), translate("List of nodes to test, <a target='_blank' href='https://sing-box.sagernet.org/configuration/outbound/urltest'>document</a>"))
o:depends({ [_n("node_add_mode")] = "manual" }) o:depends({ [_n("node_add_mode")] = "manual" })
o.widget = "checkbox" o.widget = "checkbox"
o.template = appname .. "/cbi/nodes_multivalue" o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {} o.group = {}
for k1, v1 in pairs(node_list) do 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" then
@@ -876,7 +876,7 @@ if not load_shunt_options then
o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy.")) o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false }) o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false })
o1.template = appname .. "/cbi/nodes_listvalue" o1.template = m:template_path("/cbi/nodes_listvalue")
o1.group = {} o1.group = {}
o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface")) o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface"))
@@ -888,7 +888,7 @@ if not load_shunt_options then
o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false }) o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false })
o2.template = appname .. "/cbi/nodes_listvalue" o2.template = m:template_path("/cbi/nodes_listvalue")
o2.group = {} o2.group = {}
for k1, v1 in pairs(node_list) do for k1, v1 in pairs(node_list) do
@@ -911,7 +911,7 @@ end
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)
if load_shunt_options then if load_shunt_options then
local current_node = m.uci:get_all(appname, arg[1]) or {} local current_node = m:get(arg[1]) or {}
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua") local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, { setfenv(shunt_lua, getfenv(1))(m, s, {
node_id = arg[1], node_id = arg[1],
@@ -1,12 +1,9 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = api.appname
api.set_default_cbi() api.set_default_cbi()
m = Map("passwall_server", translate("Server-Side")) m = Map(api.s_config)
api.set_apply_on_parse(m)
t = m:section(NamedSection, "global", "global") t = m:section(NamedSection, "global", "global", translate("Server-Side"))
t.anonymous = true t.anonymous = true
t.addremove = false t.addremove = false
@@ -94,17 +91,9 @@ e = s_server:option(Flag, "log", translate("Log"))
e.default = "1" e.default = "1"
e.rmempty = false e.rmempty = false
local sortable = Template(appname .. "/cbi/sortable") m:appendTemplate("/cbi/sortable", {sectiontype = s_server.sectiontype})
sortable.api = api
sortable.appname = m.config
sortable.target_cfgname = s_server.sectiontype
m:append(sortable)
local server_list_status = Template(appname .. "/server/server_list_status") m:appendTemplate("/server/server_list_status", {sectiontype = s_server.sectiontype})
server_list_status.api = api
server_list_status.appname = m.config
server_list_status.sectiontype = s_server.sectiontype
m:append(server_list_status)
s_user = m:section(TypedSection, "user", translate("Users Manager")) s_user = m:section(TypedSection, "user", translate("Users Manager"))
s_user.anonymous = true s_user.anonymous = true
@@ -120,7 +109,7 @@ end
s_user.remove = function(self, section) s_user.remove = function(self, section)
local o = m:get(section) or {} local o = m:get(section) or {}
if o[".type"] == self.sectiontype then if o[".type"] == self.sectiontype then
m.uci:foreach(m.config, "server", function(o) m:foreach("server", function(o)
if o.user and section == o.user then if o.user and section == o.user then
m:set(o[".name"], "user", "") m:set(o[".name"], "user", "")
end end
@@ -150,12 +139,8 @@ e.width = "25%"
e = s_user:option(DummyValue, "uuid", "UUID") e = s_user:option(DummyValue, "uuid", "UUID")
e.width = "25%" e.width = "25%"
local sortable = Template(appname .. "/cbi/sortable") m:appendTemplate("/cbi/sortable", {sectiontype = s_user.sectiontype})
sortable.api = api
sortable.appname = m.config
sortable.target_cfgname = s_user.sectiontype
m:append(sortable)
m:append(Template(appname .. "/server/log")) m:appendTemplate("/server/log")
return api.return_map(m) return api.return_map(m)
@@ -1,35 +1,27 @@
api = require "luci.passwall.api" api = require "luci.passwall.api"
appname = api.appname
fs = api.fs
api.set_default_cbi() api.set_default_cbi()
m = Map("passwall_server", translate("Server Config")) m = Map(api.s_config)
m.redirect = api.url("server") m.redirect = api.url("server")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
end end
local header = Template(appname .. "/server/config_header") m:appendTemplate("/server/config_header", {section = arg[1]})
header.api = api
header.config = m.config
header.section = arg[1]
m:append(header)
m:append(Template(appname .. "/cbi/nodes_listvalue_com")) m:appendTemplate("/cbi/nodes_listvalue_com")
user_list = {} user_list = {}
m.uci:foreach(m.config, "user", function(s) m:foreach("user", function(s)
user_list[#user_list + 1] = s user_list[#user_list + 1] = s
end) end)
s = m:section(NamedSection, arg[1], "server", "") s = m:section(NamedSection, arg[1], "server", translate("Server Config"))
s.addremove = false s.addremove = false
s.dynamic = false s.dynamic = false
local types_dir = "/usr/lib/lua/luci/model/cbi/" .. appname .. "/server/type/" local types_dir = "/usr/lib/lua/luci/model/cbi/" .. api.appname .. "/server/type/"
s.val = m:get(arg[1]) or {} s.val = m:get(arg[1]) or {}
o = s:option(Flag, "enable", translate("Enable")) o = s:option(Flag, "enable", translate("Enable"))
@@ -43,7 +35,7 @@ o.rmempty = false
o = s:option(ListValue, "type", translate("Type")) o = s:option(ListValue, "type", translate("Type"))
local type_table = {} local type_table = {}
for filename in fs.dir(types_dir) do for filename in api.fs.dir(types_dir) do
table.insert(type_table, filename) table.insert(type_table, filename)
end end
table.sort(type_table, function(a, b) table.sort(type_table, function(a, b)
@@ -57,10 +49,6 @@ for index, value in ipairs(type_table) do
setfenv(p_func, getfenv(1))(m, s) setfenv(p_func, getfenv(1))(m, s)
end end
local footer = Template(appname .. "/server/config_footer") m:appendTemplate("/server/config_footer", {section = arg[1]})
footer.api = api
footer.config = m.config
footer.section = arg[1]
m:append(footer)
return api.return_map(m) return api.return_map(m)
@@ -441,7 +441,7 @@ o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks")) o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP")) o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface")) o:value("_iface", translate("Custom Interface"))
o.template = api.appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {"","","",""} o.group = {"","","",""}
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
@@ -424,7 +424,7 @@ o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks")) o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP")) o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface")) o:value("_iface", translate("Custom Interface"))
o.template = api.appname .. "/cbi/nodes_listvalue" o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {"","","",""} o.group = {"","","",""}
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
@@ -1,18 +1,14 @@
api = require "luci.passwall.api" api = require "luci.passwall.api"
appname = api.appname
fs = api.fs
api.set_default_cbi() api.set_default_cbi()
m = Map("passwall_server", translate("User Config")) m = Map(api.s_config)
m.redirect = api.url("server") m.redirect = api.url("server")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
end end
s = m:section(NamedSection, arg[1], "user", "") s = m:section(NamedSection, arg[1], "user", translate("User Config"))
s.addremove = false s.addremove = false
s.dynamic = false s.dynamic = false
+87 -51
View File
@@ -1,4 +1,7 @@
module("luci.passwall.api", package.seeall) module("luci.passwall.api", package.seeall)
appname = "passwall"
c_config = "passwall"
s_config = "passwall_server"
local com = require "luci.passwall.com" local com = require "luci.passwall.com"
nixio = require "nixio" nixio = require "nixio"
fs = require "nixio.fs" fs = require "nixio.fs"
@@ -30,10 +33,6 @@ function log(...)
end end
end end
function is_js_luci()
return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
end
function is_old_uci() function is_old_uci()
return sys.call("grep -E 'require[ \t]*\"uci\"' /usr/lib/lua/luci/model/uci.lua >/dev/null 2>&1") == 0 return sys.call("grep -E 'require[ \t]*\"uci\"' /usr/lib/lua/luci/model/uci.lua >/dev/null 2>&1") == 0
end end
@@ -214,7 +213,7 @@ function curl_direct(url, file, args)
end end
function curl_auto(url, file, args) function curl_auto(url, file, args)
local localhost_proxy = uci:get(appname, "@global[0]", "localhost_proxy") or "1" local localhost_proxy = uci:get(c_config, "@global[0]", "localhost_proxy") or "1"
if localhost_proxy == "1" then if localhost_proxy == "1" then
return curl_base(url, file, args) -- 当路由器本机开启代理时,采用passwall规则进行访问 return curl_base(url, file, args) -- 当路由器本机开启代理时,采用passwall规则进行访问
else else
@@ -482,11 +481,11 @@ function get_domain_from_url(url)
end end
function get_valid_nodes() function get_valid_nodes()
local show_node_info = uci_get_type("global_other", "show_node_info", "0") local show_node_info = uci:get(c_config, "@global_other[0]", "show_node_info") or "0"
local nodes = {} local nodes = {}
local default_nodes = {} local default_nodes = {}
local other_nodes = {} local other_nodes = {}
uci:foreach(appname, "nodes", function(e) uci:foreach(c_config, "nodes", function(e)
e.id = e[".name"] e.id = e[".name"]
if e.type and e.remarks then if e.type and e.remarks then
local type_name = e.type local type_name = e.type
@@ -559,7 +558,7 @@ function get_node_list()
socks_list = {}, socks_list = {},
normal_list = {}, normal_list = {},
} }
uci:foreach(appname, "socks", function(s) uci:foreach(c_config, "socks", function(s)
if s.enabled == "1" and s.node then if s.enabled == "1" and s.node then
node_list.socks_list[#node_list.socks_list + 1] = { node_list.socks_list[#node_list.socks_list + 1] = {
id = s[".name"], id = s[".name"],
@@ -658,23 +657,7 @@ function gen_random_char(length)
return sys.exec("echo -n $(head /dev/urandom | tr -dc A-Za-z0-9 | head -c %s)" % length) return sys.exec("echo -n $(head /dev/urandom | tr -dc A-Za-z0-9 | head -c %s)" % length)
end end
function uci_get_type(type, config, default) function chmod_755(file)
local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")")
if (value == nil or value == "") and (default and default ~= "") then
value = default
end
return value
end
function uci_get_type_id(id, config, default)
local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")")
if (value == nil or value == "") and (default and default ~= "") then
value = default
end
return value
end
local function chmod_755(file)
if file and file ~= "" then if file and file ~= "" then
if not fs.access(file, "rwx", "rx", "rx") then if not fs.access(file, "rwx", "rx", "rx") then
fs.chmod(file, 755) fs.chmod(file, 755)
@@ -683,7 +666,7 @@ local function chmod_755(file)
end end
function get_customed_path(e) function get_customed_path(e)
return uci_get_type("global_app", e .. "_file") return uci:get(c_config, "@global_app[0]", e .. "_file")
end end
function finded_com(e) function finded_com(e)
@@ -742,7 +725,7 @@ end
function get_app_path(app_name) function get_app_path(app_name)
if com[app_name] then if com[app_name] then
local def_path = com[app_name].default_path local def_path = com[app_name].default_path
local path = uci_get_type("global_app", app_name:gsub("%-","_") .. "_file") local path = uci:get(c_config, "@global_app[0]", app_name:gsub("%-","_") .. "_file")
path = path and (#path>0 and path or def_path) or def_path path = path and (#path>0 and path or def_path) or def_path
return path return path
end end
@@ -1020,7 +1003,7 @@ local default_file_tree = {
} }
local function get_api_json(url) local function get_api_json(url)
local gh_proxy = uci_get_type("global_app", "github_proxy", "0") local gh_proxy = uci:get(c_config, "@global_app[0]", "github_proxy") or "0"
local return_code, content local return_code, content
if gh_proxy == "1" then if gh_proxy == "1" then
url = "https://gh-proxy.org/" .. url url = "https://gh-proxy.org/" .. url
@@ -1144,7 +1127,7 @@ function to_download(app_name, url, size)
local _curl_args = clone(curl_args) local _curl_args = clone(curl_args)
table.insert(_curl_args, "--speed-limit 51200 --speed-time 15 --max-time 300") table.insert(_curl_args, "--speed-limit 51200 --speed-time 15 --max-time 300")
local gh_proxy = uci_get_type("global_app", "github_proxy", "0") local gh_proxy = uci:get(c_config, "@global_app[0]", "github_proxy") or "0"
local return_code, result local return_code, result
if gh_proxy == "1" then if gh_proxy == "1" then
url = "https://gh-proxy.org/" .. url url = "https://gh-proxy.org/" .. url
@@ -1302,7 +1285,7 @@ end
function to_check_self() function to_check_self()
local url = "https://raw.githubusercontent.com/Openwrt-Passwall/openwrt-passwall/main/luci-app-passwall/Makefile" local url = "https://raw.githubusercontent.com/Openwrt-Passwall/openwrt-passwall/main/luci-app-passwall/Makefile"
local tmp_file = "/tmp/passwall_makefile" local tmp_file = "/tmp/passwall_makefile"
local gh_proxy = uci_get_type("global_app", "github_proxy", "0") local gh_proxy = uci:get(c_config, "@global_app[0]", "github_proxy") or "0"
local return_code, result local return_code, result
if gh_proxy == "1" then if gh_proxy == "1" then
url = "https://gh-proxy.org/" .. url url = "https://gh-proxy.org/" .. url
@@ -1339,8 +1322,72 @@ function to_check_self()
} }
end end
function is_js_luci()
return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
end
function set_default_cbi() function set_default_cbi()
local cbi = require "luci.cbi" local cbi = require "luci.cbi"
if true then
--Map
local Map = cbi.Map
if not Map._passwall_default_cbi then
Map._passwall_default_cbi = true
local original_parse = Map.parse
function Map.parse(self, ...)
if is_js_luci() then
apply_redirect(self)
local old = self.on_after_save
self.on_after_save = function(map)
if old then old(map) end
map:set("@global[0]", "timestamp", os.time())
end
end
return original_parse(self, ...)
end
end
local original_init = Map.__init__
function Map.__init__(self, config, ...)
if not config then config = c_config end
original_init(self, config, ...)
self.api = require "luci.passwall.api"
end
function Map.foreach(self, stype, func)
self.uci:foreach(self.config, stype, func)
end
function Map.template_path(self, template)
return appname .. template
end
function Map.appendTemplate(self, template, data)
local obj = cbi.Template(self:template_path(template))
obj.map = self
if data and next(data) then
for k, v in pairs(data) do
obj[k] = v
end
end
self:append(obj)
return obj
end
end
if true then
--AbstractSection
local AbstractSection = cbi.AbstractSection
function AbstractSection.appendTemplate(self, template, data)
local obj = cbi.Template(self.map:template_path(template))
obj.map = self.map
obj.section = self
if data and next(data) then
for k, v in pairs(data) do
obj[k] = v
end
end
self:append(obj)
return obj
end
end
if true then if true then
--TextValue --TextValue
local TextValue = cbi.TextValue local TextValue = cbi.TextValue
@@ -1377,18 +1424,15 @@ function return_map(map)
if true then if true then
-- header -- header
local header = cbi.Template(appname .. "/cbi/header") local header = cbi.Template(appname .. "/cbi/header")
header.api = api header.map = map
header.config = map.config
table.insert(map.children, 1, header) table.insert(map.children, 1, header)
end end
if true then if true then
-- footer -- footer
local footer = cbi.Template(appname .. "/cbi/footer") local footer = cbi.Template(appname .. "/cbi/footer")
footer.api = api footer.map = map
footer.config = map.config
map:append(footer) map:append(footer)
end end
return map return map
end end
@@ -1569,20 +1613,8 @@ function format_go_time(input, default)
return result return result
end end
function set_apply_on_parse(map)
if not map then return end
if is_js_luci() then
apply_redirect(map)
local old = map.on_after_save
map.on_after_save = function(self)
if old then old(self) end
map:set("@global[0]", "timestamp", os.time())
end
end
end
function apply_redirect(m) function apply_redirect(m)
local tmp_uci_file = "/etc/config/" .. appname .. "_redirect" local tmp_uci_file = "/etc/config/" .. c_config .. "_redirect"
if m.redirect and m.redirect ~= "" then if m.redirect and m.redirect ~= "" then
if fs.access(tmp_uci_file) then if fs.access(tmp_uci_file) then
local redirect local redirect
@@ -1597,10 +1629,14 @@ function apply_redirect(m)
else else
fs.writefile(tmp_uci_file, "config redirect\n") fs.writefile(tmp_uci_file, "config redirect\n")
end end
local old = m.on_after_save
m.on_after_save = function(self) m.on_after_save = function(self)
if old then
old(self)
end
local redirect = self.redirect local redirect = self.redirect
if redirect and redirect ~= "" then if redirect and redirect ~= "" then
uci:set(appname .. "_redirect", "@redirect[0]", "url", redirect) uci:set(c_config .. "_redirect", "@redirect[0]", "url", redirect)
end end
end end
else else
@@ -1705,7 +1741,7 @@ end
function get_socks_backup_nodes(id) function get_socks_backup_nodes(id)
id = trim(id) id = trim(id)
if id == "" then return "" end if id == "" then return "" end
local socks = uci:get_all(appname, id) local socks = uci:get_all(c_config, id)
local nodes local nodes
if socks.backup_node_add_mode and socks.backup_node_add_mode == "batch" then if socks.backup_node_add_mode and socks.backup_node_add_mode == "batch" then
local node = {} local node = {}
@@ -1726,7 +1762,7 @@ function get_socks_backup_nodes(id)
end end
function get_core(field, candidates) function get_core(field, candidates)
local v = uci:get(appname, "@global_subscribe[0]", field) local v = uci:get(c_config, "@global_subscribe[0]", field)
if v and v ~= "" then if v and v ~= "" then
for _, c in ipairs(candidates) do for _, c in ipairs(candidates) do
if c[2] == v and c[1] then if c[2] == v and c[1] then
@@ -6,7 +6,7 @@ local sys = api.sys
local uci = api.uci local uci = api.uci
local jsonc = api.jsonc local jsonc = api.jsonc
local CONFIG = "passwall_server" local CONFIG = api.s_config
local CONFIG_PATH = "/tmp/etc/" .. CONFIG local CONFIG_PATH = "/tmp/etc/" .. CONFIG
local NFT_INCLUDE_FILE = CONFIG_PATH .. "/" .. CONFIG .. ".nft" local NFT_INCLUDE_FILE = CONFIG_PATH .. "/" .. CONFIG .. ".nft"
local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log" local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log"
@@ -9,7 +9,7 @@ function gen_config_server(node)
if node.users and #node.users > 0 then if node.users and #node.users > 0 then
users = {} users = {}
for i, v in ipairs(node.users) do for i, v in ipairs(node.users) do
local user = uci:get_all("passwall_server", v) or {} local user = uci:get_all(api.s_config, v) or {}
if user[".type"] == "user" then if user[".type"] == "user" then
users[user.username] = user.password users[user.username] = user.password
end end
@@ -74,7 +74,7 @@ function gen_config(var)
print("node 不能为空") print("node 不能为空")
return return
end end
local node = uci:get_all("passwall", node_id) local node = uci:get_all(api.c_config, node_id)
local local_tcp_redir_port = var["local_tcp_redir_port"] local local_tcp_redir_port = var["local_tcp_redir_port"]
local local_udp_redir_port = var["local_udp_redir_port"] local local_udp_redir_port = var["local_udp_redir_port"]
local local_socks_address = var["local_socks_address"] or "0.0.0.0" local local_socks_address = var["local_socks_address"] or "0.0.0.0"
@@ -9,7 +9,7 @@ function gen_config(var)
print("node 不能为空") print("node 不能为空")
return return
end end
local node = uci:get_all("passwall", node_id) local node = uci:get_all(api.c_config, node_id)
local run_type = var["run_type"] local run_type = var["run_type"]
local local_addr = var["local_addr"] local local_addr = var["local_addr"]
local local_port = var["local_port"] local local_port = var["local_port"]
@@ -6,7 +6,7 @@ local jsonc = api.jsonc
function gen_config_server(node) function gen_config_server(node)
local user = nil local user = nil
if node.user then if node.user then
user = uci:get_all("passwall_server", node.user) user = uci:get_all(api.s_config, node.user)
end end
local config = {} local config = {}
config.server_port = tonumber(node.port) config.server_port = tonumber(node.port)
@@ -40,7 +40,7 @@ function gen_config(var)
print("node 不能为空") print("node 不能为空")
return return
end end
local node = uci:get_all("passwall", node_id) local node = uci:get_all(api.c_config, node_id)
local server_host = var["server_host"] or (node.address or ""):lower() local server_host = var["server_host"] or (node.address or ""):lower()
local server_port = var["server_port"] or node.port local server_port = var["server_port"] or node.port
local local_addr = var["local_addr"] local local_addr = var["local_addr"]
@@ -3,7 +3,7 @@ local api = require "luci.passwall.api"
local uci = api.uci local uci = api.uci
local sys = api.sys local sys = api.sys
local jsonc = api.jsonc local jsonc = api.jsonc
local appname = "passwall" local appname = api.appname
local fs = api.fs local fs = api.fs
local ech_domain = {} local ech_domain = {}
@@ -34,7 +34,7 @@ function check_geoview()
if GEO_VAR.OK == 0 then if GEO_VAR.OK == 0 then
api.log("!!!注意:缺少 Geoview 组件或版本过低,Sing-Box 分流无法启用!") api.log("!!!注意:缺少 Geoview 组件或版本过低,Sing-Box 分流无法启用!")
else else
GEO_VAR.DIR = GEO_VAR.DIR or (uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/") GEO_VAR.DIR = GEO_VAR.DIR or (uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/")
GEO_VAR.SITE_PATH = GEO_VAR.SITE_PATH or (GEO_VAR.DIR .. "/geosite.dat") GEO_VAR.SITE_PATH = GEO_VAR.SITE_PATH or (GEO_VAR.DIR .. "/geosite.dat")
GEO_VAR.IP_PATH = GEO_VAR.IP_PATH or (GEO_VAR.DIR .. "/geoip.dat") GEO_VAR.IP_PATH = GEO_VAR.IP_PATH or (GEO_VAR.DIR .. "/geoip.dat")
if not fs.access(GEO_VAR.TO_SRS_PATH) then if not fs.access(GEO_VAR.TO_SRS_PATH) then
@@ -771,7 +771,7 @@ function gen_config_server(node)
if node.users and #node.users > 0 then if node.users and #node.users > 0 then
users = {} users = {}
for i, v in ipairs(node.users) do for i, v in ipairs(node.users) do
local user = uci:get_all("passwall_server", v) or {} local user = uci:get_all(api.s_config, v) or {}
if user[".type"] == "user" then if user[".type"] == "user" then
local u = {} local u = {}
if node.protocol == "mixed" or node.protocol == "socks" or node.protocol == "http" or node.protocol == "naive" then if node.protocol == "mixed" or node.protocol == "socks" or node.protocol == "http" or node.protocol == "naive" then
@@ -1008,7 +1008,7 @@ function gen_config_server(node)
} }
sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface)) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface))
else else
local outbound_node_t = uci:get_all("passwall", node.outbound_node) local outbound_node_t = uci:get_all(api.c_config, node.outbound_node)
if node.outbound_node == "_socks" or node.outbound_node == "_http" then if node.outbound_node == "_socks" or node.outbound_node == "_http" then
outbound_node_t = { outbound_node_t = {
type = node.type, type = node.type,
@@ -1104,7 +1104,7 @@ function gen_config(var)
local rule_set_table = {} local rule_set_table = {}
local COMMON = {} local COMMON = {}
local singbox_settings = uci:get_all(appname, "@global_singbox[0]") or {} local singbox_settings = uci:get_all(api.c_config, "@global_singbox[0]") or {}
local route = { local route = {
rules = {} rules = {}
@@ -1166,7 +1166,7 @@ function gen_config(var)
end end
if node_id then if node_id then
local node = uci:get_all(appname, node_id) local node = uci:get_all(api.c_config, node_id)
if node then if node then
if server_host and server_port then if server_host and server_port then
node.address = server_host node.address = server_host
@@ -1256,7 +1256,7 @@ function gen_config(var)
function get_node_by_id(node_id) function get_node_by_id(node_id)
if not node_id or node_id == "" or node_id == "nil" then return nil end if not node_id or node_id == "" or node_id == "nil" then return nil end
local section = uci:get_all(appname, node_id) or {} local section = uci:get_all(api.c_config, node_id) or {}
if section[".type"] == "socks" then if section[".type"] == "socks" then
local result = { local result = {
[".name"] = node_id, [".name"] = node_id,
@@ -1533,7 +1533,7 @@ function gen_config(var)
--shunt rule --shunt rule
local function foreach_shunt_rule(callback) local function foreach_shunt_rule(callback)
uci:foreach(appname, "shunt_rules", callback) uci:foreach(api.c_config, "shunt_rules", callback)
if use_gfw_list ~= "1" or chn_list ~= "0" then return end if use_gfw_list ~= "1" or chn_list ~= "0" then return end
@@ -1559,7 +1559,7 @@ function gen_config(var)
local bin = api.finded_com("geoview") local bin = api.finded_com("geoview")
if bin then if bin then
local geo_file = (uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/") .. "/geosite.dat" local geo_file = (uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/") .. "/geosite.dat"
if luci.sys.call('"' .. bin .. '" -type geosite -input "' .. geo_file .. '" | grep -q "^GFW$"') == 0 then if luci.sys.call('"' .. bin .. '" -type geosite -input "' .. geo_file .. '" | grep -q "^GFW$"') == 0 then
domain_list = (domain_list == "") and "geosite:gfw" or domain_list .. "\ngeosite:gfw" domain_list = (domain_list == "") and "geosite:gfw" or domain_list .. "\ngeosite:gfw"
end end
+11 -11
View File
@@ -3,7 +3,7 @@ local api = require "luci.passwall.api"
local uci = api.uci local uci = api.uci
local sys = api.sys local sys = api.sys
local jsonc = api.jsonc local jsonc = api.jsonc
local appname = "passwall" local appname = api.appname
local fs = api.fs local fs = api.fs
local GLOBAL = { local GLOBAL = {
@@ -493,7 +493,7 @@ function gen_config_server(node)
if node.users and #node.users > 0 then if node.users and #node.users > 0 then
users = {} users = {}
for i, v in ipairs(node.users) do for i, v in ipairs(node.users) do
local user = uci:get_all("passwall_server", v) or {} local user = uci:get_all(api.s_config, v) or {}
if user[".type"] == "user" then if user[".type"] == "user" then
local u = {} local u = {}
if node.protocol == "socks" or node.protocol == "http" then if node.protocol == "socks" or node.protocol == "http" then
@@ -625,7 +625,7 @@ function gen_config_server(node)
} }
sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface)) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface))
else else
local outbound_node_t = uci:get_all("passwall", node.outbound_node) local outbound_node_t = uci:get_all(api.c_config, node.outbound_node)
if node.outbound_node == "_socks" or node.outbound_node == "_http" then if node.outbound_node == "_socks" or node.outbound_node == "_http" then
outbound_node_t = { outbound_node_t = {
type = node.type, type = node.type,
@@ -901,7 +901,7 @@ function gen_config(var)
local outbounds = {} local outbounds = {}
local COMMON = {} local COMMON = {}
local xray_settings = uci:get_all(appname, "@global_xray[0]") or {} local xray_settings = uci:get_all(api.c_config, "@global_xray[0]") or {}
if xray_settings.fragment == "1" then if xray_settings.fragment == "1" then
local lengths, delays = {}, {} local lengths, delays = {}, {}
@@ -926,7 +926,7 @@ function gen_config(var)
if xray_settings.noise == "1" then if xray_settings.noise == "1" then
local noises = {} local noises = {}
uci:foreach(appname, "xray_noise_packets", function(n) uci:foreach(api.c_config, "xray_noise_packets", function(n)
if n.enabled == "1" then if n.enabled == "1" then
local noise = { local noise = {
rand = (n.type == "rand" and n.packet) and (n.packet:find("-", 1, true) and n.packet or tonumber(n.packet)) or nil, rand = (n.type == "rand" and n.packet) and (n.packet:find("-", 1, true) and n.packet or tonumber(n.packet)) or nil,
@@ -944,7 +944,7 @@ function gen_config(var)
end end
if node_id then if node_id then
local node = uci:get_all(appname, node_id) local node = uci:get_all(api.c_config, node_id)
local balancers = {} local balancers = {}
local rules = {} local rules = {}
if node then if node then
@@ -1001,7 +1001,7 @@ function gen_config(var)
function get_node_by_id(node_id) function get_node_by_id(node_id)
if not node_id or node_id == "" or node_id == "nil" then return nil end if not node_id or node_id == "" or node_id == "nil" then return nil end
local section = uci:get_all(appname, node_id) or {} local section = uci:get_all(api.c_config, node_id) or {}
if section[".type"] == "socks" then if section[".type"] == "socks" then
local result = { local result = {
[".name"] = node_id, [".name"] = node_id,
@@ -1374,7 +1374,7 @@ function gen_config(var)
--shunt rule --shunt rule
local function foreach_shunt_rule(callback) local function foreach_shunt_rule(callback)
uci:foreach(appname, "shunt_rules", callback) uci:foreach(api.c_config, "shunt_rules", callback)
if use_gfw_list ~= "1" or chn_list ~= "0" then return end if use_gfw_list ~= "1" or chn_list ~= "0" then return end
@@ -1400,7 +1400,7 @@ function gen_config(var)
local bin = api.finded_com("geoview") local bin = api.finded_com("geoview")
if bin then if bin then
local geo_file = (uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/") .. "/geosite.dat" local geo_file = (uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/") .. "/geosite.dat"
if luci.sys.call('"' .. bin .. '" -type geosite -input "' .. geo_file .. '" | grep -q "^GFW$"') == 0 then if luci.sys.call('"' .. bin .. '" -type geosite -input "' .. geo_file .. '" | grep -q "^GFW$"') == 0 then
domain_list = (domain_list == "") and "geosite:gfw" or domain_list .. "\ngeosite:gfw" domain_list = (domain_list == "") and "geosite:gfw" or domain_list .. "\ngeosite:gfw"
end end
@@ -1788,7 +1788,7 @@ function gen_config(var)
}) })
-- remote dns outbound -- remote dns outbound
local chn_list = uci:get(appname, "@global[0]", "chn_list") or "direct" local chn_list = uci:get(api.c_config, "@global[0]", "chn_list") or "direct"
remote_dns_outbound = { remote_dns_outbound = {
tag = "dns-out", tag = "dns-out",
protocol = "dns", protocol = "dns",
@@ -1979,7 +1979,7 @@ function gen_config(var)
if inbounds or outbounds then if inbounds or outbounds then
local config = { local config = {
env = (function() env = (function()
local asset_location = uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/" local asset_location = uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
return { XRAY_LOCATION_ASSET = asset_location } return { XRAY_LOCATION_ASSET = asset_location }
end)(), end)(),
log = { log = {
@@ -1,6 +1,7 @@
<% <%
local api = self.api local map = self.map
local cfgid = self.cfgid local api = map.api
local sid = self.section
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@@ -20,8 +21,8 @@ local cfgid = self.cfgid
return; return;
} }
let to_url = '<%=api.url("node_config")%>/' + node_select_value; let to_url = '<%=api.url("node_config")%>/' + node_select_value;
if (node_select_value.indexOf("Socks_") === 0) { if (node_select_value.indexOf("socks_") === 0) {
to_url = '<%=api.url("socks_config")%>/' + node_select_value.substring("Socks_".length); to_url = '<%=api.url("socks_config")%>/' + node_select_value;
} }
location.href = to_url; location.href = to_url;
} }
@@ -50,7 +51,7 @@ local cfgid = self.cfgid
const m = cbid.match(/\.(tcp|udp)_node$/); const m = cbid.match(/\.(tcp|udp)_node$/);
if (m && (m[1] === "tcp" || m[1] === "udp")) { if (m && (m[1] === "tcp" || m[1] === "udp")) {
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_redir_log") .. "?name=" .. cfgid%>&proto=' + m[1] + '\', \'_blank\')"><%:Log%></a>'; html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_redir_log") .. "?name=" .. sid%>&proto=' + m[1] + '\', \'_blank\')"><%:Log%></a>';
} }
html = '<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">' + html + '</div>' html = '<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">' + html + '</div>'
@@ -112,7 +113,7 @@ local cfgid = self.cfgid
logLink.href = "#"; logLink.href = "#";
logLink.className = "dns-log-link"; logLink.className = "dns-log-link";
logLink.style.marginLeft = "10px"; logLink.style.marginLeft = "10px";
logLink.setAttribute("onclick", "window.open('" + '<%=api.url("get_chinadns_log") .. "?flag=" .. cfgid%>' + "', '_blank')"); logLink.setAttribute("onclick", "window.open('" + '<%=api.url("get_chinadns_log") .. "?flag=" .. sid%>' + "', '_blank')");
select.insertAdjacentElement("afterend", logLink); select.insertAdjacentElement("afterend", logLink);
}; };
})(); })();
@@ -1,6 +1,7 @@
<div id="app_version"> <div id="app_version">
<% <%
local api = self.api local map = self.map
local api = map.api
local com = self.com local com = self.com
-%> -%>
@@ -1,3 +1,6 @@
<%
local map = self.map
-%>
<!-- map footer --> <!-- map footer -->
<script type="text/javascript"> <script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
@@ -1,11 +1,15 @@
<%
local map = self.map
local api = map.api
-%>
<!-- map header --> <!-- map header -->
<script src="<%=resource%>/view/<%=self.api.appname%>/cbi.js"></script> <script src="<%=resource%>/view/<%=api.appname%>/cbi.js"></script>
<script src="<%=resource%>/view/<%=self.api.appname%>/func.js"></script> <script src="<%=resource%>/view/<%=api.appname%>/func.js"></script>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
function update_config(cfgid, data, redirect_url) { function update_config(cfgid, data, redirect_url) {
XHR.get('<%=self.api.url("update_config")%>', { XHR.get('<%=api.url("update_config")%>', {
id: cfgid, id: cfgid,
data: JSON.stringify(data) data: JSON.stringify(data)
}, },
@@ -1,7 +1,8 @@
<% <%
local api = self.api local map = self.map
local appname = self.appname or api.appname local sectiontype = self.sectiontype
local target_cfgname = self.target_cfgname local api = map.api
local appname = self.appname or map.config
-%> -%>
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js"></script> <script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js"></script>
<style> <style>
@@ -37,7 +38,7 @@ local target_cfgname = self.target_cfgname
} }
@media screen and (max-width: 1152px) { @media screen and (max-width: 1152px) {
#cbi-<%=appname%>-<%=target_cfgname%> .cbi-section-table-titles { #cbi-<%=appname%>-<%=sectiontype%> .cbi-section-table-titles {
display: none !important; display: none !important;
} }
} }
@@ -47,7 +48,7 @@ local target_cfgname = self.target_cfgname
//Add drag-and-drop sorting //Add drag-and-drop sorting
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
function initSortableForTable() { function initSortableForTable() {
var section = document.getElementById("cbi-<%=appname%>-<%=target_cfgname%>"); var section = document.getElementById("cbi-<%=appname%>-<%=sectiontype%>");
if (!section) return; if (!section) return;
// === insert drag handle === // === insert drag handle ===
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
-%> -%>
<div class="cbi-section"> <div class="cbi-section">
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
-%> -%>
<style> <style>
.dns-con { .dns-con {
@@ -1,6 +1,8 @@
<% <%
local api = self.api local map = self.map
local appname = api.appname local api = map.api
local appname = map.config
local sid = "@global[0]"
-%> -%>
<style> <style>
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
@@ -35,15 +37,17 @@ local appname = api.appname
</style> </style>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
let global_id = "<%=sid%>";
const shunt_list = JSON.parse('<%=self.shunt_list%>'); const shunt_list = JSON.parse('<%=self.shunt_list%>');
function to_edit_node(btn) { function to_edit_node(btn, stype) {
if (!btn) return; if (!btn) return;
const idReg = /^cbid\..*\..*node$/; if (!stype) return;
let hidden_select = null; let hidden_select = null;
const container = btn.closest('#cbi-<%=appname%>-global') || btn.closest('#cbi-<%=appname%>-socks'); const stype_dom = document.getElementById("cbi-<%=appname%>-" + stype);
if (!container) return null; if (!stype_dom) return;
const selects = container.querySelectorAll('select[id^="cbid."][id*="."][id$="node"]'); const selects = stype_dom.querySelectorAll('select[id^="cbid."][id*="."][id$="node"]');
const idReg = /^cbid\..*\..*node$/;
for (const sel of selects) { for (const sel of selects) {
if ( idReg.test(sel.id) && getComputedStyle(sel).display === "none" && (sel.compareDocumentPosition(btn) & Node.DOCUMENT_POSITION_FOLLOWING)) { if ( idReg.test(sel.id) && getComputedStyle(sel).display === "none" && (sel.compareDocumentPosition(btn) & Node.DOCUMENT_POSITION_FOLLOWING)) {
hidden_select = sel; hidden_select = sel;
@@ -94,8 +98,7 @@ local appname = api.appname
); );
} }
let global_id = null; const global = document.getElementById("cbi-<%=appname%>-" + global_id);
const global = document.getElementById("cbi-<%=appname%>-global");
if (global) { if (global) {
// 分流规则节点提前加入 “编辑” 占位符,以保证节点列表左对齐 // 分流规则节点提前加入 “编辑” 占位符,以保证节点列表左对齐
document.querySelectorAll('.td[data-widget="nodes_listvalue"][data-name="_node"] > div').forEach(container => { document.querySelectorAll('.td[data-widget="nodes_listvalue"][data-name="_node"] > div').forEach(container => {
@@ -109,10 +112,7 @@ local appname = api.appname
await delay(100); await delay(100);
const node = global.getElementsByClassName("cbi-section-node")[0]; const all_node = global.querySelectorAll("[id]");
const node_id = node.getAttribute("id");
global_id = node_id;
const all_node = node.querySelectorAll("[id]");
const reg1 = /^cbid\..*node\.main$/; const reg1 = /^cbid\..*node\.main$/;
//const reg1 = /^cbid\..*\.(tcp_node|udp_node)\.main$/; //const reg1 = /^cbid\..*\.(tcp_node|udp_node)\.main$/;
@@ -129,7 +129,7 @@ local appname = api.appname
continue; continue;
} }
let html = '<a href="#" onclick="return to_edit_node(this);"><%:Edit%></a>'; let html = '<a href="#" onclick="return to_edit_node(this, global_id);"><%:Edit%></a>';
const m = cbid.match(/\.(tcp|udp)_node$/); const m = cbid.match(/\.(tcp|udp)_node$/);
if (m && (m[1] === "tcp" || m[1] === "udp")) { if (m && (m[1] === "tcp" || m[1] === "udp")) {
@@ -149,7 +149,7 @@ local appname = api.appname
const socks = document.getElementById("cbi-<%=appname%>-socks"); const socks = document.getElementById("cbi-<%=appname%>-socks");
if (socks) { if (socks) {
const socks_enabled_dom = document.getElementById(global_id + "-socks_enabled"); const socks_enabled_dom = document.getElementById("cbi-<%=appname%>-" + global_id + "-socks_enabled");
const descr = socks.getElementsByClassName("cbi-section-descr")[0]; const descr = socks.getElementsByClassName("cbi-section-descr")[0];
descr.replaceWith(socks_enabled_dom); descr.replaceWith(socks_enabled_dom);
const rows = socks.getElementsByClassName("cbi-section-table-row"); const rows = socks.getElementsByClassName("cbi-section-table-row");
@@ -164,7 +164,7 @@ local appname = api.appname
const node_select = document.getElementById(dom_id); const node_select = document.getElementById(dom_id);
if (!node_select) continue; if (!node_select) continue;
let html = '<a href="#" onclick="return to_edit_node(this);"><%:Edit%></a>'; let html = '<a href="#" onclick="return to_edit_node(this, \'socks\');"><%:Edit%></a>';
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>'; html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>';
node_select.insertAdjacentHTML("afterend", node_select.insertAdjacentHTML("afterend",
@@ -249,7 +249,7 @@ local appname = api.appname
})(); })();
document.addEventListener("DOMContentLoaded", () => setTimeout(() => { document.addEventListener("DOMContentLoaded", () => setTimeout(() => {
const hiddenSelect = document.getElementById("cbid.<%=appname%>.<%=self.global_cfgid%>.tcp_node"); const hiddenSelect = document.getElementById("cbid.<%=appname%>.<%=sid%>.tcp_node");
let o_val = hiddenSelect.value let o_val = hiddenSelect.value
const o_hasItem = shunt_list.find(element => element.id == o_val); const o_hasItem = shunt_list.find(element => element.id == o_val);
hiddenSelect.addEventListener("change", function(el){ hiddenSelect.addEventListener("change", function(el){
@@ -257,7 +257,7 @@ local appname = api.appname
const new_hasItem = shunt_list.find(element => element.id == new_val); const new_hasItem = shunt_list.find(element => element.id == new_val);
if (new_hasItem) { if (new_hasItem) {
XHR.get('<%=api.url("update_config")%>', { XHR.get('<%=api.url("update_config")%>', {
id: "<%=self.global_cfgid%>", id: "<%=sid%>",
data: JSON.stringify({ data: JSON.stringify({
tcp_node: new_val tcp_node: new_val
}) })
@@ -272,8 +272,8 @@ local appname = api.appname
}); });
} else { } else {
try { try {
document.getElementById("tab.<%=appname%>.<%=self.global_cfgid%>.Shunt").classList.add('shunt-tab-hidden'); document.getElementById("tab.<%=appname%>.<%=sid%>.Shunt").classList.add('shunt-tab-hidden');
document.getElementById("tab.<%=appname%>.<%=self.global_cfgid%>.Shunt").style.display = "none"; document.getElementById("tab.<%=appname%>.<%=sid%>.Shunt").style.display = "none";
} catch (error) {} } catch (error) {}
try { try {
document.querySelector('li[data-tab*="Shunt"]').classList.add('shunt-tab-hidden'); document.querySelector('li[data-tab*="Shunt"]').classList.add('shunt-tab-hidden');
@@ -281,7 +281,7 @@ local appname = api.appname
} catch (error) {} } catch (error) {}
} }
}); });
let shunt_taboption = document.getElementById("container.<%=appname%>.<%=self.global_cfgid%>.Shunt"); let shunt_taboption = document.getElementById("container.<%=appname%>.<%=sid%>.Shunt");
if (shunt_taboption) { if (shunt_taboption) {
let shunt_option_list = document.getElementById("cbi-<%=appname%>-shunt_option_list"); let shunt_option_list = document.getElementById("cbi-<%=appname%>-shunt_option_list");
if (shunt_option_list) { if (shunt_option_list) {
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
-%> -%>
<style> <style>
@@ -1,6 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local appname = api.appname local appname = map.config
-%> -%>
<style> <style>
@@ -1,7 +1,8 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local haproxy_enable = api.uci_get_type("global_haproxy", "balancing_enable", "0") local api = map.api
local console_port = api.uci_get_type("global_haproxy", "console_port", "") local haproxy_enable = map:get("@global_haproxy[0]", "balancing_enable") or "0"
local console_port = map:get("@global_haproxy[0]", "console_port") or ""
-%> -%>
<p id="_status"></p> <p id="_status"></p>
@@ -1,3 +1,10 @@
<%
local map = self.map
local api = map.api
local config = map.config
local id = self.id
local s_cfgid = self.s_cfgid
-%>
<style> <style>
.hidden { .hidden {
display: none !important; display: none !important;
@@ -54,15 +61,15 @@
} }
} }
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
waitForElement('select[name*="<%=self.config%>"][name*="shunt_group"]', function(el) { waitForElement('select[name*="<%=config%>"][name*="shunt_group"]', function(el) {
let o_val = el.value; let o_val = el.value;
el.addEventListener("change", () => { el.addEventListener("change", () => {
el.blur(); el.blur();
if (o_val != el.value) { if (o_val != el.value) {
let save = true; let save = true;
if (save) { if (save) {
update_config("<%=self.id%>", { update_config("<%=id%>", {
shunt_group: getOption("<%=self.config%>", "<%=self.s_cfgid%>", "shunt_group").value, shunt_group: getOption("<%=config%>", "<%=s_cfgid%>", "shunt_group").value,
}, get_current_url()); }, get_current_url());
} }
} }
@@ -1,10 +1,16 @@
<%
local map = self.map
local api = map.api
local sid = self.section
local config = map.config
-%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
let node_id = "<%=self.section%>"; let node_id = "<%=sid%>";
let node_config_url = '<%=self.api.url("node_config")%>/' + node_id; let node_config_url = '<%=api.url("node_config")%>/' + node_id;
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
waitForElement('select[name*="<%=self.config%>"][name*="type"]', function(el) { waitForElement('select[name*="<%=config%>"][name*="type"]', function(el) {
let o_val = el.value; let o_val = el.value;
el.addEventListener("change", () => { el.addEventListener("change", () => {
el.blur(); el.blur();
@@ -18,16 +24,16 @@
} }
*/ */
update_config(node_id, { update_config(node_id, {
remarks: getOption("<%=self.config%>", "<%=self.section%>", "remarks").value, remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=self.config%>", "<%=self.section%>", "group").value, group: getOption("<%=config%>", "<%=sid%>", "group").value,
type: getOption("<%=self.config%>", "<%=self.section%>", "type").value, type: getOption("<%=config%>", "<%=sid%>", "type").value,
//protocol: '' //protocol: ''
}, node_config_url); }, node_config_url);
} }
} }
}); });
}); });
waitForElement('select[name*="<%=self.config%>"][name*="protocol"]', function(el) { waitForElement('select[name*="<%=config%>"][name*="protocol"]', function(el) {
let o_val = el.value; let o_val = el.value;
el.addEventListener("change", () => { el.addEventListener("change", () => {
el.blur(); el.blur();
@@ -43,9 +49,9 @@
} }
*/ */
update_config(node_id, { update_config(node_id, {
remarks: getOption("<%=self.config%>", "<%=self.section%>", "remarks").value, remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=self.config%>", "<%=self.section%>", "group").value, group: getOption("<%=config%>", "<%=sid%>", "group").value,
protocol: getOption("<%=self.config%>", "<%=self.section%>", name).value, protocol: getOption("<%=config%>", "<%=sid%>", name).value,
}, node_config_url); }, node_config_url);
} else { } else {
window.location.href = node_config_url + "?select_proto=" + encodeURIComponent(el.value); window.location.href = node_config_url + "?select_proto=" + encodeURIComponent(el.value);
@@ -1,3 +1,8 @@
<%
local map = self.map
local api = map.api
local sid = self.section
-%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
function fetchCertSha256(el) { function fetchCertSha256(el) {
@@ -5,7 +10,7 @@
el.setAttribute("data-loading", "1"); el.setAttribute("data-loading", "1");
el.style.pointerEvents = "none"; el.style.pointerEvents = "none";
el.style.color = "red"; el.style.color = "red";
XHR.get('<%=self.api.url("fetch_certsha256")%>', { id: "<%=self.section%>" }, function(x, res) { XHR.get('<%=api.url("fetch_certsha256")%>', { id: "<%=sid%>" }, function(x, res) {
el.setAttribute("data-loading", "0"); el.setAttribute("data-loading", "0");
el.style.pointerEvents = ""; el.style.pointerEvents = "";
el.style.color = ""; el.style.color = "";
@@ -1,7 +1,7 @@
<% <%
local api = self.api
local appname = api.appname
local map = self.map local map = self.map
local api = map.api
local appname = map.config
local is_js_luci = api.is_js_luci() local is_js_luci = api.is_js_luci()
local section_tag = is_js_luci and "div" or "fieldset" local section_tag = is_js_luci and "div" or "fieldset"
-%> -%>
@@ -415,8 +415,8 @@ table td, .table .td {
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
let auto_detection_time = "<%=api.uci_get_type("global_other", "auto_detection_time", "0")%>" let auto_detection_time = "<%=map:get("@global_other[0]", "auto_detection_time") or "0"%>"
let show_node_info = "<%=api.uci_get_type("global_other", "show_node_info", "0")%>" let show_node_info = "<%=map:get("@global_other[0]", "show_node_info") or "0"%>"
var ajax = { var ajax = {
list: [], list: [],
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
local fs = api.fs local fs = api.fs
local has_old_geoip = fs.access("/tmp/bak_v2ray/geoip.dat") local has_old_geoip = fs.access("/tmp/bak_v2ray/geoip.dat")
local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat") local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
@@ -1,6 +1,7 @@
<% <%
local api = self.api local map = self.map
local appname = api.appname local api = map.api
local appname = map.config
local is_js_luci = api.is_js_luci() local is_js_luci = api.is_js_luci()
local section_tag = is_js_luci and "div" or "fieldset" local section_tag = is_js_luci and "div" or "fieldset"
local title_tag = is_js_luci and "h3" or "legend" local title_tag = is_js_luci and "h3" or "legend"
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
-%> -%>
<style> <style>
@@ -1,7 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local translate = luci.i18n.translate local api = map.api
local total_lines_text = translate("Total Lines")
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@@ -14,7 +13,7 @@ local total_lines_text = translate("Total Lines")
textarea.innerHTML = data; textarea.innerHTML = data;
//textarea.scrollTop = textarea.scrollHeight; //textarea.scrollTop = textarea.scrollHeight;
var totalLinesLabel = document.getElementById('gfw_total_lines'); var totalLinesLabel = document.getElementById('gfw_total_lines');
totalLinesLabel.innerHTML = "<%= total_lines_text %> " + total_lines; totalLinesLabel.innerHTML = "<%:Total Lines%> " + total_lines;
}) })
} }
@@ -27,7 +26,7 @@ local total_lines_text = translate("Total Lines")
textarea.innerHTML = data; textarea.innerHTML = data;
//textarea.scrollTop = textarea.scrollHeight; //textarea.scrollTop = textarea.scrollHeight;
var totalLinesLabel = document.getElementById('chn_total_lines'); var totalLinesLabel = document.getElementById('chn_total_lines');
totalLinesLabel.innerHTML = "<%= total_lines_text %> " + total_lines; totalLinesLabel.innerHTML = "<%:Total Lines%> " + total_lines;
}) })
} }
@@ -40,7 +39,7 @@ local total_lines_text = translate("Total Lines")
textarea.innerHTML = data; textarea.innerHTML = data;
//textarea.scrollTop = textarea.scrollHeight; //textarea.scrollTop = textarea.scrollHeight;
var totalLinesLabel = document.getElementById('chnroute_total_lines'); var totalLinesLabel = document.getElementById('chnroute_total_lines');
totalLinesLabel.innerHTML = "<%= total_lines_text %> " + total_lines; totalLinesLabel.innerHTML = "<%:Total Lines%> " + total_lines;
}) })
} }
//]]> //]]>
@@ -1,13 +1,16 @@
<% <%
local api = self.api local map = self.map
local api = map.api
local config = map.config
local section = self.section
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
let node_id = "<%=self.section%>"; let node_id = "<%=section%>";
let node_config_url = '<%=api.url("server_config")%>/' + node_id; let node_config_url = '<%=api.url("server_config")%>/' + node_id;
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
waitForElement('select[name*="<%=self.config%>"][name*="type"]', function(el) { waitForElement('select[name*="<%=config%>"][name*="type"]', function(el) {
let o_val = el.value; let o_val = el.value;
el.addEventListener("change", () => { el.addEventListener("change", () => {
el.blur(); el.blur();
@@ -16,9 +19,9 @@ local api = self.api
if (save) { if (save) {
//document.getElementsByClassName('cbi-button-save')[0].click(); //document.getElementsByClassName('cbi-button-save')[0].click();
server_update_config(node_id, { server_update_config(node_id, {
enable: getOption("<%=self.config%>", node_id, "enable").value, enable: getOption("<%=config%>", node_id, "enable").value,
remarks: getOption("<%=self.config%>", node_id, "remarks").value, remarks: getOption("<%=config%>", node_id, "remarks").value,
type: getOption("<%=self.config%>", node_id, "type").value, type: getOption("<%=config%>", node_id, "type").value,
protocol: '' protocol: ''
}, node_config_url); }, node_config_url);
} }
@@ -1,7 +1,12 @@
<%
local map = self.map
local api = map.api
local section = self.section
-%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
function server_update_config(cfgid, data, redirect_url) { function server_update_config(cfgid, data, redirect_url) {
XHR.get('<%=self.api.url("server_update_config")%>', { XHR.get('<%=api.url("server_update_config")%>', {
id: cfgid, id: cfgid,
data: JSON.stringify(data) data: JSON.stringify(data)
}, },
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@@ -1,5 +1,8 @@
<% <%
local api = self.api local map = self.map
local api = map.api
local config = map.config
local sectiontype = self.sectiontype
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@@ -19,7 +22,7 @@ local api = self.api
); );
} }
var edit_btn = document.getElementById("cbi-<%=self.appname%>-<%=self.sectiontype%>").getElementsByClassName("cbi-button cbi-button-edit"); var edit_btn = document.getElementById("cbi-<%=config%>-<%=sectiontype%>").getElementsByClassName("cbi-button cbi-button-edit");
for (var i = 0; i < edit_btn.length; i++) { for (var i = 0; i < edit_btn.length; i++) {
try { try {
var onclick_str = edit_btn[i].getAttribute("onclick"); var onclick_str = edit_btn[i].getAttribute("onclick");
@@ -1,5 +1,6 @@
<% <%
local api = require "luci.passwall.api" local map = self.map
local api = map.api
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
-24
View File
@@ -1508,18 +1508,6 @@ msgstr "配合伪装类型 DNS 使用,可随便填一个域名。"
msgid "Auth" msgid "Auth"
msgstr "身份认证" msgstr "身份认证"
msgid "Socks for authentication"
msgstr "Socks 认证方式"
msgid "Socks protocol authentication, support anonymous and password."
msgstr "Socks 协议的认证方式,支持匿名方式和账号密码方式。"
msgid "anonymous"
msgstr "匿名"
msgid "User Password"
msgstr "账号密码"
msgid "This username already exists." msgid "This username already exists."
msgstr "该用户名已存在。" msgstr "该用户名已存在。"
@@ -1538,18 +1526,6 @@ msgstr "IPv6 透明代理(TProxy)"
msgid "Experimental feature. Make sure that your node supports IPv6." msgid "Experimental feature. Make sure that your node supports IPv6."
msgstr "实验特性,请确保你的节点支持IPv6" msgstr "实验特性,请确保你的节点支持IPv6"
msgid "Status info"
msgstr "状态信息"
msgid "Big icon"
msgstr "大图标"
msgid "Show node check"
msgstr "显示节点检测"
msgid "Show Show IP111"
msgstr "显示 IP111"
msgid "Destination protocol" msgid "Destination protocol"
msgstr "目标协议" msgstr "目标协议"
@@ -5,9 +5,6 @@ if [ -e "/etc/config/ucitrack" ]; then
delete ucitrack.@passwall[-1] delete ucitrack.@passwall[-1]
add ucitrack passwall add ucitrack passwall
set ucitrack.@passwall[-1].init=passwall set ucitrack.@passwall[-1].init=passwall
delete ucitrack.@passwall_server[-1]
add ucitrack passwall_server
set ucitrack.@passwall_server[-1].init=passwall_server
commit ucitrack commit ucitrack
EOF EOF
fi fi
@@ -18,11 +15,6 @@ uci -q batch <<-EOF
set firewall.passwall.type='script' set firewall.passwall.type='script'
set firewall.passwall.path='/var/etc/passwall.include' set firewall.passwall.path='/var/etc/passwall.include'
delete firewall.passwall_server
set firewall.passwall_server=include
set firewall.passwall_server.type='script'
set firewall.passwall_server.path='/var/etc/passwall_server.include'
set dhcp.@dnsmasq[0].localuse=1 set dhcp.@dnsmasq[0].localuse=1
commit dhcp commit dhcp
set uhttpd.main.max_requests=50 set uhttpd.main.max_requests=50
@@ -31,12 +23,9 @@ EOF
if [ -x "/sbin/fw3" ]; then if [ -x "/sbin/fw3" ]; then
uci -q set firewall.passwall.reload='1' uci -q set firewall.passwall.reload='1'
uci -q set firewall.passwall_server.reload='1'
else else
uci -q delete firewall.passwall.reload uci -q delete firewall.passwall.reload
uci -q delete firewall.passwall.fw4_compatible uci -q delete firewall.passwall.fw4_compatible
uci -q delete firewall.passwall_server.reload
uci -q delete firewall.passwall_server.fw4_compatible
fi fi
uci commit firewall uci commit firewall
@@ -0,0 +1,31 @@
#!/bin/sh
if [ -e "/etc/config/ucitrack" ]; then
uci -q batch <<-EOF
delete ucitrack.@passwall_server[-1]
add ucitrack passwall_server
set ucitrack.@passwall_server[-1].init=passwall_server
commit ucitrack
EOF
fi
uci -q batch <<-EOF
delete firewall.passwall_server
set firewall.passwall_server=include
set firewall.passwall_server.type='script'
set firewall.passwall_server.path='/var/etc/passwall_server.include'
EOF
if [ -x "/sbin/fw3" ]; then
uci -q set firewall.passwall_server.reload='1'
else
uci -q delete firewall.passwall_server.reload
uci -q delete firewall.passwall_server.fw4_compatible
fi
uci commit firewall
rm -f /tmp/luci-indexcache /tmp/luci-indexcache.*
rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null
exit 0
@@ -23,11 +23,11 @@ local haproxy_conf = var["-conf"]
local haproxy_dns = var["-dns"] or "119.29.29.29:53,223.5.5.5:53" local haproxy_dns = var["-dns"] or "119.29.29.29:53,223.5.5.5:53"
local cpu_thread = sys.exec('echo -n $(cat /proc/cpuinfo | grep "processor" | wc -l)') or "1" local cpu_thread = sys.exec('echo -n $(cat /proc/cpuinfo | grep "processor" | wc -l)') or "1"
local health_check_type = uci:get(appname, "@global_haproxy[0]", "health_check_type") or "tcp" local health_check_type = uci:get(api.c_config, "@global_haproxy[0]", "health_check_type") or "tcp"
local health_check_inter = uci:get(appname, "@global_haproxy[0]", "health_check_inter") or "20" local health_check_inter = uci:get(api.c_config, "@global_haproxy[0]", "health_check_inter") or "20"
local balancingStrategy = uci:get(appname, "@global_haproxy[0]", "balancingStrategy") or "roundrobin" local balancingStrategy = uci:get(api.c_config, "@global_haproxy[0]", "balancingStrategy") or "roundrobin"
local console_port = uci:get(appname, "@global_haproxy[0]", "console_port") local console_port = uci:get(api.c_config, "@global_haproxy[0]", "console_port")
local bind_local = uci:get(appname, "@global_haproxy[0]", "bind_local") or "0" local bind_local = uci:get(api.c_config, "@global_haproxy[0]", "bind_local") or "0"
local bind_address = "0.0.0.0" local bind_address = "0.0.0.0"
if bind_local == "1" then bind_address = "127.0.0.1" end if bind_local == "1" then bind_address = "127.0.0.1" end
@@ -94,15 +94,15 @@ f_out:write(haproxy_config)
local listens = {} local listens = {}
uci:foreach(appname, "haproxy_config", function(t) uci:foreach(api.c_config, "haproxy_config", function(t)
if t.enabled == "1" then if t.enabled == "1" then
local server_remark local server_remark
local server_address local server_address
local server_port local server_port
local lbss = t.lbss local lbss = t.lbss
local listen_port = tonumber(t.haproxy_port) or 0 local listen_port = tonumber(t.haproxy_port) or 0
local server_node = uci:get_all(appname, lbss) local server_node = uci:get_all(api.c_config, lbss)
local hop = (health_check_type == "passwall_logic") and (server_node.hysteria_hop or server_node.hysteria2_hop) or nil local hop = (health_check_type == "script_logic") and (server_node.hysteria_hop or server_node.hysteria2_hop) or nil
hop = hop and hop:gsub(":", "-") or nil hop = hop and hop:gsub(":", "-") or nil
if server_node and server_node.address and (server_node.port or hop) then if server_node and server_node.address and (server_node.port or hop) then
server_remark = server_node.address .. ":" .. (server_node.port or hop) server_remark = server_node.address .. ":" .. (server_node.port or hop)
@@ -110,7 +110,7 @@ uci:foreach(appname, "haproxy_config", function(t)
server_port = server_node.port or hop server_port = server_node.port or hop
t.origin_address = server_address t.origin_address = server_address
t.origin_port = server_port t.origin_port = server_port
if health_check_type == "passwall_logic" then if health_check_type == "script_logic" then
if server_node.type ~= "Socks" then if server_node.type ~= "Socks" then
local relay_port = server_node.port local relay_port = server_node.port
local new_port = api.get_new_port() local new_port = api.get_new_port()
@@ -172,7 +172,7 @@ listen %s
balance %s balance %s
]], port, bind_address, port, balancingStrategy)) ]], port, bind_address, port, balancingStrategy))
if health_check_type == "passwall_logic" then if health_check_type == "script_logic" then
f_out:write(string.format([[ f_out:write(string.format([[
option external-check option external-check
external-check command "/usr/share/%s/haproxy_check.sh" external-check command "/usr/share/%s/haproxy_check.sh"
@@ -214,8 +214,8 @@ listen %s
end end
--控制台配置 --控制台配置
local console_user = uci:get(appname, "@global_haproxy[0]", "console_user") local console_user = uci:get(api.c_config, "@global_haproxy[0]", "console_user")
local console_password = uci:get(appname, "@global_haproxy[0]", "console_password") local console_password = uci:get(api.c_config, "@global_haproxy[0]", "console_password")
local str = [[ local str = [[
listen console listen console
bind 0.0.0.0:%s bind 0.0.0.0:%s
@@ -230,8 +230,8 @@ f_out:write("\n" .. string.format(str, console_port, (console_user and console_u
f_out:close() f_out:close()
--passwall内置健康检查URL --passwall内置健康检查URL
if health_check_type == "passwall_logic" then if health_check_type == "script_logic" then
local probeUrl = uci:get(appname, "@global_haproxy[0]", "health_probe_url") or "https://www.google.com/generate_204" local probeUrl = uci:get(api.c_config, "@global_haproxy[0]", "health_probe_url") or "https://www.google.com/generate_204"
local f_url = io.open(haproxy_path .. "/Probe_URL", "w") local f_url = io.open(haproxy_path .. "/Probe_URL", "w")
f_url:write(probeUrl) f_url:write(probeUrl)
f_url:close() f_url:close()
@@ -31,8 +31,8 @@ local RULES_PATH = "/usr/share/" .. appname .. "/rules"
local FLAG_PATH = TMP_ACL_PATH .. "/" .. FLAG local FLAG_PATH = TMP_ACL_PATH .. "/" .. FLAG
local config_lines = {} local config_lines = {}
local tmp_lines = {} local tmp_lines = {}
local USE_GEOVIEW = uci:get(appname, "@global_rules[0]", "enable_geoview") local USE_GEOVIEW = uci:get(api.c_config, "@global_rules[0]", "enable_geoview")
local IS_SHUNT_NODE = uci:get(appname, TCP_NODE, "protocol") == "_shunt" local IS_SHUNT_NODE = uci:get(api.c_config, TCP_NODE, "protocol") == "_shunt"
if not api.is_finded("geoview") then if not api.is_finded("geoview") then
USE_GEOVIEW = "0" USE_GEOVIEW = "0"
@@ -92,7 +92,7 @@ local function insert_array_after(array1, array2, target) --将array2插入到ar
end end
local function get_geosite(list_arg, out_path) local function get_geosite(list_arg, out_path)
local geosite_path = uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/" local geosite_path = uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat" geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat"
if not is_file_nonzero(geosite_path) then return 1 end if not is_file_nonzero(geosite_path) then return 1 end
local bin = api.finded_com("geoview") local bin = api.finded_com("geoview")
@@ -183,7 +183,7 @@ if not is_file_nonzero(file_vpslist) then
written_domains[address] = true written_domains[address] = true
end end
end end
uci:foreach(appname, "nodes", function(t) uci:foreach(api.c_config, "nodes", function(t)
process_address(t.address) process_address(t.address)
process_address(t.download_address) process_address(t.download_address)
local dns, _ = api.get_domain_port_from_url(t.domain_resolver_dns or t.domain_resolver_dns_https or "") local dns, _ = api.get_domain_port_from_url(t.domain_resolver_dns or t.domain_resolver_dns_https or "")
@@ -191,7 +191,7 @@ if not is_file_nonzero(file_vpslist) then
process_address(dns) process_address(dns)
end end
end) end)
uci:foreach(appname, "subscribe_list", function(t) --订阅链接 uci:foreach(api.c_config, "subscribe_list", function(t) --订阅链接
local url, _ = api.get_domain_port_from_url(t.url or "") local url, _ = api.get_domain_port_from_url(t.url or "")
if url and url ~= "" then if url and url ~= "" then
process_address(url) process_address(url)
@@ -387,9 +387,9 @@ if IS_SHUNT_NODE then
local file_shunt_host = FLAG_PATH .. "/shunt_proxy_host" local file_shunt_host = FLAG_PATH .. "/shunt_proxy_host"
local geosite_white_arg, geosite_shunt_arg = "", "" local geosite_white_arg, geosite_shunt_arg = "", ""
local t = uci:get_all(appname, TCP_NODE) local t = uci:get_all(api.c_config, TCP_NODE)
local default_node_id = t["default_node"] or "_direct" local default_node_id = t["default_node"] or "_direct"
uci:foreach(appname, "shunt_rules", function(s) uci:foreach(api.c_config, "shunt_rules", function(s)
local _node_id = t[s[".name"]] local _node_id = t[s[".name"]]
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
if _node_id == "_default" then if _node_id == "_default" then
@@ -24,8 +24,8 @@ end
local function backup_servers() local function backup_servers()
local DNSMASQ_DNS = uci:get("dhcp", "@dnsmasq[0]", "server") local DNSMASQ_DNS = uci:get("dhcp", "@dnsmasq[0]", "server")
if DNSMASQ_DNS and #DNSMASQ_DNS > 0 then if DNSMASQ_DNS and #DNSMASQ_DNS > 0 then
uci:set(appname, "@global[0]", "dnsmasq_servers", DNSMASQ_DNS) uci:set(api.c_config, "@global[0]", "dnsmasq_servers", DNSMASQ_DNS)
api.uci_save(uci, appname, true) api.uci_save(uci, api.c_config, true)
end end
end end
@@ -37,13 +37,13 @@ local function restore_servers()
tinsert(dns_table, v) tinsert(dns_table, v)
end end
end end
local OLD_SERVER = uci:get(appname, "@global[0]", "dnsmasq_servers") local OLD_SERVER = uci:get(api.c_config, "@global[0]", "dnsmasq_servers")
if OLD_SERVER and #OLD_SERVER > 0 then if OLD_SERVER and #OLD_SERVER > 0 then
for k, v in ipairs(OLD_SERVER) do for k, v in ipairs(OLD_SERVER) do
tinsert(dns_table, v) tinsert(dns_table, v)
end end
uci:delete(appname, "@global[0]", "dnsmasq_servers") uci:delete(api.c_config, "@global[0]", "dnsmasq_servers")
api.uci_save(uci, appname, true) api.uci_save(uci, api.c_config, true)
end end
if dns_table and #dns_table > 0 then if dns_table and #dns_table > 0 then
uci:set_list("dhcp", "@dnsmasq[0]", "server", dns_table) uci:set_list("dhcp", "@dnsmasq[0]", "server", dns_table)
@@ -180,8 +180,8 @@ function add_rule(var)
local CACHE_DNS_PATH = CACHE_PATH .. "/" .. CACHE_FLAG local CACHE_DNS_PATH = CACHE_PATH .. "/" .. CACHE_FLAG
local CACHE_TEXT_FILE = CACHE_DNS_PATH .. ".txt" local CACHE_TEXT_FILE = CACHE_DNS_PATH .. ".txt"
local USE_CHINADNS_NG = "0" local USE_CHINADNS_NG = "0"
local IS_SHUNT_NODE = uci:get(appname, TCP_NODE, "protocol") == "_shunt" local IS_SHUNT_NODE = uci:get(api.c_config, TCP_NODE, "protocol") == "_shunt"
local USE_GEOVIEW = uci:get(appname, "@global_rules[0]", "enable_geoview") local USE_GEOVIEW = uci:get(api.c_config, "@global_rules[0]", "enable_geoview")
local list1 = {} local list1 = {}
local excluded_domain = {} local excluded_domain = {}
@@ -307,7 +307,7 @@ function add_rule(var)
end end
local function foreach_geosite(list_arg, callback) local function foreach_geosite(list_arg, callback)
local geosite_path = uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/" local geosite_path = uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat" geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat"
if not fs.access(geosite_path) then return end if not fs.access(geosite_path) then return end
local bin = api.finded_com("geoview") local bin = api.finded_com("geoview")
@@ -412,7 +412,7 @@ function add_rule(var)
set_domain_ipset(address, table.concat(sets, ",")) set_domain_ipset(address, table.concat(sets, ","))
end end
end end
uci:foreach(appname, "nodes", function(t) uci:foreach(api.c_config, "nodes", function(t)
process_address(t.address) process_address(t.address)
process_address(t.download_address) process_address(t.download_address)
local dns, _ = api.get_domain_port_from_url(t.domain_resolver_dns or t.domain_resolver_dns_https or "") local dns, _ = api.get_domain_port_from_url(t.domain_resolver_dns or t.domain_resolver_dns_https or "")
@@ -420,7 +420,7 @@ function add_rule(var)
process_address(dns) process_address(dns)
end end
end) end)
uci:foreach(appname, "subscribe_list", function(t) --订阅链接 uci:foreach(api.c_config, "subscribe_list", function(t) --订阅链接
local url, _ = api.get_domain_port_from_url(t.url or "") local url, _ = api.get_domain_port_from_url(t.url or "")
if url and url ~= "" then if url and url ~= "" then
process_address(url) process_address(url)
@@ -615,9 +615,9 @@ function add_rule(var)
--分流规则 --分流规则
if IS_SHUNT_NODE and USE_CHINADNS_NG == "0" then if IS_SHUNT_NODE and USE_CHINADNS_NG == "0" then
local t = uci:get_all(appname, TCP_NODE) local t = uci:get_all(api.c_config, TCP_NODE)
local default_node_id = t["default_node"] or "_direct" local default_node_id = t["default_node"] or "_direct"
uci:foreach(appname, "shunt_rules", function(s) uci:foreach(api.c_config, "shunt_rules", function(s)
local _node_id = t[s[".name"]] local _node_id = t[s[".name"]]
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
if _node_id == "_default" then if _node_id == "_default" then
@@ -37,8 +37,8 @@ local FLAG_PATH = TMP_ACL_PATH .. "/" .. FLAG
local TMP_CONF_FILE = FLAG_PATH .. "/smartdns.conf" local TMP_CONF_FILE = FLAG_PATH .. "/smartdns.conf"
local config_lines = {} local config_lines = {}
local tmp_lines = {} local tmp_lines = {}
local USE_GEOVIEW = uci:get(appname, "@global_rules[0]", "enable_geoview") local USE_GEOVIEW = uci:get(api.c_config, "@global_rules[0]", "enable_geoview")
local IS_SHUNT_NODE = uci:get(appname, TCP_NODE, "protocol") == "_shunt" local IS_SHUNT_NODE = uci:get(api.c_config, TCP_NODE, "protocol") == "_shunt"
if not api.is_finded("geoview") then if not api.is_finded("geoview") then
USE_GEOVIEW = "0" USE_GEOVIEW = "0"
@@ -98,7 +98,7 @@ local function insert_array_after(array1, array2, target) --将array2插入到ar
end end
local function get_geosite(list_arg, out_path) local function get_geosite(list_arg, out_path)
local geosite_path = uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/" local geosite_path = uci:get(api.c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat" geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat"
if not is_file_nonzero(geosite_path) then return 1 end if not is_file_nonzero(geosite_path) then return 1 end
local bin = api.finded_com("geoview") local bin = api.finded_com("geoview")
@@ -187,7 +187,7 @@ if not REMOTE_GROUP or REMOTE_GROUP == "nil" then
sys.call('sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1') sys.call('sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1')
end end
local force_https_soa = uci:get(appname, "@global[0]", "force_https_soa") or 0 local force_https_soa = uci:get(api.c_config, "@global[0]", "force_https_soa") or 0
local proxy_server_name = "passwall-proxy-server" local proxy_server_name = "passwall-proxy-server"
config_lines = { config_lines = {
tonumber(LISTEN_PORT) ~= 0 and "bind [::]:" .. LISTEN_PORT .. "@lo" or "", tonumber(LISTEN_PORT) ~= 0 and "bind [::]:" .. LISTEN_PORT .. "@lo" or "",
@@ -342,7 +342,7 @@ if not is_file_nonzero(file_vpslist) then
written_domains[address] = true written_domains[address] = true
end end
end end
uci:foreach(appname, "nodes", function(t) uci:foreach(api.c_config, "nodes", function(t)
process_address(t.address) process_address(t.address)
process_address(t.download_address) process_address(t.download_address)
local dns, _ = api.get_domain_port_from_url(t.domain_resolver_dns or t.domain_resolver_dns_https or "") local dns, _ = api.get_domain_port_from_url(t.domain_resolver_dns or t.domain_resolver_dns_https or "")
@@ -350,7 +350,7 @@ if not is_file_nonzero(file_vpslist) then
process_address(dns) process_address(dns)
end end
end) end)
uci:foreach(appname, "subscribe_list", function(t) --订阅链接 uci:foreach(api.c_config, "subscribe_list", function(t) --订阅链接
local url, _ = api.get_domain_port_from_url(t.url or "") local url, _ = api.get_domain_port_from_url(t.url or "")
if url and url ~= "" then if url and url ~= "" then
process_address(url) process_address(url)
@@ -555,9 +555,9 @@ if IS_SHUNT_NODE then
local file_shunt_host = FLAG_PATH .. "/shunt_proxy_host" local file_shunt_host = FLAG_PATH .. "/shunt_proxy_host"
local geosite_white_arg, geosite_shunt_arg = "", "" local geosite_white_arg, geosite_shunt_arg = "", ""
local t = uci:get_all(appname, TCP_NODE) local t = uci:get_all(api.c_config, TCP_NODE)
local default_node_id = t["default_node"] or "_direct" local default_node_id = t["default_node"] or "_direct"
uci:foreach(appname, "shunt_rules", function(s) uci:foreach(api.c_config, "shunt_rules", function(s)
local _node_id = t[s[".name"]] local _node_id = t[s[".name"]]
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
if _node_id == "_default" then if _node_id == "_default" then
@@ -2,6 +2,7 @@
local api = require ("luci.passwall.api") local api = require ("luci.passwall.api")
local name = api.appname local name = api.appname
local c_config = api.c_config
local uci = api.uci local uci = api.uci
local sys = api.sys local sys = api.sys
local jsonc = api.jsonc local jsonc = api.jsonc
@@ -23,14 +24,14 @@ local geosite_update = "0"
local excluded_domain = {"apple.com","sina.cn","sina.com.cn","baidu.com","byr.cn","jlike.com","weibo.com","zhongsou.com","youdao.com","sogou.com","so.com","soso.com","aliyun.com","taobao.com","jd.com","qq.com","bing.com"} local excluded_domain = {"apple.com","sina.cn","sina.com.cn","baidu.com","byr.cn","jlike.com","weibo.com","zhongsou.com","youdao.com","sogou.com","so.com","soso.com","aliyun.com","taobao.com","jd.com","qq.com","bing.com"}
local gfwlist_url = uci:get(name, "@global_rules[0]", "gfwlist_url") or {"https://fastly.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt"} local gfwlist_url = uci:get(c_config, "@global_rules[0]", "gfwlist_url") or {"https://fastly.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt"}
local chnroute_url = uci:get(name, "@global_rules[0]", "chnroute_url") or {"https://ispip.clang.cn/all_cn.txt"} local chnroute_url = uci:get(c_config, "@global_rules[0]", "chnroute_url") or {"https://ispip.clang.cn/all_cn.txt"}
local chnroute6_url = uci:get(name, "@global_rules[0]", "chnroute6_url") or {"https://ispip.clang.cn/all_cn_ipv6.txt"} local chnroute6_url = uci:get(c_config, "@global_rules[0]", "chnroute6_url") or {"https://ispip.clang.cn/all_cn_ipv6.txt"}
local chnlist_url = uci:get(name, "@global_rules[0]", "chnlist_url") or {"https://fastly.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf","https://fastly.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf","https://fastly.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf"} local chnlist_url = uci:get(c_config, "@global_rules[0]", "chnlist_url") or {"https://fastly.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf","https://fastly.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf","https://fastly.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf"}
local geoip_url = uci:get(name, "@global_rules[0]", "geoip_url") or "https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.dat" local geoip_url = uci:get(c_config, "@global_rules[0]", "geoip_url") or "https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.dat"
local geosite_url = uci:get(name, "@global_rules[0]", "geosite_url") or "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" local geosite_url = uci:get(c_config, "@global_rules[0]", "geosite_url") or "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat"
local asset_location = uci:get(name, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/" local asset_location = uci:get(c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
local geo2rule = uci:get(name, "@global_rules[0]", "geo2rule") or "0" local geo2rule = uci:get(c_config, "@global_rules[0]", "geo2rule") or "0"
local geoip_update_ok, geosite_update_ok = false, false local geoip_update_ok, geosite_update_ok = false, false
asset_location = asset_location:match("/$") and asset_location or (asset_location .. "/") asset_location = asset_location:match("/$") and asset_location or (asset_location .. "/")
local backup_path = "/tmp/bak_v2ray/" local backup_path = "/tmp/bak_v2ray/"
@@ -659,12 +660,12 @@ if arg2 then
end) end)
if rollback then arg2 = nil end if rollback then arg2 = nil end
else else
gfwlist_update = uci:get(name, "@global_rules[0]", "gfwlist_update") or "1" gfwlist_update = uci:get(c_config, "@global_rules[0]", "gfwlist_update") or "1"
chnroute_update = uci:get(name, "@global_rules[0]", "chnroute_update") or "1" chnroute_update = uci:get(c_config, "@global_rules[0]", "chnroute_update") or "1"
chnroute6_update = uci:get(name, "@global_rules[0]", "chnroute6_update") or "1" chnroute6_update = uci:get(c_config, "@global_rules[0]", "chnroute6_update") or "1"
chnlist_update = uci:get(name, "@global_rules[0]", "chnlist_update") or "1" chnlist_update = uci:get(c_config, "@global_rules[0]", "chnlist_update") or "1"
geoip_update = uci:get(name, "@global_rules[0]", "geoip_update") or "1" geoip_update = uci:get(c_config, "@global_rules[0]", "geoip_update") or "1"
geosite_update = uci:get(name, "@global_rules[0]", "geosite_update") or "1" geosite_update = uci:get(c_config, "@global_rules[0]", "geosite_update") or "1"
end end
if geo2rule ~= "1" and gfwlist_update == "0" and chnroute_update == "0" and chnroute6_update == "0" and chnlist_update == "0" and geoip_update == "0" and geosite_update == "0" then if geo2rule ~= "1" and gfwlist_update == "0" and chnroute_update == "0" and chnroute6_update == "0" and chnlist_update == "0" and geoip_update == "0" and geosite_update == "0" then
os.exit(0) os.exit(0)
@@ -777,13 +778,13 @@ else
end end
if not rollback then if not rollback then
uci:set(name, "@global_rules[0]", "gfwlist_update", gfwlist_update) uci:set(c_config, "@global_rules[0]", "gfwlist_update", gfwlist_update)
uci:set(name, "@global_rules[0]", "chnroute_update", chnroute_update) uci:set(c_config, "@global_rules[0]", "chnroute_update", chnroute_update)
uci:set(name, "@global_rules[0]", "chnroute6_update", chnroute6_update) uci:set(c_config, "@global_rules[0]", "chnroute6_update", chnroute6_update)
uci:set(name, "@global_rules[0]", "chnlist_update", chnlist_update) uci:set(c_config, "@global_rules[0]", "chnlist_update", chnlist_update)
uci:set(name, "@global_rules[0]", "geoip_update", geoip_update) uci:set(c_config, "@global_rules[0]", "geoip_update", geoip_update)
uci:set(name, "@global_rules[0]", "geosite_update", geosite_update) uci:set(c_config, "@global_rules[0]", "geosite_update", geosite_update)
api.uci_save(uci, name, true) api.uci_save(uci, c_config, true)
end end
if reboot == 1 then if reboot == 1 then
@@ -794,8 +795,8 @@ if reboot == 1 then
end end
log("重启服务,应用新的规则。") log("重启服务,应用新的规则。")
uci:set(name, "@global[0]", "flush_set", "1") uci:set(c_config, "@global[0]", "flush_set", "1")
api.uci_save(uci, name, true, true) api.uci_save(uci, c_config, true, true)
end end
log("规则更新完毕...\n") log("规则更新完毕...\n")
@@ -6,8 +6,9 @@
require 'luci.util' require 'luci.util'
require 'luci.jsonc' require 'luci.jsonc'
require 'luci.sys' require 'luci.sys'
local appname = 'passwall' local api = require "luci.passwall.api"
local api = require ("luci.passwall.api") local appname = api.appname
local c_config = api.c_config
local datatypes = require "luci.cbi.datatypes" local datatypes = require "luci.cbi.datatypes"
loadfile("/usr/share/" .. appname .. "/clash_subconverter.lua")() loadfile("/usr/share/" .. appname .. "/clash_subconverter.lua")()
@@ -30,9 +31,9 @@ local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
local has_hysteria2 = api.finded_com("hysteria") local has_hysteria2 = api.finded_com("hysteria")
local DEFAULT_ALLOWINSECURE = true local DEFAULT_ALLOWINSECURE = true
local DEFAULT_FILTER_KEYWORD_MODE = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local DEFAULT_FILTER_KEYWORD_MODE = uci:get(c_config, "@global_subscribe[0]", "filter_keyword_mode") or "0"
local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci:get(c_config, "@global_subscribe[0]", "filter_discard_list") or {}
local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {} local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci:get(c_config, "@global_subscribe[0]", "filter_keep_list") or {}
-- 取节点使用core类型(节点订阅页面未设置时,自动取默认) -- 取节点使用core类型(节点订阅页面未设置时,自动取默认)
local DEFAULT_SS_TYPE = api.get_core("ss_type", {{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_TROJAN_TYPE = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
@@ -141,13 +142,13 @@ do
local szType = "@global[0]" local szType = "@global[0]"
local option = protocol .. "_node" local option = protocol .. "_node"
local node_id = uci:get(appname, szType, option) local node_id = uci:get(c_config, szType, option)
CONFIG[#CONFIG + 1] = { CONFIG[#CONFIG + 1] = {
log = true, log = true,
remarks = name .. "节点", remarks = name .. "节点",
currentNode = node_id and uci:get_all(appname, node_id) or nil, currentNode = node_id and uci:get_all(c_config, node_id) or nil,
set = function(o, server) set = function(o, server)
uci:set(appname, szType, option, server) uci:set(c_config, szType, option, server)
o.newNodeId = server o.newNodeId = server
end end
} }
@@ -158,7 +159,7 @@ do
if true then if true then
local i = 0 local i = 0
local option = "node" local option = "node"
uci:foreach(appname, "socks", function(t) uci:foreach(c_config, "socks", function(t)
i = i + 1 i = i + 1
local id = t[".name"] local id = t[".name"]
local node_id = t[option] local node_id = t[option]
@@ -166,14 +167,14 @@ do
log = true, log = true,
id = id, id = id,
remarks = "Socks节点列表[" .. i .. "]", remarks = "Socks节点列表[" .. i .. "]",
currentNode = node_id and uci:get_all(appname, node_id) or nil, currentNode = node_id and uci:get_all(c_config, node_id) or nil,
set = function(o, server) set = function(o, server)
if not server or server == "" then if not server or server == "" then
if #nodes_table > 0 then if #nodes_table > 0 then
server = nodes_table[1][".name"] server = nodes_table[1][".name"]
end end
end end
uci:set(appname, t[".name"], option, server) uci:set(c_config, t[".name"], option, server)
o.newNodeId = server o.newNodeId = server
end end
} }
@@ -183,7 +184,7 @@ do
local newNodes = {} local newNodes = {}
for k, asb_node_id in ipairs(t.autoswitch_backup_node) do for k, asb_node_id in ipairs(t.autoswitch_backup_node) do
if asb_node_id then if asb_node_id then
local currentNode = uci:get_all(appname, asb_node_id) or {} local currentNode = uci:get_all(c_config, asb_node_id) or {}
if currentNode[".type"] == "nodes" then if currentNode[".type"] == "nodes" then
currentNodes[#currentNodes + 1] = { currentNodes[#currentNodes + 1] = {
log = true, log = true,
@@ -205,7 +206,7 @@ do
set = function(o, newNodes) set = function(o, newNodes)
if o then if o then
if not newNodes then newNodes = o.newNodes end if not newNodes then newNodes = o.newNodes end
uci:set_list(appname, id, "autoswitch_backup_node", newNodes or {}) uci:set_list(c_config, id, "autoswitch_backup_node", newNodes or {})
end end
end end
} }
@@ -221,25 +222,25 @@ do
local ip, port = str:match("^([%d%.]+):(%d+)$") local ip, port = str:match("^([%d%.]+):(%d+)$")
return ip and datatypes.ipaddr(ip) and tonumber(port) and tonumber(port) <= 65535 return ip and datatypes.ipaddr(ip) and tonumber(port) and tonumber(port) <= 65535
end end
uci:foreach(appname, "haproxy_config", function(t) uci:foreach(c_config, "haproxy_config", function(t)
i = i + 1 i = i + 1
local node_id = t[option] local node_id = t[option]
CONFIG[#CONFIG + 1] = { CONFIG[#CONFIG + 1] = {
log = true, log = true,
id = t[".name"], id = t[".name"],
remarks = "HAProxy负载均衡节点列表[" .. i .. "]", remarks = "HAProxy负载均衡节点列表[" .. i .. "]",
currentNode = node_id and uci:get_all(appname, node_id) or nil, currentNode = node_id and uci:get_all(c_config, node_id) or nil,
set = function(o, server) set = function(o, server)
-- 如果当前 lbss 值不是 ip:port 格式,才进行修改 -- 如果当前 lbss 值不是 ip:port 格式,才进行修改
if not is_ip_port(t[option]) then if not is_ip_port(t[option]) then
uci:set(appname, t[".name"], option, server) uci:set(c_config, t[".name"], option, server)
o.newNodeId = server o.newNodeId = server
end end
end, end,
delete = function(o) delete = function(o)
-- 如果当前 lbss 值不是 ip:port 格式,才进行删除 -- 如果当前 lbss 值不是 ip:port 格式,才进行删除
if not is_ip_port(t[option]) then if not is_ip_port(t[option]) then
uci:delete(appname, t[".name"]) uci:delete(c_config, t[".name"])
end end
end end
} }
@@ -249,7 +250,7 @@ do
if true then if true then
local i = 0 local i = 0
local options = {"tcp", "udp"} local options = {"tcp", "udp"}
uci:foreach(appname, "acl_rule", function(t) uci:foreach(c_config, "acl_rule", function(t)
i = i + 1 i = i + 1
for index, value in ipairs(options) do for index, value in ipairs(options) do
local option = value .. "_node" local option = value .. "_node"
@@ -258,9 +259,9 @@ do
log = true, log = true,
id = t[".name"], id = t[".name"],
remarks = "访问控制列表[" .. i .. "]", remarks = "访问控制列表[" .. i .. "]",
currentNode = node_id and uci:get_all(appname, node_id) or nil, currentNode = node_id and uci:get_all(c_config, node_id) or nil,
set = function(o, server) set = function(o, server)
uci:set(appname, t[".name"], option, server) uci:set(c_config, t[".name"], option, server)
o.newNodeId = server o.newNodeId = server
end end
} }
@@ -268,11 +269,11 @@ do
end) end)
end end
uci:foreach(appname, "nodes", function(node) uci:foreach(c_config, "nodes", function(node)
local node_id = node[".name"] local node_id = node[".name"]
if node.protocol and node.protocol == '_shunt' then if node.protocol and node.protocol == '_shunt' then
local rules = {} local rules = {}
uci:foreach(appname, "shunt_rules", function(e) uci:foreach(c_config, "shunt_rules", function(e)
if e[".name"] and e.remarks then if e[".name"] and e.remarks then
table.insert(rules, e) table.insert(rules, e)
table.insert(rules, { table.insert(rules, {
@@ -293,7 +294,7 @@ do
for k, e in pairs(rules) do for k, e in pairs(rules) do
local _node_id = node[e[".name"]] or nil local _node_id = node[e[".name"]] or nil
if _node_id then if _node_id then
local section = uci:get_all(appname, _node_id) or {} local section = uci:get_all(c_config, _node_id) or {}
if section[".type"] == "nodes" then if section[".type"] == "nodes" then
CONFIG[#CONFIG + 1] = { CONFIG[#CONFIG + 1] = {
log = false, log = false,
@@ -301,7 +302,7 @@ do
remarks = "分流" .. e.remarks .. "节点", remarks = "分流" .. e.remarks .. "节点",
set = function(o, server) set = function(o, server)
if not server then server = "" end if not server then server = "" end
uci:set(appname, node_id, e[".name"], server) uci:set(c_config, node_id, e[".name"], server)
o.newNodeId = server o.newNodeId = server
end end
} }
@@ -318,7 +319,7 @@ do
log = true, log = true,
node = b_node_id, node = b_node_id,
currentNode = (function() currentNode = (function()
local section = uci:get_all(appname, b_node_id) or {} local section = uci:get_all(c_config, b_node_id) or {}
if section[".type"] == "socks" then if section[".type"] == "socks" then
return { Socks = b_node_id } return { Socks = b_node_id }
end end
@@ -340,15 +341,15 @@ do
set = function(o, newNodes) set = function(o, newNodes)
if o then if o then
if not newNodes then newNodes = o.newNodes end if not newNodes then newNodes = o.newNodes end
uci:set_list(appname, node_id, "balancing_node", newNodes or {}) uci:set_list(c_config, node_id, "balancing_node", newNodes or {})
end end
end end
} }
--后备节点 --后备节点
local currentNode = uci:get_all(appname, node_id) or nil local currentNode = uci:get_all(c_config, node_id) or nil
if currentNode and currentNode.fallback_node then if currentNode and currentNode.fallback_node then
local section = uci:get_all(appname, currentNode.fallback_node) or {} local section = uci:get_all(c_config, currentNode.fallback_node) or {}
if section[".type"] == "nodes" then if section[".type"] == "nodes" then
CONFIG[#CONFIG + 1] = { CONFIG[#CONFIG + 1] = {
log = true, log = true,
@@ -356,11 +357,11 @@ do
remarks = "Xray负载均衡节点[" .. node_id .. "]后备节点", remarks = "Xray负载均衡节点[" .. node_id .. "]后备节点",
currentNode = section, currentNode = section,
set = function(o, server) set = function(o, server)
uci:set(appname, node_id, "fallback_node", server) uci:set(c_config, node_id, "fallback_node", server)
o.newNodeId = server o.newNodeId = server
end, end,
delete = function(o) delete = function(o)
uci:delete(appname, node_id, "fallback_node") uci:delete(c_config, node_id, "fallback_node")
end end
} }
end end
@@ -375,7 +376,7 @@ do
log = true, log = true,
node = u_node_id, node = u_node_id,
currentNode = (function() currentNode = (function()
local section = uci:get_all(appname, u_node_id) or {} local section = uci:get_all(c_config, u_node_id) or {}
if section[".type"] == "socks" then if section[".type"] == "socks" then
return { Socks = u_node_id } return { Socks = u_node_id }
end end
@@ -397,47 +398,47 @@ do
set = function(o, newNodes) set = function(o, newNodes)
if o then if o then
if not newNodes then newNodes = o.newNodes end if not newNodes then newNodes = o.newNodes end
uci:set_list(appname, node_id, "urltest_node", newNodes or {}) uci:set_list(c_config, node_id, "urltest_node", newNodes or {})
end end
end end
} }
else else
--前置代理节点 --前置代理节点
local currentNode = uci:get_all(appname, node_id) or nil local currentNode = uci:get_all(c_config, node_id) or nil
if currentNode and currentNode.preproxy_node then if currentNode and currentNode.preproxy_node then
local section = uci:get_all(appname, currentNode.preproxy_node) or {} local section = uci:get_all(c_config, currentNode.preproxy_node) or {}
if section[".type"] == "nodes" then if section[".type"] == "nodes" then
CONFIG[#CONFIG + 1] = { CONFIG[#CONFIG + 1] = {
log = true, log = true,
id = node_id, id = node_id,
remarks = "节点[" .. node_id .. "]前置代理节点", remarks = "节点[" .. node_id .. "]前置代理节点",
currentNode = uci:get_all(appname, currentNode.preproxy_node) or nil, currentNode = uci:get_all(c_config, currentNode.preproxy_node) or nil,
set = function(o, server) set = function(o, server)
uci:set(appname, node_id, "preproxy_node", server) uci:set(c_config, node_id, "preproxy_node", server)
o.newNodeId = server o.newNodeId = server
end, end,
delete = function(o) delete = function(o)
uci:delete(appname, node_id, "preproxy_node") uci:delete(c_config, node_id, "preproxy_node")
end end
} }
end end
end end
--落地节点 --落地节点
local currentNode = uci:get_all(appname, node_id) or nil local currentNode = uci:get_all(c_config, node_id) or nil
if currentNode and currentNode.to_node then if currentNode and currentNode.to_node then
local section = uci:get_all(appname, currentNode.to_node) or {} local section = uci:get_all(c_config, currentNode.to_node) or {}
if section[".type"] == "nodes" then if section[".type"] == "nodes" then
CONFIG[#CONFIG + 1] = { CONFIG[#CONFIG + 1] = {
log = true, log = true,
id = node_id, id = node_id,
remarks = "节点[" .. node_id .. "]落地节点", remarks = "节点[" .. node_id .. "]落地节点",
currentNode = uci:get_all(appname, currentNode.to_node) or nil, currentNode = uci:get_all(c_config, currentNode.to_node) or nil,
set = function(o, server) set = function(o, server)
uci:set(appname, node_id, "to_node", server) uci:set(c_config, node_id, "to_node", server)
o.newNodeId = server o.newNodeId = server
end, end,
delete = function(o) delete = function(o)
uci:delete(appname, node_id, "to_node") uci:delete(c_config, node_id, "to_node")
end end
} }
end end
@@ -1756,19 +1757,19 @@ local function truncate_nodes(group)
end end
end end
end end
uci:foreach(appname, "nodes", function(node) uci:foreach(c_config, "nodes", function(node)
if node.add_mode == "2" then if node.add_mode == "2" then
if (not group) or (group:lower() == (node.group or ""):lower()) then if (not group) or (group:lower() == (node.group or ""):lower()) then
uci:delete(appname, node['.name']) uci:delete(c_config, node['.name'])
end end
end end
end) end)
uci:foreach(appname, "subscribe_list", function(o) uci:foreach(c_config, "subscribe_list", function(o)
if (not group) or (group:lower() == (o.remark or ""):lower()) then if (not group) or (group:lower() == (o.remark or ""):lower()) then
uci:delete(appname, o['.name'], "md5") uci:delete(c_config, o['.name'], "md5")
end end
end) end)
api.uci_save(uci, appname, true) api.uci_save(uci, c_config, true)
end end
local function select_node(nodes, config, parentConfig) local function select_node(nodes, config, parentConfig)
@@ -1907,10 +1908,10 @@ local function update_node(manual)
end end
if manual == 0 and next(group) then if manual == 0 and next(group) then
uci:foreach(appname, "nodes", function(node) uci:foreach(c_config, "nodes", function(node)
-- 如果未发现新节点或手动导入的节点就不要删除了... -- 如果未发现新节点或手动导入的节点就不要删除了...
if node.add_mode == "2" and (node.group and group[node.group:lower()] == true) then if node.add_mode == "2" and (node.group and group[node.group:lower()] == true) then
uci:delete(appname, node['.name']) uci:delete(c_config, node['.name'])
end end
end) end)
end end
@@ -1923,9 +1924,9 @@ local function update_node(manual)
-- Subscription Group Chain Agent -- Subscription Group Chain Agent
local function valid_chain_node(node) local function valid_chain_node(node)
if not node then return "" end if not node then return "" end
local cp = uci:get(appname, node, "chain_proxy") or "" local cp = uci:get(c_config, node, "chain_proxy") or ""
local am = uci:get(appname, node, "add_mode") or "0" local am = uci:get(c_config, node, "add_mode") or "0"
chain_node_type = (cp == "" and am ~= "2") and (uci:get(appname, node, "type") or "") or "" chain_node_type = (cp == "" and am ~= "2") and (uci:get(c_config, node, "type") or "") or ""
if chain_node_type ~= "Xray" and chain_node_type ~= "sing-box" then if chain_node_type ~= "Xray" and chain_node_type ~= "sing-box" then
chain_node_type = "" chain_node_type = ""
return "" return ""
@@ -1944,22 +1945,22 @@ local function update_node(manual)
chain_node_type = (outbound_iface_group ~= "") and "iface" or chain_node_type chain_node_type = (outbound_iface_group ~= "") and "iface" or chain_node_type
end end
for _, vv in ipairs(list) do for _, vv in ipairs(list) do
local cfgid = uci:section(appname, "nodes", api.gen_random_char()) local cfgid = uci:section(c_config, "nodes", api.gen_random_char())
for kkk, vvv in pairs(vv) do for kkk, vvv in pairs(vv) do
if type(vvv) == "table" and next(vvv) ~= nil then if type(vvv) == "table" and next(vvv) ~= nil then
uci:set_list(appname, cfgid, kkk, vvv) uci:set_list(c_config, cfgid, kkk, vvv)
else else
if kkk ~= "group" or vvv ~= "default" then if kkk ~= "group" or vvv ~= "default" then
uci:set(appname, cfgid, kkk, vvv) uci:set(c_config, cfgid, kkk, vvv)
end end
-- sing-box/xray 节点域名解析 -- sing-box/xray 节点域名解析
if kkk == "type" and (vvv == "Xray" or vvv == "sing-box") then if kkk == "type" and (vvv == "Xray" or vvv == "sing-box") then
if domain_resolver then if domain_resolver then
uci:set(appname, cfgid, "domain_resolver", domain_resolver) uci:set(c_config, cfgid, "domain_resolver", domain_resolver)
if domain_resolver_dns then if domain_resolver_dns then
uci:set(appname, cfgid, "domain_resolver_dns", domain_resolver_dns) uci:set(c_config, cfgid, "domain_resolver_dns", domain_resolver_dns)
elseif domain_resolver_dns_https then elseif domain_resolver_dns_https then
uci:set(appname, cfgid, "domain_resolver_dns_https", domain_resolver_dns_https) uci:set(c_config, cfgid, "domain_resolver_dns_https", domain_resolver_dns_https)
end end
end end
if domain_strategy then if domain_strategy then
@@ -1968,20 +1969,20 @@ local function update_node(manual)
local map = { UseIPv4v6 = "prefer_ipv4", UseIPv6v4 = "prefer_ipv6", UseIPv4 = "ipv4_only", UseIPv6 = "ipv6_only" } local map = { UseIPv4v6 = "prefer_ipv4", UseIPv6v4 = "prefer_ipv6", UseIPv4 = "ipv4_only", UseIPv6 = "ipv6_only" }
ds = map[ds] or "" ds = map[ds] or ""
end end
uci:set(appname, cfgid, "domain_strategy", ds) uci:set(c_config, cfgid, "domain_strategy", ds)
end end
end end
-- 订阅组链式代理 -- 订阅组链式代理
if chain_node_type ~= "" and kkk == "type" and (vvv == "Xray" or vvv == "sing-box") then if chain_node_type ~= "" and kkk == "type" and (vvv == "Xray" or vvv == "sing-box") then
if preproxy_node_group ~="" then if preproxy_node_group ~="" then
uci:set(appname, cfgid, "chain_proxy", "1") uci:set(c_config, cfgid, "chain_proxy", "1")
uci:set(appname, cfgid, "preproxy_node", preproxy_node_group) uci:set(c_config, cfgid, "preproxy_node", preproxy_node_group)
elseif to_node_group ~= "" then elseif to_node_group ~= "" then
uci:set(appname, cfgid, "chain_proxy", "2") uci:set(c_config, cfgid, "chain_proxy", "2")
uci:set(appname, cfgid, "to_node", to_node_group) uci:set(c_config, cfgid, "to_node", to_node_group)
elseif outbound_iface_group ~= "" then elseif outbound_iface_group ~= "" then
uci:set(appname, cfgid, "chain_proxy", "3") uci:set(c_config, cfgid, "chain_proxy", "3")
uci:set(appname, cfgid, "outbound_iface", outbound_iface_group) uci:set(c_config, cfgid, "outbound_iface", outbound_iface_group)
end end
end end
end end
@@ -1992,16 +1993,16 @@ local function update_node(manual)
for cfgid, info in pairs(subscribe_info) do for cfgid, info in pairs(subscribe_info) do
for key, value in pairs(info) do for key, value in pairs(info) do
if value ~= "" then if value ~= "" then
uci:set(appname, cfgid, key, value) uci:set(c_config, cfgid, key, value)
else else
uci:delete(appname, cfgid, key) uci:delete(c_config, cfgid, key)
end end
end end
end end
if next(CONFIG) then if next(CONFIG) then
local nodes = {} local nodes = {}
uci:foreach(appname, "nodes", function(node) uci:foreach(c_config, "nodes", function(node)
nodes[#nodes + 1] = node nodes[#nodes + 1] = node
end) end)
@@ -2020,11 +2021,11 @@ local function update_node(manual)
end end
end end
api.uci_save(uci, appname, true) api.uci_save(uci, c_config, true)
if arg[3] == "cron" then if arg[3] == "cron" then
if not fs.access("/var/lock/" .. appname .. ".lock") then if not fs.access("/var/lock/" .. c_config .. ".lock") then
luci.sys.call("touch /tmp/lock/" .. appname .. "_cron.lock") luci.sys.call("touch /tmp/lock/" .. c_config .. "_cron.lock")
end end
end end
@@ -2133,10 +2134,10 @@ local execute = function()
local fail_list = {} local fail_list = {}
if arg[2] ~= "all" then if arg[2] ~= "all" then
string.gsub(arg[2], '[^' .. "," .. ']+', function(w) string.gsub(arg[2], '[^' .. "," .. ']+', function(w)
subscribe_list[#subscribe_list + 1] = uci:get_all(appname, w) or {} subscribe_list[#subscribe_list + 1] = uci:get_all(c_config, w) or {}
end) end)
else else
uci:foreach(appname, "subscribe_list", function(o) uci:foreach(c_config, "subscribe_list", function(o)
subscribe_list[#subscribe_list + 1] = o subscribe_list[#subscribe_list + 1] = o
end) end)
end end
@@ -2182,7 +2183,7 @@ local execute = function()
raw_data = parseClashNode(raw_data) raw_data = parseClashNode(raw_data)
subscribe_info[cfgid] = parse_clash_sub_info(headers) subscribe_info[cfgid] = parse_clash_sub_info(headers)
parse_link(raw_data, "2", remark, value) parse_link(raw_data, "2", remark, value)
uci:set(appname, cfgid, "md5", new_md5) uci:set(c_config, cfgid, "md5", new_md5)
end end
else else
fail_list[#fail_list + 1] = value fail_list[#fail_list + 1] = value
@@ -2216,7 +2217,7 @@ local function check_instance(action)
os.exit(0) os.exit(0)
else else
luci.sys.call("touch " .. sub_lock) luci.sys.call("touch " .. sub_lock)
uci:revert(appname) uci:revert(c_config)
end end
elseif action == "end" then elseif action == "end" then
luci.sys.call("rm -f " .. sub_lock) luci.sys.call("rm -f " .. sub_lock)
@@ -204,7 +204,7 @@ end
current_node = current_node_id and m:get(current_node_id) or {} current_node = current_node_id and m:get(current_node_id) or {}
o = s:option(Flag, "log", translate("Enable Node Log")) o = s:option(Flag, "log", translate("Enable Node Log"))
o:depends({ _hide_node_option = "1", ['!reverse'] = true }) o:depends({ node = "", ['!reverse'] = true })
o = s:option(ListValue, "loglevel", translate("Log Level")) o = s:option(ListValue, "loglevel", translate("Log Level"))
o.default = "warn" o.default = "warn"
@@ -352,6 +352,10 @@ o:depends("remote_dns_protocol", "http3")
o:depends("remote_dns_protocol", "quic") o:depends("remote_dns_protocol", "quic")
o:depends("remote_dns_protocol", "tls") o:depends("remote_dns_protocol", "tls")
o = s:option(Value, "remote_rewrite_ttl", translate("Remote DNS") .. " TTL")
o.datatype = "min(1)"
o.default = "30"
o = s:option(ListValue, "dns_hosts_mode", translate("Domain Override")) o = s:option(ListValue, "dns_hosts_mode", translate("Domain Override"))
o:value("default", translate("Use global config")) o:value("default", translate("Use global config"))
o:value("disable", translate("No patterns are used")) o:value("disable", translate("No patterns are used"))
@@ -377,6 +381,9 @@ local o_node = s.fields["node"]
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o_node:value(v.id, v["remark"]) o_node:value(v.id, v["remark"])
o_node.group[#o_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default") o_node.group[#o_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
if v.type == "sing-box" then
s.fields["remote_rewrite_ttl"]:depends({ node = v.id })
end
if v.node_type == "normal" or v.protocol == "_balancing" or v.protocol == "_urltest" then if v.node_type == "normal" or v.protocol == "_balancing" or v.protocol == "_urltest" then
--Shunt node has its own separate options. --Shunt node has its own separate options.
s.fields["remote_fakedns"]:depends({ node = v.id, remote_dns_protocol = "tcp" }) s.fields["remote_fakedns"]:depends({ node = v.id, remote_dns_protocol = "tcp" })
@@ -234,6 +234,12 @@ o:value("UseIP")
o:value("UseIPv4") o:value("UseIPv4")
o:value("UseIPv6") o:value("UseIPv6")
if current_node.type == "sing-box" then
o = s:taboption("DNS", Value, "remote_rewrite_ttl", translate("Remote DNS") .. " TTL")
o.datatype = "min(1)"
o.default = "30"
end
o = s:taboption("DNS", TextValue, "dns_hosts", translate("Domain Override")) o = s:taboption("DNS", TextValue, "dns_hosts", translate("Domain Override"))
o.rows = 5 o.rows = 5
o.wrap = "off" o.wrap = "off"
@@ -1116,6 +1116,7 @@ function gen_config(var)
local remote_dns_query_strategy = var["remote_dns_query_strategy"] local remote_dns_query_strategy = var["remote_dns_query_strategy"]
local remote_dns_fake = var["remote_dns_fake"] local remote_dns_fake = var["remote_dns_fake"]
local remote_dns_client_ip = var["remote_dns_client_ip"] local remote_dns_client_ip = var["remote_dns_client_ip"]
local remote_rewrite_ttl = var["remote_rewrite_ttl"] or "30"
local dns_cache = var["dns_cache"] local dns_cache = var["dns_cache"]
local tags = var["tags"] local tags = var["tags"]
local no_run = var["no_run"] local no_run = var["no_run"]
@@ -2026,7 +2027,7 @@ function gen_config(var)
end end
if value.outboundTag ~= "block" and value.outboundTag ~= "direct" then if value.outboundTag ~= "block" and value.outboundTag ~= "direct" then
dns_rule.server = "remote" dns_rule.server = "remote"
dns_rule.rewrite_ttl = 30 dns_rule.rewrite_ttl = tonumber(remote_rewrite_ttl)
if true then if true then
local block_rule local block_rule
if remote_strategy == "ipv4_only" then if remote_strategy == "ipv4_only" then
@@ -2073,29 +2074,42 @@ function gen_config(var)
end end
end end
if default_dns_flag == "remote" then if default_dns_flag == "remote" then
local block_rule
local dns_rule_query_type = { "A", "AAAA" } local dns_rule_query_type = { "A", "AAAA" }
if remote_strategy == "ipv4_only" then if remote_strategy == "ipv4_only" then
block_rule = {
query_type = { "AAAA" },
action = "predefined",
rcode = "NOERROR"
}
dns_rule_query_type = { "A" } dns_rule_query_type = { "A" }
elseif remote_strategy == "ipv6_only" then elseif remote_strategy == "ipv6_only" then
block_rule = {
query_type = { "A" },
action = "predefined",
rcode = "NOERROR"
}
dns_rule_query_type = { "AAAA" } dns_rule_query_type = { "AAAA" }
end end
if block_rule then
table.insert(dns.rules, block_rule)
end
if remote_dns_fake then if remote_dns_fake then
-- When default is not direct and enable fakedns, default DNS use FakeDNS. -- When default is not direct and enable fakedns, default DNS use FakeDNS.
local fakedns_dns_rule = { local fakedns_dns_rule = {
query_type = dns_rule_query_type, query_type = dns_rule_query_type,
server = fakedns_tag, server = fakedns_tag,
disable_cache = true, disable_cache = true,
rewrite_ttl = 30 rewrite_ttl = tonumber(remote_rewrite_ttl)
} }
table.insert(dns.rules, fakedns_dns_rule) table.insert(dns.rules, fakedns_dns_rule)
else
local remote_dns_rule = {
query_type = dns_rule_query_type,
server = "remote",
disable_cache = true,
}
table.insert(dns.rules, remote_dns_rule)
end end
local remote_dns_rule = {
server = "remote",
disable_cache = true,
rewrite_ttl = tonumber(remote_rewrite_ttl)
}
table.insert(dns.rules, remote_dns_rule)
end end
local dns_in_inbound = { local dns_in_inbound = {
type = "direct", type = "direct",
@@ -201,7 +201,7 @@ run_xray() {
run_singbox() { run_singbox() {
local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy remote_rewrite_ttl dns_cache
local loglevel log_file config_file local loglevel log_file config_file
eval_set_val $@ eval_set_val $@
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
@@ -317,6 +317,7 @@ run_singbox() {
[ -n "$dns_listen_port" ] && json_add_string "dns_listen_port" "${dns_listen_port}" [ -n "$dns_listen_port" ] && json_add_string "dns_listen_port" "${dns_listen_port}"
[ -n "$dns_cache" ] && json_add_string "dns_cache" "${dns_cache}" [ -n "$dns_cache" ] && json_add_string "dns_cache" "${dns_cache}"
[ "$remote_fakedns" = "1" ] && json_add_string "remote_dns_fake" "1" [ "$remote_fakedns" = "1" ] && json_add_string "remote_dns_fake" "1"
[ -n "$remote_rewrite_ttl" ] && json_add_string "remote_rewrite_ttl" "${remote_rewrite_ttl}"
} }
json_add_string "direct_dns_udp_port" "${DIRECT_DNS_UDP_PORT}" json_add_string "direct_dns_udp_port" "${DIRECT_DNS_UDP_PORT}"
json_add_string "direct_dns_udp_server" "${DIRECT_DNS_UDP_SERVER}" json_add_string "direct_dns_udp_server" "${DIRECT_DNS_UDP_SERVER}"
@@ -612,6 +613,7 @@ run_global() {
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip) local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
[ -n "${_remote_dns_client_ip}" ] && V2RAY_ARGS="${V2RAY_ARGS} remote_dns_client_ip=${_remote_dns_client_ip}" [ -n "${_remote_dns_client_ip}" ] && V2RAY_ARGS="${V2RAY_ARGS} remote_dns_client_ip=${_remote_dns_client_ip}"
V2RAY_ARGS="${V2RAY_ARGS} remote_rewrite_ttl=$(config_t_get global remote_rewrite_ttl)"
} }
dns_msg="${dns_msg})" dns_msg="${dns_msg})"
@@ -982,7 +984,7 @@ acl_app() {
dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400} dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400}
for sid in $items; do for sid in $items; do
index=$(expr $index + 1) index=$(expr $index + 1)
local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy log loglevel log_file local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy remote_rewrite_ttl log loglevel log_file
local _ip _mac _iprange _ipset _ip_or_mac source_list config_file local _ip _mac _iprange _ipset _ip_or_mac source_list config_file
[ "$(config_n_get $sid enabled)" = "1" ] || continue [ "$(config_n_get $sid enabled)" = "1" ] || continue
has_enabled=1 has_enabled=1
@@ -1086,7 +1088,8 @@ acl_app() {
dns_listen_port=${dns_port} \ dns_listen_port=${dns_port} \
direct_dns_query_strategy=${direct_dns_query_strategy} \ direct_dns_query_strategy=${direct_dns_query_strategy} \
remote_dns_protocol=${remote_dns_protocol} remote_dns_tcp_server=${remote_dns} remote_dns_udp_server=${remote_dns} remote_dns_doh="${remote_dns}" \ remote_dns_protocol=${remote_dns_protocol} remote_dns_tcp_server=${remote_dns} remote_dns_udp_server=${remote_dns} remote_dns_doh="${remote_dns}" \
remote_dns_client_ip=${remote_dns_client_ip} remote_dns_detour=${remote_dns_detour} remote_fakedns=${remote_fakedns} remote_dns_query_strategy=${remote_dns_query_strategy} \ remote_dns_client_ip=${remote_dns_client_ip} remote_dns_detour=${remote_dns_detour} remote_dns_query_strategy=${remote_dns_query_strategy} \
remote_fakedns=${remote_fakedns} remote_rewrite_ttl=${remote_rewrite_ttl} \
config_file=${config_file} \ config_file=${config_file} \
log_file="${log_file}" loglevel="${loglevel}" log_file="${log_file}" loglevel="${loglevel}"
local status=$? local status=$?
@@ -1108,7 +1111,7 @@ acl_app() {
} }
fi fi
} }
unset enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy unset enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy remote_rewrite_ttl
unset _ip _mac _iprange _ipset _ip_or_mac source_list config_file unset _ip _mac _iprange _ipset _ip_or_mac source_list config_file
done done
unset redir_port dns_port dnsmasq_port unset redir_port dns_port dnsmasq_port
+22
View File
@@ -0,0 +1,22 @@
# Copyright (C) 2020 Gyj1109
# 适配 OpenWrt 25.12 修改版
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-syncthing
PKG_VERSION:=1.0
PKG_RELEASE:=3
LUCI_TITLE:=LuCI support for Syncthing
LUCI_PKGARCH:=all
# 适配 25.12:确保安装了 syncthing 后,LuCI 界面能正确拉起
LUCI_DEPENDS:=+syncthing
include $(TOPDIR)/feeds/luci/luci.mk
# 明确定义配置文件的归属,这对 25.12 的 apk 管理器非常重要
define Package/$(PKG_NAME)/conffiles
/etc/config/syncthing
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
+2
View File
@@ -0,0 +1,2 @@
# luci-app-syncthing
在Potat0000源码基础上进行了汉化优化,官方openwrt23.05.3编译后可使用
@@ -0,0 +1,17 @@
module("luci.controller.syncthing", package.seeall)
function index()
if not nixio.fs.access("/etc/config/syncthing") then
return
end
entry({"admin", "services", "syncthing"}, cbi("syncthing"), _("文件同步"), 10).dependent = true
entry({"admin", "services", "syncthing", "status"}, call("act_status")).leaf = true
end
function act_status()
local e = {}
e.running = luci.sys.call("pgrep syncthing >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
@@ -0,0 +1,48 @@
require("nixio.fs")
m = Map("syncthing", translate("Syncthing同步工具"))
m:section(SimpleSection).template = "syncthing/syncthing_status"
s = m:section(TypedSection, "syncthing")
s.anonymous = true
o = s:option(Flag, "enabled", translate("启用"))
o.default = 0
o.rmempty = false
gui_address = s:option(Value, "gui_address", translate("GUI访问地址"))
gui_address.description = translate("使用0.0.0.0以监控所有访问。")
gui_address.default = "http://0.0.0.0:8384"
gui_address.placeholder = "http://0.0.0.0:8384"
gui_address.rmempty = false
home = s:option(Value, "home", translate("配置文件目录"))
home.description = translate("只有保存在/etc/syncthing中的配置会自动备份!")
home.default = "/etc/syncthing"
home.placeholder = "/etc/syncthing"
home.rmempty = false
user = s:option(ListValue, "user", translate("用户"))
user.description = translate("默认是syncthing,但这可能会导致权限被拒绝。Syncthing官方不建议以root身份运行。")
user:value("", translate("syncthing"))
for u in luci.util.execi("cat /etc/passwd | cut -d ':' -f1") do
user:value(u)
end
macprocs = s:option(Value, "macprocs", translate("线程限制"))
macprocs.description = translate("0表示匹配CPU数量(默认),>0表示显式指定并发数。")
macprocs.default = "0"
macprocs.placeholder = "0"
macprocs.datatype = "range(0,32)"
macprocs.rmempty = false
nice = s:option(Value, "nice", translate("优先级"))
nice.description = translate("显式指定优先级值。0是最高,19是最低。(暂时不允许设置负值)")
nice.default = "19"
nice.placeholder = "19"
nice.datatype = "range(0,19)"
nice.rmempty = false
return m
@@ -0,0 +1,27 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(1, '<%=url([[admin]], [[services]], [[syncthing]], [[status]])%>', null,
function (x, data) {
var tb = document.getElementById('syncthing_status');
if (data && tb) {
if (data.running) {
var links = '<em><b><font color="green">Syncthing <%:运行中%></font></b></em><input class="btn cbi-button mar-10" type="button" value="<%:打开Syncthing页面%>" onclick="openwebui();" />';
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><b><font color="red">Syncthing <%:未运行%></font></b></em>';
}
}
}
);
function openwebui(){
var url = window.location.host+":<%=luci.sys.exec("uci -q get syncthing.syncthing.gui_address"):match(":[0-9]+"):gsub(":", "")%>";
window.open('http://'+url,'target','');
}
//]]>
</script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="syncthing_status">
<em><%:正在收集数据...%></em>
</p>
</fieldset>
@@ -0,0 +1,12 @@
#!/bin/sh
touch /etc/config/syncthing
uci -q batch <<-EOF >/dev/null
delete ucitrack.@syncthing[-1]
add ucitrack syncthing
set ucitrack.@syncthing[-1].exec='/etc/init.d/syncthing stop && /etc/init.d/syncthing start'
commit ucitrack
EOF
# remove LuCI cache
rm -f /tmp/luci*
exit 0
@@ -0,0 +1,11 @@
{
"luci-app-syncthing": {
"description": "Grant UCI access for luci-app-syncthing",
"read": {
"uci": [ "syncthing" ]
},
"write": {
"uci": [ "syncthing" ]
}
}
}