plugins/muc/muc.lib.lua

changeset 1989
97c3236cc4ac
parent 1862
115f274dd17f
child 1996
3e6b36c6d7b7
equal deleted inserted replaced
1988:a6e7fe0fc3dd 1989:97c3236cc4ac
104 elseif affiliation == "member" or not affiliation then 104 elseif affiliation == "member" or not affiliation then
105 return "participant"; 105 return "participant";
106 end 106 end
107 end 107 end
108 108
109 function room_mt:broadcast_presence(stanza, code, nick) 109 function room_mt:broadcast_presence(stanza, sid, code, nick)
110 stanza = get_filtered_presence(stanza); 110 stanza = get_filtered_presence(stanza);
111 local occupant = self._occupants[stanza.attr.from]; 111 local occupant = self._occupants[stanza.attr.from];
112 stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) 112 stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
113 :tag("item", {affiliation=occupant.affiliation, role=occupant.role, nick=nick}):up(); 113 :tag("item", {affiliation=occupant.affiliation, role=occupant.role, nick=nick}):up();
114 if code then 114 if code then
116 end 116 end
117 self:broadcast_except_nick(stanza, stanza.attr.from); 117 self:broadcast_except_nick(stanza, stanza.attr.from);
118 local me = self._occupants[stanza.attr.from]; 118 local me = self._occupants[stanza.attr.from];
119 if me then 119 if me then
120 stanza:tag("status", {code='110'}); 120 stanza:tag("status", {code='110'});
121 for jid in pairs(me.sessions) do 121 stanza.attr.to = sid;
122 stanza.attr.to = jid; 122 self:route_stanza(stanza);
123 self:route_stanza(stanza);
124 end
125 end 123 end
126 end 124 end
127 function room_mt:broadcast_message(stanza, historic) 125 function room_mt:broadcast_message(stanza, historic)
128 for occupant, o_data in pairs(self._occupants) do 126 for occupant, o_data in pairs(self._occupants) do
129 for jid in pairs(o_data.sessions) do 127 for jid in pairs(o_data.sessions) do
215 end 213 end
216 elseif type == "unavailable" then -- unavailable 214 elseif type == "unavailable" then -- unavailable
217 if current_nick then 215 if current_nick then
218 log("debug", "%s leaving %s", current_nick, room); 216 log("debug", "%s leaving %s", current_nick, room);
219 local occupant = self._occupants[current_nick]; 217 local occupant = self._occupants[current_nick];
220 local old_session = occupant.sessions[from];
221 local new_jid = next(occupant.sessions); 218 local new_jid = next(occupant.sessions);
222 if new_jid == from then new_jid = next(occupant.sessions, new_jid); end 219 if new_jid == from then new_jid = next(occupant.sessions, new_jid); end
223 if new_jid then 220 if new_jid then
221 local jid = occupant.jid;
224 occupant.jid = new_jid; 222 occupant.jid = new_jid;
225 occupant.sessions[from] = nil; 223 occupant.sessions[from] = nil;
226 local pr = st.clone(occupant[new_jid]) 224 pr.attr.to = from;
227 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) 225 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
228 :tag("item", {affiliation=occupant.affiliation, role=occupant.role}); 226 :tag("item", {affiliation=occupant.affiliation, role='none'}):up()
229 self:broadcast_except_nick(pr, current_nick); 227 :tag("status", {code='110'});
228 self:route_stanza(pr);
229 if jid ~= new_jid then
230 pr = st.clone(occupant.sessions[new_jid])
231 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
232 :tag("item", {affiliation=occupant.affiliation, role=occupant.role});
233 self:broadcast_except_nick(pr, current_nick);
234 end
230 else 235 else
231 occupant.role = 'none'; 236 occupant.role = 'none';
232 self:broadcast_presence(pr); 237 self:broadcast_presence(pr, from);
233 self._occupants[current_nick] = nil; 238 self._occupants[current_nick] = nil;
234 end 239 end
235 self._jid_nick[from] = nil; 240 self._jid_nick[from] = nil;
236 end 241 end
237 elseif not type then -- available 242 elseif not type then -- available
238 if current_nick then 243 if current_nick then
239 --if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence 244 --if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence
240 if current_nick == to then -- simple presence 245 if current_nick == to then -- simple presence
241 log("debug", "%s broadcasted presence", current_nick); 246 log("debug", "%s broadcasted presence", current_nick);
242 self._occupants[current_nick].sessions[from] = pr; 247 self._occupants[current_nick].sessions[from] = pr;
243 self:broadcast_presence(pr); 248 self:broadcast_presence(pr, from);
244 else -- change nick 249 else -- change nick
245 if self._occupants[to] then 250 local occupant = self._occupants[current_nick];
251 local is_multisession = next(occupant, next(occupant));
252 if self._occupants[to] or is_multisession then
246 log("debug", "%s couldn't change nick", current_nick); 253 log("debug", "%s couldn't change nick", current_nick);
247 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); 254 local reply = st.error_reply(stanza, "cancel", "conflict"):up();
248 reply.tags[1].attr.code = "409"; 255 reply.tags[1].attr.code = "409";
249 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); 256 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
250 else 257 else
251 local data = self._occupants[current_nick]; 258 local data = self._occupants[current_nick];
252 local to_nick = select(3, jid_split(to)); 259 local to_nick = select(3, jid_split(to));
253 if to_nick then 260 if to_nick then
254 log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); 261 log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to);
255 local p = st.presence({type='unavailable', from=current_nick}); 262 local p = st.presence({type='unavailable', from=current_nick});
256 self:broadcast_presence(p, '303', to_nick); 263 self:broadcast_presence(p, from, '303', to_nick);
257 self._occupants[current_nick] = nil; 264 self._occupants[current_nick] = nil;
258 self._occupants[to] = data; 265 self._occupants[to] = data;
259 self._jid_nick[from] = to; 266 self._jid_nick[from] = to;
260 pr.attr.from = to; 267 pr.attr.from = to;
261 self._occupants[to].sessions[from] = pr; 268 self._occupants[to].sessions[from] = pr;
262 self:broadcast_presence(pr); 269 self:broadcast_presence(pr, from);
263 else 270 else
264 --TODO malformed-jid 271 --TODO malformed-jid
265 end 272 end
266 end 273 end
267 end 274 end
271 -- :tag('status'):text('Replaced by new connection'):up()); -- send unavailable 278 -- :tag('status'):text('Replaced by new connection'):up()); -- send unavailable
272 -- self:handle_to_occupant(origin, stanza); -- resend available 279 -- self:handle_to_occupant(origin, stanza); -- resend available
273 --end 280 --end
274 else -- enter room 281 else -- enter room
275 local new_nick = to; 282 local new_nick = to;
283 local is_merge;
276 if self._occupants[to] then 284 if self._occupants[to] then
277 new_nick = nil; 285 if jid_bare(from) ~= jid_bare(self._occupants[to].jid) then
286 new_nick = nil;
287 end
288 is_merge = true;
278 end 289 end
279 if not new_nick then 290 if not new_nick then
280 log("debug", "%s couldn't join due to nick conflict: %s", from, to); 291 log("debug", "%s couldn't join due to nick conflict: %s", from, to);
281 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); 292 local reply = st.error_reply(stanza, "cancel", "conflict"):up();
282 reply.tags[1].attr.code = "409"; 293 reply.tags[1].attr.code = "409";
287 self._affiliations[jid_bare(from)] = "owner"; 298 self._affiliations[jid_bare(from)] = "owner";
288 end 299 end
289 local affiliation = self:get_affiliation(from); 300 local affiliation = self:get_affiliation(from);
290 local role = self:get_default_role(affiliation) 301 local role = self:get_default_role(affiliation)
291 if role then -- new occupant 302 if role then -- new occupant
292 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; 303 if not is_merge then
304 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}};
305 else
306 self._occupants[to].sessions[from] = get_filtered_presence(stanza);
307 end
293 self._jid_nick[from] = to; 308 self._jid_nick[from] = to;
294 self:send_occupant_list(from); 309 self:send_occupant_list(from);
295 pr.attr.from = to; 310 pr.attr.from = to;
296 self:broadcast_presence(pr); 311 if not is_merge then
312 self:broadcast_presence(pr, from);
313 else
314 pr.attr.to = from;
315 self:route_stanza(pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
316 :tag("item", {affiliation=affiliation, role=role}):up()
317 :tag("status", {code='110'}));
318 end
297 self:send_history(from); 319 self:send_history(from);
298 else -- banned 320 else -- banned
299 local reply = st.error_reply(stanza, "auth", "forbidden"):up(); 321 local reply = st.error_reply(stanza, "auth", "forbidden"):up();
300 reply.tags[1].attr.code = "403"; 322 reply.tags[1].attr.code = "403";
301 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); 323 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"}));

mercurial