Apply IDNA to ASCII on hostnames.
[prosody.git] / util / discohelper.lua
1 \r
2 local t_insert = table.insert;\r
3 local jid_split = require "util.jid".split;\r
4 local ipairs = ipairs;\r
5 local st = require "util.stanza";\r
6 \r
7 module "discohelper";\r
8 \r
9 local function addDiscoItemsHandler(self, jid, func)\r
10         if self.item_handlers[jid] then\r
11                 t_insert(self.item_handlers[jid], func);\r
12         else\r
13                 self.item_handlers[jid] = {func};\r
14         end\r
15 end\r
16 \r
17 local function addDiscoInfoHandler(self, jid, func)\r
18         if self.info_handlers[jid] then\r
19                 t_insert(self.info_handlers[jid], func);\r
20         else\r
21                 self.info_handlers[jid] = {func};\r
22         end\r
23 end\r
24 \r
25 local function handle(self, stanza)\r
26         if stanza.name == "iq" and stanza.tags[1].name == "query" then\r
27                 local query = stanza.tags[1];\r
28                 local to = stanza.attr.to;\r
29                 local from = stanza.attr.from\r
30                 local node = query.attr.node or "";\r
31                 local to_node, to_host = jid_split(to);\r
32 \r
33                 local reply = st.reply(stanza):query(query.attr.xmlns);\r
34                 local handlers;\r
35                 if query.attr.xmlns == "http://jabber.org/protocol/disco#info" then -- select handler set\r
36                         handlers = self.info_handlers;\r
37                 elseif query.attr.xmlns == "http://jabber.org/protocol/disco#items" then\r
38                         handlers = self.item_handlers;\r
39                 end\r
40                 local handler = handlers[to]; -- get the handler\r
41                 if not handler then -- if not found then use default handler\r
42                         if to_node then\r
43                                 handler = handlers["*defaultnode"];\r
44                         else\r
45                                 handler = handlers["*defaulthost"];\r
46                         end\r
47                 end\r
48                 local found; -- to keep track of any handlers found\r
49                 if handler then\r
50                         for _, h in ipairs(handler) do\r
51                                 if h(reply, to, from, node) then found = true; end\r
52                         end\r
53                 end\r
54                 if to_node then -- handlers which get called always\r
55                         handler = handlers["*node"];\r
56                 else\r
57                         handler = handlers["*host"];\r
58                 end\r
59                 if handler then -- call always called handler\r
60                         for _, h in ipairs(handler) do\r
61                                 if h(reply, to, from, node) then found = true; end\r
62                         end\r
63                 end\r
64                 if found then return reply; end -- return the reply if there was one\r
65                 return st.error_reply(stanza, "cancel", "service-unavailable");\r
66         end\r
67 end\r
68 \r
69 function new()\r
70         return {\r
71                 item_handlers = {};\r
72                 info_handlers = {};\r
73                 addDiscoItemsHandler = addDiscoItemsHandler;\r
74                 addDiscoInfoHandler = addDiscoInfoHandler;\r
75                 handle = handle;\r
76         };\r
77 end\r
78 \r
79 return _M;\r