aboutsummaryrefslogtreecommitdiff
path: root/src/mod_disco.erl
diff options
context:
space:
mode:
authorBadlop <badlop@process-one.net>2013-03-14 10:33:02 +0100
committerBadlop <badlop@process-one.net>2013-03-14 10:33:02 +0100
commit9deb294328bb3f9eb6bd2c0e7cd500732e9b5830 (patch)
tree7e1066c130250627ee0abab44a135f583a28d07f /src/mod_disco.erl
parentlist_to_integer/2 only works in OTP R14 and newer (diff)
Accumulated patch to binarize and indent code
Diffstat (limited to '')
-rw-r--r--src/mod_disco.erl683
1 files changed, 353 insertions, 330 deletions
diff --git a/src/mod_disco.erl b/src/mod_disco.erl
index 3d623e2b6..c883e0782 100644
--- a/src/mod_disco.erl
+++ b/src/mod_disco.erl
@@ -25,446 +25,469 @@
%%%----------------------------------------------------------------------
-module(mod_disco).
+
-author('alexey@process-one.net').
-behaviour(gen_mod).
--export([start/2,
- stop/1,
- process_local_iq_items/3,
- process_local_iq_info/3,
- get_local_identity/5,
- get_local_features/5,
- get_local_services/5,
- process_sm_iq_items/3,
- process_sm_iq_info/3,
- get_sm_identity/5,
- get_sm_features/5,
- get_sm_items/5,
- get_info/5,
- register_feature/2,
- unregister_feature/2,
- register_extra_domain/2,
- unregister_extra_domain/2]).
+-export([start/2, stop/1, process_local_iq_items/3,
+ process_local_iq_info/3, get_local_identity/5,
+ get_local_features/5, get_local_services/5,
+ process_sm_iq_items/3, process_sm_iq_info/3,
+ get_sm_identity/5, get_sm_features/5, get_sm_items/5,
+ get_info/5, register_feature/2, unregister_feature/2,
+ register_extra_domain/2, unregister_extra_domain/2]).
-include("ejabberd.hrl").
+
-include("jlib.hrl").
+
-include("mod_roster.hrl").
start(Host, Opts) ->
ejabberd_local:refresh_iq_handlers(),
-
- IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
- ?MODULE, process_local_iq_items, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
- ?MODULE, process_local_iq_info, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS,
- ?MODULE, process_sm_iq_items, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_DISCO_INFO,
- ?MODULE, process_sm_iq_info, IQDisc),
-
- catch ets:new(disco_features, [named_table, ordered_set, public]),
- register_feature(Host, "iq"),
- register_feature(Host, "presence"),
- register_feature(Host, "presence-invisible"),
-
- catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
- ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
- lists:foreach(fun(Domain) -> register_extra_domain(Host, Domain) end,
+ IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
+ one_queue),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_ITEMS, ?MODULE,
+ process_local_iq_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_INFO, ?MODULE,
+ process_local_iq_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_ITEMS, ?MODULE, process_sm_iq_items,
+ IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_INFO, ?MODULE, process_sm_iq_info,
+ IQDisc),
+ catch ets:new(disco_features,
+ [named_table, ordered_set, public]),
+ register_feature(Host, <<"iq">>),
+ register_feature(Host, <<"presence">>),
+ catch ets:new(disco_extra_domains,
+ [named_table, ordered_set, public]),
+ ExtraDomains = gen_mod:get_opt(extra_domains, Opts,
+ fun(Hs) ->
+ [iolist_to_binary(H) || H <- Hs]
+ end, []),
+ lists:foreach(fun (Domain) ->
+ register_extra_domain(Host, Domain)
+ end,
ExtraDomains),
- catch ets:new(disco_sm_features, [named_table, ordered_set, public]),
- catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]),
- ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_services, 100),
- ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 100),
- ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 100),
- ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 100),
- ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 100),
- ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100),
- ejabberd_hooks:add(disco_info, Host, ?MODULE, get_info, 100),
+ catch ets:new(disco_sm_features,
+ [named_table, ordered_set, public]),
+ catch ets:new(disco_sm_nodes,
+ [named_table, ordered_set, public]),
+ ejabberd_hooks:add(disco_local_items, Host, ?MODULE,
+ get_local_services, 100),
+ ejabberd_hooks:add(disco_local_features, Host, ?MODULE,
+ get_local_features, 100),
+ ejabberd_hooks:add(disco_local_identity, Host, ?MODULE,
+ get_local_identity, 100),
+ ejabberd_hooks:add(disco_sm_items, Host, ?MODULE,
+ get_sm_items, 100),
+ ejabberd_hooks:add(disco_sm_features, Host, ?MODULE,
+ get_sm_features, 100),
+ ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE,
+ get_sm_identity, 100),
+ ejabberd_hooks:add(disco_info, Host, ?MODULE, get_info,
+ 100),
ok.
stop(Host) ->
- ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100),
- ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 100),
- ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 100),
- ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 100),
- ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 100),
- ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_services, 100),
- ejabberd_hooks:delete(disco_info, Host, ?MODULE, get_info, 100),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_INFO),
+ ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE,
+ get_sm_identity, 100),
+ ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE,
+ get_sm_features, 100),
+ ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE,
+ get_sm_items, 100),
+ ejabberd_hooks:delete(disco_local_identity, Host,
+ ?MODULE, get_local_identity, 100),
+ ejabberd_hooks:delete(disco_local_features, Host,
+ ?MODULE, get_local_features, 100),
+ ejabberd_hooks:delete(disco_local_items, Host, ?MODULE,
+ get_local_services, 100),
+ ejabberd_hooks:delete(disco_info, Host, ?MODULE,
+ get_info, 100),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_INFO),
catch ets:match_delete(disco_features, {{'_', Host}}),
- catch ets:match_delete(disco_extra_domains, {{'_', Host}}),
+ catch ets:match_delete(disco_extra_domains,
+ {{'_', Host}}),
ok.
-
register_feature(Host, Feature) ->
- catch ets:new(disco_features, [named_table, ordered_set, public]),
+ catch ets:new(disco_features,
+ [named_table, ordered_set, public]),
ets:insert(disco_features, {{Feature, Host}}).
unregister_feature(Host, Feature) ->
- catch ets:new(disco_features, [named_table, ordered_set, public]),
+ catch ets:new(disco_features,
+ [named_table, ordered_set, public]),
ets:delete(disco_features, {Feature, Host}).
register_extra_domain(Host, Domain) ->
- catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
+ catch ets:new(disco_extra_domains,
+ [named_table, ordered_set, public]),
ets:insert(disco_extra_domains, {{Domain, Host}}).
unregister_extra_domain(Host, Domain) ->
- catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
+ catch ets:new(disco_extra_domains,
+ [named_table, ordered_set, public]),
ets:delete(disco_extra_domains, {Domain, Host}).
-process_local_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
+process_local_iq_items(From, To,
+ #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
- set ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
- get ->
- Node = xml:get_tag_attr_s("node", SubEl),
- Host = To#jid.lserver,
-
- case ejabberd_hooks:run_fold(disco_local_items,
- Host,
- empty,
- [From, To, Node, Lang]) of
- {result, Items} ->
- ANode = case Node of
- "" -> [];
- _ -> [{"node", Node}]
- end,
- IQ#iq{type = result,
- sub_el = [{xmlelement, "query",
- [{"xmlns", ?NS_DISCO_ITEMS} | ANode],
- Items
- }]};
- {error, Error} ->
- IQ#iq{type = error, sub_el = [SubEl, Error]}
- end
+ set ->
+ IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ get ->
+ Node = xml:get_tag_attr_s(<<"node">>, SubEl),
+ Host = To#jid.lserver,
+ case ejabberd_hooks:run_fold(disco_local_items, Host,
+ empty, [From, To, Node, Lang])
+ of
+ {result, Items} ->
+ ANode = case Node of
+ <<"">> -> [];
+ _ -> [{<<"node">>, Node}]
+ end,
+ IQ#iq{type = result,
+ sub_el =
+ [#xmlel{name = <<"query">>,
+ attrs =
+ [{<<"xmlns">>, ?NS_DISCO_ITEMS} | ANode],
+ children = Items}]};
+ {error, Error} ->
+ IQ#iq{type = error, sub_el = [SubEl, Error]}
+ end
end.
-
-process_local_iq_info(From, To, #iq{type = Type, lang = Lang,
- sub_el = SubEl} = IQ) ->
+process_local_iq_info(From, To,
+ #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
- set ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
- get ->
- Host = To#jid.lserver,
- Node = xml:get_tag_attr_s("node", SubEl),
- Identity = ejabberd_hooks:run_fold(disco_local_identity,
- Host,
- [],
- [From, To, Node, Lang]),
- Info = ejabberd_hooks:run_fold(disco_info, Host, [],
- [Host, ?MODULE, Node, Lang]),
- case ejabberd_hooks:run_fold(disco_local_features,
- Host,
- empty,
- [From, To, Node, Lang]) of
- {result, Features} ->
- ANode = case Node of
- "" -> [];
- _ -> [{"node", Node}]
- end,
- IQ#iq{type = result,
- sub_el = [{xmlelement, "query",
- [{"xmlns", ?NS_DISCO_INFO} | ANode],
- Identity ++
- Info ++
- features_to_xml(Features)
- }]};
- {error, Error} ->
- IQ#iq{type = error, sub_el = [SubEl, Error]}
- end
+ set ->
+ IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ get ->
+ Host = To#jid.lserver,
+ Node = xml:get_tag_attr_s(<<"node">>, SubEl),
+ Identity = ejabberd_hooks:run_fold(disco_local_identity,
+ Host, [], [From, To, Node, Lang]),
+ Info = ejabberd_hooks:run_fold(disco_info, Host, [],
+ [Host, ?MODULE, Node, Lang]),
+ case ejabberd_hooks:run_fold(disco_local_features, Host,
+ empty, [From, To, Node, Lang])
+ of
+ {result, Features} ->
+ ANode = case Node of
+ <<"">> -> [];
+ _ -> [{<<"node">>, Node}]
+ end,
+ IQ#iq{type = result,
+ sub_el =
+ [#xmlel{name = <<"query">>,
+ attrs =
+ [{<<"xmlns">>, ?NS_DISCO_INFO} | ANode],
+ children =
+ Identity ++
+ Info ++ features_to_xml(Features)}]};
+ {error, Error} ->
+ IQ#iq{type = error, sub_el = [SubEl, Error]}
+ end
end.
-get_local_identity(Acc, _From, _To, [], _Lang) ->
- Acc ++ [{xmlelement, "identity",
- [{"category", "server"},
- {"type", "im"},
- {"name", "ejabberd"}], []}];
-
+get_local_identity(Acc, _From, _To, <<>>, _Lang) ->
+ Acc ++
+ [#xmlel{name = <<"identity">>,
+ attrs =
+ [{<<"category">>, <<"server">>}, {<<"type">>, <<"im">>},
+ {<<"name">>, <<"ejabberd">>}],
+ children = []}];
get_local_identity(Acc, _From, _To, _Node, _Lang) ->
Acc.
-get_local_features({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
+get_local_features({error, _Error} = Acc, _From, _To,
+ _Node, _Lang) ->
Acc;
-
-get_local_features(Acc, _From, To, [], _Lang) ->
+get_local_features(Acc, _From, To, <<>>, _Lang) ->
Feats = case Acc of
- {result, Features} -> Features;
- empty -> []
+ {result, Features} -> Features;
+ empty -> []
end,
Host = To#jid.lserver,
{result,
- ets:select(disco_features, [{{{'_', Host}}, [], ['$_']}]) ++ Feats};
-
+ ets:select(disco_features,
+ [{{{'_', Host}}, [], ['$_']}])
+ ++ Feats};
get_local_features(Acc, _From, _To, _Node, _Lang) ->
case Acc of
- {result, _Features} ->
- Acc;
- empty ->
- {error, ?ERR_ITEM_NOT_FOUND}
+ {result, _Features} -> Acc;
+ empty -> {error, ?ERR_ITEM_NOT_FOUND}
end.
-
features_to_xml(FeatureList) ->
- %% Avoid duplicating features
- [{xmlelement, "feature", [{"var", Feat}], []} ||
- Feat <- lists:usort(
- lists:map(
- fun({{Feature, _Host}}) ->
- Feature;
- (Feature) when is_list(Feature) ->
- Feature
- end, FeatureList))].
+ [#xmlel{name = <<"feature">>,
+ attrs = [{<<"var">>, Feat}], children = []}
+ || Feat
+ <- lists:usort(lists:map(fun ({{Feature, _Host}}) ->
+ Feature;
+ (Feature) when is_binary(Feature) ->
+ Feature
+ end,
+ FeatureList))].
domain_to_xml({Domain}) ->
- {xmlelement, "item", [{"jid", Domain}], []};
+ #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Domain}],
+ children = []};
domain_to_xml(Domain) ->
- {xmlelement, "item", [{"jid", Domain}], []}.
+ #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Domain}],
+ children = []}.
-get_local_services({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
+get_local_services({error, _Error} = Acc, _From, _To,
+ _Node, _Lang) ->
Acc;
-
-get_local_services(Acc, _From, To, [], _Lang) ->
+get_local_services(Acc, _From, To, <<>>, _Lang) ->
Items = case Acc of
- {result, Its} -> Its;
- empty -> []
+ {result, Its} -> Its;
+ empty -> []
end,
Host = To#jid.lserver,
{result,
- lists:usort(
- lists:map(fun domain_to_xml/1,
- get_vh_services(Host) ++
- ets:select(disco_extra_domains,
- [{{{'$1', Host}}, [], ['$1']}]))
- ) ++ Items};
-
-get_local_services({result, _} = Acc, _From, _To, _Node, _Lang) ->
+ lists:usort(lists:map(fun domain_to_xml/1,
+ get_vh_services(Host) ++
+ ets:select(disco_extra_domains,
+ [{{{'$1', Host}}, [], ['$1']}])))
+ ++ Items};
+get_local_services({result, _} = Acc, _From, _To, _Node,
+ _Lang) ->
Acc;
-
get_local_services(empty, _From, _To, _Node, _Lang) ->
{error, ?ERR_ITEM_NOT_FOUND}.
get_vh_services(Host) ->
- Hosts = lists:sort(fun(H1, H2) -> length(H1) >= length(H2) end, ?MYHOSTS),
- lists:filter(fun(H) ->
- case lists:dropwhile(
- fun(VH) ->
- not lists:suffix("." ++ VH, H)
- end, Hosts) of
- [] ->
- false;
- [VH | _] ->
- VH == Host
+ Hosts = lists:sort(fun (H1, H2) ->
+ byte_size(H1) >= byte_size(H2)
+ end,
+ ?MYHOSTS),
+ lists:filter(fun (H) ->
+ case lists:dropwhile(fun (VH) ->
+ not
+ str:suffix(
+ <<".", VH/binary>>,
+ H)
+ end,
+ Hosts)
+ of
+ [] -> false;
+ [VH | _] -> VH == Host
end
- end, ejabberd_router:dirty_get_all_routes()).
+ end,
+ ejabberd_router:dirty_get_all_routes()).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-process_sm_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
+process_sm_iq_items(From, To,
+ #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
- set ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
- get ->
- case is_presence_subscribed(From, To) of
- true ->
- Host = To#jid.lserver,
- Node = xml:get_tag_attr_s("node", SubEl),
- case ejabberd_hooks:run_fold(disco_sm_items,
- Host,
- empty,
- [From, To, Node, Lang]) of
- {result, Items} ->
- ANode = case Node of
- "" -> [];
- _ -> [{"node", Node}]
- end,
- IQ#iq{type = result,
- sub_el = [{xmlelement, "query",
- [{"xmlns", ?NS_DISCO_ITEMS} | ANode],
- Items
- }]};
- {error, Error} ->
- IQ#iq{type = error, sub_el = [SubEl, Error]}
- end;
- false ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}
- end
+ set ->
+ IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ get ->
+ case is_presence_subscribed(From, To) of
+ true ->
+ Host = To#jid.lserver,
+ Node = xml:get_tag_attr_s(<<"node">>, SubEl),
+ case ejabberd_hooks:run_fold(disco_sm_items, Host,
+ empty, [From, To, Node, Lang])
+ of
+ {result, Items} ->
+ ANode = case Node of
+ <<"">> -> [];
+ _ -> [{<<"node">>, Node}]
+ end,
+ IQ#iq{type = result,
+ sub_el =
+ [#xmlel{name = <<"query">>,
+ attrs =
+ [{<<"xmlns">>, ?NS_DISCO_ITEMS}
+ | ANode],
+ children = Items}]};
+ {error, Error} ->
+ IQ#iq{type = error, sub_el = [SubEl, Error]}
+ end;
+ false ->
+ IQ#iq{type = error,
+ sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}
+ end
end.
-get_sm_items({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
+get_sm_items({error, _Error} = Acc, _From, _To, _Node,
+ _Lang) ->
Acc;
-
get_sm_items(Acc, From,
- #jid{user = User, server = Server} = To,
- [], _Lang) ->
+ #jid{user = User, server = Server} = To, <<>>, _Lang) ->
Items = case Acc of
- {result, Its} -> Its;
- empty -> []
+ {result, Its} -> Its;
+ empty -> []
end,
Items1 = case is_presence_subscribed(From, To) of
- true ->
- get_user_resources(User, Server);
- _ ->
- []
- end,
+ true -> get_user_resources(User, Server);
+ _ -> []
+ end,
{result, Items ++ Items1};
-
-get_sm_items({result, _} = Acc, _From, _To, _Node, _Lang) ->
+get_sm_items({result, _} = Acc, _From, _To, _Node,
+ _Lang) ->
Acc;
-
get_sm_items(empty, From, To, _Node, _Lang) ->
#jid{luser = LFrom, lserver = LSFrom} = From,
#jid{luser = LTo, lserver = LSTo} = To,
case {LFrom, LSFrom} of
- {LTo, LSTo} ->
- {error, ?ERR_ITEM_NOT_FOUND};
- _ ->
- {error, ?ERR_NOT_ALLOWED}
+ {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND};
+ _ -> {error, ?ERR_NOT_ALLOWED}
end.
-is_presence_subscribed(#jid{luser=User, lserver=Server}, #jid{luser=LUser, lserver=LServer}) ->
- lists:any(fun(#roster{jid = {TUser, TServer, _}, subscription = S}) ->
- if
- LUser == TUser, LServer == TServer, S/=none ->
- true;
- true ->
- false
- end
- end,
- ejabberd_hooks:run_fold(roster_get, Server, [], [{User, Server}]))
- orelse User == LUser andalso Server == LServer.
-
-process_sm_iq_info(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
+is_presence_subscribed(#jid{luser = User,
+ lserver = Server},
+ #jid{luser = LUser, lserver = LServer}) ->
+ lists:any(fun (#roster{jid = {TUser, TServer, _},
+ subscription = S}) ->
+ if LUser == TUser, LServer == TServer, S /= none ->
+ true;
+ true -> false
+ end
+ end,
+ ejabberd_hooks:run_fold(roster_get, Server, [],
+ [{User, Server}]))
+ orelse User == LUser andalso Server == LServer.
+
+process_sm_iq_info(From, To,
+ #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
- set ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
- get ->
- case is_presence_subscribed(From, To) of
- true ->
- Host = To#jid.lserver,
- Node = xml:get_tag_attr_s("node", SubEl),
- Identity = ejabberd_hooks:run_fold(disco_sm_identity,
- Host,
- [],
- [From, To, Node, Lang]),
- case ejabberd_hooks:run_fold(disco_sm_features,
- Host,
- empty,
- [From, To, Node, Lang]) of
- {result, Features} ->
- ANode = case Node of
- "" -> [];
- _ -> [{"node", Node}]
- end,
- IQ#iq{type = result,
- sub_el = [{xmlelement, "query",
- [{"xmlns", ?NS_DISCO_INFO} | ANode],
- Identity ++
- features_to_xml(Features)
- }]};
- {error, Error} ->
- IQ#iq{type = error, sub_el = [SubEl, Error]}
- end;
- false ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}
- end
- end.
-
-get_sm_identity(Acc, _From, #jid{luser = LUser, lserver=LServer}, _Node, _Lang) ->
- Acc ++ case ejabberd_auth:is_user_exists(LUser, LServer) of
- true ->
- [{xmlelement, "identity", [{"category", "account"},
- {"type", "registered"}], []}];
- _ ->
- []
+ set ->
+ IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ get ->
+ case is_presence_subscribed(From, To) of
+ true ->
+ Host = To#jid.lserver,
+ Node = xml:get_tag_attr_s(<<"node">>, SubEl),
+ Identity = ejabberd_hooks:run_fold(disco_sm_identity,
+ Host, [],
+ [From, To, Node, Lang]),
+ case ejabberd_hooks:run_fold(disco_sm_features, Host,
+ empty, [From, To, Node, Lang])
+ of
+ {result, Features} ->
+ ANode = case Node of
+ <<"">> -> [];
+ _ -> [{<<"node">>, Node}]
+ end,
+ IQ#iq{type = result,
+ sub_el =
+ [#xmlel{name = <<"query">>,
+ attrs =
+ [{<<"xmlns">>, ?NS_DISCO_INFO}
+ | ANode],
+ children =
+ Identity ++
+ features_to_xml(Features)}]};
+ {error, Error} ->
+ IQ#iq{type = error, sub_el = [SubEl, Error]}
+ end;
+ false ->
+ IQ#iq{type = error,
+ sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}
+ end
end.
+get_sm_identity(Acc, _From,
+ #jid{luser = LUser, lserver = LServer}, _Node, _Lang) ->
+ Acc ++
+ case ejabberd_auth:is_user_exists(LUser, LServer) of
+ true ->
+ [#xmlel{name = <<"identity">>,
+ attrs =
+ [{<<"category">>, <<"account">>},
+ {<<"type">>, <<"registered">>}],
+ children = []}];
+ _ -> []
+ end.
get_sm_features(empty, From, To, _Node, _Lang) ->
#jid{luser = LFrom, lserver = LSFrom} = From,
#jid{luser = LTo, lserver = LSTo} = To,
case {LFrom, LSFrom} of
- {LTo, LSTo} ->
- {error, ?ERR_ITEM_NOT_FOUND};
- _ ->
- {error, ?ERR_NOT_ALLOWED}
+ {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND};
+ _ -> {error, ?ERR_NOT_ALLOWED}
end;
-
-get_sm_features(Acc, _From, _To, _Node, _Lang) ->
- Acc.
+get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc.
get_user_resources(User, Server) ->
Rs = ejabberd_sm:get_user_resources(User, Server),
- lists:map(fun(R) ->
- {xmlelement, "item",
- [{"jid", User ++ "@" ++ Server ++ "/" ++ R},
- {"name", User}], []}
- end, lists:sort(Rs)).
+ lists:map(fun (R) ->
+ #xmlel{name = <<"item">>,
+ attrs =
+ [{<<"jid">>,
+ <<User/binary, "@", Server/binary, "/",
+ R/binary>>},
+ {<<"name">>, User}],
+ children = []}
+ end,
+ lists:sort(Rs)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Support for: XEP-0157 Contact Addresses for XMPP Services
-get_info(_A, Host, Mod, Node, _Lang) when Node == [] ->
+get_info(_A, Host, Mod, Node, _Lang) when Node == <<>> ->
Module = case Mod of
- undefined ->
- ?MODULE;
- _ ->
- Mod
+ undefined -> ?MODULE;
+ _ -> Mod
end,
Serverinfo_fields = get_fields_xml(Host, Module),
- [{xmlelement, "x",
- [{"xmlns", ?NS_XDATA}, {"type", "result"}],
- [{xmlelement, "field",
- [{"var", "FORM_TYPE"}, {"type", "hidden"}],
- [{xmlelement, "value",
- [],
- [{xmlcdata, ?NS_SERVERINFO}]
- }]
- }]
- ++ Serverinfo_fields
- }];
-
-get_info(Acc, _, _, _Node, _) ->
- Acc.
+ [#xmlel{name = <<"x">>,
+ attrs =
+ [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}],
+ children =
+ [#xmlel{name = <<"field">>,
+ attrs =
+ [{<<"var">>, <<"FORM_TYPE">>},
+ {<<"type">>, <<"hidden">>}],
+ children =
+ [#xmlel{name = <<"value">>, attrs = [],
+ children = [{xmlcdata, ?NS_SERVERINFO}]}]}]
+ ++ Serverinfo_fields}];
+get_info(Acc, _, _, _Node, _) -> Acc.
get_fields_xml(Host, Module) ->
- Fields = gen_mod:get_module_opt(Host, ?MODULE, server_info, []),
-
- %% filter, and get only the ones allowed for this module
- Fields_good = lists:filter(
- fun({Modules, _, _}) ->
- case Modules of
- all -> true;
- Modules -> lists:member(Module, Modules)
- end
- end,
- Fields),
-
+ Fields = gen_mod:get_module_opt(Host, ?MODULE, server_info,
+ fun(L) when is_list(L) -> L end,
+ []),
+ Fields_good = lists:filter(fun ({Modules, _, _}) ->
+ case Modules of
+ all -> true;
+ Modules ->
+ lists:member(Module, Modules)
+ end
+ end,
+ Fields),
fields_to_xml(Fields_good).
fields_to_xml(Fields) ->
- [ field_to_xml(Field) || Field <- Fields].
+ [field_to_xml(Field) || Field <- Fields].
field_to_xml({_, Var, Values}) ->
Values_xml = values_to_xml(Values),
- {xmlelement, "field",
- [{"var", Var}],
- Values_xml
- }.
+ #xmlel{name = <<"field">>, attrs = [{<<"var">>, Var}],
+ children = Values_xml}.
values_to_xml(Values) ->
- lists:map(
- fun(Value) ->
- {xmlelement, "value",
- [],
- [{xmlcdata, Value}]
- }
- end,
- Values
- ).
+ lists:map(fun (Value) ->
+ #xmlel{name = <<"value">>, attrs = [],
+ children = [{xmlcdata, Value}]}
+ end,
+ Values).