_ ->
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",
%%%
%%%----------------------------------------------------------------------
+%%% @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').
item_to_xml/1,
webadmin_page/3,
webadmin_user/4,
+ get_versioning_feature/2,
roster_versioning_enabled/1,
roster_version/2]).
?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,
?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,
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,
[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
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)
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),
%%%
%%%----------------------------------------------------------------------
+%%% @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').
get_jid_info/4,
webadmin_page/3,
webadmin_user/4,
+ get_versioning_feature/2,
roster_versioning_enabled/1]).
-include("ejabberd.hrl").
?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,
?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,
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,
[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
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)
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),
+++ /dev/null
-%%%----------------------------------------------------------------------
-%%% File : mod_roster.erl
-%%% Author : Pablo Polvorin <pablo.polvorin@process-one.net>
-%%% Purpose : Common utility functions for XEP-0237 (Roster Versioning)
-%%% Created : 19 Jul 2009 by Pablo Polvorin <pablo.polvorin@process-one.net>
-%%%
-%%%
-%%% 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)).