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_PROTO:=git
PKG_SOURCE_VERSION:=8d37150fd674731c4a5931cb82937d3c57a09301
PKG_SOURCE_VERSION:=04569ccae1bc6c926e59da5c70949010ffb55ba9
PKG_SOURCE_URL:=https://github.com/olicesx/dae.git
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)
local api = require "luci.passwall.api"
local appname = "passwall" -- not available
local uci = api.uci -- in funtion index()
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 fs = api.fs
local http = require "luci.http"
local util = require "luci.util"
@@ -20,14 +22,16 @@ function index()
else return end
end
local api = require "luci.passwall.api"
local appname = "passwall" -- global definitions not available
local uci = api.uci -- in function index()
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()
local fs = api.fs
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"), _("Pass Wall"), -1)
else
e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), nil, -1)
@@ -140,7 +144,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/passwall.log")
luci.sys.call('/etc/init.d/passwall stop')
if luci.sys.call('[ -s "/usr/share/passwall/0_default_config" ]') == 0 then
@@ -152,14 +156,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"))
@@ -195,10 +199,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
@@ -207,8 +211,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
@@ -217,15 +221,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
@@ -389,7 +393,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
@@ -481,9 +485,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
@@ -495,20 +499,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", "Socks")
uci:set(c_config, uid, "type", "Socks")
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
@@ -516,82 +520,80 @@ end
function set_node()
local protocol = http.formvalue("protocol")
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
local node_protocol = uci:get(appname, section, "protocol")
local node_protocol = uci:get(c_config, section, "protocol")
if node_protocol == "_shunt" then
local type = uci:get(appname, section, "type")
local dns_shunt = uci:get(appname, "@global[0]", "dns_shunt")
local type = uci:get(c_config, section, "type")
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_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"
if dns_mode ~= new_dns_mode then
uci:set(appname, "@global[0]", dns_key, new_dns_mode)
uci:set(appname, "@global[0]", "v2ray_dns_mode", "tcp")
uci:set(c_config, "@global[0]", dns_key, new_dns_mode)
uci:set(c_config, "@global[0]", "v2ray_dns_mode", "tcp")
end
end
end
api.uci_save(uci, appname, true, true)
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]', "tcp_node")
uci:delete(appname, '@global[0]', "udp_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]', "tcp_node")
uci:delete(c_config, '@global[0]', "udp_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"], "tcp_node")
uci:delete(appname, t[".name"], "udp_node")
uci:delete(c_config, t[".name"], "tcp_node")
uci:delete(c_config, t[".name"], "udp_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)
local socks
uci:foreach(appname, "socks", function(t)
uci:foreach(c_config, "socks", function(t)
if t["node"] == w then
uci:delete(appname, t[".name"])
socks = "Socks_" .. 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)
@@ -599,42 +601,40 @@ 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)
local tcp_node = uci:get(appname, "@global[0]", "tcp_node") or ""
if tcp_node == w or tcp_node == socks then
uci:delete(appname, '@global[0]', "tcp_node")
if (uci:get(c_config, "@global[0]", "tcp_node") or "") == w then
uci:delete(c_config, '@global[0]', "tcp_node")
end
local udp_node = uci:get(appname, "@global[0]", "udp_node") or ""
if udp_node == w or udp_node == socks then
uci:delete(appname, '@global[0]', "udp_node")
if (uci:get(c_config, "@global[0]", "udp_node") or "") == w then
uci:delete(c_config, '@global[0]', "udp_node")
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)
if t["tcp_node"] == w or t["tcp_node"] == socks then
uci:delete(appname, t[".name"], "tcp_node")
uci:foreach(c_config, "acl_rule", function(t)
if t["tcp_node"] == w then
uci:delete(c_config, t[".name"], "tcp_node")
end
if t["udp_node"] == w or t["udp_node"] == socks then
uci:delete(appname, t[".name"], "udp_node")
if t["udp_node"] == w then
uci:delete(c_config, t[".name"], "udp_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 = {}
@@ -646,48 +646,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 or t["fallback_node"] == socks then
uci:delete(appname, t[".name"], "fallback_node")
if t["fallback_node"] == w then
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
@@ -700,12 +700,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
@@ -724,12 +724,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
@@ -737,7 +737,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
@@ -760,8 +760,8 @@ 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 geo2rule = uci:get(appname, "@global_rules[0]", "geo2rule") or "0"
local geo_dir = (uci:get(c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/")
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.rmdir(bak_dir)
if geo2rule == "1" and rules ~= "" then
@@ -777,9 +777,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
@@ -914,7 +914,7 @@ function restore_backup()
fp:write(decoded)
fp:close()
if chunk_index + 1 == total_chunks then
uci:revert(appname)
uci:revert(c_config)
luci.sys.call("echo '' > /tmp/log/passwall.log")
api.log(" * PassWall 配置文件上传成功…")
local temp_dir = '/tmp/passwall_bak'
@@ -957,7 +957,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
@@ -974,7 +974,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
@@ -1046,13 +1046,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." })
@@ -1069,7 +1069,7 @@ function subscribe_manual_all()
local url_list = util.split(urls, ",")
-- 检查是否存在未保存配置
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
@@ -1078,9 +1078,9 @@ function subscribe_manual_all()
-- 保存有变动的url
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 &")
@@ -1091,10 +1091,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"))
@@ -1103,9 +1103,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
local protocol = uci:get(appname, id, "protocol")
local h3, timeout = false, 10
@@ -1130,11 +1130,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
@@ -1153,7 +1153,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
@@ -1161,18 +1161,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
@@ -1181,17 +1181,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
@@ -1,22 +1,17 @@
local api = require "luci.passwall.api"
local appname = "passwall"
local sys = api.sys
api.set_default_cbi()
m = Map(appname)
api.set_apply_on_parse(m)
m = Map()
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.anonymous = true
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>")
o = s:option(Flag, "acl_enable", translate("Main switch"))
o.rmempty = false
o.default = false
-- [[ ACLs Settings ]]--
local cfgname = "acl_rule"
s = m:section(TypedSection, cfgname)
s = m:section(TypedSection, "acl_rule")
s.template = "cbi/tblsection"
s.sortable = true
s.anonymous = true
@@ -28,7 +23,7 @@ function s.create(e, t)
luci.http.redirect(e.extedit:format(uid))
end
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)
end
@@ -42,7 +37,7 @@ o = s:option(Value, "remarks", translate("Remarks"))
o.rmempty = true
local mac_t = {}
sys.net.mac_hints(function(e, t)
api.sys.net.mac_hints(function(e, t)
mac_t[e] = {
ip = t,
mac = e
@@ -85,41 +80,6 @@ i.cfgvalue = function(t, n)
return translate("No Proxy")
end
--[[
---- 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)
m:appendTemplate("/cbi/sortable", {sectiontype = s.sectiontype})
return api.return_map(m)
@@ -1,26 +1,20 @@
local api = require "luci.passwall.api"
local appname = "passwall"
api.set_default_cbi()
m = Map(appname)
m = Map()
m.redirect = api.url("acl")
api.set_apply_on_parse(m)
local cfgid = arg[1]
if not cfgid or not m:get(cfgid) then
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
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_xray = api.finded_com("xray")
local has_gfwlist = fs.access("/usr/share/passwall/rules/gfwlist")
local has_chnlist = fs.access("/usr/share/passwall/rules/chnlist")
local has_chnroute = fs.access("/usr/share/passwall/rules/chnroute")
local has_gfwlist = api.fs.access("/usr/share/passwall/rules/gfwlist")
local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist")
local has_chnroute = api.fs.access("/usr/share/passwall/rules/chnroute")
local port_validate = function(self, value, t)
return value:gsub("-", ":")
@@ -39,10 +33,10 @@ for _, v in pairs(nodes_table) do
end
local socks_list = {}
m.uci:foreach(appname, "socks", function(s)
m:foreach("socks", function(s)
if s.enabled == "1" and s.node then
socks_list[#socks_list + 1] = {
id = "Socks_" .. s[".name"],
id = s[".name"],
remark = translate("Socks Config") .. " " .. string.format("[%s %s]", s.port, translate("Port")),
group = "Socks"
}
@@ -50,7 +44,7 @@ m.uci:foreach(appname, "socks", function(s)
end)
-- [[ 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.dynamic = false
@@ -61,7 +55,7 @@ o.rmempty = false
---- Remarks
o = s:option(Value, "remarks", translate("Remarks"))
o.default = cfgid
o.default = arg[1]
o.rmempty = false
o = s:option(Value, "interface", translate("Source Interface"))
@@ -78,7 +72,7 @@ o.validate = function(self, value, section)
end
local mac_t = {}
sys.net.mac_hints(function(e, t)
api.sys.net.mac_hints(function(e, t)
mac_t[#mac_t + 1] = {
ip = t,
mac = e
@@ -188,7 +182,7 @@ o:depends("mode", "1")
o.validate = port_validate
o = s:option(DummyValue, "_hide_node_option", "")
o.template = "passwall/cbi/hidevalue"
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends("mode", "0")
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.default = ""
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.remove = function(self, section)
m:del(section, self.option)
@@ -212,7 +206,7 @@ o.remove = function(self, section)
end
o = s:option(DummyValue, "_tcp_node_bool", "")
o.template = "passwall/cbi/hidevalue"
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ tcp_node = "", ['!reverse'] = true })
@@ -221,7 +215,7 @@ o.default = ""
o:value("", translate("Close"))
o:value("tcp", translate("Same as the tcp node"))
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.remove = function(self, section)
local v = s.fields["shunt_udp_node"]:formvalue(section)
@@ -248,7 +242,7 @@ o.write = function(self, section, value)
end
o = s:option(DummyValue, "_udp_node_bool", "")
o.template = "passwall/cbi/hidevalue"
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ udp_node = "", ['!reverse'] = true })
o:depends({ shunt_udp_node = "tcp" })
@@ -355,17 +349,17 @@ o:value("proxy", translate("Proxy"))
o:depends({ _udp_node_bool = "1" })
o = s:option(DummyValue, "switch_mode", " ")
o.template = appname .. "/global/proxy"
o.template = m:template_path("/global/proxy")
o:depends({ _tcp_node_bool = "1" })
-- Node → DNS Depends Settings
o = s:option(DummyValue, "_node_sel_shunt", "")
o.template = appname .. "/cbi/hidevalue"
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ tcp_node = "__always__" })
o = s:option(DummyValue, "_node_sel_other", "")
o.template = appname .. "/cbi/hidevalue"
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ _node_sel_shunt = "1", ['!reverse'] = true })
@@ -603,9 +597,6 @@ for k, v in pairs(nodes_table) do
end
end
local footer = Template(appname .. "/acl/config_footer")
footer.api = api
footer.cfgid = cfgid
m:append(footer)
m:appendTemplate("/acl/config_footer", {section = arg[1]})
return api.return_map(m)
@@ -1,21 +1,15 @@
local api = require "luci.passwall.api"
local com = require "luci.passwall.com"
local appname = "passwall"
api.set_default_cbi()
m = Map(appname)
api.set_apply_on_parse(m)
local com = require "luci.passwall.com"
m = Map()
-- [[ App Settings ]]--
s = m:section(TypedSection, "global_app", translate("App Update"))
s.anonymous = true
s = m:section(NamedSection, "@global_app[0]", "global_app", translate("App Update"))
local app_version = Template(appname .. "/app_update/app_version")
app_version.api = api
app_version.config = m.config
app_version.com = com
s:append(app_version)
s:appendTemplate("/app_update/app_version", {com = com})
o = s:option(Flag, "github_proxy", translate("GitHub Proxy"), translate("Use gh-proxy instead of proxy nodes for component updates."))
o.default = 0
@@ -1,5 +1,4 @@
api = require "luci.passwall.api"
appname = "passwall"
datatypes = api.datatypes
local fs = api.fs
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()
m = Map(appname)
api.set_apply_on_parse(m)
m = Map()
m:append(Template(appname .. "/cbi/nodes_listvalue_com"))
m:appendTemplate("/cbi/nodes_listvalue_com")
local nodes_table = {}
for _, e in ipairs(api.get_valid_nodes()) do
@@ -51,7 +49,7 @@ socks_table[#socks_table + 1] = {
id = tcp_socks_server,
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
local id, remark
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"
end
m:append(Template(appname .. "/global/status"))
m:appendTemplate("/global/status")
global_cfgid = (m:get("@global[0]") or {})[".name"] or ""
s = m:section(TypedSection, "global")
s.anonymous = true
s.addremove = false
s = m:section(NamedSection, "@global[0]", "global")
s:tab("Main", translate("Main"))
@@ -111,13 +105,13 @@ o.rmempty = false
---- TCP Node
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.group = {""}
---- UDP Node
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("tcp", translate("Same as the tcp node"))
o.group = {"",""}
@@ -146,15 +140,16 @@ o.write = function(self, section, value)
return m:set(section, "udp_node", value)
end
current_node_id = m:get(s.section, "tcp_node")
current_node = current_node_id and m:get(current_node_id) or {}
-- Shunt Start
if (has_singbox or has_xray) and #nodes_table > 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
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, {
s_cfgid = s:cfgsections()[1],
s_cfgid = s.section,
node_id = current_node_id,
node = current_node,
socks_list = socks_list,
@@ -200,12 +195,12 @@ o:depends({ tcp_node = "", ["!reverse"] = true })
-- Node → DNS Depends Settings
o = s:taboption("Main", DummyValue, "_node_sel_shunt", "")
o.template = appname .. "/cbi/hidevalue"
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ tcp_node = "__always__" })
o = s:taboption("Main", DummyValue, "_node_sel_other", "")
o.template = appname .. "/cbi/hidevalue"
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ _node_sel_shunt = "1", ['!reverse'] = true })
@@ -583,7 +578,7 @@ o:value("proxy", translate("Proxy"))
o.default = "proxy"
o = s:taboption("Proxy", DummyValue, "switch_mode", " ")
o.template = appname .. "/global/proxy"
o.template = m:template_path("/global/proxy")
---- Check the transparent proxy component
local handle = io.popen("lsmod")
@@ -662,11 +657,11 @@ end
s:tab("faq", "FAQ")
o = s:taboption("faq", DummyValue, "")
o.template = appname .. "/global/faq"
o.template = m:template_path("/global/faq")
s:tab("maintain", translate("Maintain"))
o = s:taboption("maintain", DummyValue, "")
o.template = appname .. "/global/backup"
o.template = m:template_path("/global/backup")
-- [[ Socks Server ]]--
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))
end
function s2.remove(e, t)
local socks = "Socks_" .. t
local new_node = ""
local node0 = m:get("@nodes[0]") or nil
if node0 then
new_node = node0[".name"]
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)
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)
end
m.uci:foreach(appname, "acl_rule", function(s)
if s["tcp_node"] and s["tcp_node"] == socks then
m:foreach("acl_rule", function(s)
if s["tcp_node"] and s["tcp_node"] == t then
m:set(s[".name"], "tcp_node", "default")
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")
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")
if list_name then
local nodes = m.uci:get_list(appname, s[".name"], list_name)
@@ -711,7 +705,7 @@ function s2.remove(e, t)
local changed = false
local new_nodes = {}
for _, node in ipairs(nodes) do
if node ~= socks then
if node ~= t then
table.insert(new_nodes, node)
else
changed = true
@@ -722,7 +716,7 @@ function s2.remove(e, t)
end
end
end
if s["fallback_node"] == socks then
if s["fallback_node"] == t then
m:del(s[".name"], "fallback_node")
end
end)
@@ -741,7 +735,7 @@ o.default = 1
o.rmempty = false
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 = s2:option(DummyValue, "now_node", translate("Current Node"))
@@ -757,7 +751,7 @@ o.cfgvalue = function(_, n)
end
local n = 1
m.uci:foreach(appname, "socks", function(s)
m:foreach("socks", function(s)
if s[".name"] == section then
return false
end
@@ -819,10 +813,6 @@ for k, v in pairs(nodes_table) do
end
end
local footer = Template(appname .. "/global/footer")
footer.api = api
footer.global_cfgid = global_cfgid
footer.shunt_list = api.jsonc.stringify(shunt_list)
m:append(footer)
m:appendTemplate("/global/footer", {shunt_list = api.jsonc.stringify(shunt_list)})
return api.return_map(m)
@@ -1,7 +1,6 @@
local api = require "luci.passwall.api"
local appname = api.appname
local datatypes = api.datatypes
local net = require "luci.model.network".init()
api.set_default_cbi()
local nodes_table = {}
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
api.set_default_cbi()
m = Map(api.c_config, "HAPROXY " .. translate("Load Balancing"))
m = Map(appname, "HAPROXY " .. translate("Load Balancing"))
api.set_apply_on_parse(m)
m:append(Template(appname .. "/cbi/nodes_value_com"))
m:appendTemplate("/cbi/nodes_value_com")
-- [[ Haproxy Settings ]]--
s = m:section(TypedSection, "global_haproxy", translate("Basic Settings"))
s.anonymous = true
s = m:section(NamedSection, "@global_haproxy[0]", "global_haproxy", translate("Basic Settings"))
s:append(Template(appname .. "/haproxy/status"))
s:appendTemplate("/haproxy/status")
---- Balancing Enable
o = s:option(Flag, "balancing_enable", translate("Enable Load Balancing"))
@@ -69,9 +64,9 @@ o:depends("balancing_enable", true)
---- 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("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)
---- 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.default = o.keylist[3]
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
o = s:option(Value, "health_check_inter", translate("Health Check Inter"))
@@ -100,11 +95,10 @@ o.rawhtml = true
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."))
end
o:depends("health_check_type", "passwall_logic")
o:depends("health_check_type", "script_logic")
-- [[ Balancing Settings ]]--
local cfgname = "haproxy_config"
s = m:section(TypedSection, cfgname, translate("Node List"))
s = m:section(TypedSection, "haproxy_config", translate("Node List"))
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("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
o = s:option(Value, "lbss", translate("Node Address"))
o.template = appname .. "/cbi/nodes_value"
o.template = m:template_path("/cbi/nodes_value")
o.group = {}
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
@@ -181,11 +175,8 @@ o:value(0, translate("Primary"))
o:value(1, translate("Standby"))
o.rmempty = false
local sortable = Template(appname .. "/cbi/sortable")
sortable.api = api
sortable.target_cfgname = cfgname
m:append(sortable)
m:appendTemplate("/cbi/sortable", {sectiontype = s.sectiontype})
m:append(Template(appname .. "/haproxy/js"))
m:appendTemplate("/haproxy/js")
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 groups = {}
m.uci:foreach(appname, "shunt_rules", function(s)
m:foreach("shunt_rules", function(s)
if s.group and s.group ~= "" then
groups[s.group] = true
end
@@ -109,7 +109,7 @@ end
local shunt_group_val = m:get(current_node_id, "shunt_group") or ""
shunt_group_val = shunt_group_val:lower()
local shunt_rules = {}
m.uci:foreach(appname, "shunt_rules", function(e)
m:foreach("shunt_rules", function(e)
local group = e.group or ""
group = group:lower()
if group == shunt_group_val then
@@ -132,7 +132,7 @@ table.insert(shunt_rules, {
})
s2 = m:section(Table, shunt_rules, " ")
s2.config = appname
s2.config = m.config
s2.sectiontype = "shunt_option_list"
o = s2:option(DummyValue, "remarks", translate("Rule"))
@@ -146,7 +146,7 @@ o.cfgvalue = function(self, section)
end
_node = s2:option(Value, "_node", translate("Node"))
_node.template = appname .. "/cbi/nodes_listvalue"
_node.template = m:template_path("/cbi/nodes_listvalue")
_node.group = {"","","",""}
_node:value("", translate("Close (Not use)"))
_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>',
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")))
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:value("", translate("Close (Not use)"))
proxy_tag_node.cfgvalue = function(self, section)
@@ -203,10 +203,4 @@ for k1, v1 in pairs(node_list) do
end
end
local footer = Template(appname .. "/include/shunt_options")
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)
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)})
@@ -1,30 +1,22 @@
api = require "luci.passwall.api"
appname = "passwall"
api.set_default_cbi()
m = Map(appname, translate("Node Config"))
m = Map()
m.redirect = api.url("node_list")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
end
fs = require "nixio.fs"
formvalue_key = "cbid." .. appname .. "." .. arg[1] .. "."
formvalue_key = "cbid." .. m.config .. "." .. arg[1] .. "."
local header = Template(appname .. "/node_config/header")
header.api = api
header.config = m.config
header.section = arg[1]
m:append(header)
m:append(Template(appname .. "/cbi/nodes_multivalue_com"))
m:append(Template(appname .. "/cbi/nodes_listvalue_com"))
m:appendTemplate("/node_config/header", {section = arg[1]})
m:appendTemplate("/cbi/nodes_multivalue_com")
m:appendTemplate("/cbi/nodes_listvalue_com")
groups = {}
m.uci:foreach(appname, "nodes", function(s)
m:foreach("nodes", function(s)
if s[".name"] ~= arg[1] then
if s.group and s.group ~= "" then
groups[s.group] = true
@@ -32,13 +24,13 @@ m.uci:foreach(appname, "nodes", function(s)
end
end)
s = m:section(NamedSection, arg[1], "nodes", "")
s = m:section(NamedSection, arg[1], "nodes", translate("Node Config"))
s.addremove = false
s.dynamic = false
o = s:option(DummyValue, "passwall", " ")
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 = s:option(Value, "remarks", translate("Node Remarks"))
@@ -67,10 +59,10 @@ o.write = function(self, section, value)
m:set(section, self.option, value)
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["type"] = m.uci:get(appname, arg[1], "type")
s.val["protocol"] = m.uci:get(appname, arg[1], "protocol")
s.val["type"] = m:get(arg[1], "type")
s.val["protocol"] = m:get(arg[1], "protocol")
if luci.http.formvalue("cbi.submit") == "1" then
local formvalue_type = luci.http.formvalue(formvalue_key .. "type")
@@ -118,10 +110,6 @@ for index, value in ipairs(type_table) do
setfenv(p_func, getfenv(1))(m, s)
end
local footer = Template(appname .. "/node_config/footer")
footer.api = api
footer.config = m.config
footer.section = arg[1]
m:append(footer)
m:appendTemplate("/node_config/footer", {section = arg[1]})
return api.return_map(m)
@@ -1,14 +1,10 @@
local api = require "luci.passwall.api"
local appname = "passwall"
api.set_default_cbi()
m = Map(appname)
api.set_apply_on_parse(m)
m = Map()
-- [[ Other Settings ]]--
s = m:section(TypedSection, "global_other")
s.anonymous = true
s = m:section(NamedSection, "@global_other[0]", "global_other")
o = s:option(ListValue, "auto_detection_time", translate("Automatic detection delay"))
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]
if true then
local o = Template(appname .. "/node_list/node_list")
o.map = m
o.api = api
m:append(o)
m:appendTemplate("/node_list/node_list")
if luci.http.formvalue("cbi.submit") == "1" then
local group_order = {}
@@ -45,7 +38,7 @@ if true then
new_order[#new_order + 1] = w
end)
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
@@ -1,6 +1,6 @@
local api = require "luci.passwall.api"
local uci = api.uci
local appname = "passwall"
api.set_default_cbi()
local has_ss_rust = api.is_finded("sslocal")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
@@ -38,23 +38,16 @@ if has_hysteria2 then
table.insert(hysteria2_type, s)
end
api.set_default_cbi()
m = Map(appname)
api.set_apply_on_parse(m)
m = Map()
function m.on_before_save(self)
if self.no_commit then
return
end
self.uci:foreach(appname, "subscribe_list", function(e)
self:foreach("subscribe_list", function(e)
self:del(e[".name"], "md5")
end)
end
-- [[ Subscribe Settings ]]--
s = m:section(TypedSection, "global_subscribe", "")
s.anonymous = true
s = m:section(NamedSection, "@global_subscribe[0]", "global_subscribe")
o = s:option(ListValue, "filter_keyword_mode", translate("Filter keyword Mode"))
o:value("0", translate("Close"))
@@ -129,15 +122,13 @@ o.cfgvalue = function(self, section)
translate("Manual subscription All"))
end
local cfgname = "subscribe_list"
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 = 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.addremove = true
s.anonymous = true
s.sortable = true
s.template = "cbi/tblsection"
s.extedit = api.url("node_subscribe_config", "%s")
function s.create(e, t)
m.no_commit = true
local uid = "sub_" .. api.gen_random_char(5)
TypedSection.create(e, uid)
m:set(uid, "hysteria_up_mbps", "100")
@@ -154,7 +145,7 @@ o.validate = function(self, value, section)
return nil, translate("Remark cannot be empty.")
end
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
duplicate = true
return false
@@ -168,9 +159,9 @@ end
o.write = function(self, section, value)
local old = m:get(section, self.option) or ""
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
m.uci:set(appname, e[".name"], "group", value)
m:set(e[".name"], "group", value)
end
if e["protocol"] and (e["protocol"] == "_balancing" or e["protocol"] == "_urltest") and e["node_group"] then
local gs = ""
@@ -182,7 +173,7 @@ o.write = function(self, section, value)
end
end
gs = api.trim(gs)
m.uci:set(appname, e[".name"], "node_group", gs)
m:set(e[".name"], "node_group", gs)
end
end)
end
@@ -200,7 +191,7 @@ o.cfgvalue = function(t, n)
end
str = str ~= "" and "<br>" .. str or ""
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
num = num + 1
end
@@ -229,11 +220,8 @@ o.cfgvalue = function(self, section)
section, translate("Manual subscription"))
end
local sortable = Template(appname .. "/cbi/sortable")
sortable.api = api
sortable.target_cfgname = cfgname
m:append(sortable)
m:appendTemplate("/cbi/sortable", {sectiontype = s.sectiontype})
m:append(Template(appname .. "/node_subscribe/js"))
m:appendTemplate("/node_subscribe/js")
return api.return_map(m)
@@ -1,12 +1,8 @@
local api = require "luci.passwall.api"
local uci = api.uci
local appname = "passwall"
api.set_default_cbi()
m = Map(appname)
m = Map()
m.redirect = api.url("node_subscribe")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
@@ -16,7 +12,7 @@ function m.on_before_save(self)
self:del(arg[1], "md5")
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_singbox = api.finded_com("sing-box")
@@ -80,7 +76,7 @@ o.validate = function(self, value, section)
return nil, translate("Remark cannot be empty.")
end
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
duplicate = true
return false
@@ -94,9 +90,9 @@ end
o.write = function(self, section, value)
local old = m:get(section, self.option) or ""
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
m.uci:set(appname, e[".name"], "group", value)
self:set(e[".name"], "group", value)
end
if e["protocol"] and (e["protocol"] == "_balancing" or e["protocol"] == "_urltest") and e["node_group"] then
local gs = ""
@@ -108,7 +104,7 @@ o.write = function(self, section, value)
end
end
gs = api.trim(gs)
m.uci:set(appname, e[".name"], "node_group", gs)
self:set(e[".name"], "node_group", gs)
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:depends({ ["chain_proxy"] = "1" })
o1.description = descrStr
o1.template = appname .. "/cbi/nodes_listvalue"
o1.template = m:template_path("/cbi/nodes_listvalue")
o1.group = {}
o2 = s:option(ListValue, "to_node", translate("Landing Node"))
o2:depends({ ["chain_proxy"] = "2" })
o2.description = descrStr
o2.template = appname .. "/cbi/nodes_listvalue"
o2.template = m:template_path("/cbi/nodes_listvalue")
o2.group = {}
o3 = s:option(Value, "outbound_iface", translate("Outbound Interface"))
@@ -1,5 +1,6 @@
local api = require "luci.passwall.api"
local appname = "passwall"
api.set_default_cbi()
local fs = api.fs
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
@@ -8,15 +9,10 @@ local port_validate = function(self, value, t)
return value:gsub("-", ":")
end
api.set_default_cbi()
m = Map(appname)
api.set_apply_on_parse(m)
m = Map()
-- [[ Delay Settings ]]--
s = m:section(TypedSection, "global_delay", translate("Delay Settings"))
s.anonymous = true
s.addremove = false
s = m:section(NamedSection, "@global_delay[0]", "global_delay", translate("Delay Settings"))
---- 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
-- [[ Forwarding Settings ]]--
s = m:section(TypedSection, "global_forwarding", translate("Forwarding Settings"))
s.anonymous = true
s.addremove = false
s = m:section(NamedSection, "@global_forwarding[0]", "global_forwarding", translate("Forwarding Settings"))
---- 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
if has_xray then
s_xray = m:section(TypedSection, "global_xray", "Xray " .. translate("Settings"))
s_xray.anonymous = true
s_xray.addremove = false
s_xray = m:section(NamedSection, "@global_xray[0]", "global_xray", "Xray " .. translate("Settings"))
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
@@ -204,7 +196,7 @@ if has_xray then
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.")
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.rows = 15
o.wrap = "off"
@@ -227,11 +219,14 @@ if has_xray then
end
s_xray_noise.remove = function(self, section)
for k, v in pairs(self.children) do
v.rmempty = true
v.validate = nil
local o = m:get(section) or {}
if o[".type"] == self.sectiontype then
for k, v in pairs(self.children) do
v.rmempty = true
v.validate = nil
end
TypedSection.remove(self, section)
end
TypedSection.remove(self, section)
end
o = s_xray_noise:option(Flag, "enabled", translate("Enable"))
@@ -255,9 +250,7 @@ if has_xray then
end
if has_singbox then
s = m:section(TypedSection, "global_singbox", "Sing-Box " .. translate("Settings"))
s.anonymous = true
s.addremove = false
s = m:section(NamedSection, "@global_singbox[0]", "global_singbox", "Sing-Box " .. translate("Settings"))
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."))
@@ -1,16 +1,12 @@
local api = require "luci.passwall.api"
local appname = "passwall"
local has_xray = api.finded_com("xray")
local has_singbox = api.finded_com("sing-box")
api.set_default_cbi()
m = Map(appname)
api.set_apply_on_parse(m)
m = Map()
-- [[ Rule Settings ]]--
s = m:section(TypedSection, "global_rules", translate("Rule status"))
s.anonymous = true
s = m:section(NamedSection, "@global_rules[0]", "global_rules", translate("Rule status"))
--[[
o = s:option(Flag, "adblock", translate("Enable adblock"))
@@ -143,12 +139,10 @@ for _, f in ipairs(flags) do
o.rmempty = false
end
s:append(Template(appname .. "/rule/rule_version"))
s:appendTemplate("/rule/rule_version")
if has_xray or has_singbox then
local o = Template(appname .. "/rule/shunt_rule_list")
o.api = api
m:append(o)
m:appendTemplate("/rule/shunt_rule_list")
if luci.http.formvalue("cbi.submit") == "1" then
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
end)
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
@@ -1,18 +1,16 @@
local api = require "luci.passwall.api"
local appname = api.appname
local fs = api.fs
local sys = api.sys
local uci = api.uci
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 chnlist_path = "/usr/share/passwall/rules/chnlist"
local chnroute_path = "/usr/share/passwall/rules/chnroute"
api.set_default_cbi()
m = Map(appname)
api.set_apply_on_parse(m)
m = Map()
function clean_text(text)
local nbsp = string.char(0xC2, 0xA0) -- 不间断空格(U+00A0)
@@ -319,9 +317,9 @@ if fs.access(chnroute_path) then
]], translate("Read List"))
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 geoip_path = geo_dir .. "/geoip.dat"
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"))
o = s:taboption("geoview", DummyValue, "_geoview_fieldset")
o.rawhtml = true
o.template = appname .. "/rule_list/geoview"
o.template = m:template_path("/rule_list/geoview")
end
end
@@ -1,19 +1,17 @@
local api = require "luci.passwall.api"
local appname = "passwall"
local datatypes = api.datatypes
api.set_default_cbi()
m = Map(appname, "Sing-Box/Xray " .. translate("Shunt Rule"))
local datatypes = api.datatypes
m = Map()
m.redirect = api.url("rule")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
end
m.on_before_save = function(self)
m:set("@global[0]", "flush_set", "1")
function m.on_before_save(self)
self:set("@global[0]", "flush_set", "1")
end
-- Add inline CSS to map description
@@ -46,7 +44,7 @@ end
local remarks_lookup = {}
local groups = {}
m.uci:foreach(appname, "shunt_rules", function(s)
m:foreach("shunt_rules", function(s)
if s[".name"] ~= arg[1] then
if s.remarks then
remarks_lookup[s.remarks] = s[".name"]
@@ -57,7 +55,7 @@ m.uci:foreach(appname, "shunt_rules", function(s)
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.dynamic = false
@@ -1,18 +1,14 @@
local api = require "luci.passwall.api"
local appname = "passwall"
api.set_default_cbi()
m = Map(appname)
m.redirect = api.url()
api.set_apply_on_parse(m)
m = Map()
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
end
m:append(Template(appname .. "/cbi/nodes_dynamiclist_com"))
m:append(Template(appname .. "/cbi/nodes_listvalue_com"))
m:appendTemplate("/cbi/nodes_dynamiclist_com")
m:appendTemplate("/cbi/nodes_listvalue_com")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
@@ -50,14 +46,14 @@ socks_node = s:option(ListValue, "node", translate("Node"))
if auto_switch_tip then
socks_node.description = auto_switch_tip
end
socks_node.template = appname .. "/cbi/nodes_listvalue"
socks_node.template = m:template_path("/cbi/nodes_listvalue")
socks_node.group = {}
o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
o.default = "0"
local n = 1
m.uci:foreach(appname, "socks", function(s)
m:foreach("socks", function(s)
if s[".name"] == section then
return false
end
@@ -91,7 +87,7 @@ o:value("batch", translate("Batch"))
o = s:option(DynamicList, "autoswitch_backup_node", translate("List of backup nodes"))
o:depends("backup_node_add_mode", "manual")
o.template = appname .. "/cbi/nodes_dynamiclist"
o.template = m:template_path("/cbi/nodes_dynamiclist")
o.group = {}
o.write = function(self, section, value)
local n = s.fields["node"]:formvalue(section)
@@ -117,7 +113,7 @@ o:depends("backup_node_add_mode", "batch")
o.widget = "checkbox"
o:value("default", translate("default"))
local groups = {}
m.uci:foreach(appname, "nodes", function(s)
m:foreach("nodes", function(s)
if s.group and s.group ~= "" then
groups[s.group] = true
end
@@ -165,7 +161,7 @@ o.default = o.keylist[3]
o:depends("enable_autoswitch", true)
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")
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:depends({ [_n("node_add_mode")] = "manual" })
o.widget = "checkbox"
o.template = appname .. "/cbi/nodes_multivalue"
o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {}
for k1, v1 in pairs(node_list) do
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("_direct", translate("Direct Connection"))
o:depends({ [_n("protocol")] = "_balancing" })
o.template = appname .. "/cbi/nodes_listvalue"
o.template = m:template_path("/cbi/nodes_listvalue")
-- 最大 fallback 套娃层数
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: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 = {}
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: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 = {}
for k1, v1 in pairs(node_list) do
@@ -890,7 +890,7 @@ end
api.luci_types(arg[1], m, s, type_name, option_prefix)
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")
setfenv(shunt_lua, getfenv(1))(m, s, {
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:depends({ [_n("node_add_mode")] = "manual" })
o.widget = "checkbox"
o.template = appname .. "/cbi/nodes_multivalue"
o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {}
for k1, v1 in pairs(node_list) do
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: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 = {}
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: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 = {}
for k1, v1 in pairs(node_list) do
@@ -911,7 +911,7 @@ end
api.luci_types(arg[1], m, s, type_name, option_prefix)
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")
setfenv(shunt_lua, getfenv(1))(m, s, {
node_id = arg[1],
@@ -1,12 +1,9 @@
local api = require "luci.passwall.api"
local appname = api.appname
api.set_default_cbi()
m = Map("passwall_server", translate("Server-Side"))
api.set_apply_on_parse(m)
m = Map(api.s_config)
t = m:section(NamedSection, "global", "global")
t = m:section(NamedSection, "global", "global", translate("Server-Side"))
t.anonymous = true
t.addremove = false
@@ -94,17 +91,9 @@ e = s_server:option(Flag, "log", translate("Log"))
e.default = "1"
e.rmempty = false
local sortable = Template(appname .. "/cbi/sortable")
sortable.api = api
sortable.appname = m.config
sortable.target_cfgname = s_server.sectiontype
m:append(sortable)
m:appendTemplate("/cbi/sortable", {sectiontype = s_server.sectiontype})
local server_list_status = Template(appname .. "/server/server_list_status")
server_list_status.api = api
server_list_status.appname = m.config
server_list_status.sectiontype = s_server.sectiontype
m:append(server_list_status)
m:appendTemplate("/server/server_list_status", {sectiontype = s_server.sectiontype})
s_user = m:section(TypedSection, "user", translate("Users Manager"))
s_user.anonymous = true
@@ -120,7 +109,7 @@ end
s_user.remove = function(self, section)
local o = m:get(section) or {}
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
m:set(o[".name"], "user", "")
end
@@ -150,12 +139,8 @@ e.width = "25%"
e = s_user:option(DummyValue, "uuid", "UUID")
e.width = "25%"
local sortable = Template(appname .. "/cbi/sortable")
sortable.api = api
sortable.appname = m.config
sortable.target_cfgname = s_user.sectiontype
m:append(sortable)
m:appendTemplate("/cbi/sortable", {sectiontype = s_user.sectiontype})
m:append(Template(appname .. "/server/log"))
m:appendTemplate("/server/log")
return api.return_map(m)
@@ -1,35 +1,27 @@
api = require "luci.passwall.api"
appname = api.appname
fs = api.fs
api.set_default_cbi()
m = Map("passwall_server", translate("Server Config"))
m = Map(api.s_config)
m.redirect = api.url("server")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
end
local header = Template(appname .. "/server/config_header")
header.api = api
header.config = m.config
header.section = arg[1]
m:append(header)
m:appendTemplate("/server/config_header", {section = arg[1]})
m:append(Template(appname .. "/cbi/nodes_listvalue_com"))
m:appendTemplate("/cbi/nodes_listvalue_com")
user_list = {}
m.uci:foreach(m.config, "user", function(s)
m:foreach("user", function(s)
user_list[#user_list + 1] = s
end)
s = m:section(NamedSection, arg[1], "server", "")
s = m:section(NamedSection, arg[1], "server", translate("Server Config"))
s.addremove = 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 {}
o = s:option(Flag, "enable", translate("Enable"))
@@ -43,7 +35,7 @@ o.rmempty = false
o = s:option(ListValue, "type", translate("Type"))
local type_table = {}
for filename in fs.dir(types_dir) do
for filename in api.fs.dir(types_dir) do
table.insert(type_table, filename)
end
table.sort(type_table, function(a, b)
@@ -57,10 +49,6 @@ for index, value in ipairs(type_table) do
setfenv(p_func, getfenv(1))(m, s)
end
local footer = Template(appname .. "/server/config_footer")
footer.api = api
footer.config = m.config
footer.section = arg[1]
m:append(footer)
m:appendTemplate("/server/config_footer", {section = arg[1]})
return api.return_map(m)
@@ -441,7 +441,7 @@ o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface"))
o.template = api.appname .. "/cbi/nodes_listvalue"
o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {"","","",""}
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
@@ -424,7 +424,7 @@ o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface"))
o.template = api.appname .. "/cbi/nodes_listvalue"
o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {"","","",""}
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
@@ -1,18 +1,14 @@
api = require "luci.passwall.api"
appname = api.appname
fs = api.fs
api.set_default_cbi()
m = Map("passwall_server", translate("User Config"))
m = Map(api.s_config)
m.redirect = api.url("server")
api.set_apply_on_parse(m)
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
end
s = m:section(NamedSection, arg[1], "user", "")
s = m:section(NamedSection, arg[1], "user", translate("User Config"))
s.addremove = false
s.dynamic = false
+87 -51
View File
@@ -1,4 +1,7 @@
module("luci.passwall.api", package.seeall)
appname = "passwall"
c_config = "passwall"
s_config = "passwall_server"
local com = require "luci.passwall.com"
nixio = require "nixio"
fs = require "nixio.fs"
@@ -30,10 +33,6 @@ function log(...)
end
end
function is_js_luci()
return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
end
function is_old_uci()
return sys.call("grep -E 'require[ \t]*\"uci\"' /usr/lib/lua/luci/model/uci.lua >/dev/null 2>&1") == 0
end
@@ -214,7 +213,7 @@ function curl_direct(url, file, args)
end
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
return curl_base(url, file, args) -- 当路由器本机开启代理时,采用passwall规则进行访问
else
@@ -482,11 +481,11 @@ function get_domain_from_url(url)
end
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 default_nodes = {}
local other_nodes = {}
uci:foreach(appname, "nodes", function(e)
uci:foreach(c_config, "nodes", function(e)
e.id = e[".name"]
if e.type and e.remarks then
local type_name = e.type
@@ -559,7 +558,7 @@ function get_node_list()
socks_list = {},
normal_list = {},
}
uci:foreach(appname, "socks", function(s)
uci:foreach(c_config, "socks", function(s)
if s.enabled == "1" and s.node then
node_list.socks_list[#node_list.socks_list + 1] = {
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)
end
function uci_get_type(type, config, default)
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)
function chmod_755(file)
if file and file ~= "" then
if not fs.access(file, "rwx", "rx", "rx") then
fs.chmod(file, 755)
@@ -683,7 +666,7 @@ local function chmod_755(file)
end
function get_customed_path(e)
return uci_get_type("global_app", e .. "_file")
return uci:get(c_config, "@global_app[0]", e .. "_file")
end
function finded_com(e)
@@ -742,7 +725,7 @@ end
function get_app_path(app_name)
if com[app_name] then
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
return path
end
@@ -1020,7 +1003,7 @@ local default_file_tree = {
}
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
if gh_proxy == "1" then
url = "https://gh-proxy.org/" .. url
@@ -1144,7 +1127,7 @@ function to_download(app_name, url, size)
local _curl_args = clone(curl_args)
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
if gh_proxy == "1" then
url = "https://gh-proxy.org/" .. url
@@ -1302,7 +1285,7 @@ end
function to_check_self()
local url = "https://raw.githubusercontent.com/Openwrt-Passwall/openwrt-passwall/main/luci-app-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
if gh_proxy == "1" then
url = "https://gh-proxy.org/" .. url
@@ -1339,8 +1322,72 @@ function to_check_self()
}
end
function is_js_luci()
return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
end
function set_default_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
--TextValue
local TextValue = cbi.TextValue
@@ -1377,18 +1424,15 @@ function return_map(map)
if true then
-- header
local header = cbi.Template(appname .. "/cbi/header")
header.api = api
header.config = map.config
header.map = map
table.insert(map.children, 1, header)
end
if true then
-- footer
local footer = cbi.Template(appname .. "/cbi/footer")
footer.api = api
footer.config = map.config
footer.map = map
map:append(footer)
end
return map
end
@@ -1569,20 +1613,8 @@ function format_go_time(input, default)
return result
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)
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 fs.access(tmp_uci_file) then
local redirect
@@ -1597,10 +1629,14 @@ function apply_redirect(m)
else
fs.writefile(tmp_uci_file, "config redirect\n")
end
local old = m.on_after_save
m.on_after_save = function(self)
if old then
old(self)
end
local redirect = self.redirect
if redirect and redirect ~= "" then
uci:set(appname .. "_redirect", "@redirect[0]", "url", redirect)
uci:set(c_config .. "_redirect", "@redirect[0]", "url", redirect)
end
end
else
@@ -1705,7 +1741,7 @@ end
function get_socks_backup_nodes(id)
id = trim(id)
if id == "" then return "" end
local socks = uci:get_all(appname, id)
local socks = uci:get_all(c_config, id)
local nodes
if socks.backup_node_add_mode and socks.backup_node_add_mode == "batch" then
local node = {}
@@ -1726,7 +1762,7 @@ function get_socks_backup_nodes(id)
end
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
for _, c in ipairs(candidates) do
if c[2] == v and c[1] then
@@ -6,7 +6,7 @@ local sys = api.sys
local uci = api.uci
local jsonc = api.jsonc
local CONFIG = "passwall_server"
local CONFIG = api.s_config
local CONFIG_PATH = "/tmp/etc/" .. CONFIG
local NFT_INCLUDE_FILE = CONFIG_PATH .. "/" .. CONFIG .. ".nft"
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
users = {}
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
users[user.username] = user.password
end
@@ -74,7 +74,7 @@ function gen_config(var)
print("node 不能为空")
return
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_udp_redir_port = var["local_udp_redir_port"]
local local_socks_address = var["local_socks_address"] or "0.0.0.0"
@@ -9,7 +9,7 @@ function gen_config(var)
print("node 不能为空")
return
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 local_addr = var["local_addr"]
local local_port = var["local_port"]
@@ -6,7 +6,7 @@ local jsonc = api.jsonc
function gen_config_server(node)
local user = nil
if node.user then
user = uci:get_all("passwall_server", node.user)
user = uci:get_all(api.s_config, node.user)
end
local config = {}
config.server_port = tonumber(node.port)
@@ -40,7 +40,7 @@ function gen_config(var)
print("node 不能为空")
return
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_port = var["server_port"] or node.port
local local_addr = var["local_addr"]
@@ -3,7 +3,7 @@ local api = require "luci.passwall.api"
local uci = api.uci
local sys = api.sys
local jsonc = api.jsonc
local appname = "passwall"
local appname = api.appname
local fs = api.fs
local ech_domain = {}
@@ -34,7 +34,7 @@ function check_geoview()
if GEO_VAR.OK == 0 then
api.log("!!!注意:缺少 Geoview 组件或版本过低,Sing-Box 分流无法启用!")
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.IP_PATH = GEO_VAR.IP_PATH or (GEO_VAR.DIR .. "/geoip.dat")
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
users = {}
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
local u = {}
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))
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
outbound_node_t = {
type = node.type,
@@ -1104,7 +1104,7 @@ function gen_config(var)
local rule_set_table = {}
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 = {
rules = {}
@@ -1166,7 +1166,7 @@ function gen_config(var)
end
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 server_host and server_port then
node.address = server_host
@@ -1256,7 +1256,7 @@ function gen_config(var)
function get_node_by_id(node_id)
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
local result = {
[".name"] = node_id,
@@ -1533,7 +1533,7 @@ function gen_config(var)
--shunt rule
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
@@ -1559,7 +1559,7 @@ function gen_config(var)
local bin = api.finded_com("geoview")
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
domain_list = (domain_list == "") and "geosite:gfw" or domain_list .. "\ngeosite:gfw"
end
+11 -11
View File
@@ -3,7 +3,7 @@ local api = require "luci.passwall.api"
local uci = api.uci
local sys = api.sys
local jsonc = api.jsonc
local appname = "passwall"
local appname = api.appname
local fs = api.fs
local GLOBAL = {
@@ -493,7 +493,7 @@ function gen_config_server(node)
if node.users and #node.users > 0 then
users = {}
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
local u = {}
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))
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
outbound_node_t = {
type = node.type,
@@ -901,7 +901,7 @@ function gen_config(var)
local outbounds = {}
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
local lengths, delays = {}, {}
@@ -926,7 +926,7 @@ function gen_config(var)
if xray_settings.noise == "1" then
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
local noise = {
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
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 rules = {}
if node then
@@ -1001,7 +1001,7 @@ function gen_config(var)
function get_node_by_id(node_id)
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
local result = {
[".name"] = node_id,
@@ -1374,7 +1374,7 @@ function gen_config(var)
--shunt rule
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
@@ -1400,7 +1400,7 @@ function gen_config(var)
local bin = api.finded_com("geoview")
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
domain_list = (domain_list == "") and "geosite:gfw" or domain_list .. "\ngeosite:gfw"
end
@@ -1788,7 +1788,7 @@ function gen_config(var)
})
-- 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 = {
tag = "dns-out",
protocol = "dns",
@@ -1979,7 +1979,7 @@ function gen_config(var)
if inbounds or outbounds then
local config = {
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 }
end)(),
log = {
@@ -1,6 +1,7 @@
<%
local api = self.api
local cfgid = self.cfgid
local map = self.map
local api = map.api
local sid = self.section
-%>
<script type="text/javascript">
//<![CDATA[
@@ -20,8 +21,8 @@ local cfgid = self.cfgid
return;
}
let to_url = '<%=api.url("node_config")%>/' + node_select_value;
if (node_select_value.indexOf("Socks_") === 0) {
to_url = '<%=api.url("socks_config")%>/' + node_select_value.substring("Socks_".length);
if (node_select_value.indexOf("socks_") === 0) {
to_url = '<%=api.url("socks_config")%>/' + node_select_value;
}
location.href = to_url;
}
@@ -50,7 +51,7 @@ local cfgid = self.cfgid
const m = cbid.match(/\.(tcp|udp)_node$/);
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>'
@@ -112,7 +113,7 @@ local cfgid = self.cfgid
logLink.href = "#";
logLink.className = "dns-log-link";
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);
};
})();
@@ -1,6 +1,7 @@
<div id="app_version">
<%
local api = self.api
local map = self.map
local api = map.api
local com = self.com
-%>
@@ -1,3 +1,6 @@
<%
local map = self.map
-%>
<!-- map footer -->
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
@@ -1,11 +1,15 @@
<%
local map = self.map
local api = map.api
-%>
<!-- map header -->
<script src="<%=resource%>/view/<%=self.api.appname%>/cbi.js"></script>
<script src="<%=resource%>/view/<%=self.api.appname%>/func.js"></script>
<script src="<%=resource%>/view/<%=api.appname%>/cbi.js"></script>
<script src="<%=resource%>/view/<%=api.appname%>/func.js"></script>
<script type="text/javascript">
//<![CDATA[
function update_config(cfgid, data, redirect_url) {
XHR.get('<%=self.api.url("update_config")%>', {
XHR.get('<%=api.url("update_config")%>', {
id: cfgid,
data: JSON.stringify(data)
},
@@ -1,7 +1,8 @@
<%
local api = self.api
local appname = self.appname or api.appname
local target_cfgname = self.target_cfgname
local map = self.map
local sectiontype = self.sectiontype
local api = map.api
local appname = self.appname or map.config
-%>
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js"></script>
<style>
@@ -37,7 +38,7 @@ local target_cfgname = self.target_cfgname
}
@media screen and (max-width: 1152px) {
#cbi-<%=appname%>-<%=target_cfgname%> .cbi-section-table-titles {
#cbi-<%=appname%>-<%=sectiontype%> .cbi-section-table-titles {
display: none !important;
}
}
@@ -47,7 +48,7 @@ local target_cfgname = self.target_cfgname
//Add drag-and-drop sorting
document.addEventListener("DOMContentLoaded", function () {
function initSortableForTable() {
var section = document.getElementById("cbi-<%=appname%>-<%=target_cfgname%>");
var section = document.getElementById("cbi-<%=appname%>-<%=sectiontype%>");
if (!section) return;
// === 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">
@@ -1,5 +1,6 @@
<%
local api = require "luci.passwall.api"
local map = self.map
local api = map.api
-%>
<style>
.dns-con {
@@ -1,6 +1,8 @@
<%
local api = self.api
local appname = api.appname
local map = self.map
local api = map.api
local appname = map.config
local sid = "@global[0]"
-%>
<style>
#cbi-<%=appname%>-socks .td.cbi-value-field > div {
@@ -35,15 +37,17 @@ local appname = api.appname
</style>
<script type="text/javascript">
//<![CDATA[
let global_id = "<%=sid%>";
const shunt_list = JSON.parse('<%=self.shunt_list%>');
function to_edit_node(btn) {
function to_edit_node(btn, stype) {
if (!btn) return;
const idReg = /^cbid\..*\..*node$/;
if (!stype) return;
let hidden_select = null;
const container = btn.closest('#cbi-<%=appname%>-global') || btn.closest('#cbi-<%=appname%>-socks');
if (!container) return null;
const selects = container.querySelectorAll('select[id^="cbid."][id*="."][id$="node"]');
const stype_dom = document.getElementById("cbi-<%=appname%>-" + stype);
if (!stype_dom) return;
const selects = stype_dom.querySelectorAll('select[id^="cbid."][id*="."][id$="node"]');
const idReg = /^cbid\..*\..*node$/;
for (const sel of selects) {
if ( idReg.test(sel.id) && getComputedStyle(sel).display === "none" && (sel.compareDocumentPosition(btn) & Node.DOCUMENT_POSITION_FOLLOWING)) {
hidden_select = sel;
@@ -94,8 +98,7 @@ local appname = api.appname
);
}
let global_id = null;
const global = document.getElementById("cbi-<%=appname%>-global");
const global = document.getElementById("cbi-<%=appname%>-" + global_id);
if (global) {
// 分流规则节点提前加入 “编辑” 占位符,以保证节点列表左对齐
document.querySelectorAll('.td[data-widget="nodes_listvalue"][data-name="_node"] > div').forEach(container => {
@@ -109,10 +112,7 @@ local appname = api.appname
await delay(100);
const node = global.getElementsByClassName("cbi-section-node")[0];
const node_id = node.getAttribute("id");
global_id = node_id;
const all_node = node.querySelectorAll("[id]");
const all_node = global.querySelectorAll("[id]");
const reg1 = /^cbid\..*node\.main$/;
//const reg1 = /^cbid\..*\.(tcp_node|udp_node)\.main$/;
@@ -129,7 +129,7 @@ local appname = api.appname
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$/);
if (m && (m[1] === "tcp" || m[1] === "udp")) {
@@ -149,7 +149,7 @@ local appname = api.appname
const socks = document.getElementById("cbi-<%=appname%>-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];
descr.replaceWith(socks_enabled_dom);
const rows = socks.getElementsByClassName("cbi-section-table-row");
@@ -164,7 +164,7 @@ local appname = api.appname
const node_select = document.getElementById(dom_id);
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>';
node_select.insertAdjacentHTML("afterend",
@@ -249,7 +249,7 @@ local appname = api.appname
})();
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
const o_hasItem = shunt_list.find(element => element.id == o_val);
hiddenSelect.addEventListener("change", function(el){
@@ -257,7 +257,7 @@ local appname = api.appname
const new_hasItem = shunt_list.find(element => element.id == new_val);
if (new_hasItem) {
XHR.get('<%=api.url("update_config")%>', {
id: "<%=self.global_cfgid%>",
id: "<%=sid%>",
data: JSON.stringify({
tcp_node: new_val
})
@@ -272,8 +272,8 @@ local appname = api.appname
});
} else {
try {
document.getElementById("tab.<%=appname%>.<%=self.global_cfgid%>.Shunt").classList.add('shunt-tab-hidden');
document.getElementById("tab.<%=appname%>.<%=self.global_cfgid%>.Shunt").style.display = "none";
document.getElementById("tab.<%=appname%>.<%=sid%>.Shunt").classList.add('shunt-tab-hidden');
document.getElementById("tab.<%=appname%>.<%=sid%>.Shunt").style.display = "none";
} catch (error) {}
try {
document.querySelector('li[data-tab*="Shunt"]').classList.add('shunt-tab-hidden');
@@ -281,7 +281,7 @@ local appname = api.appname
} 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) {
let shunt_option_list = document.getElementById("cbi-<%=appname%>-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>
@@ -1,6 +1,6 @@
<%
local api = require "luci.passwall.api"
local appname = api.appname
local map = self.map
local appname = map.config
-%>
<style>
@@ -1,7 +1,8 @@
<%
local api = require "luci.passwall.api"
local haproxy_enable = api.uci_get_type("global_haproxy", "balancing_enable", "0")
local console_port = api.uci_get_type("global_haproxy", "console_port", "")
local map = self.map
local api = map.api
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>
@@ -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>
.hidden {
display: none !important;
@@ -54,15 +61,15 @@
}
}
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;
el.addEventListener("change", () => {
el.blur();
if (o_val != el.value) {
let save = true;
if (save) {
update_config("<%=self.id%>", {
shunt_group: getOption("<%=self.config%>", "<%=self.s_cfgid%>", "shunt_group").value,
update_config("<%=id%>", {
shunt_group: getOption("<%=config%>", "<%=s_cfgid%>", "shunt_group").value,
}, 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">
//<![CDATA[
let node_id = "<%=self.section%>";
let node_config_url = '<%=self.api.url("node_config")%>/' + node_id;
let node_id = "<%=sid%>";
let node_config_url = '<%=api.url("node_config")%>/' + node_id;
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;
el.addEventListener("change", () => {
el.blur();
@@ -18,16 +24,16 @@
}
*/
update_config(node_id, {
remarks: getOption("<%=self.config%>", "<%=self.section%>", "remarks").value,
group: getOption("<%=self.config%>", "<%=self.section%>", "group").value,
type: getOption("<%=self.config%>", "<%=self.section%>", "type").value,
remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=config%>", "<%=sid%>", "group").value,
type: getOption("<%=config%>", "<%=sid%>", "type").value,
//protocol: ''
}, 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;
el.addEventListener("change", () => {
el.blur();
@@ -43,9 +49,9 @@
}
*/
update_config(node_id, {
remarks: getOption("<%=self.config%>", "<%=self.section%>", "remarks").value,
group: getOption("<%=self.config%>", "<%=self.section%>", "group").value,
protocol: getOption("<%=self.config%>", "<%=self.section%>", name).value,
remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=config%>", "<%=sid%>", "group").value,
protocol: getOption("<%=config%>", "<%=sid%>", name).value,
}, node_config_url);
} else {
window.location.href = node_config_url + "?select_proto=" + encodeURIComponent(el.value);
@@ -1,3 +1,8 @@
<%
local map = self.map
local api = map.api
local sid = self.section
-%>
<script type="text/javascript">
//<![CDATA[
function fetchCertSha256(el) {
@@ -5,7 +10,7 @@
el.setAttribute("data-loading", "1");
el.style.pointerEvents = "none";
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.style.pointerEvents = "";
el.style.color = "";
@@ -1,7 +1,7 @@
<%
local api = self.api
local appname = api.appname
local map = self.map
local api = map.api
local appname = map.config
local is_js_luci = api.is_js_luci()
local section_tag = is_js_luci and "div" or "fieldset"
-%>
@@ -415,8 +415,8 @@ table td, .table .td {
<script type="text/javascript">
//<![CDATA[
let auto_detection_time = "<%=api.uci_get_type("global_other", "auto_detection_time", "0")%>"
let show_node_info = "<%=api.uci_get_type("global_other", "show_node_info", "0")%>"
let auto_detection_time = "<%=map:get("@global_other[0]", "auto_detection_time") or "0"%>"
let show_node_info = "<%=map:get("@global_other[0]", "show_node_info") or "0"%>"
var ajax = {
list: [],
@@ -1,5 +1,6 @@
<%
local api = require "luci.passwall.api"
local map = self.map
local api = map.api
-%>
<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 has_old_geoip = fs.access("/tmp/bak_v2ray/geoip.dat")
local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
@@ -1,6 +1,7 @@
<%
local api = self.api
local appname = api.appname
local map = self.map
local api = map.api
local appname = map.config
local is_js_luci = api.is_js_luci()
local section_tag = is_js_luci and "div" or "fieldset"
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>
@@ -1,7 +1,6 @@
<%
local api = require "luci.passwall.api"
local translate = luci.i18n.translate
local total_lines_text = translate("Total Lines")
local map = self.map
local api = map.api
-%>
<script type="text/javascript">
//<![CDATA[
@@ -14,7 +13,7 @@ local total_lines_text = translate("Total Lines")
textarea.innerHTML = data;
//textarea.scrollTop = textarea.scrollHeight;
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.scrollTop = textarea.scrollHeight;
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.scrollTop = textarea.scrollHeight;
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">
//<![CDATA[
let node_id = "<%=self.section%>";
let node_id = "<%=section%>";
let node_config_url = '<%=api.url("server_config")%>/' + node_id;
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;
el.addEventListener("change", () => {
el.blur();
@@ -16,9 +19,9 @@ local api = self.api
if (save) {
//document.getElementsByClassName('cbi-button-save')[0].click();
server_update_config(node_id, {
enable: getOption("<%=self.config%>", node_id, "enable").value,
remarks: getOption("<%=self.config%>", node_id, "remarks").value,
type: getOption("<%=self.config%>", node_id, "type").value,
enable: getOption("<%=config%>", node_id, "enable").value,
remarks: getOption("<%=config%>", node_id, "remarks").value,
type: getOption("<%=config%>", node_id, "type").value,
protocol: ''
}, node_config_url);
}
@@ -1,7 +1,12 @@
<%
local map = self.map
local api = map.api
local section = self.section
-%>
<script type="text/javascript">
//<![CDATA[
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,
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">
//<![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">
//<![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++) {
try {
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">
-24
View File
@@ -1508,18 +1508,6 @@ msgstr "配合伪装类型 DNS 使用,可随便填一个域名。"
msgid "Auth"
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."
msgstr "该用户名已存在。"
@@ -1538,18 +1526,6 @@ msgstr "IPv6 透明代理(TProxy)"
msgid "Experimental feature. Make sure that your node supports 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"
msgstr "目标协议"
@@ -5,9 +5,6 @@ if [ -e "/etc/config/ucitrack" ]; then
delete ucitrack.@passwall[-1]
add ucitrack 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
EOF
fi
@@ -18,11 +15,6 @@ uci -q batch <<-EOF
set firewall.passwall.type='script'
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
commit dhcp
set uhttpd.main.max_requests=50
@@ -31,12 +23,9 @@ EOF
if [ -x "/sbin/fw3" ]; then
uci -q set firewall.passwall.reload='1'
uci -q set firewall.passwall_server.reload='1'
else
uci -q delete firewall.passwall.reload
uci -q delete firewall.passwall.fw4_compatible
uci -q delete firewall.passwall_server.reload
uci -q delete firewall.passwall_server.fw4_compatible
fi
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 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_inter = uci:get(appname, "@global_haproxy[0]", "health_check_inter") or "20"
local balancingStrategy = uci:get(appname, "@global_haproxy[0]", "balancingStrategy") or "roundrobin"
local console_port = uci:get(appname, "@global_haproxy[0]", "console_port")
local bind_local = uci:get(appname, "@global_haproxy[0]", "bind_local") or "0"
local health_check_type = uci:get(api.c_config, "@global_haproxy[0]", "health_check_type") or "tcp"
local health_check_inter = uci:get(api.c_config, "@global_haproxy[0]", "health_check_inter") or "20"
local balancingStrategy = uci:get(api.c_config, "@global_haproxy[0]", "balancingStrategy") or "roundrobin"
local console_port = uci:get(api.c_config, "@global_haproxy[0]", "console_port")
local bind_local = uci:get(api.c_config, "@global_haproxy[0]", "bind_local") or "0"
local bind_address = "0.0.0.0"
if bind_local == "1" then bind_address = "127.0.0.1" end
@@ -94,15 +94,15 @@ f_out:write(haproxy_config)
local listens = {}
uci:foreach(appname, "haproxy_config", function(t)
uci:foreach(api.c_config, "haproxy_config", function(t)
if t.enabled == "1" then
local server_remark
local server_address
local server_port
local lbss = t.lbss
local listen_port = tonumber(t.haproxy_port) or 0
local server_node = uci:get_all(appname, lbss)
local hop = (health_check_type == "passwall_logic") and (server_node.hysteria_hop or server_node.hysteria2_hop) or nil
local server_node = uci:get_all(api.c_config, lbss)
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
if server_node and server_node.address and (server_node.port or hop) then
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
t.origin_address = server_address
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
local relay_port = server_node.port
local new_port = api.get_new_port()
@@ -172,7 +172,7 @@ listen %s
balance %s
]], port, bind_address, port, balancingStrategy))
if health_check_type == "passwall_logic" then
if health_check_type == "script_logic" then
f_out:write(string.format([[
option external-check
external-check command "/usr/share/%s/haproxy_check.sh"
@@ -214,8 +214,8 @@ listen %s
end
--控制台配置
local console_user = uci:get(appname, "@global_haproxy[0]", "console_user")
local console_password = uci:get(appname, "@global_haproxy[0]", "console_password")
local console_user = uci:get(api.c_config, "@global_haproxy[0]", "console_user")
local console_password = uci:get(api.c_config, "@global_haproxy[0]", "console_password")
local str = [[
listen console
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()
--passwall内置健康检查URL
if health_check_type == "passwall_logic" then
local probeUrl = uci:get(appname, "@global_haproxy[0]", "health_probe_url") or "https://www.google.com/generate_204"
if health_check_type == "script_logic" then
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")
f_url:write(probeUrl)
f_url:close()
@@ -31,8 +31,8 @@ local RULES_PATH = "/usr/share/" .. appname .. "/rules"
local FLAG_PATH = TMP_ACL_PATH .. "/" .. FLAG
local config_lines = {}
local tmp_lines = {}
local USE_GEOVIEW = uci:get(appname, "@global_rules[0]", "enable_geoview")
local IS_SHUNT_NODE = uci:get(appname, TCP_NODE, "protocol") == "_shunt"
local USE_GEOVIEW = uci:get(api.c_config, "@global_rules[0]", "enable_geoview")
local IS_SHUNT_NODE = uci:get(api.c_config, TCP_NODE, "protocol") == "_shunt"
if not api.is_finded("geoview") then
USE_GEOVIEW = "0"
@@ -92,7 +92,7 @@ local function insert_array_after(array1, array2, target) --将array2插入到ar
end
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"
if not is_file_nonzero(geosite_path) then return 1 end
local bin = api.finded_com("geoview")
@@ -183,7 +183,7 @@ if not is_file_nonzero(file_vpslist) then
written_domains[address] = true
end
end
uci:foreach(appname, "nodes", function(t)
uci:foreach(api.c_config, "nodes", function(t)
process_address(t.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 "")
@@ -191,7 +191,7 @@ if not is_file_nonzero(file_vpslist) then
process_address(dns)
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 "")
if url and url ~= "" then
process_address(url)
@@ -387,9 +387,9 @@ if IS_SHUNT_NODE then
local file_shunt_host = FLAG_PATH .. "/shunt_proxy_host"
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"
uci:foreach(appname, "shunt_rules", function(s)
uci:foreach(api.c_config, "shunt_rules", function(s)
local _node_id = t[s[".name"]]
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
if _node_id == "_default" then
@@ -24,8 +24,8 @@ end
local function backup_servers()
local DNSMASQ_DNS = uci:get("dhcp", "@dnsmasq[0]", "server")
if DNSMASQ_DNS and #DNSMASQ_DNS > 0 then
uci:set(appname, "@global[0]", "dnsmasq_servers", DNSMASQ_DNS)
api.uci_save(uci, appname, true)
uci:set(api.c_config, "@global[0]", "dnsmasq_servers", DNSMASQ_DNS)
api.uci_save(uci, api.c_config, true)
end
end
@@ -37,13 +37,13 @@ local function restore_servers()
tinsert(dns_table, v)
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
for k, v in ipairs(OLD_SERVER) do
tinsert(dns_table, v)
end
uci:delete(appname, "@global[0]", "dnsmasq_servers")
api.uci_save(uci, appname, true)
uci:delete(api.c_config, "@global[0]", "dnsmasq_servers")
api.uci_save(uci, api.c_config, true)
end
if dns_table and #dns_table > 0 then
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_TEXT_FILE = CACHE_DNS_PATH .. ".txt"
local USE_CHINADNS_NG = "0"
local IS_SHUNT_NODE = uci:get(appname, TCP_NODE, "protocol") == "_shunt"
local USE_GEOVIEW = uci:get(appname, "@global_rules[0]", "enable_geoview")
local IS_SHUNT_NODE = uci:get(api.c_config, TCP_NODE, "protocol") == "_shunt"
local USE_GEOVIEW = uci:get(api.c_config, "@global_rules[0]", "enable_geoview")
local list1 = {}
local excluded_domain = {}
@@ -307,7 +307,7 @@ function add_rule(var)
end
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"
if not fs.access(geosite_path) then return end
local bin = api.finded_com("geoview")
@@ -412,7 +412,7 @@ function add_rule(var)
set_domain_ipset(address, table.concat(sets, ","))
end
end
uci:foreach(appname, "nodes", function(t)
uci:foreach(api.c_config, "nodes", function(t)
process_address(t.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 "")
@@ -420,7 +420,7 @@ function add_rule(var)
process_address(dns)
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 "")
if url and url ~= "" then
process_address(url)
@@ -615,9 +615,9 @@ function add_rule(var)
--分流规则
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"
uci:foreach(appname, "shunt_rules", function(s)
uci:foreach(api.c_config, "shunt_rules", function(s)
local _node_id = t[s[".name"]]
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group 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 config_lines = {}
local tmp_lines = {}
local USE_GEOVIEW = uci:get(appname, "@global_rules[0]", "enable_geoview")
local IS_SHUNT_NODE = uci:get(appname, TCP_NODE, "protocol") == "_shunt"
local USE_GEOVIEW = uci:get(api.c_config, "@global_rules[0]", "enable_geoview")
local IS_SHUNT_NODE = uci:get(api.c_config, TCP_NODE, "protocol") == "_shunt"
if not api.is_finded("geoview") then
USE_GEOVIEW = "0"
@@ -98,7 +98,7 @@ local function insert_array_after(array1, array2, target) --将array2插入到ar
end
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"
if not is_file_nonzero(geosite_path) then return 1 end
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')
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"
config_lines = {
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
end
end
uci:foreach(appname, "nodes", function(t)
uci:foreach(api.c_config, "nodes", function(t)
process_address(t.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 "")
@@ -350,7 +350,7 @@ if not is_file_nonzero(file_vpslist) then
process_address(dns)
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 "")
if url and url ~= "" then
process_address(url)
@@ -555,9 +555,9 @@ if IS_SHUNT_NODE then
local file_shunt_host = FLAG_PATH .. "/shunt_proxy_host"
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"
uci:foreach(appname, "shunt_rules", function(s)
uci:foreach(api.c_config, "shunt_rules", function(s)
local _node_id = t[s[".name"]]
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
if _node_id == "_default" then
@@ -2,6 +2,7 @@
local api = require ("luci.passwall.api")
local name = api.appname
local c_config = api.c_config
local uci = api.uci
local sys = api.sys
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 gfwlist_url = uci:get(name, "@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 chnroute6_url = uci:get(name, "@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 geoip_url = uci:get(name, "@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 asset_location = uci:get(name, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
local geo2rule = uci:get(name, "@global_rules[0]", "geo2rule") or "0"
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(c_config, "@global_rules[0]", "chnroute_url") or {"https://ispip.clang.cn/all_cn.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(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(c_config, "@global_rules[0]", "geoip_url") or "https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.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(c_config, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
local geo2rule = uci:get(c_config, "@global_rules[0]", "geo2rule") or "0"
local geoip_update_ok, geosite_update_ok = false, false
asset_location = asset_location:match("/$") and asset_location or (asset_location .. "/")
local backup_path = "/tmp/bak_v2ray/"
@@ -659,12 +660,12 @@ if arg2 then
end)
if rollback then arg2 = nil end
else
gfwlist_update = uci:get(name, "@global_rules[0]", "gfwlist_update") or "1"
chnroute_update = uci:get(name, "@global_rules[0]", "chnroute_update") or "1"
chnroute6_update = uci:get(name, "@global_rules[0]", "chnroute6_update") or "1"
chnlist_update = uci:get(name, "@global_rules[0]", "chnlist_update") or "1"
geoip_update = uci:get(name, "@global_rules[0]", "geoip_update") or "1"
geosite_update = uci:get(name, "@global_rules[0]", "geosite_update") or "1"
gfwlist_update = uci:get(c_config, "@global_rules[0]", "gfwlist_update") or "1"
chnroute_update = uci:get(c_config, "@global_rules[0]", "chnroute_update") or "1"
chnroute6_update = uci:get(c_config, "@global_rules[0]", "chnroute6_update") or "1"
chnlist_update = uci:get(c_config, "@global_rules[0]", "chnlist_update") or "1"
geoip_update = uci:get(c_config, "@global_rules[0]", "geoip_update") or "1"
geosite_update = uci:get(c_config, "@global_rules[0]", "geosite_update") or "1"
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
os.exit(0)
@@ -777,13 +778,13 @@ else
end
if not rollback then
uci:set(name, "@global_rules[0]", "gfwlist_update", gfwlist_update)
uci:set(name, "@global_rules[0]", "chnroute_update", chnroute_update)
uci:set(name, "@global_rules[0]", "chnroute6_update", chnroute6_update)
uci:set(name, "@global_rules[0]", "chnlist_update", chnlist_update)
uci:set(name, "@global_rules[0]", "geoip_update", geoip_update)
uci:set(name, "@global_rules[0]", "geosite_update", geosite_update)
api.uci_save(uci, name, true)
uci:set(c_config, "@global_rules[0]", "gfwlist_update", gfwlist_update)
uci:set(c_config, "@global_rules[0]", "chnroute_update", chnroute_update)
uci:set(c_config, "@global_rules[0]", "chnroute6_update", chnroute6_update)
uci:set(c_config, "@global_rules[0]", "chnlist_update", chnlist_update)
uci:set(c_config, "@global_rules[0]", "geoip_update", geoip_update)
uci:set(c_config, "@global_rules[0]", "geosite_update", geosite_update)
api.uci_save(uci, c_config, true)
end
if reboot == 1 then
@@ -794,8 +795,8 @@ if reboot == 1 then
end
log("重启服务,应用新的规则。")
uci:set(name, "@global[0]", "flush_set", "1")
api.uci_save(uci, name, true, true)
uci:set(c_config, "@global[0]", "flush_set", "1")
api.uci_save(uci, c_config, true, true)
end
log("规则更新完毕...\n")
@@ -6,8 +6,9 @@
require 'luci.util'
require 'luci.jsonc'
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"
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_hysteria2 = api.finded_com("hysteria")
local DEFAULT_ALLOWINSECURE = true
local DEFAULT_FILTER_KEYWORD_MODE = uci:get(appname, "@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_KEEP_LIST = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {}
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(c_config, "@global_subscribe[0]", "filter_discard_list") or {}
local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci:get(c_config, "@global_subscribe[0]", "filter_keep_list") or {}
-- 取节点使用core类型(节点订阅页面未设置时,自动取默认)
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"}})
@@ -141,13 +142,13 @@ do
local szType = "@global[0]"
local option = protocol .. "_node"
local node_id = uci:get(appname, szType, option)
local node_id = uci:get(c_config, szType, option)
CONFIG[#CONFIG + 1] = {
log = true,
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)
uci:set(appname, szType, option, server)
uci:set(c_config, szType, option, server)
o.newNodeId = server
end
}
@@ -158,7 +159,7 @@ do
if true then
local i = 0
local option = "node"
uci:foreach(appname, "socks", function(t)
uci:foreach(c_config, "socks", function(t)
i = i + 1
local id = t[".name"]
local node_id = t[option]
@@ -166,14 +167,14 @@ do
log = true,
id = id,
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)
if not server or server == "" then
if #nodes_table > 0 then
server = nodes_table[1][".name"]
end
end
uci:set(appname, t[".name"], option, server)
uci:set(c_config, t[".name"], option, server)
o.newNodeId = server
end
}
@@ -183,7 +184,7 @@ do
local newNodes = {}
for k, asb_node_id in ipairs(t.autoswitch_backup_node) do
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
currentNodes[#currentNodes + 1] = {
log = true,
@@ -205,7 +206,7 @@ do
set = function(o, newNodes)
if o then
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
}
@@ -221,25 +222,25 @@ do
local ip, port = str:match("^([%d%.]+):(%d+)$")
return ip and datatypes.ipaddr(ip) and tonumber(port) and tonumber(port) <= 65535
end
uci:foreach(appname, "haproxy_config", function(t)
uci:foreach(c_config, "haproxy_config", function(t)
i = i + 1
local node_id = t[option]
CONFIG[#CONFIG + 1] = {
log = true,
id = t[".name"],
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)
-- 如果当前 lbss 值不是 ip:port 格式,才进行修改
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
end
end,
delete = function(o)
-- 如果当前 lbss 值不是 ip:port 格式,才进行删除
if not is_ip_port(t[option]) then
uci:delete(appname, t[".name"])
uci:delete(c_config, t[".name"])
end
end
}
@@ -249,7 +250,7 @@ do
if true then
local i = 0
local options = {"tcp", "udp"}
uci:foreach(appname, "acl_rule", function(t)
uci:foreach(c_config, "acl_rule", function(t)
i = i + 1
for index, value in ipairs(options) do
local option = value .. "_node"
@@ -258,9 +259,9 @@ do
log = true,
id = t[".name"],
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)
uci:set(appname, t[".name"], option, server)
uci:set(c_config, t[".name"], option, server)
o.newNodeId = server
end
}
@@ -268,11 +269,11 @@ do
end)
end
uci:foreach(appname, "nodes", function(node)
uci:foreach(c_config, "nodes", function(node)
local node_id = node[".name"]
if node.protocol and node.protocol == '_shunt' then
local rules = {}
uci:foreach(appname, "shunt_rules", function(e)
uci:foreach(c_config, "shunt_rules", function(e)
if e[".name"] and e.remarks then
table.insert(rules, e)
table.insert(rules, {
@@ -293,7 +294,7 @@ do
for k, e in pairs(rules) do
local _node_id = node[e[".name"]] or nil
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
CONFIG[#CONFIG + 1] = {
log = false,
@@ -301,7 +302,7 @@ do
remarks = "分流" .. e.remarks .. "节点",
set = function(o, server)
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
end
}
@@ -318,7 +319,7 @@ do
log = true,
node = b_node_id,
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
return { Socks = b_node_id }
end
@@ -340,15 +341,15 @@ do
set = function(o, newNodes)
if o then
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
}
--后备节点
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
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
CONFIG[#CONFIG + 1] = {
log = true,
@@ -356,11 +357,11 @@ do
remarks = "Xray负载均衡节点[" .. node_id .. "]后备节点",
currentNode = section,
set = function(o, server)
uci:set(appname, node_id, "fallback_node", server)
uci:set(c_config, node_id, "fallback_node", server)
o.newNodeId = server
end,
delete = function(o)
uci:delete(appname, node_id, "fallback_node")
uci:delete(c_config, node_id, "fallback_node")
end
}
end
@@ -375,7 +376,7 @@ do
log = true,
node = u_node_id,
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
return { Socks = u_node_id }
end
@@ -397,47 +398,47 @@ do
set = function(o, newNodes)
if o then
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
}
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
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
CONFIG[#CONFIG + 1] = {
log = true,
id = 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)
uci:set(appname, node_id, "preproxy_node", server)
uci:set(c_config, node_id, "preproxy_node", server)
o.newNodeId = server
end,
delete = function(o)
uci:delete(appname, node_id, "preproxy_node")
uci:delete(c_config, node_id, "preproxy_node")
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
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
CONFIG[#CONFIG + 1] = {
log = true,
id = 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)
uci:set(appname, node_id, "to_node", server)
uci:set(c_config, node_id, "to_node", server)
o.newNodeId = server
end,
delete = function(o)
uci:delete(appname, node_id, "to_node")
uci:delete(c_config, node_id, "to_node")
end
}
end
@@ -1756,19 +1757,19 @@ local function truncate_nodes(group)
end
end
end
uci:foreach(appname, "nodes", function(node)
uci:foreach(c_config, "nodes", function(node)
if node.add_mode == "2" 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)
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
uci:delete(appname, o['.name'], "md5")
uci:delete(c_config, o['.name'], "md5")
end
end)
api.uci_save(uci, appname, true)
api.uci_save(uci, c_config, true)
end
local function select_node(nodes, config, parentConfig)
@@ -1907,10 +1908,10 @@ local function update_node(manual)
end
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
uci:delete(appname, node['.name'])
uci:delete(c_config, node['.name'])
end
end)
end
@@ -1923,9 +1924,9 @@ local function update_node(manual)
-- Subscription Group Chain Agent
local function valid_chain_node(node)
if not node then return "" end
local cp = uci:get(appname, node, "chain_proxy") or ""
local am = uci:get(appname, node, "add_mode") or "0"
chain_node_type = (cp == "" and am ~= "2") and (uci:get(appname, node, "type") or "") or ""
local cp = uci:get(c_config, node, "chain_proxy") or ""
local am = uci:get(c_config, node, "add_mode") or "0"
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
chain_node_type = ""
return ""
@@ -1944,22 +1945,22 @@ local function update_node(manual)
chain_node_type = (outbound_iface_group ~= "") and "iface" or chain_node_type
end
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
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
if kkk ~= "group" or vvv ~= "default" then
uci:set(appname, cfgid, kkk, vvv)
uci:set(c_config, cfgid, kkk, vvv)
end
-- sing-box/xray 节点域名解析
if kkk == "type" and (vvv == "Xray" or vvv == "sing-box") 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
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
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
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" }
ds = map[ds] or ""
end
uci:set(appname, cfgid, "domain_strategy", ds)
uci:set(c_config, cfgid, "domain_strategy", ds)
end
end
-- 订阅组链式代理
if chain_node_type ~= "" and kkk == "type" and (vvv == "Xray" or vvv == "sing-box") then
if preproxy_node_group ~="" then
uci:set(appname, cfgid, "chain_proxy", "1")
uci:set(appname, cfgid, "preproxy_node", preproxy_node_group)
uci:set(c_config, cfgid, "chain_proxy", "1")
uci:set(c_config, cfgid, "preproxy_node", preproxy_node_group)
elseif to_node_group ~= "" then
uci:set(appname, cfgid, "chain_proxy", "2")
uci:set(appname, cfgid, "to_node", to_node_group)
uci:set(c_config, cfgid, "chain_proxy", "2")
uci:set(c_config, cfgid, "to_node", to_node_group)
elseif outbound_iface_group ~= "" then
uci:set(appname, cfgid, "chain_proxy", "3")
uci:set(appname, cfgid, "outbound_iface", outbound_iface_group)
uci:set(c_config, cfgid, "chain_proxy", "3")
uci:set(c_config, cfgid, "outbound_iface", outbound_iface_group)
end
end
end
@@ -1992,16 +1993,16 @@ local function update_node(manual)
for cfgid, info in pairs(subscribe_info) do
for key, value in pairs(info) do
if value ~= "" then
uci:set(appname, cfgid, key, value)
uci:set(c_config, cfgid, key, value)
else
uci:delete(appname, cfgid, key)
uci:delete(c_config, cfgid, key)
end
end
end
if next(CONFIG) then
local nodes = {}
uci:foreach(appname, "nodes", function(node)
uci:foreach(c_config, "nodes", function(node)
nodes[#nodes + 1] = node
end)
@@ -2020,11 +2021,11 @@ local function update_node(manual)
end
end
api.uci_save(uci, appname, true)
api.uci_save(uci, c_config, true)
if arg[3] == "cron" then
if not fs.access("/var/lock/" .. appname .. ".lock") then
luci.sys.call("touch /tmp/lock/" .. appname .. "_cron.lock")
if not fs.access("/var/lock/" .. c_config .. ".lock") then
luci.sys.call("touch /tmp/lock/" .. c_config .. "_cron.lock")
end
end
@@ -2133,10 +2134,10 @@ local execute = function()
local fail_list = {}
if arg[2] ~= "all" then
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)
else
uci:foreach(appname, "subscribe_list", function(o)
uci:foreach(c_config, "subscribe_list", function(o)
subscribe_list[#subscribe_list + 1] = o
end)
end
@@ -2182,7 +2183,7 @@ local execute = function()
raw_data = parseClashNode(raw_data)
subscribe_info[cfgid] = parse_clash_sub_info(headers)
parse_link(raw_data, "2", remark, value)
uci:set(appname, cfgid, "md5", new_md5)
uci:set(c_config, cfgid, "md5", new_md5)
end
else
fail_list[#fail_list + 1] = value
@@ -2216,7 +2217,7 @@ local function check_instance(action)
os.exit(0)
else
luci.sys.call("touch " .. sub_lock)
uci:revert(appname)
uci:revert(c_config)
end
elseif action == "end" then
luci.sys.call("rm -f " .. sub_lock)
@@ -204,7 +204,7 @@ end
current_node = current_node_id and m:get(current_node_id) or {}
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.default = "warn"
@@ -352,6 +352,10 @@ o:depends("remote_dns_protocol", "http3")
o:depends("remote_dns_protocol", "quic")
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:value("default", translate("Use global config"))
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
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")
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
--Shunt node has its own separate options.
s.fields["remote_fakedns"]:depends({ node = v.id, remote_dns_protocol = "tcp" })
@@ -234,6 +234,12 @@ o:value("UseIP")
o:value("UseIPv4")
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.rows = 5
o.wrap = "off"
@@ -1116,6 +1116,7 @@ function gen_config(var)
local remote_dns_query_strategy = var["remote_dns_query_strategy"]
local remote_dns_fake = var["remote_dns_fake"]
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 tags = var["tags"]
local no_run = var["no_run"]
@@ -2026,7 +2027,7 @@ function gen_config(var)
end
if value.outboundTag ~= "block" and value.outboundTag ~= "direct" then
dns_rule.server = "remote"
dns_rule.rewrite_ttl = 30
dns_rule.rewrite_ttl = tonumber(remote_rewrite_ttl)
if true then
local block_rule
if remote_strategy == "ipv4_only" then
@@ -2073,29 +2074,42 @@ function gen_config(var)
end
end
if default_dns_flag == "remote" then
local block_rule
local dns_rule_query_type = { "A", "AAAA" }
if remote_strategy == "ipv4_only" then
block_rule = {
query_type = { "AAAA" },
action = "predefined",
rcode = "NOERROR"
}
dns_rule_query_type = { "A" }
elseif remote_strategy == "ipv6_only" then
block_rule = {
query_type = { "A" },
action = "predefined",
rcode = "NOERROR"
}
dns_rule_query_type = { "AAAA" }
end
if block_rule then
table.insert(dns.rules, block_rule)
end
if remote_dns_fake then
-- When default is not direct and enable fakedns, default DNS use FakeDNS.
local fakedns_dns_rule = {
query_type = dns_rule_query_type,
server = fakedns_tag,
disable_cache = true,
rewrite_ttl = 30
rewrite_ttl = tonumber(remote_rewrite_ttl)
}
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
local remote_dns_rule = {
server = "remote",
disable_cache = true,
rewrite_ttl = tonumber(remote_rewrite_ttl)
}
table.insert(dns.rules, remote_dns_rule)
end
local dns_in_inbound = {
type = "direct",
@@ -201,7 +201,7 @@ run_xray() {
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 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
eval_set_val $@
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_cache" ] && json_add_string "dns_cache" "${dns_cache}"
[ "$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_server" "${DIRECT_DNS_UDP_SERVER}"
@@ -612,6 +613,7 @@ run_global() {
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}"
V2RAY_ARGS="${V2RAY_ARGS} remote_rewrite_ttl=$(config_t_get global remote_rewrite_ttl)"
}
dns_msg="${dns_msg})"
@@ -982,7 +984,7 @@ acl_app() {
dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400}
for sid in $items; do
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
[ "$(config_n_get $sid enabled)" = "1" ] || continue
has_enabled=1
@@ -1086,7 +1088,8 @@ acl_app() {
dns_listen_port=${dns_port} \
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_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} \
log_file="${log_file}" loglevel="${loglevel}"
local status=$?
@@ -1108,7 +1111,7 @@ acl_app() {
}
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
done
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" ]
}
}
}