plugins/muc/muc.lib.lua
changeset 1739 393abf245322
parent 1737 31c3eb5797c7
child 1740 b37ccf9bec89
equal deleted inserted replaced
1738:ee4a7151ed07 1739:393abf245322
   103 	end
   103 	end
   104 end
   104 end
   105 
   105 
   106 function room_mt:broadcast_presence(stanza, code, nick)
   106 function room_mt:broadcast_presence(stanza, code, nick)
   107 	stanza = get_filtered_presence(stanza);
   107 	stanza = get_filtered_presence(stanza);
   108 	local data = self._participants[stanza.attr.from];
   108 	local data = self._occupants[stanza.attr.from];
   109 	stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
   109 	stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
   110 		:tag("item", {affiliation=data.affiliation, role=data.role, nick=nick}):up();
   110 		:tag("item", {affiliation=data.affiliation, role=data.role, nick=nick}):up();
   111 	if code then
   111 	if code then
   112 		stanza:tag("status", {code=code}):up();
   112 		stanza:tag("status", {code=code}):up();
   113 	end
   113 	end
   114 	local me;
   114 	local me;
   115 	for occupant, o_data in pairs(self._participants) do
   115 	for occupant, o_data in pairs(self._occupants) do
   116 		if occupant ~= stanza.attr.from then
   116 		if occupant ~= stanza.attr.from then
   117 			for jid in pairs(o_data.sessions) do
   117 			for jid in pairs(o_data.sessions) do
   118 				stanza.attr.to = jid;
   118 				stanza.attr.to = jid;
   119 				self:route_stanza(stanza);
   119 				self:route_stanza(stanza);
   120 			end
   120 			end
   129 			self:route_stanza(stanza);
   129 			self:route_stanza(stanza);
   130 		end
   130 		end
   131 	end
   131 	end
   132 end
   132 end
   133 function room_mt:broadcast_message(stanza, historic)
   133 function room_mt:broadcast_message(stanza, historic)
   134 	for occupant, o_data in pairs(self._participants) do
   134 	for occupant, o_data in pairs(self._occupants) do
   135 		for jid in pairs(o_data.sessions) do
   135 		for jid in pairs(o_data.sessions) do
   136 			stanza.attr.to = jid;
   136 			stanza.attr.to = jid;
   137 			self:route_stanza(stanza);
   137 			self:route_stanza(stanza);
   138 		end
   138 		end
   139 	end
   139 	end
   149 end
   149 end
   150 
   150 
   151 
   151 
   152 function room_mt:send_occupant_list(to)
   152 function room_mt:send_occupant_list(to)
   153 	local current_nick = self._jid_nick[to];
   153 	local current_nick = self._jid_nick[to];
   154 	for occupant, o_data in pairs(self._participants) do
   154 	for occupant, o_data in pairs(self._occupants) do
   155 		if occupant ~= current_nick then
   155 		if occupant ~= current_nick then
   156 			local pres = get_filtered_presence(o_data.sessions[o_data.jid]);
   156 			local pres = get_filtered_presence(o_data.sessions[o_data.jid]);
   157 			pres.attr.to, pres.attr.from = to, occupant;
   157 			pres.attr.to, pres.attr.from = to, occupant;
   158 			pres:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
   158 			pres:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
   159 				:tag("item", {affiliation=o_data.affiliation, role=o_data.role}):up();
   159 				:tag("item", {affiliation=o_data.affiliation, role=o_data.role}):up();
   204 					:tag('status'):text('This participant is kicked from the room because he sent an error presence')); -- send unavailable
   204 					:tag('status'):text('This participant is kicked from the room because he sent an error presence')); -- send unavailable
   205 			end
   205 			end
   206 		elseif type == "unavailable" then -- unavailable
   206 		elseif type == "unavailable" then -- unavailable
   207 			if current_nick then
   207 			if current_nick then
   208 				log("debug", "%s leaving %s", current_nick, room);
   208 				log("debug", "%s leaving %s", current_nick, room);
   209 				local data = self._participants[current_nick];
   209 				local data = self._occupants[current_nick];
   210 				data.role = 'none';
   210 				data.role = 'none';
   211 				self:broadcast_presence(pr);
   211 				self:broadcast_presence(pr);
   212 				self._participants[current_nick] = nil;
   212 				self._occupants[current_nick] = nil;
   213 				self._jid_nick[from] = nil;
   213 				self._jid_nick[from] = nil;
   214 			end
   214 			end
   215 		elseif not type then -- available
   215 		elseif not type then -- available
   216 			if current_nick then
   216 			if current_nick then
   217 				--if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence
   217 				--if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence
   218 					if current_nick == to then -- simple presence
   218 					if current_nick == to then -- simple presence
   219 						log("debug", "%s broadcasted presence", current_nick);
   219 						log("debug", "%s broadcasted presence", current_nick);
   220 						self._participants[current_nick].sessions[from] = pr;
   220 						self._occupants[current_nick].sessions[from] = pr;
   221 						self:broadcast_presence(pr);
   221 						self:broadcast_presence(pr);
   222 					else -- change nick
   222 					else -- change nick
   223 						if self._participants[to] then
   223 						if self._occupants[to] then
   224 							log("debug", "%s couldn't change nick", current_nick);
   224 							log("debug", "%s couldn't change nick", current_nick);
   225 							origin.send(st.error_reply(stanza, "cancel", "conflict"):tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
   225 							origin.send(st.error_reply(stanza, "cancel", "conflict"):tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
   226 						else
   226 						else
   227 							local data = self._participants[current_nick];
   227 							local data = self._occupants[current_nick];
   228 							local to_nick = select(3, jid_split(to));
   228 							local to_nick = select(3, jid_split(to));
   229 							if to_nick then
   229 							if to_nick then
   230 								log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to);
   230 								log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to);
   231 								local p = st.presence({type='unavailable', from=current_nick});
   231 								local p = st.presence({type='unavailable', from=current_nick});
   232 								self:broadcast_presence(p, '303', to_nick);
   232 								self:broadcast_presence(p, '303', to_nick);
   233 								self._participants[current_nick] = nil;
   233 								self._occupants[current_nick] = nil;
   234 								self._participants[to] = data;
   234 								self._occupants[to] = data;
   235 								self._jid_nick[from] = to;
   235 								self._jid_nick[from] = to;
   236 								pr.attr.from = to;
   236 								pr.attr.from = to;
   237 								self._participants[to].sessions[from] = pr;
   237 								self._occupants[to].sessions[from] = pr;
   238 								self:broadcast_presence(pr);
   238 								self:broadcast_presence(pr);
   239 							else
   239 							else
   240 								--TODO malformed-jid
   240 								--TODO malformed-jid
   241 							end
   241 							end
   242 						end
   242 						end
   247 				--		:tag('status'):text('Replaced by new connection'):up()); -- send unavailable
   247 				--		:tag('status'):text('Replaced by new connection'):up()); -- send unavailable
   248 				--	self:handle_to_occupant(origin, stanza); -- resend available
   248 				--	self:handle_to_occupant(origin, stanza); -- resend available
   249 				--end
   249 				--end
   250 			else -- enter room
   250 			else -- enter room
   251 				local new_nick = to;
   251 				local new_nick = to;
   252 				if self._participants[to] then
   252 				if self._occupants[to] then
   253 					new_nick = nil;
   253 					new_nick = nil;
   254 				end
   254 				end
   255 				if not new_nick then
   255 				if not new_nick then
   256 					log("debug", "%s couldn't join due to nick conflict: %s", from, to);
   256 					log("debug", "%s couldn't join due to nick conflict: %s", from, to);
   257 					origin.send(st.error_reply(stanza, "cancel", "conflict"):tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
   257 					origin.send(st.error_reply(stanza, "cancel", "conflict"):tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
   267 					end
   267 					end
   268 					if not data then -- new occupant
   268 					if not data then -- new occupant
   269 						local affiliation = self:get_affiliation(from);
   269 						local affiliation = self:get_affiliation(from);
   270 						data = {affiliation=affiliation, role=self:get_default_role(affiliation), jid=from, sessions={[from]=get_filtered_presence(stanza)}};
   270 						data = {affiliation=affiliation, role=self:get_default_role(affiliation), jid=from, sessions={[from]=get_filtered_presence(stanza)}};
   271 					end
   271 					end
   272 					self._participants[to] = data;
   272 					self._occupants[to] = data;
   273 					self._jid_nick[from] = to;
   273 					self._jid_nick[from] = to;
   274 					self:send_occupant_list(from);
   274 					self:send_occupant_list(from);
   275 					pr.attr.from = to;
   275 					pr.attr.from = to;
   276 					self:broadcast_presence(pr);
   276 					self:broadcast_presence(pr);
   277 					self:send_history(from);
   277 					self:send_history(from);
   286 		origin.send(st.error_reply(stanza, "modify", "bad-request"));
   286 		origin.send(st.error_reply(stanza, "modify", "bad-request"));
   287 	elseif stanza.name == "message" and type == "error" and get_kickable_error(stanza) then
   287 	elseif stanza.name == "message" and type == "error" and get_kickable_error(stanza) then
   288 		log("debug", "%s kicked from %s for sending an error message", current_nick, room);
   288 		log("debug", "%s kicked from %s for sending an error message", current_nick, room);
   289 		self:handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant')); -- send unavailable
   289 		self:handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant')); -- send unavailable
   290 	else -- private stanza
   290 	else -- private stanza
   291 		local o_data = self._participants[to];
   291 		local o_data = self._occupants[to];
   292 		if o_data then
   292 		if o_data then
   293 			log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid);
   293 			log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid);
   294 			local jid = o_data.jid;
   294 			local jid = o_data.jid;
   295 			-- TODO if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then jid = jid_bare(jid); end
   295 			-- TODO if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then jid = jid_bare(jid); end
   296 			stanza.attr.to, stanza.attr.from = jid, current_nick;
   296 			stanza.attr.to, stanza.attr.from = jid, current_nick;
   387 
   387 
   388 function _M:new_room(jid)
   388 function _M:new_room(jid)
   389 	return setmetatable({
   389 	return setmetatable({
   390 		jid = jid;
   390 		jid = jid;
   391 		_jid_nick = {};
   391 		_jid_nick = {};
   392 		_participants = {};
   392 		_occupants = {};
   393 		_data = {};
   393 		_data = {};
   394 		_affiliations = {};
   394 		_affiliations = {};
   395 	}, room_mt);
   395 	}, room_mt);
   396 end
   396 end
   397 
   397