28 if origin.username then |
27 if origin.username then |
29 features:add_child(rosterver_stream_feature); |
28 features:add_child(rosterver_stream_feature); |
30 end |
29 end |
31 end); |
30 end); |
32 |
31 |
33 module:add_iq_handler("c2s", "jabber:iq:roster", |
32 module:hook("iq/self/jabber:iq:roster:query", function(event) |
34 function (session, stanza) |
33 local session, stanza = event.origin, event.stanza; |
35 if stanza.tags[1].name == "query" then |
34 |
36 if stanza.attr.type == "get" then |
35 if stanza.attr.type == "get" then |
37 local roster = st.reply(stanza); |
36 local roster = st.reply(stanza); |
38 |
37 |
39 local client_ver = tonumber(stanza.tags[1].attr.ver); |
38 local client_ver = tonumber(stanza.tags[1].attr.ver); |
40 local server_ver = tonumber(session.roster[false].version or 1); |
39 local server_ver = tonumber(session.roster[false].version or 1); |
41 |
40 |
42 if not (client_ver and server_ver) or client_ver ~= server_ver then |
41 if not (client_ver and server_ver) or client_ver ~= server_ver then |
43 roster:query("jabber:iq:roster"); |
42 roster:query("jabber:iq:roster"); |
44 -- Client does not support versioning, or has stale roster |
43 -- Client does not support versioning, or has stale roster |
45 for jid, item in pairs(session.roster) do |
44 for jid, item in pairs(session.roster) do |
46 if jid ~= "pending" and jid then |
45 if jid ~= "pending" and jid then |
47 roster:tag("item", { |
46 roster:tag("item", { |
48 jid = jid, |
47 jid = jid, |
49 subscription = item.subscription, |
48 subscription = item.subscription, |
50 ask = item.ask, |
49 ask = item.ask, |
51 name = item.name, |
50 name = item.name, |
52 }); |
51 }); |
53 for group in pairs(item.groups) do |
52 for group in pairs(item.groups) do |
54 roster:tag("group"):text(group):up(); |
53 roster:tag("group"):text(group):up(); |
|
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 |
|
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 from_node, from_host = jid_split(stanza.attr.from); |
|
70 local from_bare = from_node and (from_node.."@"..from_host) or from_host; -- bare JID |
|
71 local jid = jid_prep(item.attr.jid); |
|
72 local node, host, resource = jid_split(jid); |
|
73 if not resource and host then |
|
74 if jid ~= from_node.."@"..from_host then |
|
75 if item.attr.subscription == "remove" then |
|
76 local roster = session.roster; |
|
77 local r_item = roster[jid]; |
|
78 if r_item then |
|
79 local to_bare = node and (node.."@"..host) or host; -- bare JID |
|
80 if r_item.subscription == "both" or r_item.subscription == "from" or (roster.pending and roster.pending[jid]) then |
|
81 core_post_stanza(session, st.presence({type="unsubscribed", from=session.full_jid, to=to_bare})); |
|
82 end |
|
83 if r_item.subscription == "both" or r_item.subscription == "to" or r_item.ask then |
|
84 core_post_stanza(session, st.presence({type="unsubscribe", from=session.full_jid, to=to_bare})); |
|
85 end |
|
86 local success, err_type, err_cond, err_msg = rm_remove_from_roster(session, jid); |
|
87 if success then |
|
88 session.send(st.reply(stanza)); |
|
89 rm_roster_push(from_node, from_host, jid); |
|
90 else |
|
91 session.send(st.error_reply(stanza, err_type, err_cond, err_msg)); |
|
92 end |
|
93 else |
|
94 session.send(st.error_reply(stanza, "modify", "item-not-found")); |
|
95 end |
|
96 else |
|
97 local r_item = {name = item.attr.name, groups = {}}; |
|
98 if r_item.name == "" then r_item.name = nil; end |
|
99 if session.roster[jid] then |
|
100 r_item.subscription = session.roster[jid].subscription; |
|
101 r_item.ask = session.roster[jid].ask; |
|
102 else |
|
103 r_item.subscription = "none"; |
|
104 end |
|
105 for _, child in ipairs(item) do |
|
106 if child.name == "group" then |
|
107 local text = t_concat(child); |
|
108 if text and text ~= "" then |
|
109 r_item.groups[text] = true; |
55 end |
110 end |
56 roster:up(); -- move out from item |
|
57 end |
111 end |
58 end |
112 end |
59 roster.tags[1].attr.ver = server_ver; |
113 local success, err_type, err_cond, err_msg = rm_add_to_roster(session, jid, r_item); |
|
114 if success then |
|
115 -- Ok, send success |
|
116 session.send(st.reply(stanza)); |
|
117 -- and push change to all resources |
|
118 rm_roster_push(from_node, from_host, jid); |
|
119 else |
|
120 -- Adding to roster failed |
|
121 session.send(st.error_reply(stanza, err_type, err_cond, err_msg)); |
|
122 end |
60 end |
123 end |
61 session.send(roster); |
124 else |
62 session.interested = true; -- resource is interested in roster updates |
125 -- Trying to add self to roster |
63 return true; |
126 session.send(st.error_reply(stanza, "cancel", "not-allowed")); |
64 elseif stanza.attr.type == "set" then |
|
65 local query = stanza.tags[1]; |
|
66 if #query.tags == 1 and query.tags[1].name == "item" |
|
67 and query.tags[1].attr.xmlns == "jabber:iq:roster" and query.tags[1].attr.jid |
|
68 -- Protection against overwriting roster.pending, until we move it |
|
69 and query.tags[1].attr.jid ~= "pending" then |
|
70 local item = query.tags[1]; |
|
71 local from_node, from_host = jid_split(stanza.attr.from); |
|
72 local from_bare = from_node and (from_node.."@"..from_host) or from_host; -- bare JID |
|
73 local jid = jid_prep(item.attr.jid); |
|
74 local node, host, resource = jid_split(jid); |
|
75 if not resource and host then |
|
76 if jid ~= from_node.."@"..from_host then |
|
77 if item.attr.subscription == "remove" then |
|
78 local roster = session.roster; |
|
79 local r_item = roster[jid]; |
|
80 if r_item then |
|
81 local to_bare = node and (node.."@"..host) or host; -- bare JID |
|
82 if r_item.subscription == "both" or r_item.subscription == "from" or (roster.pending and roster.pending[jid]) then |
|
83 core_post_stanza(session, st.presence({type="unsubscribed", from=session.full_jid, to=to_bare})); |
|
84 end |
|
85 if r_item.subscription == "both" or r_item.subscription == "to" or r_item.ask then |
|
86 core_post_stanza(session, st.presence({type="unsubscribe", from=session.full_jid, to=to_bare})); |
|
87 end |
|
88 local success, err_type, err_cond, err_msg = rm_remove_from_roster(session, jid); |
|
89 if success then |
|
90 session.send(st.reply(stanza)); |
|
91 rm_roster_push(from_node, from_host, jid); |
|
92 else |
|
93 session.send(st.error_reply(stanza, err_type, err_cond, err_msg)); |
|
94 end |
|
95 else |
|
96 session.send(st.error_reply(stanza, "modify", "item-not-found")); |
|
97 end |
|
98 else |
|
99 local r_item = {name = item.attr.name, groups = {}}; |
|
100 if r_item.name == "" then r_item.name = nil; end |
|
101 if session.roster[jid] then |
|
102 r_item.subscription = session.roster[jid].subscription; |
|
103 r_item.ask = session.roster[jid].ask; |
|
104 else |
|
105 r_item.subscription = "none"; |
|
106 end |
|
107 for _, child in ipairs(item) do |
|
108 if child.name == "group" then |
|
109 local text = t_concat(child); |
|
110 if text and text ~= "" then |
|
111 r_item.groups[text] = true; |
|
112 end |
|
113 end |
|
114 end |
|
115 local success, err_type, err_cond, err_msg = rm_add_to_roster(session, jid, r_item); |
|
116 if success then |
|
117 -- Ok, send success |
|
118 session.send(st.reply(stanza)); |
|
119 -- and push change to all resources |
|
120 rm_roster_push(from_node, from_host, jid); |
|
121 else |
|
122 -- Adding to roster failed |
|
123 session.send(st.error_reply(stanza, err_type, err_cond, err_msg)); |
|
124 end |
|
125 end |
|
126 else |
|
127 -- Trying to add self to roster |
|
128 session.send(st.error_reply(stanza, "cancel", "not-allowed")); |
|
129 end |
|
130 else |
|
131 -- Invalid JID added to roster |
|
132 session.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME what's the correct error? |
|
133 end |
|
134 else |
|
135 -- Roster set didn't include a single item, or its name wasn't 'item' |
|
136 session.send(st.error_reply(stanza, "modify", "bad-request")); |
|
137 end |
|
138 return true; |
|
139 end |
127 end |
|
128 else |
|
129 -- Invalid JID added to roster |
|
130 session.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME what's the correct error? |
140 end |
131 end |
141 end); |
132 else |
|
133 -- Roster set didn't include a single item, or its name wasn't 'item' |
|
134 session.send(st.error_reply(stanza, "modify", "bad-request")); |
|
135 end |
|
136 end |
|
137 return true; |
|
138 end); |