mirror of
https://github.com/processone/ejabberd.git
synced 2024-10-31 15:21:38 +01:00
Add roster subscriptions handling and make PEP events sent to all resources
SVN Revision: 1957
This commit is contained in:
parent
06abf6331b
commit
55942d1f4a
@ -1,3 +1,12 @@
|
|||||||
|
2009-03-03 Christophe Romain <christophe.romain@process-one.net>
|
||||||
|
|
||||||
|
* src/mod_pubsub/mod_pubsub.erl: Add roster subscriptions handling
|
||||||
|
so on_sub_and_presence if fully supported.
|
||||||
|
|
||||||
|
* src/mod_pubsub/mod_pubsub.erl: Allow to send PEP events to all
|
||||||
|
connected ressources, even via s2s.
|
||||||
|
* src/mod_caps.erl: Likewise
|
||||||
|
|
||||||
2009-02-27 Badlop <badlop@process-one.net>
|
2009-02-27 Badlop <badlop@process-one.net>
|
||||||
|
|
||||||
* src/web/ejabberd_http.erl: Added a workaround for inet:peername
|
* src/web/ejabberd_http.erl: Added a workaround for inet:peername
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
note_caps/3,
|
note_caps/3,
|
||||||
clear_caps/1,
|
clear_caps/1,
|
||||||
get_features/2,
|
get_features/2,
|
||||||
get_user_resource/2,
|
get_user_resources/2,
|
||||||
handle_disco_response/3]).
|
handle_disco_response/3]).
|
||||||
|
|
||||||
%% gen_mod callbacks
|
%% gen_mod callbacks
|
||||||
@ -61,7 +61,7 @@
|
|||||||
-record(caps, {node, version, exts}).
|
-record(caps, {node, version, exts}).
|
||||||
-record(caps_features, {node_pair, features}).
|
-record(caps_features, {node_pair, features}).
|
||||||
-record(user_caps, {jid, caps}).
|
-record(user_caps, {jid, caps}).
|
||||||
-record(user_caps_default, {uid, resource}).
|
-record(user_caps_resources, {uid, resource}).
|
||||||
-record(state, {host,
|
-record(state, {host,
|
||||||
disco_requests = ?DICT:new(),
|
disco_requests = ?DICT:new(),
|
||||||
feature_queries = []}).
|
feature_queries = []}).
|
||||||
@ -109,21 +109,17 @@ clear_caps(JID) ->
|
|||||||
BJID = list_to_binary(jlib:jid_to_string(JID)),
|
BJID = list_to_binary(jlib:jid_to_string(JID)),
|
||||||
BUID = list_to_binary(jlib:jid_to_string({U, S, []})),
|
BUID = list_to_binary(jlib:jid_to_string({U, S, []})),
|
||||||
catch mnesia:dirty_delete({user_caps, BJID}),
|
catch mnesia:dirty_delete({user_caps, BJID}),
|
||||||
case catch mnesia:dirty_read({user_caps_default, BUID}) of
|
catch mnesia:dirty_delete_object(#user_caps_resources{uid = BUID, resource = list_to_binary(R)}),
|
||||||
[#user_caps_default{resource=R}] ->
|
ok.
|
||||||
catch mnesia:dirty_delete({user_caps_default, BUID});
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% give default user resource
|
%% give default user resource
|
||||||
get_user_resource(LUser, LServer) ->
|
get_user_resources(LUser, LServer) ->
|
||||||
BUID = list_to_binary(jlib:jid_to_string({LUser, LServer, []})),
|
BUID = list_to_binary(jlib:jid_to_string({LUser, LServer, []})),
|
||||||
case catch mnesia:dirty_read({user_caps_default, BUID}) of
|
case catch mnesia:dirty_read({user_caps_resources, BUID}) of
|
||||||
[#user_caps_default{resource=R}] ->
|
{'EXIT', _} ->
|
||||||
R;
|
[];
|
||||||
_ ->
|
Resources ->
|
||||||
[]
|
lists:map(fun(#user_caps_resources{resource=R}) -> binary_to_list(R) end, Resources)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% note_caps should be called to make the module request disco
|
%% note_caps should be called to make the module request disco
|
||||||
@ -180,9 +176,11 @@ init([Host, _Opts]) ->
|
|||||||
mnesia:create_table(user_caps,
|
mnesia:create_table(user_caps,
|
||||||
[{disc_copies, [node()]},
|
[{disc_copies, [node()]},
|
||||||
{attributes, record_info(fields, user_caps)}]),
|
{attributes, record_info(fields, user_caps)}]),
|
||||||
mnesia:create_table(user_caps_default,
|
mnesia:create_table(user_caps_resources,
|
||||||
[{disc_copies, [node()]},
|
[{disc_copies, [node()]},
|
||||||
{attributes, record_info(fields, user_caps_default)}]),
|
{type, bag},
|
||||||
|
{attributes, record_info(fields, user_caps_resources)}]),
|
||||||
|
mnesia:delete_table(user_caps_default),
|
||||||
{ok, #state{host = Host}}.
|
{ok, #state{host = Host}}.
|
||||||
|
|
||||||
maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) ->
|
maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) ->
|
||||||
@ -239,11 +237,11 @@ handle_cast({note_caps, From,
|
|||||||
mnesia:dirty_write(#user_caps{jid = BJID, caps = Caps}),
|
mnesia:dirty_write(#user_caps{jid = BJID, caps = Caps}),
|
||||||
case ejabberd_sm:get_user_resources(U, S) of
|
case ejabberd_sm:get_user_resources(U, S) of
|
||||||
[] ->
|
[] ->
|
||||||
ok;
|
% only store resources of caps aware external contacts
|
||||||
_ ->
|
|
||||||
% only store default resource of external contacts
|
|
||||||
BUID = list_to_binary(jlib:jid_to_string(jlib:jid_remove_resource(From))),
|
BUID = list_to_binary(jlib:jid_to_string(jlib:jid_remove_resource(From))),
|
||||||
mnesia:dirty_write(#user_caps_default{uid = BUID, resource = R})
|
mnesia:dirty_write(#user_caps_resources{uid = BUID, resource = list_to_binary(R)});
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
end,
|
end,
|
||||||
SubNodes = [Version | Exts],
|
SubNodes = [Version | Exts],
|
||||||
%% Now, find which of these are not already in the database.
|
%% Now, find which of these are not already in the database.
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
-module(mod_pubsub).
|
-module(mod_pubsub).
|
||||||
-author('christophe.romain@process-one.net').
|
-author('christophe.romain@process-one.net').
|
||||||
-version('1.12-01').
|
-version('1.12-02').
|
||||||
|
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
%% exports for hooks
|
%% exports for hooks
|
||||||
-export([presence_probe/3,
|
-export([presence_probe/3,
|
||||||
|
in_subscription/6,
|
||||||
remove_user/2,
|
remove_user/2,
|
||||||
disco_local_identity/5,
|
disco_local_identity/5,
|
||||||
disco_local_features/5,
|
disco_local_features/5,
|
||||||
@ -163,6 +164,7 @@ init([ServerHost, Opts]) ->
|
|||||||
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
||||||
ejabberd_hooks:add(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
ejabberd_hooks:add(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||||
ejabberd_hooks:add(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
ejabberd_hooks:add(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
||||||
|
ejabberd_hooks:add(roster_in_subscription, ServerHost, ?MODULE, in_subscription, 50),
|
||||||
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
@ -417,6 +419,16 @@ presence_probe(#jid{lserver = Host} = JID, JID, Pid) ->
|
|||||||
presence_probe(_, _, _) ->
|
presence_probe(_, _, _) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
%% -------
|
||||||
|
%% subscription hooks handling functions
|
||||||
|
%%
|
||||||
|
in_subscription(Acc, User, Server, JID, subscribed, _) ->
|
||||||
|
Proc = gen_mod:get_module_proc(Server, ?PROCNAME),
|
||||||
|
gen_server:cast(Proc, {subscribed, User, Server, JID}),
|
||||||
|
Acc;
|
||||||
|
in_subscription(Acc, _, _, _, _, _) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
%% -------
|
%% -------
|
||||||
%% user remove hook handling function
|
%% user remove hook handling function
|
||||||
%%
|
%%
|
||||||
@ -518,6 +530,42 @@ handle_cast({presence, JID, Pid}, State) ->
|
|||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
|
handle_cast({subscribed, User, Server, JID}, State) ->
|
||||||
|
%% and send last PEP events published by JID
|
||||||
|
Owner = jlib:jid_tolower(jlib:jid_remove_resource(JID)),
|
||||||
|
Host = State#state.host,
|
||||||
|
ServerHost = State#state.server_host,
|
||||||
|
lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, options = Options}) ->
|
||||||
|
case get_option(Options, send_last_published_item) of
|
||||||
|
on_sub_and_presence ->
|
||||||
|
lists:foreach(fun(Resource) ->
|
||||||
|
LJID = jlib:jid_tolower(jlib:make_jid(User, Server, Resource)),
|
||||||
|
case is_caps_notify(ServerHost, Node, LJID) of
|
||||||
|
true ->
|
||||||
|
Subscribed = case get_option(Options, access_model) of
|
||||||
|
open -> true;
|
||||||
|
presence -> true;
|
||||||
|
whitelist -> false; % subscribers are added manually
|
||||||
|
authorize -> false; % likewise
|
||||||
|
roster ->
|
||||||
|
Grps = get_option(Options, roster_groups_allowed, []),
|
||||||
|
element(2, get_roster_info(User, Server, LJID, Grps))
|
||||||
|
end,
|
||||||
|
if Subscribed ->
|
||||||
|
send_last_item(Owner, Node, LJID);
|
||||||
|
true ->
|
||||||
|
ok
|
||||||
|
end;
|
||||||
|
false ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end, user_resources(User, Server));
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end, tree_action(Host, get_nodes, [Owner])),
|
||||||
|
{noreply, State};
|
||||||
|
|
||||||
handle_cast({remove_user, LUser, LServer}, State) ->
|
handle_cast({remove_user, LUser, LServer}, State) ->
|
||||||
Host = State#state.host,
|
Host = State#state.host,
|
||||||
Owner = jlib:make_jid(LUser, LServer, ""),
|
Owner = jlib:make_jid(LUser, LServer, ""),
|
||||||
@ -582,6 +630,7 @@ terminate(_Reason, #state{host = Host,
|
|||||||
ejabberd_hooks:delete(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
ejabberd_hooks:delete(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
||||||
ejabberd_hooks:delete(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
ejabberd_hooks:delete(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||||
ejabberd_hooks:delete(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
ejabberd_hooks:delete(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
||||||
|
ejabberd_hooks:delete(roster_in_subscription, ServerHost, ?MODULE, in_subscription, 50),
|
||||||
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||||
lists:foreach(fun({NS,Mod}) ->
|
lists:foreach(fun({NS,Mod}) ->
|
||||||
gen_iq_handler:remove_iq_handler(Mod, ServerHost, NS)
|
gen_iq_handler:remove_iq_handler(Mod, ServerHost, NS)
|
||||||
@ -2301,7 +2350,10 @@ broadcast_stanza(Host, NodeOpts, States, Stanza) ->
|
|||||||
%% broadcast Stanza to all contacts of the user that are advertising
|
%% broadcast Stanza to all contacts of the user that are advertising
|
||||||
%% interest in this kind of Node.
|
%% interest in this kind of Node.
|
||||||
broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
||||||
SenderResource = user_resource(LUser, LServer, LResource),
|
SenderResource = case LResource of
|
||||||
|
[] -> hd(user_resources(LUser, LServer));
|
||||||
|
_ -> LResource
|
||||||
|
end,
|
||||||
case ejabberd_sm:get_session_pid(LUser, LServer, SenderResource) of
|
case ejabberd_sm:get_session_pid(LUser, LServer, SenderResource) of
|
||||||
C2SPid when is_pid(C2SPid) ->
|
C2SPid when is_pid(C2SPid) ->
|
||||||
%% set the from address on the notification to the bare JID of the account owner
|
%% set the from address on the notification to the bare JID of the account owner
|
||||||
@ -2311,14 +2363,17 @@ broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
|||||||
%%ReplyTo = jlib:make_jid(LUser, LServer, SenderResource), % This has to be used
|
%%ReplyTo = jlib:make_jid(LUser, LServer, SenderResource), % This has to be used
|
||||||
case catch ejabberd_c2s:get_subscribed(C2SPid) of
|
case catch ejabberd_c2s:get_subscribed(C2SPid) of
|
||||||
Contacts when is_list(Contacts) ->
|
Contacts when is_list(Contacts) ->
|
||||||
lists:foreach(fun({U, S, R}) ->
|
lists:foreach(fun({U, S, _}) ->
|
||||||
LJID = {U, S, user_resource(U, S, R)},
|
JIDs = lists:foldl(fun(R, Acc) ->
|
||||||
case is_caps_notify(LServer, Node, LJID) of
|
LJID = {U, S, R},
|
||||||
true ->
|
case is_caps_notify(LServer, Node, LJID) of
|
||||||
ejabberd_router ! {route, Sender, jlib:make_jid(LJID), Stanza};
|
true -> [LJID | Acc];
|
||||||
false ->
|
false -> Acc
|
||||||
ok
|
end
|
||||||
end
|
end, [], user_resources(U, S)),
|
||||||
|
lists:foreach(fun(JID) ->
|
||||||
|
ejabberd_router ! {route, Sender, jlib:make_jid(JID), Stanza}
|
||||||
|
end, JIDs)
|
||||||
end, Contacts);
|
end, Contacts);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
@ -2333,15 +2388,11 @@ broadcast_by_caps(_, _, _, _) ->
|
|||||||
|
|
||||||
%% If we don't know the resource, just pick first if any
|
%% If we don't know the resource, just pick first if any
|
||||||
%% If no resource available, check if caps anyway (remote online)
|
%% If no resource available, check if caps anyway (remote online)
|
||||||
user_resource(LUser, LServer, []) ->
|
user_resources(User, Server) ->
|
||||||
case ejabberd_sm:get_user_resources(LUser, LServer) of
|
case ejabberd_sm:get_user_resources(User, Server) of
|
||||||
[R|_] ->
|
[] -> mod_caps:get_user_resources(User, Server);
|
||||||
R;
|
Rs -> Rs
|
||||||
[] ->
|
end.
|
||||||
mod_caps:get_user_resource(LUser, LServer)
|
|
||||||
end;
|
|
||||||
user_resource(_, _, LResource) ->
|
|
||||||
LResource.
|
|
||||||
|
|
||||||
is_caps_notify(Host, Node, LJID) ->
|
is_caps_notify(Host, Node, LJID) ->
|
||||||
case mod_caps:get_caps(LJID) of
|
case mod_caps:get_caps(LJID) of
|
||||||
|
Loading…
Reference in New Issue
Block a user