]> granicus.if.org Git - ejabberd/commitdiff
Improve handling of PEP sent to external contacts (EJAB-825)
authorChristophe Romain <christophe.romain@process-one.net>
Tue, 23 Dec 2008 10:20:34 +0000 (10:20 +0000)
committerChristophe Romain <christophe.romain@process-one.net>
Tue, 23 Dec 2008 10:20:34 +0000 (10:20 +0000)
SVN Revision: 1745

ChangeLog
src/mod_caps.erl
src/mod_pubsub/mod_pubsub.erl

index dc97f4d67940930df4deb233e5353a3a5ae02f59..6d8a3952332e7510962192bce94896e51d840457 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * src/mod_last.erl: Implement workaround for uptime statistic in
index 13b8e1a7f2269538baf2df8a4472dfd5affcd863..408415bbb40b47173d91298ac4bab664c703604f 100644 (file)
@@ -35,6 +35,7 @@
         note_caps/3,
         clear_caps/1,
         get_features/2,
+        get_user_resource/2,
         handle_disco_response/3]).
 
 %% gen_mod callbacks
@@ -60,6 +61,7 @@
 -record(caps, {node, version, exts}).
 -record(caps_features, {node_pair, features}).
 -record(user_caps, {jid, caps}).
+-record(user_caps_default, {uid, resource}).
 -record(state, {host,
                disco_requests = ?DICT:new(),
                feature_queries = []}).
@@ -103,7 +105,26 @@ get_caps(JID) ->
 
 %% clear_caps removes user caps from database
 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
 %% information.  Host is the host that asks, From is the full JID that
@@ -122,7 +143,8 @@ note_caps(Host, From, Caps) ->
 %% timeout error.
 get_features(Host, Caps) ->
     case Caps of
-       nothing -> [];
+       nothing -> 
+           [];
        #caps{} ->
            Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
            gen_server:call(Proc, {get_features, Caps})
@@ -158,6 +180,9 @@ init([Host, _Opts]) ->
     mnesia:create_table(user_caps,
                        [{disc_copies, [node()]},
                         {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}}.
 
 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) ->
     %% XXX: this leads to race conditions where ejabberd will send
     %% lots of caps disco requests.
-    mnesia:dirty_write(#user_caps{jid = list_to_binary(jlib:jid_to_string(From)),
-                                 caps = Caps}),
+    {_, _, R} = jlib:jid_tolower(From),
+    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],
     %% Now, find which of these are not already in the database.
     Fun = fun() ->
index f87605283dd5080994cc6ac1c254b83cfce006fe..e9082208194244e408f4b25f137049de88f5b9a9 100644 (file)
@@ -2398,20 +2398,15 @@ broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
            %%ReplyTo = jlib:make_jid(LUser, LServer, SenderResource),  % This has to be used
            case catch ejabberd_c2s:get_subscribed(C2SPid) of
                Contacts when is_list(Contacts) ->
-                   Online = lists:foldl(fun({U, S, R}, Acc) ->
-                               case user_resource(U, S, R) of
-                                   [] -> Acc;
-                                   OR -> [{U, S, OR}|Acc]
-                               end
-                           end, [], Contacts),
-                   lists:foreach(fun(LJID) ->
+                   lists:foreach(fun({U, S, R}) ->
+                       LJID = {U, S, user_resource(U, S, R)}, 
                        case is_caps_notify(LServer, Node, LJID) of
                            true ->
                                ejabberd_router ! {route, Sender, jlib:make_jid(LJID), Stanza};
                            false ->
                                ok
                        end
-                   end, Online);
+                   end, Contacts);
                _ ->
                    ok
            end,
@@ -2423,20 +2418,27 @@ broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
 broadcast_by_caps(_, _, _, _) ->
     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, []) ->
-    %% If we don't know the resource, just pick first if any
     case ejabberd_sm:get_user_resources(LUser, LServer) of
-       [R|_] -> R;
-       [] -> []
+       [R|_] -> 
+           R;
+       [] -> 
+           mod_caps:get_user_resource(LUser, LServer)
     end;
 user_resource(_, _, LResource) ->
     LResource.
 
 is_caps_notify(Host, Node, LJID) ->
-    Caps = mod_caps:get_caps(LJID),
-    case catch mod_caps:get_features(Host, Caps) of
-       Features when is_list(Features) -> lists:member(Node ++ "+notify", Features);
-       _ -> false
+    case mod_caps:get_caps(LJID) of
+       nothing -> 
+           false;
+       Caps ->
+           case catch mod_caps:get_features(Host, Caps) of
+               Features when is_list(Features) -> lists:member(Node ++ "+notify", Features);
+               _ -> false
+           end
     end.
 
 %%%%%%% Configuration handling