mod_privilege/mod_privilege.lua
changeset 1670 0b1b4b7d5fe0
parent 1669 746d94f37a4c
child 1671 c81a981479d4
equal deleted inserted replaced
1669:746d94f37a4c 1670:0b1b4b7d5fe0
    32 local _PRESENCE_MANAGED = set.new({'managed_entity', 'roster'})
    32 local _PRESENCE_MANAGED = set.new({'managed_entity', 'roster'})
    33 local _TO_CHECK = {roster=_ALLOWED_ROSTER, message=_ALLOWED_MESSAGE, presence=_ALLOWED_PRESENCE}
    33 local _TO_CHECK = {roster=_ALLOWED_ROSTER, message=_ALLOWED_MESSAGE, presence=_ALLOWED_PRESENCE}
    34 local _PRIV_ENT_NS = 'urn:xmpp:privilege:1'
    34 local _PRIV_ENT_NS = 'urn:xmpp:privilege:1'
    35 local _FORWARDED_NS = 'urn:xmpp:forward:0'
    35 local _FORWARDED_NS = 'urn:xmpp:forward:0'
    36 
    36 
       
    37 local last_presence = nil -- cache used to avoid to send several times the same stanza (see § 7 #2)
       
    38 
    37 
    39 
    38 module:log("debug", "Loading privileged entity module ");
    40 module:log("debug", "Loading privileged entity module ");
    39 
    41 
    40 
    42 
    41 --> Permissions management <--
    43 --> Permissions management <--
    56 	session.send(message)
    58 	session.send(message)
    57 end
    59 end
    58 
    60 
    59 function set_presence_perm_set(to_jid, perms)
    61 function set_presence_perm_set(to_jid, perms)
    60 	-- fill the global presence sets according to perms
    62 	-- fill the global presence sets according to perms
    61 	if perms.presence == 'managed_entity' then
    63 	if _PRESENCE_MANAGED:contains(perms.presence) then
    62 		presence_man_ent:add(to_jid)
    64 		presence_man_ent:add(to_jid)
    63 	elseif perms.presence == 'roster' then
    65 	end
    64 		presence_man_ent:add(to_jid) -- roster imply managed_entity
    66 	if perms.presence == 'roster' then
    65 		presence_roster:add(to_jid)
    67 		presence_roster:add(to_jid)
    66 	end
    68 	end
    67 end
    69 end
    68 
    70 
    69 function advertise_presences(session, to_jid, perms)
    71 function advertise_presences(session, to_jid, perms)
   308 end);
   310 end);
   309 
   311 
   310 
   312 
   311 --> presence permission <--
   313 --> presence permission <--
   312 
   314 
       
   315 function same_tags(tag1, tag2)
       
   316 	-- check if two tags are equivalent
       
   317 
       
   318     if tag1.name ~= tag2.name then return false; end
       
   319 
       
   320 	if #tag1 ~= #tag2 then return false; end
       
   321 
       
   322 	for name, value in pairs(tag1.attr) do
       
   323 		if tag2.attr[name] ~= value then return false; end
       
   324 	end
       
   325 
       
   326 	for i=1,#tag1 do
       
   327 		if type(tag1[i]) == "string" then
       
   328 			if tag1[i] ~= tag2[i] then return false; end
       
   329 		else
       
   330 			if not same_tags(tag1[i], tag2[i]) then return false; end
       
   331 		end
       
   332 	end
       
   333 
       
   334 	return true
       
   335 end
       
   336 
       
   337 function same_presences(presence1, presence2)
       
   338 	-- check that 2 <presence/> stanzas are equivalent (except for "to" attribute)
       
   339 	-- /!\ if the id change but everything else is equivalent, this method return false
       
   340 	-- this behaviour may change in the future
       
   341 	if presence1.attr.from ~= presence2.attr.from or presence1.attr.id ~= presence2.attr.id
       
   342 		or presence1.attr.type ~= presence2.attr.type then
       
   343 		return false
       
   344 	end
       
   345 
       
   346 	if presence1.attr.id and presence1.attr.id == presence2.attr.id then return true; end
       
   347 
       
   348 	if #presence1 ~= #presence2 then return false; end
       
   349 
       
   350 	for i=1,#presence1 do
       
   351 		if type(presence1[i]) == "string" then
       
   352 			if presence1[i] ~= presence2[i] then return false; end
       
   353 		else
       
   354 			if not same_tags(presence1[i], presence2[i]) then return false; end
       
   355 		end
       
   356 	end
       
   357 
       
   358 	return true
       
   359 end
       
   360 
       
   361 function forward_presence(presence, to_jid)
       
   362 	presence_fwd = st.clone(presence)
       
   363 	presence_fwd.attr.to = to_jid
       
   364 	module:log("debug", "presence forwarded to "..to_jid..": "..tostring(presence_fwd))
       
   365 	module:send(presence_fwd)
       
   366 	last_presence = presence -- we keep the presence in cache
       
   367 end
       
   368 
   313 module:hook("presence/bare", function(event)
   369 module:hook("presence/bare", function(event)
   314 	if presence_man_ent:empty() then return; end
   370 	if presence_man_ent:empty() and presence_roster:empty() then return; end
   315 	local session, stanza = event.origin, event.stanza;
   371 
   316 	if stanza.attr.to then return; end
   372 	local session, stanza = event.origin, event.stanza;
   317 	if stanza.attr.type == nil or stanza.attr.type == "unavailable" then
   373 	if stanza.attr.type == nil or stanza.attr.type == "unavailable" then
   318 		for entity in presence_man_ent:items() do
   374 		if not stanza.attr.to then
   319 			if stanza.attr.from ~= entity then
   375 			for entity in presence_man_ent:items() do
   320 				presence_fwd = st.clone(stanza)
   376 				if stanza.attr.from ~= entity then forward_presence(stanza, entity); end
   321 				presence_fwd.attr.to = entity
   377 			end
   322 				module:log("debug", "presence forwarded to "..entity..": "..tostring(presence_fwd))
   378 		else -- directed presence
   323 				prosody.core_route_stanza(nil, presence_fwd)
   379 			-- we ignore directed presences from our own host, as we already have them
   324 			end
   380 			_, from_host = jid.split(stanza.attr.from)
   325 		end
   381 			if hosts[from_host] then return; end
   326 	end
   382 
   327 end, 150);
   383 			-- we don't send several time the same presence, as recommended in §7 #2
       
   384 			if last_presence and same_presences(last_presence, stanza) then
       
   385 			   return
       
   386 		   end
       
   387 
       
   388 			for entity in presence_roster:items() do
       
   389 				if stanza.attr.from ~= entity then forward_presence(stanza, entity); end
       
   390 			end
       
   391 		end
       
   392 	end
       
   393 end, 150)