summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--applications/luci-app-ddns/luasrc/controller/ddns.lua95
-rw-r--r--applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua644
-rw-r--r--applications/luci-app-ddns/luasrc/model/cbi/ddns/global.lua65
-rw-r--r--applications/luci-app-ddns/luasrc/model/cbi/ddns/hints.lua18
-rw-r--r--applications/luci-app-ddns/luasrc/model/cbi/ddns/overview.lua43
-rw-r--r--applications/luci-app-ddns/luasrc/tools/ddns.lua137
-rw-r--r--applications/luci-app-ddns/luasrc/view/ddns/detail_logview.htm2
-rw-r--r--applications/luci-app-ddns/luasrc/view/ddns/overview_status.htm14
-rw-r--r--applications/luci-app-ddns/luasrc/view/ddns/system_status.htm14
-rw-r--r--applications/luci-app-ddns/po/de/ddns.po62
-rw-r--r--applications/luci-app-ddns/po/templates/ddns.pot44
-rw-r--r--applications/luci-app-privoxy/Makefile4
-rw-r--r--applications/luci-app-privoxy/luasrc/model/cbi/privoxy.lua3
-rw-r--r--applications/luci-app-qos/luasrc/model/cbi/qos/qos.lua10
-rw-r--r--applications/luci-app-radicale/Makefile2
-rw-r--r--applications/luci-app-radicale/luasrc/controller/radicale.lua6
-rwxr-xr-xcontrib/package/freifunk-common/files/usr/bin/neigh.sh65
l---------contrib/package/freifunk-policyrouting/files/etc/rc.d/S15-freifunk-policyrouting1
-rw-r--r--documentation/api/modules/luci.model.uci.html8
-rw-r--r--modules/luci-base/Makefile2
-rw-r--r--modules/luci-base/luasrc/http.lua1
-rw-r--r--modules/luci-base/luasrc/model/network.lua305
-rw-r--r--modules/luci-base/luasrc/model/uci.luadoc8
-rw-r--r--modules/luci-base/luasrc/util.lua53
-rw-r--r--modules/luci-mod-admin-full/luasrc/controller/admin/network.lua22
-rw-r--r--modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/iface_add.lua7
-rw-r--r--modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua6
-rw-r--r--modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua3
-rw-r--r--modules/luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab/mount.lua2
-rw-r--r--modules/luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm14
-rw-r--r--modules/luci-mod-admin-full/luasrc/view/admin_network/iface_status.htm12
31 files changed, 1050 insertions, 622 deletions
diff --git a/applications/luci-app-ddns/luasrc/controller/ddns.lua b/applications/luci-app-ddns/luasrc/controller/ddns.lua
index 4fbd3c3fcf..29598ea8ad 100644
--- a/applications/luci-app-ddns/luasrc/controller/ddns.lua
+++ b/applications/luci-app-ddns/luasrc/controller/ddns.lua
@@ -10,28 +10,43 @@ local NX = require "nixio"
local NXFS = require "nixio.fs"
local DISP = require "luci.dispatcher"
local HTTP = require "luci.http"
-local UCI = require "luci.model.uci"
+local I18N = require "luci.i18n" -- not globally avalible here
+local IPKG = require "luci.model.ipkg"
local SYS = require "luci.sys"
-local DDNS = require "luci.tools.ddns" -- ddns multiused functions
+local UCI = require "luci.model.uci"
local UTIL = require "luci.util"
+local DDNS = require "luci.tools.ddns" -- ddns multiused functions
-DDNS_MIN = "2.4.2-1" -- minimum version of service required
+local srv_name = "ddns-scripts"
+local srv_ver_min = "2.5.0" -- minimum version of service required
+local srv_ver_cmd = [[/usr/lib/ddns/dynamic_dns_updater.sh --version | awk {'print $2'}]]
+local app_name = "luci-app-ddns"
+local app_title = "Dynamic DNS"
+local app_version = "2.3.0-1"
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 verinst = ddns.ipkg_ver_installed("ddns-scripts")
- local verok = ddns.ipkg_ver_compare(verinst, ">=", "2.0.0-0")
- -- do NOT start it not ddns-scripts version 2.x
- if not verok then
- return
- end
+ local muci = require "luci.model.uci"
+
-- no config create an empty one
if not nxfs.access("/etc/config/ddns") then
nxfs.writefile("/etc/config/ddns", "")
end
+ -- preset new option "lookup_host" if not already defined
+ local uci = muci.cursor()
+ local commit = false
+ uci:foreach("ddns", "service", function (s)
+ if not s["lookup_host"] and s["domain"] then
+ uci:set("ddns", s[".name"], "lookup_host", s["domain"])
+ commit = true
+ end
+ end)
+ if commit then uci:commit("ddns") end
+ uci:unload("ddns")
+
entry( {"admin", "services", "ddns"}, cbi("ddns/overview"), _("Dynamic DNS"), 59)
entry( {"admin", "services", "ddns", "detail"}, cbi("ddns/detail"), nil ).leaf = true
entry( {"admin", "services", "ddns", "hints"}, cbi("ddns/hints",
@@ -42,7 +57,60 @@ function index()
entry( {"admin", "services", "ddns", "status"}, call("status") ).leaf = true
end
--- function to read all sections status and return data array
+-- 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>]]
+end
+function app_title_back()
+ return [[<a href="]]
+ .. DISP.build_url("admin", "services", "ddns")
+ .. [[">]]
+ .. I18N.translate(app_title)
+ .. [[</a>]]
+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>]]
+end
+function service_version()
+ local ver = nil
+ IPKG.list_installed(srv_name, function(n, ver, d)
+ -- nothing to do
+ end
+ )
+ if not ver then
+ ver = UTIL.exec(srv_ver_cmd)
+ if #ver == 0 then ver = nil end
+ end
+ return ver
+end
+function service_ok()
+ return IPKG.compare_versions((service_version() or "0"), ">=", srv_ver_min)
+end
+
+-- internal function to read all sections status and return data array
local function _get_status()
local uci = UCI.cursor()
local service = SYS.init.enabled("ddns") and 1 or 0
@@ -118,12 +186,12 @@ local function _get_status()
end
-- try to get registered IP
- local domain = s["domain"] or "_nodomain_"
+ local lookup_host = s["lookup_host"] or "_nolookup_"
local dnsserver = s["dns_server"] or ""
local force_ipversion = tonumber(s["force_ipversion"] or 0)
local force_dnstcp = tonumber(s["force_dnstcp"] or 0)
local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh]]
- command = command .. [[ get_registered_ip ]] .. domain .. [[ ]] .. use_ipv6 ..
+ command = command .. [[ get_registered_ip ]] .. lookup_host .. [[ ]] .. use_ipv6 ..
[[ ]] .. force_ipversion .. [[ ]] .. force_dnstcp .. [[ ]] .. dnsserver
local reg_ip = SYS.exec(command)
if reg_ip == "" then
@@ -135,7 +203,7 @@ local function _get_status()
section = section,
enabled = enabled,
iface = iface,
- domain = domain,
+ lookup = lookup_host,
reg_ip = reg_ip,
pid = pid,
datelast = datelast,
@@ -235,3 +303,4 @@ function status()
HTTP.prepare_content("application/json")
HTTP.write_json(data)
end
+
diff --git a/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua b/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua
index e655ce5219..88429fd12c 100644
--- a/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua
+++ b/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua
@@ -8,13 +8,15 @@ local NX = require "nixio"
local NXFS = require "nixio.fs"
local SYS = require "luci.sys"
local UTIL = require "luci.util"
+local HTTP = require "luci.http"
local DISP = require "luci.dispatcher"
local WADM = require "luci.tools.webadmin"
local DTYP = require "luci.cbi.datatypes"
+local CTRL = require "luci.controller.ddns" -- this application's controller
local DDNS = require "luci.tools.ddns" -- ddns multiused functions
-- takeover arguments -- #######################################################
-local section = arg[1]
+local section = arg[1]
-- check supported options -- ##################################################
-- saved to local vars here because doing multiple os calls slow down the system
@@ -31,15 +33,15 @@ local bold_on = "<strong>"
local bold_off = "</strong>"
-- error text constants -- #####################################################
-err_ipv6_plain = translate("IPv6 not supported") .. " - " ..
+local err_ipv6_plain = translate("IPv6 not supported") .. " - " ..
translate("please select 'IPv4' address version")
-err_ipv6_basic = bold_on ..
+local err_ipv6_basic = bold_on ..
font_red ..
translate("IPv6 not supported") ..
font_off ..
"<br />" .. translate("please select 'IPv4' address version") ..
bold_off
-err_ipv6_other = bold_on ..
+local err_ipv6_other = bold_on ..
font_red ..
translate("IPv6 not supported") ..
font_off ..
@@ -52,16 +54,46 @@ err_ipv6_other = bold_on ..
[[</a>]] ..
bold_off
-function err_tab_basic(self)
+local function err_tab_basic(self)
return translate("Basic Settings") .. " - " .. self.title .. ": "
end
-function err_tab_adv(self)
+local function err_tab_adv(self)
return translate("Advanced Settings") .. " - " .. self.title .. ": "
end
-function err_tab_timer(self)
+local function err_tab_timer(self)
return translate("Timer Settings") .. " - " .. self.title .. ": "
end
+-- read services/services_ipv6 files -- ########################################
+local services4 = { } -- IPv4 --
+local fd4 = io.open("/usr/lib/ddns/services", "r")
+if fd4 then
+ local ln, s, t
+ repeat
+ ln = fd4:read("*l")
+ s = ln and ln:match('^%s*".*') -- only handle lines beginning with "
+ s = s and s:gsub('"','') -- remove "
+ t = s and UTIL.split(s,"(%s+)",nil,true) -- split on whitespaces
+ if t then services4[t[1]]=t[2] end
+ until not ln
+ fd4:close()
+end
+
+local services6 = { } -- IPv6 --
+local fd6 = io.open("/usr/lib/ddns/services_ipv6", "r")
+if fd6 then
+ local ln, s, t
+ repeat
+ ln = fd6:read("*l")
+ s = ln and ln:match('^%s*".*') -- only handle lines beginning with "
+ s = s and s:gsub('"','') -- remove "
+ t = s and UTIL.split(s,"(%s+)",nil,true) -- split on whitespaces
+ if t then services6[t[1]]=t[2] end
+ until not ln
+ fd6:close()
+end
+
+-- multi-used functions -- ####################################################
-- function to verify settings around ip_source
-- will use dynamic_dns_lucihelper to check if
-- local IP can be read
@@ -105,17 +137,94 @@ local function _verify_ip_source()
end
end
--- cbi-map definition -- #######################################################
-m = Map("ddns")
+-- function to check if option is used inside url or script
+-- return -1 on error, 0 NOT required, 1 required
+local function _option_used(option, urlscript)
+ local surl -- search string for url
+ local ssh -- search string for script
+ local required -- option used inside url or script
-m.title = [[<a href="]] .. DISP.build_url("admin", "services", "ddns") .. [[">]] ..
- translate("Dynamic DNS") .. [[</a>]]
+ if option == "domain" then surl, ssh = '%[DOMAIN%]', '%$domain'
+ elseif option == "username" then surl, ssh = '%[USERNAME%]', '%$username'
+ elseif option == "password" then surl, ssh = '%[PASSWORD%]', '%$password'
+ elseif option == "param_enc" then surl, ssh = '%[PARAMENC%]', '%$param_enc'
+ elseif option == "param_opt" then surl, ssh = '%[PARAMOPT%]', '%$param_opt'
+ else
+ error("undefined option")
+ return -1 -- return on error
+ end
-m.description = translate("Dynamic DNS allows that your router can be reached with " ..
- "a fixed hostname while having a dynamically changing " ..
- "IP address.")
+ local required = false
+ -- handle url
+ if urlscript:find('http') then
+ required = ( urlscript:find(surl) )
+ -- handle script
+ else
+ if not urlscript:find("/") then
+ -- might be inside ddns-scripts directory
+ urlscript = "/usr/lib/ddns/" .. urlscript
+ end
+ -- problem with script exit here
+ if not NXFS.access(urlscript) then return -1 end
+
+ local f = io.input(urlscript)
+ -- still problem with script exit here
+ if not f then return -1 end
+ for l in f:lines() do
+ repeat
+ if l:find('^#') then break end -- continue on comment lines
+ required = ( l:find(surl) or l:find(ssh) )
+ until true
+ if required then break end
+ end
+ f:close()
+ end
+ return (required and 1 or 0)
+end
-m.redirect = DISP.build_url("admin", "services", "ddns")
+-- function to verify if option is valid
+local function _option_validate(self, value)
+ -- section is globally defined here be calling agrument (see above)
+ local fusev6 = usev6:formvalue(section)
+ local fsvc4 = svc4:formvalue(section)
+ local fsvc6 = svc6:formvalue(section)
+ local urlsh, used
+
+ -- IP-Version dependent custom service selected
+ if (fusev6 == "0" and fsvc4 == "-") or
+ (fusev6 == "1" and fsvc6 == "-") then
+ -- read custom url
+ urlsh = uurl:formvalue(section)
+ -- no url then read custom script
+ if not urlsh or (#urlsh == 0) then
+ urlsh = ush:formvalue(section)
+ end
+ -- IPv4 read from services4 table
+ elseif (fusev6 == "0") then
+ urlsh = services4[fsvc4]
+ -- IPv6 read from services6 table
+ else
+ urlsh = services6[fsvc6]
+ end
+ -- problem with url or script exit here
+ -- error handled somewhere else
+ if not urlsh or (#urlsh == 0) then return "" end
+
+ used = _option_used(self.option, urlsh)
+ -- on error or not used return empty sting
+ if used < 1 then return "" end
+ -- needed but no data then return error
+ if not value or (#value == 0) then
+ return nil, err_tab_basic(self) .. translate("missing / required")
+ end
+ return value
+end
+
+-- cbi-map definition -- #######################################################
+local m = Map("ddns")
+m.title = CTRL.app_title_back()
+m.description = CTRL.app_description()
+m.redirect = DISP.build_url("admin", "services", "ddns")
m.on_after_commit = function(self)
if self.changed then -- changes ?
@@ -126,19 +235,42 @@ m.on_after_commit = function(self)
end
end
+-- provider switch was requested, save and reload page
+if m:formvalue("cbid.ddns.%s._switch" % section) then -- section == arg[1]
+ local fsvc
+ local fusev6 = m:formvalue("cbid.ddns.%s.use_ipv6" % section)
+ if fusev6 == "1" then
+ fsvc = m:formvalue("cbid.ddns.%s.ipv6_service_name" % section)
+ else
+ fsvc = m:formvalue("cbid.ddns.%s.ipv4_service_name" % section)
+ end
+
+ if fusev6 ~= (m:get(section, "use_ipv6") or "0") then -- IPv6 was changed
+ m:set(section, "use_ipv6", fusev6) -- save it
+ end
+
+ if fsvc ~= "-" then -- NOT "custom"
+ m:set(section, "service_name", fsvc) -- save it
+ else -- else
+ m:del(section, "service_name") -- delete it
+ end
+ m.uci:save(m.config)
+
+ -- reload page
+ HTTP.redirect( DISP.build_url("admin", "services", "ddns", "detail", section) )
+ return
+end
+
-- read application settings -- ################################################
-- date format; if not set use ISO format
-date_format = m.uci:get(m.config, "global", "date_format") or "%F %R"
+local date_format = m.uci:get(m.config, "global", "date_format") or "%F %R"
-- log directory
-log_dir = m.uci:get(m.config, "global", "log_dir") or "/var/log/ddns"
+local log_dir = m.uci:get(m.config, "global", "log_dir") or "/var/log/ddns"
-- cbi-section definition -- ###################################################
-ns = m:section( NamedSection, section, "service",
+local ns = m:section( NamedSection, section, "service",
translate("Details for") .. ([[: <strong>%s</strong>]] % section),
- translate("Configure here the details for selected Dynamic DNS service.")
- .. [[<br /><a href="http://wiki.openwrt.org/doc/uci/ddns#version_1x" target="_blank">]]
- .. translate("For detailed information about parameter settings look here.")
- .. [[</a>]] )
+ translate("Configure here the details for selected Dynamic DNS service.") )
ns.instance = section -- arg [1]
ns:tab("basic", translate("Basic Settings"), nil )
ns:tab("advanced", translate("Advanced Settings"), nil )
@@ -146,17 +278,33 @@ ns:tab("timer", translate("Timer Settings"), nil )
ns:tab("logview", translate("Log File Viewer"), nil )
-- TAB: Basic #####################################################################################
--- enabled -- #################################################################
+-- enabled -- #################################################################
en = ns:taboption("basic", Flag, "enabled",
translate("Enabled"),
translate("If this service section is disabled it could not be started." .. "<br />" ..
"Neither from LuCI interface nor from console") )
en.orientation = "horizontal"
-function en.parse(self, section)
- DDNS.flag_parse(self, section)
+
+-- IPv4/IPv6 - lookup_host -- #################################################
+luh = ns:taboption("basic", Value, "lookup_host",
+ translate("Lookup Hostname"),
+ translate("Hostname/FQDN to validate, if IP update happen or necessary") )
+luh.rmempty = false
+luh.placeholder = "myhost.example.com"
+function luh.validate(self, value)
+ if not value
+ or not (#value > 0)
+ or not DTYP.hostname(value) then
+ return nil, err_tab_basic(self) .. translate("invalid FQDN / required - Sample") .. ": 'myhost.example.com'"
+ else
+ return UTIL.trim(value)
+ end
+end
+function luh.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
--- use_ipv6 (NEW) -- ##########################################################
+-- use_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") )
@@ -179,36 +327,15 @@ function usev6.validate(self, value)
end
return nil, err_tab_basic(self) .. err_ipv6_plain
end
-function usev6.write(self, section, value)
- if value == "0" then -- force rmempty
- return self.map:del(section, self.option)
- else
- return self.map:set(section, self.option, value)
- end
+function usev6.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
--- IPv4 - service_name -- ######################################################
+-- IPv4 - service_name -- #####################################################
svc4 = ns:taboption("basic", ListValue, "ipv4_service_name",
translate("DDNS Service provider") .. " [IPv4]" )
svc4.default = "-"
svc4:depends("use_ipv6", "0") -- only show on IPv4
-
-local services4 = { }
-local fd4 = io.open("/usr/lib/ddns/services", "r")
-
-if fd4 then
- local ln
- repeat
- ln = fd4:read("*l")
- local s = ln and ln:match('^%s*"([^"]+)"')
- if s then services4[#services4+1] = s end
- until not ln
- fd4:close()
-end
-
-for _, v in UTIL.vspairs(services4) do svc4:value(v) end
-svc4:value("-", translate("-- custom --") )
-
function svc4.cfgvalue(self, section)
local v = DDNS.read_value(self, section, "service_name")
if not v or #v == 0 then
@@ -229,14 +356,18 @@ function svc4.write(self, section, value)
self.map:del(section, self.option) -- to be shure
if value ~= "-" then -- and write "service_name
self.map:del(section, "update_url") -- delete update_url
+ self.map:del(section, "update_script") -- delete update_script
return self.map:set(section, "service_name", value)
else
return self.map:del(section, "service_name")
end
end
end
+function svc4.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv6 - service_name -- ######################################################
+-- IPv6 - service_name -- #####################################################
svc6 = ns:taboption("basic", ListValue, "ipv6_service_name",
translate("DDNS Service provider") .. " [IPv6]" )
svc6.default = "-"
@@ -244,23 +375,6 @@ svc6:depends("use_ipv6", "1") -- only show on IPv6
if not has_ipv6 then
svc6.description = err_ipv6_basic
end
-
-local services6 = { }
-local fd6 = io.open("/usr/lib/ddns/services_ipv6", "r")
-
-if fd6 then
- local ln
- repeat
- ln = fd6:read("*l")
- local s = ln and ln:match('^%s*"([^"]+)"')
- if s then services6[#services6+1] = s end
- until not ln
- fd6:close()
-end
-
-for _, v in UTIL.vspairs(services6) do svc6:value(v) end
-svc6:value("-", translate("-- custom --") )
-
function svc6.cfgvalue(self, section)
local v = DDNS.read_value(self, section, "service_name")
if not v or #v == 0 then
@@ -282,33 +396,42 @@ function svc6.write(self, section, value)
self.map:del(section, self.option) -- delete "ipv6_service_name" helper
if value ~= "-" then -- and write "service_name
self.map:del(section, "update_url") -- delete update_url
+ self.map:del(section, "update_script") -- delete update_script
return self.map:set(section, "service_name", value)
else
return self.map:del(section, "service_name")
end
end
end
+function svc6.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
+
+-- IPv4/IPv6 - change Provider -- #############################################
+svs = ns:taboption("basic", Button, "_switch")
+svs.title = translate("Really change DDNS provider?")
+svs.inputtitle = translate("Change provider")
+svs.inputstyle = "apply"
--- IPv4/IPv6 - update_url -- ###################################################
+-- IPv4/IPv6 - update_url -- ##################################################
uurl = ns:taboption("basic", Value, "update_url",
translate("Custom update-URL"),
translate("Update URL to be used for updating your DDNS Provider." .. "<br />" ..
"Follow instructions you will find on their WEB page.") )
-uurl:depends("ipv4_service_name", "-")
-uurl:depends("ipv6_service_name", "-")
function uurl.validate(self, value)
- local script = ush:formvalue(section)
+ local fush = ush:formvalue(section)
+ local fusev6 = usev6:formvalue(section)
- if (usev6:formvalue(section) == "0" and svc4:formvalue(section) ~= "-") or
- (usev6:formvalue(section) == "1" and svc6:formvalue(section) ~= "-") then
+ if (fusev6 == "0" and svc4:formvalue(section) ~= "-") or
+ (fusev6 == "1" and svc6:formvalue(section) ~= "-") then
return "" -- suppress validate error
elseif not value then
- if not script or not (#script > 0) then
+ if not fush or (#fush == 0) then
return nil, err_tab_basic(self) .. translate("missing / required")
else
return "" -- suppress validate error / update_script is given
end
- elseif (#script > 0) then
+ elseif (#fush > 0) then
return nil, err_tab_basic(self) .. translate("either url or script could be set")
end
@@ -325,80 +448,159 @@ function uurl.validate(self, value)
return value
end
+function uurl.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4/IPv6 - update_script -- ################################################
+-- IPv4/IPv6 - update_script -- ###############################################
ush = ns:taboption("basic", Value, "update_script",
translate("Custom update-script"),
translate("Custom update script to be used for updating your DDNS Provider.") )
-ush:depends("ipv4_service_name", "-")
-ush:depends("ipv6_service_name", "-")
function ush.validate(self, value)
- local url = uurl:formvalue(section)
+ local fuurl = uurl:formvalue(section)
+ local fusev6 = usev6:formvalue(section)
- if (usev6:formvalue(section) == "0" and svc4:formvalue(section) ~= "-") or
- (usev6:formvalue(section) == "1" and svc6:formvalue(section) ~= "-") then
+ if (fusev6 == "0" and svc4:formvalue(section) ~= "-") or
+ (fusev6 == "1" and svc6:formvalue(section) ~= "-") then
return "" -- suppress validate error
elseif not value then
- if not url or not (#url > 0) then
+ if not fuurl or (#fuurl == 0) then
return nil, err_tab_basic(self) .. translate("missing / required")
else
return "" -- suppress validate error / update_url is given
end
- elseif (#url > 0) then
+ elseif (#fuurl > 0) then
return nil, err_tab_basic(self) .. translate("either url or script could be set")
elseif not NXFS.access(value) then
return nil, err_tab_basic(self) .. translate("File not found")
end
return value
end
+function ush.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4/IPv6 - domain -- #######################################################
+-- IPv4/IPv6 - domain -- ######################################################
dom = ns:taboption("basic", Value, "domain",
- translate("Hostname/Domain"),
+ translate("Domain"),
translate("Replaces [DOMAIN] in Update-URL") )
-dom.rmempty = false
-dom.placeholder = "mypersonaldomain.dyndns.org"
+dom.placeholder = "myhost.example.com"
function dom.validate(self, value)
- if not value
- or not (#value > 0)
- or not DTYP.hostname(value) then
- return nil, err_tab_basic(self) .. translate("invalid - Sample") .. ": 'mypersonaldomain.dyndns.org'"
- else
- return value
- end
+ return _option_validate(self, value)
+end
+function dom.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
--- IPv4/IPv6 - username -- #####################################################
+-- IPv4/IPv6 - username -- ####################################################
user = ns:taboption("basic", Value, "username",
translate("Username"),
- translate("Replaces [USERNAME] in Update-URL") )
-user.rmempty = false
+ translate("Replaces [USERNAME] in Update-URL (URL-encoded)") )
function user.validate(self, value)
- if not value then
- return nil, err_tab_basic(self) .. translate("missing / required")
- end
- return value
+ return _option_validate(self, value)
+end
+function user.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
--- IPv4/IPv6 - password -- #####################################################
+-- IPv4/IPv6 - password -- ####################################################
pw = ns:taboption("basic", Value, "password",
translate("Password"),
- translate("Replaces [PASSWORD] in Update-URL") )
-pw.rmempty = false
+ translate("Replaces [PASSWORD] in Update-URL (URL-encoded)") )
pw.password = true
function pw.validate(self, value)
- if not value then
- return nil, err_tab_basic(self) .. translate("missing / required")
+ return _option_validate(self, value)
+end
+function pw.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
+
+-- IPv4/IPv6 - param_enc -- ###################################################
+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)
+end
+function pe.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
+
+-- IPv4/IPv6 - param_enc -- ###################################################
+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)
+end
+function po.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
+
+-- handled service dependent show/display -- ##################################
+-- IPv4 --
+local cv4 = svc4:cfgvalue(section)
+if cv4 ~= "-" then
+ svs:depends ("ipv4_service_name", "-" ) -- show only if "-"
+ ush:depends ("ipv4_service_name", "?")
+ uurl:depends("ipv4_service_name", "?")
+else
+ uurl:depends("ipv4_service_name", "-")
+ ush:depends ("ipv4_service_name", "-")
+ dom:depends("ipv4_service_name", "-" )
+ user:depends("ipv4_service_name", "-" )
+ pw:depends("ipv4_service_name", "-" )
+ pe:depends("ipv4_service_name", "-" )
+ po:depends("ipv4_service_name", "-" )
+end
+for s, u in UTIL.kspairs(services4) do
+ svc4:value(s) -- fill DropDown-List
+ if cv4 ~= s then
+ svs:depends("ipv4_service_name", s )
+ else
+ dom:depends ("ipv4_service_name", ((_option_used(dom.option, u) == 1) and s or "?") )
+ user:depends("ipv4_service_name", ((_option_used(user.option, u) == 1) and s or "?") )
+ pw:depends ("ipv4_service_name", ((_option_used(pw.option, u) == 1) and s or "?") )
+ pe:depends ("ipv4_service_name", ((_option_used(pe.option, u) == 1) and s or "?") )
+ po:depends ("ipv4_service_name", ((_option_used(po.option, u) == 1) and s or "?") )
end
- return value
end
+svc4:value("-", translate("-- custom --") )
+
+-- IPv6 --
+local cv6 = svc6:cfgvalue(section)
+if cv6 ~= "-" then
+ svs:depends ("ipv6_service_name", "-" )
+ uurl:depends("ipv6_service_name", "?")
+ ush:depends ("ipv6_service_name", "?")
+else
+ uurl:depends("ipv6_service_name", "-")
+ ush:depends ("ipv6_service_name", "-")
+ dom:depends("ipv6_service_name", "-" )
+ user:depends("ipv6_service_name", "-" )
+ pw:depends("ipv6_service_name", "-" )
+ pe:depends("ipv6_service_name", "-" )
+ po:depends("ipv6_service_name", "-" )
+end
+for s, u in UTIL.kspairs(services6) do
+ svc6:value(s) -- fill DropDown-List
+ if cv6 ~= s then
+ svs:depends("ipv6_service_name", s )
+ else
+ dom:depends ("ipv6_service_name", ((_option_used(dom.option, u) == 1) and s or "?") )
+ user:depends("ipv6_service_name", ((_option_used(user.option, u) == 1) and s or "?") )
+ pw:depends ("ipv6_service_name", ((_option_used(pw.option, u) == 1) and s or "?") )
+ pe:depends ("ipv6_service_name", ((_option_used(pe.option, u) == 1) and s or "?") )
+ po:depends ("ipv6_service_name", ((_option_used(po.option, u) == 1) and s or "?") )
+ end
+end
+svc6:value("-", translate("-- custom --") )
--- IPv4/IPv6 - use_https (NEW) -- ##############################################
+-- IPv4/IPv6 - use_https -- ###################################################
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"
- https.rmempty = false -- force validate function
function https.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section)
if not has_ssl and value == "1" then
@@ -410,9 +612,6 @@ if has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
end
return value
end
- function https.parse(self, section)
- DDNS.flag_parse(self, section)
- end
function https.validate(self, value)
if (value == "1" and has_ssl ) or value == "0" then return value end
return nil, err_tab_basic(self) .. translate("HTTPS not supported") .. " !"
@@ -427,7 +626,7 @@ if has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
end
end
--- IPv4/IPv6 - cacert (NEW) -- #################################################
+-- IPv4/IPv6 - cacert -- ######################################################
if has_ssl then
cert = ns:taboption("basic", Value, "cacert",
translate("Path to CA-Certificate"),
@@ -435,8 +634,8 @@ if has_ssl then
translate("or") .. bold_on .. " IGNORE " .. bold_off ..
translate("to run HTTPS without verification of server certificates (insecure)") )
cert:depends("use_https", "1")
- cert.rmempty = false -- force validate function
cert.default = "/etc/ssl/certs"
+ cert.forcewrite = true
function cert.validate(self, value)
if https:formvalue(section) == "0" then
return "" -- supress validate error if NOT https
@@ -451,10 +650,13 @@ if has_ssl then
return nil, err_tab_basic(self) ..
translate("file or directory not found or not 'IGNORE'") .. " !"
end
+ function cert.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+ end
end
--- TAB: Advanced ##################################################################################
--- IPv4 - ip_source -- #########################################################
+-- TAB: Advanced #################################################################################
+-- IPv4 - ip_source -- ########################################################
src4 = ns:taboption("advanced", ListValue, "ipv4_source",
translate("IP address source") .. " [IPv4]",
translate("Defines the source to read systems IPv4-Address from, that will be send to the DDNS provider") )
@@ -500,8 +702,11 @@ function src4.write(self, section, value)
self.map:del(section, self.option) -- delete "ipv4_source" helper
return self.map:set(section, "ip_source", value) -- and write "ip_source
end
+function src4.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv6 - ip_source -- #########################################################
+-- IPv6 - ip_source -- ########################################################
src6 = ns:taboption("advanced", ListValue, "ipv6_source",
translate("IP address source") .. " [IPv6]",
translate("Defines the source to read systems IPv6-Address from, that will be send to the DDNS provider") )
@@ -552,8 +757,11 @@ function src6.write(self, section, value)
self.map:del(section, self.option) -- delete "ipv4_source" helper
return self.map:set(section, "ip_source", value) -- and write "ip_source
end
+function src6.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4 - ip_network (default "wan") -- ########################################
+-- IPv4 - ip_network (default "wan") -- #######################################
ipn4 = ns:taboption("advanced", ListValue, "ipv4_network",
translate("Network") .. " [IPv4]",
translate("Defines the network to read systems IPv4-Address from") )
@@ -586,8 +794,11 @@ function ipn4.write(self, section, value)
return self.map:set(section, "ip_network", value) -- and write "ip_network"
end
end
+function ipn4.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv6 - ip_network (default "wan6") -- #######################################
+-- IPv6 - ip_network (default "wan6") -- ######################################
ipn6 = ns:taboption("advanced", ListValue, "ipv6_network",
translate("Network") .. " [IPv6]" )
ipn6:depends("ipv6_source", "network")
@@ -626,8 +837,11 @@ function ipn6.write(self, section, value)
return self.map:set(section, "ip_network", value) -- and write "ip_network"
end
end
+function ipn6.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4 - ip_url (default "checkip.dyndns.com") -- #############################
+-- IPv4 - ip_url (default "checkip.dyndns.com") -- ############################
iurl4 = ns:taboption("advanced", Value, "ipv4_url",
translate("URL to detect") .. " [IPv4]",
translate("Defines the Web page to read systems IPv4-Address from") )
@@ -668,8 +882,11 @@ function iurl4.write(self, section, value)
return self.map:set(section, "ip_url", value) -- and write "ip_url"
end
end
+function iurl4.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv6 - ip_url (default "checkipv6.dyndns.com") -- ###########################
+-- IPv6 - ip_url (default "checkipv6.dyndns.com") -- ##########################
iurl6 = ns:taboption("advanced", Value, "ipv6_url",
translate("URL to detect") .. " [IPv6]" )
iurl6:depends("ipv6_source", "web")
@@ -716,8 +933,11 @@ function iurl6.write(self, section, value)
return self.map:set(section, "ip_url", value) -- and write "ip_url"
end
end
+function iurl6.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4 + IPv6 - ip_interface -- ###############################################
+-- IPv4 + IPv6 - ip_interface -- ##############################################
ipi = ns:taboption("advanced", ListValue, "ip_interface",
translate("Interface"),
translate("Defines the interface to read systems IP-Address from") )
@@ -732,16 +952,18 @@ for _, v in pairs(SYS.net.devices()) do
end
end
function ipi.validate(self, value)
- if (usev6:formvalue(section) == "0" and src4:formvalue(section) ~= "interface")
- or (usev6:formvalue(section) == "1" and src6:formvalue(section) ~= "interface") then
+ local fusev6 = usev6:formvalue(section)
+ if (fusev6 == "0" and src4:formvalue(section) ~= "interface")
+ or (fusev6 == "1" and src6:formvalue(section) ~= "interface") then
return ""
else
return value
end
end
function ipi.write(self, section, value)
- if (usev6:formvalue(section) == "0" and src4:formvalue(section) ~= "interface")
- or (usev6:formvalue(section) == "1" and src6:formvalue(section) ~= "interface") then
+ local fusev6 = usev6:formvalue(section)
+ if (fusev6 == "0" and src4:formvalue(section) ~= "interface")
+ or (fusev6 == "1" and src6:formvalue(section) ~= "interface") then
return true
else
-- get network from device to
@@ -751,21 +973,24 @@ function ipi.write(self, section, value)
return self.map:set(section, self.option, value)
end
end
+function ipi.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4 + IPv6 - ip_script (NEW) -- ############################################
+-- IPv4 + IPv6 - ip_script -- #################################################
ips = ns:taboption("advanced", Value, "ip_script",
translate("Script"),
translate("User defined script to read systems IP-Address") )
ips:depends("ipv4_source", "script") -- IPv4
ips:depends("ipv6_source", "script") -- or IPv6
-ips.rmempty = false
ips.placeholder = "/path/to/script.sh"
function ips.validate(self, value)
+ local fusev6 = usev6:formvalue(section)
local split
if value then split = UTIL.split(value, " ") end
- if (usev6:formvalue(section) == "0" and src4:formvalue(section) ~= "script")
- or (usev6:formvalue(section) == "1" and src6:formvalue(section) ~= "script") then
+ if (fusev6 == "0" and src4:formvalue(section) ~= "script")
+ or (fusev6 == "1" and src6:formvalue(section) ~= "script") then
return ""
elseif not value or not (#value > 0) or not NXFS.access(split[1], "x") then
return nil, err_tab_adv(self) ..
@@ -775,15 +1000,19 @@ function ips.validate(self, value)
end
end
function ips.write(self, section, value)
- if (usev6:formvalue(section) == "0" and src4:formvalue(section) ~= "script")
- or (usev6:formvalue(section) == "1" and src6:formvalue(section) ~= "script") then
+ local fusev6 = usev6:formvalue(section)
+ if (fusev6 == "0" and src4:formvalue(section) ~= "script")
+ or (fusev6 == "1" and src6:formvalue(section) ~= "script") then
return true
else
return self.map:set(section, self.option, value)
end
end
+function ips.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4 - interface - default "wan" -- #########################################
+-- IPv4 - interface - default "wan" -- ########################################
-- event network to monitor changes/hotplug/dynamic_dns_updater.sh
-- only needs to be set if "ip_source"="web" or "script"
-- if "ip_source"="network" or "interface" we use their network
@@ -798,27 +1027,32 @@ function eif4.cfgvalue(self, section)
return DDNS.read_value(self, section, "interface")
end
function eif4.validate(self, value)
+ local fsrc4 = src4:formvalue(section)
if usev6:formvalue(section) == "1"
- or src4:formvalue(section) == "network"
- or src4:formvalue(section) == "interface" then
+ or fsrc4 == "network"
+ or fsrc4 == "interface" then
return "" -- ignore IPv6, network, interface
else
return value
end
end
function eif4.write(self, section, value)
+ local fsrc4 = src4:formvalue(section)
if usev6:formvalue(section) == "1"
- or src4:formvalue(section) == "network"
- or src4:formvalue(section) == "interface" then
+ or fsrc4 == "network"
+ or fsrc4 == "interface" then
return true -- ignore IPv6, network, interface
else
self.map:del(section, self.option) -- delete "ipv4_interface" helper
return self.map:set(section, "interface", value) -- and write "interface"
end
end
+function eif4.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv6 - interface (NEW) - default "wan6" -- ##################################
--- event network to monitor changes/hotplug (NEW)
+-- IPv6 - interface - default "wan6" -- #######################################
+-- event network to monitor changes/hotplug
-- only needs to be set if "ip_source"="web" or "script"
-- if "ip_source"="network" or "interface" we use their network
eif6 = ns:taboption("advanced", ListValue, "ipv6_interface",
@@ -836,9 +1070,10 @@ function eif6.cfgvalue(self, section)
return DDNS.read_value(self, section, "interface")
end
function eif6.validate(self, value)
+ local fsrc6 = src6:formvalue(section)
if usev6:formvalue(section) == "0"
- or src4:formvalue(section) == "network"
- or src4:formvalue(section) == "interface" then
+ or fsrc6 == "network"
+ or fsrc6 == "interface" then
return "" -- ignore IPv4, network, interface
elseif not has_ipv6 then
return nil, err_tab_adv(self) .. err_ipv6_plain
@@ -847,23 +1082,26 @@ function eif6.validate(self, value)
end
end
function eif6.write(self, section, value)
+ local fsrc6 = src6:formvalue(section)
if usev6:formvalue(section) == "0"
- or src4:formvalue(section) == "network"
- or src4:formvalue(section) == "interface" then
+ or fsrc6 == "network"
+ or fsrc6 == "interface" then
return true -- ignore IPv4, network, interface
else
self.map:del(section, self.option) -- delete "ipv6_interface" helper
return self.map:set(section, "interface", value) -- and write "interface"
end
end
+function eif6.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4/IPv6 - bind_network -- #################################################
+-- IPv4/IPv6 - bind_network -- ################################################
if has_ssl or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
bnet = ns:taboption("advanced", ListValue, "bind_network",
translate("Bind Network") )
bnet:depends("ipv4_source", "web")
bnet:depends("ipv6_source", "web")
- bnet.rmempty = true
bnet.default = ""
bnet:value("", translate("-- default --"))
WADM.cbi_add_networks(bnet)
@@ -883,9 +1121,12 @@ if has_ssl or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
if (value ~= "" and has_ssl ) 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)
+ DDNS.value_parse(self, section, novld)
+ end
end
--- IPv4 + IPv6 - force_ipversion (NEW) -- ######################################
+-- IPv4 + IPv6 - force_ipversion -- ###########################################
-- optional to force wget/curl and host to use only selected IP version
-- command parameter "-4" or "-6"
if has_force or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then
@@ -907,19 +1148,9 @@ if has_force or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then
if (value == "1" and has_force) or value == "0" then return value end
return nil, err_tab_adv(self) .. translate("Force IP Version not supported")
end
- function fipv.parse(self, section)
- DDNS.flag_parse(self, section)
- end
- function fipv.write(self, section, value)
- if value == "1" then
- return self.map:set(section, self.option, value)
- else
- return self.map:del(section, self.option)
- end
- end
end
--- IPv4 + IPv6 - dns_server (NEW) -- ###########################################
+-- IPv4 + IPv6 - dns_server -- ################################################
-- optional DNS Server to use resolving my IP if "ip_source"="web"
dns = ns:taboption("advanced", Value, "dns_server",
translate("DNS-Server"),
@@ -928,7 +1159,7 @@ dns = ns:taboption("advanced", Value, "dns_server",
dns.placeholder = "mydns.lan"
function dns.validate(self, value)
-- if .datatype is set, then it is checked before calling this function
- if not value then
+ if not value or (#value == 0) then
return "" -- ignore on empty
elseif not DTYP.host(value) then
return nil, err_tab_adv(self) .. translate("use hostname, FQDN, IPv4- or IPv6-Address")
@@ -946,8 +1177,11 @@ function dns.validate(self, value)
end
end
end
+function dns.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- IPv4 + IPv6 - force_dnstcp (NEW) -- #########################################
+-- IPv4 + IPv6 - force_dnstcp -- ##############################################
if has_dnstcp or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) then
tcp = ns:taboption("advanced", Flag, "force_dnstcp",
translate("Force TCP on DNS") )
@@ -969,12 +1203,9 @@ if has_dnstcp or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) then
end
return nil, err_tab_adv(self) .. translate("DNS requests via TCP not supported")
end
- function tcp.parse(self, section)
- DDNS.flag_parse(self, section)
- end
end
--- IPv4 + IPv6 - proxy (NEW) -- ################################################
+-- IPv4 + IPv6 - proxy -- #####################################################
-- optional Proxy to use for http/https requests [user:password@]proxyhost[:port]
if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
pxy = ns:taboption("advanced", Value, "proxy",
@@ -996,7 +1227,7 @@ if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
end
function pxy.validate(self, value)
-- if .datatype is set, then it is checked before calling this function
- if not value then
+ if not value or (#value == 0) then
return "" -- ignore on empty
elseif has_proxy then
local ipv6 = usev6:formvalue(section) or "0"
@@ -1015,9 +1246,12 @@ if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
return nil, err_tab_adv(self) .. translate("PROXY-Server not supported")
end
end
+ function pxy.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+ end
end
--- use_syslog -- ###############################################################
+-- use_syslog -- ##############################################################
slog = ns:taboption("advanced", ListValue, "use_syslog",
translate("Log to syslog"),
translate("Writes log messages to syslog. Critical Errors will always be written to syslog.") )
@@ -1027,26 +1261,24 @@ slog:value("1", translate("Info"))
slog:value("2", translate("Notice"))
slog:value("3", translate("Warning"))
slog:value("4", translate("Error"))
+function slog.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- use_logfile (NEW) -- ########################################################
+-- use_logfile -- #############################################################
logf = ns:taboption("advanced", Flag, "use_logfile",
translate("Log to file"),
translate("Writes detailed messages to log file. File will be truncated automatically.") .. "<br />" ..
translate("File") .. [[: "]] .. log_dir .. [[/]] .. section .. [[.log"]] )
logf.orientation = "horizontal"
-logf.rmempty = false -- we want to save in /etc/config/ddns file on "0" because
-logf.default = "1" -- if not defined write to log by default
-function logf.parse(self, section)
- DDNS.flag_parse(self, section)
-end
+logf.default = "1" -- if not defined write to log by default
--- TAB: Timer #####################################################################################
--- check_interval -- ###########################################################
+-- TAB: Timer ####################################################################################
+-- check_interval -- ##########################################################
ci = ns:taboption("timer", Value, "check_interval",
translate("Check Interval") )
ci.template = "ddns/detail_value"
-ci.default = 10
-ci.rmempty = false -- validate ourselves for translatable error messages
+ci.default = "10"
function ci.validate(self, value)
if not DTYP.uinteger(value)
or tonumber(value) < 1 then
@@ -1061,7 +1293,7 @@ function ci.validate(self, value)
end
end
function ci.write(self, section, value)
- -- simulate rmempty=true remove default
+ -- remove when default
local secs = DDNS.calc_seconds(value, cu:formvalue(section))
if secs ~= 600 then --default 10 minutes
return self.map:set(section, self.option, value)
@@ -1070,20 +1302,22 @@ function ci.write(self, section, value)
return self.map:del(section, self.option)
end
end
+function ci.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- check_unit -- ###############################################################
+-- check_unit -- ##############################################################
cu = ns:taboption("timer", ListValue, "check_unit", "not displayed, but needed otherwise error",
translate("Interval to check for changed IP" .. "<br />" ..
"Values below 5 minutes == 300 seconds are not supported") )
cu.template = "ddns/detail_lvalue"
cu.default = "minutes"
-cu.rmempty = false -- want to control write process
cu:value("seconds", translate("seconds"))
cu:value("minutes", translate("minutes"))
cu:value("hours", translate("hours"))
--cu:value("days", translate("days"))
function cu.write(self, section, value)
- -- simulate rmempty=true remove default
+ -- remove when default
local secs = DDNS.calc_seconds(ci:formvalue(section), value)
if secs ~= 600 then --default 10 minutes
return self.map:set(section, self.option, value)
@@ -1091,13 +1325,16 @@ function cu.write(self, section, value)
return true
end
end
+function cu.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- force_interval (modified) -- ################################################
+-- force_interval (modified) -- ###############################################
fi = ns:taboption("timer", Value, "force_interval",
translate("Force Interval") )
fi.template = "ddns/detail_value"
-fi.default = 72 -- see dynamic_dns_updater.sh script
-fi.rmempty = false -- validate ourselves for translatable error messages
+fi.default = "72" -- see dynamic_dns_updater.sh script
+--fi.rmempty = false -- validate ourselves for translatable error messages
function fi.validate(self, value)
if not DTYP.uinteger(value)
or tonumber(value) < 0 then
@@ -1131,15 +1368,18 @@ function fi.write(self, section, value)
return self.map:del(section, self.option)
end
end
+function fi.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- force_unit -- ###############################################################
+-- force_unit -- ##############################################################
fu = ns:taboption("timer", ListValue, "force_unit", "not displayed, but needed otherwise error",
translate("Interval to force updates send to DDNS Provider" .. "<br />" ..
"Setting this parameter to 0 will force the script to only run once" .. "<br />" ..
"Values lower 'Check Interval' except '0' are not supported") )
fu.template = "ddns/detail_lvalue"
fu.default = "hours"
-fu.rmempty = false -- want to control write process
+--fu.rmempty = false -- want to control write process
--fu:value("seconds", translate("seconds"))
fu:value("minutes", translate("minutes"))
fu:value("hours", translate("hours"))
@@ -1153,15 +1393,17 @@ function fu.write(self, section, value)
return true
end
end
+function fu.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- retry_count (NEW) -- ########################################################
+-- retry_count -- #############################################################
rc = ns:taboption("timer", Value, "retry_count")
rc.title = translate("Error Retry Counter")
rc.description = translate("On Error the script will stop execution after given number of retrys")
.. "<br />"
.. translate("The default setting of '0' will retry infinite.")
-rc.default = 0
-rc.rmempty = false -- validate ourselves for translatable error messages
+rc.default = "0"
function rc.validate(self, value)
if not DTYP.uinteger(value) then
return nil, err_tab_timer(self) .. translate("minimum value '0'")
@@ -1169,21 +1411,15 @@ function rc.validate(self, value)
return value
end
end
-function rc.write(self, section, value)
- -- simulate rmempty=true remove default
- if tonumber(value) ~= self.default then
- return self.map:set(section, self.option, value)
- else
- return self.map:del(section, self.option)
- end
+function rc.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
--- retry_interval -- ###########################################################
+-- retry_interval -- ##########################################################
ri = ns:taboption("timer", Value, "retry_interval",
translate("Error Retry Interval") )
ri.template = "ddns/detail_value"
-ri.default = 60
-ri.rmempty = false -- validate ourselves for translatable error messages
+ri.default = "60"
function ri.validate(self, value)
if not DTYP.uinteger(value)
or tonumber(value) < 1 then
@@ -1202,13 +1438,16 @@ function ri.write(self, section, value)
return self.map:del(section, self.option)
end
end
+function ri.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- retry_unit -- ###############################################################
+-- retry_unit -- ##############################################################
ru = ns:taboption("timer", ListValue, "retry_unit", "not displayed, but needed otherwise error",
translate("On Error the script will retry the failed action after given time") )
ru.template = "ddns/detail_lvalue"
ru.default = "seconds"
-ru.rmempty = false -- want to control write process
+--ru.rmempty = false -- want to control write process
ru:value("seconds", translate("seconds"))
ru:value("minutes", translate("minutes"))
--ru:value("hours", translate("hours"))
@@ -1222,8 +1461,11 @@ function ru.write(self, section, value)
return true -- will be deleted by retry_interval
end
end
+function ru.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
--- TAB: LogView (NEW) #############################################################################
+-- TAB: LogView ##################################################################################
lv = ns:taboption("logview", DummyValue, "_logview")
lv.template = "ddns/detail_logview"
lv.inputtitle = translate("Read / Reread log file")
diff --git a/applications/luci-app-ddns/luasrc/model/cbi/ddns/global.lua b/applications/luci-app-ddns/luasrc/model/cbi/ddns/global.lua
index 25d09b73bb..23ce4f13f7 100644
--- a/applications/luci-app-ddns/luasrc/model/cbi/ddns/global.lua
+++ b/applications/luci-app-ddns/luasrc/model/cbi/ddns/global.lua
@@ -5,18 +5,14 @@ local NX = require "nixio"
local NXFS = require "nixio.fs"
local DISP = require "luci.dispatcher"
local SYS = require "luci.sys"
+local CTRL = require "luci.controller.ddns" -- this application's controller
local DDNS = require "luci.tools.ddns" -- ddns multiused functions
-- cbi-map definition -- #######################################################
local m = Map("ddns")
-
-m.title = [[<a href="]] .. DISP.build_url("admin", "services", "ddns") .. [[">]]
- .. translate("Dynamic DNS") .. [[</a>]]
-
-m.description = translate("Dynamic DNS allows that your router can be reached with " ..
- "a fixed hostname while having a dynamically changing IP address.")
-
-m.redirect = DISP.build_url("admin", "services", "ddns")
+m.title = CTRL.app_title_back()
+m.description = CTRL.app_description()
+m.redirect = DISP.build_url("admin", "services", "ddns")
function m.commit_handler(self)
if self.changed then -- changes ?
@@ -52,17 +48,7 @@ ali.description = translate("Non-public and by default blocked IP's") .. ":"
.. "0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12, 192.168/16"
.. [[<br /><strong>IPv6: </strong>]]
.. "::/32, f000::/4"
-ali.reempty = true
ali.default = "0"
-function ali.parse(self, section)
- DDNS.flag_parse(self, section)
-end
-function ali.validate(self, value)
- if value == self.default then
- return "" -- default = empty
- end
- return value
-end
-- date_format -- #############################################################
local df = ns:option(Value, "date_format")
@@ -71,7 +57,6 @@ df.description = [[<a href="http://www.cplusplus.com/reference/ctime/strftime/"
.. translate("For supported codes look here")
.. [[</a>]]
df.template = "ddns/global_value"
-df.rmempty = true
df.default = "%F %R"
df.date_string = ""
function df.cfgvalue(self, section)
@@ -80,55 +65,45 @@ function df.cfgvalue(self, section)
self.date_string = DDNS.epoch2date(epoch, value)
return value
end
-function df.validate(self, value)
- if value == self.default then
- return "" -- default = empty
- end
- return value
+function df.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
-- run_dir -- #################################################################
local rd = ns:option(Value, "run_dir")
rd.title = translate("Status directory")
rd.description = translate("Directory contains PID and other status information for each running section")
-rd.rmempty = true
rd.default = "/var/run/ddns"
-function rd.validate(self, value)
- if value == self.default then
- return "" -- default = empty
- end
- return value
+-- no need to validate. if empty default is used everything else created by dns-scripts
+function rd.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
-- log_dir -- #################################################################
local ld = ns:option(Value, "log_dir")
ld.title = translate("Log directory")
ld.description = translate("Directory contains Log files for each running section")
-ld.rmempty = true
ld.default = "/var/log/ddns"
-function ld.validate(self, value)
- if value == self.default then
- return "" -- default = empty
- end
- return value
+-- no need to validate. if empty default is used everything else created by dns-scripts
+function ld.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
end
-- log_lines -- ###############################################################
local ll = ns:option(Value, "log_lines")
ll.title = translate("Log length")
ll.description = translate("Number of last lines stored in log files")
-ll.rmempty = true
ll.default = "250"
function ll.validate(self, value)
local n = tonumber(value)
if not n or math.floor(n) ~= n or n < 1 then
return nil, self.title .. ": " .. translate("minimum value '1'")
end
- if value == self.default then
- return "" -- default = empty
- end
return value
end
+function ll.parse(self, section, novld)
+ DDNS.value_parse(self, section, novld)
+end
-- use_curl -- ################################################################
if (SYS.call([[ grep -i "\+ssl" /usr/bin/wget >/dev/null 2>&1 ]]) == 0)
@@ -139,17 +114,7 @@ and NXFS.access("/usr/bin/curl") then
.. [[<br />]]
.. translate("To use cURL activate this option.")
pc.orientation = "horizontal"
- pc.rmempty = true
pc.default = "0"
- function pc.parse(self, section)
- DDNS.flag_parse(self, section)
- end
- function pc.validate(self, value)
- if value == self.default then
- return "" -- default = empty
- end
- return value
- end
end
return m
diff --git a/applications/luci-app-ddns/luasrc/model/cbi/ddns/hints.lua b/applications/luci-app-ddns/luasrc/model/cbi/ddns/hints.lua
index 2a65fd04fa..031bf513cf 100644
--- a/applications/luci-app-ddns/luasrc/model/cbi/ddns/hints.lua
+++ b/applications/luci-app-ddns/luasrc/model/cbi/ddns/hints.lua
@@ -1,9 +1,9 @@
-- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
-- Licensed to the public under the Apache License 2.0.
-local CTRL = require "luci.controller.ddns" -- this application's controller
local DISP = require "luci.dispatcher"
local SYS = require "luci.sys"
+local CTRL = require "luci.controller.ddns" -- this application's controller
local DDNS = require "luci.tools.ddns" -- ddns multiused functions
-- check supported options -- ##################################################
@@ -11,8 +11,6 @@ local DDNS = require "luci.tools.ddns" -- ddns multiused functions
has_ssl = DDNS.check_ssl() -- HTTPS support and --bind-network / --interface
has_proxy = DDNS.check_proxy() -- Proxy support
has_dnstcp = DDNS.check_bind_host() -- DNS TCP support
--- correct ddns-scripts version
-need_update = DDNS.ipkg_ver_compare(DDNS.ipkg_ver_installed("ddns-scripts"), "<<", CTRL.DDNS_MIN)
-- html constants
font_red = [[<font color="red">]]
@@ -22,15 +20,9 @@ bold_off = [[</strong>]]
-- cbi-map definition -- #######################################################
m = Map("ddns")
-
-m.title = [[<a href="]] .. DISP.build_url("admin", "services", "ddns") .. [[">]] ..
- translate("Dynamic DNS") .. [[</a>]]
-
-m.description = translate("Dynamic DNS allows that your router can be reached with " ..
- "a fixed hostname while having a dynamically changing " ..
- "IP address.")
-
-m.redirect = DISP.build_url("admin", "services", "ddns")
+m.title = CTRL.app_title_back()
+m.description = CTRL.app_description()
+m.redirect = DISP.build_url("admin", "services", "ddns")
-- SimpleSection definition -- #################################################
-- show Hints to optimize installation and script usage
@@ -39,7 +31,7 @@ s = m:section( SimpleSection,
translate("Below a list of configuration tips for your system to run Dynamic DNS updates without limitations") )
-- ddns_scripts needs to be updated for full functionality
-if need_update then
+if not CTRL.service_ok() then
local dv = s:option(DummyValue, "_update_needed")
dv.titleref = DISP.build_url("admin", "system", "packages")
dv.rawhtml = true
diff --git a/applications/luci-app-ddns/luasrc/model/cbi/ddns/overview.lua b/applications/luci-app-ddns/luasrc/model/cbi/ddns/overview.lua
index 5b5925b25e..46fc0a4a29 100644
--- a/applications/luci-app-ddns/luasrc/model/cbi/ddns/overview.lua
+++ b/applications/luci-app-ddns/luasrc/model/cbi/ddns/overview.lua
@@ -2,10 +2,10 @@
-- Licensed to the public under the Apache License 2.0.
local NXFS = require "nixio.fs"
-local CTRL = require "luci.controller.ddns" -- this application's controller
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
-- show hints ?
@@ -15,7 +15,7 @@ show_hints = not (DDNS.check_ipv6() -- IPv6 support
and DDNS.check_bind_host() -- DNS TCP support
)
-- correct ddns-scripts version
-need_update = DDNS.ipkg_ver_compare(DDNS.ipkg_ver_installed("ddns-scripts"), "<<", CTRL.DDNS_MIN)
+need_update = not CTRL.service_ok()
-- html constants
font_red = [[<font color="red">]]
@@ -25,22 +25,8 @@ bold_off = [[</strong>]]
-- cbi-map definition -- #######################################################
m = Map("ddns")
-
-m.title = [[<a href="javascript:alert(']]
- .. translate("Version Information")
- .. [[\n\nluci-app-ddns]]
- .. [[\n\t]] .. translate("Version") .. [[:\t]] .. DDNS.ipkg_ver_installed("luci-app-ddns")
- .. [[\n\nddns-scripts ]] .. translate("required") .. [[:]]
- .. [[\n\t]] .. translate("Version") .. [[:\t]] .. CTRL.DDNS_MIN .. [[ ]] .. translate("or higher")
- .. [[\n\nddns-scripts ]] .. translate("installed") .. [[:]]
- .. [[\n\t]] .. translate("Version") .. [[:\t]] .. DDNS.ipkg_ver_installed("ddns-scripts")
- .. [[\n\n]]
- .. [[')">]]
- .. translate("Dynamic DNS") .. [[</a>]]
-
-m.description = translate("Dynamic DNS allows that your router can be reached with " ..
- "a fixed hostname while having a dynamically changing " ..
- "IP address.")
+m.title = CTRL.app_title_main()
+m.description = CTRL.app_description()
m.on_after_commit = function(self)
if self.changed then -- changes ?
@@ -122,21 +108,21 @@ function ts.create(self, name)
HTTP.redirect( self.extedit:format(name) )
end
--- Domain and registered IP -- #################################################
-dom = ts:option(DummyValue, "_domainIP",
- translate("Hostname/Domain") .. "<br />" .. translate("Registered IP") )
+-- Lookup_Host and registered IP -- #################################################
+dom = ts:option(DummyValue, "_lookupIP",
+ translate("Lookup Hostname") .. "<br />" .. translate("Registered IP") )
dom.template = "ddns/overview_doubleline"
function dom.set_one(self, section)
- local domain = self.map:get(section, "domain") or ""
- if domain ~= "" then
- return domain
+ local lookup = self.map:get(section, "lookup_host") or ""
+ if lookup ~= "" then
+ return lookup
else
return [[<em>]] .. translate("config error") .. [[</em>]]
end
end
function dom.set_two(self, section)
- local domain = self.map:get(section, "domain") or ""
- if domain == "" then return "" end
+ local lookup = self.map:get(section, "lookup_host") or ""
+ if lookup == "" then return "" end
local dnsserver = self.map:get(section, "dnsserver") or ""
local use_ipv6 = tonumber(self.map:get(section, "use_ipv6") or 0)
local force_ipversion = tonumber(self.map:get(section, "force_ipversion") or 0)
@@ -145,7 +131,7 @@ function dom.set_two(self, section)
if not NXFS.access(command, "rwx", "rx", "rx") then
NXFS.chmod(command, 755)
end
- command = command .. [[ get_registered_ip ]] .. domain .. [[ ]] .. use_ipv6 ..
+ command = command .. [[ get_registered_ip ]] .. lookup .. [[ ]] .. use_ipv6 ..
[[ ]] .. force_ipversion .. [[ ]] .. force_dnstcp .. [[ ]] .. dnsserver
local ip = SYS.exec(command)
if ip == "" then ip = translate("no data") end
@@ -157,9 +143,6 @@ ena = ts:option( Flag, "enabled",
translate("Enabled"))
ena.template = "ddns/overview_enabled"
ena.rmempty = false
-function ena.parse(self, section)
- DDNS.flag_parse(self, section)
-end
-- show PID and next update
upd = ts:option( DummyValue, "_update",
diff --git a/applications/luci-app-ddns/luasrc/tools/ddns.lua b/applications/luci-app-ddns/luasrc/tools/ddns.lua
index 4466063cb3..ecc4131364 100644
--- a/applications/luci-app-ddns/luasrc/tools/ddns.lua
+++ b/applications/luci-app-ddns/luasrc/tools/ddns.lua
@@ -96,58 +96,6 @@ function get_pid(section)
return pid
end
--- compare versions using "<=" "<" ">" ">=" "=" "<<" ">>"
-function ipkg_ver_compare(ver1, comp, ver2)
- if not ver1 or not ver2
- or not comp or not (#comp > 0) then return nil end
- -- correct compare string
- if comp == "<>" or comp == "><" or comp == "!=" or comp == "~=" then comp = "~="
- elseif comp == "<=" or comp == "<" or comp == "=<" then comp = "<="
- elseif comp == ">=" or comp == ">" or comp == "=>" then comp = ">="
- elseif comp == "=" or comp == "==" then comp = "=="
- elseif comp == "<<" then comp = "<"
- elseif comp == ">>" then comp = ">"
- else return nil end
-
- local av1 = UTIL.split(ver1, "[%.%-]", nil, true)
- local av2 = UTIL.split(ver2, "[%.%-]", nil, true)
-
- for i = 1, math.max(table.getn(av1),table.getn(av2)), 1 do
- local s1 = av1[i] or ""
- local s2 = av2[i] or ""
-
- -- first "not equal" found return true
- if comp == "~=" and (s1 ~= s2) then return true end
- -- first "lower" found return true
- if (comp == "<" or comp == "<=") and (s1 < s2) then return true end
- -- first "greater" found return true
- if (comp == ">" or comp == ">=") and (s1 > s2) then return true end
- -- not equal then return false
- if (s1 ~= s2) then return false end
- end
-
- -- all equal and not compare greater or lower then true
- return not (comp == "<" or comp == ">")
-end
-
--- read version information for given package if installed
-function ipkg_ver_installed(pkg)
- local version = nil
- local control = io.open("/usr/lib/opkg/info/%s.control" % pkg, "r")
- if control then
- local ln
- repeat
- ln = control:read("*l")
- if ln and ln:match("^Version: ") then
- version = ln:gsub("^Version: ", "")
- break
- end
- until not ln
- control:close()
- end
- return version
-end
-
-- replacement of build-in read of UCI option
-- modified AbstractValue.cfgvalue(self, section) from cbi.lua
-- needed to read from other option then current value definition
@@ -172,24 +120,77 @@ function read_value(self, section, option)
end
end
--- replacement of build-in Flag.parse of cbi.lua
--- modified to mark section as changed if value changes
--- current parse did not do this, but it is done AbstaractValue.parse()
-function flag_parse(self, section)
- local fexists = self.map:formvalue(
- luci.cbi.FEXIST_PREFIX .. self.config .. "." .. section .. "." .. self.option)
+-- replacement of build-in parse of "Value"
+-- modified AbstractValue.parse(self, section, novld) from cbi.lua
+-- validate is called if rmempty/optional true or false
+-- before write check if forcewrite, value eq default, and more
+function value_parse(self, section, novld)
+ local fvalue = self:formvalue(section)
+ local fexist = ( fvalue and (#fvalue > 0) ) -- not "nil" and "not empty"
+ local cvalue = self:cfgvalue(section)
+ local rm_opt = ( self.rmempty or self.optional )
+ local eq_cfg -- flag: equal cfgvalue
- if fexists then
- local fvalue = self:formvalue(section) and self.enabled or self.disabled
- local cvalue = self:cfgvalue(section)
- if fvalue ~= self.default or (not self.optional and not self.rmempty) then
- self:write(section, fvalue)
- else
- self:remove(section)
+ -- If favlue and cvalue are both tables and have the same content
+ -- make them identical
+ if type(fvalue) == "table" and type(cvalue) == "table" then
+ eq_cfg = (#fvalue == #cvalue)
+ if eq_cfg then
+ for i=1, #fvalue do
+ if cvalue[i] ~= fvalue[i] then
+ eq_cfg = false
+ end
+ end
end
- if (fvalue ~= cvalue) then self.section.changed = true end
- else
- self:remove(section)
+ if eq_cfg then
+ fvalue = cvalue
+ end
+ end
+
+ -- removed parameter "section" from function call because used/accepted nowhere
+ -- also removed call to function "transfer"
+ local vvalue, errtxt = self:validate(fvalue)
+
+ -- error handling; validate return "nil"
+ if not vvalue then
+ if novld then -- and "novld" set
+ return -- then exit without raising an error
+ end
+
+ if fexist then -- and there is a formvalue
+ self:add_error(section, "invalid", errtxt)
+ return -- so data are invalid
+
+ elseif not rm_opt then -- and empty formvalue but NOT (rmempty or optional) set
+ self:add_error(section, "missing", errtxt)
+ return -- so data is missing
+ end
+ end
+ -- for whatever reason errtxt set and not handled above
+ assert( not (errtxt and (#errtxt > 0)), "unhandled validate error" )
+
+ -- lets continue with value returned from validate
+ eq_cfg = ( vvalue == cvalue ) -- update equal_config flag
+ local vexist = ( vvalue and (#vvalue > 0) ) -- not "nil" and "not empty"
+ local eq_def = ( vvalue == self.default ) -- equal_default flag
+
+ -- not forcewrite and (rmempty or optional)
+ -- and (no data or equal_default)
+ if not self.forcewrite and rm_opt
+ and (not vexist or eq_def) then
+ if self:remove(section) then -- remove data from UCI
+ self.section.changed = true -- and push events
+ end
+ return
+ end
+
+ -- not forcewrite and no changes, so nothing to write
+ if not self.forcewrite and eq_cfg then
+ return
+ end
+
+ -- write data to UCI; raise event only on changes
+ if self:write(section, vvalue) and not eq_cfg then
self.section.changed = true
end
end
diff --git a/applications/luci-app-ddns/luasrc/view/ddns/detail_logview.htm b/applications/luci-app-ddns/luasrc/view/ddns/detail_logview.htm
index 4dcb7bb6fe..fd1d5be268 100644
--- a/applications/luci-app-ddns/luasrc/view/ddns/detail_logview.htm
+++ b/applications/luci-app-ddns/luasrc/view/ddns/detail_logview.htm
@@ -6,7 +6,7 @@
var txt = document.getElementById("cbid.ddns." + section + "._logview.txt"); // TextArea
if ( !txt ) { return; } // security check
- XHR.get('<%=url('admin/services/ddns/logview')%>/' + section, null,
+ XHR.get('<%=url([[admin]], [[services]], [[ddns]], [[logview]])%>/' + section, null,
function(x) {
if (x.responseText == "_nodata_")
txt.value = "<%:File not found or empty%>";
diff --git a/applications/luci-app-ddns/luasrc/view/ddns/overview_status.htm b/applications/luci-app-ddns/luasrc/view/ddns/overview_status.htm
index b6d4ebb9fd..b409ed0728 100644
--- a/applications/luci-app-ddns/luasrc/view/ddns/overview_status.htm
+++ b/applications/luci-app-ddns/luasrc/view/ddns/overview_status.htm
@@ -19,7 +19,7 @@
var section = data[i].section // Section to handle
var cbx = document.getElementById("cbid.ddns." + section + ".enabled"); // Enabled
var btn = document.getElementById("cbid.ddns." + section + "._startstop"); // Start/Stop button
- var rip = document.getElementById("cbid.ddns." + section + "._domainIP.two"); // Registered IP
+ var rip = document.getElementById("cbid.ddns." + section + "._lookupIP.two"); // Registered IP
var lup = document.getElementById("cbid.ddns." + section + "._update.one"); // Last Update
var nup = document.getElementById("cbid.ddns." + section + "._update.two"); // Next Update
if ( !(cbx && btn && rip && lup && nup) ) { return; } // security check
@@ -76,12 +76,12 @@
break;
}
- // domain
- // (data[i].domain ignored here
+ // lookup
+ // (data[i].lookup ignored here
// registered IP
// rip.innerHTML = "Registered IP";
- if (data[i].domain == "_nodomain_")
+ if (data[i].lookup == "_nolookup_")
rip.innerHTML = '';
else if (data[i].reg_ip == "_nodata_")
rip.innerHTML = '<em><%:No data%></em>';
@@ -136,7 +136,7 @@
// do start/stop
var btnXHR = new XHR();
- btnXHR.post('<%=url('admin/services/ddns/startstop')%>/' + section + '/' + cbx.checked, { token: '<%=token%>' },
+ btnXHR.post('<%=url([[admin]], [[services]], [[ddns]], [[startstop]])%>/' + section + '/' + cbx.checked, { token: '<%=token%>' },
function(x, data) {
if (x.responseText == "_uncommitted_") {
// we need a trick to display Ampersand "&" in stead of "&#38;" or "&amp;"
@@ -155,7 +155,7 @@
}
// force to immediate show status on page load (not waiting for XHR.poll)
- XHR.get('<%=url('admin/services/ddns/status')%>', null,
+ XHR.get('<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
function(x, data) {
if (data) { _data2elements(data); }
}
@@ -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(15, '<%=url('admin/services/ddns/status')%>', null,
+ XHR.poll(5, '<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
function(x, data) {
if (data) { _data2elements(data); }
}
diff --git a/applications/luci-app-ddns/luasrc/view/ddns/system_status.htm b/applications/luci-app-ddns/luasrc/view/ddns/system_status.htm
index 06dca48a9c..5bdcb03e73 100644
--- a/applications/luci-app-ddns/luasrc/view/ddns/system_status.htm
+++ b/applications/luci-app-ddns/luasrc/view/ddns/system_status.htm
@@ -69,15 +69,15 @@
break;
}
- // domain
- if (data[j].domain == "_nodomain_")
+ // lookup
+ if (data[j].lookup == "_nolookup_")
tr.insertCell(-1).innerHTML = '<em><%:config error%></em>';
else
- tr.insertCell(-1).innerHTML = data[j].domain;
+ tr.insertCell(-1).innerHTML = data[j].lookup;
// registered IP
switch (data[j].reg_ip) {
- case "_nodomain_":
+ case "_nolookup_":
tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>';
break;
case "_nodata_":
@@ -111,13 +111,13 @@
}
// force to immediate show status (not waiting for XHR.poll)
- XHR.get('<%=url('admin/services/ddns/status')%>', null,
+ XHR.get('<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
function(x, data) {
if (data) { _data2elements(x, data); }
}
);
- XHR.poll(5, '<%=url('admin/services/ddns/status')%>', null,
+ XHR.poll(15, '<%=url([[admin]], [[services]], [[ddns]], [[status]])%>', null,
function(x, data) {
if (data) { _data2elements(x, data); }
}
@@ -132,7 +132,7 @@
<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"><%:Hostname/Domain%></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>
diff --git a/applications/luci-app-ddns/po/de/ddns.po b/applications/luci-app-ddns/po/de/ddns.po
index 6ffde5d547..e662adc780 100644
--- a/applications/luci-app-ddns/po/de/ddns.po
+++ b/applications/luci-app-ddns/po/de/ddns.po
@@ -1,15 +1,15 @@
msgid ""
msgstr ""
"Project-Id-Version: luci-app-ddns\n"
-"POT-Creation-Date: 2015-05-08 21:29+0100\n"
-"PO-Revision-Date: 2015-05-08 21:47+0100\n"
+"POT-Creation-Date: 2015-11-04 19:10-0100\n"
+"PO-Revision-Date: 2015-11-14 18:31+0100\n"
"Last-Translator: Christian Schoenebeck <christian.schoenebeck@gmail.com>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.7.5\n"
+"X-Generator: Poedit 1.8.6\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: .\n"
@@ -70,6 +70,9 @@ msgstr ""
msgid "Casual users should not change this setting"
msgstr "Standard Benutzer sollten diese Einstellung nicht ändern."
+msgid "Change provider"
+msgstr "Anbieter wechseln"
+
msgid "Check Interval"
msgstr "Prüfinterval"
@@ -125,6 +128,12 @@ msgstr "Eigenes Update-Skript"
msgid "DDNS Autostart disabled"
msgstr "DDNS Autostart deaktiviert"
+msgid "DDNS Client Configuration"
+msgstr "DDNS Client Konfiguration"
+
+msgid "DDNS Client Documentation"
+msgstr "DDNS Client Dokumentation"
+
msgid "DDNS Service provider"
msgstr "DDNS-Dienstanbieter"
@@ -196,6 +205,9 @@ msgstr ""
msgid "Disabled"
msgstr "Deaktiviert"
+msgid "Domain"
+msgstr "Domäne"
+
msgid "Dynamic DNS"
msgstr "Dynamisches DNS"
@@ -284,8 +296,10 @@ msgstr "HTTPS nicht unterstützt"
msgid "Hints"
msgstr "Hinweise"
-msgid "Hostname/Domain"
-msgstr "Rechnername/Domäne"
+msgid "Hostname/FQDN to validate, if IP update happen or necessary"
+msgstr ""
+"Hostname/FQDN um zu überprüfen, ob eine Aktualisierung stattgefunden hat "
+"oder notwendig ist"
msgid "IP address source"
msgstr "IP-Adressquelle"
@@ -385,6 +399,12 @@ msgstr "Protokoll in Datei schreiben"
msgid "Log to syslog"
msgstr "Systemprotokoll verwenden"
+msgid "Lookup Hostname"
+msgstr "Nachschlage-Hostname"
+
+msgid "NOT installed"
+msgstr "NICHT installiert"
+
msgid ""
"Neither GNU Wget with SSL nor cURL installed to select a network to use for "
"communication."
@@ -454,6 +474,21 @@ msgstr ""
msgid "On Error the script will stop execution after given number of retrys"
msgstr "Das Skript wird nach der gegebenen Anzahl von Fehlversuchen beendet."
+msgid "OpenWrt Wiki"
+msgstr "OpenWrt Wiki"
+
+msgid "Optional Encoded Parameter"
+msgstr "Optionaler codierten Parameter"
+
+msgid "Optional Parameter"
+msgstr "Optionaler Parameter"
+
+msgid "Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)"
+msgstr "Optional: Ersetzt [PARAMENC] in der Update-URL (URL-codiert)"
+
+msgid "Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)"
+msgstr "Optional: Ersetzt [PARAMENC] in der Update-URL (NICHT URL-codiert)"
+
msgid "Overview"
msgstr "Ãœbersicht"
@@ -484,17 +519,20 @@ msgstr "Prozess ID"
msgid "Read / Reread log file"
msgstr "Protokolldatei (neu) einlesen"
+msgid "Really change DDNS provider?"
+msgstr "Wirklich DDNS-Anbieter wechseln?"
+
msgid "Registered IP"
msgstr "Registrierte IP"
msgid "Replaces [DOMAIN] in Update-URL"
msgstr "Ersetzt [DOMAIN] in der Update-URL"
-msgid "Replaces [PASSWORD] in Update-URL"
-msgstr "Ersetzt [PASSWORD] in der Update-URL"
+msgid "Replaces [PASSWORD] in Update-URL (URL-encoded)"
+msgstr "Ersetzt [PASSWORD] in der Update-URL (URL-codiert)"
-msgid "Replaces [USERNAME] in Update-URL"
-msgstr "Ersetzt [USERNAME] in der Update-URL"
+msgid "Replaces [USERNAME] in Update-URL (URL-encoded)"
+msgstr "Ersetzt [USERNAME] in der Update-URL (URL-codiert)"
msgid "Run once"
msgstr "Einmalig ausführen"
@@ -528,7 +566,7 @@ msgstr ""
"Optionen."
msgid "The default setting of '0' will retry infinite."
-msgstr "Der Standard-Wert von '0' wird es endlosen erneut versuchen."
+msgstr "Beim Standard-Wert von '0' wird es endlos erneut versucht."
msgid "There is no service configured."
msgstr "Kein Dienst konfiguriert"
@@ -661,8 +699,8 @@ msgstr "Stunden"
msgid "installed"
msgstr "installiert"
-msgid "invalid - Sample"
-msgstr "ungültig - Beispiel"
+msgid "invalid FQDN / required - Sample"
+msgstr "ungültige FQDN / Pflichtfeld - Beispiel"
msgid "minimum value '0'"
msgstr "Minimum Wert '0'"
diff --git a/applications/luci-app-ddns/po/templates/ddns.pot b/applications/luci-app-ddns/po/templates/ddns.pot
index 35386802bf..7ab51dd93a 100644
--- a/applications/luci-app-ddns/po/templates/ddns.pot
+++ b/applications/luci-app-ddns/po/templates/ddns.pot
@@ -50,6 +50,9 @@ msgstr ""
msgid "Casual users should not change this setting"
msgstr ""
+msgid "Change provider"
+msgstr ""
+
msgid "Check Interval"
msgstr ""
@@ -96,6 +99,12 @@ msgstr ""
msgid "DDNS Autostart disabled"
msgstr ""
+msgid "DDNS Client Configuration"
+msgstr ""
+
+msgid "DDNS Client Documentation"
+msgstr ""
+
msgid "DDNS Service provider"
msgstr ""
@@ -149,6 +158,9 @@ msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Domain"
+msgstr ""
+
msgid "Dynamic DNS"
msgstr ""
@@ -230,7 +242,7 @@ msgstr ""
msgid "Hints"
msgstr ""
-msgid "Hostname/Domain"
+msgid "Hostname/FQDN to validate, if IP update happen or necessary"
msgstr ""
msgid "IP address source"
@@ -315,6 +327,12 @@ msgstr ""
msgid "Log to syslog"
msgstr ""
+msgid "Lookup Hostname"
+msgstr ""
+
+msgid "NOT installed"
+msgstr ""
+
msgid ""
"Neither GNU Wget with SSL nor cURL installed to select a network to use for "
"communication."
@@ -373,6 +391,21 @@ msgstr ""
msgid "On Error the script will stop execution after given number of retrys"
msgstr ""
+msgid "OpenWrt Wiki"
+msgstr ""
+
+msgid "Optional Encoded Parameter"
+msgstr ""
+
+msgid "Optional Parameter"
+msgstr ""
+
+msgid "Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)"
+msgstr ""
+
+msgid "Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)"
+msgstr ""
+
msgid "Overview"
msgstr ""
@@ -403,16 +436,19 @@ msgstr ""
msgid "Read / Reread log file"
msgstr ""
+msgid "Really change DDNS provider?"
+msgstr ""
+
msgid "Registered IP"
msgstr ""
msgid "Replaces [DOMAIN] in Update-URL"
msgstr ""
-msgid "Replaces [PASSWORD] in Update-URL"
+msgid "Replaces [PASSWORD] in Update-URL (URL-encoded)"
msgstr ""
-msgid "Replaces [USERNAME] in Update-URL"
+msgid "Replaces [USERNAME] in Update-URL (URL-encoded)"
msgstr ""
msgid "Run once"
@@ -563,7 +599,7 @@ msgstr ""
msgid "installed"
msgstr ""
-msgid "invalid - Sample"
+msgid "invalid FQDN / required - Sample"
msgstr ""
msgid "minimum value '0'"
diff --git a/applications/luci-app-privoxy/Makefile b/applications/luci-app-privoxy/Makefile
index e16eb4176e..260f840c63 100644
--- a/applications/luci-app-privoxy/Makefile
+++ b/applications/luci-app-privoxy/Makefile
@@ -10,11 +10,11 @@ PKG_NAME:=luci-app-privoxy
# Version == major.minor.patch
# increase "minor" on new functionality and "patch" on patches/optimization
-PKG_VERSION:=1.0.4
+PKG_VERSION:=1.0.5
# Release == build
# increase on changes of translation files
-PKG_RELEASE:=2
+PKG_RELEASE:=1
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Christian Schoenebeck <christian.schoenebeck@gmail.com>
diff --git a/applications/luci-app-privoxy/luasrc/model/cbi/privoxy.lua b/applications/luci-app-privoxy/luasrc/model/cbi/privoxy.lua
index c415f8e064..8ea2496173 100644
--- a/applications/luci-app-privoxy/luasrc/model/cbi/privoxy.lua
+++ b/applications/luci-app-privoxy/luasrc/model/cbi/privoxy.lua
@@ -14,7 +14,7 @@ local HELP = [[<a href="http://www.privoxy.org/user-manual/config.html#%s" targe
local VERINST = CTRL.ipkg_ver_installed("privoxy")
local VEROK = CTRL.ipkg_ver_compare(VERINST,">=",CTRL.PRIVOXY_MIN)
-local TITLE = [[</a><a href="javascript:alert(']]
+local TITLE = [[<a href="javascript:alert(']]
.. translate("Version Information")
.. [[\n\nluci-app-privoxy]]
.. [[\n\t]] .. translate("Version") .. [[:\t]]
@@ -26,6 +26,7 @@ local TITLE = [[</a><a href="javascript:alert(']]
.. [[\n\n]]
.. [[')">]]
.. translate("Privoxy WEB proxy")
+ .. [[</a>]]
local DESC = translate("Privoxy is a non-caching web proxy with advanced filtering "
.. "capabilities for enhancing privacy, modifying web page data and HTTP headers, "
diff --git a/applications/luci-app-qos/luasrc/model/cbi/qos/qos.lua b/applications/luci-app-qos/luasrc/model/cbi/qos/qos.lua
index a8ea57e311..177b17b07e 100644
--- a/applications/luci-app-qos/luasrc/model/cbi/qos/qos.lua
+++ b/applications/luci-app-qos/luasrc/model/cbi/qos/qos.lua
@@ -41,6 +41,16 @@ t:value("Priority", translate("priority"))
t:value("Express", translate("express"))
t:value("Normal", translate("normal"))
t:value("Bulk", translate("low"))
+
+local uci = require "luci.model.uci"
+uci.cursor():foreach("qos", "class",
+ function (section)
+ local n = section[".name"]
+ if string.sub(n,-string.len("_down"))~="_down" then
+ t:value(n)
+ end
+ end)
+
t.default = "Normal"
srch = s:option(Value, "srchost", translate("Source host"))
diff --git a/applications/luci-app-radicale/Makefile b/applications/luci-app-radicale/Makefile
index 960618dbac..1501d4f0e8 100644
--- a/applications/luci-app-radicale/Makefile
+++ b/applications/luci-app-radicale/Makefile
@@ -10,7 +10,7 @@ PKG_NAME:=luci-app-radicale
# Version == major.minor.patch
# increase "minor" on new functionality and "patch" on patches/optimization
-PKG_VERSION:=1.0.1
+PKG_VERSION:=1.0.2
# Release == build
# increase on changes of translation files
diff --git a/applications/luci-app-radicale/luasrc/controller/radicale.lua b/applications/luci-app-radicale/luasrc/controller/radicale.lua
index 35f5a83a0c..10ec1fe545 100644
--- a/applications/luci-app-radicale/luasrc/controller/radicale.lua
+++ b/applications/luci-app-radicale/luasrc/controller/radicale.lua
@@ -82,7 +82,7 @@ function service_ok()
end
function app_title_main()
- return [[</a><a href="javascript:alert(']]
+ return [[<a href="javascript:alert(']]
.. I18N.translate("Version Information")
.. [[\n\n]] .. luci_app_name()
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
@@ -100,12 +100,14 @@ function app_title_main()
.. [[\n\n]]
.. [[')">]]
.. I18N.translate("Radicale CalDAV/CardDAV Server")
+ .. [[</a>]]
end
function app_title_back()
- return [[</a><a href="]]
+ return [[<a href="]]
.. DISP.build_url("admin", "services", "radicale")
.. [[">]]
.. I18N.translate("Radicale CalDAV/CardDAV Server")
+ .. [[</a>]]
end
function app_description()
return I18N.translate("The Radicale Project is a complete CalDAV (calendar) and CardDAV (contact) server solution.") .. [[<br />]]
diff --git a/contrib/package/freifunk-common/files/usr/bin/neigh.sh b/contrib/package/freifunk-common/files/usr/bin/neigh.sh
index cf4342450c..b1dc01a77e 100755
--- a/contrib/package/freifunk-common/files/usr/bin/neigh.sh
+++ b/contrib/package/freifunk-common/files/usr/bin/neigh.sh
@@ -2,9 +2,69 @@
. /usr/share/libubox/jshn.sh
-VARS="localIP:Local remoteIP:Remote validityTime:vTime linkQuality:LQ neighborLinkQuality:NLQ linkCost:Cost"
+hostsfile_getname()
+{
+ local config="$1"
+ local i=0
+ local value file
-for HOST in 127.0.0.1 ::1;do
+ while value="$( uci -q get $config.@LoadPlugin[$i].library )"; do {
+ case "$value" in
+ 'olsrd_nameservice.so.'*)
+ file="$( uci -q get $config.@LoadPlugin[$i].hosts_file )"
+ break
+ ;;
+ esac
+
+ i=$(( i + 1 ))
+ } done
+
+ echo "${file:-/var/run/hosts_olsr}"
+}
+
+read_hostnames()
+{
+ local file_list=" $( hostsfile_getname 'olsrd' ) $(hostsfile_getname 'olsrd6' ) "
+ local line ip hostname file file_list_uniq
+
+ for file in $file_list; do {
+ case " $file_list_uniq " in
+ *" $file "*)
+ ;;
+ *)
+ file_list_uniq="$file_list_uniq $file"
+ ;;
+ esac
+ } done
+
+ for file in $file_list_uniq; do {
+ [ -e "$file" ] || continue
+
+ while read -r line; do {
+ case "$line" in
+ [0-9]*)
+ # 2001:bf7:820:901::1 stuttgarter-core.olsr # myself
+ # 10.63.160.161 AlexLaterne # 10.63.160.161
+ set -f
+ set +f -- $line
+ ip="$1"
+ hostname="$2"
+
+ # global vars, e.g.
+ # IP_1_2_3_4='foo' or IP_2001_bf7_820_901__1='bar'
+ eval IP_${ip//[.:]/_}="$hostname"
+ ;;
+ esac
+ } done <"$file"
+ } done
+}
+
+read_hostnames
+
+VARS='localIP:Local remoteIP:Remote validityTime:vTime linkQuality:LQ'
+VARS="$VARS neighborLinkQuality:NLQ linkCost:Cost remoteHostname:Host"
+
+for HOST in '127.0.0.1' '::1';do
json_init
json_load "$(echo /links|nc ${HOST} 9090)"
if json_is_a links array;then
@@ -29,6 +89,7 @@ for HOST in 127.0.0.1 ::1;do
;;*)
for v in ${VARS};do
eval printf \"%-\${_${v%:*}}s \" \$${v%:*}
+ eval remoteHostname="\$IP_${remoteIP//[.:]/_}"
done
echo
;;esac
diff --git a/contrib/package/freifunk-policyrouting/files/etc/rc.d/S15-freifunk-policyrouting b/contrib/package/freifunk-policyrouting/files/etc/rc.d/S15-freifunk-policyrouting
deleted file mode 120000
index 3c3dad87d1..0000000000
--- a/contrib/package/freifunk-policyrouting/files/etc/rc.d/S15-freifunk-policyrouting
+++ /dev/null
@@ -1 +0,0 @@
-../init.d/freifunk-policyrouting \ No newline at end of file
diff --git a/documentation/api/modules/luci.model.uci.html b/documentation/api/modules/luci.model.uci.html
index 9e50d9900d..cf75aebccb 100644
--- a/documentation/api/modules/luci.model.uci.html
+++ b/documentation/api/modules/luci.model.uci.html
@@ -1119,6 +1119,12 @@ Name of created section
Set a value or create a named section.
+
+When invoked with three arguments <code>config</code>, <code>sectionname</code>, <code>sectiontype</code>,
+then a named section of the given type is created.
+
+When invoked with four arguments <code>config</code>, <code>sectionname</code>, <code>optionname</code> and
+<code>optionvalue</code> then the value of the specified option is set to the given value.
@@ -1138,7 +1144,7 @@ Set a value or create a named section.
</li>
<li>
- value: UCI value or nil if you want to create a section
+ value: UCI value or nothing if you want to create a section
</li>
</ul>
diff --git a/modules/luci-base/Makefile b/modules/luci-base/Makefile
index 54506b023a..26cbe0820e 100644
--- a/modules/luci-base/Makefile
+++ b/modules/luci-base/Makefile
@@ -12,7 +12,7 @@ LUCI_TYPE:=mod
LUCI_BASENAME:=base
LUCI_TITLE:=LuCI core libraries
-LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua
+LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua +luci-lib-jsonc
PKG_SOURCE:=LuaSrcDiet-0.12.1.tar.bz2
PKG_SOURCE_URL:=https://luasrcdiet.googlecode.com/files
diff --git a/modules/luci-base/luasrc/http.lua b/modules/luci-base/luasrc/http.lua
index a92d8affb6..4b35731727 100644
--- a/modules/luci-base/luasrc/http.lua
+++ b/modules/luci-base/luasrc/http.lua
@@ -208,6 +208,7 @@ function splice(fd, size)
end
function redirect(url)
+ if url == "" then url = "/" end
status(302, "Found")
header("Location", url)
close()
diff --git a/modules/luci-base/luasrc/model/network.lua b/modules/luci-base/luasrc/model/network.lua
index 20e1032760..81fc416fed 100644
--- a/modules/luci-base/luasrc/model/network.lua
+++ b/modules/luci-base/luasrc/model/network.lua
@@ -1,8 +1,8 @@
-- Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
-local type, next, pairs, ipairs, loadfile, table
- = type, next, pairs, ipairs, loadfile, table
+local type, next, pairs, ipairs, loadfile, table, select
+ = type, next, pairs, ipairs, loadfile, table, select
local tonumber, tostring, math = tonumber, tostring, math
@@ -16,6 +16,7 @@ local utl = require "luci.util"
local dsp = require "luci.dispatcher"
local uci = require "luci.model.uci"
local lng = require "luci.i18n"
+local jsc = require "luci.jsonc"
module "luci.model.network"
@@ -31,10 +32,10 @@ local _protocols = { }
local _interfaces, _bridge, _switch, _tunnel
local _ubusnetcache, _ubusdevcache, _ubuswificache
-local _uci_real, _uci_state
+local _uci
function _filter(c, s, o, r)
- local val = _uci_real:get(c, s, o)
+ local val = _uci:get(c, s, o)
if val then
local l = { }
if type(val) == "string" then
@@ -44,9 +45,9 @@ function _filter(c, s, o, r)
end
end
if #l > 0 then
- _uci_real:set(c, s, o, table.concat(l, " "))
+ _uci:set(c, s, o, table.concat(l, " "))
else
- _uci_real:delete(c, s, o)
+ _uci:delete(c, s, o)
end
elseif type(val) == "table" then
for _, val in ipairs(val) do
@@ -55,16 +56,16 @@ function _filter(c, s, o, r)
end
end
if #l > 0 then
- _uci_real:set(c, s, o, l)
+ _uci:set(c, s, o, l)
else
- _uci_real:delete(c, s, o)
+ _uci:delete(c, s, o)
end
end
end
end
function _append(c, s, o, a)
- local val = _uci_real:get(c, s, o) or ""
+ local val = _uci:get(c, s, o) or ""
if type(val) == "string" then
local l = { }
for val in val:gmatch("%S+") do
@@ -73,7 +74,7 @@ function _append(c, s, o, a)
end
end
l[#l+1] = a
- _uci_real:set(c, s, o, table.concat(l, " "))
+ _uci:set(c, s, o, table.concat(l, " "))
elseif type(val) == "table" then
local l = { }
for _, val in ipairs(val) do
@@ -82,7 +83,7 @@ function _append(c, s, o, a)
end
end
l[#l+1] = a
- _uci_real:set(c, s, o, l)
+ _uci:set(c, s, o, l)
end
end
@@ -95,15 +96,15 @@ function _stror(s1, s2)
end
function _get(c, s, o)
- return _uci_real:get(c, s, o)
+ return _uci:get(c, s, o)
end
function _set(c, s, o, v)
if v ~= nil then
if type(v) == "boolean" then v = v and "1" or "0" end
- return _uci_real:set(c, s, o, v)
+ return _uci:set(c, s, o, v)
else
- return _uci_real:delete(c, s, o)
+ return _uci:delete(c, s, o)
end
end
@@ -127,7 +128,7 @@ function _wifi_state(key, val, field)
for radio, radiostate in pairs(_ubuswificache) do
for ifc, ifcstate in pairs(radiostate.interfaces) do
if ifcstate.section and ifcstate.section:sub(1, 1) == '@' then
- local s = _uci_real:get_all('wireless.%s' % ifcstate.section)
+ local s = _uci:get_all('wireless.%s' % ifcstate.section)
if s then
ifcstate.section = s['.name']
end
@@ -153,7 +154,7 @@ function _wifi_lookup(ifn)
local num = 0
ifnidx = tonumber(ifnidx)
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device == radio then
num = num + 1
@@ -166,20 +167,9 @@ function _wifi_lookup(ifn)
return sid
- -- looks like wifi, try to locate the section via state vars
+ -- looks like wifi, try to locate the section via ubus state
elseif _wifi_iface(ifn) then
- local sid = _wifi_state("ifname", ifn, "section")
- if not sid then
- _uci_state:foreach("wireless", "wifi-iface",
- function(s)
- if s.ifname == ifn then
- sid = s['.name']
- return false
- end
- end)
- end
-
- return sid
+ return _wifi_state("ifname", ifn, "section")
end
end
@@ -205,8 +195,7 @@ end
function init(cursor)
- _uci_real = cursor or _uci_real or uci.cursor()
- _uci_state = _uci_real:substate()
+ _uci = cursor or _uci or uci.cursor()
_interfaces = { }
_bridge = { }
@@ -281,13 +270,13 @@ function init(cursor)
end
function save(self, ...)
- _uci_real:save(...)
- _uci_real:load(...)
+ _uci:save(...)
+ _uci:load(...)
end
function commit(self, ...)
- _uci_real:commit(...)
- _uci_real:load(...)
+ _uci:commit(...)
+ _uci:load(...)
end
function ifnameof(self, x)
@@ -345,7 +334,7 @@ end
function add_network(self, n, options)
local oldnet = self:get_network(n)
if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
- if _uci_real:section("network", "interface", n, options) then
+ if _uci:section("network", "interface", n, options) then
return network(n)
end
elseif oldnet and oldnet:is_empty() then
@@ -360,7 +349,7 @@ function add_network(self, n, options)
end
function get_network(self, n)
- if n and _uci_real:get("network", n) == "interface" then
+ if n and _uci:get("network", n) == "interface" then
return network(n)
end
end
@@ -369,7 +358,7 @@ function get_networks(self)
local nets = { }
local nls = { }
- _uci_real:foreach("network", "interface",
+ _uci:foreach("network", "interface",
function(s)
nls[s['.name']] = network(s['.name'])
end)
@@ -383,18 +372,18 @@ function get_networks(self)
end
function del_network(self, n)
- local r = _uci_real:delete("network", n)
+ local r = _uci:delete("network", n)
if r then
- _uci_real:delete_all("network", "alias",
+ _uci:delete_all("network", "alias",
function(s) return (s.interface == n) end)
- _uci_real:delete_all("network", "route",
+ _uci:delete_all("network", "route",
function(s) return (s.interface == n) end)
- _uci_real:delete_all("network", "route6",
+ _uci:delete_all("network", "route6",
function(s) return (s.interface == n) end)
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
local net
local rest = { }
@@ -404,10 +393,10 @@ function del_network(self, n)
end
end
if #rest > 0 then
- _uci_real:set("wireless", s['.name'], "network",
+ _uci:set("wireless", s['.name'], "network",
table.concat(rest, " "))
else
- _uci_real:delete("wireless", s['.name'], "network")
+ _uci:delete("wireless", s['.name'], "network")
end
end)
end
@@ -417,31 +406,31 @@ end
function rename_network(self, old, new)
local r
if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
- r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
+ r = _uci:section("network", "interface", new, _uci:get_all("network", old))
if r then
- _uci_real:foreach("network", "alias",
+ _uci:foreach("network", "alias",
function(s)
if s.interface == old then
- _uci_real:set("network", s['.name'], "interface", new)
+ _uci:set("network", s['.name'], "interface", new)
end
end)
- _uci_real:foreach("network", "route",
+ _uci:foreach("network", "route",
function(s)
if s.interface == old then
- _uci_real:set("network", s['.name'], "interface", new)
+ _uci:set("network", s['.name'], "interface", new)
end
end)
- _uci_real:foreach("network", "route6",
+ _uci:foreach("network", "route6",
function(s)
if s.interface == old then
- _uci_real:set("network", s['.name'], "interface", new)
+ _uci:set("network", s['.name'], "interface", new)
end
end)
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
local net
local list = { }
@@ -453,12 +442,12 @@ function rename_network(self, old, new)
end
end
if #list > 0 then
- _uci_real:set("wireless", s['.name'], "network",
+ _uci:set("wireless", s['.name'], "network",
table.concat(list, " "))
end
end)
- _uci_real:delete("network", old)
+ _uci:delete("network", old)
end
end
return r or false
@@ -470,7 +459,7 @@ function get_interface(self, i)
else
local ifc
local num = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
@@ -485,6 +474,21 @@ function get_interface(self, i)
end
end
+local function swdev_from_board_json()
+ local boardinfo = jsc.parse(nfs.readfile("/etc/board.json") or "")
+ if type(boardinfo) == "table" and type(boardinfo.network) == "table" then
+ local net, val
+ for net, val in pairs(boardinfo.network) do
+ if type(val) == "table" and type(val.ifname) == "string" and
+ val.create_vlan == true
+ then
+ return val.ifname
+ end
+ end
+ end
+ return nil
+end
+
function get_interfaces(self)
local iface
local ifaces = { }
@@ -493,7 +497,7 @@ function get_interfaces(self)
local baseof = { }
-- find normal interfaces
- _uci_real:foreach("network", "interface",
+ _uci:foreach("network", "interface",
function(s)
for iface in utl.imatch(s.ifname) do
if not _iface_ignore(iface) and not _wifi_iface(iface) then
@@ -510,7 +514,7 @@ function get_interfaces(self)
end
-- find vlan interfaces
- _uci_real:foreach("network", "switch_vlan",
+ _uci:foreach("network", "switch_vlan",
function(s)
if not s.device then
return
@@ -526,7 +530,7 @@ function get_interfaces(self)
end
end
if not base or not base:match("^eth%d") then
- base = "eth0"
+ base = swdev_from_board_json() or "eth0"
end
else
base = s.device
@@ -551,7 +555,7 @@ function get_interfaces(self)
-- find wifi interfaces
local num = { }
local wfs = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
@@ -572,7 +576,7 @@ function ignore_interface(self, x)
end
function get_wifidev(self, dev)
- if _uci_real:get("wireless", dev) == "wifi-device" then
+ if _uci:get("wireless", dev) == "wifi-device" then
return wifidev(dev)
end
end
@@ -581,7 +585,7 @@ function get_wifidevs(self)
local devs = { }
local wfd = { }
- _uci_real:foreach("wireless", "wifi-device",
+ _uci:foreach("wireless", "wifi-device",
function(s) wfd[#wfd+1] = s['.name'] end)
local dev
@@ -601,9 +605,9 @@ end
function add_wifinet(self, net, options)
if type(options) == "table" and options.device and
- _uci_real:get("wireless", options.device) == "wifi-device"
+ _uci:get("wireless", options.device) == "wifi-device"
then
- local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
+ local wnet = _uci:section("wireless", "wifi-iface", nil, options)
return wifinet(wnet)
end
end
@@ -611,7 +615,7 @@ end
function del_wifinet(self, net)
local wnet = _wifi_lookup(net)
if wnet then
- _uci_real:delete("wireless", wnet)
+ _uci:delete("wireless", wnet)
return true
end
return false
@@ -684,7 +688,7 @@ end
function network(name, proto)
if name then
- local p = proto or _uci_real:get("network", name, "proto")
+ local p = proto or _uci:get("network", name, "proto")
local c = p and _protocols[p] or protocol
return c(name)
end
@@ -695,7 +699,7 @@ function protocol.__init__(self, name)
end
function protocol._get(self, opt)
- local v = _uci_real:get("network", self.sid, opt)
+ local v = _uci:get("network", self.sid, opt)
if type(v) == "table" then
return table.concat(v, " ")
end
@@ -730,7 +734,7 @@ function protocol.ifname(self)
end
if not ifname then
local num = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device]
@@ -779,17 +783,21 @@ function protocol.uptime(self)
end
function protocol.expires(self)
- local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
- local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
- if a and l then
- l = l - (nxo.sysinfo().uptime - a)
- return l > 0 and l or 0
+ local u = self:_ubus("uptime")
+ local d = self:_ubus("data")
+
+ if type(u) == "number" and type(d) == "table" and
+ type(d.leasetime) == "number"
+ then
+ local r = (d.leasetime - (u % d.leasetime))
+ return r > 0 and r or 0
end
+
return -1
end
function protocol.metric(self)
- return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
+ return self:_ubus("metric") or 0
end
function protocol.ipaddr(self)
@@ -797,6 +805,20 @@ function protocol.ipaddr(self)
return addrs and #addrs > 0 and addrs[1].address
end
+function protocol.ipaddrs(self)
+ local addrs = self:_ubus("ipv4-address")
+ local rv = { }
+
+ if type(addrs) == "table" then
+ local n, addr
+ for n, addr in ipairs(addrs) do
+ rv[#rv+1] = "%s/%d" %{ addr.address, addr.mask }
+ end
+ end
+
+ return rv
+end
+
function protocol.netmask(self)
local addrs = self:_ubus("ipv4-address")
return addrs and #addrs > 0 and
@@ -835,6 +857,28 @@ function protocol.ip6addr(self)
end
end
+function protocol.ip6addrs(self)
+ local addrs = self:_ubus("ipv6-address")
+ local rv = { }
+ local n, addr
+
+ if type(addrs) == "table" then
+ for n, addr in ipairs(addrs) do
+ rv[#rv+1] = "%s/%d" %{ addr.address, addr.mask }
+ end
+ end
+
+ addrs = self:_ubus("ipv6-prefix-assignment")
+
+ if type(addrs) == "table" then
+ for n, addr in ipairs(addrs) do
+ rv[#rv+1] = "%s1/%d" %{ addr.address, addr.mask }
+ end
+ end
+
+ return rv
+end
+
function protocol.gw6addr(self)
local _, route
for _, route in ipairs(self:_ubus("route") or { }) do
@@ -885,7 +929,7 @@ function protocol.is_empty(self)
rv = false
end
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
local n
for n in utl.imatch(s.network) do
@@ -937,12 +981,12 @@ function protocol.get_interface(self)
else
local ifn = nil
local num = { }
- for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
+ for ifn in utl.imatch(_uci:get("network", self.sid, "ifname")) do
ifn = ifn:match("^[^:/]+")
return ifn and interface(ifn, self)
end
ifn = nil
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
@@ -977,7 +1021,7 @@ function protocol.get_interfaces(self)
local num = { }
local wfs = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
@@ -1020,7 +1064,7 @@ function protocol.contains_interface(self, ifname)
local wif = _wifi_lookup(ifname)
if wif then
local n
- for n in utl.imatch(_uci_real:get("wireless", wif, "network")) do
+ for n in utl.imatch(_uci:get("wireless", wif, "network")) do
if n == self.sid then
return true
end
@@ -1066,7 +1110,8 @@ function interface.name(self)
end
function interface.mac(self)
- return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
+ local mac = self:_ubus("macaddr")
+ return mac and mac:upper()
end
function interface.ipaddrs(self)
@@ -1278,22 +1323,11 @@ function wifidev.is_up(self)
return (_ubuswificache[self.sid].up == true)
end
- local up = false
- _uci_state:foreach("wireless", "wifi-iface",
- function(s)
- if s.device == self.sid then
- if s.up == "1" then
- up = true
- return false
- end
- end
- end)
-
- return up
+ return false
end
function wifidev.get_wifinet(self, net)
- if _uci_real:get("wireless", net) == "wifi-iface" then
+ if _uci:get("wireless", net) == "wifi-iface" then
return wifinet(net)
else
local wnet = _wifi_lookup(net)
@@ -1306,7 +1340,7 @@ end
function wifidev.get_wifinets(self)
local nets = { }
- _uci_real:foreach("wireless", "wifi-iface",
+ _uci:foreach("wireless", "wifi-iface",
function(s)
if s.device == self.sid then
nets[#nets+1] = wifinet(s['.name'])
@@ -1320,7 +1354,7 @@ function wifidev.add_wifinet(self, options)
options = options or { }
options.device = self.sid
- local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
+ local wnet = _uci:section("wireless", "wifi-iface", nil, options)
if wnet then
return wifinet(wnet, options)
end
@@ -1329,12 +1363,12 @@ end
function wifidev.del_wifinet(self, net)
if utl.instanceof(net, wifinet) then
net = net.sid
- elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
+ elseif _uci:get("wireless", net) ~= "wifi-iface" then
net = _wifi_lookup(net)
end
- if net and _uci_real:get("wireless", net, "device") == self.sid then
- _uci_real:delete("wireless", net)
+ if net and _uci:get("wireless", net, "device") == self.sid then
+ _uci:delete("wireless", net)
return true
end
@@ -1347,26 +1381,58 @@ wifinet = utl.class()
function wifinet.__init__(self, net, data)
self.sid = net
+ local n = 0
local num = { }
- local netid
- _uci_real:foreach("wireless", "wifi-iface",
+ local netid, sid
+ _uci:foreach("wireless", "wifi-iface",
function(s)
+ n = n + 1
if s.device then
num[s.device] = num[s.device] and num[s.device] + 1 or 1
if s['.name'] == self.sid then
+ sid = "@wifi-iface[%d]" % n
netid = "%s.network%d" %{ s.device, num[s.device] }
return false
end
end
end)
+ if sid then
+ local _, k, r, i
+ for k, r in pairs(_ubuswificache) do
+ if type(r) == "table" and
+ type(r.interfaces) == "table"
+ then
+ for _, i in ipairs(r.interfaces) do
+ if type(i) == "table" and i.section == sid then
+ self._ubusdata = {
+ radio = k,
+ dev = r,
+ net = i
+ }
+ end
+ end
+ end
+ end
+ end
+
local dev = _wifi_state("section", self.sid, "ifname") or netid
self.netid = netid
self.wdev = dev
self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
- self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
- _uci_real:get_all("wireless", self.sid) or { }
+end
+
+function wifinet.ubus(self, ...)
+ local n, v = self._ubusdata
+ for n = 1, select('#', ...) do
+ if type(v) == "table" then
+ v = v[select(n, ...)]
+ else
+ return nil
+ end
+ end
+ return v
end
function wifinet.get(self, opt)
@@ -1378,19 +1444,23 @@ function wifinet.set(self, opt, val)
end
function wifinet.mode(self)
- return _uci_state:get("wireless", self.sid, "mode") or "ap"
+ return self:ubus("net", "config", "mode") or self:get("mode") or "ap"
end
function wifinet.ssid(self)
- return _uci_state:get("wireless", self.sid, "ssid")
+ return self:ubus("net", "config", "ssid") or self:get("ssid")
end
function wifinet.bssid(self)
- return _uci_state:get("wireless", self.sid, "bssid")
+ return self:ubus("net", "config", "bssid") or self:get("bssid")
end
function wifinet.network(self)
- return _uci_state:get("wifinet", self.sid, "network")
+ local net, networks = nil, { }
+ for net in utl.imatch(self:ubus("net", "config", "network") or self:get("network")) do
+ networks[#networks+1] = net
+ end
+ return networks
end
function wifinet.id(self)
@@ -1402,7 +1472,7 @@ function wifinet.name(self)
end
function wifinet.ifname(self)
- local ifname = self.iwinfo.ifname
+ local ifname = self:ubus("net", "ifname") or self.iwinfo.ifname
if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
ifname = self.wdev
end
@@ -1410,9 +1480,8 @@ function wifinet.ifname(self)
end
function wifinet.get_device(self)
- if self.iwdata.device then
- return wifidev(self.iwdata.device)
- end
+ local dev = self:ubus("radio") or self:get("device")
+ return dev and wifidev(dev) or nil
end
function wifinet.is_up(self)
@@ -1421,7 +1490,7 @@ function wifinet.is_up(self)
end
function wifinet.active_mode(self)
- local m = _stror(self.iwdata.mode, self.iwinfo.mode) or "ap"
+ local m = self.iwinfo.mode or self:ubus("net", "config", "mode") or self:get("mode") or "ap"
if m == "ap" then m = "Master"
elseif m == "sta" then m = "Client"
@@ -1438,11 +1507,11 @@ function wifinet.active_mode_i18n(self)
end
function wifinet.active_ssid(self)
- return _stror(self.iwdata.ssid, self.iwinfo.ssid)
+ return self.iwinfo.ssid or self:ubus("net", "config", "ssid") or self:get("ssid")
end
function wifinet.active_bssid(self)
- return _stror(self.iwdata.bssid, self.iwinfo.bssid) or "00:00:00:00:00:00"
+ return self.iwinfo.bssid or self:ubus("net", "config", "bssid") or self:get("bssid")
end
function wifinet.active_encryption(self)
@@ -1469,8 +1538,8 @@ function wifinet.bitrate(self)
end
function wifinet.channel(self)
- return self.iwinfo.channel or
- tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
+ return self.iwinfo.channel or self:ubus("dev", "config", "channel") or
+ tonumber(self:get("channel"))
end
function wifinet.signal(self)
@@ -1482,7 +1551,7 @@ function wifinet.noise(self)
end
function wifinet.country(self)
- return self.iwinfo.country or "00"
+ return self.iwinfo.country or self:ubus("dev", "config", "country") or "00"
end
function wifinet.txpower(self)
@@ -1548,8 +1617,8 @@ end
function wifinet.get_networks(self)
local nets = { }
local net
- for net in utl.imatch(tostring(self.iwdata.network)) do
- if _uci_real:get("network", net) == "interface" then
+ for net in utl.imatch(self:ubus("net", "config", "network") or self:get("network")) do
+ if _uci:get("network", net) == "interface" then
nets[#nets+1] = network(net)
end
end
diff --git a/modules/luci-base/luasrc/model/uci.luadoc b/modules/luci-base/luasrc/model/uci.luadoc
index 80464f7cec..7591b68b02 100644
--- a/modules/luci-base/luasrc/model/uci.luadoc
+++ b/modules/luci-base/luasrc/model/uci.luadoc
@@ -235,12 +235,18 @@ Saves changes made to a config to make them committable.
---[[
Set a value or create a named section.
+When invoked with three arguments `config`, `sectionname`, `sectiontype`,
+then a named section of the given type is created.
+
+When invoked with four arguments `config`, `sectionname`, `optionname` and
+`optionvalue` then the value of the specified option is set to the given value.
+
@class function
@name Cursor.set
@param config UCI config
@param section UCI section name
@param option UCI option or UCI section type
-@param value UCI value or nil if you want to create a section
+@param value UCI value or nothing if you want to create a section
@return Boolean whether operation succeeded
]]
diff --git a/modules/luci-base/luasrc/util.lua b/modules/luci-base/luasrc/util.lua
index dcf8230b3e..787bc66f90 100644
--- a/modules/luci-base/luasrc/util.lua
+++ b/modules/luci-base/luasrc/util.lua
@@ -9,6 +9,7 @@ local ldebug = require "luci.debug"
local string = require "string"
local coroutine = require "coroutine"
local tparser = require "luci.template.parser"
+local json = require "luci.jsonc"
local _ubus = require "ubus"
local _ubus_connection = nil
@@ -600,55 +601,11 @@ function ubus(object, method, data)
end
function serialize_json(x, cb)
- local rv, push = nil, cb
- if not push then
- rv = { }
- push = function(tok) rv[#rv+1] = tok end
- end
-
- if x == nil then
- push("null")
- elseif type(x) == "table" then
- -- test if table is array like
- local k, v
- local n1, n2 = 0, 0
- for k in pairs(x) do n1 = n1 + 1 end
- for k in ipairs(x) do n2 = n2 + 1 end
-
- if n1 == n2 and n1 > 0 then
- push("[")
- for k = 1, n2 do
- if k > 1 then
- push(",")
- end
- serialize_json(x[k], push)
- end
- push("]")
- else
- push("{")
- for k, v in pairs(x) do
- push("%q:" % tostring(k))
- serialize_json(v, push)
- if next(x, k) then
- push(",")
- end
- end
- push("}")
- end
- elseif type(x) == "number" or type(x) == "boolean" then
- if (x ~= x) then
- -- NaN is the only value that doesn't equal to itself.
- push("Number.NaN")
- else
- push(tostring(x))
- end
+ local js = json.stringify(x)
+ if type(cb) == "function" then
+ cb(js)
else
- push('"%s"' % tostring(x):gsub('["%z\1-\31\\]',
- function(c) return '\\u%04x' % c:byte(1) end))
- end
-
- if not cb then
- return table.concat(rv, "")
+ return js
end
end
diff --git a/modules/luci-mod-admin-full/luasrc/controller/admin/network.lua b/modules/luci-mod-admin-full/luasrc/controller/admin/network.lua
index 879e54b249..aa533cb70b 100644
--- a/modules/luci-mod-admin-full/luasrc/controller/admin/network.lua
+++ b/modules/luci-mod-admin-full/luasrc/controller/admin/network.lua
@@ -235,6 +235,8 @@ function iface_status(ifaces)
proto = net:proto(),
uptime = net:uptime(),
gwaddr = net:gwaddr(),
+ ipaddrs = net:ipaddrs(),
+ ip6addrs = net:ip6addrs(),
dnsaddrs = net:dnsaddrs(),
name = device:shortname(),
type = device:type(),
@@ -246,29 +248,9 @@ function iface_status(ifaces)
rx_packets = device:rx_packets(),
tx_packets = device:tx_packets(),
- ipaddrs = { },
- ip6addrs = { },
subdevices = { }
}
- local _, a
- for _, a in ipairs(device:ipaddrs()) do
- data.ipaddrs[#data.ipaddrs+1] = {
- addr = a:host():string(),
- netmask = a:mask():string(),
- prefix = a:prefix()
- }
- end
- for _, a in ipairs(device:ip6addrs()) do
- if not a:is6linklocal() then
- data.ip6addrs[#data.ip6addrs+1] = {
- addr = a:host():string(),
- netmask = a:mask():string(),
- prefix = a:prefix()
- }
- end
- end
-
for _, device in ipairs(net:get_interfaces() or {}) do
data.subdevices[#data.subdevices+1] = {
name = device:shortname(),
diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/iface_add.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/iface_add.lua
index da1e140de0..e48e3b4bdf 100644
--- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/iface_add.lua
+++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/iface_add.lua
@@ -17,7 +17,12 @@ newnet = m:field(Value, "_netname", translate("Name of the new interface"),
newnet:depends("_attach", "")
newnet.default = arg[1] and "net_" .. arg[1]:gsub("[^%w_]+", "_")
-newnet.datatype = "uciname"
+newnet.datatype = "and(uciname,maxlength(15))"
+
+advice = m:field(DummyValue, "d1", translate("Note: interface name length"),
+ translate("Maximum length of the name is 15 characters including " ..
+ "the automatic protocol/bridge prefix (br-, 6in4-, pppoe- etc.)"
+ ))
newproto = m:field(ListValue, "_netproto", translate("Protocol of the new interface"))
diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua
index 40f8014f1a..ce3c3ef325 100644
--- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua
+++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua
@@ -107,6 +107,12 @@ m.uci:foreach("network", "switch",
local sp = s:option(ListValue, "mirror_source_port", translate("Mirror source port"))
local mp = s:option(ListValue, "mirror_monitor_port", translate("Mirror monitor port"))
+ sp:depends("enable_mirror_tx", "1")
+ sp:depends("enable_mirror_rx", "1")
+
+ mp:depends("enable_mirror_tx", "1")
+ mp:depends("enable_mirror_rx", "1")
+
local pt
for pt = 0, num_ports - 1 do
local name
diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua
index 9a2bd5d201..b91c29b088 100644
--- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua
+++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua
@@ -361,7 +361,8 @@ s:tab("encryption", translate("Wireless Security"))
s:tab("macfilter", translate("MAC-Filter"))
s:tab("advanced", translate("Advanced Settings"))
-s:taboption("general", Value, "ssid", translate("<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
+ssid = s:taboption("general", Value, "ssid", translate("<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
+ssid.datatype = "maxlength(32)"
mode = s:taboption("general", ListValue, "mode", translate("Mode"))
mode.override_values = true
diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab/mount.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab/mount.lua
index 2652e00f25..f5751673fd 100644
--- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab/mount.lua
+++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab/mount.lua
@@ -112,7 +112,7 @@ o.default = [[
mkdir -p /tmp/extroot
mount --bind / /tmp/introot
mount /dev/sda1 /tmp/extroot
-tar -C /tmp/intproot -cvf - . | tar -C /tmp/extroot -xf -
+tar -C /tmp/introot -cvf - . | tar -C /tmp/extroot -xf -
umount /tmp/introot
umount /tmp/extroot</pre>
]] %{
diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm b/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm
index 9a77f89106..b222cbca18 100644
--- a/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm
+++ b/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm
@@ -135,7 +135,7 @@
html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
}
- if (ifc.type != 'tunnel')
+ if (ifc.macaddr)
{
html += String.format('<strong><%:MAC-Address%>:</strong> %s<br />', ifc.macaddr);
}
@@ -153,10 +153,9 @@
for (var i = 0; i < ifc.ipaddrs.length; i++)
html += String.format(
- '%s%s/%d',
+ '%s%s',
i ? ', ' : '',
- ifc.ipaddrs[i].addr,
- ifc.ipaddrs[i].prefix
+ ifc.ipaddrs[i]
);
html += '<br />';
@@ -168,10 +167,9 @@
for (var i = 0; i < ifc.ip6addrs.length; i++)
html += String.format(
- '%s%s/%d',
+ '%s%s',
i ? ', ' : '',
- ifc.ip6addrs[i].addr.toUpperCase(),
- ifc.ip6addrs[i].prefix
+ ifc.ip6addrs[i].toUpperCase()
);
html += '<br />';
@@ -250,7 +248,7 @@
<input type="button" class="cbi-button cbi-button-reload" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', true)" title="<%:Reconnect this interface%>" value="<%:Connect%>" />
<input type="button" class="cbi-button cbi-button-reset" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', false)" title="<%:Shutdown this interface%>" value="<%:Stop%>" />
<input type="button" class="cbi-button cbi-button-edit" style="width:100px" onclick="location.href='<%=url("admin/network/network", net[1])%>'" title="<%:Edit this interface%>" value="<%:Edit%>" id="<%=net[1]%>-ifc-edit" />
- <input type="submit" class="cbi-button cbi-button-remove" style="width:100px" onclick="iface_delete('<%=net[1]%>')" value="<%:Delete%>" />
+ <input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="iface_delete('<%=net[1]%>')" value="<%:Delete%>" />
</td>
</tr>
<% end %>
diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_status.htm b/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_status.htm
index 1ebdbfcfb4..94d9e88117 100644
--- a/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_status.htm
+++ b/modules/luci-mod-admin-full/luasrc/view/admin_network/iface_status.htm
@@ -25,7 +25,7 @@
html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
}
- if (ifc.type != 'tunnel')
+ if (ifc.macaddr)
{
html += String.format('<strong><%:MAC-Address%>:</strong> %s<br />', ifc.macaddr);
}
@@ -43,10 +43,9 @@
for (var i = 0; i < ifc.ipaddrs.length; i++)
html += String.format(
- '%s%s/%d',
+ '%s%s',
i ? ', ' : '',
- ifc.ipaddrs[i].addr,
- ifc.ipaddrs[i].prefix
+ ifc.ipaddrs[i]
);
html += '<br />';
@@ -58,10 +57,9 @@
for (var i = 0; i < ifc.ip6addrs.length; i++)
html += String.format(
- '%s%s/%d',
+ '%s%s',
i ? ', ' : '',
- ifc.ip6addrs[i].addr.toUpperCase(),
- ifc.ip6addrs[i].prefix
+ ifc.ip6addrs[i].toUpperCase()
);
html += '<br />';