Improve handling of PEP sent to external contacts (EJAB-825)

SVN Revision: 1746
This commit is contained in:
Christophe Romain 2008-12-23 10:25:00 +00:00
parent 9539a50c33
commit 252a08e037
3 changed files with 55 additions and 19 deletions

View File

@ -1,3 +1,9 @@
2008-12-23 Christophe Romain <christophe.romain@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: Improve handling of PEP sent to
external contacts (EJAB-825)
* src/mod_caps.erl: Likewise
2008-12-23 Badlop <badlop@process-one.net> 2008-12-23 Badlop <badlop@process-one.net>
* src/cyrsasl_digest.erl: Check digest-uri in SASL digest * src/cyrsasl_digest.erl: Check digest-uri in SASL digest

View File

@ -35,6 +35,7 @@
note_caps/3, note_caps/3,
clear_caps/1, clear_caps/1,
get_features/2, get_features/2,
get_user_resource/2,
handle_disco_response/3]). handle_disco_response/3]).
%% gen_mod callbacks %% gen_mod callbacks
@ -60,6 +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(state, {host, -record(state, {host,
disco_requests = ?DICT:new(), disco_requests = ?DICT:new(),
feature_queries = []}). feature_queries = []}).
@ -103,7 +105,26 @@ get_caps(JID) ->
%% clear_caps removes user caps from database %% clear_caps removes user caps from database
clear_caps(JID) -> clear_caps(JID) ->
catch mnesia:dirty_delete({user_caps, list_to_binary(jlib:jid_to_string(JID))}). {U, S, R} = jlib:jid_tolower(JID),
BJID = list_to_binary(jlib:jid_to_string(JID)),
BUID = list_to_binary(jlib:jid_to_string({U, S, []})),
catch mnesia:dirty_delete({user_caps, BJID}),
case catch mnesia:dirty_read({user_caps_default, BUID}) of
[#user_caps_default{resource=R}] ->
catch mnesia:dirty_delete({user_caps_default, BUID});
_ ->
ok
end.
%% give default user resource
get_user_resource(LUser, LServer) ->
BUID = list_to_binary(jlib:jid_to_string({LUser, LServer, []})),
case catch mnesia:dirty_read({user_caps_default, BUID}) of
[#user_caps_default{resource=R}] ->
R;
_ ->
[]
end.
%% note_caps should be called to make the module request disco %% note_caps should be called to make the module request disco
%% information. Host is the host that asks, From is the full JID that %% information. Host is the host that asks, From is the full JID that
@ -122,7 +143,8 @@ note_caps(Host, From, Caps) ->
%% timeout error. %% timeout error.
get_features(Host, Caps) -> get_features(Host, Caps) ->
case Caps of case Caps of
nothing -> []; nothing ->
[];
#caps{} -> #caps{} ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
gen_server:call(Proc, {get_features, Caps}) gen_server:call(Proc, {get_features, Caps})
@ -158,6 +180,9 @@ 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,
[{disc_copies, [node()]},
{attributes, record_info(fields, 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}) ->
@ -209,8 +234,11 @@ handle_cast({note_caps, From,
#state{host = Host, disco_requests = Requests} = State) -> #state{host = Host, disco_requests = Requests} = State) ->
%% XXX: this leads to race conditions where ejabberd will send %% XXX: this leads to race conditions where ejabberd will send
%% lots of caps disco requests. %% lots of caps disco requests.
mnesia:dirty_write(#user_caps{jid = list_to_binary(jlib:jid_to_string(From)), {_, _, R} = jlib:jid_tolower(From),
caps = Caps}), BJID = list_to_binary(jlib:jid_to_string(From)),
BUID = list_to_binary(jlib:jid_to_string(jlib:jid_remove_resource(From))),
mnesia:dirty_write(#user_caps{jid = BJID, caps = Caps}),
mnesia:dirty_write(#user_caps_default{uid = BUID, resource = R}),
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.
Fun = fun() -> Fun = fun() ->

View File

@ -2350,20 +2350,15 @@ 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) ->
Online = lists:foldl(fun({U, S, R}, Acc) -> lists:foreach(fun({U, S, R}) ->
case user_resource(U, S, R) of LJID = {U, S, user_resource(U, S, R)},
[] -> Acc;
OR -> [{U, S, OR}|Acc]
end
end, [], Contacts),
lists:foreach(fun(LJID) ->
case is_caps_notify(LServer, Node, LJID) of case is_caps_notify(LServer, Node, LJID) of
true -> true ->
ejabberd_router ! {route, Sender, jlib:make_jid(LJID), Stanza}; ejabberd_router ! {route, Sender, jlib:make_jid(LJID), Stanza};
false -> false ->
ok ok
end end
end, Online); end, Contacts);
_ -> _ ->
ok ok
end, end,
@ -2375,20 +2370,27 @@ broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
broadcast_by_caps(_, _, _, _) -> broadcast_by_caps(_, _, _, _) ->
ok. ok.
%% If we don't know the resource, just pick first if any
%% If no resource available, check if caps anyway (remote online)
user_resource(LUser, LServer, []) -> user_resource(LUser, LServer, []) ->
%% If we don't know the resource, just pick first if any
case ejabberd_sm:get_user_resources(LUser, LServer) of case ejabberd_sm:get_user_resources(LUser, LServer) of
[R|_] -> R; [R|_] ->
[] -> [] R;
[] ->
mod_caps:get_user_resource(LUser, LServer)
end; end;
user_resource(_, _, LResource) -> user_resource(_, _, LResource) ->
LResource. LResource.
is_caps_notify(Host, Node, LJID) -> is_caps_notify(Host, Node, LJID) ->
Caps = mod_caps:get_caps(LJID), case mod_caps:get_caps(LJID) of
case catch mod_caps:get_features(Host, Caps) of nothing ->
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features); false;
_ -> false Caps ->
case catch mod_caps:get_features(Host, Caps) of
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features);
_ -> false
end
end. end.
%%%%%%% Configuration handling %%%%%%% Configuration handling