Software /
code /
prosody-modules
Comparison
mod_remote_roster/mod_remote_roster.lua @ 314:df212e1fa576
mod_remote_roster: Initial commit. Implements 2.2, 2.3 of <http://jkaluza.fedorapeople.org/remote-roster.html>.
author | Waqas Hussain <waqas20@gmail.com> |
---|---|
date | Mon, 10 Jan 2011 16:35:43 +0500 |
child | 315:dead242beee3 |
comparison
equal
deleted
inserted
replaced
313:524f22ef2c2b | 314:df212e1fa576 |
---|---|
1 -- | |
2 -- mod_remote_roster | |
3 -- | |
4 -- This is an experimental implementation of http://jkaluza.fedorapeople.org/remote-roster.html | |
5 -- | |
6 | |
7 local st = require "util.stanza"; | |
8 local jid_split = require "util.jid".split; | |
9 local jid_prep = require "util.jid".prep; | |
10 local t_concat = table.concat; | |
11 local tonumber = tonumber; | |
12 local pairs, ipairs = pairs, ipairs; | |
13 local hosts = hosts; | |
14 | |
15 local load_roster = require "core.rostermanager".load_roster; | |
16 local rm_remove_from_roster = require "core.rostermanager".remove_from_roster; | |
17 local rm_add_to_roster = require "core.rostermanager".add_to_roster; | |
18 local rm_roster_push = require "core.rostermanager".roster_push; | |
19 local core_post_stanza = core_post_stanza; | |
20 local user_exists = require "core.usermanager".user_exists; | |
21 local add_task = require "util.timer".add_task; | |
22 | |
23 module:hook("iq-get/bare/jabber:iq:roster:query", function(event) | |
24 local origin, stanza = event.origin, event.stanza; | |
25 | |
26 if origin.type == "component" and stanza.attr.from == origin.host then | |
27 local node, host = jid_split(stanza.attr.to); | |
28 local roster = load_roster(node, host); | |
29 | |
30 local reply = st.reply(stanza):query("jabber:iq:roster"); | |
31 for jid, item in pairs(roster) do | |
32 if jid ~= "pending" and jid then | |
33 local node, host = jid_split(jid); | |
34 if host == origin.host then -- only include contacts which are on this component | |
35 reply:tag("item", { | |
36 jid = jid, | |
37 subscription = item.subscription, | |
38 ask = item.ask, | |
39 name = item.name, | |
40 }); | |
41 for group in pairs(item.groups) do | |
42 reply:tag("group"):text(group):up(); | |
43 end | |
44 reply:up(); -- move out from item | |
45 end | |
46 end | |
47 end | |
48 origin.send(reply); | |
49 --origin.interested = true; -- resource is interested in roster updates | |
50 return true; | |
51 end | |
52 end); | |
53 | |
54 module:hook("iq-set/bare/jabber:iq:roster:query", function(event) | |
55 local session, stanza = event.origin, event.stanza; | |
56 | |
57 if not(session.type == "component" and stanza.attr.from == session.host) then return; end | |
58 local from_node, from_host = jid_split(stanza.attr.to); | |
59 if not(user_exists(from_node, from_host)) then return; end | |
60 local roster = load_roster(from_node, from_host); | |
61 if not(roster) then return; end | |
62 | |
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 | |
66 -- Protection against overwriting roster.pending, until we move it | |
67 and query.tags[1].attr.jid ~= "pending" then | |
68 local item = query.tags[1]; | |
69 local jid = jid_prep(item.attr.jid); | |
70 local node, host, resource = jid_split(jid); | |
71 if not resource and host then | |
72 if jid ~= stanza.attr.to then | |
73 if item.attr.subscription == "remove" then | |
74 local r_item = roster[jid]; | |
75 if r_item then | |
76 local to_bare = node and (node.."@"..host) or host; -- bare JID | |
77 if r_item.subscription == "both" or r_item.subscription == "from" or (roster.pending and roster.pending[jid]) then | |
78 core_post_stanza(session, st.presence({type="unsubscribed", from=session.full_jid, to=to_bare})); | |
79 end | |
80 if r_item.subscription == "both" or r_item.subscription == "to" or r_item.ask then | |
81 core_post_stanza(session, st.presence({type="unsubscribe", from=session.full_jid, to=to_bare})); | |
82 end | |
83 local success, err_type, err_cond, err_msg = rm_remove_from_roster(session, jid); | |
84 if success then | |
85 session.send(st.reply(stanza)); | |
86 rm_roster_push(from_node, from_host, jid); | |
87 else | |
88 session.send(st.error_reply(stanza, err_type, err_cond, err_msg)); | |
89 end | |
90 else | |
91 session.send(st.error_reply(stanza, "modify", "item-not-found")); | |
92 end | |
93 else | |
94 local r_item = {name = item.attr.name, groups = {}}; | |
95 if r_item.name == "" then r_item.name = nil; end | |
96 if session.roster[jid] then | |
97 r_item.subscription = session.roster[jid].subscription; | |
98 r_item.ask = session.roster[jid].ask; | |
99 else | |
100 r_item.subscription = "none"; | |
101 end | |
102 for _, child in ipairs(item) do | |
103 if child.name == "group" then | |
104 local text = t_concat(child); | |
105 if text and text ~= "" then | |
106 r_item.groups[text] = true; | |
107 end | |
108 end | |
109 end | |
110 local success, err_type, err_cond, err_msg = rm_add_to_roster(session, jid, r_item); | |
111 if success then -- Ok, send success | |
112 session.send(st.reply(stanza)); | |
113 -- and push change to all resources | |
114 rm_roster_push(from_node, from_host, jid); | |
115 else -- Adding to roster failed | |
116 session.send(st.error_reply(stanza, err_type, err_cond, err_msg)); | |
117 end | |
118 end | |
119 else -- Trying to add self to roster | |
120 session.send(st.error_reply(stanza, "cancel", "not-allowed")); | |
121 end | |
122 else -- Invalid JID added to roster | |
123 session.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME what's the correct error? | |
124 end | |
125 else -- Roster set didn't include a single item, or its name wasn't 'item' | |
126 session.send(st.error_reply(stanza, "modify", "bad-request")); | |
127 end | |
128 return true; | |
129 end); | |
130 | |
131 function component_roster_push(node, host, jid) | |
132 local roster = load_roster(node, host); | |
133 if roster then | |
134 local item = roster[jid]; | |
135 local contact_node, contact_host = jid_split(jid); | |
136 local stanza = st.iq({ type="set", from=node.."@"..host, to=contact_host }):query("jabber:iq:roster"); | |
137 if item then | |
138 stanza:tag("item", { jid = jid, subscription = item.subscription, name = item.name, ask = item.ask }); | |
139 for group in pairs(item.groups) do | |
140 stanza:tag("group"):text(group):up(); | |
141 end | |
142 else | |
143 stanza:tag("item", {jid = jid, subscription = "remove"}); | |
144 end | |
145 stanza:up(); -- move out from item | |
146 stanza:up(); -- move out from stanza | |
147 core_post_stanza(hosts[module.host], stanza); | |
148 end | |
149 end | |
150 | |
151 module:hook("iq-set/bare/jabber:iq:roster:query", function(event) | |
152 local origin, stanza = event.origin, event.stanza; | |
153 local query = stanza.tags[1]; | |
154 local item = query.tags[1]; | |
155 local contact_jid = item and item.name == "item" and item.attr.jid ~= "pending" and item.attr.jid; | |
156 if contact_jid then | |
157 local contact_node, contact_host = jid_split(contact_jid); | |
158 if hosts[contact_host] and hosts[contact_host].type == "component" then | |
159 local node, host = jid_split(stanza.attr.to or origin.full_jid); | |
160 add_task(0, function() | |
161 component_roster_push(node, host, contact_jid); | |
162 end); | |
163 end | |
164 end | |
165 end, 100); |