From 409ab4806896d0f962ac5b85459ed1ab05cb444c Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 10 Apr 2009 07:36:17 +0000 Subject: [PATCH] better hadling of presence in mod_caps SVN Revision: 2012 --- ChangeLog | 10 +++++++ src/ejabberd_c2s.erl | 10 ------- src/mod_caps.erl | 39 +++++++++++++++++++++++++++- src/mod_pubsub/mod_pubsub.erl | 49 +++++++++++++++-------------------- 4 files changed, 69 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6c41ea9d4..c5ccd1a47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-04-10 Christophe Romain + + * src/mod_caps.erl: Better handling of presence hook and caps clean + * src/ejabberd_c2s.erl: Likewise + * src/mod_pubsub/mod_pubsub.erl: Likewise + + * src/mod_pubsub/mod_pubsub.erl: Improve invalid-payload check, send + last published item to new resource only, thread message sending. + (from r2005 commit) + 2009-04-09 Badlop * src/msgs/pl.po: Fix some translations (thanks to Andrzej Smyk) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 05bbdd070..79242dda4 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1126,16 +1126,6 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> allow -> LFrom = jlib:jid_tolower(From), LBFrom = jlib:jid_remove_resource(LFrom), - %% Note contact availability - case xml:get_attr_s("type", Attrs) of - "unavailable" -> - %mod_caps:clear_caps(From); - % caps clear disabled cause it breaks things - ok; - _ -> - Caps = mod_caps:read_caps(Els), - mod_caps:note_caps(StateData#state.server, From, Caps) - end, case ?SETS:is_element( LFrom, StateData#state.pres_a) orelse ?SETS:is_element( diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 1eca49aab..2ccdd435a 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -51,6 +51,10 @@ code_change/3 ]). +%% hook handlers +-export([receive_packet/3, + receive_packet/4]). + -include("ejabberd.hrl"). -include("jlib.hrl"). @@ -165,6 +169,34 @@ stop(Host) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:call(Proc, stop). +receive_packet(From, To, {xmlelement, "presence", Attrs, Els}) -> + case xml:get_attr_s("type", Attrs) of + "probe" -> + ok; + "error" -> + ok; + "invisible" -> + ok; + "subscribe" -> + ok; + "subscribed" -> + ok; + "unsubscribe" -> + ok; + "unsubscribed" -> + ok; + "unavailable" -> + mod_caps:clear_caps(From); + _ -> + Caps = mod_caps:read_caps(Els), + mod_caps:note_caps(To#jid.lserver, From, Caps) + end; +receive_packet(_, _, _) -> + ok. + +receive_packet(_JID, From, To, Packet) -> + receive_packet(From, To, Packet). + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -181,6 +213,8 @@ init([Host, _Opts]) -> {type, bag}, {attributes, record_info(fields, user_caps_resources)}]), mnesia:delete_table(user_caps_default), + ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, receive_packet, 30), + ejabberd_hooks:add(s2s_receive_packet, Host, ?MODULE, receive_packet, 30), {ok, #state{host = Host}}. maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) -> @@ -359,7 +393,10 @@ handle_disco_response(From, To, IQ) -> handle_info(_Info, State) -> {noreply, State}. -terminate(_Reason, _State) -> +terminate(_Reason, State) -> + Host = State#state.host, + ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, receive_packet, 30), + ejabberd_hooks:delete(s2s_receive_packet, Host, ?MODULE, receive_packet, 30), ok. code_change(_OldVsn, State, _Extra) -> diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index fcb918bb8..bcbb2bfe4 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -157,6 +157,7 @@ init([ServerHost, Opts]) -> ?DEBUG("pubsub init ~p ~p",[ServerHost,Opts]), Host = gen_mod:get_opt_host(ServerHost, Opts, "pubsub.@HOST@"), Access = gen_mod:get_opt(access_createnode, Opts, all), + IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), mod_disco:register_feature(ServerHost, ?NS_PUBSUB), ejabberd_hooks:add(disco_sm_identity, ServerHost, ?MODULE, disco_sm_identity, 75), ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75), @@ -164,14 +165,8 @@ init([ServerHost, Opts]) -> ejabberd_hooks:add(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50), ejabberd_hooks:add(roster_out_subscription, ServerHost, ?MODULE, out_subscription, 50), ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, remove_user, 50), - IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), - lists:foreach( - fun({NS,Mod,Fun}) -> - gen_iq_handler:add_iq_handler( - Mod, ServerHost, NS, ?MODULE, Fun, IQDisc) - end, - [{?NS_PUBSUB, ejabberd_sm, iq_sm}, - {?NS_PUBSUB_OWNER, ejabberd_sm, iq_sm}]), + gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, ?NS_PUBSUB, ?MODULE, iq_sm, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, ?NS_PUBSUB_OWNER, ?MODULE, iq_sm, IQDisc), ejabberd_router:register_route(Host), {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts), case lists:member("pep", Plugins) of @@ -179,13 +174,8 @@ init([ServerHost, Opts]) -> ejabberd_hooks:add(disco_local_identity, ServerHost, ?MODULE, disco_local_identity, 75), ejabberd_hooks:add(disco_local_features, ServerHost, ?MODULE, disco_local_features, 75), ejabberd_hooks:add(disco_local_items, ServerHost, ?MODULE, disco_local_items, 75), - lists:foreach( - fun({NS,Mod,Fun}) -> - gen_iq_handler:add_iq_handler( - Mod, ServerHost, NS, ?MODULE, Fun, IQDisc) - end, - [{?NS_PUBSUB, ejabberd_local, iq_local}, - {?NS_PUBSUB_OWNER, ejabberd_local, iq_local}]); + gen_iq_handler:add_iq_handler(ejabberd_local, ServerHost, ?NS_PUBSUB, ?MODULE, iq_local, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, ServerHost, ?NS_PUBSUB_OWNER, ?MODULE, iq_local, IQDisc); false -> ok end, @@ -613,21 +603,24 @@ terminate(_Reason, #state{host = Host, plugins = Plugins}) -> terminate_plugins(Host, ServerHost, Plugins, TreePlugin), ejabberd_router:unregister_route(Host), - ejabberd_hooks:delete(disco_local_identity, ServerHost, ?MODULE, disco_local_identity, 75), - ejabberd_hooks:delete(disco_local_features, ServerHost, ?MODULE, disco_local_features, 75), - ejabberd_hooks:delete(disco_local_items, ServerHost, ?MODULE, disco_local_items, 75), + case lists:member("pep", Plugins) of + true -> + ejabberd_hooks:delete(disco_local_identity, ServerHost, ?MODULE, disco_local_identity, 75), + ejabberd_hooks:delete(disco_local_features, ServerHost, ?MODULE, disco_local_features, 75), + ejabberd_hooks:delete(disco_local_items, ServerHost, ?MODULE, disco_local_items, 75), + gen_iq_handler:remove_iq_handler(ejabberd_local, ServerHost, ?NS_PUBSUB), + gen_iq_handler:remove_iq_handler(ejabberd_local, ServerHost, ?NS_PUBSUB_OWNER); + false -> + ok + end, ejabberd_hooks:delete(disco_sm_identity, ServerHost, ?MODULE, disco_sm_identity, 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(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50), ejabberd_hooks:delete(roster_out_subscription, ServerHost, ?MODULE, out_subscription, 50), ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, remove_user, 50), - lists:foreach(fun({NS,Mod}) -> - gen_iq_handler:remove_iq_handler(Mod, ServerHost, NS) - end, [{?NS_PUBSUB, ejabberd_local}, - {?NS_PUBSUB_OWNER, ejabberd_local}, - {?NS_PUBSUB, ejabberd_sm}, - {?NS_PUBSUB_OWNER, ejabberd_sm}]), + gen_iq_handler:remove_iq_handler(ejabberd_sm, ServerHost, ?NS_PUBSUB), + gen_iq_handler:remove_iq_handler(ejabberd_sm, ServerHost, ?NS_PUBSUB_OWNER), mod_disco:unregister_feature(ServerHost, ?NS_PUBSUB), ok. @@ -1553,12 +1546,12 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> PayloadSize > PayloadMaxSize -> %% Entity attempts to publish very large payload {error, extended_error(?ERR_NOT_ACCEPTABLE, "payload-too-big")}; - PayloadCount =/= 1 -> - %% Entity attempts to publish item with multiple payload elements - {error, extended_error(?ERR_BAD_REQUEST, "invalid-payload")}; - Payload == "" -> %% TODO better use PayloadSize == 0 ? + PayloadCount == 0 -> %% Publisher attempts to publish to payload node with no payload {error, extended_error(?ERR_BAD_REQUEST, "payload-required")}; + PayloadCount > 1 -> + %% Entity attempts to publish item with multiple payload elements + {error, extended_error(?ERR_BAD_REQUEST, "invalid-payload")}; (DeliverPayloads == 0) and (PersistItems == 0) and (PayloadSize > 0) -> %% Publisher attempts to publish to transient notification node with item {error, extended_error(?ERR_BAD_REQUEST, "item-forbidden")};