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
|
local log = require "util.logger".init("modulemanager")
local loadfile, pcall = loadfile, pcall;
local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv;
local pairs, ipairs = pairs, ipairs;
local t_insert = table.insert;
local type = type;
local tostring, print = tostring, print;
local _G = _G;
module "modulemanager"
local handler_info = {};
local handlers = {};
local modulehelpers = setmetatable({}, { __index = _G });
local function _add_iq_handler(module, origin_type, xmlns, handler)
handlers[origin_type] = handlers[origin_type] or {};
handlers[origin_type].iq = handlers[origin_type].iq or {};
if not handlers[origin_type].iq[xmlns] then
handlers[origin_type].iq[xmlns]= handler;
handler_info[handler] = module;
log("debug", "mod_%s now handles tag 'iq' with query namespace '%s'", module.name, xmlns);
else
log("warning", "mod_%s wants to handle tag 'iq' with query namespace '%s' but mod_%s already handles that", module.name, xmlns, handler_info[handlers[origin_type].iq[xmlns]].module.name);
end
end
function modulehelpers.add_iq_handler(origin_type, xmlns, handler)
if not (origin_type and handler and xmlns) then return false; end
if type(origin_type) == "table" then
for _, origin_type in ipairs(origin_type) do
_add_iq_handler(getfenv(2).module, origin_type, xmlns, handler);
end
return;
end
_add_iq_handler(getfenv(2).module, origin_type, xmlns, handler);
end
local function _add_handler(module, origin_type, tag, xmlns, handler)
handlers[origin_type] = handlers[origin_type] or {};
if not handlers[origin_type][tag] then
handlers[origin_type][tag] = handlers[origin_type][tag] or {};
handlers[origin_type][tag][xmlns]= handler;
handler_info[handler] = module;
log("debug", "mod_%s now handles tag '%s'", module.name, tag);
elseif handler_info[handlers[origin_type][tag]] then
log("warning", "mod_%s wants to handle tag '%s' but mod_%s already handles that", module.name, tag, handler_info[handlers[origin_type][tag]].module.name);
end
end
function modulehelpers.add_handler(origin_type, tag, xmlns, handler)
if not (origin_type and tag and xmlns and handler) then return false; end
if type(origin_type) == "table" then
for _, origin_type in ipairs(origin_type) do
_add_handler(getfenv(2).module, origin_type, tag, xmlns, handler);
end
return;
end
_add_handler(getfenv(2).module, origin_type, tag, xmlns, handler);
end
function load(name)
local mod, err = loadfile("plugins/mod_"..name..".lua");
if not mod then
log("error", "Unable to load module '%s': %s", name or "nil", err or "nil");
return nil, err;
end
local pluginenv = setmetatable({ module = { name = name } }, { __index = modulehelpers });
setfenv(mod, pluginenv);
local success, ret = pcall(mod);
if not success then
log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil");
return nil, err;
end
return true;
end
function handle_stanza(origin, stanza)
local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type;
if name == "iq" and xmlns == "jabber:client" and handlers[origin_type] then
log("debug", "Stanza is an <iq/>");
local child = stanza.tags[1];
if child then
local xmlns = child.attr.xmlns;
log("debug", "Stanza has xmlns: %s", xmlns);
local handler = handlers[origin_type][name][xmlns];
if handler then
log("debug", "Passing stanza to mod_%s", handler_info[handler].name);
return handler(origin, stanza) or true;
end
end
elseif handlers[origin_type] then
local handler = handlers[origin_type][name];
if handler then
handler = handler[xmlns];
if handler then
log("debug", "Passing stanza to mod_%s", handler_info[handler].name);
return handler(origin, stanza) or true;
end
end
end
log("debug", "Stanza unhandled by any modules, xmlns: %s", stanza.attr.xmlns);
return false; -- we didn't handle it
end
do
local event_handlers = {};
function modulehelpers.add_event_hook(name, handler)
if not event_handlers[name] then
event_handlers[name] = {};
end
t_insert(event_handlers[name] , handler);
end
function fire_event(name, ...)
local event_handlers = event_handlers[name];
if event_handlers then
for name, handler in ipairs(event_handlers) do
handler(...);
end
end
end
end
return _M;
|