1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
module(..., package.seeall)
-- Load libraries
require("modelfunctions")
require("posix")
fs = require("acf.fs")
format = require("acf.format")
validator = require("acf.validator")
-- Set variables
local processname = "postfix"
local packagename = "postfix"
local baseurl = "/etc/postfix/"
local aliasesfile = "/etc/postfix/aliases"
local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin "
-- ################################################################################
-- LOCAL FUNCTIONS
local getconfig = function()
-- the postfix config is like an ini file, but it allows multi-line entries
-- so, we convert and then parse like ini file
local content = fs.read_file(baseurl.."main.cf") or ""
-- lines that begin with whitespace and first non-whitespace character is not '#'
-- are continuations, so delete the carriage return
-- have to delete blank and comment lines first, because could be before continuation line
-- I've seen no documentation on inline comments, so user beware
content = string.gsub(content, "\n+", "\n")
content = string.gsub(content, "\n%s*#[^\n]*", "")
content = string.gsub(content, "\n[^%S\n]+([^#])", " %1")
return format.parse_ini_file(content, "") or {}, content
end
-- ################################################################################
-- PUBLIC FUNCTIONS
function get_startstop(clientdata)
return modelfunctions.get_startstop(processname)
end
function startstop_service(startstop, action)
return modelfunctions.startstop_service(startstop, action)
end
function getstatus()
return modelfunctions.getstatus(processname, packagename, "Postfix Status")
end
function getstatusdetails()
return cfe({ type="longtext", value="", label="Postfix Status Details" })
end
local function geteditablefilelist()
local listed_files = fs.find_files_as_array("[^%.].*", baseurl)
-- remove .db files
local result = {}
for i,name in ipairs(listed_files) do
if not string.find(name, "%.db$") then
result[#result+1] = name
end
end
return result
end
function getfilelist()
local listed_files = {}
for i,name in ipairs(geteditablefilelist()) do
local filedetails = fs.stat(name) or {}
table.insert ( listed_files , {filename=name, mtime=filedetails.mtime or "---", filesize=filedetails.size or "0"} )
end
table.sort(listed_files, function (a,b) return (a.filename < b.filename) end )
return cfe({ type="list", value=listed_files, label="Postfix File List" })
end
function getfiledetails(filename)
return modelfunctions.getfiledetails(filename, geteditablefilelist())
end
function updatefiledetails(filedetails)
return modelfunctions.setfiledetails(filedetails, geteditablefilelist())
end
function getnewfile()
local options = {}
options.filename = cfe({ label="File Name" })
return cfe({ type="group", value=options, label="New File" })
end
function createfile(newfile)
newfile.errtxt = "Failed to create file"
local path = string.match(newfile.value.filename.value, "^%s*(.*%S)%s*$") or ""
if not string.find(path, "/") then
path = baseurl..path
end
if validator.is_valid_filename(path, baseurl) then
if posix.stat(path) then
newfile.value.filename.errtxt = "File already exists"
elseif string.find(path, "%.db$") then
newfile.value.filename.errtxt = "Cannot create .db files"
else
fs.create_file(path)
newfile.errtxt = nil
end
else
newfile.value.filename.errtxt = "Invalid filename"
end
return newfile
end
function deletefile(filename)
local result = cfe({ value="Failed to delete file", label="Delete file result" })
if not validator.is_valid_filename(filename, baseurl) then
result.errtxt = "Not a valid filename!"
elseif not fs.is_file(filename) then
result.errtxt = "File doesn't exist!"
else
os.remove(filename)
result.value = "File Deleted"
end
return result
end
function rebuild_databases()
local result = cfe({ value={"Rebuilding databases"}, label="Rebuild Databases result" })
table.insert(result.value, " See logfile for possible errors")
local cmd,f,cmdresult
-- parse main.cf looking for hash files
local config, content = getconfig()
for i,db in ipairs({"btree", "cdb", "dbm", "hash", "sdbm"}) do
for filename in string.gmatch(content, "[%s=]("..db..":%S+)") do
filename = string.gsub(filename, ",$", "")
-- run postmap on file
if filename and not string.find(filename, aliasesfile) then
cmd = "postmap "..filename
table.insert(result.value, "Running: "..cmd)
f = io.popen(format.escapespecialcharacters(path..cmd))
table.insert(result.value, f:read("*a"))
f:close()
end
end
end
-- finally, run newaliases
cmd = "newaliases"
table.insert(result.value, "Running: "..cmd)
f = io.popen(format.escapespecialcharacters(path..cmd))
table.insert(result.value, f:read("*a"))
f:close()
result.value = table.concat(result.value, "\n")
return result
end
function getmailqueue()
local f = io.popen(path.."mailq")
local result = f:read("*a")
f:close()
return cfe({ type="longtext", value=result, label="Postfix Mail Queue" })
end
function flushqueue()
local f = io.popen(path.."postqueue -f")
local result = f:read("*a")
f:close()
if not result or result == "" then result = "Queue Flushed" end
return cfe({ type="longtext", value=result, label="Postfix Flush Queue Result" })
end
|