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
|
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- 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;
local eventmanager = require "core.eventmanager";
module "configmanager"
local parsers = {};
local config = { ["*"] = { core = {} } };
local global_config = config["*"];
-- When host not found, use global
setmetatable(config, { __index = function () return global_config; end});
local host_mt = { __index = global_config };
-- 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);
if not section then return nil; end
return section[k];
end };
end
function getconfig()
return config;
end
function get(host, section, key)
local sec = config[host][section];
if sec then
return sec[key];
end
return nil;
end
function set(host, section, key, value)
if host and section and key then
local hostconfig = rawget(config, host);
if not hostconfig then
hostconfig = rawset(config, host, setmetatable({}, host_mt))[host];
end
if not rawget(hostconfig, section) then
hostconfig[section] = setmetatable({}, section_mt(section));
end
hostconfig[section][key] = value;
return true;
end
return false;
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);
f:close();
if ok then
eventmanager.fire_event("config-reloaded", { filename = filename, format = format });
end
return ok, "parser", err;
end
return f, "file", err;
end
if not format then
return nil, "file", "no parser specified";
else
return nil, "file", "no parser for "..(format);
end
end
function save(filename, format)
end
function addparser(format, parser)
if format and parser then
parsers[format] = parser;
end
end
-- _M needed to avoid name clash with local 'parsers'
function _M.parsers()
local p = {};
for format in pairs(parsers) do
table.insert(p, format);
end
return p;
end
-- Built-in Lua parser
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)
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 }, { __index = function (t, k)
return rawget(_G, k) or
function (settings_table)
config[__currenthost or "*"][k] = settings_table;
end;
end,
__newindex = function (t, k, v)
set(env.__currenthost or "*", "core", k, v);
end});
rawset(env, "__currenthost", "*") -- Default is global
function env.VirtualHost(name)
if rawget(config, name) and rawget(config[name].core, "component_module") then
error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s",
name, config[name].core.component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0);
end
rawset(env, "__currenthost", name);
-- Needs at least one setting to logically exist :)
set(name or "*", "core", "defined", true);
end
env.Host, env.host = env.VirtualHost, env.VirtualHost;
function env.Component(name)
if rawget(config, name) and rawget(config[name].core, "defined") and not rawget(config[name].core, "component_module") then
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");
-- Don't load the global modules by default
set(name, "core", "load_global_modules", false);
rawset(env, "__currenthost", name);
return function (module)
if type(module) == "string" then
set(name, "core", "component_module", module);
end
end
end
env.component = env.Component;
function env.Include(file)
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
end
if not f then error("Error loading included "..file..": "..err, 0); end
return f, err;
end
env.include = env.Include;
local chunk, err = loadstring(data, "@"..filename);
if not chunk then
return nil, err;
end
setfenv(chunk, env);
local ok, err = pcall(chunk);
if not ok then
return nil, err;
end
return true;
end
end
return _M;
|