Commit 7675a312 authored by Ted Trask's avatar Ted Trask

Added config to fetchmail to configure globals and multiple entries. Also...

Added config to fetchmail to configure globals and multiple entries.  Also added ability to run once and test.  Still need support for ETRN and SSL.

git-svn-id: svn://svn.alpinelinux.org/acf/fetchmail/trunk@1437 ab2d0c66-481e-0410-8bed-d214d4d58bed
parent 0441e224
<% local form = ... <% local view, viewlibrary, page_info, session = ... %>
require("viewfunctions") <% 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>SYSTEM INFO</H1> <% displaycommandresults({"deleteentry"}, session) %>
<DL>
<%
local myform = form.status
local tags = { "status", "version", "autostart", }
displayinfo(myform,tags,"viewonly")
%>
</DL>
<H1>CONFIGURATION</H1>
<% local myform = form.config %>
<form action="<%= form.option.script .. "/" .. form.option.prefix ..
form.option.controller .. "/" .. form.option.action %>" method="POST">
<H2>GUIDED CONFIGURATION</H2> <% if viewlibrary and viewlibrary.dispatch_component then
<% --[[ %> viewlibrary.dispatch_component("status")
<H3>FREQUENCY</H3> end %>
<P>Select how often the mailboxes will be checked. For ETRN transfers (below) this specifies how often transfers are initiated</P>
<%
local tags = { "freq", }
displayinfo(myform,tags)
%>
<% --]] %>
<H3>MAILBOXES</H3> <H1>Global Settings</H1>
<P>You will need to specify the remote mailbox and password, as well as the local (internal) mailbox to forward the mail to. The SMTP host is the name or address of the SMTP server to send the mail to.</P>
<P>If you want to use POP3 account for the entire domain, selecting the <U>pop3domain</U> method will setup the appropriate configuration for retrieving and distributing the mail appropriately. The <B>domain</B> information should be your internet smtp domain. The <B>mailbox</B> field is ignored when this method is selected.</P>
<P>When selecting the <U>pop3</U> or <U>imap</U> methods, the <B>domain</B> field should be left blank.</P>
<% -- START - SPECIAL VIEW FOR SHOWING AVAILABLE MAILBOXES %>
<%
local tags = "mailboxes"
local mailboxform = myform[tags]["value"]
%>
<DL> <DL>
<% <dt>Edit global settings</dt>
io.write("\n\t<CENTER><TABLE STYLE='border:1px solid #ccc;background:#eee'>\n\t\t<TR>\n\t\t\t<TD CLASS='header' WIDTH='150px'>") <dd><form action="<%= page_info.script .. page_info.prefix .. page_info.controller .. "/editconfig" %>" method="POST">
io.write("<CENTER>METHOD</CENTER></TD>\n\t\t\t<TD CLASS='header' COLSPAN=2>") <input type=submit value="Edit" class="submit">
io.write("<CENTER>REMOTE</CENTER></TD>\n\t\t\t<TD CLASS='header' COLSPAN=2>") </form></dd>
io.write("<CENTER>LOCAL</CENTER></TD>\n\t\t</TR>")
for i=1, table.maxn(mailboxform) do
leftpadd="30px"
rightpadd="5px"
io.write("\n\t\t<TR>\n\t\t\t<TD>")
val = "method"
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write("</TD>\n\t\t\t<TD style='padding-left:".. leftpadd .. ";padding-right:".. rightpadd .. ";' WIDTH='5%'>")
val = "remotehost"
io.write(mailboxform[i][val]["label"])
io.write(":</TD>\n\t\t\t<TD>")
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write("</TD>\n\t\t\t<TD style='padding-left:".. leftpadd .. ";padding-right:".. rightpadd .. ";' WIDTH='5%'>")
val = "localhost"
io.write(mailboxform[i][val]["label"])
io.write(":</TD>\n\t\t\t<TD>")
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write("</TD>\n\t\t</TR>")
io.write("\n\t\t<TR>\n\t\t\t<TD>")
val = "disabled"
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write(" " .. mailboxform[i][val]["label"])
io.write("</TD>\n\t\t\t<TD style='padding-left:".. leftpadd .. ";padding-right:".. rightpadd .. ";'>")
val = "remotemailbox"
io.write(mailboxform[i][val]["label"])
io.write(":</TD>\n\t\t\t<TD>")
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write("</TD>\n\t\t\t<TD style='padding-left:".. leftpadd .. ";padding-right:".. rightpadd .. ";'>")
val = "localmailbox"
io.write(mailboxform[i][val]["label"])
io.write(":</TD>\n\t\t\t<TD>")
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write("</TD>\n\t\t</TR>")
io.write("\n\t\t<TR>\n\t\t\t<TD>")
io.write("</TD>\n\t\t\t<TD style='padding-left:".. leftpadd .. ";padding-right:".. rightpadd .. ";'>")
val = "remotepassword"
io.write(mailboxform[i][val]["label"])
io.write(":</TD>\n\t\t\t<TD>")
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write("</TD>\n\t\t\t<TD style='padding-left:".. leftpadd .. ";padding-right:".. rightpadd .. ";'>")
val = "localdomain"
io.write(mailboxform[i][val]["label"])
io.write(":</TD>\n\t\t\t<TD>")
io.write(html.form[mailboxform[i][val]["type"]](mailboxform[i][val]))
io.write("</TD>\n\t\t</TR>")
io.write("\n\t\t<TR>\n\t\t\t<TD COLSPAN=5><HR></TD>\n\t\t</TR>")
end
io.write("</TABLE></CENTER>")
%>
</DL> </DL>
<% -- START - SPECIAL VIEW FOR SHOWING AVAILABLE MAILBOXES %>
<H3>LAST RESORT</H3>
<P>The Postmaster address is the address of last resort when fetchmail cannot determine how to send a mail message. If left blank, undelieverable mail may be discarded.</P>
<%
local tags = { "postmaster", }
displayinfo(myform,tags)
%>
<H3>ETRN</H3>
<P>This is for branches that have DNS mail domains hosted by an ISP that allows for ETRN dequeueing. ETRN dequeueing causes the SMTP mail exchanger at the ISP to forward mail to you via SMTP. You will need to make sure that DNS is setup appropriately and that your ISP supports ETRN. If you have not arranged with your ISP to have ETRN support, leave these fields blank.</P>
<%
local tags = { "etrnremote","etrnquedomain", }
displayinfo(myform,tags)
%>
<% --[[ %>
<H2>ADVANCED CONFIGURATION</H2>
<H3>GENERAL</H3>
<%
local tags = { "logfile", "loglevel", "smallerlogs", }
displayinfo(myform,tags)
%>
<% --]] %>
<H2>SAVE AND APPLY ABOVE SETTINGS</H2>
<%
local tags = { "cmdsave","cmdtest", }
displayinfo(myform,tags)
%>
</form>
<%
local cmdform = form.management
local tags = { "start", "stop", "restart" }
if (cmdform) and (cmdform[tags[1]]) then
%>
<form name="management" action="" method="POST">
<H1>MANAGEMENT</H1>
<dl>
<dt><%= cmdform[tags[1]]["label"] %></dt>
<dd>
<% for k,v in pairs(tags) do %>
<% if (cmdform[v]) then %>
<% io.write(html.form[cmdform[v].type](cmdform[v])) %>
<% end %>
<% end %>
</dd>
<% if (form.cmdmanagement) and (#form.cmdmanagement.descr > 0) then %> <% if viewlibrary and viewlibrary.dispatch_component then
<dt>Previous action result</dt> viewlibrary.dispatch_component("listentries")
<dd><pre><%= form.cmdmanagement.descr %></pre></dd> end %>
<% end %>
</dl>
</form>
<% end %> <% if viewlibrary and viewlibrary.dispatch_component then
viewlibrary.dispatch_component("startstop")
end %>
...@@ -11,11 +11,27 @@ end ...@@ -11,11 +11,27 @@ end
function startstop(self) function startstop(self)
return controllerfunctions.handle_startstop(self, self.model.startstop_service, self.model.getstatus, self.clientdata) return controllerfunctions.handle_startstop(self, self.model.startstop_service, self.model.getstatus, self.clientdata)
end end
--[[
function config(self) function editconfig(self)
return controllerfunctions.handle_form(self, self.model.getconfig, self.model.updateconfig, self.clientdata, "Save", "Edit Config", "Configuration Set") return controllerfunctions.handle_form(self, self.model.getconfig, self.model.updateconfig, self.clientdata, "Save", "Edit Config", "Configuration Set")
end end
--]]
function expert(self) function expert(self)
return controllerfunctions.handle_form(self, self.model.get_filedetails, self.model.update_filecontent, self.clientdata, "Save", "Edit Config", "Configuration Set") return controllerfunctions.handle_form(self, self.model.get_filedetails, self.model.update_filecontent, self.clientdata, "Save", "Edit Config", "Configuration Set")
end end
function listentries(self)
return self.model.readentries()
end
function editentry(self)
return controllerfunctions.handle_form(self, function() return self.model.readentry(self.clientdata.entry) end, self.model.updateentry, self.clientdata, "Save", "Edit Entry", "Entry Saved")
end
function createentry(self)
return controllerfunctions.handle_form(self, self.model.readentry, self.model.createentry, self.clientdata, "Create", "Create Entry", "Entry Created")
end
function deleteentry(self)
return self:redirect_to_referrer(self.model.deleteentry(self.clientdata.entry))
end
fetchmail-editentry-html.lsp
\ No newline at end of file
../form-html.lsp
\ No newline at end of file
<% local form, viewlibrary, page_info = ...
require("viewfunctions")
%>
<H1><%= form.label %></H1>
<%
form.action = page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action
if page_info.action == "editentry" then
form.value.remotehost.contenteditable = false
end
local order = { "remotehost", "enabled", "method", "remotemailbox", "remotepassword", "localhost", "localmailbox", "localdomain" }
displayform(form, order)
%>
<% local data, viewlibrary, page_info, session = ...
require("viewfunctions")
%>
<%
--[[ DEBUG INFORMATION
io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
io.write(html.cfe_unpack(data))
io.write("</span>")
--]]
%>
<% displaycommandresults({"deleteentry"}, session) %>
<h1>Edit/View Fetchmail Entries</h1>
<DL>
<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:left;" class="header">Entry</TD>
<TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Enabled</TD>
<TD style="white-space:nowrap;text-align:left;" class="header">Method</TD>
</TR>
<% for i,entry in ipairs(data.value) do %>
<TR>
<TD style="padding-right:20px;white-space:nowrap;">
<% io.write(html.link{value = "editentry?entry=" .. entry.entry, label="Edit " }) %>
<% io.write(html.link{value = "deleteentry?entry=" .. entry.entry, label="Delete " }) %>
</TD>
<TD style="padding-right:20px;white-space:nowrap;"><%= entry.entry %></TD>
<TD style="padding-right:20px;white-space:nowrap;"><%= entry.enabled %></TD>
<TD style="white-space:nowrap;" width="90%"><%= entry.method %></TD>
</TR>
<% end %>
</TABLE>
<DT>Add new entry</DT>
<DD><form action="<%= page_info.script .. page_info.prefix .. page_info.controller .. "/createentry" %>" method="POST">
<input type=submit value="New" class="submit">
</form></DD>
</DL>
...@@ -2,186 +2,304 @@ module(..., package.seeall) ...@@ -2,186 +2,304 @@ module(..., package.seeall)
-- Load libraries -- Load libraries
require("modelfunctions") require("modelfunctions")
require("posix")
require("fs") require("fs")
require("getopts")
require("validator")
-- Set variables -- Set variables
local packagename = "fetchmail" local packagename = "fetchmail"
local processname = "fetchmail" local processname = "fetchmail"
local configfile = "/root/.fetchmailrc" local configfile = "/etc/fetchmailrc"
local config = {} local confdfile = "/etc/conf.d/fetchmail"
local config
local methods = {"pop3","imap","pop3domain", }
-- ################################################################################ -- ################################################################################
-- LOCAL FUNCTIONS -- LOCAL FUNCTIONS
local function getloglevels() local function parseconfigfile(file)
local loglevels = {} file = file or ""
for i=1,8 do local retval = {}
table.insert(loglevels,i) local linenum=0
end for line in string.gmatch(file, "([^\n]*)\n?") do
return loglevels linenum=linenum+1
end if not string.match(line, "^%s*$") and not string.match(line, "^%s*#") then
table.insert(retval, {linenum=linenum})
local function getmethods() -- Iterate through each word, being careful about quoted strings and comments
local methods = {"pop3","imap","pop3domain", } local offset = 1
return methods while string.find(line, "%S+", offset) do
end local word = string.match(line, "%S+", offset)
local endword = select(2, string.find(line, "%S+", offset))
local function getmailboxes(t) if string.find(word, "^#") then
local objects = cfe({}) break
objects.label = "Mailbox " .. tostring(t["RBOX"]) elseif string.find(word, "^\"") then
objects.method = cfe({ endword = select(2, string.find(line, "\"[^\"]*\"", offset))
name="method", word = string.sub(line, string.find(line, "\"", offset), endword)
label = "Method", end
type = "select", table.insert(retval[#retval], word)
value = t["METHOD"], offset = endword + 1
option = getmethods(), end
}) end
objects.disabled = cfe({ end
name="disabled", return retval
type="checkbox", end
label = "Disabled",
checked = t["DISABLED"], local function findentryline(entryname)
}) if entryname and entryname ~= "" then
objects.remotehost = cfe({ config = config or parseconfigfile(fs.read_file(configfile))
name="remotehost", for i,entry in ipairs(config or {}) do
label = "RemoteHost", if (entry[1] == "server" or entry[1] == "poll" or entry[1] == "skip") and entry[2] == entryname then
value = t["RHOST"], return entry
}) end
objects.remotemailbox = cfe({ end
name="remotemailbox", end
label = "Mailbox", return nil
value = t["RBOX"], end
})
objects.remotepassword = cfe({ local function writeentryline(entrystruct, entryline)
name="remotepassword", if not entrystruct and not entryline then
label = "Password", return
type = "passwd", end
value = t["PASSWD"],
}) -- If there is a structure, create the entryline array
objects.localhost = cfe({ if entrystruct then
name="localhost", entryline = entryline or {}
label = "LocalHost", if entrystruct.value.enabled.value then
value = t["LHOST"], entryline[1] = "poll"
}) else
objects.localmailbox = cfe({ entryline[1] = "skip"
name="localmailbox", end
label = "LocalMailbox", entryline[2] = entrystruct.value.remotehost.value
value = t["LBOX"], local reverseentry = {}
}) for i,word in ipairs(entryline) do reverseentry[word] = i end
objects.localdomain = cfe({ -- server options must come before user options, so add user option to end
name="localdomain", -- and add server options just after remotehost (3)
label = "LocalDomain", -- start with the user options so we can add to the end and not mess up reverseentry
value = t["DOMAIN"], -- this means that we do method last
}) if reverseentry["user"] or reverseentry["username"] then
return objects entryline[(reverseentry["user"] or reverseentry["username"])+1] = entrystruct.value.remotemailbox.value
end else
entryline[#entryline+1] = "username"
local function read_config() entryline[#entryline+1] = entrystruct.value.remotemailbox.value
--[[ end
imap/pop3 lines are: if reverseentry["pass"] or reverseentry["password"] then
1 2 3 4 5 6 7 8 9 10 entryline[(reverseentry["pass"] or reverseentry["password"])+1] = '"'..entrystruct.value.remotepassword.value..'"'
poll <host> protocol <proto> no dns username <uname> password <passwd> else
11 12 13 14 15 16 17 entryline[#entryline+1] = "password"
is <localmailbox> smtphost <desthost> no rewrite fetchall entryline[#entryline+1] = '"'..entrystruct.value.remotepassword.value..'"'
end
pop3domain lines are: if reverseentry["smtphost"] then
1 2 3 4 5 6 7 8 9 10 11 12 entryline[reverseentry["smtphost"]+1] = entrystruct.value.localhost.value
poll <host> localdomainst <domain> protocol pop3 no dns username <uname> password <passwd> else
13 14 15 16 17 18 19 20 21 22 entryline[#entryline+1] = "smtphost"
to * here smtphost <desthost> smtpaddress <domain> no rewrite fetchall entryline[#entryline+1] = entrystruct.value.localhost.value
end
etrn is: -- add in some user options
1 2 3 4 5 6 if not reverseentry["rewrite"] then
pool <host> protocol etrn smtpdomain <mydomain> entryline[#entryline+1] = "no"
--]] entryline[#entryline+1] = "rewrite"
local mailboxes = {} end
local configcontent_postmaster = {} if not reverseentry["fetchall"] then
local configcontent_etrn = {} entryline[#entryline+1] = "fetchall"
local path = configfile end
local valid = nil -- now handle the method, localmailbox, and localdomain
configcontenttable = fs.read_file_as_array(path) or {} if entrystruct.value.method.value == "pop3domain" then
for k,v in pairs(configcontenttable) do if reverseentry["to"] then
if (string.match(v, "^%s*#Begin Fetchmail")) then valid=1 end entryline[reverseentry["to"]+1] = "*"
if (valid) then else
-- entryline[#entryline+1] = "to"
local DISABLED = string.match(v, "^%s*(#)") entryline[#entryline+1] = "*"
end
-- Set parameters for POP3 or IMAP if reverseentry["smtpaddress"] then
local val = {RHOST=2, CHECK=9 ,METHOD=4, RBOX=8, PASSWD=10, LBOX=12, LHOST=14} entryline[reverseentry["smtpaddress"]+1] = entrystruct.value.localdomain.value
local configcontent = {} else
configcontent[k] = {} entryline[#entryline+1] = "smtpaddress"
configcontent[k]["DISABLED"] = DISABLED entryline[#entryline+1] = entrystruct.value.localdomain.value
for kk,vv in pairs(val) do end
configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) if reverseentry["is"] then
end -- THIS MESSES UP reverseentry FOR THE USER OPTIONS
-- Remove quotes from passwords table.remove(entryline, reverseentry["is"])
if (configcontent[k]["PASSWD"]) then table.remove(entryline, reverseentry["is"])
configcontent[k]["PASSWD"] = string.match(configcontent[k]["PASSWD"], "^\"(.-)\"") end
end if reverseentry["proto"] or reverseentry["protocol"] then
-- Check if row is valid config entryline[(reverseentry["proto"] or reverseentry["protocol"])+1] = "pop3"
if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "password") then else
table.insert(mailboxes,getmailboxes(configcontent[k])) -- THIS MESSES UP reverseentry FOR EVERYTHING
end table.insert(entryline, 3, "pop3")
table.insert(entryline, 3, "protocol")
-- Set parameters for POP3domain -- FIX reverseentry
local val = {RHOST=2, METHOD=6, RBOX=10, CHECK=11, PASSWD=12, LHOST=17, DOMAIN=19,} reverseentry = {}
local configcontent = {} for i,word in ipairs(entryline) do reverseentry[word] = i end
configcontent[k] = {} end
configcontent[k]["DISABLED"] = DISABLED if reverseentry["local"] or reverseentry["localdomains"] then
for kk,vv in pairs(val) do entryline[(reverseentry["local"] or reverseentry["localdomains"])+1] = entrystruct.value.localdomain.value
configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) else
end -- THIS MESSES UP reverseentry FOR EVERYTHING
-- Display this config as Method=pop3domain (as the current options in the view) table.insert(entryline, 3, entrystruct.value.localdomain.value)
configcontent[k]["METHOD"] = "pop3domain" table.insert(entryline, 3, "localdomains")
-- Remove quotes from passwords end
if (configcontent[k]["PASSWD"]) then if not reverseentry["dns"] then
configcontent[k]["PASSWD"] = string.match(configcontent[k]["PASSWD"], "^\"(.-)\"") -- THIS MESSES UP reverseentry FOR EVERYTHING
end table.insert(entryline, 3, "dns")
-- Check if row is valid config table.insert(entryline, 3, "no")
if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "password") then end
table.insert(mailboxes,getmailboxes(configcontent[k])) else
end if reverseentry["is"] then
entryline[reverseentry["is"]+1] = entrystruct.value.localmailbox.value
-- Set parameters for etrn else
local val = {ETRNSMTPHOST=2, CHECK=4, ETRNDOMAIN=6} entryline[#entryline+1] = "is"
local configcontent = {} entryline[#entryline+1] = entrystruct.value.localmailbox.value
configcontent[k] = {} end
configcontent[k]["DISABLED"] = DISABLED if reverseentry["to"] then
for kk,vv in pairs(val) do -- THIS MESSES UP reverseentry FOR THE USER OPTIONS
configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) table.remove(entryline, reverseentry["to"])
end table.remove(entryline, reverseentry["to"])
-- Check if row is valid config -- FIX reverseentry
if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "etrn") then reverseentry = {}
configcontent_etrn=configcontent[k] for i,word in ipairs(entryline) do reverseentry[word] = i end
end end
if reverseentry["smtpaddress"] then
-- Set parameters for postmaster -- THIS MESSES UP reverseentry FOR THE USER OPTIONS
local val = {CHECK=2, POSTMASTER=3} table.remove(entryline, reverseentry["smtpaddress"])
local configcontent = {} table.remove(entryline, reverseentry["smtpaddress"])
configcontent[k] = {} end
configcontent[k]["DISABLED"] = DISABLED if reverseentry["proto"] or reverseentry["protocol"] then
for kk,vv in pairs(val) do entryline[(reverseentry["proto"] or reverseentry["protocol"])+1] = entrystruct.value.method.value
configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) else
end -- THIS MESSES UP reverseentry FOR EVERYTHING
-- Check if row is valid config table.insert(entryline, 3, entrystruct.value.method.value)
if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "postmaster") then table.insert(entryline, 3, "protocol")
configcontent_postmaster=configcontent[k] -- FIX reverseentry
end reverseentry = {}
for i,word in ipairs(entryline) do reverseentry[word] = i end
end end
if (string.match(v, "^%s*#End Fetchmail")) then valid=nil end if reverseentry["local"] or reverseentry["localdomains"] then
end -- THIS MESSES UP reverseentry FOR EVERYTHING
-- Create one empty record so that user can add settings table.remove(entryline, (reverseentry["local"] or reverseentry["localdomains"]))
table.insert(mailboxes,getmailboxes({})) table.remove(entryline, (reverseentry["local"] or reverseentry["localdomains"]))
return mailboxes,configcontent_postmaster,configcontent_etrn end
if not reverseentry["dns"] then
-- THIS MESSES UP reverseentry FOR EVERYTHING
table.insert(entryline, 3, "dns")
table.insert(entryline, 3, "no")
end
end
-- remove here and there
for i=#entryline,1,-1 do
if entryline[i] == "here" or entryline[i] == "there" then
table.remove(entryline, i)
end
end
end
local file = fs.read_file(configfile)
local lines = {file}
if entryline and entryline.linenum then
-- Split the file to remove the line
local startchar, endchar = string.match(file, string.rep("[^\n]*\n", entryline.linenum-1) .. "()[^\n]*\n()")
if startchar and endchar then
lines[1] = string.sub(file, 1, startchar-1)
lines[2] = string.sub(file, endchar, -1)
end
end
if entryline and entrystruct then
table.insert(lines, 2, table.concat(entryline," ").."\n")
end
fs.write_file(configfile, string.gsub(table.concat(lines), "\n+$", ""))
posix.chmod(configfile, "rwx--x---")
config = nil
end
local function validateentry(entry)
local success = true
success = modelfunctions.validateselect(entry.value.method) and success
if entry.value.remotehost.value == "" then
entry.value.remotehost.errtxt = "Invalid entry - cannot be blank"
success = false
elseif string.find(entry.value.remotehost.value, "[^%w.-]") then
entry.value.remotehost.errtxt = "Invalid entry - may only contain alphanumeric, '.', or '-'"
success = false
end
if entry.value.remotemailbox.value == "" then
entry.value.remotemailbox.errtxt = "Invalid entry - cannot be blank"
success = false
elseif string.find(entry.value.remotemailbox.value, "[^%w.-_@]") then
entry.value.remotemailbox.errtxt = "Invalid entry"
success = false
end
if entry.value.remotepassword.value == "" then
entry.value.remotepassword.errtxt = "Invalid entry - cannot be blank"
success = false
elseif string.find(entry.value.remotepassword.value, "%s") then
entry.value.remotepassword.errtxt = "Invalid entry - cannot contain whitespace"
success = false
end
if entry.value.localhost.value == "" then
entry.value.localhost.errtxt = "Invalid entry - cannot be blank"
success = false
elseif string.find(entry.value.localhost.value, "[^%w.-]") then
entry.value.localhost.errtxt = "Invalid entry - may only contain alphanumeric, '.', or '-'"
success = false
end
if entry.value.method.value == "pop3domain" and entry.value.localmailbox.value ~= "" then
entry.value.localmailbox.errtxt = "Cannot define local mailbox for pop3domain method"
success = false
elseif entry.value.method.value ~= "pop3domain" and entry.value.localmailbox.value == "" then
entry.value.localmailbox.errtxt = "Invalid entry - cannot be blank"
success = false
elseif string.find(entry.value.localmailbox.value, "[^%w.-_@]") then
entry.value.localmailbox.errtxt = "Invalid entry"
success = false
end
if entry.value.method.value ~= "pop3domain" and entry.value.localdomain.value ~= "" then
entry.value.localdomain.errtxt = "Cannot define local domain unless pop3domain method"
success = false
elseif entry.value.method.value == "pop3domain" and entry.value.localdomain.value == "" then
entry.value.localdomain.errtxt = "Invalid entry - cannot be blank"
success = false
elseif string.find(entry.value.localdomain.value, "[^%w.-]") then
entry.value.localdomain.errtxt = "Invalid entry - may only contain alphanumeric, '.', or '-'"
success = false