From eed04050845bf81ac5e5d114c2fb05ae8dfede47 Mon Sep 17 00:00:00 2001 From: Ted Trask Date: Fri, 12 Jun 2009 14:02:29 +0000 Subject: Rewrote config write to make keyword order consistent and always put username as first user option. --- fetchmail-model.lua | 179 +++++++++++++++++++++++++++++----------------------- 1 file changed, 101 insertions(+), 78 deletions(-) (limited to 'fetchmail-model.lua') diff --git a/fetchmail-model.lua b/fetchmail-model.lua index bb74348..610b99c 100644 --- a/fetchmail-model.lua +++ b/fetchmail-model.lua @@ -106,29 +106,45 @@ local function writeentryline(entrystruct, entryline) -- If there is a structure, create the entryline array if entrystruct then - entryline = entryline or {} - insertentries = {} - local reverseentry = findkeywordsinentry(entryline) - -- Server options must come before user options, so add user option to end - -- and add server options just after remotehost (3). To do this, we'll use an array - -- of insertentries that will be inserted at the end. To delete entries, just set - -- them to nil, creating a sparse array. We can fix that at the end also - -- Here are two helper functions - function setserveroption(option, value) - if reverseentry[option] then - entryline[reverseentry[option]+1] = value - else - insertentries[table.maxn(insertentries)+1] = option - insertentries[table.maxn(insertentries)+1] = value + -- We'll use a reverseentry array to tell where entries are in entryline + local reverseentry = {} + if entryline then + reverseentry = findkeywordsinentry(entryline) + -- to handle entries that have multiple names + function equateentries(option1,option2) + if reverseentry[option1] then + reverseentry[option2] = reverseentry[option1] + else + reverseentry[option1] = reverseentry[option2] + end end + equateentries("proto", "protocol") + equateentries("local", "localdomains") + equateentries("auth", "authenticate") + equateentries("user", "username") + equateentries("pass", "password") + else + entryline = {} + end + + -- From http://fetchmail.berlios.de/fetchmail-man.html: + -- "All user options must begin with a user description (user or username option) + -- and follow all server descriptions and options." + -- So, what we'll do is build two new server/user option arrays. + -- Then, we'll add in the options we don't understand and combine the arrays. + -- So, our options will be in order and unknown ones will be at the end of each section. + local serveroptions = {} + local useroptions = {} + -- Here are some helper functions to set option values and delete from entryline + function setserveroption(option, value) + serveroptions[#serveroptions+1] = option + serveroptions[#serveroptions+1] = value + deleteoptionandvalue(option) end function setuseroption(option, value) - if reverseentry[option] then - entryline[reverseentry[option]+1] = value - else - entryline[table.maxn(entryline)+1] = option - entryline[table.maxn(entryline)+1] = value - end + useroptions[#useroptions+1] = option + useroptions[#useroptions+1] = value + deleteoptionandvalue(option) end function deleteoption(option) if reverseentry[option] then @@ -152,21 +168,57 @@ local function writeentryline(entrystruct, entryline) end -- Now we can start to set stuff + -- First, the first two entries if entrystruct.value.enabled.value then - entryline[1] = "poll" + serveroptions[1] = "poll" else - entryline[1] = "skip" - end - entryline[2] = entrystruct.value.remotehost.value - -- generic stuff - deleteoptionandvalue("proto") - deleteoptionandvalue("local") - deleteoptionandvalue("user") - deleteoptionandvalue("pass") + serveroptions[1] = "skip" + end + serveroptions[2] = entrystruct.value.remotehost.value + entryline[1] = nil + entryline[2] = nil -- remove here and there - for i=1,table.maxn(entryline) do - if entryline[i] == "here" or entryline[i] == "there" then - entryline[i] = nil + if reverseentry.here then + entryline[reverseentry.here] = nil + end + if reverseentry.there then + entryline[reverseentry.there] = nil + end + + -- Now we get to the interesting stuff + if entrystruct.value.method.value == "etrn" then + deleteoptionandvalue("username") + deleteoptionandvalue("password") + deleteoptionandvalue("is") + deleteoptionandvalue("smtphost") + deleteoption("ssl") + deletenooption("rewrite") + deleteoption("fetchall") + deletenooption("dns") + else -- Method not etrn + setuseroption("username", entrystruct.value.remotemailbox.value) + setuseroption("password", '"'..entrystruct.value.remotepassword.value..'"') + if entrystruct.value.method.value == "pop3domain" then + deleteoptionandvalue("is") + else + setuseroption("is", entrystruct.value.localmailbox.value) + end + setuseroption("smtphost", entrystruct.value.localhost.value) + if entrystruct.value.ssl.value and not reverseentry["ssl"] then + useroptions[#useroptions+1] = "ssl" + elseif not entrystruct.value.ssl.value and reverseentry["ssl"] then + entryline[reverseentry["ssl"]] = nil + end + if not reverseentry["rewrite"] then + useroptions[#useroptions+1] = "no" + useroptions[#useroptions+1] = "rewrite" + end + if not reverseentry["fetchall"] then + useroptions[#useroptions+1] = "fetchall" + end + if not reverseentry["dns"] then + serveroptions[#serveroptions+1] = "no" + serveroptions[#serveroptions+1] = "dns" end end if entrystruct.value.method.value == "pop3domain" then @@ -208,58 +260,29 @@ local function writeentryline(entrystruct, entryline) end if entrystruct.value.method.value == "pop3domain" then if entrystruct.value.envelope.value == "disabled" then - insertentries[table.maxn(insertentries)+1] = "no" - insertentries[table.maxn(insertentries)+1] = "envelope" + + serveroptions[#serveroptions+1] = "no" + serveroptions[#serveroptions+1] = "envelope" else - insertentries[table.maxn(insertentries)+1] = "envelope" - insertentries[table.maxn(insertentries)+1] = envelopecount - insertentries[table.maxn(insertentries)+1] = entrystruct.value.envelope.value + serveroptions[#serveroptions+1] = "envelope" + serveroptions[#serveroptions+1] = envelopecount + serveroptions[#serveroptions+1] = entrystruct.value.envelope.value end end - if entrystruct.value.method.value == "etrn" then - deletenooption("dns") - deleteoptionandvalue("username") - deleteoptionandvalue("password") - deleteoptionandvalue("smtphost") - deletenooption("rewrite") - deleteoption("fetchall") - deleteoption("ssl") - else -- Method not etrn - if not reverseentry["dns"] then - insertentries[table.maxn(insertentries)+1] = "no" - insertentries[table.maxn(insertentries)+1] = "dns" - end - setuseroption("username", entrystruct.value.remotemailbox.value) - setuseroption("password", '"'..entrystruct.value.remotepassword.value..'"') - setuseroption("smtphost", entrystruct.value.localhost.value) - if not reverseentry["rewrite"] then - entryline[table.maxn(entryline)+1] = "no" - entryline[table.maxn(entryline)+1] = "rewrite" - end - if not reverseentry["fetchall"] then - entryline[table.maxn(entryline)+1] = "fetchall" - end - if entrystruct.value.ssl.value and not reverseentry["ssl"] then - entryline[table.maxn(entryline)+1] = "ssl" - elseif not entrystruct.value.ssl.value and reverseentry["ssl"] then - entryline[reverseentry["ssl"]] = nil - end + + -- Now, insert the remaining options + for i=1,reverseentry["username"] or table.maxn(entryline) do + serveroptions[#serveroptions+1] = entryline[i] end - -- for some reason, the "is" option has to come after username/password - if entrystruct.value.method.value == "pop3domain" or entrystruct.value.method.value == "etrn" then - deleteoptionandvalue("is") - else - setuseroption("is", entrystruct.value.localmailbox.value) + for i=reverseentry["username"] or table.maxn(entryline), table.maxn(entryline) do + useroptions[#useroptions+1] = entryline[i] end - - -- Now, insert the insertentries and remove the nil entries - table.insert(insertentries, 1, entryline[1]) - table.insert(insertentries, 2, entryline[2]) - for i=3,table.maxn(entryline) do - table.insert(insertentries, entryline[i]) + local linenum = entryline.linenum + entryline = serveroptions + for i,val in ipairs(useroptions) do + entryline[#entryline+1] = val end - insertentries.linenum = entryline.linenum - entryline = insertentries + entryline.linenum = linenum end local file = fs.read_file(configfile) or "" -- cgit v1.2.3