122 self:broadcast_except_nick(stanza, stanza.attr.from); |
122 self:broadcast_except_nick(stanza, stanza.attr.from); |
123 local me = self._occupants[stanza.attr.from]; |
123 local me = self._occupants[stanza.attr.from]; |
124 if me then |
124 if me then |
125 stanza:tag("status", {code='110'}); |
125 stanza:tag("status", {code='110'}); |
126 stanza.attr.to = sid; |
126 stanza.attr.to = sid; |
127 self:route_stanza(stanza); |
127 self:_route_stanza(stanza); |
128 end |
128 end |
129 end |
129 end |
130 function room_mt:broadcast_message(stanza, historic) |
130 function room_mt:broadcast_message(stanza, historic) |
131 for occupant, o_data in pairs(self._occupants) do |
131 for occupant, o_data in pairs(self._occupants) do |
132 for jid in pairs(o_data.sessions) do |
132 for jid in pairs(o_data.sessions) do |
133 stanza.attr.to = jid; |
133 stanza.attr.to = jid; |
134 self:route_stanza(stanza); |
134 self:_route_stanza(stanza); |
135 end |
135 end |
136 end |
136 end |
137 if historic then -- add to history |
137 if historic then -- add to history |
138 local history = self._data['history']; |
138 local history = self._data['history']; |
139 if not history then history = {}; self._data['history'] = history; end |
139 if not history then history = {}; self._data['history'] = history; end |
147 function room_mt:broadcast_except_nick(stanza, nick) |
147 function room_mt:broadcast_except_nick(stanza, nick) |
148 for rnick, occupant in pairs(self._occupants) do |
148 for rnick, occupant in pairs(self._occupants) do |
149 if rnick ~= nick then |
149 if rnick ~= nick then |
150 for jid in pairs(occupant.sessions) do |
150 for jid in pairs(occupant.sessions) do |
151 stanza.attr.to = jid; |
151 stanza.attr.to = jid; |
152 self:route_stanza(stanza); |
152 self:_route_stanza(stanza); |
153 end |
153 end |
154 end |
154 end |
155 end |
155 end |
156 end |
156 end |
157 |
157 |
161 if occupant ~= current_nick then |
161 if occupant ~= current_nick then |
162 local pres = get_filtered_presence(o_data.sessions[o_data.jid]); |
162 local pres = get_filtered_presence(o_data.sessions[o_data.jid]); |
163 pres.attr.to, pres.attr.from = to, occupant; |
163 pres.attr.to, pres.attr.from = to, occupant; |
164 pres:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
164 pres:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
165 :tag("item", {affiliation=o_data.affiliation or "none", role=o_data.role or "none"}):up(); |
165 :tag("item", {affiliation=o_data.affiliation or "none", role=o_data.role or "none"}):up(); |
166 self:route_stanza(pres); |
166 self:_route_stanza(pres); |
167 end |
167 end |
168 end |
168 end |
169 end |
169 end |
170 function room_mt:send_history(to) |
170 function room_mt:send_history(to) |
171 local history = self._data['history']; -- send discussion history |
171 local history = self._data['history']; -- send discussion history |
172 if history then |
172 if history then |
173 for _, msg in ipairs(history) do |
173 for _, msg in ipairs(history) do |
174 msg = st.deserialize(msg); |
174 msg = st.deserialize(msg); |
175 msg.attr.to=to; |
175 msg.attr.to=to; |
176 self:route_stanza(msg); |
176 self:_route_stanza(msg); |
177 end |
177 end |
178 end |
178 end |
179 if self._data['subject'] then |
179 if self._data['subject'] then |
180 self:route_stanza(st.message({type='groupchat', from=self.jid, to=to}):tag("subject"):text(self._data['subject'])); |
180 self:_route_stanza(st.message({type='groupchat', from=self.jid, to=to}):tag("subject"):text(self._data['subject'])); |
181 end |
181 end |
182 end |
182 end |
183 |
183 |
184 local function room_get_disco_info(self, stanza) |
184 local function room_get_disco_info(self, stanza) |
185 return st.reply(stanza):query("http://jabber.org/protocol/disco#info") |
185 return st.reply(stanza):query("http://jabber.org/protocol/disco#info") |
232 occupant.sessions[from] = nil; |
232 occupant.sessions[from] = nil; |
233 pr.attr.to = from; |
233 pr.attr.to = from; |
234 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
234 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
235 :tag("item", {affiliation=occupant.affiliation or "none", role='none'}):up() |
235 :tag("item", {affiliation=occupant.affiliation or "none", role='none'}):up() |
236 :tag("status", {code='110'}); |
236 :tag("status", {code='110'}); |
237 self:route_stanza(pr); |
237 self:_route_stanza(pr); |
238 if jid ~= new_jid then |
238 if jid ~= new_jid then |
239 pr = st.clone(occupant.sessions[new_jid]) |
239 pr = st.clone(occupant.sessions[new_jid]) |
240 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
240 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
241 :tag("item", {affiliation=occupant.affiliation or "none", role=occupant.role or "none"}); |
241 :tag("item", {affiliation=occupant.affiliation or "none", role=occupant.role or "none"}); |
242 pr.attr.from = current_nick; |
242 pr.attr.from = current_nick; |
320 pr.attr.from = to; |
320 pr.attr.from = to; |
321 if not is_merge then |
321 if not is_merge then |
322 self:broadcast_presence(pr, from); |
322 self:broadcast_presence(pr, from); |
323 else |
323 else |
324 pr.attr.to = from; |
324 pr.attr.to = from; |
325 self:route_stanza(pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
325 self:_route_stanza(pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
326 :tag("item", {affiliation=affiliation or "none", role=role or "none"}):up() |
326 :tag("item", {affiliation=affiliation or "none", role=role or "none"}):up() |
327 :tag("status", {code='110'})); |
327 :tag("status", {code='110'})); |
328 end |
328 end |
329 self:send_history(from); |
329 self:send_history(from); |
330 else -- banned |
330 else -- banned |
352 break; |
352 break; |
353 end |
353 end |
354 end |
354 end |
355 if _to then |
355 if _to then |
356 stanza.attr.to, stanza.attr.from, stanza.attr.id = _to, self._jid_nick[_nick], _id; |
356 stanza.attr.to, stanza.attr.from, stanza.attr.id = _to, self._jid_nick[_nick], _id; |
357 self:route_stanza(stanza); |
357 self:_route_stanza(stanza); |
358 stanza.attr.to, stanza.attr.from, stanza.attr.id = to, from, id; |
358 stanza.attr.to, stanza.attr.from, stanza.attr.id = to, from, id; |
359 end |
359 end |
360 end |
360 end |
361 else |
361 else |
362 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); |
362 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); |
377 local id = stanza.attr.id; |
377 local id = stanza.attr.id; |
378 if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' and bare ~= jid then |
378 if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' and bare ~= jid then |
379 stanza.attr.to = bare; |
379 stanza.attr.to = bare; |
380 stanza.attr.id = base64.encode(jid.."\0"..id.."\0"..md5(from)); |
380 stanza.attr.id = base64.encode(jid.."\0"..id.."\0"..md5(from)); |
381 end |
381 end |
382 self:route_stanza(stanza); |
382 self:_route_stanza(stanza); |
383 stanza.attr.to, stanza.attr.from, stanza.attr.id = to, from, id; |
383 stanza.attr.to, stanza.attr.from, stanza.attr.id = to, from, id; |
384 elseif type ~= "error" and type ~= "result" then -- recipient not in room |
384 elseif type ~= "error" and type ~= "result" then -- recipient not in room |
385 origin.send(st.error_reply(stanza, "cancel", "item-not-found", "Recipient not in room")); |
385 origin.send(st.error_reply(stanza, "cancel", "item-not-found", "Recipient not in room")); |
386 end |
386 end |
387 end |
387 end |
563 :text(_reason or "") |
563 :text(_reason or "") |
564 :up() |
564 :up() |
565 :tag('body') -- Add a plain message for clients which don't support invites |
565 :tag('body') -- Add a plain message for clients which don't support invites |
566 :text(_from..' invited you to the room '.._to..(_reason and (' ('.._reason..')') or "")) |
566 :text(_from..' invited you to the room '.._to..(_reason and (' ('.._reason..')') or "")) |
567 :up(); |
567 :up(); |
568 self:route_stanza(invite); |
568 self:_route_stanza(invite); |
569 else |
569 else |
570 origin.send(st.error_reply(stanza, "cancel", "jid-malformed")); |
570 origin.send(st.error_reply(stanza, "cancel", "jid-malformed")); |
571 end |
571 end |
572 else |
572 else |
573 origin.send(st.error_reply(stanza, "cancel", "bad-request")); |
573 origin.send(st.error_reply(stanza, "cancel", "bad-request")); |
632 end |
632 end |
633 p.attr.from = nick; |
633 p.attr.from = nick; |
634 for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick |
634 for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick |
635 if not role then self._jid_nick[jid] = nil; end |
635 if not role then self._jid_nick[jid] = nil; end |
636 p.attr.to = jid; |
636 p.attr.to = jid; |
637 self:route_stanza(p); |
637 self:_route_stanza(p); |
638 end |
638 end |
639 end |
639 end |
640 end |
640 end |
641 if self.save then self:save(); end |
641 if self.save then self:save(); end |
642 if callback then callback(); end |
642 if callback then callback(); end |
673 else |
673 else |
674 occupant.role = role; |
674 occupant.role = role; |
675 end |
675 end |
676 for jid in pairs(occupant.sessions) do -- send to all sessions of the nick |
676 for jid in pairs(occupant.sessions) do -- send to all sessions of the nick |
677 p.attr.to = jid; |
677 p.attr.to = jid; |
678 self:route_stanza(p); |
678 self:_route_stanza(p); |
679 end |
679 end |
680 if callback then callback(); end |
680 if callback then callback(); end |
681 self:broadcast_except_nick(p, nick); |
681 self:broadcast_except_nick(p, nick); |
682 return true; |
682 return true; |
|
683 end |
|
684 |
|
685 function room_mt:_route_stanza(stanza) |
|
686 local muc_child; |
|
687 local to_occupant = self._occupants[self._jid_nick[stanza.attr.to]]; |
|
688 local from_occupant = self._occupants[stanza.attr.from]; |
|
689 if stanza.name == "presence" then |
|
690 if to_occupant and from_occupant then |
|
691 if to_occupant.role == "moderator" or jid_bare(to_occupant.jid) == jid_bare(from_occupant.jid) then |
|
692 for i=#stanza.tags,1,-1 do |
|
693 local tag = stanza.tags[i]; |
|
694 if tag.name == "x" and tag.attr.xmlns == "http://jabber.org/protocol/muc#user" then |
|
695 muc_child = tag; |
|
696 break; |
|
697 end |
|
698 end |
|
699 end |
|
700 end |
|
701 end |
|
702 if muc_child then |
|
703 for _, item in pairs(muc_child.tags) do |
|
704 if item.name == "item" then |
|
705 if from_occupant == to_occupant then |
|
706 item.attr.jid = stanza.attr.to; |
|
707 else |
|
708 item.attr.jid = from_occupant.jid; |
|
709 end |
|
710 end |
|
711 end |
|
712 end |
|
713 self:route_stanza(stanza); |
|
714 if muc_child then |
|
715 for _, item in pairs(muc_child.tags) do |
|
716 if item.name == "item" then |
|
717 item.attr.jid = nil; |
|
718 end |
|
719 end |
|
720 end |
683 end |
721 end |
684 |
722 |
685 local _M = {}; -- module "muc" |
723 local _M = {}; -- module "muc" |
686 |
724 |
687 function _M.new_room(jid) |
725 function _M.new_room(jid) |