mod_csi_simple: Consider messages encrypted payload as important (fixes part of ...
[prosody.git] / plugins / mod_roster.lua
blob39d59cbdc7c61b4f5c774a3625de7b174be0b901
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 --
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
10 local st = require "util.stanza"
12 local jid_split = require "util.jid".split;
13 local jid_prep = require "util.jid".prep;
14 local tonumber = tonumber;
15 local pairs = pairs;
17 local rm_load_roster = require "core.rostermanager".load_roster;
18 local rm_remove_from_roster = require "core.rostermanager".remove_from_roster;
19 local rm_add_to_roster = require "core.rostermanager".add_to_roster;
20 local rm_roster_push = require "core.rostermanager".roster_push;
22 module:add_feature("jabber:iq:roster");
24 local rosterver_stream_feature = st.stanza("ver", {xmlns="urn:xmpp:features:rosterver"});
25 module:hook("stream-features", function(event)
26 local origin, features = event.origin, event.features;
27 if origin.username then
28 features:add_child(rosterver_stream_feature);
29 end
30 end);
32 module:hook("iq/self/jabber:iq:roster:query", function(event)
33 local session, stanza = event.origin, event.stanza;
35 if stanza.attr.type == "get" then
36 local roster = st.reply(stanza);
38 local client_ver = tonumber(stanza.tags[1].attr.ver);
39 local server_ver = tonumber(session.roster[false].version or 1);
41 if not (client_ver and server_ver) or client_ver ~= server_ver then
42 roster:query("jabber:iq:roster");
43 -- Client does not support versioning, or has stale roster
44 for jid, item in pairs(session.roster) do
45 if jid then
46 roster:tag("item", {
47 jid = jid,
48 subscription = item.subscription,
49 ask = item.ask,
50 name = item.name,
51 });
52 for group in pairs(item.groups) do
53 roster:text_tag("group", group);
54 end
55 roster:up(); -- move out from item
56 end
57 end
58 roster.tags[1].attr.ver = server_ver;
59 end
60 session.send(roster);
61 session.interested = true; -- resource is interested in roster updates
62 else -- stanza.attr.type == "set"
63 local query = stanza.tags[1];
64 if #query.tags == 1 and query.tags[1].name == "item"
65 and query.tags[1].attr.xmlns == "jabber:iq:roster" and query.tags[1].attr.jid then
66 local item = query.tags[1];
67 local from_node, from_host = jid_split(stanza.attr.from);
68 local jid = jid_prep(item.attr.jid);
69 local node, host, resource = jid_split(jid);
70 if not resource and host then
71 if jid ~= from_node.."@"..from_host then
72 if item.attr.subscription == "remove" then
73 local roster = session.roster;
74 local r_item = roster[jid];
75 if r_item then
76 module:fire_event("roster-item-removed", {
77 username = node, jid = jid, item = r_item, origin = session, roster = roster,
78 });
79 local success, err_type, err_cond, err_msg = rm_remove_from_roster(session, jid);
80 if success then
81 session.send(st.reply(stanza));
82 rm_roster_push(from_node, from_host, jid);
83 else
84 session.send(st.error_reply(stanza, err_type, err_cond, err_msg));
85 end
86 else
87 session.send(st.error_reply(stanza, "modify", "item-not-found"));
88 end
89 else
90 local r_item = {name = item.attr.name, groups = {}};
91 if r_item.name == "" then r_item.name = nil; end
92 if session.roster[jid] then
93 r_item.subscription = session.roster[jid].subscription;
94 r_item.ask = session.roster[jid].ask;
95 else
96 r_item.subscription = "none";
97 end
98 for group in item:childtags("group") do
99 local text = group:get_text();
100 if text then
101 r_item.groups[text] = true;
104 local success, err_type, err_cond, err_msg = rm_add_to_roster(session, jid, r_item);
105 if success then
106 -- Ok, send success
107 session.send(st.reply(stanza));
108 -- and push change to all resources
109 rm_roster_push(from_node, from_host, jid);
110 else
111 -- Adding to roster failed
112 session.send(st.error_reply(stanza, err_type, err_cond, err_msg));
115 else
116 -- Trying to add self to roster
117 session.send(st.error_reply(stanza, "cancel", "not-allowed"));
119 else
120 -- Invalid JID added to roster
121 session.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME what's the correct error?
123 else
124 -- Roster set didn't include a single item, or its name wasn't 'item'
125 session.send(st.error_reply(stanza, "modify", "bad-request"));
128 return true;
129 end);
131 module:hook_global("user-deleted", function(event)
132 local username, host = event.username, event.host;
133 local origin = event.origin or prosody.hosts[host];
134 if host ~= module.host then return end
135 local roster = rm_load_roster(username, host);
136 for jid, item in pairs(roster) do
137 if jid then
138 module:fire_event("roster-item-removed", {
139 username = username, jid = jid, item = item, roster = roster, origin = origin,
141 else
142 for pending_jid in pairs(item.pending) do
143 module:fire_event("roster-item-removed", {
144 username = username, jid = pending_jid, roster = roster, origin = origin,
149 end, 300);