Bumper commit for the new modulemanager API \o/ Updates all the modules, though some...
[prosody.git] / plugins / mod_roster.lua
1
2 local st = require "util.stanza"
3
4 local jid_split = require "util.jid".split;
5 local t_concat = table.concat;
6
7 local handle_outbound_presence_subscriptions_and_probes = require "core.presencemanager".handle_outbound_presence_subscriptions_and_probes;
8 local rm_remove_from_roster = require "core.rostermanager".remove_from_roster;
9 local rm_add_to_roster = require "core.rostermanager".add_to_roster;
10 local rm_roster_push = require "core.rostermanager".roster_push;
11
12 require "core.discomanager".set("roster", "jabber:iq:roster");
13
14 module:add_iq_handler("c2s", "jabber:iq:roster", 
15                 function (session, stanza)
16                         if stanza.tags[1].name == "query" then
17                                 if stanza.attr.type == "get" then
18                                         local roster = st.reply(stanza)
19                                                                 :query("jabber:iq:roster");
20                                         for jid in pairs(session.roster) do
21                                                 if jid ~= "pending" then
22                                                         roster:tag("item", {
23                                                                 jid = jid,
24                                                                 subscription = session.roster[jid].subscription,
25                                                                 ask = session.roster[jid].ask,
26                                                                 name = session.roster[jid].name,
27                                                         });
28                                                         for group in pairs(session.roster[jid].groups) do
29                                                                 roster:tag("group"):text(group):up();
30                                                         end
31                                                         roster:up(); -- move out from item
32                                                 end
33                                         end
34                                         session.send(roster);
35                                         session.interested = true; -- resource is interested in roster updates
36                                         return true;
37                                 elseif stanza.attr.type == "set" then
38                                         local query = stanza.tags[1];
39                                         if #query.tags == 1 and query.tags[1].name == "item"
40                                                         and query.tags[1].attr.xmlns == "jabber:iq:roster" and query.tags[1].attr.jid
41                                                         and query.tags[1].attr.jid ~= "pending" then
42                                                 local item = query.tags[1];
43                                                 local from_node, from_host = jid_split(stanza.attr.from);
44                                                 local from_bare = from_node and (from_node.."@"..from_host) or from_host; -- bare JID
45                                                 local node, host, resource = jid_split(item.attr.jid);
46                                                 local to_bare = node and (node.."@"..host) or host; -- bare JID
47                                                 if not resource and host then
48                                                         if item.attr.jid ~= from_node.."@"..from_host then
49                                                                 if item.attr.subscription == "remove" then
50                                                                         local r_item = session.roster[item.attr.jid];
51                                                                         if r_item then
52                                                                                 local success, err_type, err_cond, err_msg = rm_remove_from_roster(session, item.attr.jid);
53                                                                                 if success then
54                                                                                         session.send(st.reply(stanza));
55                                                                                         rm_roster_push(from_node, from_host, item.attr.jid);
56                                                                                         if r_item.subscription == "both" or r_item.subscription == "from" then
57                                                                                                 handle_outbound_presence_subscriptions_and_probes(session,
58                                                                                                         st.presence({type="unsubscribed"}), from_bare, to_bare);
59                                                                                         elseif r_item.subscription == "both" or r_item.subscription == "to" then
60                                                                                                 handle_outbound_presence_subscriptions_and_probes(session,
61                                                                                                         st.presence({type="unsubscribe"}), from_bare, to_bare);
62                                                                                         end
63                                                                                 else
64                                                                                         session.send(st.error_reply(stanza, err_type, err_cond, err_msg));
65                                                                                 end
66                                                                         else
67                                                                                 session.send(st.error_reply(stanza, "modify", "item-not-found"));
68                                                                         end
69                                                                 else
70                                                                         local r_item = {name = item.attr.name, groups = {}};
71                                                                         if r_item.name == "" then r_item.name = nil; end
72                                                                         if session.roster[item.attr.jid] then
73                                                                                 r_item.subscription = session.roster[item.attr.jid].subscription;
74                                                                                 r_item.ask = session.roster[item.attr.jid].ask;
75                                                                         else
76                                                                                 r_item.subscription = "none";
77                                                                         end
78                                                                         for _, child in ipairs(item) do 
79                                                                                 if child.name == "group" then
80                                                                                         local text = t_concat(child);
81                                                                                         if text and text ~= "" then
82                                                                                                 r_item.groups[text] = true;
83                                                                                         end
84                                                                                 end
85                                                                         end
86                                                                         local success, err_type, err_cond, err_msg = rm_add_to_roster(session, item.attr.jid, r_item);
87                                                                         if success then
88                                                                                 session.send(st.reply(stanza));
89                                                                                 rm_roster_push(from_node, from_host, item.attr.jid);
90                                                                         else
91                                                                                 session.send(st.error_reply(stanza, err_type, err_cond, err_msg));
92                                                                         end
93                                                                 end
94                                                         else
95                                                                 session.send(st.error_reply(stanza, "cancel", "not-allowed"));
96                                                         end
97                                                 else
98                                                         session.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME what's the correct error?
99                                                 end
100                                         else
101                                                 session.send(st.error_reply(stanza, "modify", "bad-request"));
102                                         end
103                                         return true;
104                                 end
105                         end
106                 end);