[for-15.05] luci-app-ddns: adaption to support backported ddns-scripts 2.7.6 935/head
authorChristian Schoenebeck <christian.schoenebeck@gmail.com>
Wed, 11 Jan 2017 19:13:55 +0000 (20:13 +0100)
committerChristian Schoenebeck <christian.schoenebeck@gmail.com>
Wed, 11 Jan 2017 19:13:55 +0000 (20:13 +0100)
Signed-off-by: Christian Schoenebeck <christian.schoenebeck@gmail.com>
applications/luci-app-ddns/Makefile
applications/luci-app-ddns/luasrc/controller/ddns.lua
applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua
applications/luci-app-ddns/luasrc/model/cbi/ddns/global.lua
applications/luci-app-ddns/luasrc/model/cbi/ddns/hints.lua
applications/luci-app-ddns/luasrc/model/cbi/ddns/overview.lua
applications/luci-app-ddns/luasrc/tools/ddns.lua
applications/luci-app-ddns/luasrc/view/ddns/overview_status.htm
applications/luci-app-ddns/luasrc/view/ddns/system_status.htm

index dadff5ab68ffa961901276a13958c49670139f5e..9c16de6384386b5d8551d0df10c8cfc1a1830833 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2008-2015 The LuCI Team <luci@lists.subsignal.org>
+# Copyright (C) 2008-2017 The LuCI Team <luci@lists.subsignal.org>
 #
 # This is free software, licensed under the Apache License, Version 2.0 .
 #
@@ -10,7 +10,7 @@ PKG_NAME:=luci-app-ddns
 
 # Version == major.minor.patch
 # increase on new functionality (minor) or patches (patch)
-PKG_VERSION:=2.2.4
+PKG_VERSION:=2.2.5
 
 # Release == build
 # increase on changes of translation files
index 946dfefbc8bb8ace5e6aa6b890be97ecc953994a..f0ecdd7509faff3a6d7df927ef99721f4e191580 100644 (file)
@@ -1,7 +1,7 @@
 -- Copyright 2008 Steven Barth <steven@midlink.org>
 -- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
 -- Copyright 2013 Manuel Munz <freifunk at somakoma dot de>
--- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
+-- Copyright 2014-2017 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
 -- Licensed to the public under the Apache License 2.0.
 
 module("luci.controller.ddns", package.seeall)
@@ -15,7 +15,8 @@ local SYS  = require "luci.sys"
 local DDNS = require "luci.tools.ddns"         -- ddns multiused functions
 local UTIL = require "luci.util"
 
-DDNS_MIN = "2.4.2-1"   -- minimum version of service required
+DDNS_MIN = "2.7.6-1"   -- minimum version of service required
+luci_helper = "/usr/lib/ddns/dynamic_dns_lucihelper.sh"
 
 function index()
        local nxfs      = require "nixio.fs"            -- global definitions not available
@@ -118,13 +119,19 @@ local function _get_status()
                end
 
                -- try to get registered IP
-               local domain    = s["domain"] or "_nodomain_"
+               local lookup_host = s["lookup_host"] or "_nolookup_"
                local dnsserver = s["dns_server"] or ""
                local force_ipversion = tonumber(s["force_ipversion"] or 0)
                local force_dnstcp = tonumber(s["force_dnstcp"] or 0)
-               local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh]]
-               command = command .. [[ get_registered_ip ]] .. domain .. [[ ]] .. use_ipv6 ..
-                       [[ ]] .. force_ipversion .. [[ ]] .. force_dnstcp .. [[ ]] .. dnsserver
+               local is_glue = tonumber(s["is_glue"] or 0)
+               local command = luci_helper .. [[ -]]
+               if (use_ipv6 == 1) then command = command .. [[6]] end
+               if (force_ipversion == 1) then command = command .. [[f]] end
+               if (force_dnstcp == 1) then command = command .. [[t]] end
+               if (is_glue == 1) then command = command .. [[g]] end
+               command = command .. [[l ]] .. lookup_host
+               if (#dnsserver > 0) then command = command .. [[ -d ]] .. dnsserver end
+               command = command .. [[ -- get_registered_ip]]
                local reg_ip = SYS.exec(command)
                if reg_ip == "" then
                        reg_ip = "_nodata_"
@@ -135,7 +142,7 @@ local function _get_status()
                        section  = section,
                        enabled  = enabled,
                        iface    = iface,
-                       domain   = domain,
+                       lookup   = lookup_host,
                        reg_ip   = reg_ip,
                        pid      = pid,
                        datelast = datelast,
@@ -151,7 +158,7 @@ end
 function logread(section)
        -- read application settings
        local uci       = UCI.cursor()
-       local log_dir   = uci:get("ddns", "global", "log_dir") or "/var/log/ddns"
+       local log_dir   = uci:get("ddns", "global", "ddns_logdir") or "/var/log/ddns"
        local lfile     = log_dir .. "/" .. section .. ".log"
        local ldata     = NXFS.readfile(lfile)
 
@@ -220,7 +227,8 @@ function startstop(section, enabled)
        uci:unload("ddns")
 
        -- start dynamic_dns_updater.sh script
-       os.execute ([[/usr/lib/ddns/dynamic_dns_updater.sh %s 0 > /dev/null 2>&1 &]] % section)
+       local command = luci_helper .. [[ -S ]] .. section .. [[ -- start]]
+       os.execute(command)
        NX.nanosleep(3) -- 3 seconds "show time"
 
        -- status changed so return full status
index 27f9a9f2640d4b58c2a5eb93f625b94a863a3a40..60a6f2cb7b7737137a5fcb1a357564a1521824d5 100644 (file)
@@ -1,7 +1,7 @@
 -- Copyright 2008 Steven Barth <steven@midlink.org>
 -- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
 -- Copyright 2013 Manuel Munz <freifunk at somakoma dot de>
--- Copyright 2014-2015 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
+-- Copyright 2014-2017 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
 -- Licensed to the public under the Apache License 2.0.
 
 local NX   = require "nixio"
@@ -12,6 +12,7 @@ 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
+local CTRL = require "luci.controller.ddns"    -- this application's controller
 
 -- takeover arguments -- #######################################################
 local section  = arg[1]
@@ -67,42 +68,39 @@ end
 -- local IP can be read
 local function _verify_ip_source()
        -- section is globally defined here be calling agrument (see above)
-       local _network   = "-"
-       local _url       = "-"
-       local _interface = "-"
-       local _script    = "-"
-       local _proxy     = ""
+       local _arg
 
        local _ipv6   = usev6:formvalue(section)
        local _source = (_ipv6 == "1")
                        and src6:formvalue(section)
                        or  src4:formvalue(section)
+
+       local command = CTRL.luci_helper .. [[ -]]
+       if (_ipv6 == "1")  then command = command .. [[6]] end
+
        if _source == "network" then
-               _network = (_ipv6 == "1")
+               _arg = (_ipv6 == "1")
                        and ipn6:formvalue(section)
                        or  ipn4:formvalue(section)
+               command = command .. [[n ]] .. _arg
        elseif _source == "web" then
-               _url = (_ipv6 == "1")
+               _arg = (_ipv6 == "1")
                        and iurl6:formvalue(section)
                        or  iurl4:formvalue(section)
+               command = command .. [[u ]] .. _arg
+
                -- proxy only needed for checking url
-               _proxy = (pxy) and pxy:formvalue(section) or ""
+               _arg = (pxy) and pxy:formvalue(section) or ""
+               if (_arg and #_arg > 0) then
+                       command = command .. [[ -p ]] .. _arg
+               end
        elseif _source == "interface" then
-               _interface = ipi:formvalue(section)
+               command = command .. [[i ]] .. ipi:formvalue(section)
        elseif _source == "script" then
-               _script = ips:formvalue(section)
-       end
-
-       local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh get_local_ip ]] ..
-               _ipv6 .. [[ ]] .. _source .. [[ ]] .. _network .. [[ ]] ..
-               _url .. [[ ]] .. _interface .. [[ ']] .. _script.. [[' ]] .. _proxy
-       local ret = SYS.call(command)
-
-       if ret == 0 then
-               return true     -- valid
-       else
-               return nil      -- invalid
+               command = command .. [[s ]] .. ips:formvalue(section)
        end
+       command = command .. [[ -- get_local_ip]]
+       return (SYS.call(command) == 0)
 end
 
 -- cbi-map definition -- #######################################################
@@ -129,9 +127,9 @@ 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"
+ddns_dateformat = m.uci:get(m.config, "global", "ddns_dateformat") or "%F %R"
 -- log directory
-log_dir = m.uci:get(m.config, "global", "log_dir") or "/var/log/ddns"
+ddns_logdir = m.uci:get(m.config, "global", "ddns_logdir") or "/var/log/ddns"
 
 -- cbi-section definition -- ###################################################
 ns = m:section( NamedSection, section, "service",
@@ -157,6 +155,25 @@ function en.parse(self, section)
        DDNS.flag_parse(self, section)
 end
 
+-- IPv4/IPv6 - lookup_host -- #################################################
+luh = ns:taboption("basic", Value, "lookup_host",
+               translate("Lookup Hostname"),
+               translate("Hostname/FQDN to validate, if IP update happen or necessary") )
+luh.rmempty    = false
+luh.placeholder = "myhost.example.com"
+function luh.validate(self, value)
+       if not value
+       or not (#value > 0)
+       or not DTYP.hostname(value) then
+               return nil, err_tab_basic(self) .. translate("invalid FQDN / required - Sample") .. ": 'myhost.example.com'"
+       else
+               return UTIL.trim(value)
+       end
+end
+--function luh.parse(self, section, novld)
+--     DDNS.value_parse(self, section, novld)
+--end
+
 -- use_ipv6 (NEW)  -- ##########################################################
 usev6 = ns:taboption("basic", ListValue, "use_ipv6",
        translate("IP address version"),
@@ -195,7 +212,7 @@ svc4.default        = "-"
 svc4:depends("use_ipv6", "0")  -- only show on IPv4
 
 local services4 = { }
-local fd4 = io.open("/usr/lib/ddns/services", "r")
+local fd4 = io.open("/etc/ddns/services", "r")
 
 if fd4 then
        local ln
@@ -247,7 +264,7 @@ if not has_ipv6 then
 end
 
 local services6 = { }
-local fd6 = io.open("/usr/lib/ddns/services_ipv6", "r")
+local fd6 = io.open("/etc/ddns/services_ipv6", "r")
 
 if fd6 then
        local ln
@@ -936,8 +953,10 @@ function dns.validate(self, value)
        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 ]] ..
-                       value .. [[ ]] .. ipv6 .. [[ ]] .. force
+               local command = CTRL.luci_helper .. [[ -]]
+               if (ipv6 == 1)  then command = command .. [[6]] end
+               if (force == 1) then command = command .. [[f]] end
+               command = command .. [[d ]] .. value .. [[ -- verify_dns]]
                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")
@@ -1002,8 +1021,10 @@ if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) 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 ]] ..
-                               value .. [[ ]] .. ipv6 .. [[ ]] .. force
+                       local command = CRTL.luci_helper .. [[ -]]
+                       if (ipv6 == 1)  then command = command .. [[6]] end
+                       if (force == 1) then command = command .. [[f]] end
+                       command = command .. [[p ]] .. value .. [[ -- verify_proxy]]
                        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")
@@ -1033,7 +1054,7 @@ slog:value("4", translate("Error"))
 logf = ns:taboption("advanced", Flag, "use_logfile",
        translate("Log to file"),
        translate("Writes detailed messages to log file. File will be truncated automatically.") .. "<br />" ..
-       translate("File") .. [[: "]] .. log_dir .. [[/]] .. section .. [[.log"]] )
+       translate("File") .. [[: "]] .. ddns_logdir .. [[/]] .. 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
@@ -1230,7 +1251,7 @@ lv.template = "ddns/detail_logview"
 lv.inputtitle = translate("Read / Reread log file")
 lv.rows = 50
 function lv.cfgvalue(self, section)
-       local lfile=log_dir .. "/" .. section .. ".log"
+       local lfile=ddns_logdir .. "/" .. section .. ".log"
        if NXFS.access(lfile) then
                return lfile .. "\n" .. translate("Please press [Read] button")
        end
index fbd3cb337719d615767154bd0af249162f75ebad..a474257f871f04c65117a5cc1aa248924e55bcb7 100644 (file)
@@ -1,4 +1,4 @@
--- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
+-- Copyright 2014-2017 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
 -- Licensed to the public under the Apache License 2.0.
 
 local NX   = require "nixio"
@@ -45,8 +45,8 @@ function ns.cfgvalue(self, section)
        return self.map:get(section)
 end
 
--- allow_local_ip  -- ##########################################################
-local ali      = ns:option(Flag, "allow_local_ip")
+-- upd_privateip  -- ###########################################################
+local ali      = ns:option(Flag, "upd_privateip")
 ali.title      = translate("Allow non-public IP's")
 ali.description = translate("Non-public and by default blocked IP's") .. ":"
                .. [[<br /><strong>IPv4: </strong>]]
@@ -65,8 +65,8 @@ function ali.validate(self, value)
        return value
 end
 
--- date_format  -- #############################################################
-local df       = ns:option(Value, "date_format")
+-- ddns_dateformat  -- #########################################################
+local df       = ns:option(Value, "ddns_dateformat")
 df.title       = translate("Date format")
 df.description = [[<a href="http://www.cplusplus.com/reference/ctime/strftime/" target="_blank">]]
                .. translate("For supported codes look here") 
@@ -88,8 +88,8 @@ function df.validate(self, value)
        return value
 end
 
--- run_dir  -- #################################################################
-local rd       = ns:option(Value, "run_dir")
+-- ddns_rundir  -- #############################################################
+local rd       = ns:option(Value, "ddns_rundir")
 rd.title       = translate("Status directory")
 rd.description = translate("Directory contains PID and other status information for each running section")
 rd.rmempty     = true
@@ -101,8 +101,8 @@ function rd.validate(self, value)
        return value
 end
 
--- log_dir  -- #################################################################
-local ld       = ns:option(Value, "log_dir")
+-- ddns_logdir  -- #############################################################
+local ld       = ns:option(Value, "ddns_logdir")
 ld.title       = translate("Log directory")
 ld.description = translate("Directory contains Log files for each running section")
 ld.rmempty     = true
@@ -114,8 +114,8 @@ function ld.validate(self, value)
        return value
 end
 
--- log_lines  -- ###############################################################
-local ll       = ns:option(Value, "log_lines")
+-- ddns_loglines  -- ###########################################################
+local ll       = ns:option(Value, "ddns_loglines")
 ll.title       = translate("Log length")
 ll.description = translate("Number of last lines stored in log files")
 ll.rmempty     = true
index ff7aa7a41cc7ab8d2d6a456fe29e66a99ce13034..3de85b266361bdf93e35d0cdb4016402753504ee 100644 (file)
@@ -1,4 +1,4 @@
--- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
+-- Copyright 2014-2017 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
 -- Licensed to the public under the Apache License 2.0.
 
 local CTRL = require "luci.controller.ddns"    -- this application's controller
index 9e8df2d0896f3f6eb83262957b2c61955f8038b6..0c98134c7a384b89bec10f0c2f6dceb396dde341 100644 (file)
@@ -1,4 +1,4 @@
--- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
+-- Copyright 2014-2017 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
 -- Licensed to the public under the Apache License 2.0.
 
 local NXFS = require "nixio.fs"
@@ -45,10 +45,13 @@ m.description = translate("Dynamic DNS allows that your router can be reached wi
 
 m.on_after_commit = function(self)
        if self.changed then    -- changes ?
+               local command = CTRL.luci_helper
                if SYS.init.enabled("ddns") then        -- ddns service enabled, restart all
-                       os.execute("/etc/init.d/ddns restart")
+                       command = command .. " -- restart"
+                       os.execute(command)
                else    -- ddns service disabled, send SIGHUP to running
-                       os.execute("killall -1 dynamic_dns_updater.sh")
+                       command = command .. " -- reload"
+                       os.execute(command)
                end
        end
 end
@@ -123,31 +126,34 @@ function ts.create(self, name)
        HTTP.redirect( self.extedit:format(name) )
 end
 
--- Domain and registered IP -- #################################################
-dom = ts:option(DummyValue, "_domainIP",
-       translate("Hostname/Domain") .. "<br />" .. translate("Registered IP") )
+-- Lookup_Host and registered IP -- #################################################
+dom = ts:option(DummyValue, "_lookupIP",
+       translate("Lookup Hostname") .. "<br />" .. translate("Registered IP") )
 dom.template = "ddns/overview_doubleline"
 function dom.set_one(self, section)
-       local domain = self.map:get(section, "domain") or ""
-       if domain ~= "" then
-               return domain
+       local lookup = self.map:get(section, "lookup_host") or ""
+       if lookup ~= "" then
+               return lookup
        else
                return [[<em>]] .. translate("config error") .. [[</em>]]
        end
 end
 function dom.set_two(self, section)
-       local domain = self.map:get(section, "domain") or ""
-       if domain == "" then return "" end
+       local lookup_host = self.map:get(section, "lookup_host") or ""
+       if lookup_host == "" then return "" end
        local dnsserver = self.map:get(section, "dnsserver") or ""
        local use_ipv6 = tonumber(self.map:get(section, "use_ipv6") or 0)
        local force_ipversion = tonumber(self.map:get(section, "force_ipversion") or 0)
        local force_dnstcp = tonumber(self.map:get(section, "force_dnstcp") or 0)
-       local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh]]
-       if not NXFS.access(command, "rwx", "rx", "rx") then
-               NXFS.chmod(command, 755)
-       end
-       command = command .. [[ get_registered_ip ]] .. domain .. [[ ]] .. use_ipv6 ..
-               [[ ]] .. force_ipversion .. [[ ]] .. force_dnstcp .. [[ ]] .. dnsserver
+       local is_glue = tonumber(self.map:get(section, "is_glue") or 0)
+       local command = CTRL.luci_helper .. [[ -]]
+       if (use_ipv6 == 1) then command = command .. [[6]] end
+       if (force_ipversion == 1) then command = command .. [[f]] end
+       if (force_dnstcp == 1) then command = command .. [[t]] end
+       if (is_glue == 1) then command = command .. [[g]] end
+       command = command .. [[l ]] .. lookup_host
+       if (#dnsserver > 0) then command = command .. [[ -d ]] .. dnsserver end
+       command = command .. [[ -- get_registered_ip]]
        local ip = SYS.exec(command)
        if ip == "" then ip = translate("no data") end
        return ip
index 4466063cb339ee2848cfc18d08e8b93b312b0e17..0b2bc2794f89c70eb227437b7c6b6e04c4a90aa1 100644 (file)
@@ -1,4 +1,4 @@
--- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
+-- Copyright 2014-2017 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
 -- Licensed to the public under the Apache License 2.0.
 
 module("luci.tools.ddns", package.seeall)
@@ -35,17 +35,21 @@ end
 
 -- check if Wget with SSL support or cURL installed
 function check_ssl()
-       if (SYS.call([[ grep -i "\+ssl" /usr/bin/wget >/dev/null 2>&1 ]]) == 0) then
+       if NXFS.access("/usr/bin/wget-ssl") then
                return true
+       elseif NXFS.access("/usr/bin/curl") then
+               return true
+       elseif NXFS.access("/usr/bin/uclient-fetch") then
+               return NXFS.access("/lib/libustream-ssl.so")
        else
-               return NXFS.access("/usr/bin/curl")
+               return false
        end
 end
 
 -- check if Wget with SSL or cURL with proxy support installed
 function check_proxy()
        -- we prefere GNU Wget for communication
-       if (SYS.call([[ grep -i "\+ssl" /usr/bin/wget >/dev/null 2>&1 ]]) == 0) then
+       if NXFS.access("/usr/bin/wget-ssl") then
                return true
 
        -- if not installed cURL must support proxy
@@ -54,13 +58,13 @@ function check_proxy()
 
        -- only BusyBox Wget is installed
        else
-               return NXFS.access("/usr/bin/wget")
+               return NXFS.access("/usr/bin/wget") or NXFS.access("/usr/bin/uclient-fetch")
        end
 end
 
 -- check if BIND host installed
 function check_bind_host()
-       return NXFS.access("/usr/bin/host")
+       return NXFS.access("/usr/bin/host") or NXFS.access("/usr/bin/khost")
 end
 
 -- convert epoch date to given format
index ea8e4a1e31fb07ce0a6ff6e371ac1a618befba97..1801b28c57bccc81b526ac5b5ab7177018808b04 100644 (file)
@@ -19,7 +19,7 @@
                        var section = data[i].section   // Section to handle
                        var cbx = document.getElementById("cbid.ddns." + section + ".enabled");         // Enabled
                        var btn = document.getElementById("cbid.ddns." + section + "._startstop");      // Start/Stop button
-                       var rip = document.getElementById("cbid.ddns." + section + "._domainIP.two");   // Registered IP
+                       var rip = document.getElementById("cbid.ddns." + section + "._lookupIP.two");   // Registered IP
                        var lup = document.getElementById("cbid.ddns." + section + "._update.one");     // Last Update
                        var nup = document.getElementById("cbid.ddns." + section + "._update.two");     // Next Update
                        if ( !(cbx && btn && rip && lup && nup) ) { return; }   // security check
@@ -81,7 +81,7 @@
 
                        // registered IP
                        // rip.innerHTML = "Registered IP";
-                       if (data[i].domain == "_nodomain_")
+                       if (data[i].lookup == "_nolookup_")
                                rip.innerHTML = '';
                        else if (data[i].reg_ip == "_nodata_")
                                rip.innerHTML = '<em><%:No data%></em>';
index 4ca0abb0e54a25c98b60d48e51607626e9a9b2a9..b3500af3945c59212a22078f851de22676ed4d9b 100644 (file)
                        if (data[j].domain == "_nodomain_")
                                tr.insertCell(-1).innerHTML = '<em><%:config error%></em>';
                        else
-                               tr.insertCell(-1).innerHTML = data[j].domain;
+                               tr.insertCell(-1).innerHTML = data[j].lookup;
 
                        // registered IP
                        switch (data[j].reg_ip) {
-                               case "_nodomain_":
+                               case "_nolookup_":
                                        tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>';
                                        break;
                                case "_nodata_":