plugins/muc/muc.lib.lua
changeset 5061 186f34d88073
parent 4999 d5a3c5c1873c
child 5063 4bc202a7b351
equal deleted inserted replaced
5060:b0e36777f715 5061:186f34d88073
   342 	length = math.min(tonumber(length) or default_history_length, self._data_max_history_length or math.huge);
   342 	length = math.min(tonumber(length) or default_history_length, self._data_max_history_length or math.huge);
   343 	if length == default_history_length then
   343 	if length == default_history_length then
   344 		length = nil;
   344 		length = nil;
   345 	end
   345 	end
   346 	self._data.history_length = length;
   346 	self._data.history_length = length;
       
   347 end
       
   348 
       
   349 
       
   350 local function construct_stanza_id(room, stanza)
       
   351 	local from_jid, to_nick = stanza.attr.from, stanza.attr.to;
       
   352 	local from_nick = room._jid_nick[from_jid];
       
   353 	local occupant = room._occupants[to_nick];
       
   354 	local to_jid = occupant.jid;
       
   355 	
       
   356 	return from_nick, to_jid, base64.encode(to_jid.."\0"..stanza.attr.id.."\0"..md5(from_jid));
       
   357 end
       
   358 local function deconstruct_stanza_id(room, stanza)
       
   359 	local from_jid_possiblybare, to_nick = stanza.attr.from, stanza.attr.to;
       
   360 	local from_jid, id, to_jid_hash = (base64.decode(stanza.attr.id) or ""):match("^(.+)%z(.*)%z(.+)$");
       
   361 	local from_nick = room._jid_nick[from_jid];
       
   362 
       
   363 	if not(from_nick) then return; end
       
   364 	if not(from_jid_possiblybare == from_jid or from_jid_possiblybare == jid_bare(from_jid)) then return; end
       
   365 
       
   366 	local occupant = room._occupants[to_nick];
       
   367 	for to_jid in pairs(occupant and occupant.sessions or {}) do
       
   368 		if md5(to_jid) == to_jid_hash then
       
   369 			return from_nick, to_jid, id;
       
   370 		end
       
   371 	end
   347 end
   372 end
   348 
   373 
   349 
   374 
   350 function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc
   375 function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc
   351 	local from, to = stanza.attr.from, stanza.attr.to;
   376 	local from, to = stanza.attr.from, stanza.attr.to;
   495 			if type ~= 'visible' and type ~= 'invisible' then -- COMPAT ejabberd can broadcast or forward XEP-0018 presences
   520 			if type ~= 'visible' and type ~= 'invisible' then -- COMPAT ejabberd can broadcast or forward XEP-0018 presences
   496 				origin.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME correct error?
   521 				origin.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME correct error?
   497 			end
   522 			end
   498 		end
   523 		end
   499 	elseif not current_nick then -- not in room
   524 	elseif not current_nick then -- not in room
   500 		if type == "error" or type == "result" then
   525 		if type == "error" or type == "result" and stanza.name == "iq" then
   501 			local id = stanza.name == "iq" and stanza.attr.id and base64.decode(stanza.attr.id);
   526 			local id = stanza.attr.id;
   502 			local _nick, _id, _hash = (id or ""):match("^(.+)%z(.*)%z(.+)$");
   527 			stanza.attr.from, stanza.attr.to, stanza.attr.id = deconstruct_stanza_id(self, stanza);
   503 			local occupant = self._occupants[stanza.attr.to];
   528 			self:_route_stanza(stanza);
   504 			if occupant and _nick and self._jid_nick[_nick] and _id and _hash then
   529 			stanza.attr.from, stanza.attr.to, stanza.attr.id = from, to, id;
   505 				local id, _to = stanza.attr.id;
       
   506 				for jid in pairs(occupant.sessions) do
       
   507 					if md5(jid) == _hash then
       
   508 						_to = jid;
       
   509 						break;
       
   510 					end
       
   511 				end
       
   512 				if _to then
       
   513 					stanza.attr.to, stanza.attr.from, stanza.attr.id = _to, self._jid_nick[_nick], _id;
       
   514 					self:_route_stanza(stanza);
       
   515 					stanza.attr.to, stanza.attr.from, stanza.attr.id = to, from, id;
       
   516 				end
       
   517 			end
       
   518 		else
   530 		else
   519 			origin.send(st.error_reply(stanza, "cancel", "not-acceptable"));
   531 			origin.send(st.error_reply(stanza, "cancel", "not-acceptable"));
   520 		end
   532 		end
   521 	elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM
   533 	elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM
   522 		origin.send(st.error_reply(stanza, "modify", "bad-request"));
   534 		origin.send(st.error_reply(stanza, "modify", "bad-request"));
   525 		self:handle_to_occupant(origin, build_unavailable_presence_from_error(stanza)); -- send unavailable
   537 		self:handle_to_occupant(origin, build_unavailable_presence_from_error(stanza)); -- send unavailable
   526 	else -- private stanza
   538 	else -- private stanza
   527 		local o_data = self._occupants[to];
   539 		local o_data = self._occupants[to];
   528 		if o_data then
   540 		if o_data then
   529 			log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid);
   541 			log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid);
   530 			local jid = o_data.jid;
   542 			if stanza.name == "iq" then
   531 			local bare = jid_bare(jid);
   543 				local id = stanza.attr.id;
   532 			stanza.attr.to, stanza.attr.from = jid, current_nick;
   544 				stanza.attr.from, stanza.attr.to, stanza.attr.id = construct_stanza_id(self, stanza);
   533 			local id = stanza.attr.id;
   545 				if type == 'get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then
   534 			if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' and bare ~= jid then
   546 					stanza.attr.to = jid_bare(stanza.attr.to);
   535 				stanza.attr.to = bare;
   547 				end
   536 				stanza.attr.id = base64.encode(jid.."\0"..id.."\0"..md5(from));
   548 				self:_route_stanza(stanza);
   537 			end
   549 				stanza.attr.from, stanza.attr.to, stanza.attr.id = from, to, id;
   538 			self:_route_stanza(stanza);
   550 			else -- message
   539 			stanza.attr.to, stanza.attr.from, stanza.attr.id = to, from, id;
   551 				stanza.attr.from = current_nick;
       
   552 				for jid in pairs(o_data.sessions) do
       
   553 					stanza.attr.to = jid;
       
   554 					self:_route_stanza(stanza);
       
   555 				end
       
   556 				stanza.attr.from, stanza.attr.to = from, to;
       
   557 			end
   540 		elseif type ~= "error" and type ~= "result" then -- recipient not in room
   558 		elseif type ~= "error" and type ~= "result" then -- recipient not in room
   541 			origin.send(st.error_reply(stanza, "cancel", "item-not-found", "Recipient not in room"));
   559 			origin.send(st.error_reply(stanza, "cancel", "item-not-found", "Recipient not in room"));
   542 		end
   560 		end
   543 	end
   561 	end
   544 end
   562 end