summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-https-dns-proxy/luasrc/model/cbi/https-dns-proxy.lua
blob: d914bf09a33fe58d1711e14540622a188b462b38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
local sys = require "luci.sys"
local util = require "luci.util"
local fs = require "nixio.fs"
local dispatcher = require "luci.dispatcher"
local i18n = require "luci.i18n"
local uci = require("luci.model.uci").cursor()

local packageName = "https-dns-proxy"
local providers_dir = "/usr/lib/lua/luci/" .. packageName .. "/providers/"
local helperText = ""

function create_helper_text()
	local initText = "<br />" .. translate("For more information on different options check") .. " "
	for filename in fs.dir(providers_dir) do
		local p_func = loadfile(providers_dir .. filename)
		setfenv(p_func, { _ = i18n.translate })
		local p = p_func()
		if p.help_link then
			local url, domain
			url = p.help_link
			domain = p.help_link_text or url:match('^%w+://([^/]+)')
			if not helperText:find(domain) then
				if helperText == "" then
					helperText = initText
				else
					helperText = helperText .. ", "
				end
				helperText = helperText .. [[<a href="]] .. url .. [[">]] .. domain .. [[</a>]]
			end
		end
	end
	if helperText ~= "" then
		local a = helperText:gsub('(.*),%s.*$', '%1')
		helperText = a .. " " .. translate("and") .. helperText:sub(#a + 2) .. "."
	end
end

function get_provider_name(value)
	for filename in fs.dir(providers_dir) do
		local p_func = loadfile(providers_dir .. filename)
		setfenv(p_func, { _ = i18n.translate })
		local p = p_func()
		value = value:gsub('[%p%c%s]', '')
		p.url_match = p.resolver_url:gsub('[%p%c%s]', '')
		if value:match(p.url_match) then
			return p.label
		end
	end
	return translate("Unknown Provider")
end

local tmpfsStatus, tmpfsStatusCode
local ubusStatus = util.ubus("service", "list", { name = packageName })
local tmpfsVersion = tostring(util.trim(sys.exec("opkg list-installed " .. packageName .. " | awk '{print $3}'")))

if not tmpfsVersion or tmpfsVersion == "" then
	tmpfsStatusCode = -1
	tmpfsVersion = ""
	tmpfsStatus = packageName .. " " .. translate("is not installed or not found")
else  
	tmpfsVersion = " [" .. packageName .. " " .. tmpfsVersion .. "]"
	if not ubusStatus or not ubusStatus[packageName] then
		tmpfsStatusCode = 0
		tmpfsStatus = translate("Stopped")
		if not luci.sys.init.enabled(packageName) then
			tmpfsStatus = tmpfsStatus .. " (" .. translate("disabled") .. ")"
		end
	else
		tmpfsStatusCode, tmpfsStatus = 1, ""
		for n = 1,1000 do
			if ubusStatus and ubusStatus[packageName] and 
				 ubusStatus[packageName]["instances"] and 
				 ubusStatus[packageName]["instances"]["instance" .. n] and 
				 ubusStatus[packageName]["instances"]["instance" .. n]["running"] then
				local value, k, v, url, url_flag, la, la_flag, lp, lp_flag
				for k, v in pairs(ubusStatus[packageName]["instances"]["instance" .. n]["command"]) do
					if la_flag then la, la_flag = v, false end
					if lp_flag then lp, lp_flag = v, false end
					if url_flag then url, url_flag = v, false end
					if v == "-a" then la_flag = true end
					if v == "-p" then lp_flag = true end
					if v == "-r" then url_flag = true end
				end
				la = la or "127.0.0.1"
				lp = lp or n + 5053
				tmpfsStatus = tmpfsStatus .. translate("Running") .. ": " .. get_provider_name(url) .. " " .. translate("DoH") .. " " .. translate("at") .. " " .. la .. ":" .. lp .. "\n"
			else
				break
			end
		end
	end
end

m = Map("https-dns-proxy", translate("DNS Over HTTPS Proxy Settings"))

h = m:section(TypedSection, "_dummy", translate("Service Status") .. tmpfsVersion)
h.template = "cbi/nullsection"
ss = h:option(DummyValue, "_dummy", translate("Service Status"))
if tmpfsStatusCode == -1 then
	ss.template = packageName .. "/status"
	ss.value = tmpfsStatus
else
		if tmpfsStatusCode == 0 then
			ss.template = packageName .. "/status"
		else
			ss.template = packageName .. "/status-textarea"
		end
	ss.value = tmpfsStatus
	buttons = h:option(DummyValue, "_dummy")
	buttons.template = packageName .. "/buttons"
end

create_helper_text()
s3 = m:section(TypedSection, "https-dns-proxy", translate("Instances"), translate("When you add/remove any instances below, they will be used to override the 'DNS forwardings' section of ")
		.. [[ <a href="]] .. dispatcher.build_url("admin/network/dhcp") .. [[">]]
		.. translate("DHCP and DNS") .. [[</a>]] .. "." .. helperText)
s3.template = "cbi/tblsection"
s3.sortable  = false
s3.anonymous = true
s3.addremove = true

prov = s3:option(ListValue, "resolver_url", translate("Resolver"))
for filename in fs.dir(providers_dir) do
	local p_func = loadfile(providers_dir .. filename)
	setfenv(p_func, { _ = i18n.translate })
	local p = p_func()
	prov:value(p.resolver_url, p.label)
	if p.default then
		prov.default = p.resolver_url
	end
end
prov.forcewrite = true
prov.write = function(self, section, value)
	if not value then return end
	for filename in fs.dir(providers_dir) do
		local p_func = loadfile(providers_dir .. filename)
		setfenv(p_func, { _ = i18n.translate })
		local p = p_func()
		value = value:gsub('[%p%c%s]', '')
		p.url_match = p.resolver_url:gsub('[%p%c%s]', '')
		if value:match(p.url_match) then
			uci:set(packageName, section, "bootstrap_dns", p.bootstrap_dns)
			uci:set(packageName, section, "resolver_url", p.resolver_url)
		end
	end
	uci:save(packageName)
end

la = s3:option(Value, "listen_addr", translate("Listen address"))
la.datatype    = "host"
la.placeholder = "127.0.0.1"
la.rmempty     = true

local n = 0
uci:foreach(packageName, packageName, function(s)
		if s[".name"] == section then
				return false
		end
		n = n + 1
end)

lp = s3:option(Value, "listen_port", translate("Listen port"))
lp.datatype = "port"
lp.value    = n + 5053

sa = s3:option(Value, "edns_subnet", translate("EDNS client subnet"))
sa.rmempty  = true

ps = s3:option(Value, "proxy_server", translate("Proxy server"))
ps.rmempty  = true

return m