224 function handle_to_occupant(origin, stanza) -- PM, vCards, etc |
224 function handle_to_occupant(origin, stanza) -- PM, vCards, etc |
225 local from, to = stanza.attr.from, stanza.attr.to; |
225 local from, to = stanza.attr.from, stanza.attr.to; |
226 local room = jid_bare(to); |
226 local room = jid_bare(to); |
227 local current_nick = jid_nick:get(from, room); |
227 local current_nick = jid_nick:get(from, room); |
228 local type = stanza.attr.type; |
228 local type = stanza.attr.type; |
|
229 log("debug", "room: %s, current_nick: %s, stanza: %s", room, current_nick, stanza:top_tag()); |
229 if stanza.name == "presence" then |
230 if stanza.name == "presence" then |
230 local pr = get_filtered_presence(stanza); |
231 local pr = get_filtered_presence(stanza); |
231 pr.attr.from = to; |
232 pr.attr.from = to; |
232 if type == "error" then -- error, kick em out! |
233 if type == "error" then -- error, kick em out! |
233 if current_nick then |
234 if current_nick then |
|
235 log("debug", "kicking %s from %s", current_nick, room); |
234 local data = rooms:get(room, current_nick); |
236 local data = rooms:get(room, current_nick); |
235 data.role = 'none'; |
237 data.role = 'none'; |
236 local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error presence'):up() |
238 local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error presence'):up() |
237 --:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
239 --:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
238 --:tag("item", {affiliation=data.affiliation, role=data.role}):up(); |
240 --:tag("item", {affiliation=data.affiliation, role=data.role}):up(); |
241 rooms:remove(room, current_nick); |
243 rooms:remove(room, current_nick); |
242 jid_nick:remove(from, room); |
244 jid_nick:remove(from, room); |
243 end |
245 end |
244 elseif type == "unavailable" then -- unavailable |
246 elseif type == "unavailable" then -- unavailable |
245 if current_nick then |
247 if current_nick then |
|
248 log("debug", "%s leaving %s", current_nick, room); |
246 local data = rooms:get(room, current_nick); |
249 local data = rooms:get(room, current_nick); |
247 data.role = 'none'; |
250 data.role = 'none'; |
248 broadcast_presence_stanza(room, pr); |
251 broadcast_presence_stanza(room, pr); |
249 --broadcast_presence('unavailable', current_nick, room); |
252 --broadcast_presence('unavailable', current_nick, room); |
250 rooms:remove(room, current_nick); |
253 rooms:remove(room, current_nick); |
252 end |
255 end |
253 elseif not type then -- available |
256 elseif not type then -- available |
254 if current_nick then |
257 if current_nick then |
255 if current_nick == to then -- simple presence |
258 if current_nick == to then -- simple presence |
256 if #pr == #stanza then |
259 if #pr == #stanza then |
|
260 log("debug", "%s broadcasted presence", current_nick); |
257 broadcast_presence_stanza(room, pr); |
261 broadcast_presence_stanza(room, pr); |
258 else -- possible rejoin |
262 else -- possible rejoin |
|
263 log("debug", "%s had connection replaced", current_nick); |
259 local pr_ = st.presence({type='unavailable', from=from, to=current_nick}):tag('status'):text('Replaced by new connection'); |
264 local pr_ = st.presence({type='unavailable', from=from, to=current_nick}):tag('status'):text('Replaced by new connection'); |
260 handle_to_occupant(origin, pr_); -- send unavailable |
265 handle_to_occupant(origin, pr_); -- send unavailable |
261 handle_to_occupant(origin, pr); -- resend available |
266 handle_to_occupant(origin, pr); -- resend available |
262 end |
267 end |
263 else -- change nick |
268 else -- change nick |
264 if rooms:get(room, to) then |
269 if rooms:get(room, to) then |
|
270 log("debug", "%s couldn't change nick", current_nick); |
265 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
271 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
266 else |
272 else |
267 local data = rooms:get(room, current_nick); |
273 local data = rooms:get(room, current_nick); |
268 local to_nick = select(3, jid_split(to)); |
274 local to_nick = select(3, jid_split(to)); |
269 if to_nick then |
275 if to_nick then |
|
276 log("debug", "%s changing nick to %s", current_nick, to_nick); |
270 local p = st.presence({type='unavailable', from=current_nick}); |
277 local p = st.presence({type='unavailable', from=current_nick}); |
271 --[[:tag('x', {xmlns='http://jabber.org/protocol/muc#user'}) |
278 --[[:tag('x', {xmlns='http://jabber.org/protocol/muc#user'}) |
272 :tag('item', {affiliation=data.affiliation, role=data.role, nick=to_nick}):up() |
279 :tag('item', {affiliation=data.affiliation, role=data.role, nick=to_nick}):up() |
273 :tag('status', {code='303'});]] |
280 :tag('status', {code='303'});]] |
274 broadcast_presence_stanza(room, p, '303', to_nick); |
281 broadcast_presence_stanza(room, p, '303', to_nick); |
287 local new_nick = to; |
294 local new_nick = to; |
288 if rooms:get(room, to) then |
295 if rooms:get(room, to) then |
289 new_nick = nil; |
296 new_nick = nil; |
290 end |
297 end |
291 if not new_nick then |
298 if not new_nick then |
|
299 log("debug", "%s couldn't join due to nick conflict: %s", from, to); |
292 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
300 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
293 else |
301 else |
|
302 log("debug", "%s joining as %s", from, to); |
294 local data; |
303 local data; |
295 if not rooms:get(room) and not rooms_info:get(room) then -- new room |
304 if not rooms:get(room) and not rooms_info:get(room) then -- new room |
296 data = {affiliation='owner', role='moderator', jid=from, sessions={[from]=get_filtered_presence(stanza)}}; |
305 data = {affiliation='owner', role='moderator', jid=from, sessions={[from]=get_filtered_presence(stanza)}}; |
297 end |
306 end |
298 if not data then -- new occupant |
307 if not data then -- new occupant |
336 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); |
345 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); |
337 elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM |
346 elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM |
338 origin.send(st.error_reply(stanza, "modify", "bad-request")); |
347 origin.send(st.error_reply(stanza, "modify", "bad-request")); |
339 elseif stanza.name == "message" and type == "error" then |
348 elseif stanza.name == "message" and type == "error" then |
340 if current_nick then |
349 if current_nick then |
|
350 log("debug", "%s kicked from %s for sending an error message", current_nick, room); |
341 local data = rooms:get(room, to); |
351 local data = rooms:get(room, to); |
342 data.role = 'none'; |
352 data.role = 'none'; |
343 local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant'):up() |
353 local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant'):up() |
344 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
354 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
345 :tag("item", {affiliation=data.affiliation, role=data.role}):up(); |
355 :tag("item", {affiliation=data.affiliation, role=data.role}):up(); |
348 jid_nick:remove(from, room); |
358 jid_nick:remove(from, room); |
349 end |
359 end |
350 else -- private stanza |
360 else -- private stanza |
351 local o_data = rooms:get(room, to); |
361 local o_data = rooms:get(room, to); |
352 if o_data then |
362 if o_data then |
|
363 log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid); |
353 local jid = o_data.jid; |
364 local jid = o_data.jid; |
354 if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then jid = jid_bare(jid); end |
365 if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then jid = jid_bare(jid); end |
355 stanza.attr.to, stanza.attr.from = jid, current_nick; |
366 stanza.attr.to, stanza.attr.from = jid, current_nick; |
356 core_route_stanza(component, stanza); |
367 core_route_stanza(component, stanza); |
357 else -- recipient not in room |
368 else -- recipient not in room |