summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Trask <ttrask01@yahoo.com>2008-06-18 20:07:55 +0000
committerTed Trask <ttrask01@yahoo.com>2008-06-18 20:07:55 +0000
commit151f597ce365349add8c21fff63902be0084645f (patch)
treefdfa505adeaea2d4bb0e8c604a0439b211016111
parentf0dcd211ed5fca855655d8b60b588b1d193e92fd (diff)
downloadacf-tinydns-151f597ce365349add8c21fff63902be0084645f.tar.bz2
acf-tinydns-151f597ce365349add8c21fff63902be0084645f.tar.xz
Rewrite of tinydns to simplify code and use new cfe model.
Added js to filter records. git-svn-id: svn://svn.alpinelinux.org/acf/tinydns/trunk@1219 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r--tinydns-basicstatus-html.lsp16
-rwxr-xr-xtinydns-config-html.lsp86
-rw-r--r--tinydns-confirmaction-html.lsp20
-rw-r--r--tinydns-controller.lua454
-rw-r--r--tinydns-edit-html.lsp62
-rw-r--r--tinydns-expert-html.lsp73
-rw-r--r--tinydns-listfiles-html.lsp49
-rw-r--r--tinydns-model.lua668
-rw-r--r--tinydns-newfile-html.lsp17
-rw-r--r--tinydns-startstop-html.lsp26
-rw-r--r--tinydns-status-html.lsp183
-rw-r--r--tinydns.menu4
-rw-r--r--tinydns.roles4
13 files changed, 516 insertions, 1146 deletions
diff --git a/tinydns-basicstatus-html.lsp b/tinydns-basicstatus-html.lsp
new file mode 100644
index 0000000..d0eae68
--- /dev/null
+++ b/tinydns-basicstatus-html.lsp
@@ -0,0 +1,16 @@
+<? local data = ... ?>
+<? require("viewfunctions") ?>
+<? --[[
+io.write(html.cfe_unpack(data))
+--]] ?>
+
+<H1>SYSTEM INFO</H1>
+<DL>
+<?
+displayitem(data.value.status)
+displayitem(data.value.version)
+displayitem(data.value.autostart)
+displayitem(data.value.configdir)
+displayitem(data.value.listen)
+?>
+</DL>
diff --git a/tinydns-config-html.lsp b/tinydns-config-html.lsp
index 839570e..4c56ea3 100755
--- a/tinydns-config-html.lsp
+++ b/tinydns-config-html.lsp
@@ -1,4 +1,4 @@
-<? local form = ...
+<? local form, viewlibrary = ...
require("viewfunctions")
?>
<?
@@ -9,82 +9,16 @@ io.write("</span>")
--]]
?>
-<H1>SYSTEM INFO</H1>
-<?
-local myform = form.status
-local tags = { "status", "version", "autostart", }
-displayinfo(myform,tags,"viewonly")
-?>
-
-<form name="cmd" action="<?= form.option.link ?>/<?= form.option.action ?>" method="POST">
-<H1>CONFIG</H1>
-<H2>General settings</H2>
-<?
-local myform = form.config
-local tags = { "listen","listen_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H2>Locations</H2>
-<?
-local tags = { "locations","locations_cmd", "cmdnewlocations", }
-displayinfo(myform,tags)
-?>
-
-
-<H2>Records</H2>
-<H3><? io.write(tostring(form.config.nsourdomain.label) or "NS record") ?></H3>
-<?
-local tags = { "nsourdomain","nsourdomain_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H3><? io.write(tostring(form.config.nsdomain.label) or "NS record") ?></H3>
-<?
-local tags = { "nsdomain","nsdomain_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H3><? io.write(tostring(form.config.host.label) or "Hosts record") ?></H3>
-<?
-local tags = { "host","host_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H3><? io.write(tostring(form.config.alias.label) or "Alias record") ?></H3>
-<?
-local tags = { "alias","alias_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H3><? io.write(tostring(form.config.mx.label) or "MX record") ?></H3>
-<?
-local tags = { "mx","mx_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H3><? io.write(tostring(form.config.ptr.label) or "PTR record") ?></H3>
-<?
-local tags = { "ptr","ptr_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H3><? io.write(tostring(form.config.cname.label) or "CNAME record") ?></H3>
-<?
-local tags = { "cname","cname_cmd", }
-displayinfo(myform,tags)
-?>
-
-<H3><? io.write(tostring(form.config.soa.label) or "SOA record") ?></H3>
-<?
-local tags = { "soa","soa_cmd", }
-displayinfo(myform,tags)
-?>
+<? if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("basicstatus")
+end ?>
-<H3><? io.write(tostring(form.config.generic.label) or "GENERIC record") ?></H3>
+<h1>CONFIGURATION</h1>
+<h2><?= form.label ?></h2>
<?
-local tags = { "generic","generic_cmd", }
-displayinfo(myform,tags)
+ displayform(form)
?>
-</form>
+<? if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("startstop")
+end ?>
diff --git a/tinydns-confirmaction-html.lsp b/tinydns-confirmaction-html.lsp
deleted file mode 100644
index 5303310..0000000
--- a/tinydns-confirmaction-html.lsp
+++ /dev/null
@@ -1,20 +0,0 @@
-<? local form = ...
-require("viewfunctions")
-?>
-<?
---[[ DEBUG INFORMATION
-io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
-io.write(html.cfe_unpack(form))
-io.write("</span>")
---]]
-?>
-
-
-<H1>Confirmation</H1>
-<form name="myform" action="" method="POST">
-<DL>
-<DT><? io.write(form.cmddelete.label or "") ?></DT>
-<DD><? io.write(html.form[form.cmddelete.type](form.cmddelete)) ?> <? io.write(html.form[form.cancel.type](form.cancel)) ?>
-<input type="hidden" value="<? io.write(form.name.value) ?>" name="name">
-</DD>
-</form>
diff --git a/tinydns-controller.lua b/tinydns-controller.lua
index dc06911..b0f4272 100644
--- a/tinydns-controller.lua
+++ b/tinydns-controller.lua
@@ -1,405 +1,145 @@
module(..., package.seeall)
--- Set variables
-local newrecordtxt = "[New]"
-
-- ################################################################################
-- LOCAL FUNCTIONS
-local function getstatus(self)
- local status = self.model.getstatus()
- if (#status.status.value > 0) then
- status.status.value = "Enabled"
- else
- status.status.value = "Disabled"
- end
-
- return status
-end
-
-local function filtertable(t,limit,counter)
- if not (counter) then counter = 0 end
- counter = counter + 1
-
- if (t) then
- for k,v in pairs(t) do
- if (counter > (limit + 2)) then
- t[k] = nil
- end
- if (type(t[k]) == "table") then
- filtertable(v,limit,counter)
- end
- end
- end
-end
-
-local function unpackoptions(t,array,descrfield)
- for k,v in pairs(t) do
- if not (v.option) then
- if (type(v) == "table") then
- unpackoptions(v,array,descrfield)
- end
- else
- if (v.option[descrfield]) and (v.option[descrfield].value) then
- table.insert(array, v.label .. " (" .. v.option[descrfield].value .. ")")
- else
- table.insert(array, v.label)
- end
- end
- end
-end
-
-local function unpackoptionstooriginal(t,array,filter)
- for k,v in pairs(t) do
- if not (v.option) then
- if (type(v) == "table") then
- unpackoptionstooriginal(v,array,filter)
- end
- else
- if (v.orgrecordtable) and (v.orgrecordtable[2] == filter) then
- table.insert(array, v.orgrecordtable)
- end
- end
- end
-end
-
-local function displaycmdmanagement(pidofstatus)
- -- Add a management buttons
- local management = {}
- management.start = cfe({ name="cmdmanagement",
- label="Program control-panel",
- value="Start",
- type="submit",
- })
- management.stop = cfe({ name="cmdmanagement",
- label="Program control-panel",
- value="Stop",
- type="submit",
- })
- management.restart = cfe({ name="cmdmanagement",
- label="Program control-panel",
- value="Restart",
- type="submit",
- })
- -- next CFE can be used to present the result of the previous action
- management.actionresult = cfe({ name="actionresult",
- label="Previous action result",
- })
-
- -- Disable management buttons based on if the process is running or not
- if (pidofstatus) then
- management.start.disabled = "yes"
- else
- management.stop.disabled = "yes"
- management.restart.disabled = "yes"
- end
-
- return management
-end
-
-- ################################################################################
-- PUBLIC FUNCTIONS
default_action = "status"
-function status(self)
- local config = {}
- config.settings = {}
- local locations=self.model.getlocations(self)
- local availablesigns = self.model.check_signs("prefix")
-
- config.locations = cfe ({
- name="locations",
- label="Defining locations",
- value=locations,
- })
-
- local prefix = "."
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.nsourdomain = cfe ({
- name="nsourdomain",
- label=availablesigns[prefix],
- value=domainoptions,
- })
- end
+function basicstatus(self)
+ return self.model.getstatus(self)
+end
- local prefix = "&"
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.nsdomain = cfe ({
- name="nsdomain",
- label=availablesigns[prefix],
- value=domainoptions,
- })
- end
+function status(self)
+ return self.model.getconfigobjects(self)
+end
- local prefix = "="
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.host = cfe ({
- name="host",
- label=availablesigns[prefix],
- value=domainoptions,
- })
+function startstop(self)
+ local result
+ if self.clientdata.action then
+ result = self.model:startstop_service(self.clientdata.action)
+ self.sessiondata.tinydnsstartstopresult = result
+ self.redirect_to_referrer(self)
end
- local prefix = "+"
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.alias = cfe ({
- name="alias",
- label=availablesigns[prefix],
- value=domainoptions,
- })
+ local status = self.model.getstatus()
+ status = status.value.status
+ if self.sessiondata.tinydnsstartstopresult then
+ result = self.sessiondata.tinydnsstartstopresult
+ self.sessiondata.tinydnsstartstopresult = nil
end
- local prefix = "@"
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.mx = cfe ({
- name="mx",
- label=availablesigns[prefix],
- value=domainoptions,
- })
- end
+ return cfe({ type="group", value={status=status, result=result} })
+end
- local prefix = "^"
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.ptr = cfe ({
- name="ptr",
- label=availablesigns[prefix],
- value=domainoptions,
- })
- end
+function config(self)
+ local config = self.model.getconfig()
- local prefix = "C"
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.cname = cfe ({
- name="cname",
- label=availablesigns[prefix],
- value=domainoptions,
- })
- end
+ if self.clientdata.Save then
+ for name,value in pairs(self.clientdata) do
+ if config.value[name] then
+ config.value[name].errtxt = nil
+ config.value[name].value = value
+ end
+ end
- local prefix = "Z"
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.soa = cfe ({
- name="soa",
- label=availablesigns[prefix],
- value=domainoptions,
- })
+ config = self.model.setconfig(config)
+ if not config.errtxt then
+ config.descr = "Configuration Set"
+ end
end
- local prefix = ":"
- local domainoptions = self.model.getconfigobjects(self,prefix)
- if (#domainoptions > 0) then
- config.settings.generic = cfe ({
- name="generic",
- label=availablesigns[prefix],
- value=domainoptions,
- })
- end
---[[
- -- This could be used for DEBUGGING
- config.settings.all = cfe ({
- name="generic",
- label="All available records",
- value=self.model.getconfigobjects(self),
- })
---]]
- local counter
+ config.type = "form"
+ config.option = "Save"
+ config.label = "Edit configuration"
- return {
- status=getstatus(self),
- config=config,
- }
+ return config
end
-function expert(self)
- -- Start/Stop/Restart process
- local cmdmanagement, actionresult
- if ( self.clientdata.cmdmanagement) then
- cmdmanagement = cfe({
- name="cmdmanagement",
- label="Previous action result",
- action=cfe({
- name="cmdmanagement",
- value=string.lower(self.clientdata.cmdmanagement), -- This row contains start/stop/restart (one of these commands)
- }),
- })
- actionresult, cmdmanagement = self.model:startstop_service( cmdmanagement.action )
- end
-
- local configopts = self.model:getconfig()
- -- Show buttons/fileds for creation of new confifiles
- local create = {}
- create.name = cfe ({
- name="name",
- label="Name of the new configfile",
- value=string.gsub(configopts.baseurl.value, "/$", "") .. "/",
- })
- create.cmdnew = cfe ({
- name="cmdnew",
- label="Create new file",
- type="submit",
- value="Create",
- })
+function newfile(self)
+ local create = self.model.getnewconfigfile()
+
-- In case we are trying to create a new configfile
- if (self.clientdata.cmdnew) then
- if (self.clientdata.name) and
- (#self.clientdata.name > 0) and not
- (string.gsub(self.clientdata.name, "/$", "") == string.gsub(create.name.value, "/$", "")) then
- local createcreated, createerrtxt = self.model:createconfigfile(self.clientdata.name)
- if (createerrtxt) and (#createerrtxt > 0) then
- create.name.errtxt = createerrtxt
- create.name.value = self.clientdata.name
+ if (self.clientdata.Create) then
+ for name,value in pairs(self.clientdata) do
+ if create.value[name] then
+ create.value[name].errtxt = nil
+ create.value[name].value = value
end
- else
- create.name.errtxt = "Incorrect filename"
end
- if not (create.name.errtxt) then
- create.cmdnew.descr = "* File was created"
- redirect(self, "edit?name=" .. (self.clientdata.name or ""))
+
+ create = self.model.createconfigfile(create)
+ if not create.errtxt then
+ create.descr = "Created new config file"
+ redirect(self, "listfiles")
end
end
- local status = getstatus(self)
+ create.type = "form"
+ create.option = "Create"
+ create.label = "Create new config file"
- local configfiles = self.model:getfilelist()
+ return create
+end
+
+function listfiles(self)
+ local configfiles = self.model.getfilelist()
local config = {}
- for k,v in pairs(configfiles) do
- local filedetails = self.model:get_filedetails(v)
+ for k,v in pairs(configfiles.value) do
+ local filedetails = self.model.get_filedetails(v)
table.insert(config,filedetails)
end
- -- Management buttons (Hide/show buttons
- local pidofstatus
- if (string.lower(status.status.value) == "enabled" ) then pidofstatus = true end
- management = displaycmdmanagement(pidofstatus)
- if (actionresult) then
- management.actionresult.descr=cmdmanagement.descr
- management.actionresult.errtxt=cmdmanagement.errtxt
- end
- if (status) and (status.version) and (#status.version.value == 0) then
- management.start.disabled = "yes"
- management.stop.disabled = "yes"
- management.restart.disabled = "yes"
- end
-
- return {
- option={ script=self.conf.script,
- prefix=self.conf.prefix,
- controller = self.conf.controller,
- action = "expert",
- link = self.conf.script .. self.conf.prefix .. self.conf.controller, },
- management = management,
- config = config,
- status = status,
- create = create,
- startstop = startstop,
- mhdebug = self.clientdata,
- }
-
+ return cfe({ type="list", value=config, label="Config files" })
end
function edit(self)
-
- -- Save changes
- if ( self.clientdata.cmdsave) then
- local filetochange = cfe ({ name=self.clientdata.name, value=self.clientdata.filecontent, })
- modifications = self.model:updatefilecontent(filetochange)
- end
-
- if not (self.model:valid_filename(self.clientdata.name)) then
- redirect(self)
- end
-
- local status = getstatus(self)
- local file = self.model:get_filedetails(self.clientdata.name)
-
-
- -- Add a cmd button to the view
- file.cmdsave = cfe({ name="cmdsave",
- label="Save/Apply above settings",
- value="Save",
- type="submit",
- })
- file.cmddelete = cfe({ name="cmddelete",
- label="Delete this configfile",
- value="Delete",
- type="submit",
- })
-
- if (self.clientdata.cmddelete) then
- redirect(self, "confirmaction?action=delete&name=" .. (self.clientdata.name or ""))
+ local config = self.model.get_filedetails(self.clientdata.filename)
+ if self.clientdata.Save then
+ local result = self.model.updatefilecontent(self.clientdata.filename, self.clientdata.filecontent)
+ if not result.value then
+ config.value.filecontent.value = self.clientdata.filecontent
+ config.value.filecontent.errtxt = result.errtxt
+ config.errtxt = "Failed to save config!"
+ else
+ config = self.model.get_filedetails(self.clientdata.filename)
+ config.descr = "Saved file"
+ end
end
- if (modifications) then
- file.cmdsave.descr="* Changes has been saved!"
- end
-
- return {
- option={ script=self.conf.script,
- prefix=self.conf.prefix,
- controller = self.conf.controller,
- action = "edit",
- extra = "",
- link = self.conf.script .. self.conf.prefix .. self.conf.controller, },
- modifications = modifications,
- file = file,
- status = status,
- startstop = startstop,
- debugclientdata = self.clientdata,
- }
+ config.type = "form"
+ config.option = "Save"
+ config.label = "Edit config file"
+ return config
end
-function confirmaction(self)
- if (self.clientdata.cancel) then
- redirect(self, "expert")
- end
- -- See to that only allowed files are modified
- local fileexists, fileerrros = self.model:get_filedetails(self.clientdata.name)
- if not (fileexists) then
- redirect(self)
+function expert(self)
+ local config = self.model.get_filedetails(self.clientdata.filename)
+ if self.clientdata.Save then
+ local result = self.model.updatefilecontent(self.clientdata.filename, self.clientdata.filecontent)
+ if not result.value then
+ config.value.filecontent.value = self.clientdata.filecontent
+ config.value.filecontent.errtxt = result.errtxt
+ config.errtxt = "Failed to save config!"
+ else
+ config = self.model.get_filedetails(self.clientdata.filename)
+ config.descr = "Saved file"
+ end
end
- local output = {}
- output.cancel = cfe({
- name="cancel",
- value="Cancel",
- type="submit",
- })
- output.cmddelete = cfe({
- name="cmddelete",
- label="Are you sure you want to delete?",
- value="Delete",
- type="submit",
- })
- output.name = cfe({
- name="name",
- value=self.clientdata.name,
- type="hidden",
- })
+ config.type = "form"
+ config.option = "Save"
+ config.label = "Edit config file"
- output.mhdebug = cfe({
- name="mhdebug",
- value=fileexists,
- descr=self.clientdata,
- errtxt=fileerrros,
- })
- if (self.clientdata.cmddelete) then
- local removesuccess, removeerrors = self.model:remove_file(self.clientdata.name)
- if (removesuccess) then
- redirect(self, "expert")
- elseif (#removeerrors > 0) then
- output.cmddelete.errtxt = removeerrors
- end
- end
+ return config
+end
- return output
+function delete(self)
+ local cmdresult = self.model.remove_file(self.clientdata.filename)
+ --self.sessiondata.cmdresult = cmdresult
+ redirect_to_referrer(self)
+ return cmdresult
end
diff --git a/tinydns-edit-html.lsp b/tinydns-edit-html.lsp
index ba9a696..93887dd 100644
--- a/tinydns-edit-html.lsp
+++ b/tinydns-edit-html.lsp
@@ -1,6 +1,5 @@
-<? local form = ...
-require("viewfunctions")
-?>
+<? local form, viewlibrary = ... ?>
+<? require("viewfunctions") ?>
<?
--[[ DEBUG INFORMATION
io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
@@ -9,50 +8,35 @@ io.write("</span>")
--]]
?>
-<H1>SYSTEM INFO</H1>
-<DL>
-<?
-local myform = form.status
-local tags = { "status", "version", "autostart", }
-displayinfo(myform,tags,"viewonly")
-?>
-</DL>
-
-<form name="myform" action="" method="POST">
-<h1>CONFIGURATION</h1>
-<H2>Expert config</H2>
-<h3>File details</h3>
+<H1>CONFIGURATION</H1>
+<H2>EXPERT CONFIGURATION</H2>
+<H3>FILE DETAILS</H3>
<DL>
<?
-local myform = form.file
-local tags = { "filename", "filesize", "mtime", "sumerrors", }
-displayinfo(myform,tags,"viewonly")
+displayitem(form.value.filename)
+displayitem(form.value.filesize)
+displayitem(form.value.mtime)
?>
</DL>
<H3>FILE CONTENT</H3>
-<?
-local myform = form.file
-io.write('<input type="hidden" value="' .. myform.filename.value .. '" name="name">')
-io.write(html.form[myform.filecontent.type](myform.filecontent))
-?>
+<? if form.descr then ?><P CLASS='descr'><?= string.gsub(form.descr, "\n", "<BR>") ?></P><? end ?>
+<? if form.errtxt then ?><P CLASS='error'><?= string.gsub(form.errtxt, "\n", "<BR>") ?></P><? end ?>
+<form action="" method="POST">
+<input type="hidden" name="filename" value="<?= form.value.filename.value ?>">
+<textarea name="filecontent">
+<?= form.value.filecontent.value ?>
+</textarea>
+<? if form.value.filecontent.errtxt then ?><P CLASS='error'><?= string.gsub(form.value.filecontent.errtxt, "\n", "<BR>") ?></P><? end ?>
<H2>SAVE AND APPLY ABOVE SETTINGS</H2>
-<DL>
-<?
-local tags = { "cmddelete", "cmdsave", }
-displayinfo(myform,tags)
-?>
-</DL>
+<DL><DT>Save/Apply above settings</DT><DD><input class="submit" type="submit" name="<?= form.option ?>" value="Save"></DD></DL>
+</form>
<?
--- Management buttons
-local myform = form.management
-local tags = { "start", "stop", "restart" }
-if (myform) then
- io.write("<H1>MANAGEMENT</H1>\n<DL>")
- displaymanagement(myform,tags)
- io.write("</DL>")
-end
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(form))
+io.write("</span>")
+--]]
?>
-</form>
diff --git a/tinydns-expert-html.lsp b/tinydns-expert-html.lsp
index 825267b..93887dd 100644
--- a/tinydns-expert-html.lsp
+++ b/tinydns-expert-html.lsp
@@ -1,6 +1,5 @@
-<? local form = ...
-require("viewfunctions")
-?>
+<? local form, viewlibrary = ... ?>
+<? require("viewfunctions") ?>
<?
--[[ DEBUG INFORMATION
io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
@@ -9,59 +8,35 @@ io.write("</span>")
--]]
?>
-
-<H1>SYSTEM INFO</H1>
+<H1>CONFIGURATION</H1>
+<H2>EXPERT CONFIGURATION</H2>
+<H3>FILE DETAILS</H3>
<DL>
<?
-local myform = form.status
-local tags = { "status", "version", "autostart", }
-displayinfo(myform,tags,"viewonly")
+displayitem(form.value.filename)
+displayitem(form.value.filesize)
+displayitem(form.value.mtime)
?>
</DL>
-<h1>CONFIGURATION</h1>
-<h2>Expert config</h2>
-<h3>Edit/View existing configfiles</h3>
-<TABLE>
- <TR style="background:#eee;font-weight:bold;">
- <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">File</TD>
- <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Size</TD>
- <TD style="white-space:nowrap;text-align:left;" class="header">Last Modified</TD>
- </TR>
-<? local myform = form.config ?>
-<? for i = 1, table.maxn(myform) do ?>
- <TR>
- <TD style="padding-right:20px;white-space:nowrap;"><? io.write(html.link{value = "edit?name=" .. myform[i].filename.value , label=myform[i].filename.value }) ?></TD>
- <TD style="padding-right:20px;white-space:nowrap;"><? io.write(myform[i].filesize.value or "--") ?></TD>
- <TD style="white-space:nowrap;" width="90%"><? io.write(myform[i].mtime.value or "--") ?></TD>
- </TR>
-<? end ?>
-</TABLE>
+<H3>FILE CONTENT</H3>
+<? if form.descr then ?><P CLASS='descr'><?= string.gsub(form.descr, "\n", "<BR>") ?></P><? end ?>
+<? if form.errtxt then ?><P CLASS='error'><?= string.gsub(form.errtxt, "\n", "<BR>") ?></P><? end ?>
+<form action="" method="POST">
+<input type="hidden" name="filename" value="<?= form.value.filename.value ?>">
+<textarea name="filecontent">
+<?= form.value.filecontent.value ?>
+</textarea>
+<? if form.value.filecontent.errtxt then ?><P CLASS='error'><?= string.gsub(form.value.filecontent.errtxt, "\n", "<BR>") ?></P><? end ?>
-<h3>Create new configfile</h3>
-<form action="<?= form.option.script .. "/" .. form.option.prefix ..
- form.option.controller .. "/" .. form.option.action ..
- (form.option.extra or "") ?>" method="POST">
-<DL>
-<?
-local myform = form.create
-local tags = { "name", "cmdnew", }
-displayinfo(myform,tags)
-?>
-</DL>
+<H2>SAVE AND APPLY ABOVE SETTINGS</H2>
+<DL><DT>Save/Apply above settings</DT><DD><input class="submit" type="submit" name="<?= form.option ?>" value="Save"></DD></DL>
</form>
-<form action="<?= form.option.script .. "/" .. form.option.prefix ..
- form.option.controller .. "/" .. form.option.action ..
- (form.option.extra or "") ?>" method="POST">
<?
--- Management buttons
-local myform = form.management
-local tags = { "start", "stop", "restart" }
-if (myform) then
- io.write("<H1>MANAGEMENT</H1>\n<DL>")
- displaymanagement(myform,tags)
- io.write("</DL>")
-end
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(form))
+io.write("</span>")
+--]]
?>
-</form>
diff --git a/tinydns-listfiles-html.lsp b/tinydns-listfiles-html.lsp
new file mode 100644
index 0000000..f61ce25
--- /dev/null
+++ b/tinydns-listfiles-html.lsp
@@ -0,0 +1,49 @@
+<? local form, viewlibrary = ...
+require("viewfunctions")
+?>
+<?
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(form))
+io.write("</span>")
+--]]
+?>
+
+<? if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("basicstatus")
+end ?>
+
+<h1>CONFIGURATION</h1>
+<h2>Edit/View existing config files</h2>
+<TABLE>
+ <TR style="background:#eee;font-weight:bold;">
+ <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Action</TD>
+ <TD style="padding-right:20px;white-space:nowrap;text-align:right;" class="header">Size</TD>
+ <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Last Modified</TD>
+ <TD style="white-space:nowrap;text-align:left;" class="header">File</TD>
+ </TR>
+<? for i,file in ipairs(form.value) do ?>
+ <TR>
+ <TD style="padding-right:20px;white-space:nowrap;">
+ <? io.write(html.link{value = "delete?filename=" .. file.value.filename.value, label="Delete " }) ?>
+ <? io.write(html.link{value = "edit?filename=" .. file.value.filename.value, label="Edit " }) ?>
+ <? io.write(html.link{value = "expert?filename=" .. file.value.filename.value, label="View " }) ?>
+ </TD>
+ <TD style="padding-right:20px;white-space:nowrap;text-align:right;"><?= file.value.filesize.value ?></TD>
+ <TD style="padding-right:20px;white-space:nowrap;"><?= file.value.mtime.value ?></TD>
+ <TD style="white-space:nowrap;" width="90%"><?= file.value.filename.value ?></TD>
+ </TR>
+<? end ?>
+</TABLE>
+
+<? if viewlibrary and viewlibrary.dispatch_component then
+ local newfileform = viewlibrary.dispatch_component("newfile", nil, true) ?>
+<h2>Create new config file</h2>
+<?
+ newfileform.action = "newfile"
+ displayform(newfileform)
+end ?>
+
+<? if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("startstop")
+end ?>
diff --git a/tinydns-model.lua b/tinydns-model.lua
index 1ace06f..fa0632f 100644
--- a/tinydns-model.lua
+++ b/tinydns-model.lua
@@ -10,23 +10,12 @@ require("daemoncontrol")
require("validator")
-- Set variables
-local configdir
-local datafile
local configfiles = {}
-local configitems = {}
local packagename = "tinydns"
local processname = "tinydns"
local configfile = "/etc/conf.d/" .. processname
-local baseurl = "/etc/tinydns"
-local initdoptions = getopts.getoptsfromfile("/etc/init.d/" .. processname, "")
-if (initdoptions) then
- configdir = initdoptions.DATADIR
- datafile = initdoptions.ROOT .. "/data" or "/var/cache/data"
-else
- configdir = "/etc/" .. processname
- datafile = "/var/cache/data"
-end
-descr = {
+local configdir = "/etc/"..processname
+local descr = {
prefix={
['.']="Name server for your domain (NS + A + SOA)",
['&']="Deletegate subdomain (NS + A)",
@@ -40,32 +29,20 @@ descr = {
[':']="Generic record",
['%']="Client location",
},
- reverse={
- ['nsourdomain']=".",
- ['nsdomain']="&",
- ['host']="=",
- ['alias']="+",
- ['mx']="@",
- ['ptr']="^",
- ['cname']="C",
- ['soa']="Z",
- [':']=":",
- ['locations']="%",
- },
fieldlabels={
- ['.']={"Prefix", "Domain", "IP address", "Name server", "Time to live", "Timestamp", "Location", },
- ['&']={"Prefix", "Domain", "IP address", "Name server", "Time to live", "Timestamp", "Location", },
- ['=']={"Prefix", "Host", "IP address", "Time to live", "Timestamp", "Location", },
- ['+']={"Prefix", "Alias", "IP address", "Time to live", "Timestamp", "Location", },
- ['@']={"Prefix", "Domain", "IP address", "Mail exchanger", "Distance", "Time to live", "Timestamp", "Location", },
- ['^']={"Prefix", "PTR", "Domain name", "Time to live", "Timestamp", "Location", },
- ['C']={"Prefix", "Domain name", "Canonical name", "Time to live", "Timestamp", "Location", },
- ['Z']={"Prefix", "Unknown", "Primary name server", "Contact address", "Serial number", "Refresh time", "Retry time", "Expire time", "Minimum time", "Time to live", "Timestamp", "Location",},
- [':']={"Prefix", },
- ['%']={"Prefix", },
+ ['.']={"Domain", "IP address", "Name server", "Time to live", "Timestamp", "Location", },
+ ['&']={"Domain", "IP address", "Name server", "Time to live", "Timestamp", "Location", },
+ ['=']={"Host", "IP address", "Time to live", "Timestamp", "Location", },
+ ['+']={"Alias", "IP address", "Time to live", "Timestamp", "Location", },
+ ['@']={"Domain", "IP address", "Mail exchanger", "Distance", "Time to live", "Timestamp", "Location", },
+ ['\'']={"Domain", "Text Record", "Time to live", "Timestamp", "Location", },
+ ['^']={"PTR", "Domain name", "Time to live", "Timestamp", "Location", },
+ ['C']={"Domain", "Canonical name", "Time to live", "Timestamp", "Location", },
+ ['Z']={"Domain", "Primary name server", "Contact address", "Serial number", "Refresh time", "Retry time", "Expire time", "Minimum time", "Time to live", "Timestamp", "Location",},
+ [':']={"Domain", "Record type", "Record data", "Time to live", "Timestamp", "Location", },
+ ['%']={"Location", "IP prefix", },
},
}
---configdir = "hidden for the moment - This row is here only for debug purpose"
-- ################################################################################
-- LOCAL FUNCTIONS
@@ -110,9 +87,9 @@ end
local function split_config_items(orgitem)
local delimiter = ":"
local output = {}
- output = format.string_to_table(string.sub(orgitem,1,1) .. ":" .. string.sub(orgitem,2),delimiter)
- output.type = descr['prefix']
- output.type = output.type[string.sub(orgitem,1,1)] or "unknown"
+ output = format.string_to_table(string.sub(orgitem,2),delimiter)
+ output.type = string.sub(orgitem,1,1)
+ output.label = descr['prefix'][output.type] or "unknown"
return output
end
@@ -129,68 +106,8 @@ local function searchforconfigfiles()
end
searchforconfigfiles()
--- Create table with doman levels
-local function recursedomains(t,array,maxn,currnum)
- if not (currnum) then currnum = maxn + 1 end
- currnum = currnum - 1
- if not (currnum == 0) then
-
- if not (array[t[currnum]]) then
- array[t[currnum]] = {}
- end
- recursedomains(t,array[t[currnum]],maxn,currnum)
- end
-
- -- FIXME: This is a /really uggly/ hack to return the current table
- -- If it's fixed nicely... it would be wonderful!
- if (array[t[maxn]]) and
- (array[t[maxn]][t[maxn-1]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]][t[maxn-4]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]][t[maxn-4]][t[maxn-5]]) then
- return array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]][t[maxn-4]][t[maxn-5]]
- end
-
- if (array[t[maxn]]) and
- (array[t[maxn]][t[maxn-1]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]][t[maxn-4]]) then
- return array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]][t[maxn-4]]
- end
-
- if (array[t[maxn]]) and
- (array[t[maxn]][t[maxn-1]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]]) then
- return array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]]
- end
-
- if (array[t[maxn]]) and
- (array[t[maxn]][t[maxn-1]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]]) then
- return array[t[maxn]][t[maxn-1]][t[maxn-2]][t[maxn-3]]
- end
-
- if (array[t[maxn]]) and
- (array[t[maxn]][t[maxn-1]]) and
- (array[t[maxn]][t[maxn-1]][t[maxn-2]]) then
- return array[t[maxn]][t[maxn-1]][t[maxn-2]]
- end
-
- if (array[t[maxn]]) and (array[t[maxn]][t[maxn-1]]) then
- return array[t[maxn]][t[maxn-1]]
- end
-
- if (array[t[maxn]]) then
- return array[t[maxn]]
- end
-end
-
local function validfilename(path)
- for k,v in pairs(getfilelist()) do
+ for k,v in pairs(getfilelist().value) do
if (v == path) then
return true
end
@@ -198,76 +115,13 @@ local function validfilename(path)
return false, "Not a valid filename!"
end
--- Example taken from PIL
--- Sort by Keys
-local function pairsByKeys(t,f)
- local a = {}
-
- for n in pairs(t) do
- -- This is to fix some bug when next table is indexnumber instead of name
- if (tonumber(n) == nil) then
- a[#a + 1] = n
- end
- end
- table.sort(a,f)
- local i = 0 -- iterator variable
- return function () --iterator function
- i = i + 1
- return a[i], t[a[i]]
- end
-end
-
-local function rebuild_table(t,domains_rebuilt)
- if not (type(t) == "string") then
- for k,v in pairs(t) do
- if (tonumber(k)) then
- table.insert(domains_rebuilt, v)
- else
- table.insert(domains_rebuilt, {label=k})
- rebuild_table(v,domains_rebuilt[#domains_rebuilt])
- end
- end
- table.sort(domains_rebuilt, function(a,b) return (a.label < b.label) end)
- end
-end
-
--- This function removes all records that doesn't have the filter-value
-local function filter_table(t1,domains_filtered,filter)
- if not (type(t1) == "string") then
- for k1,v1 in pairs(t1) do
- for k2,v2 in pairs(v1) do
- if (v2.label) then
- if ( string.find(filter,v2.label) ) then
- table.insert(domains_filtered, v2)
- end
- end
- end
- end
- end
-end
-
-- ################################################################################
-- PUBLIC FUNCTIONS
function startstop_service ( self, action )
- local cmd = action.value
- local cmdresult,cmdmessage,cmderror,cmdaction = daemoncontrol.daemoncontrol(processname, cmd)
- action.descr=cmdmessage
- action.errtxt=cmderror
- return cmdresult,action
-end
-
-function valid_filename(self,path)
- return validfilename(path)
-end
-
--- This function could be used to check that valid parameters are used in different places
-function check_signs(sign)
- local output
- if (sign) and (descr[sign]) then
- output = descr[sign]
- end
- return output
+ -- action is validated in daemoncontrol
+ local cmdresult,cmdmessage,cmderror,cmdaction = daemoncontrol.daemoncontrol(processname, action)
+ return cfe({ type="boolean", value=cmdresult, descr=cmdmessage, errtxt=cmderror, label="Start/Stop result" })
end
-- Present some general status
@@ -275,460 +129,232 @@ function getstatus()
local status = {}
local value, errtxt = processinfo.package_version(packagename)
- status.version = cfe({ name = "version",
+ status.version = cfe({
label="Program version",
value=value,
errtxt=errtxt,
})
- status.status = cfe({ name="status",
+ status.status = cfe({
label="Program status",
value=procps.pidof(processname),
})
+ if (#status.status.value > 0) then
+ status.status.value = "Enabled"
+ else
+ status.status.value = "Disabled"
+ end
- status.configdir = cfe({ name="configdir",
+ status.configdir = cfe({
label="Config directory",
value=configdir,
})
- status.configfiles = cfe({ name="configfiles",
+ status.configfiles = cfe({
+ type="list",
label="Config files",
value=configfiles,
})
local autostart_sequense, autostart_errtxt = processinfo.process_botsequence(processname)
- status.autostart = cfe({ name="autostart",
+ status.autostart = cfe({
label="Autostart sequence",
value=autostart_sequense,
errtxt=autostart_errtxt,
})
- return status
-end
-
+ local config = getconfig()
+ status.listen = config.value.listen
--- Return config-information
-function getlocations(self,filter_type)
- local config = {}
- local configobjects = {}
- local locations = {}
-
- -- Loop through all available configfiles
- for k,v in pairs(configfiles) do
- local filecontent, fileresult
- fileresult, filecontent = get_value_from_file(v)
- for kk,vv in pairs(filecontent) do
- local domaindetails = {}
- local filecontent_table = split_config_items(vv)
-
- -- This is mostly for debugging
- -- This table contains all available configs
- table.insert(configobjects, cfe({
- name=vv,
- value=vv,
- option=filecontent_table,
- }))
-
- -- Create a table with location items
- -- Containing all objects that start with %
- if (filecontent_table[1] == "%") then
- if not (locations[filecontent_table[2]]) then
- locations[filecontent_table[2]] = {}
- end
- table.insert(locations[filecontent_table[2]], filecontent_table[3])
- end
- end
- end
-
- return locations
+ return cfe({ type="group", value=status, label="DNS Status" })
end
-function getconfig(self,filter_type)
+function getconfig()
local config = {}
- local listenaddr = getopts.getoptsfromfile(configfile,"","IP") or ""
-
- config.listen = cfe({
- name = "listen",
+ local listenaddr = getopts.getoptsfromfile(configfile,"","IP") or ""
+ config.listen = cfe({
label="IP address to listen on",
value=listenaddr,
})
+ local test, errtxt = validator.is_ipv4(config.listen.value)
+ if not test then
+ config.listen.errtxt = errtxt
+ end
- config.baseurl = cfe({
- name = "baseurl",
- label="Baseurl for configfiles",
- value=baseurl,
- })
+ return cfe({ type="group", value=config, label="TinyDNS Configuration" })
+end
- return config
+function setconfig(conf)
+ local test, errtxt = validator.is_ipv4(conf.value.listen.value)
+ if not test then
+ conf.value.listen.errtxt = errtxt
+ conf.errtxt = "Failed to set configuration"
+ else
+ getopts.setoptsinfile(configfile,"","IP",conf.value.listen.value)
+ end
+
+ return conf
end
-- If you enter 'filter_type' (this should be one of the options found in local function check_signs() ) then
-- the output will be filtered to only contain this type of data.
-function getconfigobjects(self,filter_type, filter_levels)
- local domains = {}
-
+function getconfigobjects(self, filter_type)
+ local configobjects = {}
--Loop through all available configfiles
- for k,v in pairs(configfiles) do
+ for i,filename in pairs(configfiles) do
local filecontent, fileresult
- fileresult, filecontent = get_value_from_file(v)
- for kk,vv in pairs(filecontent) do
+ fileresult, filecontent = get_value_from_file(filename)
+ for j,configline in pairs(filecontent) do
local domaindetails = {}
- local filecontent_table = split_config_items(vv)
- filecontent_table["orgrecord"] = vv
-
- -- Create domain information tables
- local domain
+ local filecontent_table = split_config_items(configline)
+ filecontent_table.configline = configline
- -- * START * COMMONT SETTINGS ****************************************
- local descr=descr['prefix']
-- Use only configs that has a valid prefix
- -- We filter away location-definitions
-- If function is called with some filter options... then show only the filtered values
- if ( not (filter_type) or
- ( (filter_type) and (filter_type == filecontent_table[1]))) and
- (descr[filecontent_table[1]]) and not
- (filecontent_table[1] == "%") then
-
- domain = format.string_to_table(filecontent_table[2], "%.")
- -- We rebuild the table and add previous level-information to the current level
- for i = table.maxn(domain),2,-1 do
- domain[i-1] = domain[i-1] .. "." .. domain[i]
- end
-
- local domainoptions = {}
- -- Add details to the previous object
- table.insert(domainoptions, cfe ({
- name="type",
- label="Type",
- value=descr[filecontent_table[1]],
- }))
-
- -- Set values and labels for field #3
- local name = "ip"
- local label = "IP address"
- -- Some configs uses third column in some other way
- if (filecontent_table[1] == "^") or (filecontent_table[1] == "C") then
- name = "pointdomain"
- label = "Domain"
- end
- if (filecontent_table[1] == "Z") then
- name = "mname"
- label = "Primary nameserver"
- end
- if (filecontent_table[1] == ":") then
- name = "rectype"
- label = "Type of record"
- end
- if (filecontent_table[3]) and (#filecontent_table[3]> 0) and (name) then
- table.insert(domainoptions, cfe ({
- name=name,
- label=label,
- value=filecontent_table[3],
- }))
- end
-
- -- Set values and labels for field #4
- name = "ttl"
- label = "Time to live"
- -- Some configs uses third column in some other way
- if (filecontent_table[1] == ".") or (filecontent_table[1] == "&") then
- name = "ns"
- label = "Name server"
- end
- if (filecontent_table[1] == "@") then
- name = "mx"
- label = "Mail exchanger"
- end
- if (filecontent_table[1] == "Z") then
- name = "rname"
- label = "Contact address"
- end
- if (filecontent_table[4]) and (#filecontent_table[4]> 0) and (name) then
- table.insert(domainoptions, cfe ({
- name=name,
- label=label,
- value=filecontent_table[4],
- }))
+ if ( not (filter_type) or ((filter_type) and (filter_type == filecontent_table.type)) )
+ and (filecontent_table.label)
+ then
+ local entry = {}
+ for i,value in ipairs(filecontent_table) do
+ entry[i] = value
end
-
- -- Set values and labels for field #5
- name = "timestamp"
- label = "Time stamp"
- -- Some configs uses third column in some other way
- if (filecontent_table[1] == ".") or (filecontent_table[1] == "&") then
- name = "ttl"
- label = "Time to live"
- end
- if (filecontent_table[1] == "@") then
- name = "dist"
- label = "Distance"
- end
- if (filecontent_table[1] == "Z") then
- name = "ser"
- label = "Serial number"
- end
- if (filecontent_table[5]) and (#filecontent_table[5]> 0) and (name) then
- table.insert(domainoptions, cfe ({
- name=name,
- label=label,
- value=filecontent_table[5],
- }))
- end
-
- -- Set values and labels for field #6
- name = "lo"
- label = "Location"
- -- Some configs uses third column in some other way
- if (filecontent_table[1] == ".") or (filecontent_table[1] == "&") then
- name = "timestamp"
- label = "Time stamp"
- end
- if (filecontent_table[1] == "@") then
- name = "ttl"
- label = "Time to live"
- end
- if (filecontent_table[1] == "Z") then
- name = "ref"
- label = "Refresh time"
+ -- we're gonna add a reverse domain name to make it easier to sort
+ local domain = {}
+ for mt in string.gmatch(entry[1], "([^.]+)") do
+ table.insert(domain, mt)
end
-
- if (filecontent_table[6]) and (#filecontent_table[6]> 0) and (name) then
- table.insert(domainoptions, cfe ({
- name=name,
- label=label,
- value=filecontent_table[6],
- }))
- end
-
- -- Set values and labels for field #7
- local name = nil
- local label = nil
- -- Some configs uses third column in some other way
- if (filecontent_table[1] == ".") or (filecontent_table[1] == "&") then
- name = "lo"
- label = "Location"
- end
- if (filecontent_table[1] == "@") then
- name = "timestamp"
- label = "Timestamp"
- end
- if (filecontent_table[1] == "Z") then
- name = "ret"
- label = "Retry time"
- end
- if (filecontent_table[7]) and (#filecontent_table[7]> 0) and (name) then
- table.insert(domainoptions, cfe ({
- name=name,
- label=label,
- value=filecontent_table[7],
- }))
+ local reversedomain = {}
+ for i=#domain,1,-1 do
+ table.insert(reversedomain, domain[i])
end
+ entry.sort = table.concat(reversedomain, ".")
- -- Set values and labels for field #8
- local name = nil
- local label = nil
- -- Some configs uses third column in some other way
- if (filecontent_table[1] == "@") then
- name = "lo"
- label = "Location"
- end
- if (filecontent_table[1] == "Z") then
- name = "exp"
- label = "Expire time"
- end
- if (filecontent_table[8]) and (#filecontent_table[8]> 0) and (name) then
- table.insert(domainoptions, cfe ({
- name=name,
- label=label,
- value=filecontent_table[8],
- }))
+ -- add it to the table
+ if not configobjects[filecontent_table.type] then
+ configobjects[filecontent_table.type] = {label=filecontent_table.label, fieldlabels=descr.fieldlabels[filecontent_table.type]}
end
-
- -- Set values and labels for field #9-12
- if (filecontent_table[1] == "Z") then
- if (filecontent_table[9]) and (#filecontent_table[9]> 0) then
- table.insert(domainoptions, cfe ({
- name="min",
- label="Minimum time",
- value=filecontent_table[9],
- }))
- end
- if (filecontent_table[10]) and (#filecontent_table[10]> 0) then
- table.insert(domainoptions, cfe ({
- name="ttl",
- label="Time to live",
- value=filecontent_table[10],
- }))
- end
- if (filecontent_table[11]) and (#filecontent_table[11]> 0) then
- table.insert(domainoptions, cfe ({
- name="timestamp",
- label="Time stamp",
- value=filecontent_table[11],
- }))
- end
- if (filecontent_table[12]) and (#filecontent_table[12]> 0) then
- table.insert(domainoptions, cfe ({
- name="location",
- label="Location",
- value=filecontent_table[12],
- }))
- end
- end
-
-
- -- This is the main information on each object
- domaindetails = cfe ({
- name=filecontent_table[2],
- label=filecontent_table[2],
- option=domainoptions,
- orgrecordtable=filecontent_table,
- })
-
- end
- -- * END * COMMONT SETTINGS ********************************************
- -- Inject the previous data into the right table
- local value = filecontent_table[2]
- local currenttable
- if (type(domain) == "table") then
- currenttable = recursedomains(domain, domains, table.maxn(domain))
+ table.insert(configobjects[filecontent_table.type], entry)
end
+ end
+ end
----[[
- if (domaindetails.value) then
- table.insert (currenttable , domaindetails)
+ -- Sort each of the tables by domain name (entry 1)
+ for type,entries in pairs(configobjects) do
+ table.sort(entries, function(a,b)
+ if a == b then
+ return false;
+ elseif a.sort ~= b.sort then
+ return a.sort < b.sort
end
---]]
-
+ for i in ipairs(a) do
+ if a[i] ~= b[i] then
+ return a[i] < b[i]
+ end
+ end
+ a.errtxt = "Duplicate entry"
+ b.errtxt = "Duplicate entry"
+ return false
+ end)
+ for i,entry in ipairs(entries) do
+ entry.sort = nil
end
end
- -- TODO: Sort the domains table!
- -- Sorting is not possible when things is done as they are (se above)
- -- problem comese when we use keynames instead of [1], [2], ...
- -- Next we rebuild the domains table and do it so it can be sorted
- local domains_sorted = {}
-
- local domains_rebuilt = {}
- rebuild_table(domains,domains_rebuilt)
-
- -- Filter away not wanted records
- local domains_filtered = {}
--- local filter_level2 = "" -- < This is DEBUG!!! REMOVE WHEN DONE!
--- filter_table(domains_rebuilt,domains_filtered,filter_level2)
- domains_filtered = domains_rebuilt
-
- return domains_filtered
+ return configobjects
end
function getfilelist ()
local listed_files = {}
- for k,v in pairs{baseurl} do
- recursedir(v, listed_files)
- end
--- table.sort(listed_files, function (a,b) return (a.name < b.name) end )
+ recursedir(configdir, listed_files)
- return listed_files
+ return cfe({ type="list", value=listed_files, label="List of config files" })
end
-function get_filedetails(self,path)
- if not (validfilename(path)) then
- return false, "Not a valid filename!"
- end
+function get_filedetails(path)
local file = {}
local filedetails = {}
- local config = {}
local filenameerrtxt
if (path) and (fs.is_file(path)) then
filedetails = fs.stat(path)
- config = getconfig(path)
else
- config = {}
- config.filename = {}
- config["filename"]["errtxt"]="Config file '".. tostring(path) .. "' is missing!"
+ filenameerrtxt="Config file '".. tostring(path) .. "' is missing!"
end
- file["filename" .. (num or "")] = cfe({
- name="filename" .. (num or ""),
+ file["filename"] = cfe({
label="File name",
value=path,
errtxt=filenameerrtxt
})
- file["filesize" .. (num or "")] = cfe({
- name="filesize" .. (num or ""),
+ file["filesize"] = cfe({
label="File size",
- value=filedetails.size or 0,
+ value=filedetails.size or "0",
})
- file["mtime" .. (num or "")] = cfe({
- name="mtime" .. (num or ""),
+ file["mtime"] = cfe({
label="File date",
value=filedetails.mtime or "---",
})
- file["filecontent" .. (num or "")] = cfe({
+ file["filecontent"] = cfe({
type="longtext",
- name="filecontent" .. (num or ""),
label="File content",
value=fs.read_file(path),
})
- -- Sum all errors into one cfe
- local sumerrors = ""
- for k,v in pairs(config) do
- if (config[k]) and (config[k]["errtxt"]) and (config[k]["errtxt"] ~= "") then
- sumerrors = sumerrors .. config[k]["errtxt"] .. "\n"
- end
- end
- if (sumerrors ~= "") then
- file["sumerrors" .. (num or "")] = cfe ({
- name="sumerrors" .. (num or ""),
- label = "Configuration errors",
- errtxt = string.match(sumerrors, "(.-)\n$"),
- })
- end
-
- return file
+ return cfe({ type="group", value=file, label="Config file details" })
end
-function updatefilecontent (self, filetochange)
- local path = filetochange.name
- local modifications = filetochange.value
+function updatefilecontent (path, modifications)
+ local success = false
+ local errtxt
if not (fs.is_file(path)) then
- return false, "Not a filename"
- end
- if (validfilename(path)) then
+ errtxt = "Not a filename"
+ elseif (validfilename(path)) then
fs.write_file(path, format.dostounix(modifications))
- return true
+ success = true
else
- return false, "Not a valid filename!"
+ errtxt = "Not a valid filename!"
end
- return false, "Something went wrong!"
+
+ return cfe({ type="boolean", value=success, label="Update file result", errtxt=errtxt })
end
-function createconfigfile (self, path)
- local validfilepath, filepatherror = validator.is_valid_filename(path,baseurl)
- if (fs.is_file(path)) then
- return false,"File already exists"
- end
+function getnewconfigfile()
+ local options = {}
+ options.filename = cfe({ value=configdir.."/", label="File Name" })
+ return cfe({ type="group", value=options, label="New config file" })
+end
+
+function createconfigfile(configfile)
+ configfile.errtxt = "Failed to create file"
+ local path = configfile.value.filename.value
+ local validfilepath, filepatherror = validator.is_valid_filename(path,configdir)
if (validfilepath) then
- fs.write_file(path, "")
- return true,nil
+ if (fs.is_file(path)) then
+ configfile.value.filename.errtxt = "File already exists"
+ else
+ local file = io.open(path, "w")
+ file:close()
+ configfile.errtxt = nil
+ end
else
- return false, filepatherror
+ configfile.value.filename.errtxt = filepatherror
end
- return false, "Something went wrong!"
+
+ return configfile
end
-function remove_file(self, path)
+
+function remove_file(path)
+ local success = false
+ local errtxt
if not (fs.is_file(path)) then
- return false,"File doesn't exist!"
- end
- if (validfilename(path)) then
+ errtxt = "File doesn't exist!"
+ elseif (validfilename(path)) then
local cmd, errors = io.popen( "/bin/rm " .. path, r )
local cmdoutput = cmd:read("*a")
cmd:close()
- return true, cmdoutput
+ success = true
else
- return false, "Not a valid filename!"
+ errtxt = "Not a valid filename!"
end
- return false, "Something went wrong!"
+ return cfe({ type="boolean", value=success, label="Delete config file result", errtxt=errtxt })
end
diff --git a/tinydns-newfile-html.lsp b/tinydns-newfile-html.lsp
new file mode 100644
index 0000000..f727833
--- /dev/null
+++ b/tinydns-newfile-html.lsp
@@ -0,0 +1,17 @@
+<? local form, viewlibrary = ...
+require("viewfunctions")
+?>
+<?
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(form))
+io.write("</span>")
+--]]
+?>
+
+<h1>CONFIGURATION</h1>
+<h2><?= form.label ?></h2>
+<?
+ form.action = "newfile"
+ displayform(form)
+?>
diff --git a/tinydns-startstop-html.lsp b/tinydns-startstop-html.lsp
new file mode 100644
index 0000000..f3f7013
--- /dev/null
+++ b/tinydns-startstop-html.lsp
@@ -0,0 +1,26 @@
+<? local data = ... ?>
+<? --[[
+io.write(html.cfe_unpack(data))
+--]] ?>
+
+<H1>MANAGEMENT</H1>
+<DL>
+<form action="startstop" method="POST">
+<DT>Program control-panel</DT>
+<DD>
+<input class="submit" type="submit" name="action" value="Start" <? if data.value.status.value== "Enabled" then io.write("disabled") end ?>>
+<input class="submit" type="submit" name="action" value="Stop" <? if data.value.status.value== "Disabled" then io.write("disabled") end ?>>
+<input class="submit" type="submit" name="action" value="Restart" <? if data.value.status.value== "Disabled" then io.write("disabled") end ?>>
+</DD>
+</form>
+
+<? if data.value.result then ?>
+<DT>Previous action result</DT>
+<DD>
+<? if data.value.result.descr then ?>
+<P CLASS='descr'><?= string.gsub(data.value.result.descr, "\n", "<BR>") ?></P>
+<? end if data.value.result.errtxt then ?>
+<P CLASS='error'><?= string.gsub(data.value.result.errtxt, "\n", "<BR>") ?></P>
+<? end end ?>
+</DD>
+</DL>
diff --git a/tinydns-status-html.lsp b/tinydns-status-html.lsp
index 28c7ee2..c006939 100644
--- a/tinydns-status-html.lsp
+++ b/tinydns-status-html.lsp
@@ -1,100 +1,123 @@
-<? local form = ...
+<? local view, viewlibrary = ...
require("viewfunctions")
?>
+
+<script type="text/javascript" src="/js/jquery-latest.js"></script>
+<script type="text/javascript">
+ last_phrase = ""
+ $(function(){
+ $("#filter").keyup(function(){
+ var phrase = this.value;
+ if (phrase == last_phrase) return false;
+ last_phrase = phrase;
+ var elems = $("#records").find("li");
+ elems.each(function(){
+ var elem = this
+ if (elem.innerText.indexOf(phrase)>=0) {
+ jQuery(elem).show();
+ } else {
+ jQuery(elem).hide();
+ };
+ })
+ })
+ $("#filter-list").submit(function(){
+ return false;
+ }).focus();
+ });
+</script>
+
<?
--[[ DEBUG INFORMATION
io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
-io.write(html.cfe_unpack(form))
+io.write(html.cfe_unpack(view))
io.write("</span>")
--]]
?>
-<H1>SYSTEM INFO</H1>
+<? if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("basicstatus")
+end ?>
+
+<H1>PROGRAM SPECIFIC OPTIONS/INFORMATION</H1>
+<H2>Locations</H2>
<DL>
<?
-local myform = form.status
-local tags = { "status", "version", "autostart", }
-displayinfo(myform,tags,"viewonly")
-?>
+if (view) and (view['%']) then
+ local val = view['%'] ?>
+ <DT<? if (val.errtxt) then io.write(" class='error'") end ?>><?= val.label ?></DT>
+
+ <DD>
+ <? local currentloc = ""
+ for i,loc in ipairs(val) do
+ if currentloc ~= loc[1] then ?>
+ <IMG SRC='/skins/static/tango/16x16/places/start-here.png' width='16' height='16' alt> <B><?= loc[1] ?></B>
+ <? end
+ currentloc = loc[1] ?>
+ <BR><SPAN STYLE='margin-left:30px;'><?= loc[2] ?></SPAN><BR>
+ <? if (loc.errtxt) then ?><P CLASS='error'><?= string.gsub(loc.errtxt, "\n", "<BR>") ?></P><? end ?>
+ <? end ?>
+ </DD>
+<? end ?>
</DL>
<?
-local myform = form.config.locations
-?>
-<H2>PROGRAM SPECIFIC OPTIONS/INFORMATION</H2>
-<H3>Locations</H3>
-<?
-io.write("<DL>")
-if (myform) and (myform.value) then
- local val = myform
- io.write("\n\t<DT")
- if (val.errtxt) then
- io.write(" class='error'")
+local function doListIndents(next, indent)
+ local newentry = {}
+ for mt in string.gmatch(next, "([^.]+)") do
+ table.insert(newentry, mt)
end
- io.write(">" .. val.label .. "</DT>")
-
- io.write("\n\t\t<DD>")
- for k,v in pairs(myform.value) do
- io.write("<IMG SRC='/skins/static/tango/16x16/places/start-here.png' width='16' height='16' alt> <B>" .. tostring(k) .. "</B>")
- for kk,vv in pairs(v) do
- io.write(tostring("<BR><SPAN STYLE='margin-left:30px;'>" .. vv .. "</SPAN>\n"))
- end
- io.write("<BR>")
+ local revnewentry = {}
+ for j=#newentry,1,-1 do
+ table.insert(revnewentry, newentry[j])
end
-
- if (val.descr) and (#val.descr > 0) then io.write("\n\t\t<P CLASS='descr'>" .. string.gsub(val.descr, "\n", "<BR>") .. "</P>") end
- if (val.errtxt) then io.write("\n\t\t<P CLASS='error'>" .. string.gsub(val.errtxt, "\n", "<BR>") .. "</P>") end
- io.write("\n\t\t</DD>")
-end
-io.write("</DL>")
-?>
-
-<?
-local function recurseoutput(table,cnt)
- if not (cnt) then cnt=0 end
- cnt = cnt + 1
- for k,v in pairs(table or {}) do
- if (table[k].label) then
- if not (tonumber(k)) or (v.value) then
--- if v.label then
- io.write("\n\t\t\t<IMG SRC='/skins/static/tango/16x16/devices/computer.png' width='16' height='16' alt STYLE='margin-left:"..cnt..
- "0px'><SPAN STYLE=''> " .. tostring(v.label) .. "</SPAN><BR>")
- io.write("\n\t\t\t<TABLE STYLE='margin-left:90px;'>")
- for k1,v1 in pairs(v.option) do
- if (v1.label) then
- io.write("\n\t\t\t\t<TR>\n\t\t\t\t\t<TD WIDTH='160px' STYLE='border:none;'>".. tostring(v1.label) ..
- ":</TD>\n\t\t\t\t\t<TD STYLE='border:none;'>".. tostring(v1.value) .."</TD>\n\t\t\t\t</TR>")
- end
- end
- io.write("\n\t\t\t</TABLE>")
--- end
- else
- io.write("\n\t\t\t<SPAN STYLE='margin-left:"..cnt.."0px;font-weight:bold;'> "..
- tostring(table[k].label) .. "</SPAN><BR>")
- recurseoutput(v,cnt)
- end
- end
+ local i=1
+ while indent[i] and revnewentry[i] == indent[i] do
+ i=i+1
end
-end
-?>
-
-<H3>Records</H3>
-<?
-local tags = {"nsourdomain", "nsdomain", "host", "alias", "mx", "ptr", "cname", "soa", "generic", "all" }
-local myform = form.config.settings
-io.write("<DL>")
-for k,v in pairs(tags) do
- local myform = myform[v]
- if (myform) and (myform.value) then
- io.write("\n\t<DT")
- io.write(">" .. myform.label .. "</DT>")
- io.write("\n\t\t<DD>")
-
- for k,v in pairs(myform.value) do
- recurseoutput(v)
- end
- io.write("\n\t\t</DD>")
+ local ending = #indent-(i-1)
+ local starting = #newentry-(i-1)
+ for j=1,ending do
+ io.write("</li></ul>\n")
+ end
+ for j=1,starting do
+ io.write("<ul><li STYLE='margin-left:10px;'><strong>")
+ io.write(table.concat(newentry, ".", #newentry-(i+j-2), #newentry))
+ io.write("</strong>\n")
end
+ return revnewentry
end
-io.write("</DL>")
?>
+
+<H2>Records</H2>
+<form id="filter-list">Filter: <input name="filter" id="filter" value="" maxlength="30" size="30" type="text"></form>
+<DL id="records">
+<?
+local tags = {".", "&", "=", "+", "@", "'", "^", "C", "Z", ":" }
+for i,entrytype in ipairs(tags) do
+ local myview = view[entrytype]
+ if (myview) then ?>
+ <DT><?= myview.label ?></DT>
+ <DD><ul>
+ <? local indent = {}
+ for j,entry in ipairs(myview) do
+ indent = doListIndents(entry[1], indent) ?>
+ <ul><li STYLE='margin-left:10px;'><IMG SRC='/skins/static/tango/16x16/devices/computer.png' width='16' height='16'><?= tostring(entry[1]) ?><BR>
+ <TABLE STYLE='margin-left:<?= tostring(7-#indent) ?>0px;'>
+ <? for k=2,#entry do
+ local option = entry[k]
+ if (option) and option ~= "" then ?>
+ <TR><TD WIDTH='160px' STYLE='border:none;'><?= myview.fieldlabels[k] ?>:</TD>
+ <TD STYLE='border:none;'><?= option ?></TD></TR>
+ <? end
+ end ?>
+ </TABLE>
+ <? if entry.errtxt then ?>
+ <P CLASS='error'><?= string.gsub(entry.errtxt, "\n", "<BR>") ?></P>
+ <? end ?>
+ </li></ul>
+ <? end
+ doListIndents("", indent) ?>
+ </ul></DD>
+ <? end
+end ?>
+</DL>
diff --git a/tinydns.menu b/tinydns.menu
index 6d2ee02..70984b4 100644
--- a/tinydns.menu
+++ b/tinydns.menu
@@ -1,4 +1,4 @@
#CAT GROUP/DESC TAB ACTION
Networking 10DNS Status status
-#Networking 10DNS Config config
-Networking 10DNS Expert expert
+Networking 10DNS Config config
+Networking 10DNS List_Files listfiles
diff --git a/tinydns.roles b/tinydns.roles
index 6e6fd1f..45a2655 100644
--- a/tinydns.roles
+++ b/tinydns.roles
@@ -1,2 +1,2 @@
-READ=tinydns:status
-UPDATE=tinydns:expert,tinydns:edit,tinydns:confirmaction
+READ=tinydns:status,tinydns:basicstatus
+UPDATE=tinydns:config,tinydns:listfiles,tinydns:delete,tinydns:edit,tinydns:expert,tinydns:newfile,tinydns:startstop