Comparison

core/configmanager.lua @ 10434:8f709577fe8e

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Sat, 23 Nov 2019 23:12:01 +0100
parent 10375:3d0adbc74c39
child 12083:ec21e379c145
comparison
equal deleted inserted replaced
10433:7777f25d5266 10434:8f709577fe8e
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, rawget, rawset, io, os, error, dofile, type, pairs = 10 local setmetatable, rawget, rawset, io, os, error, dofile, type, pairs, ipairs =
11 setmetatable, rawget, rawset, io, os, error, dofile, type, pairs; 11 setmetatable, rawget, rawset, io, os, error, dofile, type, pairs, ipairs;
12 local format, math_max = string.format, math.max; 12 local format, math_max, t_insert = string.format, math.max, table.insert;
13 13
14 local envload = require"util.envload".envload; 14 local envload = require"util.envload".envload;
15 local deps = require"util.dependencies"; 15 local deps = require"util.dependencies";
16 local resolve_relative_path = require"util.paths".resolve_relative_path; 16 local resolve_relative_path = require"util.paths".resolve_relative_path;
17 local glob_to_pattern = require"util.paths".glob_to_pattern; 17 local glob_to_pattern = require"util.paths".glob_to_pattern;
18 local path_sep = package.config:sub(1,1); 18 local path_sep = package.config:sub(1,1);
19 local get_traceback_table = require "util.debug".get_traceback_table;
19 20
20 local encodings = deps.softreq"util.encodings"; 21 local encodings = deps.softreq"util.encodings";
21 local nameprep = encodings and encodings.stringprep.nameprep or function (host) return host:lower(); end 22 local nameprep = encodings and encodings.stringprep.nameprep or function (host) return host:lower(); end
22 23
23 local _M = {}; 24 local _M = {};
98 end 99 end
99 100
100 -- Built-in Lua parser 101 -- Built-in Lua parser
101 do 102 do
102 local pcall = _G.pcall; 103 local pcall = _G.pcall;
104 local function get_line_number(config_file)
105 local tb = get_traceback_table(nil, 2);
106 for i = 1, #tb do
107 if tb[i].info.short_src == config_file then
108 return tb[i].info.currentline;
109 end
110 end
111 end
103 parser = {}; 112 parser = {};
104 function parser.load(data, config_file, config_table) 113 function parser.load(data, config_file, config_table)
114 local set_options = {}; -- set_options[host.."/"..option_name] = true (when the option has been set already in this file)
115 local warnings = {};
105 local env; 116 local env;
106 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below 117 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below
107 env = setmetatable({ 118 env = setmetatable({
108 Host = true, host = true, VirtualHost = true, 119 Host = true, host = true, VirtualHost = true,
109 Component = true, component = true, 120 Component = true, component = true,
113 return os.getenv(k:sub(5)); 124 return os.getenv(k:sub(5));
114 end 125 end
115 return rawget(_G, k); 126 return rawget(_G, k);
116 end, 127 end,
117 __newindex = function (_, k, v) 128 __newindex = function (_, k, v)
129 local host = env.__currenthost or "*";
130 local option_path = host.."/"..k;
131 if set_options[option_path] then
132 t_insert(warnings, ("%s:%d: Duplicate option '%s'"):format(config_file, get_line_number(config_file), k));
133 end
134 set_options[option_path] = true;
118 set(config_table, env.__currenthost or "*", k, v); 135 set(config_table, env.__currenthost or "*", k, v);
119 end 136 end
120 }); 137 });
121 138
122 rawset(env, "__currenthost", "*") -- Default is global 139 rawset(env, "__currenthost", "*") -- Default is global
123 function env.VirtualHost(name) 140 function env.VirtualHost(name)
124 name = nameprep(name); 141 if not name then
142 error("Host must have a name", 2);
143 end
144 local prepped_name = nameprep(name);
145 if not prepped_name then
146 error(format("Name of Host %q contains forbidden characters", name), 0);
147 end
148 name = prepped_name;
125 if rawget(config_table, name) and rawget(config_table[name], "component_module") then 149 if rawget(config_table, name) and rawget(config_table[name], "component_module") then
126 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s", 150 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s",
127 name, config_table[name].component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0); 151 name, config_table[name].component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0);
128 end 152 end
129 rawset(env, "__currenthost", name); 153 rawset(env, "__currenthost", name);
137 end; 161 end;
138 end 162 end
139 env.Host, env.host = env.VirtualHost, env.VirtualHost; 163 env.Host, env.host = env.VirtualHost, env.VirtualHost;
140 164
141 function env.Component(name) 165 function env.Component(name)
142 name = nameprep(name); 166 if not name then
167 error("Component must have a name", 2);
168 end
169 local prepped_name = nameprep(name);
170 if not prepped_name then
171 error(format("Name of Component %q contains forbidden characters", name), 0);
172 end
173 name = prepped_name;
143 if rawget(config_table, name) and rawget(config_table[name], "defined") 174 if rawget(config_table, name) and rawget(config_table[name], "defined")
144 and not rawget(config_table[name], "component_module") then 175 and not rawget(config_table[name], "component_module") then
145 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s", 176 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s",
146 name, name, name), 0); 177 name, name, name), 0);
147 end 178 end
193 file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file); 224 file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file);
194 local f, err = io.open(file); 225 local f, err = io.open(file);
195 if f then 226 if f then
196 local ret, err = parser.load(f:read("*a"), file, config_table); 227 local ret, err = parser.load(f:read("*a"), file, config_table);
197 if not ret then error(err:gsub("%[string.-%]", file), 0); end 228 if not ret then error(err:gsub("%[string.-%]", file), 0); end
229 if err then
230 for _, warning in ipairs(err) do
231 t_insert(warnings, warning);
232 end
233 end
198 end 234 end
199 if not f then error("Error loading included "..file..": "..err, 0); end 235 if not f then error("Error loading included "..file..": "..err, 0); end
200 return f, err; 236 return f, err;
201 end 237 end
202 env.include = env.Include; 238 env.include = env.Include;
215 251
216 if not ok then 252 if not ok then
217 return nil, err; 253 return nil, err;
218 end 254 end
219 255
220 return true; 256 return true, warnings;
221 end 257 end
222 258
223 end 259 end
224 260
225 return _M; 261 return _M;