X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=core%2Fconfigmanager.lua;h=03679531b1b20b8a3847ec27c4ed6d962a281ed6;hb=4e2a8775d379a6a94bb976e1e505b214de483807;hp=87c78aeed3bb07c85cc883e3f60d7c1e4b9edecf;hpb=61763ab48fd7eae9bfba8c2243baee1caddc941a;p=prosody.git diff --git a/core/configmanager.lua b/core/configmanager.lua index 87c78aee..03679531 100644 --- a/core/configmanager.lua +++ b/core/configmanager.lua @@ -6,8 +6,6 @@ -- COPYING file in the source package for more information. -- - - local _G = _G; local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, format = setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, string.format; @@ -15,22 +13,22 @@ local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, p local fire_event = prosody and prosody.events.fire_event or function () end; +local path_sep = package.config:sub(1,1); + module "configmanager" local parsers = {}; -local config = { ["*"] = { core = {} } }; - -local global_config = config["*"]; +local config_mt = { __index = function (t, k) return rawget(t, "*"); end}; +local config = setmetatable({ ["*"] = { core = {} } }, config_mt); -- When host not found, use global -setmetatable(config, { __index = function () return global_config; end}); -local host_mt = { __index = global_config }; +local host_mt = { }; -- When key not found in section, check key in global's section function section_mt(section_name) return { __index = function (t, k) - local section = rawget(global_config, section_name); + local section = rawget(config["*"], section_name); if not section then return nil; end return section[k]; end @@ -49,7 +47,7 @@ function get(host, section, key) return nil; end -function set(host, section, key, value) +local function set(config, host, section, key, value) if host and section and key then local hostconfig = rawget(config, host); if not hostconfig then @@ -64,18 +62,47 @@ function set(host, section, key, value) return false; end +function _M.set(host, section, key, value) + return set(config, host, section, key, value); +end + +-- Helper function to resolve relative paths (needed by config) +do + local rel_path_start = ".."..path_sep; + function resolve_relative_path(parent_path, path) + if path then + local is_relative; + if path_sep == "/" and path:sub(1,1) ~= "/" then + is_relative = true; + elseif path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\") then + is_relative = true; + end + if is_relative then + return parent_path..path_sep..path; + end + end + return path; + end +end + function load(filename, format) format = format or filename:match("%w+$"); if parsers[format] and parsers[format].load then local f, err = io.open(filename); if f then - local ok, err = parsers[format].load(f:read("*a"), filename); + local new_config = setmetatable({ ["*"] = { core = {} } }, config_mt); + local ok, err = parsers[format].load(f:read("*a"), filename, new_config); f:close(); if ok then - fire_event("config-reloaded", { filename = filename, format = format }); + config = new_config; + fire_event("config-reloaded", { + filename = filename, + format = format, + config = config + }); end - return ok, "parser", err; + return not not new_config, "parser", err; end return f, "file", err; end @@ -110,13 +137,13 @@ do local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable; local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring; parsers.lua = {}; - function parsers.lua.load(data, filename) + function parsers.lua.load(data, filename, config) local env; -- The ' = true' are needed so as not to set off __newindex when we assign the functions below env = setmetatable({ Host = true, host = true, VirtualHost = true, Component = true, component = true, - Include = true, include = true, RunScript = dofile }, { + Include = true, include = true, RunScript = true }, { __index = function (t, k) return rawget(_G, k) or function (settings_table) @@ -124,7 +151,7 @@ do end; end, __newindex = function (t, k, v) - set(env.__currenthost or "*", "core", k, v); + set(config, env.__currenthost or "*", "core", k, v); end }); @@ -136,11 +163,11 @@ do end rawset(env, "__currenthost", name); -- Needs at least one setting to logically exist :) - set(name or "*", "core", "defined", true); + set(config, name or "*", "core", "defined", true); return function (config_options) rawset(env, "__currenthost", "*"); -- Return to global scope for option_name, option_value in pairs(config_options) do - set(name or "*", "core", option_name, option_value); + set(config, name or "*", "core", option_name, option_value); end end; end @@ -151,20 +178,20 @@ do error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s", name, name, name), 0); end - set(name, "core", "component_module", "component"); + set(config, name, "core", "component_module", "component"); -- Don't load the global modules by default - set(name, "core", "load_global_modules", false); + set(config, name, "core", "load_global_modules", false); rawset(env, "__currenthost", name); local function handle_config_options(config_options) rawset(env, "__currenthost", "*"); -- Return to global scope for option_name, option_value in pairs(config_options) do - set(name or "*", "core", option_name, option_value); + set(config, name or "*", "core", option_name, option_value); end end return function (module) if type(module) == "string" then - set(name, "core", "component_module", module); + set(config, name, "core", "component_module", module); return handle_config_options; end return handle_config_options(module); @@ -176,14 +203,19 @@ do local f, err = io.open(file); if f then local data = f:read("*a"); - local ok, err = parsers.lua.load(data, file); - if not ok then error(err:gsub("%[string.-%]", file), 0); end + local file = resolve_relative_path(filename:gsub("[^"..path_sep.."]+$", ""), file); + local ret, err = parsers.lua.load(data, file, config); + if not ret then error(err:gsub("%[string.-%]", file), 0); end end if not f then error("Error loading included "..file..": "..err, 0); end return f, err; end env.include = env.Include; + function env.RunScript(file) + return dofile(resolve_relative_path(filename:gsub("[^"..path_sep.."]+$", ""), file)); + end + local chunk, err = loadstring(data, "@"..filename); if not chunk then