plugins/mod_privacy.lua
changeset 2500 bffdaeb7ab5e
parent 2499 145d62abdbfc
child 2502 ec3eaf54bbd4
equal deleted inserted replaced
2499:145d62abdbfc 2500:bffdaeb7ab5e
    15 local jid_bare = util_Jid.bare;
    15 local jid_bare = util_Jid.bare;
    16 local jid_split = util_Jid.split;
    16 local jid_split = util_Jid.split;
    17 local load_roster = require "core.rostermanager".load_roster;
    17 local load_roster = require "core.rostermanager".load_roster;
    18 local to_number = tonumber;
    18 local to_number = tonumber;
    19 
    19 
    20 function findNamedList (privacy_lists, name)
    20 function findNamedList(privacy_lists, name)
    21 	local ret = nil
    21 	if privacy_lists.lists then
    22 	if privacy_lists.lists == nil then
    22 		for i=1,#privacy_lists.lists do
    23 		return nil;
    23 			if privacy_lists.lists[i].name == name then
    24 	end
    24 				return i;
    25 
    25 			end
    26 	for i=1, #privacy_lists.lists do
    26 		end
    27 		if privacy_lists.lists[i].name == name then
    27 	end
    28 			ret = i;
    28 end
    29 			break;
    29 
    30 		end
    30 function isListUsed(origin, name, privacy_lists)
    31 	end
    31 	local user = bare_sessions[origin.username.."@"..origin.host];
    32 	return ret;
    32 	if user then
    33 end
    33 		for resource, session in pairs(user.sessions) do
    34 
       
    35 function isListUsed(origin, name, privacy_lists)	
       
    36 	if bare_sessions[origin.username.."@"..origin.host].sessions ~= nil then
       
    37 		for resource, session in pairs(bare_sessions[origin.username.."@"..origin.host].sessions) do
       
    38 			if resource ~= origin.resource then
    34 			if resource ~= origin.resource then
    39 				if session.activePrivacyList == name then
    35 				if session.activePrivacyList == name then
    40 					return true;
    36 					return true;
    41 				elseif session.activePrivacyList == nil and privacy_lists.default == name then
    37 				elseif session.activePrivacyList == nil and privacy_lists.default == name then
    42 					return true;
    38 					return true;
    43 				end
    39 				end
    44 			end
    40 			end
    45 		end
    41 		end
    46 	end
    42 	end
    47 	return false;
       
    48 end
    43 end
    49 
    44 
    50 function isAnotherSessionUsingDefaultList(origin)
    45 function isAnotherSessionUsingDefaultList(origin)
    51 	local ret = false
    46 	local user = bare_sessions[origin.username.."@"..origin.host];
    52 	if bare_sessions[origin.username.."@"..origin.host].sessions ~= nil then
    47 	if user then
    53 		for resource, session in pairs(bare_sessions[origin.username.."@"..origin.host].sessions) do
    48 		for resource, session in pairs(user.sessions) do
    54 			if resource ~= origin.resource and session.activePrivacyList == nil then
    49 			if resource ~= origin.resource and session.activePrivacyList == nil then
    55 				ret = true;
    50 				return true;
    56 				break;
    51 			end
    57 			end
    52 		end
    58 		end
    53 	end
    59 	end
       
    60 	return ret;
       
    61 end
    54 end
    62 
    55 
    63 function sendUnavailable(origin, to, from)
    56 function sendUnavailable(origin, to, from)
    64 --[[ example unavailable presence stanza
    57 --[[ example unavailable presence stanza
    65 <presence from="node@host/resource" type="unavailable" to="node@host" >
    58 <presence from="node@host/resource" type="unavailable" to="node@host" >
    66 	<status>Logged out</status>
    59 	<status>Logged out</status>
    67 </presence>
    60 </presence>
    68 ]]--
    61 ]]--
    69 	local presence = st.presence({from=from, type="unavailable"})
    62 	local presence = st.presence({from=from, type="unavailable"});
    70 	presence:tag("status"):text("Logged out");
    63 	presence:tag("status"):text("Logged out");
    71 
    64 
    72 	local node, host = jid_bare(to);
    65 	local node, host = jid_bare(to);
    73 	local bare = node .. "@" .. host;
    66 	local bare = node .. "@" .. host;
    74 	
    67 	
    75 	if bare_sessions[bare].sessions ~= nil then
    68 	local user = bare_sessions[bare];
    76 		for resource, session in pairs(bare_sessions[bare].sessions) do
    69 	if user then
       
    70 		for resource, session in pairs(user.sessions) do
    77 			presence.attr.to = session.full_jid;
    71 			presence.attr.to = session.full_jid;
    78 			module:log("debug", "send unavailable to: %s; from: %s", tostring(presence.attr.to), tostring(presence.attr.from));
    72 			module:log("debug", "send unavailable to: %s; from: %s", tostring(presence.attr.to), tostring(presence.attr.from));
    79 			origin.send(presence);
    73 			origin.send(presence);
    80 		end
    74 		end
    81 	end
    75 	end
   115 	else
   109 	else
   116 		module:log("debug", "got unknown type: %s", type(listnameOrItem));
   110 		module:log("debug", "got unknown type: %s", type(listnameOrItem));
   117 	end
   111 	end
   118 end
   112 end
   119 
   113 
   120 function declineList (privacy_lists, origin, stanza, which)
   114 function declineList(privacy_lists, origin, stanza, which)
   121 	if which == "default" then
   115 	if which == "default" then
   122 		if isAnotherSessionUsingDefaultList(origin) then
   116 		if isAnotherSessionUsingDefaultList(origin) then
   123 			return { "cancel", "conflict", "Another session is online and using the default list."};
   117 			return { "cancel", "conflict", "Another session is online and using the default list."};
   124 		end
   118 		end
   125 		privacy_lists.default = nil;
   119 		privacy_lists.default = nil;
   131 		return {"modify", "bad-request", "Neither default nor active list specifed to decline."};
   125 		return {"modify", "bad-request", "Neither default nor active list specifed to decline."};
   132 	end
   126 	end
   133 	return true;
   127 	return true;
   134 end
   128 end
   135 
   129 
   136 function activateList (privacy_lists, origin, stanza, which, name)
   130 function activateList(privacy_lists, origin, stanza, which, name)
   137 	local idx = findNamedList(privacy_lists, name);
   131 	local idx = findNamedList(privacy_lists, name);
   138 
   132 
   139 	if privacy_lists.default == nil then
   133 	if privacy_lists.default == nil then
   140 		privacy_lists.default = "";
   134 		privacy_lists.default = "";
   141 	end
   135 	end
   162 		return {"modify", "bad-request", "Either not active or default given or unknown list name specified."};
   156 		return {"modify", "bad-request", "Either not active or default given or unknown list name specified."};
   163 	end
   157 	end
   164 	return true;
   158 	return true;
   165 end
   159 end
   166 
   160 
   167 function deleteList (privacy_lists, origin, stanza, name)
   161 function deleteList(privacy_lists, origin, stanza, name)
   168 	local idx = findNamedList(privacy_lists, name);
   162 	local idx = findNamedList(privacy_lists, name);
   169 
   163 
   170 	if idx ~= nil then
   164 	if idx ~= nil then
   171 		if isListUsed(origin, name, privacy_lists) then
   165 		if isListUsed(origin, name, privacy_lists) then
   172 			return {"cancel", "conflict", "Another session is online and using the list which should be deleted."};
   166 			return {"cancel", "conflict", "Another session is online and using the list which should be deleted."};
   376 		else
   370 		else
   377 			datamanager.store(origin.username, origin.host, "privacy", privacy_lists);
   371 			datamanager.store(origin.username, origin.host, "privacy", privacy_lists);
   378 		end
   372 		end
   379 		return true;
   373 		return true;
   380 	end
   374 	end
   381 	return false;
   375 end);
   382 end, 500);
       
   383 
   376 
   384 function checkIfNeedToBeBlocked(e, session)
   377 function checkIfNeedToBeBlocked(e, session)
   385 	local origin, stanza = e.origin, e.stanza;
   378 	local origin, stanza = e.origin, e.stanza;
   386 	local privacy_lists = datamanager.load(session.username, session.host, "privacy") or {};
   379 	local privacy_lists = datamanager.load(session.username, session.host, "privacy") or {};
   387 	local bare_jid = session.username.."@"..session.host;
   380 	local bare_jid = session.username.."@"..session.host;
   388 
   381 
   389 	module:log("debug", "stanza: %s, to: %s, from: %s", tostring(stanza.name), tostring(stanza.attr.to), tostring(stanza.attr.from));
   382 	module:log("debug", "stanza: %s, to: %s, from: %s", tostring(stanza.name), tostring(stanza.attr.to), tostring(stanza.attr.from));
   390 	
   383 	
   391 	if stanza.attr.to ~= nil and stanza.attr.from ~= nil then
   384 	if stanza.attr.to ~= nil and stanza.attr.from ~= nil then
   392 		if privacy_lists.lists == nil or
   385 		if privacy_lists.lists == nil or
   393 		   (session.activePrivacyList == nil or session.activePrivacyList == "") and
   386 			(session.activePrivacyList == nil or session.activePrivacyList == "") and
   394 		   (privacy_lists.default == nil     or privacy_lists.default == "")
   387 			(privacy_lists.default == nil     or privacy_lists.default == "")
   395 		then 
   388 		then 
   396 			return; -- Nothing to block, default is Allow all
   389 			return; -- Nothing to block, default is Allow all
   397 		end
   390 		end
   398 	    if jid_bare(stanza.attr.from) == bare_jid and jid_bare(stanza.attr.to) == bare_jid then
   391 		if jid_bare(stanza.attr.from) == bare_jid and jid_bare(stanza.attr.to) == bare_jid then
   399             module:log("debug", "Never block communications from one of a user's resources to another.");
   392 			module:log("debug", "Never block communications from one of a user's resources to another.");
   400             return; -- from one of a user's resource to another => HANDS OFF!
   393 			return; -- from one of a user's resource to another => HANDS OFF!
   401         end 
   394 		end 
   402 
   395 
   403 		local idx;
   396 		local idx;
   404 		local list;
   397 		local list;
   405 		local item;
   398 		local item;
   406 		local listname = session.activePrivacyList;
   399 		local listname = session.activePrivacyList;
   481 					return;
   474 					return;
   482 				end
   475 				end
   483 			end
   476 			end
   484 		end
   477 		end
   485 	end
   478 	end
   486 	return;
       
   487 end
   479 end
   488 
   480 
   489 function preCheckIncoming(e)
   481 function preCheckIncoming(e)
   490 	local session;
   482 	local session;
   491 	if e.stanza.attr.to ~= nil then
   483 	if e.stanza.attr.to ~= nil then
   508 			session = full_sessions[node.."@"..host.."/"..resource];
   500 			session = full_sessions[node.."@"..host.."/"..resource];
   509 		end
   501 		end
   510 		if session ~= nil then
   502 		if session ~= nil then
   511 			return checkIfNeedToBeBlocked(e, session);
   503 			return checkIfNeedToBeBlocked(e, session);
   512 		else
   504 		else
   513 			module:log("debug", "preCheckIncoming: Couldn't get session for jid: %s@%s/%s", tostring(node), tostring(host), tostring(resource))
   505 			module:log("debug", "preCheckIncoming: Couldn't get session for jid: %s@%s/%s", tostring(node), tostring(host), tostring(resource));
   514 		end
   506 		end
   515 	end
   507 	end
   516 	return;
       
   517 end
   508 end
   518 
   509 
   519 function preCheckOutgoing(e)
   510 function preCheckOutgoing(e)
   520 	local session = e.origin;
   511 	local session = e.origin;
   521 	if e.stanza.attr.from == nil then
   512 	if e.stanza.attr.from == nil then
   524 		 	e.stanza.attr.from = e.stanza.attr.from .. "/" .. session.resource;
   515 		 	e.stanza.attr.from = e.stanza.attr.from .. "/" .. session.resource;
   525 		end
   516 		end
   526 	end
   517 	end
   527 	return checkIfNeedToBeBlocked(e, session);
   518 	return checkIfNeedToBeBlocked(e, session);
   528 end
   519 end
   529 
       
   530 
   520 
   531 module:hook("pre-message/full", preCheckOutgoing, 500);
   521 module:hook("pre-message/full", preCheckOutgoing, 500);
   532 module:hook("pre-message/bare", preCheckOutgoing, 500);
   522 module:hook("pre-message/bare", preCheckOutgoing, 500);
   533 module:hook("pre-message/host", preCheckOutgoing, 500);
   523 module:hook("pre-message/host", preCheckOutgoing, 500);
   534 module:hook("pre-iq/full", preCheckOutgoing, 500);
   524 module:hook("pre-iq/full", preCheckOutgoing, 500);
   545 module:hook("iq/bare", preCheckIncoming, 500);
   535 module:hook("iq/bare", preCheckIncoming, 500);
   546 module:hook("iq/host", preCheckIncoming, 500);
   536 module:hook("iq/host", preCheckIncoming, 500);
   547 module:hook("presence/full", preCheckIncoming, 500);
   537 module:hook("presence/full", preCheckIncoming, 500);
   548 module:hook("presence/bare", preCheckIncoming, 500);
   538 module:hook("presence/bare", preCheckIncoming, 500);
   549 module:hook("presence/host", preCheckIncoming, 500);
   539 module:hook("presence/host", preCheckIncoming, 500);
   550 
       
   551 module:log("info", "mod_privacy loaded ...");