(Basic) IDNA and SRV fallback support
[prosody.git] / core / configmanager.lua
1
2 local _G = _G;
3 local   setmetatable, loadfile, pcall, rawget, rawset, io = 
4                 setmetatable, loadfile, pcall, rawget, rawset, io;
5 module "configmanager"
6
7 local parsers = {};
8
9 local config = { ["*"] = { core = {} } };
10
11 local global_config = config["*"];
12
13 -- When host not found, use global
14 setmetatable(config, { __index = function () return global_config; end});
15 local host_mt = { __index = global_config };
16
17 -- When key not found in section, check key in global's section
18 function section_mt(section_name)
19         return { __index =      function (t, k)
20                                                                         local section = rawget(global_config, section_name);
21                                                                         if not section then return nil; end
22                                                                         return section[k];
23                                                         end };
24 end
25
26 function getconfig()
27         return config;
28 end
29
30 function get(host, section, key)
31         local sec = config[host][section];
32         if sec then
33                 return sec[key];
34         end
35         return nil;
36 end
37
38 function set(host, section, key, value)
39         if host and section and key then
40                 local hostconfig = rawget(config, host);
41                 if not hostconfig then
42                         hostconfig = rawset(config, host, setmetatable({}, host_mt))[host];
43                 end
44                 if not rawget(hostconfig, section) then
45                         hostconfig[section] = setmetatable({}, section_mt(section));
46                 end
47                 hostconfig[section][key] = value;
48                 return true;
49         end
50         return false;
51 end
52
53 function load(filename, format)
54         format = format or filename:match("%w+$");
55         if parsers[format] and parsers[format].load then
56                 local f = io.open(filename);
57                 if f then 
58                         local ok, err = parsers[format].load(f:read("*a"));
59                         f:close();
60                         return ok, err;
61                 end
62         end
63         if not format then
64                 return nil, "no parser specified";
65         else
66                 return false, "no parser";
67         end
68 end
69
70 function save(filename, format)
71 end
72
73 function addparser(format, parser)
74         if format and parser then
75                 parsers[format] = parser;
76         end
77 end
78
79 -- Built-in Lua parser
80 do
81         local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable;
82         local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring;
83         parsers.lua = {};
84         function parsers.lua.load(data)
85                 local env;
86                 env = setmetatable({ Host = true; host = true; }, { __index = function (t, k)
87                                                                                                 return rawget(_G, k) or
88                                                                                                                 function (settings_table)
89                                                                                                                         config[__currenthost or "*"][k] = settings_table;
90                                                                                                                 end;
91                                                                                 end,
92                                                                 __newindex = function (t, k, v)
93                                                                                         set(env.__currenthost or "*", "core", k, v);
94                                                                                 end});
95                 
96                 function env.Host(name)
97                         rawset(env, "__currenthost", name);
98                         set(name or "*", "core", "defined", true);
99                 end
100                 env.host = env.Host;
101                 
102                 local chunk, err = loadstring(data);
103                 
104                 if not chunk then
105                         return nil, err;
106                 end
107                 
108                 setfenv(chunk, env);
109                 
110                 local ok, err = pcall(chunk);
111                 
112                 if not ok then
113                         return nil, err;
114                 end
115                 
116                 return true;
117         end
118         
119 end
120
121 return _M;