full support for XEP-0115 v1.5 (EJAB-1223) (EJAB-1189)
This commit is contained in:
parent
cce57310b0
commit
58590cf08d
|
@ -317,10 +317,10 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||||
[{xmlelement, "mechanisms",
|
[{xmlelement, "mechanisms",
|
||||||
[{"xmlns", ?NS_SASL}],
|
[{"xmlns", ?NS_SASL}],
|
||||||
Mechs}] ++
|
Mechs}] ++
|
||||||
ejabberd_hooks:run_fold(
|
ejabberd_hooks:run_fold(
|
||||||
c2s_stream_features,
|
c2s_stream_features,
|
||||||
Server,
|
Server,
|
||||||
[], [])}),
|
[], [Server])}),
|
||||||
fsm_next_state(wait_for_feature_request,
|
fsm_next_state(wait_for_feature_request,
|
||||||
StateData#state{
|
StateData#state{
|
||||||
server = Server,
|
server = Server,
|
||||||
|
@ -329,11 +329,20 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||||
_ ->
|
_ ->
|
||||||
case StateData#state.resource of
|
case StateData#state.resource of
|
||||||
"" ->
|
"" ->
|
||||||
RosterVersioningFeature = ejabberd_hooks:run_fold(roster_get_versioning_feature, Server, [], [Server]),
|
RosterVersioningFeature =
|
||||||
StreamFeatures = [{xmlelement, "bind",
|
ejabberd_hooks:run_fold(
|
||||||
[{"xmlns", ?NS_BIND}], []},
|
roster_get_versioning_feature,
|
||||||
{xmlelement, "session",
|
Server, [], [Server]),
|
||||||
[{"xmlns", ?NS_SESSION}], []} | RosterVersioningFeature],
|
StreamFeatures =
|
||||||
|
[{xmlelement, "bind",
|
||||||
|
[{"xmlns", ?NS_BIND}], []},
|
||||||
|
{xmlelement, "session",
|
||||||
|
[{"xmlns", ?NS_SESSION}], []}]
|
||||||
|
++ RosterVersioningFeature
|
||||||
|
++ ejabberd_hooks:run_fold(
|
||||||
|
c2s_stream_features,
|
||||||
|
Server,
|
||||||
|
[], [Server]),
|
||||||
send_element(
|
send_element(
|
||||||
StateData,
|
StateData,
|
||||||
{xmlelement, "stream:features", [],
|
{xmlelement, "stream:features", [],
|
||||||
|
|
|
@ -177,8 +177,9 @@ init([{SockMod, Socket}, Opts]) ->
|
||||||
wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||||
case {xml:get_attr_s("xmlns", Attrs),
|
case {xml:get_attr_s("xmlns", Attrs),
|
||||||
xml:get_attr_s("xmlns:db", Attrs),
|
xml:get_attr_s("xmlns:db", Attrs),
|
||||||
|
xml:get_attr_s("to", Attrs),
|
||||||
xml:get_attr_s("version", Attrs) == "1.0"} of
|
xml:get_attr_s("version", Attrs) == "1.0"} of
|
||||||
{"jabber:server", _, true} when
|
{"jabber:server", _, Server, true} when
|
||||||
StateData#state.tls and (not StateData#state.authenticated) ->
|
StateData#state.tls and (not StateData#state.authenticated) ->
|
||||||
send_text(StateData, ?STREAM_HEADER(" version='1.0'")),
|
send_text(StateData, ?STREAM_HEADER(" version='1.0'")),
|
||||||
SASL =
|
SASL =
|
||||||
|
@ -212,15 +213,23 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||||
end,
|
end,
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "stream:features", [],
|
{xmlelement, "stream:features", [],
|
||||||
SASL ++ StartTLS}),
|
SASL ++ StartTLS ++
|
||||||
|
ejabberd_hooks:run_fold(
|
||||||
|
s2s_stream_features,
|
||||||
|
Server,
|
||||||
|
[], [Server])}),
|
||||||
{next_state, wait_for_feature_request, StateData};
|
{next_state, wait_for_feature_request, StateData};
|
||||||
{"jabber:server", _, true} when
|
{"jabber:server", _, Server, true} when
|
||||||
StateData#state.authenticated ->
|
StateData#state.authenticated ->
|
||||||
send_text(StateData, ?STREAM_HEADER(" version='1.0'")),
|
send_text(StateData, ?STREAM_HEADER(" version='1.0'")),
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "stream:features", [], []}),
|
{xmlelement, "stream:features", [],
|
||||||
|
ejabberd_hooks:run_fold(
|
||||||
|
s2s_stream_features,
|
||||||
|
Server,
|
||||||
|
[], [Server])}),
|
||||||
{next_state, stream_established, StateData};
|
{next_state, stream_established, StateData};
|
||||||
{"jabber:server", "jabber:server:dialback", _} ->
|
{"jabber:server", "jabber:server:dialback", _Server, _} ->
|
||||||
send_text(StateData, ?STREAM_HEADER("")),
|
send_text(StateData, ?STREAM_HEADER("")),
|
||||||
{next_state, stream_established, StateData};
|
{next_state, stream_established, StateData};
|
||||||
_ ->
|
_ ->
|
||||||
|
|
194
src/mod_caps.erl
194
src/mod_caps.erl
|
@ -33,6 +33,10 @@
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([read_caps/1,
|
-export([read_caps/1,
|
||||||
|
caps_stream_features/2,
|
||||||
|
disco_features/5,
|
||||||
|
disco_identity/5,
|
||||||
|
disco_info/5,
|
||||||
get_features/1]).
|
get_features/1]).
|
||||||
|
|
||||||
%% gen_mod callbacks
|
%% gen_mod callbacks
|
||||||
|
@ -56,7 +60,7 @@
|
||||||
|
|
||||||
-define(PROCNAME, ejabberd_mod_caps).
|
-define(PROCNAME, ejabberd_mod_caps).
|
||||||
|
|
||||||
-record(caps, {node, version, exts}).
|
-record(caps, {node, version, hash, exts}).
|
||||||
-record(caps_features, {node_pair, features = []}).
|
-record(caps_features, {node_pair, features = []}).
|
||||||
|
|
||||||
-record(state, {host}).
|
-record(state, {host}).
|
||||||
|
@ -115,8 +119,10 @@ read_caps([{xmlelement, "c", Attrs, _Els} | Tail], Result) ->
|
||||||
?NS_CAPS ->
|
?NS_CAPS ->
|
||||||
Node = xml:get_attr_s("node", Attrs),
|
Node = xml:get_attr_s("node", Attrs),
|
||||||
Version = xml:get_attr_s("ver", Attrs),
|
Version = xml:get_attr_s("ver", Attrs),
|
||||||
|
Hash = xml:get_attr_s("hash", Attrs),
|
||||||
Exts = string:tokens(xml:get_attr_s("ext", Attrs), " "),
|
Exts = string:tokens(xml:get_attr_s("ext", Attrs), " "),
|
||||||
read_caps(Tail, #caps{node = Node, version = Version, exts = Exts});
|
read_caps(Tail, #caps{node = Node, hash = Hash,
|
||||||
|
version = Version, exts = Exts});
|
||||||
_ ->
|
_ ->
|
||||||
read_caps(Tail, Result)
|
read_caps(Tail, Result)
|
||||||
end;
|
end;
|
||||||
|
@ -152,6 +158,41 @@ user_send_packet(#jid{luser = User, lserver = Server} = From,
|
||||||
user_send_packet(_From, _To, _Packet) ->
|
user_send_packet(_From, _To, _Packet) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
caps_stream_features(Acc, MyHost) ->
|
||||||
|
case make_my_disco_hash(MyHost) of
|
||||||
|
"" ->
|
||||||
|
Acc;
|
||||||
|
Hash ->
|
||||||
|
[{xmlelement, "c", [{"xmlns", ?NS_CAPS},
|
||||||
|
{"hash", "sha-1"},
|
||||||
|
{"node", ?EJABBERD_URI},
|
||||||
|
{"ver", Hash}], []} | Acc]
|
||||||
|
end.
|
||||||
|
|
||||||
|
disco_features(_Acc, From, To, ?EJABBERD_URI ++ "#" ++ [_|_], Lang) ->
|
||||||
|
ejabberd_hooks:run_fold(disco_local_features,
|
||||||
|
To#jid.lserver,
|
||||||
|
empty,
|
||||||
|
[From, To, "", Lang]);
|
||||||
|
disco_features(Acc, _From, _To, _Node, _Lang) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
|
disco_identity(_Acc, From, To, ?EJABBERD_URI ++ "#" ++ [_|_], Lang) ->
|
||||||
|
ejabberd_hooks:run_fold(disco_local_identity,
|
||||||
|
To#jid.lserver,
|
||||||
|
[],
|
||||||
|
[From, To, "", Lang]);
|
||||||
|
disco_identity(Acc, _From, _To, _Node, _Lang) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
|
disco_info(_Acc, Host, Module, ?EJABBERD_URI ++ "#" ++ [_|_], Lang) ->
|
||||||
|
ejabberd_hooks:run_fold(disco_info,
|
||||||
|
Host,
|
||||||
|
[],
|
||||||
|
[Host, Module, "", Lang]);
|
||||||
|
disco_info(Acc, _Host, _Module, _Node, _Lang) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
|
@ -163,6 +204,16 @@ init([Host, _Opts]) ->
|
||||||
mnesia:add_table_copy(caps_features, node(), disc_copies),
|
mnesia:add_table_copy(caps_features, node(), disc_copies),
|
||||||
ejabberd_hooks:add(user_send_packet, Host,
|
ejabberd_hooks:add(user_send_packet, Host,
|
||||||
?MODULE, user_send_packet, 75),
|
?MODULE, user_send_packet, 75),
|
||||||
|
ejabberd_hooks:add(c2s_stream_features, Host,
|
||||||
|
?MODULE, caps_stream_features, 75),
|
||||||
|
ejabberd_hooks:add(s2s_stream_features, Host,
|
||||||
|
?MODULE, caps_stream_features, 75),
|
||||||
|
ejabberd_hooks:add(disco_local_features, Host,
|
||||||
|
?MODULE, disco_features, 75),
|
||||||
|
ejabberd_hooks:add(disco_local_identity, Host,
|
||||||
|
?MODULE, disco_identity, 75),
|
||||||
|
ejabberd_hooks:add(disco_info, Host,
|
||||||
|
?MODULE, disco_info, 75),
|
||||||
{ok, #state{host = Host}}.
|
{ok, #state{host = Host}}.
|
||||||
|
|
||||||
handle_call(stop, _From, State) ->
|
handle_call(stop, _From, State) ->
|
||||||
|
@ -180,6 +231,16 @@ terminate(_Reason, State) ->
|
||||||
Host = State#state.host,
|
Host = State#state.host,
|
||||||
ejabberd_hooks:delete(user_send_packet, Host,
|
ejabberd_hooks:delete(user_send_packet, Host,
|
||||||
?MODULE, user_send_packet, 75),
|
?MODULE, user_send_packet, 75),
|
||||||
|
ejabberd_hooks:delete(c2s_stream_features, Host,
|
||||||
|
?MODULE, caps_stream_features, 75),
|
||||||
|
ejabberd_hooks:delete(s2s_stream_features, Host,
|
||||||
|
?MODULE, caps_stream_features, 75),
|
||||||
|
ejabberd_hooks:delete(disco_local_features, Host,
|
||||||
|
?MODULE, disco_features, 75),
|
||||||
|
ejabberd_hooks:delete(disco_local_identity, Host,
|
||||||
|
?MODULE, disco_identity, 75),
|
||||||
|
ejabberd_hooks:delete(disco_info, Host,
|
||||||
|
?MODULE, disco_info, 75),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
|
@ -214,16 +275,28 @@ feature_request(_Host, _From, _Caps, []) ->
|
||||||
feature_response(#iq{type = result,
|
feature_response(#iq{type = result,
|
||||||
sub_el = [{xmlelement, _, _, Els}]},
|
sub_el = [{xmlelement, _, _, Els}]},
|
||||||
Host, From, Caps, [SubNode | SubNodes]) ->
|
Host, From, Caps, [SubNode | SubNodes]) ->
|
||||||
Features = lists:flatmap(
|
|
||||||
fun({xmlelement, "feature", FAttrs, _}) ->
|
|
||||||
[xml:get_attr_s("var", FAttrs)];
|
|
||||||
(_) ->
|
|
||||||
[]
|
|
||||||
end, Els),
|
|
||||||
BinaryNode = node_to_binary(Caps#caps.node, SubNode),
|
BinaryNode = node_to_binary(Caps#caps.node, SubNode),
|
||||||
mnesia:dirty_write(
|
IsValid = case Caps#caps.hash of
|
||||||
#caps_features{node_pair = BinaryNode,
|
"sha-1" ->
|
||||||
features = features_to_binary(Features)}),
|
Caps#caps.version == make_disco_hash(Els, sha1);
|
||||||
|
"md5" ->
|
||||||
|
Caps#caps.version == make_disco_hash(Els, md5);
|
||||||
|
_ ->
|
||||||
|
true
|
||||||
|
end,
|
||||||
|
if IsValid ->
|
||||||
|
Features = lists:flatmap(
|
||||||
|
fun({xmlelement, "feature", FAttrs, _}) ->
|
||||||
|
[xml:get_attr_s("var", FAttrs)];
|
||||||
|
(_) ->
|
||||||
|
[]
|
||||||
|
end, Els),
|
||||||
|
mnesia:dirty_write(
|
||||||
|
#caps_features{node_pair = BinaryNode,
|
||||||
|
features = features_to_binary(Features)});
|
||||||
|
true ->
|
||||||
|
mnesia:dirty_write(#caps_features{node_pair = BinaryNode})
|
||||||
|
end,
|
||||||
feature_request(Host, From, Caps, SubNodes);
|
feature_request(Host, From, Caps, SubNodes);
|
||||||
feature_response(timeout, _Host, _From, _Caps, _SubNodes) ->
|
feature_response(timeout, _Host, _From, _Caps, _SubNodes) ->
|
||||||
ok;
|
ok;
|
||||||
|
@ -239,3 +312,102 @@ node_to_binary(Node, SubNode) ->
|
||||||
|
|
||||||
features_to_binary(L) -> [list_to_binary(I) || I <- L].
|
features_to_binary(L) -> [list_to_binary(I) || I <- L].
|
||||||
binary_to_features(L) -> [binary_to_list(I) || I <- L].
|
binary_to_features(L) -> [binary_to_list(I) || I <- L].
|
||||||
|
|
||||||
|
make_my_disco_hash(Host) ->
|
||||||
|
JID = jlib:make_jid("", Host, ""),
|
||||||
|
case {ejabberd_hooks:run_fold(disco_local_features,
|
||||||
|
Host,
|
||||||
|
empty,
|
||||||
|
[JID, JID, "", ""]),
|
||||||
|
ejabberd_hooks:run_fold(disco_local_identity,
|
||||||
|
Host,
|
||||||
|
[],
|
||||||
|
[JID, JID, "", ""]),
|
||||||
|
ejabberd_hooks:run_fold(disco_info,
|
||||||
|
Host,
|
||||||
|
[],
|
||||||
|
[Host, undefined, "", ""])} of
|
||||||
|
{{result, Features}, Identities, Info} ->
|
||||||
|
Feats = lists:map(
|
||||||
|
fun({{Feat, _Host}}) ->
|
||||||
|
{xmlelement, "feature", [{"var", Feat}], []};
|
||||||
|
(Feat) ->
|
||||||
|
{xmlelement, "feature", [{"var", Feat}], []}
|
||||||
|
end, Features),
|
||||||
|
make_disco_hash(Identities ++ Info ++ Feats, sha1);
|
||||||
|
_Err ->
|
||||||
|
""
|
||||||
|
end.
|
||||||
|
|
||||||
|
make_disco_hash(DiscoEls, Algo) when Algo == sha1; Algo == md5 ->
|
||||||
|
Concat = [concat_identities(DiscoEls),
|
||||||
|
concat_features(DiscoEls),
|
||||||
|
concat_info(DiscoEls)],
|
||||||
|
base64:encode_to_string(
|
||||||
|
if Algo == sha1 ->
|
||||||
|
crypto:sha(Concat);
|
||||||
|
Algo == md5 ->
|
||||||
|
crypto:md5(Concat)
|
||||||
|
end).
|
||||||
|
|
||||||
|
concat_features(Els) ->
|
||||||
|
lists:usort(
|
||||||
|
lists:flatmap(
|
||||||
|
fun({xmlelement, "feature", Attrs, _}) ->
|
||||||
|
[[xml:get_attr_s("var", Attrs), $<]];
|
||||||
|
(_) ->
|
||||||
|
[]
|
||||||
|
end, Els)).
|
||||||
|
|
||||||
|
concat_identities(Els) ->
|
||||||
|
lists:sort(
|
||||||
|
lists:flatmap(
|
||||||
|
fun({xmlelement, "identity", Attrs, _}) ->
|
||||||
|
[[xml:get_attr_s("category", Attrs), $/,
|
||||||
|
xml:get_attr_s("type", Attrs), $/,
|
||||||
|
xml:get_attr_s("xml:lang", Attrs), $/,
|
||||||
|
xml:get_attr_s("name", Attrs), $<]];
|
||||||
|
(_) ->
|
||||||
|
[]
|
||||||
|
end, Els)).
|
||||||
|
|
||||||
|
concat_info(Els) ->
|
||||||
|
lists:sort(
|
||||||
|
lists:flatmap(
|
||||||
|
fun({xmlelement, "x", Attrs, Fields}) ->
|
||||||
|
case {xml:get_attr_s("xmlns", Attrs),
|
||||||
|
xml:get_attr_s("type", Attrs)} of
|
||||||
|
{?NS_XDATA, "result"} ->
|
||||||
|
[concat_xdata_fields(Fields)];
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end;
|
||||||
|
(_) ->
|
||||||
|
[]
|
||||||
|
end, Els)).
|
||||||
|
|
||||||
|
concat_xdata_fields(Fields) ->
|
||||||
|
[Form, Res] =
|
||||||
|
lists:foldl(
|
||||||
|
fun({xmlelement, "field", Attrs, Els} = El,
|
||||||
|
[FormType, VarFields] = Acc) ->
|
||||||
|
case xml:get_attr_s("var", Attrs) of
|
||||||
|
"" ->
|
||||||
|
Acc;
|
||||||
|
"FORM_TYPE" ->
|
||||||
|
[xml:get_subtag_cdata(El, "value"), VarFields];
|
||||||
|
Var ->
|
||||||
|
[FormType,
|
||||||
|
[[[Var, $<],
|
||||||
|
lists:sort(
|
||||||
|
lists:flatmap(
|
||||||
|
fun({xmlelement, "value", _, VEls}) ->
|
||||||
|
[[xml:get_cdata(VEls), $<]];
|
||||||
|
(_) ->
|
||||||
|
[]
|
||||||
|
end, Els))] | VarFields]]
|
||||||
|
end;
|
||||||
|
(_, Acc) ->
|
||||||
|
Acc
|
||||||
|
end, ["", []], Fields),
|
||||||
|
[Form, $<, lists:sort(Res)].
|
||||||
|
|
|
@ -172,7 +172,7 @@ process_local_iq_info(From, To, #iq{type = Type, lang = Lang,
|
||||||
[{"xmlns", ?NS_DISCO_INFO} | ANode],
|
[{"xmlns", ?NS_DISCO_INFO} | ANode],
|
||||||
Identity ++
|
Identity ++
|
||||||
Info ++
|
Info ++
|
||||||
lists:map(fun feature_to_xml/1, Features)
|
features_to_xml(Features)
|
||||||
}]};
|
}]};
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
||||||
|
@ -209,10 +209,16 @@ get_local_features(Acc, _From, _To, _Node, _Lang) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
feature_to_xml({{Feature, _Host}}) ->
|
features_to_xml(FeatureList) ->
|
||||||
feature_to_xml(Feature);
|
%% Avoid duplicating features
|
||||||
feature_to_xml(Feature) when is_list(Feature) ->
|
[{xmlelement, "feature", [{"var", Feat}], []} ||
|
||||||
{xmlelement, "feature", [{"var", Feature}], []}.
|
Feat <- lists:usort(
|
||||||
|
lists:map(
|
||||||
|
fun({{Feature, _Host}}) ->
|
||||||
|
Feature;
|
||||||
|
(Feature) when is_list(Feature) ->
|
||||||
|
Feature
|
||||||
|
end, FeatureList))].
|
||||||
|
|
||||||
domain_to_xml({Domain}) ->
|
domain_to_xml({Domain}) ->
|
||||||
{xmlelement, "item", [{"jid", Domain}], []};
|
{xmlelement, "item", [{"jid", Domain}], []};
|
||||||
|
@ -358,7 +364,7 @@ process_sm_iq_info(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ)
|
||||||
sub_el = [{xmlelement, "query",
|
sub_el = [{xmlelement, "query",
|
||||||
[{"xmlns", ?NS_DISCO_INFO} | ANode],
|
[{"xmlns", ?NS_DISCO_INFO} | ANode],
|
||||||
Identity ++
|
Identity ++
|
||||||
lists:map(fun feature_to_xml/1, Features)
|
features_to_xml(Features)
|
||||||
}]};
|
}]};
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
||||||
|
@ -403,7 +409,13 @@ get_user_resources(User, Server) ->
|
||||||
|
|
||||||
%%% Support for: XEP-0157 Contact Addresses for XMPP Services
|
%%% Support for: XEP-0157 Contact Addresses for XMPP Services
|
||||||
|
|
||||||
get_info(_A, Host, Module, Node, _Lang) when Node == [] ->
|
get_info(_A, Host, Mod, Node, _Lang) when Node == [] ->
|
||||||
|
Module = case Mod of
|
||||||
|
undefined ->
|
||||||
|
?MODULE;
|
||||||
|
_ ->
|
||||||
|
Mod
|
||||||
|
end,
|
||||||
Serverinfo_fields = get_fields_xml(Host, Module),
|
Serverinfo_fields = get_fields_xml(Host, Module),
|
||||||
[{xmlelement, "x",
|
[{xmlelement, "x",
|
||||||
[{"xmlns", ?NS_XDATA}, {"type", "result"}],
|
[{"xmlns", ?NS_XDATA}, {"type", "result"}],
|
||||||
|
@ -417,8 +429,8 @@ get_info(_A, Host, Module, Node, _Lang) when Node == [] ->
|
||||||
++ Serverinfo_fields
|
++ Serverinfo_fields
|
||||||
}];
|
}];
|
||||||
|
|
||||||
get_info(_, _, _, _Node, _) ->
|
get_info(Acc, _, _, _Node, _) ->
|
||||||
[].
|
Acc.
|
||||||
|
|
||||||
get_fields_xml(Host, Module) ->
|
get_fields_xml(Host, Module) ->
|
||||||
Fields = gen_mod:get_module_opt(Host, ?MODULE, server_info, []),
|
Fields = gen_mod:get_module_opt(Host, ?MODULE, server_info, []),
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
-export([start/2,
|
-export([start/2,
|
||||||
stop/1,
|
stop/1,
|
||||||
stream_feature_register/1,
|
stream_feature_register/2,
|
||||||
unauthenticated_iq_register/4,
|
unauthenticated_iq_register/4,
|
||||||
try_register/5,
|
try_register/5,
|
||||||
process_iq/3]).
|
process_iq/3]).
|
||||||
|
@ -65,7 +65,7 @@ stop(Host) ->
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_REGISTER).
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_REGISTER).
|
||||||
|
|
||||||
|
|
||||||
stream_feature_register(Acc) ->
|
stream_feature_register(Acc, _Host) ->
|
||||||
[{xmlelement, "register",
|
[{xmlelement, "register",
|
||||||
[{"xmlns", ?NS_FEATURE_IQREGISTER}], []} | Acc].
|
[{"xmlns", ?NS_FEATURE_IQREGISTER}], []} | Acc].
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue