update 2026-08-14 04:36:07

This commit is contained in:
action committed 2026-08-14 04:36:07 +08:00
1 parent e716bb6996
commit 5ce413d3a3
74 files changed
+693 -819

No files matched your search

+118 -114
View File
@@ -4,6 +4,8 @@
module("luci.controller.passwall2", package.seeall)
local api = require "luci.passwall2.api"
local appname = api.appname -- not available
local c_config = api.c_config -- not available
local s_config = api.s_config -- not available
local uci = api.uci -- in funtion index()
local http = require "luci.http"
local util = require "luci.util"
@@ -20,12 +22,14 @@ function index()
end
local api = require "luci.passwall2.api"
local appname = api.appname -- global definitions not available
local c_config = api.c_config -- not available
local s_config = api.s_config -- not available
local uci = api.uci -- in function index()
entry({"admin", "services", appname}).dependent = true
entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true
entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true
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"), _("PassWall 2"), 0)
else
e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), nil, 0)
@@ -137,7 +141,7 @@ local function http_write_json_error(data)
end
function reset_config()
uci:revert(appname)
uci:revert(c_config)
luci.sys.call("echo '' > /tmp/log/passwall2.log")
luci.sys.call('/etc/init.d/passwall2 stop')
luci.sys.call('[ -f "/usr/share/passwall2/0_default_config" ] && cp -f /usr/share/passwall2/0_default_config /etc/config/passwall2')
@@ -145,14 +149,14 @@ function reset_config()
end
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("/etc/init.d/rpcd restart >/dev/null")
http.redirect(api.url())
end
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("/etc/init.d/rpcd restart >/dev/null")
http.redirect(luci.dispatcher.build_url("admin", "status", "overview"))
@@ -188,10 +192,10 @@ function socks_autoswitch_add_node()
local id = http.formvalue("id")
local key = http.formvalue("key")
if id and id ~= "" and key and key ~= "" then
uci:set(appname, id, "enable_autoswitch", "1")
local new_list = uci:get(appname, id, "autoswitch_backup_node") or {}
uci:set(c_config, id, "enable_autoswitch", "1")
local new_list = uci:get(c_config, id, "autoswitch_backup_node") or {}
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)
end
end
@@ -200,8 +204,8 @@ function socks_autoswitch_add_node()
table.insert(new_list, e.id)
end
end
uci:set_list(appname, id, "autoswitch_backup_node", new_list)
api.uci_save(uci, appname)
uci:set_list(c_config, id, "autoswitch_backup_node", new_list)
api.uci_save(uci, c_config)
end
http.redirect(api.url("socks_config", id))
end
@@ -210,15 +214,15 @@ function socks_autoswitch_remove_node()
local id = http.formvalue("id")
local key = http.formvalue("key")
if id and id ~= "" and key and key ~= "" then
uci:set(appname, id, "enable_autoswitch", "1")
local new_list = uci:get(appname, id, "autoswitch_backup_node") or {}
uci:set(c_config, id, "enable_autoswitch", "1")
local new_list = uci:get(c_config, id, "autoswitch_backup_node") or {}
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)
end
end
uci:set_list(appname, id, "autoswitch_backup_node", new_list)
api.uci_save(uci, appname)
uci:set_list(c_config, id, "autoswitch_backup_node", new_list)
api.uci_save(uci, c_config)
end
http.redirect(api.url("socks_config", id))
end
@@ -309,7 +313,7 @@ function socks_status()
local id = http.formvalue("id")
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
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
if tonumber(use_http) > 0 then
e.use_http = 1
@@ -379,9 +383,9 @@ function update_config()
local data_t = jsonParse(data) or {}
if next(data_t) then
for k, v in pairs(data_t) do
uci:set(appname, id, k, v)
uci:set(c_config, id, k, v)
end
api.uci_save(uci, appname)
api.uci_save(uci, c_config)
http_write_json_ok()
return
end
@@ -393,20 +397,20 @@ function add_node()
local redirect = http.formvalue("redirect")
local uid = api.gen_random_char()
uci:section(appname, "nodes", uid)
uci:section(c_config, "nodes", uid)
local group = http.formvalue("group")
if group and group ~= "default" then
uci:set(appname, uid, "group", group)
uci:set(c_config, uid, "group", group)
end
uci:set(appname, uid, "type", "Xray")
uci:set(c_config, uid, "type", "Xray")
if redirect == "1" then
api.uci_save(uci, appname)
api.uci_save(uci, c_config)
http.redirect(api.url("node_config", uid))
else
api.uci_save(uci, appname, true, true)
api.uci_save(uci, c_config, true, true)
http_write_json({result = uid})
end
end
@@ -415,67 +419,67 @@ function set_node()
local type = http.formvalue("type")
local config = http.formvalue("config")
local section = http.formvalue("section")
uci:set(appname, type, config, section)
api.uci_save(uci, appname, true, true)
uci:set(c_config, type, config, section)
api.uci_save(uci, c_config, true, true)
http.redirect(api.url("log"))
end
function copy_node()
local section = http.formvalue("section")
local uid = api.gen_random_char()
uci:section(appname, "nodes", uid)
for k, v in pairs(uci:get_all(appname, section)) do
uci:section(c_config, "nodes", uid)
for k, v in pairs(uci:get_all(c_config, section)) do
if not k:match("^%.") and k ~= "group" then
if k == "remarks" then v = (v or "") .. "(1)" end
uci:set(appname, uid, k, v)
uci:set(c_config, uid, k, v)
end
end
uci:set(appname, uid, "add_mode", 1)
api.uci_save(uci, appname)
uci:set(c_config, uid, "add_mode", 1)
api.uci_save(uci, c_config)
http.redirect(api.url("node_config", uid))
end
function clear_all_nodes()
uci:set(appname, '@global[0]', "enabled", "0")
uci:set(appname, '@global[0]', "socks_enabled", "0")
uci:set(appname, '@global_haproxy[0]', "balancing_enable", "0")
uci:delete(appname, '@global[0]', "node")
uci:foreach(appname, "socks", function(t)
uci:delete(appname, t[".name"])
uci:set_list(appname, t[".name"], "autoswitch_backup_node", {})
uci:set(c_config, '@global[0]', "enabled", "0")
uci:set(c_config, '@global[0]', "socks_enabled", "0")
uci:set(c_config, '@global_haproxy[0]', "balancing_enable", "0")
uci:delete(c_config, '@global[0]', "node")
uci:foreach(c_config, "socks", function(t)
uci:delete(c_config, t[".name"])
uci:set_list(c_config, t[".name"], "autoswitch_backup_node", {})
end)
uci:foreach(appname, "haproxy_config", function(t)
uci:delete(appname, t[".name"])
uci:foreach(c_config, "haproxy_config", function(t)
uci:delete(c_config, t[".name"])
end)
uci:foreach(appname, "acl_rule", function(t)
uci:delete(appname, t[".name"], "node")
uci:foreach(c_config, "acl_rule", function(t)
uci:delete(c_config, t[".name"], "node")
end)
uci:foreach(appname, "nodes", function(node)
uci:delete(appname, node['.name'])
uci:foreach(c_config, "nodes", function(node)
uci:delete(c_config, node['.name'])
end)
uci:foreach(appname, "subscribe_list", function(t)
uci:delete(appname, t[".name"], "md5")
uci:delete(appname, t[".name"], "chain_proxy")
uci:delete(appname, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "to_node")
uci:foreach(c_config, "subscribe_list", function(t)
uci:delete(c_config, t[".name"], "md5")
uci:delete(c_config, t[".name"], "chain_proxy")
uci:delete(c_config, t[".name"], "preproxy_node")
uci:delete(c_config, t[".name"], "to_node")
end)
api.uci_save(uci, appname, true, true)
api.uci_save(uci, c_config, true, true)
end
function delete_select_nodes()
local ids = http.formvalue("ids")
local redirect = http.formvalue("redirect")
string.gsub(ids, '[^' .. "," .. ']+', function(w)
if (uci:get(appname, "@global[0]", "node") or "") == w then
uci:delete(appname, '@global[0]', "node")
if (uci:get(c_config, "@global[0]", "node") or "") == w then
uci:delete(c_config, '@global[0]', "node")
end
uci:foreach(appname, "socks", function(t)
uci:foreach(c_config, "socks", function(t)
if t["node"] == w then
uci:delete(appname, t[".name"])
uci:delete(c_config, t[".name"])
end
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
if w == auto_switch_node_list[i] then
table.remove(auto_switch_node_list, i)
@@ -483,31 +487,31 @@ function delete_select_nodes()
end
end
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)
uci:foreach(appname, "haproxy_config", function(t)
uci:foreach(c_config, "haproxy_config", function(t)
if t["lbss"] == w then
uci:delete(appname, t[".name"])
uci:delete(c_config, t[".name"])
end
end)
uci:foreach(appname, "acl_rule", function(t)
uci:foreach(c_config, "acl_rule", function(t)
if t["node"] == w then
uci:delete(appname, t[".name"], "node")
uci:delete(c_config, t[".name"], "node")
end
end)
uci:foreach(appname, "nodes", function(t)
uci:foreach(c_config, "nodes", function(t)
if t["preproxy_node"] == w then
uci:delete(appname, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "chain_proxy")
uci:delete(c_config, t[".name"], "preproxy_node")
uci:delete(c_config, t[".name"], "chain_proxy")
end
if t["to_node"] == w then
uci:delete(appname, t[".name"], "to_node")
uci:delete(appname, t[".name"], "chain_proxy")
uci:delete(c_config, t[".name"], "to_node")
uci:delete(c_config, t[".name"], "chain_proxy")
end
local list_name = t["urltest_node"] and "urltest_node" or (t["balancing_node"] and "balancing_node")
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
local changed = false
local new_nodes = {}
@@ -519,48 +523,48 @@ function delete_select_nodes()
end
end
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
if t["fallback_node"] == w then
uci:delete(appname, t[".name"], "fallback_node")
uci:delete(c_config, t[".name"], "fallback_node")
end
end)
uci:foreach(appname, "subscribe_list", function(t)
uci:foreach(c_config, "subscribe_list", function(t)
if t["preproxy_node"] == w then
uci:delete(appname, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "chain_proxy")
uci:delete(c_config, t[".name"], "preproxy_node")
uci:delete(c_config, t[".name"], "chain_proxy")
end
if t["to_node"] == w then
uci:delete(appname, t[".name"], "to_node")
uci:delete(appname, t[".name"], "chain_proxy")
uci:delete(c_config, t[".name"], "to_node")
uci:delete(c_config, t[".name"], "chain_proxy")
end
end)
if (uci:get(appname, w, "add_mode") or "0") == "2" then
local group = uci:get(appname, w, "group") or ""
if (uci:get(c_config, w, "add_mode") or "0") == "2" then
local group = uci:get(c_config, w, "group") or ""
if group ~= "" then
uci:foreach(appname, "subscribe_list", function(t)
uci:foreach(c_config, "subscribe_list", function(t)
if t["remark"] == group then
uci:delete(appname, t[".name"], "md5")
uci:delete(c_config, t[".name"], "md5")
end
end)
end
end
uci:delete(appname, w)
uci:delete(c_config, w)
end)
if redirect == "1" then
api.uci_save(uci, appname)
api.uci_save(uci, c_config)
http.redirect(api.url("node_list"))
else
api.uci_save(uci, appname, true, true)
api.uci_save(uci, c_config, true, true)
end
end
function get_node()
local id = http.formvalue("id")
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)
if o and o.address and show_node_info == "1" then
@@ -573,12 +577,12 @@ function get_node()
end
if id then
result = uci:get_all(appname, id)
result = uci:get_all(c_config, id)
add_is_ipv6_key(result)
else
local default_nodes = {}
local other_nodes = {}
uci:foreach(appname, "nodes", function(t)
uci:foreach(c_config, "nodes", function(t)
add_is_ipv6_key(t)
if not t.group or t.group == "" then
default_nodes[#default_nodes + 1] = t
@@ -597,12 +601,12 @@ function reassign_group()
local group = http.formvalue("group") or "default"
for id in ids:gmatch("([^,]+)") do
if group ~="" and group ~= "default" then
api.sh_uci_set(appname, id, "group", group)
api.sh_uci_set(c_config, id, "group", group)
else
api.sh_uci_del(appname, id, "group")
api.sh_uci_del(c_config, id, "group")
end
end
api.sh_uci_commit(appname)
api.sh_uci_commit(c_config)
http_write_json({ status = "ok" })
end
@@ -610,7 +614,7 @@ function save_node_list_opt()
local option = http.formvalue("option") or ""
local value = http.formvalue("value") or ""
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
http_write_json({ status = "ok" })
end
@@ -632,7 +636,7 @@ function rollback_rules()
return
end
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/")
fs.move(bak_dir .. arg_type .. ".dat", geo_dir .. arg_type .. ".dat")
fs.rmdir(bak_dir)
http_write_json_ok()
@@ -645,9 +649,9 @@ function server_update_config()
local data_t = jsonParse(data) or {}
if next(data_t) then
for k, v in pairs(data_t) do
uci:set(appname .. "_server", id, k, v)
uci:set(c_config .. "_server", id, k, v)
end
api.uci_save(uci, appname .. "_server")
api.uci_save(uci, c_config .. "_server")
http_write_json_ok()
return
end
@@ -758,7 +762,7 @@ function restore_backup()
fp:write(decoded)
fp:close()
if chunk_index + 1 == total_chunks then
uci:revert(appname)
uci:revert(c_config)
api.sys.call("echo '' > /tmp/log/passwall2.log")
api.log(0, string.format(" * PassWall2 %s", i18n.translate("Configuration file uploaded successfully…")))
local temp_dir = '/tmp/passwall2_bak'
@@ -801,7 +805,7 @@ function geo_view()
end
local function get_rules(str, type)
local rules_id = {}
uci:foreach(appname, "shunt_rules", function(s)
uci:foreach(c_config, "shunt_rules", function(s)
local list
if type == "geoip" then list = s.ip_list else list = s.domain_list end
for line in string.gmatch((list or ""), "[^\r\n]+") do
@@ -818,7 +822,7 @@ function geo_view()
end)
return rules_id
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 geoip_path = geo_dir .. "/geoip.dat"
local geo_type, file_path, cmd
@@ -890,13 +894,13 @@ function subscribe_manual()
http_write_json({ success = false, msg = "Missing section or URL, skip." })
return
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
http_write_json({ success = false, msg = i18n.translate("Please save and apply before manually subscribing.") })
return
end
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
luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start " .. section .. " manual >/dev/null 2>&1 &")
http_write_json({ success = true, msg = "Subscribe triggered." })
@@ -913,7 +917,7 @@ function subscribe_manual_all()
local url_list = util.split(urls, ",")
-- Check if there are any unsaved configurations.
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
http_write_json({ success = false, msg = i18n.translate("Please save and apply before manually subscribing.") })
return
@@ -922,9 +926,9 @@ function subscribe_manual_all()
-- Save URLs that have changed.
for i, section in ipairs(section_list) do
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
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 all manual >/dev/null 2>&1 &")
@@ -935,10 +939,10 @@ function flush_set()
local redirect = http.formvalue("redirect") or "0"
local reload = http.formvalue("reload") or "0"
if reload == "1" then
uci:set(appname, '@global[0]', "flush_set", "1")
api.uci_save(uci, appname, true, true)
uci:set(c_config, '@global[0]', "flush_set", "1")
api.uci_save(uci, c_config, true, true)
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
if redirect == "1" then
http.redirect(api.url("log"))
@@ -947,9 +951,9 @@ end
function fetch_certsha256()
local id = http.formvalue("id") or ""
local address = (id ~= "") and uci:get(appname, id, "address") or ""
local port = (id ~= "") and uci:get(appname, id, "port") or 0
local sni = (id ~= "") and uci:get(appname, id, "tls_serverName") or ""
local address = (id ~= "") and uci:get(c_config, id, "address") or ""
local port = (id ~= "") and uci:get(c_config, id, "port") or 0
local sni = (id ~= "") and uci:get(c_config, id, "tls_serverName") or ""
sni = (sni ~= "") and sni or address
if address == "" or port == 0 then
http_write_json_error()
@@ -964,11 +968,11 @@ function get_shunt_rules()
local result = {}
if id then
result = uci:get_all(appname, id)
result = uci:get_all(c_config, id)
else
local default_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
default_items[#default_items + 1] = t
else
@@ -987,7 +991,7 @@ function add_shunt_rule()
local uid = add_name
if add_name then
local has = uci:get(appname, uid)
local has = uci:get(c_config, uid)
if has then
http_write_json_error({ message = i18n.translate("This ID already exists.") })
return
@@ -995,18 +999,18 @@ function add_shunt_rule()
else
uid = api.gen_random_char()
end
uci:section(appname, "shunt_rules", uid)
uci:section(c_config, "shunt_rules", uid)
local group = http.formvalue("group")
if group and group ~= "default" then
uci:set(appname, uid, "group", group)
uci:set(c_config, uid, "group", group)
end
if redirect == "1" then
api.uci_save(uci, appname)
api.uci_save(uci, c_config)
http.redirect(api.url("shunt_rules", uid))
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)})
end
end
@@ -1015,17 +1019,17 @@ function delete_select_shunt_rules()
local ids = http.formvalue("ids")
local redirect = http.formvalue("redirect")
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
uci:delete(appname, s[".name"], w)
uci:delete(c_config, s[".name"], w)
end
end)
uci:delete(appname, w)
uci:delete(c_config, w)
end)
if redirect == "1" then
api.uci_save(uci, appname)
api.uci_save(uci, c_config)
http.redirect(api.url("rule"))
else
api.uci_save(uci, appname, true, true)
api.uci_save(uci, c_config, true, true)
end
end