5 -- This project is MIT/X11 licensed. Please see the |
5 -- This project is MIT/X11 licensed. Please see the |
6 -- COPYING file in the source package for more information. |
6 -- COPYING file in the source package for more information. |
7 -- |
7 -- |
8 |
8 |
9 local _G = _G; |
9 local _G = _G; |
10 local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, format = |
10 local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table = |
11 setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, string.format; |
11 setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table; |
12 |
12 local format, math_max = string.format, math.max; |
13 |
13 |
14 local fire_event = prosody and prosody.events.fire_event or function () end; |
14 local fire_event = prosody and prosody.events.fire_event or function () end; |
15 |
15 |
|
16 local lfs = require "lfs"; |
16 local path_sep = package.config:sub(1,1); |
17 local path_sep = package.config:sub(1,1); |
17 |
18 |
18 module "configmanager" |
19 module "configmanager" |
19 |
20 |
20 local parsers = {}; |
21 local parsers = {}; |
69 -- Helper function to resolve relative paths (needed by config) |
70 -- Helper function to resolve relative paths (needed by config) |
70 do |
71 do |
71 local rel_path_start = ".."..path_sep; |
72 local rel_path_start = ".."..path_sep; |
72 function resolve_relative_path(parent_path, path) |
73 function resolve_relative_path(parent_path, path) |
73 if path then |
74 if path then |
|
75 -- Some normalization |
|
76 parent_path = parent_path:gsub("%"..path_sep.."+$", ""); |
|
77 path = path:gsub("^%.%"..path_sep.."+", ""); |
|
78 |
74 local is_relative; |
79 local is_relative; |
75 if path_sep == "/" and path:sub(1,1) ~= "/" then |
80 if path_sep == "/" and path:sub(1,1) ~= "/" then |
76 is_relative = true; |
81 is_relative = true; |
77 elseif path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\") then |
82 elseif path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\") then |
78 is_relative = true; |
83 is_relative = true; |
81 return parent_path..path_sep..path; |
86 return parent_path..path_sep..path; |
82 end |
87 end |
83 end |
88 end |
84 return path; |
89 return path; |
85 end |
90 end |
|
91 end |
|
92 |
|
93 -- Helper function to convert a glob to a Lua pattern |
|
94 local function glob_to_pattern(glob) |
|
95 return "^"..glob:gsub("[%p*?]", function (c) |
|
96 if c == "*" then |
|
97 return ".*"; |
|
98 elseif c == "?" then |
|
99 return "."; |
|
100 else |
|
101 return "%"..c; |
|
102 end |
|
103 end).."$"; |
86 end |
104 end |
87 |
105 |
88 function load(filename, format) |
106 function load(filename, format) |
89 format = format or filename:match("%w+$"); |
107 format = format or filename:match("%w+$"); |
90 |
108 |
135 -- Built-in Lua parser |
153 -- Built-in Lua parser |
136 do |
154 do |
137 local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable; |
155 local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable; |
138 local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring; |
156 local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring; |
139 parsers.lua = {}; |
157 parsers.lua = {}; |
140 function parsers.lua.load(data, filename, config) |
158 function parsers.lua.load(data, config_file, config) |
141 local env; |
159 local env; |
142 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below |
160 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below |
143 env = setmetatable({ |
161 env = setmetatable({ |
144 Host = true, host = true, VirtualHost = true, |
162 Host = true, host = true, VirtualHost = true, |
145 Component = true, component = true, |
163 Component = true, component = true, |
197 return handle_config_options(module); |
215 return handle_config_options(module); |
198 end |
216 end |
199 end |
217 end |
200 env.component = env.Component; |
218 env.component = env.Component; |
201 |
219 |
202 function env.Include(file) |
220 function env.Include(file, wildcard) |
203 local f, err = io.open(file); |
221 if file:match("[*?]") then |
204 if f then |
222 local path_pos, glob = file:match("()([^"..path_sep.."]+)$"); |
205 local data = f:read("*a"); |
223 local path = file:sub(1, math_max(path_pos-2,0)); |
206 local file = resolve_relative_path(filename:gsub("[^"..path_sep.."]+$", ""), file); |
224 if #path > 0 then |
207 local ret, err = parsers.lua.load(data, file, config); |
225 path = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), path); |
208 if not ret then error(err:gsub("%[string.-%]", file), 0); end |
226 else |
209 end |
227 path = "."; |
210 if not f then error("Error loading included "..file..": "..err, 0); end |
228 end |
211 return f, err; |
229 local patt = glob_to_pattern(glob); |
|
230 for f in lfs.dir(path) do |
|
231 if f:sub(1,1) ~= "." and f:match(patt) then |
|
232 env.Include(path..path_sep..f); |
|
233 end |
|
234 end |
|
235 else |
|
236 local f, err = io.open(file); |
|
237 if f then |
|
238 local data = f:read("*a"); |
|
239 local file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file); |
|
240 local ret, err = parsers.lua.load(data, file, config); |
|
241 if not ret then error(err:gsub("%[string.-%]", file), 0); end |
|
242 end |
|
243 if not f then error("Error loading included "..file..": "..err, 0); end |
|
244 return f, err; |
|
245 end |
212 end |
246 end |
213 env.include = env.Include; |
247 env.include = env.Include; |
214 |
248 |
215 function env.RunScript(file) |
249 function env.RunScript(file) |
216 return dofile(resolve_relative_path(filename:gsub("[^"..path_sep.."]+$", ""), file)); |
250 return dofile(resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file)); |
217 end |
251 end |
218 |
252 |
219 local chunk, err = loadstring(data, "@"..filename); |
253 local chunk, err = loadstring(data, "@"..config_file); |
220 |
254 |
221 if not chunk then |
255 if not chunk then |
222 return nil, err; |
256 return nil, err; |
223 end |
257 end |
224 |
258 |