142 t_insert(history, st.preserialize(stanza)); |
168 t_insert(history, st.preserialize(stanza)); |
143 while #history > history_length do t_remove(history, 1) end |
169 while #history > history_length do t_remove(history, 1) end |
144 end |
170 end |
145 end |
171 end |
146 end |
172 end |
|
173 function broadcast_message_stanza(room, stanza, historic) |
|
174 local r = rooms:get(room); |
|
175 if r then |
|
176 for occupant, o_data in pairs(r) do |
|
177 for jid in pairs(o_data.sessions) do |
|
178 stanza.attr.to = jid; |
|
179 core_route_stanza(component, stanza); |
|
180 end |
|
181 end |
|
182 if historic then -- add to history |
|
183 local history = rooms_info:get(room, 'history'); |
|
184 if not history then history = {}; rooms_info:set(room, 'history', history); end |
|
185 -- stanza = st.deserialize(st.preserialize(stanza)); |
|
186 stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = muc_domain, stamp = datetime.datetime()}):up(); -- XEP-0203 |
|
187 stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated) |
|
188 t_insert(history, st.preserialize(stanza)); |
|
189 while #history > history_length do t_remove(history, 1) end |
|
190 end |
|
191 end |
|
192 end |
|
193 function broadcast_presence_stanza(room, stanza, code, nick) |
|
194 stanza = get_filtered_presence(stanza); |
|
195 local data = rooms:get(room, stanza.attr.from); |
|
196 stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
|
197 :tag("item", {affiliation=data.affiliation, role=data.role, nick=nick}):up(); |
|
198 if code then |
|
199 stanza:tag("status", {code=code}):up(); |
|
200 end |
|
201 local me; |
|
202 local r = rooms:get(room); |
|
203 if r then |
|
204 for occupant, o_data in pairs(r) do |
|
205 if occupant ~= stanza.attr.from then |
|
206 for jid in pairs(o_data.sessions) do |
|
207 stanza.attr.to = jid; |
|
208 core_route_stanza(component, stanza); |
|
209 end |
|
210 else |
|
211 me = o_data; |
|
212 end |
|
213 end |
|
214 end |
|
215 if me then |
|
216 stanza:tag("status", {code='110'}); |
|
217 for jid in pairs(me.sessions) do |
|
218 stanza.attr.to = jid; |
|
219 core_route_stanza(component, stanza); |
|
220 end |
|
221 end |
|
222 end |
147 |
223 |
148 function handle_to_occupant(origin, stanza) -- PM, vCards, etc |
224 function handle_to_occupant(origin, stanza) -- PM, vCards, etc |
149 local from, to = stanza.attr.from, stanza.attr.to; |
225 local from, to = stanza.attr.from, stanza.attr.to; |
150 local room = jid_bare(to); |
226 local room = jid_bare(to); |
151 local current_nick = jid_nick:get(from, room); |
227 local current_nick = jid_nick:get(from, room); |
152 local type = stanza.attr.type; |
228 local type = stanza.attr.type; |
153 if stanza.name == "presence" then |
229 if stanza.name == "presence" then |
|
230 local pr = get_filtered_presence(stanza); |
|
231 pr.attr.from = to; |
154 if type == "error" then -- error, kick em out! |
232 if type == "error" then -- error, kick em out! |
155 local data = rooms:get(room, to); |
233 if current_nick then |
156 data.role = 'none'; |
|
157 broadcast_presence('unavailable', to, room); -- TODO also add <status>This participant is kicked from the room because he sent an error presence: badformed error stanza</status> |
|
158 rooms:remove(room, to); |
|
159 jid_nick:remove(from, room); |
|
160 elseif type == "unavailable" then -- unavailable |
|
161 if current_nick == to then |
|
162 local data = rooms:get(room, to); |
234 local data = rooms:get(room, to); |
163 data.role = 'none'; |
235 data.role = 'none'; |
164 broadcast_presence('unavailable', to, room); |
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() |
|
237 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
|
238 :tag("item", {affiliation=data.affiliation, role=data.role}):up(); |
|
239 broadcast_presence_stanza(room, pr); |
|
240 --broadcast_presence('unavailable', to, room); -- TODO also add <status>This participant is kicked from the room because he sent an error presence: badformed error stanza</status> |
165 rooms:remove(room, to); |
241 rooms:remove(room, to); |
166 jid_nick:remove(from, room); |
242 jid_nick:remove(from, room); |
167 end -- TODO else do nothing? |
243 end |
|
244 elseif type == "unavailable" then -- unavailable |
|
245 if current_nick then |
|
246 local data = rooms:get(room, to); |
|
247 data.role = 'none'; |
|
248 broadcast_presence_stanza(room, pr); |
|
249 --broadcast_presence('unavailable', to, room); |
|
250 rooms:remove(room, to); |
|
251 jid_nick:remove(from, room); |
|
252 end |
168 elseif not type then -- available |
253 elseif not type then -- available |
169 if current_nick then |
254 if current_nick then |
170 if current_nick == to then -- simple presence |
255 if current_nick == to then -- simple presence |
171 -- TODO broadcast |
256 broadcast_presence_stanza(room, pr); |
|
257 -- FIXME check if something was filtered. if it was, then user may be rejoining |
172 else -- change nick |
258 else -- change nick |
173 if rooms:get(room, to) then |
259 if rooms:get(room, to) then |
174 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
260 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
175 else |
261 else |
176 local data = rooms:get(room, current_nick); |
262 local data = rooms:get(room, current_nick); |
177 local to_nick = select(3, jid_split(to)); |
263 local to_nick = select(3, jid_split(to)); |
178 if to_nick then |
264 if to_nick then |
179 broadcast_presence('unavailable', current_nick, room, '303', to_nick); |
265 local p = st.presence({type='unavailable', from=current_nick}); |
|
266 --[[:tag('x', {xmlns='http://jabber.org/protocol/muc#user'}) |
|
267 :tag('item', {affiliation=data.affiliation, role=data.role, nick=to_nick}):up() |
|
268 :tag('status', {code='303'});]] |
|
269 broadcast_presence_stanza(room, p, '303', to_nick); |
|
270 --broadcast_presence('unavailable', current_nick, room, '303', to_nick); |
180 rooms:remove(room, current_nick); |
271 rooms:remove(room, current_nick); |
181 rooms:set(room, to, data); |
272 rooms:set(room, to, data); |
182 jid_nick:set(from, room, to); |
273 jid_nick:set(from, room, to); |
183 broadcast_presence(nil, to, room, nil); |
274 broadcast_presence_stanza(room, pr); |
|
275 --broadcast_presence(nil, to, room, nil); |
184 else |
276 else |
185 --TODO: malformed-jid |
277 --TODO malformed-jid |
186 end |
278 end |
187 end |
279 end |
188 end |
280 end |
189 else -- enter room |
281 else -- enter room |
|
282 local new_nick = to; |
190 if rooms:get(room, to) then |
283 if rooms:get(room, to) then |
|
284 new_nick = nil; |
|
285 end |
|
286 if not new_nick then |
191 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
287 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
192 else |
288 else |
193 local data; |
289 local data; |
194 if not rooms:get(room) and not rooms_info:get(room) then -- new room |
290 if not rooms:get(room) and not rooms_info:get(room) then -- new room |
195 data = {affiliation='owner', role='moderator', jid=from}; |
291 data = {affiliation='owner', role='moderator', jid=from, sessions={[from]=get_filtered_presence(stanza)}}; |
196 end |
292 end |
197 if not data then -- new occupant |
293 if not data then -- new occupant |
198 data = {affiliation='none', role='participant', jid=from}; |
294 data = {affiliation='none', role='participant', jid=from, sessions={[from]=get_filtered_presence(stanza)}}; |
199 end |
295 end |
200 rooms:set(room, to, data); |
296 rooms:set(room, to, data); |
201 jid_nick:set(from, room, to); |
297 jid_nick:set(from, room, to); |
202 local r = rooms:get(room); |
298 local r = rooms:get(room); |
203 if r then |
299 if r then |
204 for occupant, o_data in pairs(r) do |
300 for occupant, o_data in pairs(r) do |
205 if occupant ~= from then |
301 if occupant ~= from then |
206 local pres = st.presence({to=from, from=occupant}) |
302 local pres = get_filtered_presence(o_data.sessions[o_data.jid]); |
|
303 pres.attr.to, pres.attr.from = from, occupant; |
|
304 pres |
|
305 --local pres = st.presence({to=from, from=occupant}) |
207 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
306 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
208 :tag("item", {affiliation=o_data.affiliation, role=o_data.role}):up(); |
307 :tag("item", {affiliation=o_data.affiliation, role=o_data.role}):up(); |
209 core_route_stanza(component, pres); |
308 core_route_stanza(component, pres); |
210 end |
309 end |
211 end |
310 end |
212 end |
311 end |
213 broadcast_presence(nil, to, room); |
312 broadcast_presence_stanza(room, pr); |
|
313 --broadcast_presence(nil, to, room); |
214 local history = rooms_info:get(room, 'history'); -- send discussion history |
314 local history = rooms_info:get(room, 'history'); -- send discussion history |
215 if history then |
315 if history then |
216 for _, msg in ipairs(history) do |
316 for _, msg in ipairs(history) do |
217 msg = st.deserialize(msg); |
317 msg = st.deserialize(msg); |
218 msg.attr.to=from; |
318 msg.attr.to=from; |