luci-app-ddns: Update to support ddns-scripts 2.1.0-1 248/head
authorChristian Schoenebeck <christian.schoenebeck@gmail.com>
Sun, 9 Nov 2014 17:37:15 +0000 (18:37 +0100)
committerChristian Schoenebeck <christian.schoenebeck@gmail.com>
Sun, 9 Nov 2014 17:37:15 +0000 (18:37 +0100)
fix verify of entry for DNS server Issue #244
https://github.com/openwrt/luci/issues/244
add support for option 'update_script'
add display of version information when click on "Dynamic DNS" on
overview page
add verify of installed ddns-scripts version and show as hint if not
correct version
modified epoch to date conversation
cbi object Flag did not set section.changed state, fixed in
tools.flag_parse function
ucitrack entry no longer needed and removed
minor fixes

Signed-off-by: Christian Schoenebeck <christian.schoenebeck@gmail.com>
13 files changed:
applications/luci-ddns/CHANGELOG [new file with mode: 0644]
applications/luci-ddns/Makefile
applications/luci-ddns/luasrc/controller/ddns.lua
applications/luci-ddns/luasrc/model/cbi/ddns/detail.lua
applications/luci-ddns/luasrc/model/cbi/ddns/hints.lua
applications/luci-ddns/luasrc/model/cbi/ddns/overview.lua
applications/luci-ddns/luasrc/tools/ddns.lua
applications/luci-ddns/luasrc/view/ddns/overview_status.htm
applications/luci-ddns/luasrc/view/ddns/system_status.htm
applications/luci-ddns/root/etc/uci-defaults/luci-ddns
applications/luci-ddns/root/usr/lib/ddns/dynamic_dns_lucihelper.sh
po/de/ddns.po
po/templates/ddns.pot

diff --git a/applications/luci-ddns/CHANGELOG b/applications/luci-ddns/CHANGELOG
new file mode 100644 (file)
index 0000000..7848a14
--- /dev/null
@@ -0,0 +1,25 @@
+Version: 2.1.0-1
+Date: 2014-11-09
+ddns-scripts: 2.1.0-1 or greater needed
+
+fix verify of entry for DNS server Issue #244
+       https://github.com/openwrt/luci/issues/244
+add support for option 'update_script'
+add display of version information when click on "Dynamic DNS" on overview page
+add verify of installed ddns-scripts version and show as hint if not correct version
+modified epoch to date conversation
+cbi object Flag did not set section.changed state, fixed in tools.flag_parse function
+ucitrack entry no longer needed and removed
+minor fixes
+
+--------------------------------------------------------------------------------
+Version: 2.0.1-1
+Date: 2014-09-21
+ddns-scripts: 2.0.1-1 up to 2.0.1-9
+
+New DDNS status in System->Status overview
+New Overview page with option to start/stop a section
+New Detail page with tabbed view incl. logfile viewer
+Extended verify of all entries before save to config
+   incl. connect test to DNS- and Proxy-server
+Support for all available options of ddns-scripts 1.x and 2.x
index 0a723b61dcbecd4bac1be104fa4f0630d26d8e6d..3f57d63c6974f3a49ca5f1cfe3259834e12d5114 100644 (file)
@@ -1,8 +1,3 @@
-# supports ddns-scripts 1.0.0-23 and ddns-scripts starting
-# PKG_VERSION:=2.0.1
-# PKG_RELEASE:=8
-# PKG_MAINTAINER:=Christian Schoenebeck <christian.schoenebeck@gmail.com>
-
 PO = ddns
 
 include ../../build/config.mk
index e59a2800c98d1735139c4819a37dd49d61084fa7..952c9ffe3f5ce2af0f6628790ab72ae38c7bf9e2 100644 (file)
@@ -16,15 +16,22 @@ $Id$
 
 module("luci.controller.ddns", package.seeall)
 
-require "nixio"
-require "nixio.fs"
-require "luci.sys"
-require "luci.http"
-require "luci.model.uci"
-require "luci.dispatcher"
-require "luci.tools.ddns"
+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 SYS  = require "luci.sys"
+local DDNS = require "luci.tools.ddns"         -- ddns multiused functions
+local UTIL = require "luci.util"
+
+local luci_ddns_version = "2.1.0-1"    -- luci-app-ddns / openwrt Makefile compatible version
+local ddns_scripts_min  = "2.1.0-1"    -- minimum version of ddns-scripts required
 
 function index()
+       -- above 'require "mod"' definitions are not recognized 
+       -- inside index() during initialisation
+
        -- no configuration file, don't start
        if not nixio.fs.access("/etc/config/ddns") then
                return
@@ -44,25 +51,27 @@ function index()
                entry( {"admin", "services", "ddns", "hints"}, cbi("ddns/hints", 
                        {hideapplybtn=true, hidesavebtn=true, hideresetbtn=true}), nil ).leaf = true
                entry( {"admin", "services", "ddns", "logview"}, call("logread") ).leaf = true
-               entry( {"admin", "services", "ddns", "status"}, call("status") ).leaf = true
                entry( {"admin", "services", "ddns", "startstop"}, call("startstop") ).leaf = true
+               entry( {"admin", "services", "ddns", "status"}, call("status") ).leaf = true
        end
 end
 
 -- function to read all sections status and return data array
-function _get_status()
-       local uci       = luci.model.uci.cursor()
-       local service   = luci.sys.init.enabled("ddns") and 1 or 0
-       local url_start = luci.dispatcher.build_url("admin", "system", "startup")
-       local data      = {}    -- Array to transfer data to javascript
-
-       -- read application settings
-       local date_format = uci:get("ddns", "global", "date_format") or "%F %R"
-       local run_dir     = uci:get("ddns", "global", "run_dir") or "/var/run/ddns"
+local function _get_status()
+       local uci        = UCI.cursor()
+       local service    = SYS.init.enabled("ddns") and 1 or 0
+       local url_start  = DISP.build_url("admin", "system", "startup")
+       local luci_build = DDNS.ipkg_version("luci-app-ddns").version
+       local ddns_act   = DDNS.ipkg_version("ddns-scripts").version
+       local data       = {}   -- Array to transfer data to javascript
 
        data[#data+1]   = {
-               enabled = service,      -- service enabled
-               url_up  = url_start     -- link to enable DDS (System-Startup)
+               enabled    = service,           -- service enabled
+               url_up     = url_start,         -- link to enable DDS (System-Startup)
+               luci_ver   = luci_ddns_version, -- luci-app-ddns / openwrt Makefile compatible version
+               luci_build = luci_build,        -- installed luci build
+               script_min = ddns_scripts_min,  -- minimum version of ddns-scripts needed
+               script_ver = ddns_act           -- installed ddns-scripts
        }
 
        uci:foreach("ddns", "service", function (s)
@@ -75,13 +84,13 @@ function _get_status()
                local datenext  = "_empty_"     -- formated date of next update
 
                -- get force seconds
-               local force_seconds = luci.tools.ddns.calc_seconds(
+               local force_seconds = DDNS.calc_seconds(
                                tonumber(s["force_interval"]) or 72 ,
                                s["force_unit"] or "hours" )
                -- get/validate pid and last update 
-               local pid      = luci.tools.ddns.get_pid(section, run_dir)
-               local uptime   = luci.sys.uptime()
-               local lasttime = tonumber(nixio.fs.readfile("%s/%s.update" % { run_dir, section } ) or 0 )
+               local pid      = DDNS.get_pid(section)
+               local uptime   = SYS.uptime()
+               local lasttime = DDNS.get_lastupd(section)
                if lasttime > uptime then       -- /var might not be linked to /tmp
                        lasttime = 0            -- and/or not cleared on reboot
                end
@@ -96,10 +105,9 @@ function _get_status()
                        --             sys.epoch - sys uptime   + lastupdate(uptime)
                        local epoch = os.time() - uptime + lasttime
                        -- use linux date to convert epoch
-                       datelast = luci.sys.exec([[/bin/date -d @]] .. epoch .. [[ +']] .. date_format .. [[']])
+                       datelast = DDNS.epoch2date(epoch)
                        -- calc and fill next update
-                       datenext = luci.sys.exec([[/bin/date -d @]] .. (epoch + force_seconds) .. 
-                                               [[ +']] .. date_format .. [[']])
+                       datenext = DDNS.epoch2date(epoch + force_seconds)
                end
 
                -- process running but update needs to happen
@@ -137,7 +145,7 @@ function _get_status()
                local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh]]
                command = command .. [[ get_registered_ip ]] .. domain .. [[ ]] .. use_ipv6 .. 
                        [[ ]] .. force_ipversion .. [[ ]] .. force_dnstcp .. [[ ]] .. dnsserver
-               local reg_ip = luci.sys.exec(command)
+               local reg_ip = SYS.exec(command)
                if reg_ip == "" then 
                        reg_ip = "_nodata_"
                end
@@ -156,41 +164,38 @@ function _get_status()
        end)
 
        uci:unload("ddns")
-
        return data
 end
 
 -- called by XHR.get from detail_logview.htm
 function logread(section)
        -- read application settings
-       local uci         = luci.model.uci.cursor()
+       local uci         = UCI.cursor()
        local log_dir     = uci:get("ddns", "global", "log_dir") or "/var/log/ddns"
        local lfile=log_dir .. "/" .. section .. ".log"
 
-       local ldata=nixio.fs.readfile(lfile)
+       local ldata=NXFS.readfile(lfile)
        if not ldata or #ldata == 0 then
                ldata="_nodata_"
        end 
-       luci.http.write(ldata)
+       uci:unload("ddns")
+       HTTP.write(ldata)
 end
 
 -- called by XHR.get from overview_status.htm
 function startstop(section, enabled)
-       -- Array to transfer data to javascript
-       local data      = {}
-       -- read application settings
-       local uci         = luci.model.uci.cursor()
-       local run_dir     = uci:get("ddns", "global", "run_dir") or "/var/run/ddns"
+       local uci  = UCI.cursor()
+       local data = {}         -- Array to transfer data to javascript
 
        -- if process running we want to stop and return
-       local pid = luci.tools.ddns.get_pid(section, run_dir)
+       local pid = DDNS.get_pid(section)
        if pid > 0 then
-               os.execute ([[kill -9 %s]] % pid)
-               nixio.nanosleep(2)      -- 2 second "show time"
+               local tmp = NX.kill(pid, 15)    -- terminate
+               NX.nanosleep(2) -- 2 second "show time"
                -- status changed so return full status
                data = _get_status()
-               luci.http.prepare_content("application/json")
-               luci.http.write_json(data)
+               HTTP.prepare_content("application/json")
+               HTTP.write_json(data)
                return
        end
 
@@ -219,13 +224,12 @@ function startstop(section, enabled)
                                end
                        end
                end
-
        end
 
        -- we can not execute because other 
        -- uncommited changes pending, so exit here
        if not exec then
-               luci.http.write("_uncommited_")
+               HTTP.write("_uncommited_")
                return
        end
 
@@ -237,17 +241,28 @@ function startstop(section, enabled)
 
        -- start dynamic_dns_updater.sh script
        os.execute ([[/usr/lib/ddns/dynamic_dns_updater.sh %s 0 > /dev/null 2>&1 &]] % section)
-       nixio.nanosleep(3)      -- 3 seconds "show time"
-
+       NX.nanosleep(3) -- 3 seconds "show time"
+       
        -- status changed so return full status
        data = _get_status()
-       luci.http.prepare_content("application/json")
-       luci.http.write_json(data)
+       HTTP.prepare_content("application/json")
+       HTTP.write_json(data)
 end
 
 -- called by XHR.poll from overview_status.htm
 function status()
        local data = _get_status()
-       luci.http.prepare_content("application/json")
-       luci.http.write_json(data)
+       HTTP.prepare_content("application/json")
+       HTTP.write_json(data)
 end
+
+-- check if installed ddns-scripts version < required version
+function update_needed()
+       local sver = DDNS.ipkg_version("ddns-scripts")
+       local rver = UTIL.split(ddns_scripts_min, "[%.%-]", nil, true)
+       return (sver.major < (tonumber(rver[1]) or 0))
+           or (sver.minor < (tonumber(rver[2]) or 0))
+           or (sver.patch < (tonumber(rver[3]) or 0))
+           or (sver.build < (tonumber(rver[4]) or 0))
+end
+
index c8d10f29b077ec64d42352c0b467cb8a0fd78c89..8619d449d5191b12c6be9416bed559bcb50e186a 100644 (file)
@@ -21,50 +21,52 @@ You may obtain a copy of the License at
 $Id$
 ]]--
 
-require "luci.dispatcher"
-require "nixio.fs"
-require "luci.sys"
-require "luci.tools.webadmin"
-require "luci.cbi.datatypes"
-require "luci.tools.ddns"      -- ddns multiused functions
-
--- takeover arguments
+local NX   = require "nixio"
+local FS   = require "nixio.fs"
+local SYS  = require "luci.sys"
+local UTIL = require "luci.util"
+local DISP = require "luci.dispatcher"
+local WADM = require "luci.tools.webadmin"
+local DTYP = require "luci.cbi.datatypes"
+local DDNS = require "luci.tools.ddns"         -- ddns multiused functions
+
+-- takeover arguments -- #######################################################
 section = arg[1]
 
--- check supported options
+-- check supported options -- ##################################################
 -- saved to local vars here because doing multiple os calls slow down the system
-has_ipv6   = luci.tools.ddns.check_ipv6()      -- IPv6 support
-has_ssl    = luci.tools.ddns.check_ssl()       -- HTTPS support
-has_proxy  = luci.tools.ddns.check_proxy()     -- Proxy support
-has_dnstcp = luci.tools.ddns.check_bind_host() -- DNS TCP support
+has_ipv6   = DDNS.check_ipv6() -- IPv6 support
+has_ssl    = DDNS.check_ssl()  -- HTTPS support
+has_proxy  = DDNS.check_proxy()        -- Proxy support
+has_dnstcp = DDNS.check_bind_host()    -- DNS TCP support
 has_force  = has_ssl and has_dnstcp            -- Force IP Protocoll
 
--- html constants
+-- html constants -- ###########################################################
 font_red = "<font color='red'>"
 font_off = "</font>"
 bold_on  = "<strong>"
 bold_off = "</strong>"
 
--- error text constants
+-- error text constants -- #####################################################
 err_ipv6_plain = translate("IPv6 not supported") .. " - " ..
                translate("please select 'IPv4' address version")
-err_ipv6_basic = bold_on .. 
+err_ipv6_basic = bold_on ..
                        font_red ..
-                               translate("IPv6 not supported") .. 
-                       font_off .. 
-                       "<br />" .. translate("please select 'IPv4' address version") .. 
+                               translate("IPv6 not supported") ..
+                       font_off ..
+                       "<br />" .. translate("please select 'IPv4' address version") ..
                 bold_off
-err_ipv6_other = bold_on .. 
-                       font_red .. 
-                               translate("IPv6 not supported") .. 
-                       font_off .. 
-                       "<br />" .. translate("please select 'IPv4' address version in") .. " " .. 
-                       [[<a href="]] .. 
-                                       luci.dispatcher.build_url("admin", "services", "ddns", "detail", section) .. 
+err_ipv6_other = bold_on ..
+                       font_red ..
+                               translate("IPv6 not supported") ..
+                       font_off ..
+                       "<br />" .. translate("please select 'IPv4' address version in") .. " " ..
+                       [[<a href="]] ..
+                                       DISP.build_url("admin", "services", "ddns", "detail", section) ..
                                        "?tab.dns." .. section .. "=basic" ..
-                               [[">]] .. 
-                               translate("Basic Settings") .. 
-                       [[</a>]] .. 
+                               [[">]] ..
+                               translate("Basic Settings") ..
+                       [[</a>]] ..
                 bold_off
 
 function err_tab_basic(self)
@@ -108,10 +110,10 @@ local function _verify_ip_source()
                _script = ips:formvalue(section)
        end
 
-       local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh get_local_ip ]] .. 
-               _ipv6 .. [[ ]] .. _source .. [[ ]] .. _network .. [[ ]] .. 
+       local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh get_local_ip ]] ..
+               _ipv6 .. [[ ]] .. _source .. [[ ]] .. _network .. [[ ]] ..
                _url .. [[ ]] .. _interface .. [[ ]] .. _script.. [[ ]] .. _proxy
-       local ret = luci.sys.call(command)
+       local ret = SYS.call(command)
 
        if ret == 0 then
                return true     -- valid
@@ -120,26 +122,36 @@ local function _verify_ip_source()
        end
 end
 
--- cbi-map definition
+-- cbi-map definition -- #######################################################
 m = Map("ddns")
 
-m.title = [[<a href="]] .. luci.dispatcher.build_url("admin", "services", "ddns") .. [[">]] .. 
-               translate("Dynamic DNS") .. [[</a>]]
+-- first need to close <a> from cbi map template our <a> closed by template
+m.title = [[</a><a href="]] .. DISP.build_url("admin", "services", "ddns") .. [[">]] .. 
+               translate("Dynamic DNS")
 
 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 = luci.dispatcher.build_url("admin", "services", "ddns")
+m.redirect = DISP.build_url("admin", "services", "ddns")
 
--- read application settings
+m.on_after_commit = function(self)
+       if self.changed then    -- changes ?
+               local pid = DDNS.get_pid(section)
+               if pid > 0 then -- running ?
+                       local tmp = NX.kill(pid, 1)     -- send SIGHUP
+               end
+       end
+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"
 -- log directory
 log_dir = m.uci:get(m.config, "global", "log_dir") or "/var/log/ddns"
 
--- cbi-section definition
-ns = m:section( NamedSection, section, "service", 
+-- cbi-section definition -- ###################################################
+ns = m:section( NamedSection, section, "service",
        translate("Details for") .. ([[: <strong>%s</strong>]] % section),
        translate("Configure here the details for selected Dynamic DNS service") )
 ns.instance = section  -- arg [1]
@@ -148,16 +160,19 @@ ns:tab("advanced", translate("Advanced Settings"), nil )
 ns:tab("timer", translate("Timer Settings"), nil )
 ns:tab("logview", translate("Log File Viewer"), nil )
 
--- TAB: Basic ##################################################################
--- enabled  
-en = ns:taboption("basic", Flag, "enabled", 
+-- TAB: Basic  #####################################################################################
+-- 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) 
+end
 
--- use_ipv6 (NEW)
-usev6 = ns:taboption("basic", ListValue, "use_ipv6", 
+-- use_ipv6 (NEW)  -- ##########################################################
+usev6 = ns:taboption("basic", ListValue, "use_ipv6",
        translate("IP address version"),
        translate("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider") )
 usev6.widget  = "radio"
@@ -187,8 +202,8 @@ function usev6.write(self, section, value)
        end
 end
 
--- IPv4 - service_name
-svc4 = ns:taboption("basic", ListValue, "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
@@ -206,11 +221,11 @@ if fd4 then
        fd4:close()
 end
 
-for _, v in luci.util.vspairs(services4) do svc4:value(v) end
+for _, v in UTIL.vspairs(services4) do svc4:value(v) end
 svc4:value("-", translate("-- custom --") )
 
 function svc4.cfgvalue(self, section)
-       local v =  luci.tools.ddns.read_value(self, section, "service_name")
+       local v =  DDNS.read_value(self, section, "service_name")
        if not v or #v == 0 then
                return "-"
        else
@@ -236,8 +251,8 @@ function svc4.write(self, section, value)
        end
 end
 
--- IPv6 - service_name
-svc6 = ns:taboption("basic", ListValue, "ipv6_service_name", 
+-- IPv6 - service_name -- ######################################################
+svc6 = ns:taboption("basic", ListValue, "ipv6_service_name",
        translate("DDNS Service provider") .. " [IPv6]" )
 svc6.default   = "-"
 svc6:depends("use_ipv6", "1")  -- only show on IPv6
@@ -258,11 +273,11 @@ if fd6 then
        fd6:close()
 end
 
-for _, v in luci.util.vspairs(services6) do svc6:value(v) end
+for _, v in UTIL.vspairs(services6) do svc6:value(v) end
 svc6:value("-", translate("-- custom --") )
 
 function svc6.cfgvalue(self, section)
-       local v =  luci.tools.ddns.read_value(self, section, "service_name")
+       local v =  DDNS.read_value(self, section, "service_name")
        if not v or #v == 0 then
                return "-"
        else
@@ -289,8 +304,8 @@ function svc6.write(self, section, value)
        end
 end
 
--- IPv4/IPv6 - update_url
-uurl = ns:taboption("basic", Value, "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.") )
@@ -312,22 +327,22 @@ function uurl.validate(self, value)
                return nil, err_tab_basic(self) .. translate("either url or script could be set")
        end
 
-       local url = luci.tools.ddns.parse_url(value)
+       local url = DDNS.parse_url(value)
        if not url.scheme == "http" then
                return nil, err_tab_basic(self) .. translate("must start with 'http://'")
        elseif not url.query then
                return nil, err_tab_basic(self) .. "<QUERY> " .. translate("missing / required")
        elseif not url.host then
                return nil, err_tab_basic(self) .. "<HOST> " .. translate("missing / required")
-       elseif luci.sys.call([[nslookup ]] .. url.host .. [[ >/dev/null 2>&1]]) ~= 0 then
+       elseif SYS.call([[nslookup ]] .. url.host .. [[ >/dev/null 2>&1]]) ~= 0 then
                return nil, err_tab_basic(self) .. translate("can not resolve host: ") .. url.host
        end
 
        return value
 end
 
--- IPv4/IPv6 - update_script
-ush = ns:taboption("basic", Value, "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", "-")
@@ -346,29 +361,29 @@ function ush.validate(self, value)
                end
        elseif (#url > 0) then
                return nil, err_tab_basic(self) .. translate("either url or script could be set")
-       elseif not nixio.fs.access(value) then
+       elseif not FS.access(value) then
                return nil, err_tab_basic(self) .. translate("File not found")
        end
        return value
 end
 
--- IPv4/IPv6 - domain
-dom = ns:taboption("basic", Value, "domain", 
+-- IPv4/IPv6 - domain -- #######################################################
+dom = ns:taboption("basic", Value, "domain",
                translate("Hostname/Domain"),
                translate("Replaces [DOMAIN] in Update-URL") )
 dom.rmempty    = false
 dom.placeholder        = "mypersonaldomain.dyndns.org"
 function dom.validate(self, value)
-       if not value 
+       if not value
        or not (#value > 0)
-       or not luci.cbi.datatypes.hostname(value) then
+       or not DTYP.hostname(value) then
                return nil, err_tab_basic(self) ..      translate("invalid - Sample") .. ": 'mypersonaldomain.dyndns.org'"
        else
                return value
        end
 end
 
--- IPv4/IPv6 - username
+-- IPv4/IPv6 - username -- #####################################################
 user = ns:taboption("basic", Value, "username",
                translate("Username"),
                translate("Replaces [USERNAME] in Update-URL") )
@@ -380,7 +395,7 @@ function user.validate(self, value)
        return value
 end
 
--- IPv4/IPv6 - password
+-- IPv4/IPv6 - password -- #####################################################
 pw = ns:taboption("basic", Value, "password",
                translate("Password"),
                translate("Replaces [PASSWORD] in Update-URL") )
@@ -393,9 +408,9 @@ function pw.validate(self, value)
        return value
 end
 
--- IPv4/IPv6 - use_https (NEW)
+-- IPv4/IPv6 - use_https (NEW) -- ##############################################
 if has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
-       https = ns:taboption("basic", Flag, "use_https", 
+       https = ns:taboption("basic", Flag, "use_https",
                translate("Use HTTP Secure") )
        https.orientation = "horizontal"
        https.rmempty = false -- force validate function
@@ -410,6 +425,9 @@ 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") .. " !"
@@ -424,10 +442,10 @@ if has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
        end
 end
 
--- IPv4/IPv6 - cacert (NEW)
+-- IPv4/IPv6 - cacert (NEW) -- #################################################
 if has_ssl then
-       cert = ns:taboption("basic", Value, "cacert", 
-               translate("Path to CA-Certificate"), 
+       cert = ns:taboption("basic", Value, "cacert",
+               translate("Path to CA-Certificate"),
                translate("directory or path/file") .. "<br />" ..
                translate("or") .. bold_on .. " IGNORE " .. bold_off ..
                translate("to run HTTPS without verification of server certificates (insecure)") )
@@ -439,8 +457,8 @@ if has_ssl then
                        return ""       -- supress validate error if NOT https
                end
                if value then   -- otherwise errors in datatype check
-                       if luci.cbi.datatypes.directory(value)
-                       or luci.cbi.datatypes.file(value)
+                       if DTYP.directory(value)
+                       or DTYP.file(value)
                        or value == "IGNORE" then
                                return value
                        end
@@ -450,8 +468,8 @@ if has_ssl then
        end
 end
 
--- use_syslog
-slog = ns:taboption("basic", ListValue, "use_syslog", 
+-- use_syslog -- ###############################################################
+slog = ns:taboption("basic", ListValue, "use_syslog",
        translate("Log to syslog"),
        translate("Writes log messages to syslog. Critical Errors will always be written to syslog.") )
 slog.default = "0"
@@ -461,18 +479,21 @@ slog:value("2", translate("Notice"))
 slog:value("3", translate("Warning"))
 slog:value("4", translate("Error"))
 
--- use_logfile (NEW)
-logf = ns:taboption("basic", Flag, "use_logfile", 
+-- use_logfile (NEW) -- ########################################################
+logf = ns:taboption("basic", 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
 
--- TAB: Advanced  ##############################################################
--- IPv4 - ip_source
-src4 = ns:taboption("advanced", ListValue, "ipv4_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") )
 src4:depends("use_ipv6", "0")  -- IPv4 selected
@@ -481,11 +502,11 @@ src4:value("network", translate("Network"))
 src4:value("web", translate("URL"))
 src4:value("interface", translate("Interface"))
 src4:value("script", translate("Script"))
-function src4.cfgvalue(self, section) 
-       return luci.tools.ddns.read_value(self, section, "ip_source") 
+function src4.cfgvalue(self, section)
+       return DDNS.read_value(self, section, "ip_source")
 end
 function src4.validate(self, value)
-       if usev6:formvalue(section) == "1" then 
+       if usev6:formvalue(section) == "1" then
                return ""       -- ignore on IPv6 selected
        elseif not _verify_ip_source() then
                return nil, err_tab_adv(self) ..
@@ -495,7 +516,7 @@ function src4.validate(self, value)
        end
 end
 function src4.write(self, section, value)
-       if usev6:formvalue(section) == "1" then 
+       if usev6:formvalue(section) == "1" then
                return true     -- ignore on IPv6 selected
        elseif value == "network" then
                self.map:del(section, "ip_url")         -- delete not need parameters
@@ -514,12 +535,12 @@ function src4.write(self, section, value)
                self.map:del(section, "ip_url")         -- delete not need parameters
                self.map:del(section, "ip_interface")
        end
-       self.map:del(section, self.option)              -- delete "ipv4_source" helper
+       self.map:del(section, self.option)               -- delete "ipv4_source" helper
        return self.map:set(section, "ip_source", value) -- and write "ip_source
 end
 
--- IPv6 - ip_source
-src6 = ns:taboption("advanced", ListValue, "ipv6_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") )
 src6:depends("use_ipv6", 1)    -- IPv6 selected
@@ -528,14 +549,14 @@ src6:value("network", translate("Network"))
 src6:value("web", translate("URL"))
 src6:value("interface", translate("Interface"))
 src6:value("script", translate("Script"))
-if not has_ipv6 then 
-       src6.description = err_ipv6_other 
+if not has_ipv6 then
+       src6.description = err_ipv6_other
 end
 function src6.cfgvalue(self, section)
-       return luci.tools.ddns.read_value(self, section, "ip_source")
+       return DDNS.read_value(self, section, "ip_source")
 end
 function src6.validate(self, value)
-       if usev6:formvalue(section) == "0" then 
+       if usev6:formvalue(section) == "0" then
                return ""       -- ignore on IPv4 selected
        elseif not has_ipv6 then
                return nil, err_tab_adv(self) .. err_ipv6_plain
@@ -547,7 +568,7 @@ function src6.validate(self, value)
        end
 end
 function src6.write(self, section, value)
-       if usev6:formvalue(section) == "0" then 
+       if usev6:formvalue(section) == "0" then
                return true     -- ignore on IPv4 selected
        elseif value == "network" then
                self.map:del(section, "ip_url")         -- delete not need parameters
@@ -566,19 +587,19 @@ function src6.write(self, section, value)
                self.map:del(section, "ip_url")         -- delete not need parameters
                self.map:del(section, "ip_interface")
        end
-       self.map:del(section, self.option)              -- delete "ipv4_source" helper
+       self.map:del(section, self.option)               -- delete "ipv4_source" helper
        return self.map:set(section, "ip_source", value) -- and write "ip_source
 end
 
--- IPv4 - ip_network (default "wan")
-ipn4 = ns:taboption("advanced", ListValue, "ipv4_network", 
+-- 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") )
 ipn4:depends("ipv4_source", "network")
 ipn4.default = "wan"
-luci.tools.webadmin.cbi_add_networks(ipn4)
-function ipn4.cfgvalue(self, section) 
-       return luci.tools.ddns.read_value(self, section, "ip_network") 
+WADM.cbi_add_networks(ipn4)
+function ipn4.cfgvalue(self, section)
+       return DDNS.read_value(self, section, "ip_network")
 end
 function ipn4.validate(self, value)
        if usev6:formvalue(section) == "1"
@@ -599,24 +620,24 @@ function ipn4.write(self, section, value)
        else
                -- set also as "interface" for monitoring events changes/hot-plug
                self.map:set(section, "interface", value)
-               self.map:del(section, self.option)               -- delete "ipv4_network" helper
+               self.map:del(section, self.option)                -- delete "ipv4_network" helper
                return self.map:set(section, "ip_network", value) -- and write "ip_network"
        end
 end
 
--- IPv6 - ip_network (default "wan6")
-ipn6 = ns:taboption("advanced", ListValue, "ipv6_network", 
+-- IPv6 - ip_network (default "wan6") -- #######################################
+ipn6 = ns:taboption("advanced", ListValue, "ipv6_network",
        translate("Network") .. " [IPv6]" )
 ipn6:depends("ipv6_source", "network")
 ipn6.default = "wan6"
-luci.tools.webadmin.cbi_add_networks(ipn6)
+WADM.cbi_add_networks(ipn6)
 if has_ipv6 then
        ipn6.description = translate("Defines the network to read systems IPv6-Address from")
 else
        ipn6.description = err_ipv6_other
 end
 function ipn6.cfgvalue(self, section)
-       return luci.tools.ddns.read_value(self, section, "ip_network")
+       return DDNS.read_value(self, section, "ip_network")
 end
 function ipn6.validate(self, value)
        if usev6:formvalue(section) == "0"
@@ -639,19 +660,19 @@ function ipn6.write(self, section, value)
        else
                -- set also as "interface" for monitoring events changes/hotplug
                self.map:set(section, "interface", value)
-               self.map:del(section, self.option)               -- delete "ipv6_network" helper
+               self.map:del(section, self.option)                -- delete "ipv6_network" helper
                return self.map:set(section, "ip_network", value) -- and write "ip_network"
        end
 end
 
--- IPv4 - ip_url (default "checkip.dyndns.com")
-iurl4 = ns:taboption("advanced", Value, "ipv4_url", 
+-- 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") )
 iurl4:depends("ipv4_source", "web")
 iurl4.default = "http://checkip.dyndns.com"
 function iurl4.cfgvalue(self, section)
-       return luci.tools.ddns.read_value(self, section, "ip_url")
+       return DDNS.read_value(self, section, "ip_url")
 end
 function iurl4.validate(self, value)
        if usev6:formvalue(section) == "1"
@@ -663,14 +684,12 @@ function iurl4.validate(self, value)
                return nil, err_tab_adv(self) .. translate("missing / required")
        end
 
-       local url = luci.tools.ddns.parse_url(value)
+       local url = DDNS.parse_url(value)
        if not (url.scheme == "http" or url.scheme == "https") then
                return nil, err_tab_adv(self) .. translate("must start with 'http://'")
        elseif not url.host then
                return nil, err_tab_adv(self) .. "<HOST> " .. translate("missing / required")
-       elseif luci.sys.call([[nslookup ]] .. 
-               url.host .. 
-               [[>/dev/null 2>&1]]) ~= 0 then
+       elseif SYS.call([[nslookup ]] .. url.host .. [[>/dev/null 2>&1]]) ~= 0 then
                return nil, err_tab_adv(self) .. translate("can not resolve host: ") .. url.host
        else
                return value
@@ -688,8 +707,8 @@ function iurl4.write(self, section, value)
        end
 end
 
--- IPv6 - ip_url (default "checkipv6.dyndns.com")
-iurl6 = ns:taboption("advanced", Value, "ipv6_url", 
+-- IPv6 - ip_url (default "checkipv6.dyndns.com") -- ###########################
+iurl6 = ns:taboption("advanced", Value, "ipv6_url",
        translate("URL to detect") .. " [IPv6]" )
 iurl6:depends("ipv6_source", "web")
 iurl6.default = "http://checkipv6.dyndns.com"
@@ -699,7 +718,7 @@ else
        iurl6.description = err_ipv6_other
 end
 function iurl6.cfgvalue(self, section)
-       return luci.tools.ddns.read_value(self, section, "ip_url")
+       return DDNS.read_value(self, section, "ip_url")
 end
 function iurl6.validate(self, value)
        if usev6:formvalue(section) == "0"
@@ -713,14 +732,12 @@ function iurl6.validate(self, value)
                return nil, err_tab_adv(self) .. translate("missing / required")
        end
 
-       local url = luci.tools.ddns.parse_url(value)
+       local url = DDNS.parse_url(value)
        if not (url.scheme == "http" or url.scheme == "https") then
                return nil, err_tab_adv(self) .. translate("must start with 'http://'")
        elseif not url.host then
                return nil, err_tab_adv(self) .. "<HOST> " .. translate("missing / required")
-       elseif luci.sys.call([[nslookup ]] .. 
-               url.host .. 
-               [[>/dev/null 2>&1]]) ~= 0 then
+       elseif SYS.call([[nslookup ]] .. url.host .. [[>/dev/null 2>&1]]) ~= 0 then
                return nil, err_tab_adv(self) .. translate("can not resolve host: ") .. url.host
        else
                return value
@@ -738,17 +755,17 @@ function iurl6.write(self, section, value)
        end
 end
 
--- IPv4 + IPv6 - ip_interface
-ipi = ns:taboption("advanced", ListValue, "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") )
 ipi:depends("ipv4_source", "interface")        -- IPv4
 ipi:depends("ipv6_source", "interface")        -- or IPv6
-for _, v in pairs(luci.sys.net.devices()) do
+for _, v in pairs(SYS.net.devices()) do
        -- show only interface set to a network
        -- and ignore loopback
-       net = luci.tools.webadmin.iface_get_network(v)
-       if net and net ~= "loopback" then 
+       net = WADM.iface_get_network(v)
+       if net and net ~= "loopback" then
                ipi:value(v)
        end
 end
@@ -767,14 +784,14 @@ function ipi.write(self, section, value)
        else
                -- get network from device to
                -- set also as "interface" for monitoring events changes/hotplug
-               local net = luci.tools.webadmin.iface_get_network(value)
+               local net = WADM.iface_get_network(value)
                self.map:set(section, "interface", net)
                return self.map:set(section, self.option, value)
        end
 end
 
--- IPv4 + IPv6 - ip_script (NEW)
-ips = ns:taboption("advanced", Value, "ip_script", 
+-- IPv4 + IPv6 - ip_script (NEW) -- ############################################
+ips = ns:taboption("advanced", Value, "ip_script",
        translate("Script"),
        translate("User defined script to read systems IP-Address") )
 ips:depends("ipv4_source", "script")   -- IPv4
@@ -784,8 +801,8 @@ function ips.validate(self, value)
        if (usev6:formvalue(section) == "0" and src4:formvalue(section) ~= "script")
        or (usev6:formvalue(section) == "1" and src6:formvalue(section) ~= "script") then
                return ""
-       elseif not value or not nixio.fs.access(value, "x") then 
-               return nil, err_tab_adv(self) .. 
+       elseif not value or not FS.access(value, "x") then
+               return nil, err_tab_adv(self) ..
                        translate("not found or not executable - Sample: '/path/to/script.sh'")
        else
                return value
@@ -800,19 +817,19 @@ function ips.write(self, section, value)
        end
 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 
-eif4 = ns:taboption("advanced", ListValue, "ipv4_interface", 
-       translate("Event Network") .. " [IPv4]", 
+-- if "ip_source"="network" or "interface" we use their network
+eif4 = ns:taboption("advanced", ListValue, "ipv4_interface",
+       translate("Event Network") .. " [IPv4]",
        translate("Network on which the ddns-updater scripts will be started") )
 eif4:depends("ipv4_source", "web")
 eif4:depends("ipv4_source", "script")
 eif4.default = "wan"
-luci.tools.webadmin.cbi_add_networks(eif4)
+WADM.cbi_add_networks(eif4)
 function eif4.cfgvalue(self, section)
-       return luci.tools.ddns.read_value(self, section, "interface")
+       return DDNS.read_value(self, section, "interface")
 end
 function eif4.validate(self, value)
        if usev6:formvalue(section) == "1"
@@ -829,35 +846,35 @@ function eif4.write(self, section, value)
         or src4:formvalue(section) == "interface" then
                return true     -- ignore IPv6, network, interface
        else
-               self.map:del(section, self.option)              -- delete "ipv4_interface" helper
+               self.map:del(section, self.option)               -- delete "ipv4_interface" helper
                return self.map:set(section, "interface", value) -- and write "interface"
        end
 end
 
--- IPv6 - interface (NEW) - default "wan6"
+-- IPv6 - interface (NEW) - default "wan6" -- ##################################
 -- event network to monitor changes/hotplug (NEW)
 -- 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", 
+-- if "ip_source"="network" or "interface" we use their network
+eif6 = ns:taboption("advanced", ListValue, "ipv6_interface",
        translate("Event Network") .. " [IPv6]" )
 eif6:depends("ipv6_source", "web")
 eif6:depends("ipv6_source", "script")
 eif6.default = "wan6"
-luci.tools.webadmin.cbi_add_networks(eif6)
-if not has_ipv6 then 
+WADM.cbi_add_networks(eif6)
+if not has_ipv6 then
        eif6.description = err_ipv6_other
 else
        eif6.description = translate("Network on which the ddns-updater scripts will be started")
 end
 function eif6.cfgvalue(self, section)
-       return luci.tools.ddns.read_value(self, section, "interface")
+       return DDNS.read_value(self, section, "interface")
 end
 function eif6.validate(self, value)
        if usev6:formvalue(section) == "0"
         or src4:formvalue(section) == "network"
         or src4:formvalue(section) == "interface" then
                return ""       -- ignore IPv4, network, interface
-       elseif not has_ipv6 then 
+       elseif not has_ipv6 then
                return nil, err_tab_adv(self) .. err_ipv6_plain
        else
                return value
@@ -869,12 +886,12 @@ function eif6.write(self, section, value)
         or src4:formvalue(section) == "interface" then
                return true     -- ignore IPv4, network, interface
        else
-               self.map:del(section, self.option)              -- delete "ipv6_interface" helper
+               self.map:del(section, self.option)               -- delete "ipv6_interface" helper
                return self.map:set(section, "interface", value) -- and write "interface"
        end
 end
 
--- IPv4 + IPv6 - force_ipversion (NEW)
+-- IPv4 + IPv6 - force_ipversion (NEW) -- ######################################
 -- 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
@@ -896,6 +913,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)
@@ -905,9 +925,9 @@ if has_force or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then
        end
 end
 
--- IPv4 + IPv6 - dns_server (NEW)
+-- IPv4 + IPv6 - dns_server (NEW) -- ###########################################
 -- optional DNS Server to use resolving my IP if "ip_source"="web"
-dns = ns:taboption("advanced", Value, "dns_server", 
+dns = ns:taboption("advanced", Value, "dns_server",
        translate("DNS-Server"),
        translate("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") .. "<br />" ..
        translate("Format: IP or FQDN"))
@@ -916,14 +936,14 @@ function dns.validate(self, value)
        -- if .datatype is set, then it is checked before calling this function
        if not value then
                return ""       -- ignore on empty
-       elseif not luci.cbi.datatypes.hostname(value) then
-               return nil, err .. translate("use hostname, FQDN, IPv4- or IPv6-Address")
+       elseif not DTYP.host(value) then
+               return nil, err_tab_adv(self) .. translate("use hostname, FQDN, IPv4- or IPv6-Address")
        else
                local ipv6  = usev6:formvalue(section)
                local force = (fipv) and fipv:formvalue(section) or "0"
-               local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh verify_dns ]] .. 
+               local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh verify_dns ]] ..
                        value .. [[ ]] .. ipv6 .. [[ ]] .. force
-               local ret = luci.sys.call(command)
+               local ret = SYS.call(command)
                if     ret == 0 then return value       -- everything OK
                elseif ret == 2 then return nil, err_tab_adv(self) .. translate("nslookup can not resolve host")
                elseif ret == 3 then return nil, err_tab_adv(self) .. translate("nc (netcat) can not connect")
@@ -933,7 +953,7 @@ function dns.validate(self, value)
        end
 end
 
--- IPv4 + IPv6 - force_dnstcp (NEW)
+-- IPv4 + IPv6 - force_dnstcp (NEW) -- #########################################
 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") )
@@ -955,12 +975,15 @@ 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 (NEW) -- ################################################
 -- 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", 
+       pxy = ns:taboption("advanced", Value, "proxy",
                translate("PROXY-Server") )
        pxy.placeholder="user:password@myproxy.lan:8080"
        function pxy.cfgvalue(self, section)
@@ -972,8 +995,8 @@ if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
                else
                        self.description = translate("OPTIONAL: Proxy-Server for detection and updates.") .. "<br />" ..
                                translate("Format") .. ": " .. bold_on .. "[user:password@]proxyhost:port" .. bold_off .. "<br />" ..
-                               translate("IPv6 address must be given in square brackets") .. ": " .. 
-                               bold_on .. " [2001:db8::1]:8080" .. bold_off 
+                               translate("IPv6 address must be given in square brackets") .. ": " ..
+                               bold_on .. " [2001:db8::1]:8080" .. bold_off
                end
                return value
        end
@@ -981,12 +1004,12 @@ if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
                -- if .datatype is set, then it is checked before calling this function
                if not value then
                        return ""       -- ignore on empty
-               elseif has_proxy then 
+               elseif has_proxy then
                        local ipv6  = usev6:formvalue(section) or "0"
                        local force = (fipv) and fipv:formvalue(section) or "0"
-                       local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh verify_proxy ]] .. 
+                       local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh verify_proxy ]] ..
                                value .. [[ ]] .. ipv6 .. [[ ]] .. force
-                       local ret = luci.sys.call(command)
+                       local ret = SYS.call(command)
                        if     ret == 0 then return value
                        elseif ret == 2 then return nil, err_tab_adv(self) .. translate("nslookup can not resolve host")
                        elseif ret == 3 then return nil, err_tab_adv(self) .. translate("nc (netcat) can not connect")
@@ -1000,21 +1023,21 @@ if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
        end
 end
 
--- TAB: Timer  #################################################################
--- check_interval
-ci = ns:taboption("timer", Value, "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.default  = 10
 ci.rmempty = false     -- validate ourselves for translatable error messages
 function ci.validate(self, value)
-       if not luci.cbi.datatypes.uinteger(value) 
+       if not DTYP.uinteger(value)
        or tonumber(value) < 1 then
                return nil, err_tab_timer(self) .. translate("minimum value 5 minutes == 300 seconds")
        end
 
-       local secs = luci.tools.ddns.calc_seconds(value, cu:formvalue(section))
-       if secs >= 300 then 
+       local secs = DDNS.calc_seconds(value, cu:formvalue(section))
+       if secs >= 300 then
                return value
        else
                return nil, err_tab_timer(self) .. translate("minimum value 5 minutes == 300 seconds")
@@ -1022,7 +1045,7 @@ function ci.validate(self, value)
 end
 function ci.write(self, section, value)
        -- simulate rmempty=true remove default
-       local secs = luci.tools.ddns.calc_seconds(value, cu:formvalue(section))
+       local secs = DDNS.calc_seconds(value, cu:formvalue(section))
        if secs ~= 600 then     --default 10 minutes
                return self.map:set(section, self.option, value)
        else
@@ -1031,9 +1054,9 @@ function ci.write(self, section, value)
        end
 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 />" .. 
+       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"
@@ -1044,7 +1067,7 @@ cu:value("hours", translate("hours"))
 --cu:value("days", translate("days"))
 function cu.write(self, section, value)
        -- simulate rmempty=true remove default
-       local secs = luci.tools.ddns.calc_seconds(ci:formvalue(section), value)
+       local secs = DDNS.calc_seconds(ci:formvalue(section), value)
        if secs ~= 600 then     --default 10 minutes
                return self.map:set(section, self.option, value)
        else
@@ -1052,29 +1075,29 @@ function cu.write(self, section, value)
        end
 end
 
--- force_interval (modified)
-fi = ns:taboption("timer", Value, "force_interval", 
+-- 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
 function fi.validate(self, value)
-       if not luci.cbi.datatypes.uinteger(value) 
+       if not DTYP.uinteger(value) 
        or tonumber(value) < 0 then
                return nil, err_tab_timer(self) .. translate("minimum value '0'")
        end
 
-       local force_s = luci.tools.ddns.calc_seconds(value, fu:formvalue(section))
-       if force_s == 0 then 
+       local force_s = DDNS.calc_seconds(value, fu:formvalue(section))
+       if force_s == 0 then
                return value
        end
 
        local ci_value = ci:formvalue(section)
-       if not luci.cbi.datatypes.uinteger(ci_value) then
+       if not DTYP.uinteger(ci_value) then
                return ""       -- ignore because error in check_interval above
        end
 
-       local check_s = luci.tools.ddns.calc_seconds(ci_value, cu:formvalue(section))
+       local check_s = DDNS.calc_seconds(ci_value, cu:formvalue(section))
        if force_s >= check_s then
                return value
        end
@@ -1083,7 +1106,7 @@ function fi.validate(self, value)
 end
 function fi.write(self, section, value)
        -- simulate rmempty=true remove default
-       local secs = luci.tools.ddns.calc_seconds(value, fu:formvalue(section))
+       local secs = DDNS.calc_seconds(value, fu:formvalue(section))
        if secs ~= 259200 then  --default 72 hours == 3 days
                return self.map:set(section, self.option, value)
        else
@@ -1092,7 +1115,7 @@ function fi.write(self, section, value)
        end
 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 />" ..
@@ -1106,7 +1129,7 @@ fu:value("hours", translate("hours"))
 fu:value("days", translate("days"))
 function fu.write(self, section, value)
        -- simulate rmempty=true remove default
-       local secs = luci.tools.ddns.calc_seconds(fi:formvalue(section), value)
+       local secs = DDNS.calc_seconds(fi:formvalue(section), value)
        if secs ~= 259200 and secs ~= 0 then    --default 72 hours == 3 days
                return self.map:set(section, self.option, value)
        else
@@ -1114,14 +1137,14 @@ function fu.write(self, section, value)
        end
 end
 
--- retry_count (NEW)
-rc = ns:taboption("timer", Value, "retry_count", 
+-- retry_count (NEW) -- ########################################################
+rc = ns:taboption("timer", Value, "retry_count",
        translate("Error Retry Counter"),
        translate("On Error the script will stop execution after given number of retrys") )
 rc.default = 5
 rc.rmempty = false     -- validate ourselves for translatable error messages
 function rc.validate(self, value)
-       if not luci.cbi.datatypes.uinteger(value) 
+       if not DTYP.uinteger(value) 
        or tonumber(value) < 1 then
                return nil, err_tab_timer(self) .. translate("minimum value '1'")
        else
@@ -1137,14 +1160,14 @@ function rc.write(self, section, value)
        end
 end
 
--- retry_interval
-ri = ns:taboption("timer", Value, "retry_interval", 
-       translate("Error 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
 function ri.validate(self, value)
-       if not luci.cbi.datatypes.uinteger(value) 
+       if not DTYP.uinteger(value)
        or tonumber(value) < 1 then
                return nil, err_tab_timer(self) .. translate("minimum value '1'")
        else
@@ -1153,7 +1176,7 @@ function ri.validate(self, value)
 end
 function ri.write(self, section, value)
        -- simulate rmempty=true remove default
-       local secs = luci.tools.ddns.calc_seconds(value, ru:formvalue(section))
+       local secs = DDNS.calc_seconds(value, ru:formvalue(section))
        if secs ~= 60 then      --default 60seconds
                return self.map:set(section, self.option, value)
        else
@@ -1162,7 +1185,7 @@ function ri.write(self, section, value)
        end
 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"
@@ -1174,7 +1197,7 @@ ru:value("minutes", translate("minutes"))
 --ru:value("days", translate("days"))
 function ru.write(self, section, value)
        -- simulate rmempty=true remove default
-       local secs = luci.tools.ddns.calc_seconds(ri:formvalue(section), value)
+       local secs = DDNS.calc_seconds(ri:formvalue(section), value)
        if secs ~= 60 then      --default 60seconds
                return self.map:set(section, self.option, value)
        else
@@ -1189,7 +1212,7 @@ lv.inputtitle = translate("Read / Reread log file")
 lv.rows = 50
 function lv.cfgvalue(self, section)
        local lfile=log_dir .. "/" .. section .. ".log"
-       if nixio.fs.access(lfile) then
+       if FS.access(lfile) then
                return lfile .. "\n" .. translate("Please press [Read] button")
        end
        return lfile .. "\n" .. translate("File not found or empty")
index d0d323c03ee1da98e9dee5caf235e18c1d18aa2c..dfbc7468cd976b0ee9fbc635dbb71bb7372775b4 100644 (file)
@@ -12,56 +12,74 @@ You may obtain a copy of the License at
 $Id$
 ]]--
 
-require "luci.sys"
-require "luci.dispatcher"
-require "luci.tools.ddns"
+local CTRL = require "luci.controller.ddns"    -- this application's controller
+local DISP = require "luci.dispatcher"
+local SYS  = require "luci.sys"
+local DDNS = require "luci.tools.ddns"         -- ddns multiused functions
 
--- check supported options
+-- check supported options -- ##################################################
 -- saved to local vars here because doing multiple os calls slow down the system
-has_ssl    = luci.tools.ddns.check_ssl()       -- HTTPS support
-has_proxy  = luci.tools.ddns.check_proxy()     -- Proxy support
-has_dnstcp = luci.tools.ddns.check_bind_host() -- DNS TCP support
+has_ssl     = DDNS.check_ssl()         -- HTTPS support
+has_proxy   = DDNS.check_proxy()       -- Proxy support
+has_dnstcp  = DDNS.check_bind_host()   -- DNS TCP support
+need_update = CTRL.update_needed()     -- correct ddns-scripts version
 
 -- html constants
+font_red = [[<font color="red">]]
+font_off = [[</font>]]
 bold_on  = [[<strong>]]
 bold_off = [[</strong>]]
 
--- cbi-map definition
+-- cbi-map definition -- #######################################################
 m = Map("ddns")
 
-m.title = [[<a href="]] .. luci.dispatcher.build_url("admin", "services", "ddns") .. [[">]] .. 
-               translate("Dynamic DNS") .. [[</a>]]
+-- first need to close <a> from cbi map template our <a> closed by template
+m.title = [[</a><a href="]] .. DISP.build_url("admin", "services", "ddns") .. [[">]] ..
+               translate("Dynamic DNS")
 
 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 = luci.dispatcher.build_url("admin", "services", "ddns")
+m.redirect = DISP.build_url("admin", "services", "ddns")
 
--- SimpleSection definition
+-- SimpleSection definition -- #################################################
 -- show Hints to optimize installation and script usage
-s = m:section( SimpleSection, 
-       translate("Hints"), 
+s = m:section( SimpleSection,
+       translate("Hints"),
        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
+       local dv = s:option(DummyValue, "_update_needed")
+       dv.titleref = DISP.build_url("admin", "system", "packages")
+       dv.rawhtml  = true
+       dv.title = font_red .. bold_on ..
+               translate("Software update required") .. bold_off .. font_off
+       dv.value = translate("The currently installed 'ddns-scripts' package did not support all available settings.") ..
+                       "<br />" ..
+                       translate("Please update to the current version!")
+end
+
 -- DDNS Service disabled
-if not luci.sys.init.enabled("ddns") then
+if not SYS.init.enabled("ddns") then
        local dv = s:option(DummyValue, "_not_enabled")
-       dv.titleref = luci.dispatcher.build_url("admin", "system", "startup")
+       dv.titleref = DISP.build_url("admin", "system", "startup")
        dv.rawhtml  = true
-       dv.title = bold_on .. 
+       dv.title = bold_on ..
                translate("DDNS Autostart disabled") .. bold_off
-       dv.value = translate("Currently DDNS updates are not started at boot or on interface events." .. "<br />" .. 
+       dv.value = translate("Currently DDNS updates are not started at boot or on interface events." .. "<br />" ..
                        "This is the default if you run DDNS scripts by yourself (i.e. via cron with force_interval set to '0')" )
 end
 
 -- No IPv6 support
-if not luci.tools.ddns.check_ipv6() then
+if not DDNS.check_ipv6() then
        local dv = s:option(DummyValue, "_no_ipv6")
        dv.titleref = 'http://www.openwrt.org" target="_blank'
        dv.rawhtml  = true
-       dv.title = bold_on .. 
+       dv.title = bold_on ..
                translate("IPv6 not supported") .. bold_off
-       dv.value = translate("IPv6 is currently not (fully) supported by this system" .. "<br />" .. 
+       dv.value = translate("IPv6 is currently not (fully) supported by this system" .. "<br />" ..
                        "Please follow the instructions on OpenWrt's homepage to enable IPv6 support" .. "<br />" ..
                        "or update your system to the latest OpenWrt Release")
 end
@@ -69,13 +87,13 @@ end
 -- No HTTPS support
 if not has_ssl then
        local dv = s:option(DummyValue, "_no_https")
-       dv.titleref = luci.dispatcher.build_url("admin", "system", "packages")
+       dv.titleref = DISP.build_url("admin", "system", "packages")
        dv.rawhtml  = true
-       dv.title = bold_on .. 
+       dv.title = bold_on ..
                translate("HTTPS not supported") .. bold_off
-       dv.value = translate("Neither GNU Wget with SSL nor cURL installed to support updates via HTTPS protocol.") .. 
-                       "<br />- " .. 
-                       translate("You should install GNU Wget with SSL (prefered) or cURL package.") .. 
+       dv.value = translate("Neither GNU Wget with SSL nor cURL installed to support updates via HTTPS protocol.") ..
+                       "<br />- " ..
+                       translate("You should install GNU Wget with SSL (prefered) or cURL package.") ..
                        "<br />- " ..
                        translate("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")
 end
@@ -83,13 +101,13 @@ end
 -- cURL without proxy support
 if has_ssl and not has_proxy then
        local dv = s:option(DummyValue, "_no_proxy")
-       dv.titleref = luci.dispatcher.build_url("admin", "system", "packages")
+       dv.titleref = DISP.build_url("admin", "system", "packages")
        dv.rawhtml  = true
-       dv.title = bold_on .. 
+       dv.title = bold_on ..
                translate("cURL without Proxy Support") .. bold_off
-       dv.value = translate("cURL is installed, but libcurl was compiled without proxy support.") .. 
-                       "<br />- " .. 
-                       translate("You should install GNU Wget with SSL or replace libcurl.") .. 
+       dv.value = translate("cURL is installed, but libcurl was compiled without proxy support.") ..
+                       "<br />- " ..
+                       translate("You should install GNU Wget with SSL or replace libcurl.") ..
                        "<br />- " ..
                        translate("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")
 end
@@ -97,12 +115,12 @@ end
 -- "Force IP Version not supported"
 if not (has_ssl and has_dnstcp) then
        local dv = s:option(DummyValue, "_no_force_ip")
-       dv.titleref = luci.dispatcher.build_url("admin", "system", "packages")
+       dv.titleref = DISP.build_url("admin", "system", "packages")
        dv.rawhtml  = true
-       dv.title = bold_on .. 
+       dv.title = bold_on ..
                translate("Force IP Version not supported") .. bold_off
        local value = translate("BusyBox's nslookup and Wget do not support to specify " ..
-                       "the IP version to use for communication with DDNS Provider.") 
+                       "the IP version to use for communication with DDNS Provider.")
        if not has_ssl then
                value = value .. "<br />- " ..
                        translate("You should install GNU Wget with SSL (prefered) or cURL package.")
@@ -117,11 +135,11 @@ end
 -- "DNS requests via TCP not supported"
 if not has_dnstcp then
        local dv = s:option(DummyValue, "_no_dnstcp")
-       dv.titleref = luci.dispatcher.build_url("admin", "system", "packages")
+       dv.titleref = DISP.build_url("admin", "system", "packages")
        dv.rawhtml  = true
-       dv.title = bold_on .. 
+       dv.title = bold_on ..
                translate("DNS requests via TCP not supported") .. bold_off
-       dv.value = translate("BusyBox's nslookup does not support to specify to use TCP instead of default UDP when requesting DNS server") .. 
+       dv.value = translate("BusyBox's nslookup does not support to specify to use TCP instead of default UDP when requesting DNS server") ..
                        "<br />- " ..
                        translate("You should install BIND host package for DNS requests.")
 end
index a1ce9c3aef89ebced1d0d7dd25fcd84385e71859..5d24ee5a04f83e27d24966f4908e08471eea220e 100644 (file)
@@ -12,17 +12,20 @@ You may obtain a copy of the License at
 $Id$
 ]]--
 
-require "nixio.fs"
-require "luci.sys"
-require "luci.dispatcher"
-require "luci.tools.ddns"
+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 DDNS = require "luci.tools.ddns"         -- ddns multiused functions
 
 -- show hints ?
-show_hints = not (luci.tools.ddns.check_ipv6()         -- IPv6 support
-               and luci.tools.ddns.check_ssl()         -- HTTPS support
-               and luci.tools.ddns.check_proxy()       -- Proxy support
-               and luci.tools.ddns.check_bind_host()   -- DNS TCP support
+show_hints = not (DDNS.check_ipv6()            -- IPv6 support
+               and DDNS.check_ssl()            -- HTTPS support
+               and DDNS.check_proxy()          -- Proxy support
+               and DDNS.check_bind_host()      -- DNS TCP support
                )
+need_update = CTRL.update_needed()             -- correct ddns-scripts version
 
 -- html constants
 font_red = [[<font color="red">]]
@@ -30,70 +33,96 @@ font_off = [[</font>]]
 bold_on  = [[<strong>]]
 bold_off = [[</strong>]]
 
--- cbi-map definition
-m = Map("ddns", 
-       translate("Dynamic DNS"),
-       translate("Dynamic DNS allows that your router can be reached with " ..
-               "a fixed hostname while having a dynamically changing " ..
-               "IP address."))
+-- cbi-map definition -- #######################################################
+m = Map("ddns")
 
--- read application settings
-date_format = m.uci:get(m.config, "global", "date_format") or "%F %R"
-run_dir            = m.uci:get(m.config, "global", "run_dir") or "/var/run/ddns"
+-- first need to close <a> from cbi map template our <a> closed by template
+--m.title = [[</a><a href="javascript:alert(']] .. CTRL.show_versions() ..[[')">]] ..
+--             translate("Dynamic DNS")
+m.title = [[</a><a href="#" onclick="onclick_maptitle();">]] ..
+               translate("Dynamic DNS")
 
--- SimpleSection definition
+m.description = translate("Dynamic DNS allows that your router can be reached with " ..
+                       "a fixed hostname while having a dynamically changing " ..
+                       "IP address.")
+
+m.on_after_commit = function(self)
+       if self.changed then    -- changes ?
+               if SYS.init.enabled("ddns") then        -- ddns service enabled, restart all
+                       os.execute("/etc/init.d/ddns restart")
+               else    -- ddns service disabled, send SIGHUP to running
+                       os.execute("killall -1 dynamic_dns_updater.sh")
+               end
+       end
+end
+
+-- SimpleSection definiton -- ##################################################
+-- with all the JavaScripts we need for "a good Show"
+a = m:section( SimpleSection )
+a.template = "ddns/overview_status"
+
+-- SimpleSection definition -- #################################################
 -- show Hints to optimize installation and script usage
 -- only show if        service not enabled
 --             or      no IPv6 support
 --             or      not GNU Wget and not cURL       (for https support)
 --             or      not GNU Wget but cURL without proxy support
 --             or      not BIND's host
-if show_hints or not luci.sys.init.enabled("ddns") then
+--             or      ddns-scripts package need update
+if show_hints or need_update or not SYS.init.enabled("ddns") then
        s = m:section( SimpleSection, translate("Hints") )
+
+       -- ddns_scripts needs to be updated for full functionality
+       if need_update then
+               local dv = s:option(DummyValue, "_update_needed")
+               dv.titleref = DISP.build_url("admin", "system", "packages")
+               dv.rawhtml  = true
+               dv.title = font_red .. bold_on ..
+                       translate("Software update required") .. bold_off .. font_off
+               dv.value = translate("The currently installed 'ddns-scripts' package did not support all available settings.") ..
+                               "<br />" ..
+                               translate("Please update to the current version!")
+       end
+
        -- DDNS Service disabled
-       if not luci.sys.init.enabled("ddns") then
+       if not SYS.init.enabled("ddns") then
                local dv = s:option(DummyValue, "_not_enabled")
-               dv.titleref = luci.dispatcher.build_url("admin", "system", "startup")
+               dv.titleref = DISP.build_url("admin", "system", "startup")
                dv.rawhtml  = true
-               dv.title = bold_on .. 
+               dv.title = bold_on ..
                        translate("DDNS Autostart disabled") .. bold_off
-               dv.value = translate("Currently DDNS updates are not started at boot or on interface events." .. "<br />" .. 
+               dv.value = translate("Currently DDNS updates are not started at boot or on interface events." .. "<br />" ..
                                "You can start/stop each configuration here. It will run until next reboot.")
        end
 
        -- Show more hints on a separate page
        if show_hints then
                local dv = s:option(DummyValue, "_separate")
-               dv.titleref = luci.dispatcher.build_url("admin", "services", "ddns", "hints")
+               dv.titleref = DISP.build_url("admin", "services", "ddns", "hints")
                dv.rawhtml  = true
-               dv.title = bold_on .. 
+               dv.title = bold_on ..
                        translate("Show more") .. bold_off
                dv.value = translate("Follow this link" .. "<br />" ..
                                "You will find more hints to optimize your system to run DDNS scripts with all options")
        end
 end
 
--- SimpleSection definiton
--- with all the JavaScripts we need for "a good Show"
-a = m:section( SimpleSection )
-a.template = "ddns/overview_status"
-
--- TableSection definition
-ts = m:section( TypedSection, "service", 
-       translate("Overview"), 
+-- TableSection definition -- ##################################################
+ts = m:section( TypedSection, "service",
+       translate("Overview"),
        translate("Below is a list of configured DDNS configurations and their current state." .. "<br />" ..
                "If you want to send updates for IPv4 and IPv6 you need to define two separate Configurations " ..
                "i.e. 'myddns_ipv4' and 'myddns_ipv6'") )
 ts.sectionhead = translate("Configuration")
 ts.template = "cbi/tblsection"
 ts.addremove = true
-ts.extedit = luci.dispatcher.build_url("admin", "services", "ddns", "detail", "%s")
+ts.extedit = DISP.build_url("admin", "services", "ddns", "detail", "%s")
 function ts.create(self, name)
        AbstractSection.create(self, name)
-       luci.http.redirect( self.extedit:format(name) )
+       HTTP.redirect( self.extedit:format(name) )
 end
 
--- Domain and registered IP
+-- Domain and registered IP -- #################################################
 dom = ts:option(DummyValue, "_domainIP",
        translate("Hostname/Domain") .. "<br />" .. translate("Registered IP") )
 dom.template = "ddns/overview_doubleline"
@@ -113,32 +142,35 @@ function dom.set_two(self, section)
        local force_ipversion = tonumber(self.map:get(section, "force_ipversion") or 0)
        local force_dnstcp = tonumber(self.map:get(section, "force_dnstcp") or 0)
        local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh]]
-       if not nixio.fs.access(command, "rwx", "rx", "rx") then
-               nixio.fs.chmod(command, 755)
+       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 ]] .. domain .. [[ ]] .. use_ipv6 ..
                [[ ]] .. force_ipversion .. [[ ]] .. force_dnstcp .. [[ ]] .. dnsserver
-       local ip = luci.sys.exec(command)
+       local ip = SYS.exec(command)
        if ip == "" then ip = translate("no data") end
        return ip
 end
 
--- enabled 
-ena = ts:option( Flag, "enabled", 
+-- enabled
+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", 
+upd = ts:option( DummyValue, "_update",
        translate("Last Update") .. "<br />" .. translate("Next Update"))
 upd.template = "ddns/overview_doubleline"
 function upd.set_one(self, section)    -- fill Last Update
        -- get/validate last update
-       local uptime   = luci.sys.uptime()
-       local lasttime = tonumber(nixio.fs.readfile("%s/%s.update" % { run_dir, section } ) or 0 )
+       local uptime   = SYS.uptime()
+       local lasttime = DDNS.get_lastupd(section)
        if lasttime > uptime then       -- /var might not be linked to /tmp and cleared on reboot
-               lasttime = 0 
+               lasttime = 0
        end
 
        -- no last update happen
@@ -151,7 +183,7 @@ function upd.set_one(self, section) -- fill Last Update
                --            os.epoch  - sys.uptime + lastupdate(uptime)
                local epoch = os.time() - uptime + lasttime
                -- use linux date to convert epoch
-               return luci.sys.exec([[/bin/date -d @]] .. epoch .. [[ +']] .. date_format .. [[']])
+               return DDNS.epoch2date(epoch)
        end
 end
 function upd.set_two(self, section)    -- fill Next Update
@@ -162,28 +194,28 @@ function upd.set_two(self, section)       -- fill Next Update
        -- get force seconds
        local force_interval = tonumber(self.map:get(section, "force_interval") or 72)
        local force_unit = self.map:get(section, "force_unit") or "hours"
-       local force_seconds = luci.tools.ddns.calc_seconds(force_interval, force_unit)
+       local force_seconds = DDNS.calc_seconds(force_interval, force_unit)
 
        -- get last update and get/validate PID
-       local uptime   = luci.sys.uptime()
-       local lasttime = tonumber(nixio.fs.readfile("%s/%s.update" % { run_dir, section } ) or 0 )
+       local uptime   = SYS.uptime()
+       local lasttime = DDNS.get_lastupd(section)
        if lasttime > uptime then       -- /var might not be linked to /tmp and cleared on reboot
-               lasttime = 0 
+               lasttime = 0
        end
-       local pid      = luci.tools.ddns.get_pid(section, run_dir)
+       local pid      = DDNS.get_pid(section)
 
        -- calc next update
        if lasttime > 0 then
                local epoch = os.time() - uptime + lasttime + force_seconds
                -- use linux date to convert epoch
-               datelast = luci.sys.exec([[/bin/date -d @]] .. epoch .. [[ +']] .. date_format .. [[']])
-       end             
+               datelast = DDNS.epoch2date(epoch)
+       end
 
-       -- process running but update needs to happen 
+       -- process running but update needs to happen
        if pid > 0 and ( lasttime + force_seconds - uptime ) < 0 then
                datenext = translate("Verify")
 
-       -- run once 
+       -- run once
        elseif force_seconds == 0 then
                datenext = translate("Run once")
 
@@ -191,7 +223,7 @@ function upd.set_two(self, section) -- fill Next Update
        elseif pid == 0 and enabled == 0 then
                datenext  = translate("Disabled")
 
-       -- no process running and NOT 
+       -- no process running and NOT
        elseif pid == 0 and enabled ~= 0 then
                datenext = translate("Stopped")
        end
@@ -200,11 +232,11 @@ function upd.set_two(self, section)       -- fill Next Update
 end
 
 -- start/stop button
-btn = ts:option( Button, "_startstop", 
+btn = ts:option( Button, "_startstop",
        translate("Process ID") .. "<br />" .. translate("Start / Stop") )
 btn.template = "ddns/overview_startstop"
 function btn.cfgvalue(self, section)
-       local pid = luci.tools.ddns.get_pid(section, run_dir)
+       local pid = DDNS.get_pid(section)
        if pid > 0 then
                btn.inputtitle  = "PID: " .. pid
                btn.inputstyle  = "reset"
index 4172d84ae14c365a255f839ae1ea4321d9a00800..8d56c92a16bc0f9864fddb54a940d78d5a12daaa 100644 (file)
@@ -1,7 +1,7 @@
 --[[
 LuCI - Lua Configuration Interface
 
-shared module for luci-app-ddns-v2
+shared module for luci-app-ddns
 Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
 
 function parse_url copied from https://svn.nmap.org/nmap/nselib/url.lua
@@ -18,67 +18,128 @@ You may obtain a copy of the License at
 
 module("luci.tools.ddns", package.seeall)
 
-require "luci.sys"
-require "nixio.fs"
+local NX   = require "nixio"
+local NXFS = require "nixio.fs"
+local OPKG = require "luci.model.ipkg"
+local UCI  = require "luci.model.uci"
+local SYS  = require "luci.sys"
+local UTIL = require "luci.util"
 
+-- function to calculate seconds from given interval and unit
+function calc_seconds(interval, unit)
+       if not tonumber(interval) then
+               return nil
+       elseif unit == "days" then
+               return (tonumber(interval) * 86400)     -- 60 sec * 60 min * 24 h
+       elseif unit == "hours" then
+               return (tonumber(interval) * 3600)      -- 60 sec * 60 min
+       elseif unit == "minutes" then
+               return (tonumber(interval) * 60)        -- 60 sec
+       elseif unit == "seconds" then
+               return tonumber(interval)
+       else
+               return nil
+       end
+end
+
+-- check if IPv6 supported by OpenWrt
 function check_ipv6()
-       return nixio.fs.access("/proc/net/ipv6_route") 
-          and nixio.fs.access("/usr/sbin/ip6tables")
+       return NXFS.access("/proc/net/ipv6_route") 
+          and NXFS.access("/usr/sbin/ip6tables")
 end
 
+-- check if Wget with SSL support or cURL installed
 function check_ssl()
-       if (luci.sys.call([[ grep -iq "\+ssl" /usr/bin/wget 2>/dev/null ]]) == 0) then
+       if (SYS.call([[ grep -iq "\+ssl" /usr/bin/wget 2>/dev/null ]]) == 0) then
                return true
        else
-               return nixio.fs.access("/usr/bin/curl")
+               return NXFS.access("/usr/bin/curl")
        end
 end
 
+-- check if Wget with SSL or cURL with proxy support installed
 function check_proxy()
        -- we prefere GNU Wget for communication
-       if (luci.sys.call([[ grep -iq "\+ssl" /usr/bin/wget 2>/dev/null ]]) == 0) then
+       if (SYS.call([[ grep -iq "\+ssl" /usr/bin/wget 2>/dev/null ]]) == 0) then
                return true
 
        -- if not installed cURL must support proxy
-       elseif nixio.fs.access("/usr/bin/curl") then
-               return (luci.sys.call([[ grep -iq all_proxy /usr/lib/libcurl.so* 2>/dev/null ]]) == 0)
+       elseif NXFS.access("/usr/bin/curl") then
+               return (SYS.call([[ grep -iq all_proxy /usr/lib/libcurl.so* 2>/dev/null ]]) == 0)
 
        -- only BusyBox Wget is installed
        else
-               return nixio.fs.access("/usr/bin/wget")
+               return NXFS.access("/usr/bin/wget")
        end
 end
 
+-- check if BIND host installed
 function check_bind_host()
-       return nixio.fs.access("/usr/bin/host")
+       return NXFS.access("/usr/bin/host")
 end
 
--- function to calculate seconds from given interval and unit
-function calc_seconds(interval, unit)
-       if not tonumber(interval) then
-               return nil
-       elseif unit == "days" then
-               return (tonumber(interval) * 86400)     -- 60 sec * 60 min * 24 h
-       elseif unit == "hours" then
-               return (tonumber(interval) * 3600)      -- 60 sec * 60 min
-       elseif unit == "minutes" then
-               return (tonumber(interval) * 60)        -- 60 sec
-       elseif unit == "seconds" then
-               return tonumber(interval)
-       else
-               return nil
+-- convert epoch date to given format
+function epoch2date(epoch, format)
+       if not format or #format < 2 then
+               local uci = UCI.cursor()
+               format    = uci:get("ddns", "global", "date_format") or "%F %R"
+               uci:unload("ddns")
        end
+       format = format:gsub("%%n", "<br />")   -- replace newline
+       format = format:gsub("%%t", "    ")     -- replace tab
+       return os.date(format, epoch)
+end
+
+-- read lastupdate from [section].update file
+function get_lastupd(section)
+       local uci     = UCI.cursor()
+       local run_dir = uci:get("ddns", "global", "run_dir") or "/var/run/ddns"
+       local etime   = tonumber(NXFS.readfile("%s/%s.update" % { run_dir, section } ) or 0 )
+       uci:unload("ddns")
+       return etime
 end
 
 -- read PID from run file and verify if still running
-function get_pid(section, run_dir)
-       local pid = tonumber(nixio.fs.readfile("%s/%s.pid" % { run_dir, section } ) or 0 )
-       if pid > 0 and not luci.sys.process.signal(pid, 0) then
+function get_pid(section)
+       local uci     = UCI.cursor()
+       local run_dir = uci:get("ddns", "global", "run_dir") or "/var/run/ddns"
+       local pid     = tonumber(NXFS.readfile("%s/%s.pid" % { run_dir, section } ) or 0 )
+       if pid > 0 and not NX.kill(pid, 0) then
                pid = 0
        end
+       uci:unload("ddns")
        return pid
 end
 
+-- read version information for given package if installed
+function ipkg_version(package)
+       if not package then 
+               return nil
+       end
+       local info = OPKG.info(package)
+       local data = {}
+       local version = ""
+       local i = 0
+       for k, v in pairs(info) do
+               if v.Package == package and v.Status.installed then             
+                       version = v.Version
+                       i = i + 1
+               end
+       end
+       if i > 1 then   -- more then one valid record
+               return data
+       end
+       local sver = UTIL.split(version, "[%.%-]", nil, true)
+       data = {
+               version = version,
+               major   = tonumber(sver[1]) or 0,
+               minor   = tonumber(sver[2]) or 0,
+               patch   = tonumber(sver[3]) or 0,
+               build   = tonumber(sver[4]) or 0
+       }
+       return data
+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
@@ -103,6 +164,28 @@ 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)
+
+       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)
+               end
+               if (fvalue ~= cvalue) then self.section.changed = true end
+       else
+               self:remove(section)
+               self.section.changed = true 
+       end
+end
+
 -----------------------------------------------------------------------------
 -- copied from https://svn.nmap.org/nmap/nselib/url.lua
 -- @author Diego Nehab
index b0cc2fac357b0d106b9a3627b2e7e330a13a9c54..e23cc796e9b0d05fa0ad2001272a3cb6cc321d2d 100644 (file)
@@ -2,6 +2,12 @@
 <!-- ++ BEGIN ++ Dynamic DNS ++ overview_status.htm ++ -->
 <script type="text/javascript">//<![CDATA[
 
+       // variables to store version information
+       var luci_version
+       var luci_build
+       var ddns_version
+       var ddns_required
+
        // helper to extract section from objects id
        // cbi.ddns.SECTION._xyz
        function _id2section(id) {
        // called by XHR.poll and onclick_startstop
        function _data2elements(data) {
                // DDNS Service
-               // data[0] ignored here
+               // fill Version informations
+               luci_version  = data[0].luci_ver
+               luci_build    = data[0].luci_build
+               ddns_version  = data[0].script_ver
+               ddns_required = data[0].script_min
 
                // Service sections
                for( i = 1; i < data.length; i++ )
@@ -38,7 +48,7 @@
                                btn.className = "cbi-button cbi-input-apply";
                        }
                        btn.disabled = false;   // button enabled
-                       
+
                        // last update
                        switch (data[i].datelast) {
                                case "_empty_":
@@ -71,7 +81,7 @@
                                                nup.innerHTML = '<em><%:Disabled%></em>';
                                                btn.value = '----------';
                                                btn.className = "cbi-button cbi-input-button";  // no image
-                                               btn.disabled = true;    // disabled 
+                                               btn.disabled = true;    // disabled
                                        }
                                        break;
                                default:
 
                        // registered IP
                        // rip.innerHTML = "Registered IP";
-                       if (data[i].domain == "_nodomain_") 
+                       if (data[i].domain == "_nodomain_")
                                rip.innerHTML = '';
                        else if (data[i].reg_ip == "_nodata_")
                                rip.innerHTML = '<em><%:No data%></em>';
                        else
                                rip.innerHTML = data[i].reg_ip;
-               
+
                        // monitored interfacce
                        // data[i].iface ignored here
                }
                } else {
                        btn.value = '----------';
                        btn.className = "cbi-button cbi-input-button";  // no image
-                       btn.disabled = true;            // disabled 
-               }               
+                       btn.disabled = true;            // disabled
+               }
+       }
+
+       // event handler for map.title link
+       function onclick_maptitle() {
+               var str = "<%:Version Information%>";
+               str += "\n\nluci-app-ddns:";
+               str += "\n\t<%:Version%>:\t" + luci_version;
+               str += "\n\t<%:Build%>:\t" + luci_build;
+               str += "\n\nddns-scripts <%:installed%>:";
+               str += "\n\t<%:Version%>:\t" + ddns_version;
+               str += "\n\nddns-scripts <%:required%>:";
+               str += "\n\t<%:Version%>:\t" + ddns_required + " <%:or greater%>";
+               str += "\n\n"
+               alert(str);
        }
 
        // event handler for start/stop button
        function onclick_startstop(id) {
-               // extract section              
+               // extract section
                var section = _id2section(id);
                // get elements
                var cbx = document.getElementById("cbid.ddns." + section + ".enabled");         // Enabled
                );
        }
 
+       // force to immediate show status on page load (not waiting for XHR.poll)
+       XHR.get('<%=luci.dispatcher.build_url("admin", "services", "ddns", "status")%>', null,
+               function(x, data) {
+                       _data2elements(data);
+               }
+       );
+
        // 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 30 seconds only
-       XHR.poll(30, '<%=luci.dispatcher.build_url("admin", "services", "ddns", "status")%>', null,
-               function(x, data)
-               {
+       // we need update every 15 seconds only
+       XHR.poll(15, '<%=luci.dispatcher.build_url("admin", "services", "ddns", "status")%>', null,
+               function(x, data) {
                        _data2elements(data);
-               }                       
+               }
        );
 
 //]]></script>
index d2c2b7e62cddeec4682dc0ea3a4c7ce7bca2dd29..dcf06cc0bb513cc64e0f28e8bc4278addbf0c232 100644 (file)
 
 <!-- ++ BEGIN ++ Dynamic DNS ++ system_status.htm ++ -->
 <script type="text/javascript">//<![CDATA[
-       XHR.poll(10, '<%=luci.dispatcher.build_url("admin", "services", "ddns", "status")%>', null,
-               function(x, data)
+       // helper to move status data to the relevant
+       // screen objects
+       // called by XHR.poll and XHR.get
+       function _data2elements(x, data) {
+               var tbl = document.getElementById('ddns_status_table');
+               // security check
+               if ( !(tbl) ) { return; }
+
+               // clear all rows
+               while (tbl.rows.length > 1) 
+                       tbl.deleteRow(1);
+
+               // variable for Modulo-Division use to set cbi-rowstyle-? (0 or 1)
+               var x = -1;
+               var i = 1;
+
+               // no data => no ddns-scripts Version 2 installed
+               if ( !data ) {
+                       var txt = '<br /><strong><font color="red"><%:Old version of ddns-scripts installed%></font>' ;
+                       var url = '<a href="' ;
+                       url += '<%=luci.dispatcher.build_url("admin", "system", "packages")%>' ;
+                       url += '"><%:install update here%></a></strong>' ;
+                       var tr = tbl.insertRow(-1);
+                       tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((i + x) % 2) + 1);
+                       var td = tr.insertCell(-1);
+                       td.colSpan = 2 ;
+                       td.innerHTML = txt + " - " + url
+                       tr.insertCell(-1).colSpan = 3 ;
+                       return;
+               }
+
+               // DDNS Service disabled
+               if (data[0].enabled == 0) {
+                       var txt = '<strong><font color="red"><%:DDNS Autostart disabled%></font>' ;
+                       var url = '<a href="' + data[0].url_up + '"><%:enable here%></a></strong>' ;
+                       var tr = tbl.insertRow(-1);
+                       tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((i + x) % 2) + 1);
+                       var td = tr.insertCell(-1);
+                       td.colSpan = 2 ;
+                       td.innerHTML = txt + " - " + url
+                       tr.insertCell(-1).colSpan = 3 ;
+                       x++ ;
+               }
+
+               for( i = 1; i < data.length; i++ )
                {
-                       var tbl = document.getElementById('ddns_status_table');
-                       // security check
-                       if ( !(tbl) ) { return; }
-
-                       // clear all rows
-                       while (tbl.rows.length > 1) 
-                               tbl.deleteRow(1);
-
-                       // variable for Modulo-Division use to set cbi-rowstyle-? (0 or 1)
-                       var x = -1;
-                       var i = 1;
-
-                       // no data => no ddns-scripts Version 2 installed
-                       if ( !data ) {
-                               var txt = '<br /><strong><font color="red"><%:Old version of ddns-scripts installed%></font>' ;
-                               var url = '<a href="' ;
-                               url += '<%=luci.dispatcher.build_url("admin", "system", "packages")%>' ;
-                               url += '"><%:install update here%></a></strong>' ;
-                               var tr = tbl.insertRow(-1);
-                               tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((i + x) % 2) + 1);
-                               var td = tr.insertCell(-1);
-                               td.colSpan = 2 ;
-                               td.innerHTML = txt + " - " + url
-                               tr.insertCell(-1).colSpan = 3 ;
-                               return;
+                       var tr = tbl.insertRow(-1);
+                       tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((i + x) % 2) + 1) ;
+
+                       // configuration
+                       tr.insertCell(-1).innerHTML = '<strong>' + data[i].section + '</strong>' ;
+
+                       // pid
+                       // data[i].pid ignored here
+
+                       // last update
+                       // data[i].datelast ignored here
+
+                       // next update
+                       switch (data[i].datenext) {
+                               case "_empty_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:Unknown error%></em>' ;
+                                       break;
+                               case "_stopped_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:Stopped%></em>' ;
+                                       break;
+                               case "_disabled_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:Disabled%></em>' ;
+                                       break;
+                               case "_noupdate_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:Update error%></em>' ;
+                                       break;
+                               case "_runonce_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:Run once%></em>' ;
+                                       break;
+                               case "_verify_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:Verify%></em>';
+                                       break;
+                               default:
+                                       tr.insertCell(-1).innerHTML = data[i].datenext ;
+                                       break;
                        }
 
-                       // DDNS Service disabled
-                       if (data[0].enabled == 0) {
-                               var txt = '<strong><font color="red"><%:DDNS Autostart disabled%></font>' ;
-                               var url = '<a href="' + data[0].url_up + '"><%:enable here%></a></strong>' ;
-                               var tr = tbl.insertRow(-1);
-                               tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((i + x) % 2) + 1);
-                               var td = tr.insertCell(-1);
-                               td.colSpan = 2 ;
-                               td.innerHTML = txt + " - " + url
-                               tr.insertCell(-1).colSpan = 3 ;
-                               x++ ;
-                       }
+                       // domain
+                       if (data[i].domain == "_nodomain_")
+                               tr.insertCell(-1).innerHTML = '<em><%:config error%></em>';
+                       else
+                               tr.insertCell(-1).innerHTML = data[i].domain;
 
-                       for( i = 1; i < data.length; i++ )
-                       {
-                               var tr = tbl.insertRow(-1);
-                               tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((i + x) % 2) + 1) ;
-
-                               // configuration
-                               tr.insertCell(-1).innerHTML = '<strong>' + data[i].section + '</strong>' ;
-
-                               // pid
-                               // data[i].pid ignored here
-
-                               // last update
-                               // data[i].datelast ignored here
-
-                               // next update
-                               switch (data[i].datenext) {
-                                       case "_empty_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:Unknown error%></em>' ;
-                                               break;
-                                       case "_stopped_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:Stopped%></em>' ;
-                                               break;
-                                       case "_disabled_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:Disabled%></em>' ;
-                                               break;
-                                       case "_noupdate_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:Update error%></em>' ;
-                                               break;
-                                       case "_runonce_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:Run once%></em>' ;
-                                               break;
-                                       case "_verify_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:Verify%></em>';
-                                               break;
-                                       default:
-                                               tr.insertCell(-1).innerHTML = data[i].datenext ;
-                                               break;
-                               }
-
-                               // domain
-                               if (data[i].domain == "_nodomain_")
-                                       tr.insertCell(-1).innerHTML = '<em><%:config error%></em>';
-                               else
-                                       tr.insertCell(-1).innerHTML = data[i].domain;
-
-                               // registered IP
-                               switch (data[i].reg_ip) {
-                                       case "_nodomain_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>';
-                                               break;
-                                       case "_nodata_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:No data%></em>';
-                                               break;
-                                       case "_noipv6_":
-                                               tr.insertCell(-1).innerHTML = '<em><%:IPv6 not supported%></em>';
-                                               break;
-                                       default:
-                                               tr.insertCell(-1).innerHTML = data[i].reg_ip;
-                                               break;
-                               }
-
-                               // monitored interfacce
-                               if (data[i].iface == "_nonet_")
+                       // registered IP
+                       switch (data[i].reg_ip) {
+                               case "_nodomain_":
                                        tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>';
-                               else
-                                       tr.insertCell(-1).innerHTML = data[i].iface;
+                                       break;
+                               case "_nodata_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:No data%></em>';
+                                       break;
+                               case "_noipv6_":
+                                       tr.insertCell(-1).innerHTML = '<em><%:IPv6 not supported%></em>';
+                                       break;
+                               default:
+                                       tr.insertCell(-1).innerHTML = data[i].reg_ip;
+                                       break;
                        }
 
-                       if (tbl.rows.length == 1 || (data[0].enabled == 0 && tbl.rows.length == 2) ) {
-                               var br = '<br />';
-                               if (tbl.rows.length > 1) 
-                                       br = '';
-                               var tr = tbl.insertRow(-1);
-                               tr.className = "cbi-section-table-row";
-                               var td = tr.insertCell(-1);
-                               td.colSpan = 5;
-                               td.innerHTML = '<em>' + br + '<%:There is no service configured.%></em>' ;
-                       }
+                       // monitored interfacce
+                       if (data[i].iface == "_nonet_")
+                               tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>';
+                       else
+                               tr.insertCell(-1).innerHTML = data[i].iface;
+               }
+
+               if (tbl.rows.length == 1 || (data[0].enabled == 0 && tbl.rows.length == 2) ) {
+                       var br = '<br />';
+                       if (tbl.rows.length > 1) 
+                               br = '';
+                       var tr = tbl.insertRow(-1);
+                       tr.className = "cbi-section-table-row";
+                       var td = tr.insertCell(-1);
+                       td.colSpan = 5;
+                       td.innerHTML = '<em>' + br + '<%:There is no service configured.%></em>' ;
+               }
+       }
+
+       // force to immediate show status (not waiting for XHR.poll)
+       XHR.get('<%=luci.dispatcher.build_url("admin", "services", "ddns", "status")%>', null,
+               function(x, data) {
+                       _data2elements(x, data);
+               }
+       );
+
+       XHR.poll(10, '<%=luci.dispatcher.build_url("admin", "services", "ddns", "status")%>', null,
+               function(x, data) {
+                       _data2elements(x, data);
                }
        );
 //]]></script>
index f3bad58071c6e60db6f918f36f6ccab9e85954b2..4849e59b7f771874e444d18b4c2f3f6e75fdc359 100755 (executable)
@@ -1,10 +1,8 @@
 #!/bin/sh
 
-# needed for "Save and Apply" to restart ddns
+# no longer needed for "Save and Apply" to restart ddns
 uci -q batch <<-EOF >/dev/null
        delete ucitrack.@ddns[-1]
-       add ucitrack ddns
-       set ucitrack.@ddns[-1].init="ddns"
        commit ucitrack
 EOF
 
index 1782d1f038492dd53ce6cffe594930dd84b0ddb5..3fc84748eeb5986542d939efccb5100a434f390f 100755 (executable)
@@ -1,13 +1,14 @@
 #!/bin/sh
 # /usr/lib/ddns/luci_dns_helper.sh
 #
-# Written by Christian Schoenebeck in August 2014 to support:
-# this script is used by luci-app-ddns
+# Written in August 2014
+# by Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
+# This script is used by luci-app-ddns
 # - getting registered IP
 # - check if possible to get local IP
 # - verifing given DNS- or Proxy-Server
 #
-# variables in small chars are read from /etc/config/ddns
+# variables in small chars are read from /etc/config/ddns as parameter given here
 # variables in big chars are defined inside these scripts as gloval vars
 # variables in big chars beginning with "__" are local defined inside functions only
 # set -vx      #script debugger
 
 # set -vx      #script debugger
 
-# preset some variables wrong or not set in dynamic_dns_functions.sh
-SECTION_ID="dynamic_dns_lucihelper"
+# preset some variables, wrong or not set in dynamic_dns_functions.sh
+SECTION_ID="lucihelper"
 LOGFILE="$LOGDIR/$SECTION_ID.log"
-LUCI_HELPER="ACTIV"    # supress verbose and critical logging
+VERBOSE_MODE=0         # no console logging
 # global variables normally set by reading DDNS UCI configuration
-use_logfile=0
-use_syslog=0
+use_syslog=0           # no syslog
+use_logfile=0          # by default no logfile, can be changed here
 
 case "$1" in
        get_registered_ip)
@@ -34,21 +35,24 @@ case "$1" in
                force_ipversion=${4:-"0"}       # Force IP Version - default 0 - No
                force_dnstcp=${5:-"0"}          # Force TCP on DNS - default 0 - No
                dns_server=${6:-""}             # DNS server - default No DNS
+               write_log 7 "-----> get_registered_ip IP"
                get_registered_ip IP
                [ $? -ne 0 ] && IP=""
                echo -n "$IP"                   # suppress LF
                ;;
        verify_dns)
-               # $2 == dns-server to verify    # no need for force_dnstcp because
+               # $2 : dns-server to verify     # no need for force_dnstcp because
                                                # verify with nc (netcat) uses tcp anyway
                use_ipv6=${3:-"0"}              # Use IPv6 - default IPv4
                force_ipversion=${4:-"0"}       # Force IP Version - default 0 - No
+               write_log 7 "-----> verify_dns '$2'"
                verify_dns "$2"
                ;;
        verify_proxy)
-               # $2 == proxy string to verify
+               # $2 : proxy string to verify
                use_ipv6=${3:-"0"}              # Use IPv6 - default IPv4
                force_ipversion=${4:-"0"}       # Force IP Version - default 0 - No
+               write_log 7 "-----> verify_proxy '$2'"
                verify_proxy "$2"
                ;;
        get_local_ip)
@@ -62,7 +66,7 @@ case "$1" in
                proxy="$8"                      # proxy if set
                force_ipversion="0"             # not needed but must be set
                use_https="0"                   # not needed but must be set
-               [ -n "$proxy" -a "$ip_source" == "web" ] && {
+               [ -n "$proxy" -a "$ip_source" = "web" ] && {
                        # proxy defined, used for ip_source=web
                        export HTTP_PROXY="http://$proxy"
                        export HTTPS_PROXY="http://$proxy"
@@ -70,13 +74,17 @@ case "$1" in
                        export https_proxy="http://$proxy"
                }
                # don't need IP only the return code
-               [ "$ip_source" == "web" -o  "$ip_source" == "script"] && {              
-                       # we wait only 3 seconds for an 
+               [ "$ip_source" = "web" -o  "$ip_source" = "script" ] && {
+                       # we wait only 3 seconds for an
                        # answer from "web" or "script"
-                       __timeout 3 -- get_local_ip IP
-               } || get_local_ip IP
+                       write_log 7 "-----> timeout 3 -- get_local_ip IP"
+                       timeout 3 -- get_local_ip IP
+               } || {
+                       write_log 7 "-----> get_local_ip IP"
+                       get_local_ip IP
+               }
                ;;
-       *)      
-               return 1
+       *)
+               return 255
                ;;
 esac
index d6eb2f7b16db004b6dde21bb60eb008c88132755..9706dbd106cdb87519d9a3e8869b50406e0df957 100644 (file)
@@ -1,8 +1,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: luci-app-ddns\n"
-"POT-Creation-Date: 2014-10-04 16:26+1000\n"
-"PO-Revision-Date: 2014-10-04 16:27+0100\n"
+"POT-Creation-Date: 2014-11-09 13:41+0100\n"
+"PO-Revision-Date: 2014-11-09 14:29+0100\n"
 "Last-Translator: Christian Schoenebeck <christian.schoenebeck@gmail.com>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "Language: de\n"
@@ -36,6 +36,9 @@ msgstr ""
 ">Wenn Sie Aktualisierungen für IPv4 und IPv6 senden möchten benötigen Sie "
 "zwei Konfigurationen z.B. 'myddns_ipv4' und 'myddns_ipv6'"
 
+msgid "Build"
+msgstr "Build"
+
 msgid ""
 "BusyBox's nslookup and Wget do not support to specify the IP version to use "
 "for communication with DDNS Provider."
@@ -347,6 +350,9 @@ msgstr "Bitte [Speichern & Anwenden] Sie Änderungen zunächst"
 msgid "Please press [Read] button"
 msgstr "Bitte Protokolldatei einlesen"
 
+msgid "Please update to the current version!"
+msgstr "Aktualisieren Sie bitte auf die aktuelle Version!"
+
 msgid "Process ID"
 msgstr "Prozess ID"
 
@@ -377,6 +383,9 @@ msgstr "Dienst"
 msgid "Show more"
 msgstr "Zeige mehr"
 
+msgid "Software update required"
+msgstr "Softwareaktualisierung nötig"
+
 msgid "Source of IP address"
 msgstr "Quelle der IP-Adresse"
 
@@ -386,6 +395,13 @@ msgstr "Start / Stopp"
 msgid "Stopped"
 msgstr "Angehalten"
 
+msgid ""
+"The currently installed 'ddns-scripts' package did not support all available "
+"settings."
+msgstr ""
+"Die installierte Software 'ddns-scripts' unterstützt nicht alle verfügbaren "
+"Optionen."
+
 msgid "There is no service configured."
 msgstr "Kein Dienst konfiguriert"
 
@@ -419,6 +435,9 @@ msgstr ""
 "Definiert das Skript mit dem die  aktuelle IP-Adresse des System gelesen "
 "wird."
 
+msgid "Version Information"
+msgstr "Versionsinformationen"
+
 msgid ""
 "Writes detailed messages to log file. File will be truncated automatically."
 msgstr ""
@@ -490,6 +509,9 @@ msgstr "Stunden"
 msgid "install update here"
 msgstr "Aktualisierung hier installieren"
 
+msgid "installed"
+msgstr "installiert"
+
 msgid "interface"
 msgstr "Schnittstelle"
 
@@ -542,6 +564,9 @@ msgstr "nslookup kann den Namen nicht auflösen"
 msgid "or"
 msgstr "oder"
 
+msgid "or greater"
+msgstr "oder größer"
+
 msgid "please disable"
 msgstr "Bitte deaktivieren"
 
@@ -557,6 +582,9 @@ msgstr "Bitte 'IPv4' Adressversion auswählen in den"
 msgid "proxy port missing"
 msgstr "Proxy-Port fehlt"
 
+msgid "required"
+msgstr "erforderlich"
+
 msgid "seconds"
 msgstr "Sekunden"
 
index 0f772009436636fb4c48bd3c5acdcaaec9f5c462..c3b8c9367d5df814140f82736d716bdb63c87d8a 100644 (file)
@@ -18,6 +18,9 @@ msgid ""
 "separate Configurations i.e. 'myddns_ipv4' and 'myddns_ipv6'"
 msgstr ""
 
+msgid "Build"
+msgstr ""
+
 msgid ""
 "BusyBox's nslookup and Wget do not support to specify the IP version to use "
 "for communication with DDNS Provider."
@@ -279,6 +282,9 @@ msgstr ""
 msgid "Please press [Read] button"
 msgstr ""
 
+msgid "Please update to the current version!"
+msgstr ""
+
 msgid "Process ID"
 msgstr ""
 
@@ -309,6 +315,9 @@ msgstr ""
 msgid "Show more"
 msgstr ""
 
+msgid "Software update required"
+msgstr ""
+
 msgid "Source of IP address"
 msgstr ""
 
@@ -318,6 +327,11 @@ msgstr ""
 msgid "Stopped"
 msgstr ""
 
+msgid ""
+"The currently installed 'ddns-scripts' package did not support all available "
+"settings."
+msgstr ""
+
 msgid "There is no service configured."
 msgstr ""
 
@@ -347,6 +361,9 @@ msgstr ""
 msgid "User defined script to read systems IP-Address"
 msgstr ""
 
+msgid "Version Information"
+msgstr ""
+
 msgid ""
 "Writes detailed messages to log file. File will be truncated automatically."
 msgstr ""
@@ -407,6 +424,9 @@ msgstr ""
 msgid "install update here"
 msgstr ""
 
+msgid "installed"
+msgstr ""
+
 msgid "interface"
 msgstr ""
 
@@ -458,6 +478,9 @@ msgstr ""
 msgid "or"
 msgstr ""
 
+msgid "or greater"
+msgstr ""
+
 msgid "please disable"
 msgstr ""
 
@@ -473,6 +496,9 @@ msgstr ""
 msgid "proxy port missing"
 msgstr ""
 
+msgid "required"
+msgstr ""
+
 msgid "seconds"
 msgstr ""