Merge pull request #250 from openwrt-es/luci-next2
authorJo-Philipp Wich <jow@openwrt.org>
Fri, 14 Nov 2014 16:17:39 +0000 (17:17 +0100)
committerJo-Philipp Wich <jow@openwrt.org>
Fri, 14 Nov 2014 16:17:39 +0000 (17:17 +0100)
Fix disabling service instance for dump1090/udpxy/shairplay/shairport

16 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
modules/admin-full/luasrc/view/admin_network/wifi_overview.htm
modules/base/luasrc/sys/zoneinfo/tzdata.lua
modules/base/luasrc/sys/zoneinfo/tzoffset.lua
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 0a723b6..3f57d63 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 e59a280..952c9ff 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 c8d10f2..8619d44 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 d0d323c..dfbc746 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 a1ce9c3..5d24ee5 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 4172d84..8d56c92 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 b0cc2fa..e23cc79 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 d2c2b7e..dcf06cc 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 f3bad58..4849e59 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 1782d1f..3fc8474 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 8fb6483..312fd08 100644 (file)
@@ -232,7 +232,7 @@ You may obtain a copy of the License at
                                                        toggle.title = '<%:Activate this network%>';
                                                }
 
-                                               toggle.setAttribute('active', is_assoc);
+                                               toggle.setAttribute('active', !iw.disabled);
                                        }
 
                                        var info = document.getElementById(iw.id + '-iw-status');
index 1a99f6a..8c7cc2a 100644 (file)
@@ -24,14 +24,15 @@ TZ = {
        { 'Africa/Blantyre', 'CAT-2' },
        { 'Africa/Brazzaville', 'WAT-1' },
        { 'Africa/Bujumbura', 'CAT-2' },
-       { 'Africa/Casablanca', 'WET0' },
+       { 'Africa/Cairo', 'EET-2EEST,M4.5.5/0,M9.5.4/24' },
+       { 'Africa/Casablanca', 'WET0WEST,M3.5.0,M10.5.0/3' },
        { 'Africa/Ceuta', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Africa/Conakry', 'GMT0' },
        { 'Africa/Dakar', 'GMT0' },
        { 'Africa/Dar es Salaam', 'EAT-3' },
        { 'Africa/Djibouti', 'EAT-3' },
        { 'Africa/Douala', 'WAT-1' },
-       { 'Africa/El Aaiun', 'WET0' },
+       { 'Africa/El Aaiun', 'WET0WEST,M3.5.0,M10.5.0/3' },
        { 'Africa/Freetown', 'GMT0' },
        { 'Africa/Gaborone', 'CAT-2' },
        { 'Africa/Harare', 'CAT-2' },
@@ -77,12 +78,13 @@ TZ = {
        { 'America/Argentina/Rio Gallegos', 'ART3' },
        { 'America/Argentina/Salta', 'ART3' },
        { 'America/Argentina/San Juan', 'ART3' },
+       { 'America/Argentina/San Luis', 'ART3' },
        { 'America/Argentina/Tucuman', 'ART3' },
        { 'America/Argentina/Ushuaia', 'ART3' },
        { 'America/Aruba', 'AST4' },
-       { 'America/Asuncion', 'PYT4PYST,M10.1.0/0,M4.2.0/0' },
+       { 'America/Asuncion', 'PYT4PYST,M10.1.0/0,M3.4.0/0' },
        { 'America/Atikokan', 'EST5' },
-       { 'America/Bahia', 'BRT3BRST,M10.3.0/0,M2.3.0/0' },
+       { 'America/Bahia', 'BRT3' },
        { 'America/Bahia Banderas', 'CST6CDT,M4.1.0,M10.5.0' },
        { 'America/Barbados', 'AST4' },
        { 'America/Belem', 'BRT3' },
@@ -100,6 +102,7 @@ TZ = {
        { 'America/Chicago', 'CST6CDT,M3.2.0,M11.1.0' },
        { 'America/Chihuahua', 'MST7MDT,M4.1.0,M10.5.0' },
        { 'America/Costa Rica', 'CST6' },
+       { 'America/Creston', 'MST7' },
        { 'America/Cuiaba', 'AMT4AMST,M10.3.0/0,M2.3.0/0' },
        { 'America/Curacao', 'AST4' },
        { 'America/Danmarkshavn', 'GMT0' },
@@ -109,19 +112,20 @@ TZ = {
        { 'America/Detroit', 'EST5EDT,M3.2.0,M11.1.0' },
        { 'America/Dominica', 'AST4' },
        { 'America/Edmonton', 'MST7MDT,M3.2.0,M11.1.0' },
-       { 'America/Eirunepe', 'AMT4' },
+       { 'America/Eirunepe', 'ACT5' },
        { 'America/El Salvador', 'CST6' },
        { 'America/Fortaleza', 'BRT3' },
        { 'America/Glace Bay', 'AST4ADT,M3.2.0,M11.1.0' },
+       { 'America/Godthab', 'WGT3WGST,M3.5.0/-2,M10.5.0/-1' },
        { 'America/Goose Bay', 'AST4ADT,M3.2.0,M11.1.0' },
-       { 'America/Grand Turk', 'EST5EDT,M3.2.0,M11.1.0' },
+       { 'America/Grand Turk', 'AST4' },
        { 'America/Grenada', 'AST4' },
        { 'America/Guadeloupe', 'AST4' },
        { 'America/Guatemala', 'CST6' },
        { 'America/Guayaquil', 'ECT5' },
        { 'America/Guyana', 'GYT4' },
        { 'America/Halifax', 'AST4ADT,M3.2.0,M11.1.0' },
-       { 'America/Havana', 'CST5CDT,M3.2.0/0,M10.5.0/1' },
+       { 'America/Havana', 'CST5CDT,M3.2.0/0,M11.1.0/1' },
        { 'America/Hermosillo', 'MST7' },
        { 'America/Indiana/Indianapolis', 'EST5EDT,M3.2.0,M11.1.0' },
        { 'America/Indiana/Knox', 'CST6CDT,M3.2.0,M11.1.0' },
@@ -151,13 +155,12 @@ TZ = {
        { 'America/Mazatlan', 'MST7MDT,M4.1.0,M10.5.0' },
        { 'America/Menominee', 'CST6CDT,M3.2.0,M11.1.0' },
        { 'America/Merida', 'CST6CDT,M4.1.0,M10.5.0' },
-       { 'America/Metlakatla', 'MeST8' },
+       { 'America/Metlakatla', 'PST8' },
        { 'America/Mexico City', 'CST6CDT,M4.1.0,M10.5.0' },
        { 'America/Miquelon', 'PMST3PMDT,M3.2.0,M11.1.0' },
        { 'America/Moncton', 'AST4ADT,M3.2.0,M11.1.0' },
        { 'America/Monterrey', 'CST6CDT,M4.1.0,M10.5.0' },
        { 'America/Montevideo', 'UYT3UYST,M10.1.0,M3.2.0' },
-       { 'America/Montreal', 'EST5EDT,M3.2.0,M11.1.0' },
        { 'America/Montserrat', 'AST4' },
        { 'America/Nassau', 'EST5EDT,M3.2.0,M11.1.0' },
        { 'America/New York', 'EST5EDT,M3.2.0,M11.1.0' },
@@ -173,7 +176,7 @@ TZ = {
        { 'America/Paramaribo', 'SRT3' },
        { 'America/Phoenix', 'MST7' },
        { 'America/Port of Spain', 'AST4' },
-       { 'America/Port-au-Prince', 'EST5' },
+       { 'America/Port-au-Prince', 'EST5EDT,M3.2.0,M11.1.0' },
        { 'America/Porto Velho', 'AMT4' },
        { 'America/Puerto Rico', 'AST4' },
        { 'America/Rainy River', 'CST6CDT,M3.2.0,M11.1.0' },
@@ -181,13 +184,13 @@ TZ = {
        { 'America/Recife', 'BRT3' },
        { 'America/Regina', 'CST6' },
        { 'America/Resolute', 'CST6CDT,M3.2.0,M11.1.0' },
-       { 'America/Rio Branco', 'AMT4' },
+       { 'America/Rio Branco', 'ACT5' },
        { 'America/Santa Isabel', 'PST8PDT,M4.1.0,M10.5.0' },
        { 'America/Santarem', 'BRT3' },
+       { 'America/Santiago', 'CLT4CLST,M9.1.6/24,M4.4.6/24' },
        { 'America/Santo Domingo', 'AST4' },
        { 'America/Sao Paulo', 'BRT3BRST,M10.3.0/0,M2.3.0/0' },
        { 'America/Scoresbysund', 'EGT1EGST,M3.5.0/0,M10.5.0/1' },
-       { 'America/Shiprock', 'MST7MDT,M3.2.0,M11.1.0' },
        { 'America/Sitka', 'AKST9AKDT,M3.2.0,M11.1.0' },
        { 'America/St Barthelemy', 'AST4' },
        { 'America/St Johns', 'NST3:30NDT,M3.2.0,M11.1.0' },
@@ -207,19 +210,21 @@ TZ = {
        { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' },
        { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' },
        { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' },
-       { 'Antarctica/Casey', 'WST-8' },
+       { 'Antarctica/Casey', 'AWST-8' },
        { 'Antarctica/Davis', 'DAVT-7' },
        { 'Antarctica/DumontDUrville', 'DDUT-10' },
        { 'Antarctica/Macquarie', 'MIST-11' },
        { 'Antarctica/Mawson', 'MAWT-5' },
        { 'Antarctica/McMurdo', 'NZST-12NZDT,M9.5.0,M4.1.0/3' },
+       { 'Antarctica/Palmer', 'CLT4CLST,M9.1.6/24,M4.4.6/24' },
        { 'Antarctica/Rothera', 'ROTT3' },
-       { 'Antarctica/South Pole', 'NZST-12NZDT,M9.5.0,M4.1.0/3' },
        { 'Antarctica/Syowa', 'SYOT-3' },
+       { 'Antarctica/Troll', 'UTC0CEST-2,M3.5.0/1,M10.5.0/3' },
        { 'Antarctica/Vostok', 'VOST-6' },
        { 'Arctic/Longyearbyen', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Asia/Aden', 'AST-3' },
        { 'Asia/Almaty', 'ALMT-6' },
+       { 'Asia/Amman', 'EET-2EEST,M3.5.4/24,M10.5.5/1' },
        { 'Asia/Anadyr', 'ANAT-12' },
        { 'Asia/Aqtau', 'AQTT-5' },
        { 'Asia/Aqtobe', 'AQTT-5' },
@@ -231,67 +236,69 @@ TZ = {
        { 'Asia/Beirut', 'EET-2EEST,M3.5.0/0,M10.5.0/0' },
        { 'Asia/Bishkek', 'KGT-6' },
        { 'Asia/Brunei', 'BNT-8' },
+       { 'Asia/Chita', 'IRKT-8' },
        { 'Asia/Choibalsan', 'CHOT-8' },
-       { 'Asia/Chongqing', 'CST-8' },
        { 'Asia/Colombo', 'IST-5:30' },
-       { 'Asia/Damascus', 'EET-2EEST,M4.1.5/0,M10.5.5/0' },
+       { 'Asia/Damascus', 'EET-2EEST,M3.5.5/0,M10.5.5/0' },
        { 'Asia/Dhaka', 'BDT-6' },
        { 'Asia/Dili', 'TLT-9' },
        { 'Asia/Dubai', 'GST-4' },
        { 'Asia/Dushanbe', 'TJT-5' },
-       { 'Asia/Gaza', 'EET-2' },
-       { 'Asia/Harbin', 'CST-8' },
-       { 'Asia/Hebron', 'EET-2' },
+       { 'Asia/Gaza', 'EET-2EEST,M3.5.4/24,M9.3.6/144' },
+       { 'Asia/Hebron', 'EET-2EEST,M3.5.4/24,M9.3.6/144' },
        { 'Asia/Ho Chi Minh', 'ICT-7' },
        { 'Asia/Hong Kong', 'HKT-8' },
        { 'Asia/Hovd', 'HOVT-7' },
-       { 'Asia/Irkutsk', 'IRKT-9' },
-       { 'Asia/Jakarta', 'WIT-7' },
-       { 'Asia/Jayapura', 'EIT-9' },
+       { 'Asia/Irkutsk', 'IRKT-8' },
+       { 'Asia/Jakarta', 'WIB-7' },
+       { 'Asia/Jayapura', 'WIT-9' },
+       { 'Asia/Jerusalem', 'IST-2IDT,M3.4.4/26,M10.5.0' },
        { 'Asia/Kabul', 'AFT-4:30' },
        { 'Asia/Kamchatka', 'PETT-12' },
        { 'Asia/Karachi', 'PKT-5' },
-       { 'Asia/Kashgar', 'CST-8' },
        { 'Asia/Kathmandu', 'NPT-5:45' },
+       { 'Asia/Khandyga', 'YAKT-9' },
        { 'Asia/Kolkata', 'IST-5:30' },
-       { 'Asia/Krasnoyarsk', 'KRAT-8' },
+       { 'Asia/Krasnoyarsk', 'KRAT-7' },
        { 'Asia/Kuala Lumpur', 'MYT-8' },
        { 'Asia/Kuching', 'MYT-8' },
        { 'Asia/Kuwait', 'AST-3' },
        { 'Asia/Macau', 'CST-8' },
-       { 'Asia/Magadan', 'MAGT-12' },
-       { 'Asia/Makassar', 'CIT-8' },
+       { 'Asia/Magadan', 'MAGT-10' },
+       { 'Asia/Makassar', 'WITA-8' },
        { 'Asia/Manila', 'PHT-8' },
        { 'Asia/Muscat', 'GST-4' },
        { 'Asia/Nicosia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
-       { 'Asia/Novokuznetsk', 'NOVT-7' },
-       { 'Asia/Novosibirsk', 'NOVT-7' },
-       { 'Asia/Omsk', 'OMST-7' },
+       { 'Asia/Novokuznetsk', 'KRAT-7' },
+       { 'Asia/Novosibirsk', 'NOVT-6' },
+       { 'Asia/Omsk', 'OMST-6' },
        { 'Asia/Oral', 'ORAT-5' },
        { 'Asia/Phnom Penh', 'ICT-7' },
-       { 'Asia/Pontianak', 'WIT-7' },
+       { 'Asia/Pontianak', 'WIB-7' },
        { 'Asia/Pyongyang', 'KST-9' },
        { 'Asia/Qatar', 'AST-3' },
        { 'Asia/Qyzylorda', 'QYZT-6' },
        { 'Asia/Rangoon', 'MMT-6:30' },
        { 'Asia/Riyadh', 'AST-3' },
-       { 'Asia/Sakhalin', 'SAKT-11' },
+       { 'Asia/Sakhalin', 'SAKT-10' },
        { 'Asia/Samarkand', 'UZT-5' },
        { 'Asia/Seoul', 'KST-9' },
        { 'Asia/Shanghai', 'CST-8' },
        { 'Asia/Singapore', 'SGT-8' },
+       { 'Asia/Srednekolymsk', 'SRET-11' },
        { 'Asia/Taipei', 'CST-8' },
        { 'Asia/Tashkent', 'UZT-5' },
        { 'Asia/Tbilisi', 'GET-4' },
        { 'Asia/Thimphu', 'BTT-6' },
        { 'Asia/Tokyo', 'JST-9' },
        { 'Asia/Ulaanbaatar', 'ULAT-8' },
-       { 'Asia/Urumqi', 'CST-8' },
+       { 'Asia/Urumqi', 'XJT-6' },
+       { 'Asia/Ust-Nera', 'VLAT-10' },
        { 'Asia/Vientiane', 'ICT-7' },
-       { 'Asia/Vladivostok', 'VLAT-11' },
-       { 'Asia/Yakutsk', 'YAKT-10' },
-       { 'Asia/Yekaterinburg', 'YEKT-6' },
-       { 'Asia/Yerevan', 'AMT-4AMST,M3.5.0,M10.5.0/3' },
+       { 'Asia/Vladivostok', 'VLAT-10' },
+       { 'Asia/Yakutsk', 'YAKT-9' },
+       { 'Asia/Yekaterinburg', 'YEKT-5' },
+       { 'Asia/Yerevan', 'AMT-4' },
        { 'Atlantic/Azores', 'AZOT1AZOST,M3.5.0/0,M10.5.0/1' },
        { 'Atlantic/Bermuda', 'AST4ADT,M3.2.0,M11.1.0' },
        { 'Atlantic/Canary', 'WET0WEST,M3.5.0/1,M10.5.0' },
@@ -301,19 +308,19 @@ TZ = {
        { 'Atlantic/Reykjavik', 'GMT0' },
        { 'Atlantic/South Georgia', 'GST2' },
        { 'Atlantic/St Helena', 'GMT0' },
-       { 'Atlantic/Stanley', 'FKT4FKST,M9.1.0,M4.3.0' },
-       { 'Australia/Adelaide', 'CST-9:30CST,M10.1.0,M4.1.0/3' },
-       { 'Australia/Brisbane', 'EST-10' },
-       { 'Australia/Broken Hill', 'CST-9:30CST,M10.1.0,M4.1.0/3' },
-       { 'Australia/Currie', 'EST-10EST,M10.1.0,M4.1.0/3' },
-       { 'Australia/Darwin', 'CST-9:30' },
-       { 'Australia/Eucla', 'CWST-8:45' },
-       { 'Australia/Hobart', 'EST-10EST,M10.1.0,M4.1.0/3' },
-       { 'Australia/Lindeman', 'EST-10' },
-       { 'Australia/Lord Howe', 'LHST-10:30LHST-11,M10.1.0,M4.1.0' },
-       { 'Australia/Melbourne', 'EST-10EST,M10.1.0,M4.1.0/3' },
-       { 'Australia/Perth', 'WST-8' },
-       { 'Australia/Sydney', 'EST-10EST,M10.1.0,M4.1.0/3' },
+       { 'Atlantic/Stanley', 'FKST3' },
+       { 'Australia/Adelaide', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' },
+       { 'Australia/Brisbane', 'AEST-10' },
+       { 'Australia/Broken Hill', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' },
+       { 'Australia/Currie', 'AEST-10AEDT,M10.1.0,M4.1.0/3' },
+       { 'Australia/Darwin', 'ACST-9:30' },
+       { 'Australia/Eucla', 'ACWST-8:45' },
+       { 'Australia/Hobart', 'AEST-10AEDT,M10.1.0,M4.1.0/3' },
+       { 'Australia/Lindeman', 'AEST-10' },
+       { 'Australia/Lord Howe', 'LHST-10:30LHDT-11,M10.1.0,M4.1.0' },
+       { 'Australia/Melbourne', 'AEST-10AEDT,M10.1.0,M4.1.0/3' },
+       { 'Australia/Perth', 'AWST-8' },
+       { 'Australia/Sydney', 'AEST-10AEDT,M10.1.0,M4.1.0/3' },
        { 'Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Andorra', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Athens', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
@@ -323,6 +330,7 @@ TZ = {
        { 'Europe/Brussels', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Bucharest', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
        { 'Europe/Budapest', 'CET-1CEST,M3.5.0,M10.5.0/3' },
+       { 'Europe/Busingen', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Chisinau', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
        { 'Europe/Copenhagen', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Dublin', 'GMT0IST,M3.5.0/1,M10.5.0' },
@@ -332,7 +340,7 @@ TZ = {
        { 'Europe/Isle of Man', 'GMT0BST,M3.5.0/1,M10.5.0' },
        { 'Europe/Istanbul', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
        { 'Europe/Jersey', 'GMT0BST,M3.5.0/1,M10.5.0' },
-       { 'Europe/Kaliningrad', 'FET-3' },
+       { 'Europe/Kaliningrad', 'EET-2' },
        { 'Europe/Kiev', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
        { 'Europe/Lisbon', 'WET0WEST,M3.5.0/1,M10.5.0' },
        { 'Europe/Ljubljana', 'CET-1CEST,M3.5.0,M10.5.0/3' },
@@ -341,9 +349,9 @@ TZ = {
        { 'Europe/Madrid', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Malta', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Mariehamn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
-       { 'Europe/Minsk', 'FET-3' },
+       { 'Europe/Minsk', 'MSK-3' },
        { 'Europe/Monaco', 'CET-1CEST,M3.5.0,M10.5.0/3' },
-       { 'Europe/Moscow', 'MSK-4' },
+       { 'Europe/Moscow', 'MSK-3' },
        { 'Europe/Oslo', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Paris', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Podgorica', 'CET-1CEST,M3.5.0,M10.5.0/3' },
@@ -353,7 +361,7 @@ TZ = {
        { 'Europe/Samara', 'SAMT-4' },
        { 'Europe/San Marino', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Sarajevo', 'CET-1CEST,M3.5.0,M10.5.0/3' },
-       { 'Europe/Simferopol', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
+       { 'Europe/Simferopol', 'MSK-3' },
        { 'Europe/Skopje', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Sofia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
        { 'Europe/Stockholm', 'CET-1CEST,M3.5.0,M10.5.0/3' },
@@ -364,7 +372,7 @@ TZ = {
        { 'Europe/Vatican', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Vienna', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Vilnius', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
-       { 'Europe/Volgograd', 'VOLT-4' },
+       { 'Europe/Volgograd', 'MSK-3' },
        { 'Europe/Warsaw', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Zagreb', 'CET-1CEST,M3.5.0,M10.5.0/3' },
        { 'Europe/Zaporozhye', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
@@ -380,14 +388,16 @@ TZ = {
        { 'Indian/Mauritius', 'MUT-4' },
        { 'Indian/Mayotte', 'EAT-3' },
        { 'Indian/Reunion', 'RET-4' },
-       { 'Pacific/Apia', 'WST-13' },
+       { 'Pacific/Apia', 'WSST-13WSDT,M9.5.0/3,M4.1.0/4' },
        { 'Pacific/Auckland', 'NZST-12NZDT,M9.5.0,M4.1.0/3' },
+       { 'Pacific/Bougainville', 'BST-11' },
        { 'Pacific/Chatham', 'CHAST-12:45CHADT,M9.5.0/2:45,M4.1.0/3:45' },
        { 'Pacific/Chuuk', 'CHUT-10' },
+       { 'Pacific/Easter', 'EAST6EASST,M9.1.6/22,M4.4.6/22' },
        { 'Pacific/Efate', 'VUT-11' },
        { 'Pacific/Enderbury', 'PHOT-13' },
-       { 'Pacific/Fakaofo', 'TKT10' },
-       { 'Pacific/Fiji', 'FJT-12' },
+       { 'Pacific/Fakaofo', 'TKT-13' },
+       { 'Pacific/Fiji', 'FJT-12FJST,M11.1.0,M1.3.4/75' },
        { 'Pacific/Funafuti', 'TVT-12' },
        { 'Pacific/Galapagos', 'GALT6' },
        { 'Pacific/Gambier', 'GAMT9' },
index bbe75d5..d2f77ed 100644 (file)
@@ -17,9 +17,10 @@ OFFSET = {
        cet   =   3600, -- CET
        wat   =   3600, -- WAT
        cat   =   7200, -- CAT
+       eet   =   7200, -- EET
+       eest  =  10800, -- EEST
        wet   =      0, -- WET
        sast  =   7200, -- SAST
-       eet   =   7200, -- EET
        hast  = -36000, -- HAST
        hadt  = -32400, -- HADT
        akst  = -32400, -- AKST
@@ -40,6 +41,9 @@ OFFSET = {
        gft   = -10800, -- GFT
        pst   = -28800, -- PST
        pdt   = -25200, -- PDT
+       act   = -18000, -- ACT
+       wgt   = -10800, -- WGT
+       wgst  =  -7200, -- WGST
        ect   = -18000, -- ECT
        gyt   = -14400, -- GYT
        bot   = -14400, -- BOT
@@ -50,11 +54,13 @@ OFFSET = {
        uyst  =  -7200, -- UYST
        fnt   =  -7200, -- FNT
        srt   = -10800, -- SRT
+       clt   = -14400, -- CLT
+       clst  = -10800, -- CLST
        egt   =  -3600, -- EGT
        egst  =      0, -- EGST
        nst   = -12600, -- NST
        ndt   =  -9000, -- NDT
-       wst   =  28800, -- WST
+       awst  =  28800, -- AWST
        davt  =  25200, -- DAVT
        ddut  =  36000, -- DDUT
        mist  =  39600, -- MIST
@@ -63,6 +69,7 @@ OFFSET = {
        nzdt  =  46800, -- NZDT
        rott  = -10800, -- ROTT
        syot  =  10800, -- SYOT
+       utc   =      0, -- UTC
        vost  =  21600, -- VOST
        almt  =  21600, -- ALMT
        anat  =  43200, -- ANAT
@@ -73,6 +80,7 @@ OFFSET = {
        ict   =  25200, -- ICT
        kgt   =  21600, -- KGT
        bnt   =  28800, -- BNT
+       irkt  =  28800, -- IRKT
        chot  =  28800, -- CHOT
        ist   =  19800, -- IST
        bdt   =  21600, -- BDT
@@ -81,46 +89,47 @@ OFFSET = {
        tjt   =  18000, -- TJT
        hkt   =  28800, -- HKT
        hovt  =  25200, -- HOVT
-       irkt  =  32400, -- IRKT
-       wit   =  25200, -- WIT
-       eit   =  32400, -- EIT
+       wib   =  25200, -- WIB
+       wit   =  32400, -- WIT
        aft   =  16200, -- AFT
        pett  =  43200, -- PETT
        pkt   =  18000, -- PKT
        npt   =  20700, -- NPT
-       krat  =  28800, -- KRAT
+       yakt  =  32400, -- YAKT
+       krat  =  25200, -- KRAT
        myt   =  28800, -- MYT
-       magt  =  43200, -- MAGT
-       cit   =  28800, -- CIT
+       magt  =  36000, -- MAGT
+       wita  =  28800, -- WITA
        pht   =  28800, -- PHT
-       novt  =  25200, -- NOVT
-       omst  =  25200, -- OMST
+       novt  =  21600, -- NOVT
+       omst  =  21600, -- OMST
        orat  =  18000, -- ORAT
        kst   =  32400, -- KST
        qyzt  =  21600, -- QYZT
        mmt   =  23400, -- MMT
-       sakt  =  39600, -- SAKT
+       sakt  =  36000, -- SAKT
        uzt   =  18000, -- UZT
        sgt   =  28800, -- SGT
+       sret  =  39600, -- SRET
        get   =  14400, -- GET
        btt   =  21600, -- BTT
        jst   =  32400, -- JST
        ulat  =  28800, -- ULAT
-       vlat  =  39600, -- VLAT
-       yakt  =  36000, -- YAKT
-       yekt  =  21600, -- YEKT
+       xjt   =  21600, -- XJT
+       vlat  =  36000, -- VLAT
+       yekt  =  18000, -- YEKT
        azot  =  -3600, -- AZOT
        azost =      0, -- AZOST
        cvt   =  -3600, -- CVT
-       fkt   = -14400, -- FKT
        fkst  = -10800, -- FKST
-       cwst  =  31500, -- CWST
+       acst  =  34200, -- ACST
+       acdt  =  37800, -- ACDT
+       aest  =  36000, -- AEST
+       acwst =  31500, -- ACWST
        lhst  =  37800, -- LHST
-       lhst  =  39600, -- LHST
-       fet   =  10800, -- FET
-       msk   =  14400, -- MSK
+       lhdt  =  39600, -- LHDT
+       msk   =  10800, -- MSK
        samt  =  14400, -- SAMT
-       volt  =  14400, -- VOLT
        iot   =  21600, -- IOT
        cxt   =  25200, -- CXT
        cct   =  23400, -- CCT
@@ -129,13 +138,19 @@ OFFSET = {
        mvt   =  18000, -- MVT
        mut   =  14400, -- MUT
        ret   =  14400, -- RET
+       wsst  =  46800, -- WSST
+       wsdt  =  50400, -- WSDT
+       bst   =  39600, -- BST
        chast =  45900, -- CHAST
        chadt =  49500, -- CHADT
        chut  =  36000, -- CHUT
+       east  = -21600, -- EAST
+       easst = -18000, -- EASST
        vut   =  39600, -- VUT
        phot  =  46800, -- PHOT
-       tkt   = -36000, -- TKT
+       tkt   =  46800, -- TKT
        fjt   =  43200, -- FJT
+       fjst  =  46800, -- FJST
        tvt   =  43200, -- TVT
        galt  = -21600, -- GALT
        gamt  = -32400, -- GAMT
index d6eb2f7..9706dbd 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 0f77200..c3b8c93 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 ""