plugins/muc/muc.lib.lua
changeset 2064 1ee862fd1afe
parent 2053 f5a198127dd3
child 2172 84dd0fada45b
equal deleted inserted replaced
2063:e89594a1bf4a 2064:1ee862fd1afe
   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)