-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunctions.lua
More file actions
230 lines (207 loc) · 4.67 KB
/
functions.lua
File metadata and controls
230 lines (207 loc) · 4.67 KB
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
local f = {}
function f.extract_hosts_domain(str)
-- Pattern explanation:
-- ^ - Start of string
-- [%d%.:]+ - Match 1+ digits, dots, or colons (for both IPv4 and IPv6)
-- %s+ - Match 1+ whitespace characters
-- (.*) - Capture the rest of the string (the domain)
-- $ - End of string
local domain = str:match("^[%d%.:]+%s+(.*)$")
return domain or str -- Return original string if no match
end
function f.dr_log_content(record_content)
if not record_content then
pdnslog(
"No DNS Record Content for " .. dq.qname:toString(),
pdns.loglevels.Debug
)
else
pdnslog(
"DNS Record Content: " .. record_content,
pdns.loglevels.Debug
)
end
end
function f.dq_log_record_content(dq)
local dq_records = dq:getRecords()
for _, record in ipairs(dq_records) do
local record_content = record:getContent()
f.dr_log_content(record_content)
end
end
function f.dq_ends_in_cname(dq)
local dq_records = dq:getRecords()
if not dq_records then
return false
end
local last_record = dq_records[#dq_records]
return last_record.type == pdns.CNAME
end
function f.empty_str(s)
return s == nil or s == ''
end
function f.table_contains(tab, val, has_keys)
if not tab then
return false
end
if has_keys then
for k, v in pairs(tab) do
if v == val then
return true
end
end
else
for i, v in ipairs(tab) do
if v == val then
return true
end
end
end
return false
end
function f.table_contains_key(tab, key)
if tab[key] ~= nil then return true end
return false
-- for k, v in pairs(tab) do
-- if k == key then
-- return true
-- end
-- end
-- return false
end
function f.table_len(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
function f.table_to_str(T, SEP, CALLBACK)
if not SEP then
SEP = ","
end
local s = ""
for _, v in pairs(T) do
if CALLBACK then
v = CALLBACK(v)
end
if _ == 1 then
s = tostring(v)
else
s = s .. SEP .. tostring(v)
end
end
return s
end
-- This function uses native LUA Regex, not PCRE2
function f.is_comment(v)
if not v then return false end
local p_list = {
"^%s*#", -- Matches "#" with optional leading spaces
"^%s*%-%-", -- Matches "--" with optional leading spaces
"^%s*//", -- Matches "//" with optional leading spaces
"^%s*!" -- Matches "!" with optional leading spaces
}
for _, pattern in ipairs(p_list) do
if v:match(pattern) then return true end
end
return false
end
function f.trim_hosts_comment(line)
local comment_index = line:find("#")
if comment_index then
return line:sub(1, comment_index - 1):gsub("%s+$", "")
else
return line
end
end
-- src: https://stackoverflow.com/questions/1426954/split-string-in-lua
function f.string_split(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
function f.string_starts_with(s, search)
if type(s) ~= "string" then
error("s must be of type string")
end
if not s then
return false
end
if string.sub(s, 1, #search) == search then
return true
end
return false
end
function f.string_ends_with(s, search)
if type(s) ~= "string" then
error("s must be of type string")
end
if not s then
return false
end
if s and string.sub(s, #search * -1) == search then
return true
end
return false
end
function f.qname_remove_trailing_dot(dq)
local qname
if type(dq) == "string" then
qname = dq
else
qname = dq.qname:toStringNoDot()
end
if string.sub(qname, -1) == "." then
return tostring(string.sub(qname, 1, -2))
end
return tostring(qname)
end
-- returns true if the given file exists
function f.fileExists(file)
local f = io.open(file, "rb")
if f then
f:close()
end
return f ~= nil
end
function f.isModuleAvailable(name)
if package.loaded[name] then
return true
else
for _, searcher in ipairs(package.searchers or package.loaders) do
local loader = searcher(name)
if type(loader) == 'function' then
package.preload[name] = loader
return true
end
end
return false
end
end
-- Required for load-order based execution
function f.addHookFunction(mode, f_name, hook_fn)
local t_i -- Index
local t_f -- Function
if mode == "pre" then
t_i = "preresolve_index"
t_f = "preresolve_functions"
elseif mode == "post" then
t_i = "postresolve_index"
t_f = "postresolve_functions"
elseif mode == "maintenance" then
t_i = "maintenance_index"
t_f = "maintenance_functions"
else
error("addHookFunction(): mode param must be either 'pre', 'post' or 'maintenance'")
end
if f.table_contains_key(g[t_f], f_name) then
return
end
table.insert(g[t_i], f_name)
g[t_f][f_name] = hook_fn
end
return f