luci-app-ddns: speedup ddns lua 3x display

This commit is contained in:
lean 2020-03-28 14:32:46 +08:00
parent 56fe7aeb5e
commit 8ddb435b15
39 changed files with 16077 additions and 1619 deletions

View File

@ -16,10 +16,10 @@ PKG_VERSION:=2.4.9
# Release == build
# increase on changes of translation files
PKG_RELEASE:=5
PKG_RELEASE:=7
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Christian Schoenebeck <christian.schoenebeck@gmail.com>
PKG_MAINTAINER:=Ansuel Smith <ansuelsmth@gmail.com>
# LuCI specific settings
LUCI_TITLE:=LuCI Support for Dynamic DNS Client (ddns-scripts)

View File

@ -21,15 +21,15 @@ luci_helper = "/usr/lib/ddns/dynamic_dns_lucihelper.sh"
local srv_name = "ddns-scripts"
local srv_ver_min = "2.7.7" -- minimum version of service required
local srv_ver_cmd = luci_helper .. [[ -V | awk {'print $2'}]]
local app_name = "luci-app-ddns"
local app_title = "Dynamic DNS"
local app_version = "2.4.9-1"
local translate = I18N.translate
function index()
local nxfs = require "nixio.fs" -- global definitions not available
local sys = require "luci.sys" -- in function index()
local ddns = require "luci.tools.ddns" -- ddns multiused functions
local muci = require "luci.model.uci"
-- no config create an empty one
@ -61,53 +61,67 @@ end
-- Application specific information functions
function app_description()
return I18N.translate("Dynamic DNS allows that your router can be reached with " ..
"a fixed hostname while having a dynamically changing IP address.")
.. [[<br />]]
.. I18N.translate("OpenWrt Wiki") .. ": "
.. [[<a href="http://wiki.openwrt.org/doc/howto/ddns.client" target="_blank">]]
.. I18N.translate("DDNS Client Documentation") .. [[</a>]]
.. " --- "
.. [[<a href="http://wiki.openwrt.org/doc/uci/ddns" target="_blank">]]
.. I18N.translate("DDNS Client Configuration") .. [[</a>]]
local tmp = {}
tmp[#tmp+1] = translate("Dynamic DNS allows that your router can be reached with \
a fixed hostname while having a dynamically changing IP address.")
tmp[#tmp+1] = [[<br />]]
tmp[#tmp+1] = translate("OpenWrt Wiki") .. ": "
tmp[#tmp+1] = [[<a href="https://openwrt.org/docs/guide-user/services/ddns/client" target="_blank">]]
tmp[#tmp+1] = translate("DDNS Client Documentation")
tmp[#tmp+1] = [[</a>]]
tmp[#tmp+1] = " --- "
tmp[#tmp+1] = [[<a href="https://openwrt.org/docs/guide-user/base-system/ddns" target="_blank">]]
tmp[#tmp+1] = translate("DDNS Client Configuration")
tmp[#tmp+1] = [[</a>]]
return table.concat(tmp)
end
function app_title_back()
return [[<a href="]]
.. DISP.build_url("admin", "services", "ddns")
.. [[">]]
.. I18N.translate(app_title)
.. [[</a>]]
local tmp = {}
tmp[#tmp+1] = [[<a href="]]
tmp[#tmp+1] = DISP.build_url("admin", "services", "ddns")
tmp[#tmp+1] = [[">]]
tmp[#tmp+1] = translate(app_title)
tmp[#tmp+1] = [[</a>]]
return table.concat(tmp)
end
-- Standardized application/service functions
function app_title_main()
return [[<a href="javascript:alert(']]
.. I18N.translate("Version Information")
.. [[\n\n]] .. app_name
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]] .. app_version
.. [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("required") .. [[:]]
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
.. srv_ver_min .. [[ ]] .. I18N.translate("or higher")
.. [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("installed") .. [[:]]
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
.. (service_version() or I18N.translate("NOT installed"))
.. [[\n\n]]
.. [[')">]]
.. I18N.translate(app_title)
.. [[</a>]]
local tmp = {}
tmp[#tmp+1] = [[<a href="javascript:alert(']]
tmp[#tmp+1] = translate("Version Information")
tmp[#tmp+1] = [[\n\n]] .. app_name
tmp[#tmp+1] = [[\n]] .. translate("Version") .. [[: ]] .. app_version
tmp[#tmp+1] = [[\n\n]] .. srv_name .. [[ ]] .. translate("required") .. [[:]]
tmp[#tmp+1] = [[\n]] .. translate("Version") .. [[: ]]
tmp[#tmp+1] = srv_ver_min .. [[ ]] .. translate("or higher")
tmp[#tmp+1] = [[\n\n]] .. srv_name .. [[ ]] .. translate("installed") .. [[:]]
tmp[#tmp+1] = [[\n]] .. translate("Version") .. [[: ]]
tmp[#tmp+1] = (service_version() or translate("NOT installed"))
tmp[#tmp+1] = [[\n\n]]
tmp[#tmp+1] = [[')">]]
tmp[#tmp+1] = translate(app_title)
tmp[#tmp+1] = [[</a>]]
return table.concat(tmp)
end
function service_version()
local ver = nil
local srv_ver_cmd = luci_helper .. " -V | awk {'print $2'} "
local ver
ver = UTIL.exec(srv_ver_cmd)
if #ver > 0 then return ver end
IPKG.list_installed(srv_name, function(n, v, d)
if v and (#v > 0) then ver = v end
end
)
return ver
if IPKG then
ver = IPKG.info(srv_name)[srv_name].Version
else
ver = UTIL.exec(srv_ver_cmd)
end
if ver and #ver > 0 then return ver or nil end
end
function service_ok()
return IPKG.compare_versions((service_version() or "0"), ">=", srv_ver_min)
end
@ -132,6 +146,7 @@ local function _get_status()
local enabled = tonumber(s["enabled"]) or 0
local datelast = "_empty_" -- formatted date of last update
local datenext = "_empty_" -- formatted date of next update
local datenextstat = nil
-- get force seconds
local force_seconds = DDNS.calc_seconds(
@ -165,18 +180,22 @@ local function _get_status()
force_seconds = (force_seconds > uptime) and uptime or force_seconds
if pid > 0 and ( lasttime + force_seconds - uptime ) <= 0 then
datenext = "_verify_"
datenextstat = translate("Verify")
-- run once
elseif force_seconds == 0 then
datenext = "_runonce_"
datenextstat = translate("Run once")
-- no process running and NOT enabled
elseif pid == 0 and enabled == 0 then
datenext = "_disabled_"
datenextstat = translate("Disabled")
-- no process running and enabled
elseif pid == 0 and enabled ~= 0 then
datenext = "_stopped_"
datenextstat = translate("Stopped")
end
-- get/set monitored interface and IP version
@ -187,10 +206,12 @@ local function _get_status()
-- try to get registered IP
local lookup_host = s["lookup_host"] or "_nolookup_"
local chk_sec = DDNS.calc_seconds(
tonumber(s["check_interval"]) or 10,
s["check_unit"] or "minutes" )
local reg_ip = DDNS.get_regip(section, chk_sec)
if reg_ip == "NOFILE" then
local dnsserver = s["dns_server"] or ""
local force_ipversion = tonumber(s["force_ipversion"] or 0)
@ -207,9 +228,6 @@ local function _get_status()
command = command .. [[ -- get_registered_ip]]
reg_ip = SYS.exec(command)
end
if reg_ip == "" then
reg_ip = "_nodata_"
end
-- fill transfer array
data[#data+1] = {
@ -220,7 +238,8 @@ local function _get_status()
reg_ip = reg_ip,
pid = pid,
datelast = datelast,
datenext = datenext
datenext = datenext,
datenextstat = datenextstat
}
end)

View File

@ -90,7 +90,7 @@ end
-- will use dynamic_dns_lucihelper to check if
-- local IP can be read
local function _verify_ip_source()
-- section is globally defined here be calling agrument (see above)
-- section is globally defined here be calling argument (see above)
local _arg
local _ipv6 = usev6:formvalue(section)
@ -172,8 +172,8 @@ local function _option_used(option, urlscript)
end
-- function to verify if option is valid
local function _option_validate(self, value)
-- section is globally defined here be calling agrument (see above)
local function _option_validate(self, value, optional)
-- section is globally defined here be calling argument (see above)
local fusev6 = usev6:formvalue(section) or "0"
local fsvc4 = svc4:formvalue(section) or "-"
local fsvc6 = svc6:formvalue(section) or "-"
@ -200,10 +200,11 @@ local function _option_validate(self, value)
if (#urlsh == 0) then return "" end
used = _option_used(self.option, urlsh)
-- on error or not used return empty sting
-- on error or not used return empty string
if used < 1 then return "" end
-- needed but no data then return error
if not value or (#value == 0) then
if optional then return nil end
return nil, err_tab_basic(self) .. translate("missing / required")
end
return value
@ -292,6 +293,10 @@ function luh.parse(self, section, novld)
end
-- use_ipv6 -- ################################################################
--We call it globally as it's called 11 times even outside specific function, saves 11 os.execute slow command!
local has_ipv6 = DDNS.env_info("has_ipv6")
usev6 = ns:taboption("basic", ListValue, "use_ipv6",
translate("IP address version"),
translate("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider") )
@ -300,16 +305,16 @@ usev6.default = "0"
usev6:value("0", translate("IPv4-Address") )
function usev6.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section) or "0"
if DDNS.has_ipv6 or (value == "1" and not DDNS.has_ipv6) then
if has_ipv6 or (value == "1" and not has_ipv6) then
self:value("1", translate("IPv6-Address") )
end
if value == "1" and not DDNS.has_ipv6 then
if value == "1" and not has_ipv6 then
self.description = err_ipv6_basic
end
return value
end
function usev6.validate(self, value)
if (value == "1" and DDNS.has_ipv6) or value == "0" then
if (value == "1" and has_ipv6) or value == "0" then
return value
end
return nil, err_tab_basic(self) .. err_ipv6_plain
@ -360,7 +365,7 @@ svc6 = ns:taboption("basic", ListValue, "ipv6_service_name",
translate("DDNS Service provider") .. " [IPv6]" )
svc6.default = "-"
svc6:depends("use_ipv6", "1") -- only show on IPv6
if not DDNS.has_ipv6 then
if not has_ipv6 then
svc6.description = err_ipv6_basic
end
function svc6.cfgvalue(self, section)
@ -374,7 +379,7 @@ function svc6.cfgvalue(self, section)
end
function svc6.validate(self, value)
if usev6:formvalue(section) == "1" then -- do only on IPv6
if DDNS.has_ipv6 then return value end
if has_ipv6 then return value end
return nil, err_tab_basic(self) .. err_ipv6_plain
else
return "" -- suppress validate error
@ -509,18 +514,18 @@ pe = ns:taboption("basic", Value, "param_enc",
translate("Optional Encoded Parameter"),
translate("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)") )
function pe.validate(self, value)
return _option_validate(self, value)
return _option_validate(self, value, true)
end
function pe.parse(self, section, novld)
DDNS.value_parse(self, section, novld)
end
-- IPv4/IPv6 - param_enc -- ###################################################
-- IPv4/IPv6 - param_opt -- ###################################################
po = ns:taboption("basic", Value, "param_opt",
translate("Optional Parameter"),
translate("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)") )
function po.validate(self, value)
return _option_validate(self, value)
return _option_validate(self, value, true)
end
function po.parse(self, section, novld)
DDNS.value_parse(self, section, novld)
@ -586,13 +591,17 @@ end
svc6:value("-", translate("-- custom --") )
-- IPv4/IPv6 - use_https -- ###################################################
if DDNS.has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
--We call it globally as it's called 4 times outside specific function.
local has_ssl = DDNS.env_info("has_ssl")
if has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
https = ns:taboption("basic", Flag, "use_https",
translate("Use HTTP Secure") )
https.orientation = "horizontal"
function https.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_ssl and value == "1" then
if not has_ssl and value == "1" then
self.description = bold_on .. font_red ..
translate("HTTPS not supported") .. font_off .. "<br />" ..
translate("please disable") .. " !" .. bold_off
@ -602,7 +611,7 @@ if DDNS.has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
return value
end
function https.validate(self, value)
if (value == "1" and DDNS.has_ssl ) or value == "0" then return value end
if (value == "1" and has_ssl ) or value == "0" then return value end
return nil, err_tab_basic(self) .. translate("HTTPS not supported") .. " !"
end
function https.write(self, section, value)
@ -616,7 +625,7 @@ if DDNS.has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
end
-- IPv4/IPv6 - cacert -- ######################################################
if DDNS.has_ssl then
if has_ssl then
cert = ns:taboption("basic", Value, "cacert",
translate("Path to CA-Certificate"),
translate("directory or path/file") .. "<br />" ..
@ -706,7 +715,7 @@ src6:value("network", translate("Network"))
src6:value("web", translate("URL"))
src6:value("interface", translate("Interface"))
src6:value("script", translate("Script"))
if not DDNS.has_ipv6 then
if not has_ipv6 then
src6.description = err_ipv6_other
end
function src6.cfgvalue(self, section)
@ -715,7 +724,7 @@ end
function src6.validate(self, value)
if usev6:formvalue(section) ~= "1" then
return "" -- ignore on IPv4 selected
elseif not DDNS.has_ipv6 then
elseif not has_ipv6 then
return nil, err_tab_adv(self) .. err_ipv6_plain
elseif not _verify_ip_source() then
return nil, err_tab_adv(self) ..
@ -794,7 +803,7 @@ ipn6 = ns:taboption("advanced", ListValue, "ipv6_network",
ipn6:depends("ipv6_source", "network")
ipn6.default = "wan6"
WADM.cbi_add_networks(ipn6)
if DDNS.has_ipv6 then
if has_ipv6 then
ipn6.description = translate("Defines the network to read systems IPv6-Address from")
else
ipn6.description = err_ipv6_other
@ -808,7 +817,7 @@ function ipn6.validate(self, value)
-- ignore if IPv4 selected OR
-- ignore everything except "network"
return ""
elseif DDNS.has_ipv6 then
elseif has_ipv6 then
return value
else
return nil, err_tab_adv(self) .. err_ipv6_plain
@ -881,7 +890,7 @@ iurl6 = ns:taboption("advanced", Value, "ipv6_url",
translate("URL to detect") .. " [IPv6]" )
iurl6:depends("ipv6_source", "web")
iurl6.default = "http://checkipv6.dyndns.com"
if DDNS.has_ipv6 then
if has_ipv6 then
iurl6.description = translate("Defines the Web page to read systems IPv6-Address from")
else
iurl6.description = err_ipv6_other
@ -895,7 +904,7 @@ function iurl6.validate(self, value)
-- ignore if IPv4 selected OR
-- ignore everything except "web"
return ""
elseif not DDNS.has_ipv6 then
elseif not has_ipv6 then
return nil, err_tab_adv(self) .. err_ipv6_plain
elseif not value or #value == 0 then
return nil, err_tab_adv(self) .. translate("missing / required")
@ -1051,7 +1060,7 @@ eif6:depends("ipv6_source", "web")
eif6:depends("ipv6_source", "script")
eif6.default = "wan6"
WADM.cbi_add_networks(eif6)
if not DDNS.has_ipv6 then
if not has_ipv6 then
eif6.description = err_ipv6_other
else
eif6.description = translate("Network on which the ddns-updater scripts will be started")
@ -1065,7 +1074,7 @@ function eif6.validate(self, value)
or fsrc6 == "network"
or fsrc6 == "interface" then
return "" -- ignore IPv4, network, interface
elseif not DDNS.has_ipv6 then
elseif not has_ipv6 then
return nil, err_tab_adv(self) .. err_ipv6_plain
else
return value
@ -1084,10 +1093,13 @@ function eif6.write(self, section, value)
end
function eif6.parse(self, section, novld)
DDNS.value_parse(self, section, novld)
end
end
-- IPv4/IPv6 - bind_network -- ################################################
if DDNS.has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
local has_bindnet = DDNS.env_info("has_bindnet")
if has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
bnet = ns:taboption("advanced", ListValue, "bind_network",
translate("Bind Network") )
bnet:depends("ipv4_source", "web")
@ -1097,7 +1109,7 @@ if DDNS.has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
WADM.cbi_add_networks(bnet)
function bnet.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_bindnet and value ~= "" then
if not has_bindnet and value ~= "" then
self.description = bold_on .. font_red ..
translate("Binding to a specific network not supported") .. font_off .. "<br />" ..
translate("please set to 'default'") .. " !" .. bold_off
@ -1108,7 +1120,7 @@ if DDNS.has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
return value
end
function bnet.validate(self, value)
if ( (value ~= "") and DDNS.has_bindnet ) or (value == "") then return value end
if ( (value ~= "") and has_bindnet ) or (value == "") then return value end
return nil, err_tab_adv(self) .. translate("Binding to a specific network not supported") .. " !"
end
function bnet.parse(self, section, novld)
@ -1119,13 +1131,16 @@ end
-- IPv4 + IPv6 - force_ipversion -- ###########################################
-- optional to force wget/curl and host to use only selected IP version
-- command parameter "-4" or "-6"
if DDNS.has_forceip or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then
local has_forceip = DDNS.env_info("has_forceip")
if has_forceip or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then
fipv = ns:taboption("advanced", Flag, "force_ipversion",
translate("Force IP Version") )
fipv.orientation = "horizontal"
function fipv.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_forceip and value ~= "0" then
if not has_forceip and value ~= "0" then
self.description = bold_on .. font_red ..
translate("Force IP Version not supported") .. font_off .. "<br />" ..
translate("please disable") .. " !" .. bold_off
@ -1135,14 +1150,17 @@ if DDNS.has_forceip or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) t
return value
end
function fipv.validate(self, value)
if (value == "1" and DDNS.has_forceip) or value == "0" then return value end
if (value == "1" and has_forceip) or value == "0" then return value end
return nil, err_tab_adv(self) .. translate("Force IP Version not supported")
end
end
-- IPv4 + IPv6 - dns_server -- ################################################
-- optional DNS Server to use resolving my IP
if DDNS.has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
local has_dnsserver = DDNS.env_info("has_dnsserver")
if has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
dns = ns:taboption("advanced", Value, "dns_server",
translate("DNS-Server"),
translate("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") .. "<br />" ..
@ -1152,7 +1170,7 @@ if DDNS.has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
-- if .datatype is set, then it is checked before calling this function
if not value or (#value == 0) then
return "" -- ignore on empty
elseif not DDNS.has_dnsserver then
elseif not has_dnsserver then
return nil, err_tab_adv(self) .. translate("Specifying a DNS-Server is not supported")
elseif not DTYP.host(value) then
return nil, err_tab_adv(self) .. translate("use hostname, FQDN, IPv4- or IPv6-Address")
@ -1179,13 +1197,16 @@ if DDNS.has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
end
-- IPv4 + IPv6 - force_dnstcp -- ##############################################
if DDNS.has_bindhost or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) then
local has_bindhost = DDNS.env_info("has_bindhost")
if has_bindhost or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) then
tcp = ns:taboption("advanced", Flag, "force_dnstcp",
translate("Force TCP on DNS") )
tcp.orientation = "horizontal"
function tcp.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_bindhost and value ~= "0" then
if not has_bindhost and value ~= "0" then
self.description = bold_on .. font_red ..
translate("DNS requests via TCP not supported") .. font_off .. "<br />" ..
translate("please disable") .. " !" .. bold_off
@ -1195,7 +1216,7 @@ if DDNS.has_bindhost or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) the
return value
end
function tcp.validate(self, value)
if (value == "1" and DDNS.has_bindhost ) or value == "0" then
if (value == "1" and has_bindhost ) or value == "0" then
return value
end
return nil, err_tab_adv(self) .. translate("DNS requests via TCP not supported")
@ -1204,13 +1225,16 @@ end
-- IPv4 + IPv6 - proxy -- #####################################################
-- optional Proxy to use for http/https requests [user:password@]proxyhost[:port]
if DDNS.has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
local has_proxy = DDNS.env_info("has_proxy")
if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
pxy = ns:taboption("advanced", Value, "proxy",
translate("PROXY-Server") )
pxy.placeholder="user:password@myproxy.lan:8080"
function pxy.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_proxy and value ~= "" then
if not has_proxy and value ~= "" then
self.description = bold_on .. font_red ..
translate("PROXY-Server not supported") .. font_off .. "<br />" ..
translate("please remove entry") .. "!" .. bold_off
@ -1226,7 +1250,7 @@ if DDNS.has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
-- if .datatype is set, then it is checked before calling this function
if not value or (#value == 0) then
return "" -- ignore on empty
elseif DDNS.has_proxy then
elseif has_proxy then
local ipv6 = usev6:formvalue(section) or "0"
local force = fipv:formvalue(section) or "0"
local command = CTRL.luci_helper .. [[ -]]

View File

@ -28,7 +28,7 @@ local ns = m:section( NamedSection, "global", "ddns",
.. [[<br /><strong>]]
.. translate("It is NOT recommended for casual users to change settings on this page.")
.. [[</strong><br />]]
.. [[<a href="http://wiki.openwrt.org/doc/uci/ddns#version_2x1" target="_blank">]]
.. [[<a href="https://openwrt.org/docs/guide-user/base-system/ddns#section_ddns" target="_blank">]]
.. translate("For detailed information about parameter settings look here.")
.. [[</a>]]
)

View File

@ -27,7 +27,7 @@ s = m:section( SimpleSection,
-- ddns-scripts needs to be updated for full functionality
if not CTRL.service_ok() then
local so = s:option(DummyValue, "_update_needed")
so.titleref = DISP.build_url("admin", "system", "packages")
so.titleref = DISP.build_url("admin", "system", "opkg")
so.rawhtml = true
so.title = font_red .. bold_on ..
translate("Software update required") .. bold_off .. font_off
@ -48,7 +48,7 @@ if not SYS.init.enabled("ddns") then
end
-- No IPv6 support
if not DDNS.has_ipv6 then
if not DDNS.env_info("has_ipv6") then
local v6 = s:option(DummyValue, "_no_ipv6")
v6.titleref = 'http://www.openwrt.org" target="_blank'
v6.rawhtml = true
@ -60,9 +60,9 @@ if not DDNS.has_ipv6 then
end
-- No HTTPS support
if not DDNS.has_ssl then
if not DDNS.env_info("has_ssl") then
local sl = s:option(DummyValue, "_no_https")
sl.titleref = DISP.build_url("admin", "system", "packages")
sl.titleref = DISP.build_url("admin", "system", "opkg")
sl.rawhtml = true
sl.title = bold_on ..
translate("HTTPS not supported") .. bold_off
@ -74,9 +74,9 @@ if not DDNS.has_ssl then
end
-- No bind_network
if not DDNS.has_bindnet then
if not DDNS.env_info("has_bindnet") then
local bn = s:option(DummyValue, "_no_bind_network")
bn.titleref = DISP.build_url("admin", "system", "packages")
bn.titleref = DISP.build_url("admin", "system", "opkg")
bn.rawhtml = true
bn.title = bold_on ..
translate("Binding to a specific network not supported") .. bold_off
@ -90,9 +90,9 @@ if not DDNS.has_bindnet then
end
-- currently only cURL possibly without proxy support
if not DDNS.has_proxy then
if not DDNS.env_info("has_proxy") then
local px = s:option(DummyValue, "_no_proxy")
px.titleref = DISP.build_url("admin", "system", "packages")
px.titleref = DISP.build_url("admin", "system", "opkg")
px.rawhtml = true
px.title = bold_on ..
translate("cURL without Proxy Support") .. bold_off
@ -104,19 +104,19 @@ if not DDNS.has_proxy then
end
-- "Force IP Version not supported"
if not DDNS.has_forceip then
if not DDNS.env_info("has_forceip") then
local fi = s:option(DummyValue, "_no_force_ip")
fi.titleref = DISP.build_url("admin", "system", "packages")
fi.titleref = DISP.build_url("admin", "system", "opkg")
fi.rawhtml = true
fi.title = bold_on ..
translate("Force IP Version not supported") .. bold_off
local value = translate("BusyBox's nslookup and Wget do not support to specify " ..
"the IP version to use for communication with DDNS Provider!")
if not (DDNS.has_wgetssl or DDNS.has_curl or DDNS.has_fetch) then
if not (DDNS.env_info("has_wgetssl") or DDNS.env_info("has_curl") or DDNS.env_info("has_fetch")) then
value = value .. "<br />- " ..
translate("You should install 'wget' or 'curl' or 'uclient-fetch' package.")
end
if not DDNS.has_bindhost then
if not DDNS.env_info("has_bindhost") then
value = value .. "<br />- " ..
translate("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.")
end
@ -124,9 +124,9 @@ if not DDNS.has_forceip then
end
-- "DNS requests via TCP not supported"
if not DDNS.has_bindhost then
if not DDNS.env_info("has_bindhost") then
local dt = s:option(DummyValue, "_no_dnstcp")
dt.titleref = DISP.build_url("admin", "system", "packages")
dt.titleref = DISP.build_url("admin", "system", "opkg")
dt.rawhtml = true
dt.title = bold_on ..
translate("DNS requests via TCP not supported") .. bold_off
@ -137,9 +137,9 @@ if not DDNS.has_bindhost then
end
-- nslookup compiled with musl produce problems when using
if not DDNS.has_dnsserver then
if not DDNS.env_info("has_dnsserver") then
local ds = s:option(DummyValue, "_no_dnsserver")
ds.titleref = DISP.build_url("admin", "system", "packages")
ds.titleref = DISP.build_url("admin", "system", "opkg")
ds.rawhtml = true
ds.title = bold_on ..
translate("Using specific DNS Server not supported") .. bold_off
@ -151,9 +151,9 @@ if not DDNS.has_dnsserver then
end
-- certificates installed
if DDNS.has_ssl and not DDNS.has_cacerts then
if DDNS.env_info("has_ssl") and not DDNS.env_info("has_cacerts") then
local ca = s:option(DummyValue, "_no_certs")
ca.titleref = DISP.build_url("admin", "system", "packages")
ca.titleref = DISP.build_url("admin", "system", "opkg")
ca.rawhtml = true
ca.title = bold_on ..
translate("No certificates found") .. bold_off

View File

@ -1,21 +1,20 @@
-- Copyright 2014-2018 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
-- Licensed to the public under the Apache License 2.0.
local NXFS = require "nixio.fs"
local DISP = require "luci.dispatcher"
local HTTP = require "luci.http"
local SYS = require "luci.sys"
local CTRL = require "luci.controller.ddns" -- this application's controller
local DDNS = require "luci.tools.ddns" -- ddns multiused functions
local show_hints = not (DDNS.has_ipv6 -- IPv6 support
and DDNS.has_ssl -- HTTPS support
and DDNS.has_proxy -- Proxy support
and DDNS.has_bindhost -- DNS TCP support
and DDNS.has_forceip -- Force IP version
and DDNS.has_dnsserver -- DNS server support
and DDNS.has_bindnet -- Bind to network/interface
and DDNS.has_cacerts -- certificates installed at /etc/ssl/certs
local show_hints = not (DDNS.env_info("has_ipv6") -- IPv6 support
and DDNS.env_info("has_ssl") -- HTTPS support
and DDNS.env_info("has_proxy") -- Proxy support
and DDNS.env_info("has_bindhost") -- DNS TCP support
and DDNS.env_info("has_forceip") -- Force IP version
and DDNS.env_info("has_dnsserver") -- DNS server support
and DDNS.env_info("has_bindnet") -- Bind to network/interface
and DDNS.env_info("has_cacerts") -- certificates installed at /etc/ssl/certs
)
local not_enabled = not SYS.init.enabled("ddns")
local need_update = not CTRL.service_ok()
@ -123,7 +122,7 @@ function dom.set_one(self, section)
end
function dom.set_two(self, section)
local chk_sec = DDNS.calc_seconds(
tonumber(self.map:get(section, "check_interval") or "") or 10,
tonumber(self.map:get(section, "check_interval")) or 10,
self.map:get(section, "check_unit") or "minutes" )
local ip = DDNS.get_regip(section, chk_sec)
if ip == "NOFILE" then

View File

@ -5,37 +5,134 @@ module("luci.tools.ddns", package.seeall)
local NX = require "nixio"
local NXFS = require "nixio.fs"
local OPKG = require "luci.model.ipkg"
local UCI = require "luci.model.uci"
local SYS = require "luci.sys"
local UTIL = require "luci.util"
local function _check_certs()
local _, v = NXFS.glob("/etc/ssl/certs/*.crt")
if ( v == 0 ) then _, v = NXFS.glob("/etc/ssl/certs/*.pem") end
return (v > 0)
function env_info(type)
if ( type == "has_ssl" ) or ( type == "has_proxy" ) or ( type == "has_forceip" )
or ( type == "has_bindnet" ) or ( type == "has_fetch" )
or ( type == "has_wgetssl" ) or ( type == "has_curl" )
or ( type == "has_curlssl" ) or ( type == "has_curlpxy" )
or ( type == "has_fetchssl" ) or ( type == "has_bbwget" ) then
local function has_wgetssl()
return (SYS.call( [[which wget-ssl >/dev/null 2>&1]] ) == 0) -- and true or nil
end
local function has_curlssl()
return (SYS.call( [[$(which curl) -V 2>&1 | grep -qF "https"]] ) == 0)
end
local function has_fetch()
return (SYS.call( [[which uclient-fetch >/dev/null 2>&1]] ) == 0)
end
local function has_fetchssl()
return NXFS.access("/lib/libustream-ssl.so")
end
local function has_curl()
return (SYS.call( [[which curl >/dev/null 2>&1]] ) == 0)
end
local function has_curlpxy()
return (SYS.call( [[grep -i "all_proxy" /usr/lib/libcurl.so* >/dev/null 2>&1]] ) == 0)
end
local function has_bbwget()
return (SYS.call( [[$(which wget) -V 2>&1 | grep -iqF "busybox"]] ) == 0)
end
if type == "has_wgetssl" then
return has_wgetssl()
elseif type == "has_curl" then
return has_curl()
elseif type == "has_curlssl" then
return has_curlssl()
elseif type == "has_curlpxy" then
return has_curlpxy()
elseif type == "has_fetch" then
return has_fetch()
elseif type == "has_fetchssl" then
return has_fetchssl()
elseif type == "has_bbwget" then
return has_bbwget()
elseif type == "has_ssl" then
if has_wgetssl() then return true end
if has_curlssl() then return true end
if (has_fetch() and has_fetchssl()) then return true end
return false
elseif type == "has_proxy" then
if has_wgetssl() then return true end
if has_curlpxy() then return true end
if has_fetch() then return true end
if has_bbwget() then return true end
return false
elseif type == "has_forceip" then
if has_wgetssl() then return true end
if has_curl() then return true end
if has_fetch() then return true end -- only really needed for transfer
return false
elseif type == "has_bindnet" then
if has_curl() then return true end
if has_wgetssl() then return true end
return false
end
elseif ( type == "has_dnsserver" ) or ( type == "has_bindhost" ) or ( type == "has_hostip" ) or ( type == "has_nslookup" ) then
local function has_bindhost()
if (SYS.call( [[which host >/dev/null 2>&1]] ) == 0) then return true end
if (SYS.call( [[which khost >/dev/null 2>&1]] ) == 0) then return true end
if (SYS.call( [[which drill >/dev/null 2>&1]] ) == 0) then return true end
return false
end
local function has_hostip()
return (SYS.call( [[which hostip >/dev/null 2>&1]] ) == 0)
end
local function has_nslookup()
return (SYS.call( [[which nslookup >/dev/null 2>&1]] ) == 0)
end
if type == "has_bindhost" then
return has_bindhost()
elseif type == "has_hostip" then
return has_hostip()
elseif type == "has_nslookup" then
return has_nslookup()
elseif type == "has_dnsserver" then
if has_bindhost() then return true end
if has_hostip() then return true end
if has_nslookup() then return true end
return false
end
elseif type == "has_ipv6" then
return (NXFS.access("/proc/net/ipv6_route") and NXFS.access("/usr/sbin/ip6tables"))
elseif type == "has_cacerts" then
--old _check_certs() local function
local _, v = NXFS.glob("/etc/ssl/certs/*.crt")
if ( v == 0 ) then _, v = NXFS.glob("/etc/ssl/certs/*.pem") end
return (v > 0)
else
return
end
end
has_wgetssl = (SYS.call( [[which wget-ssl >/dev/null 2>&1]] ) == 0) -- and true or nil
has_curl = (SYS.call( [[which curl >/dev/null 2>&1]] ) == 0)
has_curlssl = (SYS.call( [[$(which curl) -V 2>&1 | grep "Protocols:" | grep -qF "https"]] ) ~= 0)
has_curlpxy = (SYS.call( [[grep -i "all_proxy" /usr/lib/libcurl.so* >/dev/null 2>&1]] ) == 0)
has_fetch = (SYS.call( [[which uclient-fetch >/dev/null 2>&1]] ) == 0)
has_fetchssl = NXFS.access("/lib/libustream-ssl.so")
has_bbwget = (SYS.call( [[$(which wget) -V 2>&1 | grep -iqF "busybox"]] ) == 0)
has_bindhost = (SYS.call( [[which host >/dev/null 2>&1]] ) == 0)
or (SYS.call( [[which khost >/dev/null 2>&1]] ) == 0)
or (SYS.call( [[which drill >/dev/null 2>&1]] ) == 0)
has_hostip = (SYS.call( [[which hostip >/dev/null 2>&1]] ) == 0)
has_nslookup = (SYS.call( [[$(which nslookup) localhost 2>&1 | grep -qF "(null)"]] ) ~= 0)
has_ipv6 = (NXFS.access("/proc/net/ipv6_route") and NXFS.access("/usr/sbin/ip6tables"))
has_ssl = (has_wgetssl or has_curlssl or (has_fetch and has_fetchssl))
has_proxy = (has_wgetssl or has_curlpxy or has_fetch or has_bbwget)
has_forceip = (has_wgetssl or has_curl or has_fetch) -- only really needed for transfer
has_dnsserver = (has_bindhost or has_hostip or has_nslookup)
has_bindnet = (has_wgetssl or has_curl)
has_cacerts = _check_certs()
-- function to calculate seconds from given interval and unit
function calc_seconds(interval, unit)
if not tonumber(interval) then

View File

@ -14,7 +14,7 @@
// called by XHR.poll and onclick_startstop
function _data2elements(data) {
// Service sections
for( i = 1; i < data.length; i++ )
for( var i = 1; i < data.length; i++ )
{
var section = data[i].section // Section to handle
var cbx = document.getElementById("cbid.ddns." + section + ".enabled"); // Enabled
@ -141,7 +141,7 @@
if (x.responseText == "_uncommitted_") {
// we need a trick to display Ampersand "&" in stead of "&#38;" or "&amp;"
// after translation
txt="<%:Please [Save & Apply] your changes first%>";
var txt="<%:Please [Save & Apply] your changes first%>";
alert( txt.replace(new RegExp("<%:&%>", "g"), "&") );
} else {
// should have data because status changed
@ -164,7 +164,7 @@
// define only ONE XHR.poll in a page because if one is running it blocks the other one
// optimum is to define on Map or Section Level from here you can reach all elements
// we need update every 15 seconds only
XHR.poll(5, '<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
XHR.poll(-1, '<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
function(x, data) {
if (data) { _data2elements(data); }
}

View File

@ -1,144 +1,60 @@
<!-- ++ BEGIN ++ Dynamic DNS ++ system_status.htm ++ -->
<script type="text/javascript">//<![CDATA[
// helper to move status data to the relevant
// screen objects
// called by XHR.poll and XHR.get
function _data2elements(x, data) {
var tbl = document.getElementById('ddns_status_table');
// security check
if ( !(tbl) ) { return; }
// clear all rows
while (tbl.rows.length > 1)
tbl.deleteRow(1);
// variable for Modulo-Division use to set cbi-rowstyle-? (0 or 1)
var i = -1;
var j = 1;
// DDNS Service disabled
if (data[0].enabled == 0) {
var txt = '<strong><font color="red"><%:DDNS Autostart disabled%></font>' ;
var url = '<a href="' + data[0].url_up + '"><%:enable here%></a></strong>' ;
var tr = tbl.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((j + i) % 2) + 1);
var td = tr.insertCell(-1);
td.colSpan = 2 ;
td.innerHTML = txt + " - " + url
tr.insertCell(-1).colSpan = 3 ;
i++ ;
}
for( j = 1; j < data.length; j++ )
{
var tr = tbl.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((j + i) % 2) + 1) ;
// configuration
tr.insertCell(-1).innerHTML = '<strong>' + data[j].section + '</strong>' ;
// pid
// data[j].pid ignored here
// last update
// data[j].datelast ignored here
// next update
switch (data[j].datenext) {
case "_empty_":
tr.insertCell(-1).innerHTML = '<em><%:Unknown error%></em>' ;
break;
case "_stopped_":
tr.insertCell(-1).innerHTML = '<em><%:Stopped%></em>' ;
break;
case "_disabled_":
tr.insertCell(-1).innerHTML = '<em><%:Disabled%></em>' ;
break;
case "_noupdate_":
tr.insertCell(-1).innerHTML = '<em><%:Update error%></em>' ;
break;
case "_runonce_":
tr.insertCell(-1).innerHTML = '<em><%:Run once%></em>' ;
break;
case "_verify_":
tr.insertCell(-1).innerHTML = '<em><%:Verify%></em>';
break;
default:
tr.insertCell(-1).innerHTML = data[j].datenext ;
break;
}
// lookup
if (data[j].lookup == "_nolookup_")
tr.insertCell(-1).innerHTML = '<em><%:config error%></em>';
else
tr.insertCell(-1).innerHTML = data[j].lookup;
// registered IP
switch (data[j].reg_ip) {
case "_nolookup_":
tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>';
break;
case "_nodata_":
tr.insertCell(-1).innerHTML = '<em><%:No data%></em>';
break;
case "_noipv6_":
tr.insertCell(-1).innerHTML = '<em><%:IPv6 not supported%></em>';
break;
default:
tr.insertCell(-1).innerHTML = data[j].reg_ip;
break;
}
// monitored interface
if (data[j].iface == "_nonet_")
tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>';
else
tr.insertCell(-1).innerHTML = data[j].iface;
}
if (tbl.rows.length == 1 || (data[0].enabled == 0 && tbl.rows.length == 2) ) {
var br = '<br />';
if (tbl.rows.length > 1)
br = '';
var tr = tbl.insertRow(-1);
tr.className = "cbi-section-table-row";
var td = tr.insertCell(-1);
td.colSpan = 5;
td.innerHTML = '<em>' + br + '<%:There is no service configured.%></em>' ;
}
}
// force to immediate show status (not waiting for XHR.poll)
XHR.get('<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
//start polling data every 30 second, this doesn't change so much
XHR.poll(30, '<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
function(x, data) {
if (data) { _data2elements(x, data); }
if (data) {
var tbl = document.getElementById('ddns_status_table');
// security check
if ( !(tbl) ) { return; }
var rows = [];
// DDNS Service disabled
if (data[0].enabled == 0) {
var ddns_legend = document.getElementById('ddns_status_legend');
ddns_legend.style.display='none';
rows.push([
'<strong><font color="red"><%:DDNS Autostart disabled%></font>',
'<a class="cbi-button cbi-button-action important" type="button" href="' + data[0].url_up + '"><%:enable here%></a></strong>'
]);
} else {
for(var j = 1; j < data.length; j++ )
{
rows.push([
'<strong>' + data[j].section + '</strong>', //configuration
data[j].datenextstat ? '<em>'+data[j].datenextstat+'</em>' : '<em>'+data[j].datenext+'</em>',
data[j].lookup ? data[j].lookup : '<em><%:config error%></em>',
data[j].reg_ip ? data[j].reg_ip : '<em><%:No data%></em>',
data[j].iface // monitored interface
]);
}
}
cbi_update_table(tbl, rows, '<%:There is no service configured.%>');
}
}
);
XHR.poll(15, '<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
function(x, data) {
if (data) { _data2elements(x, data); }
}
);
//]]></script>
<fieldset class="cbi-section" id="ddns_status_section">
<legend><a href="<%=url([[admin]], [[services]], [[ddns]])%>"><%:Dynamic DNS%></a></legend>
<table class="cbi-section-table" id="ddns_status_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Configuration%></th>
<th class="cbi-section-table-cell"><%:Next Update%></th>
<th class="cbi-section-table-cell"><%:Lookup Hostname%></th>
<th class="cbi-section-table-cell"><%:Registered IP%></th>
<th class="cbi-section-table-cell"><%:Network%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="5"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
<div class="cbi-section-node">
<div class="table" id="ddns_status_table">
<div class="tr table-titles" id="ddns_status_legend">
<div class="th"><%:Configuration%></div>
<div class="th"><%:Next Update%></div>
<div class="th"><%:Lookup Hostname%></div>
<div class="th"><%:Registered IP%></div>
<div class="th"><%:Network%></div>
</div>
<div class="tr">
<div class="td"><em><br /><%:Collecting data...%></em></div>
</div>
</div>
</div>
</fieldset>
<!-- ++ END ++ Dynamic DNS ++ system_status.htm ++ -->

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff