From d6f3182731b5e8e58e1c5892467a9ef1c1d2f7d3 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 6 Aug 2009 21:06:16 +0000 Subject: [PATCH] Move functions from roster_versioning to mod_roster (EJAB-964) SVN Revision: 2429 --- src/ejabberd_c2s.erl | 6 +-- src/mod_roster.erl | 59 ++++++++++++++++++++++++++---- src/mod_roster_odbc.erl | 59 ++++++++++++++++++++++++++---- src/roster_versioning.erl | 77 --------------------------------------- 4 files changed, 105 insertions(+), 96 deletions(-) delete mode 100644 src/roster_versioning.erl diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index b929ed6e8..1c4a92bb8 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -326,11 +326,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> _ -> case StateData#state.resource of "" -> - RosterVersioningFeature = - case roster_versioning:is_enabled(Server) of - true -> [roster_versioning:stream_feature()]; - false -> [] - end, + RosterVersioningFeature = ejabberd_hooks:run_fold(roster_get_versioning_feature, Server, [], [Server]), StreamFeatures = [{xmlelement, "bind", [{"xmlns", ?NS_BIND}], []}, {xmlelement, "session", diff --git a/src/mod_roster.erl b/src/mod_roster.erl index dcceb610e..e73eb1207 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -24,6 +24,15 @@ %%% %%%---------------------------------------------------------------------- +%%% @doc Roster management (Mnesia storage). +%%% +%%% Includes support for XEP-0237: Roster Versioning. +%%% The roster versioning follows an all-or-nothing strategy: +%%% - If the version supplied by the client is the latest, return an empty response. +%%% - If not, return the entire new roster (with updated version string). +%%% Roster version is a hash digest of the entire roster. +%%% No additional data is stored in DB. + -module(mod_roster). -author('alexey@process-one.net'). @@ -43,6 +52,7 @@ item_to_xml/1, webadmin_page/3, webadmin_user/4, + get_versioning_feature/2, roster_versioning_enabled/1, roster_version/2]). @@ -79,6 +89,8 @@ start(Host, Opts) -> ?MODULE, remove_user, 50), ejabberd_hooks:add(resend_subscription_requests_hook, Host, ?MODULE, get_in_pending_subscriptions, 50), + ejabberd_hooks:add(roster_get_versioning_feature, Host, + ?MODULE, get_versioning_feature, 50), ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:add(webadmin_user, Host, @@ -103,6 +115,8 @@ stop(Host) -> ?MODULE, remove_user, 50), ejabberd_hooks:delete(resend_subscription_requests_hook, Host, ?MODULE, get_in_pending_subscriptions, 50), + ejabberd_hooks:delete(roster_get_versioning_feature, Host, + ?MODULE, get_versioning_feature, 50), ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:delete(webadmin_user, Host, @@ -110,12 +124,6 @@ stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER). -roster_versioning_enabled(Host) -> - gen_mod:get_module_opt(Host, ?MODULE, versioning, false). - -roster_version_on_db(Host) -> - gen_mod:get_module_opt(Host, ?MODULE, store_current_id, false). - process_iq(From, To, IQ) -> #iq{sub_el = SubEl} = IQ, #jid{lserver = LServer} = From, @@ -140,6 +148,24 @@ roster_hash(Items) -> [R#roster{groups = lists:sort(Grs)} || R = #roster{groups = Grs} <- Items]))). +roster_versioning_enabled(Host) -> + gen_mod:get_module_opt(Host, ?MODULE, versioning, false). + +roster_version_on_db(Host) -> + gen_mod:get_module_opt(Host, ?MODULE, store_current_id, false). + +%% Returns a list that may contain an xmlelement with the XEP-237 feature if it's enabled. +get_versioning_feature(Acc, Host) -> + case roster_versioning_enabled(Host) of + true -> + Feature = {xmlelement, + "ver", + [{"xmlns", ?NS_ROSTER_VER}], + [{xmlelement, "optional", [], []}]}, + [Feature | Acc]; + false -> [] + end. + roster_version(LServer ,LUser) -> US = {LUser, LServer}, case roster_version_on_db(LServer) of @@ -376,7 +402,7 @@ push_item(User, Server, From, Item) -> Item#roster.subscription}]}), case roster_versioning_enabled(Server) of true -> - roster_versioning:push_item(Server, User, From, Item, roster_version(Server, User)); + push_item_version(Server, User, From, Item, roster_version(Server, User)); false -> lists:foreach(fun(Resource) -> push_item(User, Server, Resource, From, Item) @@ -395,6 +421,25 @@ push_item(User, Server, Resource, From, Item) -> jlib:make_jid(User, Server, Resource), jlib:iq_to_xml(ResIQ)). +%% @doc Roster push, calculate and include the version attribute. +%% TODO: don't push to those who didn't load roster +push_item_version(Server, User, From, Item, RosterVersion) -> + lists:foreach(fun(Resource) -> + push_item_version(User, Server, Resource, From, Item, RosterVersion) + end, ejabberd_sm:get_user_resources(User, Server)). + +push_item_version(User, Server, Resource, From, Item, RosterVersion) -> + IQPush = #iq{type = 'set', xmlns = ?NS_ROSTER, + id = "push" ++ randoms:get_string(), + sub_el = [{xmlelement, "query", + [{"xmlns", ?NS_ROSTER}, + {"ver", RosterVersion}], + [item_to_xml(Item)]}]}, + ejabberd_router:route( + From, + jlib:make_jid(User, Server, Resource), + jlib:iq_to_xml(IQPush)). + get_subscription_lists(_, User, Server) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), diff --git a/src/mod_roster_odbc.erl b/src/mod_roster_odbc.erl index 418f3932f..9fb36bd9d 100644 --- a/src/mod_roster_odbc.erl +++ b/src/mod_roster_odbc.erl @@ -24,6 +24,15 @@ %%% %%%---------------------------------------------------------------------- +%%% @doc Roster management (Mnesia storage). +%%% +%%% Includes support for XEP-0237: Roster Versioning. +%%% The roster versioning follows an all-or-nothing strategy: +%%% - If the version supplied by the client is the latest, return an empty response. +%%% - If not, return the entire new roster (with updated version string). +%%% Roster version is a hash digest of the entire roster. +%%% No additional data is stored in DB. + -module(mod_roster_odbc). -author('alexey@process-one.net'). @@ -42,6 +51,7 @@ get_jid_info/4, webadmin_page/3, webadmin_user/4, + get_versioning_feature/2, roster_versioning_enabled/1]). -include("ejabberd.hrl"). @@ -69,6 +79,8 @@ start(Host, Opts) -> ?MODULE, remove_user, 50), ejabberd_hooks:add(resend_subscription_requests_hook, Host, ?MODULE, get_in_pending_subscriptions, 50), + ejabberd_hooks:add(roster_get_versioning_feature, Host, + ?MODULE, get_versioning_feature, 50), ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:add(webadmin_user, Host, @@ -93,6 +105,8 @@ stop(Host) -> ?MODULE, remove_user, 50), ejabberd_hooks:delete(resend_subscription_requests_hook, Host, ?MODULE, get_in_pending_subscriptions, 50), + ejabberd_hooks:delete(roster_get_versioning_feature, Host, + ?MODULE, get_versioning_feature, 50), ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:delete(webadmin_user, Host, @@ -100,12 +114,6 @@ stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER). -roster_versioning_enabled(Host) -> - gen_mod:get_module_opt(Host, ?MODULE, versioning, false). - -roster_version_on_db(Host) -> - gen_mod:get_module_opt(Host, ?MODULE, store_current_id, false). - process_iq(From, To, IQ) -> #iq{sub_el = SubEl} = IQ, #jid{lserver = LServer} = From, @@ -131,6 +139,24 @@ roster_hash(Items) -> [R#roster{groups = lists:sort(Grs)} || R = #roster{groups = Grs} <- Items]))). +roster_versioning_enabled(Host) -> + gen_mod:get_module_opt(Host, ?MODULE, versioning, false). + +roster_version_on_db(Host) -> + gen_mod:get_module_opt(Host, ?MODULE, store_current_id, false). + +%% Returns a list that may contain an xmlelement with the XEP-237 feature if it's enabled. +get_versioning_feature(Acc, Host) -> + case roster_versioning_enabled(Host) of + true -> + Feature = {xmlelement, + "ver", + [{"xmlns", ?NS_ROSTER_VER}], + [{xmlelement, "optional", [], []}]}, + [Feature | Acc]; + false -> [] + end. + roster_version(LServer ,LUser) -> US = {LUser, LServer}, case roster_version_on_db(LServer) of @@ -412,7 +438,7 @@ push_item(User, Server, From, Item) -> Item#roster.subscription}]}), case roster_versioning_enabled(Server) of true -> - roster_versioning:push_item(Server, User, From, Item, roster_version(Server, User)); + push_item_version(Server, User, From, Item, roster_version(Server, User)); false -> lists:foreach(fun(Resource) -> push_item(User, Server, Resource, From, Item) @@ -431,6 +457,25 @@ push_item(User, Server, Resource, From, Item) -> jlib:make_jid(User, Server, Resource), jlib:iq_to_xml(ResIQ)). +%% @doc Roster push, calculate and include the version attribute. +%% TODO: don't push to those who didn't load roster +push_item_version(Server, User, From, Item, RosterVersion) -> + lists:foreach(fun(Resource) -> + push_item_version(User, Server, Resource, From, Item, RosterVersion) + end, ejabberd_sm:get_user_resources(User, Server)). + +push_item_version(User, Server, Resource, From, Item, RosterVersion) -> + IQPush = #iq{type = 'set', xmlns = ?NS_ROSTER, + id = "push" ++ randoms:get_string(), + sub_el = [{xmlelement, "query", + [{"xmlns", ?NS_ROSTER}, + {"ver", RosterVersion}], + [item_to_xml(Item)]}]}, + ejabberd_router:route( + From, + jlib:make_jid(User, Server, Resource), + jlib:iq_to_xml(IQPush)). + get_subscription_lists(_, User, Server) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), diff --git a/src/roster_versioning.erl b/src/roster_versioning.erl deleted file mode 100644 index 6e2089fdd..000000000 --- a/src/roster_versioning.erl +++ /dev/null @@ -1,77 +0,0 @@ -%%%---------------------------------------------------------------------- -%%% File : mod_roster.erl -%%% Author : Pablo Polvorin -%%% Purpose : Common utility functions for XEP-0237 (Roster Versioning) -%%% Created : 19 Jul 2009 by Pablo Polvorin -%%% -%%% -%%% ejabberd, Copyright (C) 2009 ProcessOne -%%% -%%% This program is free software; you can redistribute it and/or -%%% modify it under the terms of the GNU General Public License as -%%% published by the Free Software Foundation; either version 2 of the -%%% License, or (at your option) any later version. -%%% -%%% This program is distributed in the hope that it will be useful, -%%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%%% General Public License for more details. -%%% -%%% You should have received a copy of the GNU General Public License -%%% along with this program; if not, write to the Free Software -%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -%%% 02111-1307 USA -%%% -%%% -%%% @doc The roster versioning follows an all-or-nothing strategy: -%%% - If the version supplied by the client is the lastest, return an empty response -%%% - If not, return the entire new roster (with updated version string). -%%% Roster version is a hash digest of the entire roster. -%%% No additional data is stored in DB. -%%%---------------------------------------------------------------------- --module(roster_versioning). --author('pablo.polvorin@process-one.net'). - -%%API --export([is_enabled/1, - stream_feature/0, - push_item/5]). - - --include("mod_roster.hrl"). --include("jlib.hrl"). - -%%@doc is roster versioning enabled? -is_enabled(Host) -> - case gen_mod:is_loaded(Host, mod_roster) of - true -> mod_roster:roster_versioning_enabled(Host); - false -> mod_roster_odbc:roster_versioning_enabled(Host) - end. - -stream_feature() -> - {xmlelement, - "ver", - [{"xmlns", ?NS_ROSTER_VER}], - [{xmlelement, "optional", [], []}]}. - - - - -%% @doc Roster push, calculate and include the version attribute. -%% TODO: don't push to those who didn't load roster -push_item(Server, User, From, Item, RosterVersion) -> - lists:foreach(fun(Resource) -> - push_item(User, Server, Resource, From, Item, RosterVersion) - end, ejabberd_sm:get_user_resources(User, Server)). - -push_item(User, Server, Resource, From, Item, RosterVersion) -> - IQPush = #iq{type = 'set', xmlns = ?NS_ROSTER, - id = "push" ++ randoms:get_string(), - sub_el = [{xmlelement, "query", - [{"xmlns", ?NS_ROSTER}, - {"ver", RosterVersion}], - [mod_roster:item_to_xml(Item)]}]}, - ejabberd_router:route( - From, - jlib:make_jid(User, Server, Resource), - jlib:iq_to_xml(IQPush)).