mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
* src/mod_muc/mod_muc_room.erl: Send password in room invitation
(thanks to Sergei Golovan) * src/mod_disco.erl: Added registration of sm features and nodes (thanks to Sergei Golovan) * src/mod_vcard.erl: Register vcard-temp feature (thanks to Sergei Golovan) * src/jlib.erl: Added functions now_to_utc_string/1, now_to_local_string/1, and datetime_string_to_timestamp/1 (thanks to Sergei Golovan) * src/mod_muc/mod_muc_room.erl: Use time parsing functions from jlib (thanks to Sergei Golovan) * ejabberd/src/mod_pubsub/mod_pubsub.erl: Bugfix (thanks to Mickael Remond) * src/mod_pubsub/mod_pubsub.erl: Bugfix SVN Revision: 265
This commit is contained in:
parent
e0ede61e0f
commit
6db9c2630d
25
ChangeLog
25
ChangeLog
@ -1,3 +1,28 @@
|
||||
2004-09-17 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* src/mod_muc/mod_muc_room.erl: Send password in room invitation
|
||||
(thanks to Sergei Golovan)
|
||||
|
||||
* src/mod_disco.erl: Added registration of sm features and nodes
|
||||
(thanks to Sergei Golovan)
|
||||
* src/mod_vcard.erl: Register vcard-temp feature (thanks to Sergei
|
||||
Golovan)
|
||||
|
||||
* src/jlib.erl: Added functions now_to_utc_string/1,
|
||||
now_to_local_string/1, and datetime_string_to_timestamp/1 (thanks
|
||||
to Sergei Golovan)
|
||||
* src/mod_muc/mod_muc_room.erl: Use time parsing functions from
|
||||
jlib (thanks to Sergei Golovan)
|
||||
|
||||
2004-09-16 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* ejabberd/src/mod_pubsub/mod_pubsub.erl: Bugfix (thanks to
|
||||
Mickael Remond)
|
||||
|
||||
2004-09-15 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* src/mod_pubsub/mod_pubsub.erl: Bugfix
|
||||
|
||||
2004-09-10 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* tools/ejabberdctl: Added call to "exec" (thanks to Sergei
|
||||
|
@ -1354,7 +1354,7 @@ update_priority(El, StateData) ->
|
||||
ejabberd_sm:set_presence(StateData#state.user,
|
||||
StateData#state.resource,
|
||||
Pri).
|
||||
|
||||
|
||||
|
||||
|
||||
process_privacy_iq(From, To,
|
||||
|
120
src/jlib.erl
120
src/jlib.erl
@ -37,6 +37,9 @@
|
||||
parse_xdata_submit/1,
|
||||
timestamp_to_iso/1,
|
||||
timestamp_to_xml/1,
|
||||
now_to_utc_string/1,
|
||||
now_to_local_string/1,
|
||||
datetime_string_to_timestamp/1,
|
||||
decode_base64/1,
|
||||
encode_base64/1]).
|
||||
|
||||
@ -438,6 +441,123 @@ timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) ->
|
||||
[Year, Month, Day, Hour, Minute, Second]))}],
|
||||
[]}.
|
||||
|
||||
now_to_utc_string({MegaSecs, Secs, MicroSecs}) ->
|
||||
{{Year, Month, Day}, {Hour, Minute, Second}} =
|
||||
calendar:now_to_universal_time({MegaSecs, Secs, MicroSecs}),
|
||||
lists:flatten(
|
||||
io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6..0wZ",
|
||||
[Year, Month, Day, Hour, Minute, Second, MicroSecs])).
|
||||
|
||||
now_to_local_string({MegaSecs, Secs, MicroSecs}) ->
|
||||
LocalTime = calendar:now_to_local_time({MegaSecs, Secs, MicroSecs}),
|
||||
UTCTime = calendar:now_to_universal_time({MegaSecs, Secs, MicroSecs}),
|
||||
Seconds = calendar:datetime_to_gregorian_seconds(LocalTime) -
|
||||
calendar:datetime_to_gregorian_seconds(UTCTime),
|
||||
{{H, M, _}, Sign} = if
|
||||
Seconds < 0 ->
|
||||
{calendar:seconds_to_time(-Seconds), "-"};
|
||||
true ->
|
||||
{calendar:seconds_to_time(Seconds), "+"}
|
||||
end,
|
||||
{{Year, Month, Day}, {Hour, Minute, Second}} = LocalTime,
|
||||
lists:flatten(
|
||||
io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6..0w~s~2..0w:~2..0w",
|
||||
[Year, Month, Day, Hour, Minute, Second, MicroSecs, Sign, H, M])).
|
||||
|
||||
|
||||
% yyyy-mm-ddThh:mm:ss[.sss]{Z|{+|-}hh:mm} -> {MegaSecs, Secs, MicroSecs}
|
||||
datetime_string_to_timestamp(TimeStr) ->
|
||||
case catch parse_datetime(TimeStr) of
|
||||
{'EXIT', _Err} ->
|
||||
undefined;
|
||||
TimeStamp ->
|
||||
TimeStamp
|
||||
end.
|
||||
|
||||
parse_datetime(TimeStr) ->
|
||||
[Date, Time] = string:tokens(TimeStr, "T"),
|
||||
D = parse_date(Date),
|
||||
{T, MS, TZH, TZM} = parse_time(Time),
|
||||
S = calendar:datetime_to_gregorian_seconds({D, T}),
|
||||
S1 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}),
|
||||
Seconds = (S - S1) - TZH * 60 * 60 - TZM * 60,
|
||||
{Seconds div 1000000, Seconds rem 1000000, MS}.
|
||||
|
||||
% yyyy-mm-dd
|
||||
parse_date(Date) ->
|
||||
[Y, M, D] = string:tokens(Date, "-"),
|
||||
Date1 = {list_to_integer(Y), list_to_integer(M), list_to_integer(D)},
|
||||
case calendar:valid_date(Date1) of
|
||||
true ->
|
||||
Date1;
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
% hh:mm:ss[.sss]TZD
|
||||
parse_time(Time) ->
|
||||
case string:str(Time, "Z") of
|
||||
0 ->
|
||||
parse_time_with_timezone(Time);
|
||||
_ ->
|
||||
[T | _] = string:tokens(Time, "Z"),
|
||||
{TT, MS} = parse_time1(T),
|
||||
{TT, MS, 0, 0}
|
||||
end.
|
||||
|
||||
parse_time_with_timezone(Time) ->
|
||||
case string:str(Time, "+") of
|
||||
0 ->
|
||||
case string:str(Time, "-") of
|
||||
0 ->
|
||||
false;
|
||||
_ ->
|
||||
parse_time_with_timezone(Time, "-")
|
||||
end;
|
||||
_ ->
|
||||
parse_time_with_timezone(Time, "+")
|
||||
end.
|
||||
|
||||
parse_time_with_timezone(Time, Delim) ->
|
||||
[T, TZ] = string:tokens(Time, Delim),
|
||||
{TZH, TZM} = parse_timezone(TZ),
|
||||
{TT, MS} = parse_time1(T),
|
||||
case Delim of
|
||||
"-" ->
|
||||
{TT, MS, -TZH, -TZM};
|
||||
"+" ->
|
||||
{TT, MS, TZH, TZM}
|
||||
end.
|
||||
|
||||
parse_timezone(TZ) ->
|
||||
[H, M] = string:tokens(TZ, ":"),
|
||||
{[H1, M1], true} = check_list([{H, 12}, {M, 60}]),
|
||||
{H1, M1}.
|
||||
|
||||
parse_time1(Time) ->
|
||||
[HMS | T] = string:tokens(Time, "."),
|
||||
MS = case T of
|
||||
[] ->
|
||||
0;
|
||||
[Val] ->
|
||||
list_to_integer(string:left(Val, 6, $0))
|
||||
end,
|
||||
[H, M, S] = string:tokens(HMS, ":"),
|
||||
{[H1, M1, S1], true} = check_list([{H, 24}, {M, 60}, {S, 60}]),
|
||||
{{H1, M1, S1}, MS}.
|
||||
|
||||
check_list(List) ->
|
||||
lists:mapfoldl(
|
||||
fun({L, N}, B)->
|
||||
V = list_to_integer(L),
|
||||
if
|
||||
(V >= 0) and (V =< N) ->
|
||||
{V, B};
|
||||
true ->
|
||||
{false, false}
|
||||
end
|
||||
end, true, List).
|
||||
|
||||
|
||||
%
|
||||
% Base64 stuff (based on httpd_util.erl)
|
||||
|
@ -21,7 +21,11 @@
|
||||
register_feature/1,
|
||||
unregister_feature/1,
|
||||
register_extra_domain/1,
|
||||
unregister_extra_domain/1]).
|
||||
unregister_extra_domain/1,
|
||||
register_sm_feature/1,
|
||||
unregister_sm_feature/1,
|
||||
register_sm_node/4,
|
||||
unregister_sm_node/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
@ -53,6 +57,8 @@ start(Opts) ->
|
||||
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
|
||||
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
|
||||
lists:foreach(fun register_extra_domain/1, ExtraDomains),
|
||||
catch ets:new(disco_sm_features, [named_table, ordered_set, public]),
|
||||
catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]),
|
||||
ok.
|
||||
|
||||
stop() ->
|
||||
@ -463,43 +469,108 @@ get_stopped_nodes(Lang) ->
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
process_sm_iq_items(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
||||
#jid{user = User} = To,
|
||||
case {acl:match_rule(configure, From), Type} of
|
||||
{deny, _} ->
|
||||
register_sm_feature(Feature) ->
|
||||
catch ets:new(disco_sm_features, [named_table, ordered_set, public]),
|
||||
ets:insert(disco_sm_features, {Feature}).
|
||||
|
||||
unregister_sm_feature(Feature) ->
|
||||
catch ets:new(disco_sm_features, [named_table, ordered_set, public]),
|
||||
ets:delete(disco_sm_features, Feature).
|
||||
|
||||
register_sm_node(Node, Name, Module, Function) ->
|
||||
catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]),
|
||||
ets:insert(disco_sm_nodes, {Node, Name, Module, Function}).
|
||||
|
||||
unregister_sm_node(Node) ->
|
||||
catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]),
|
||||
ets:delete(disco_sm_nodes, Node).
|
||||
|
||||
process_sm_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
|
||||
#jid{user = User, luser = LTo} = To,
|
||||
#jid{luser = LFrom, lserver = LServer} = From,
|
||||
Self = (LTo == LFrom) andalso (LServer == ?MYNAME),
|
||||
Node = xml:get_tag_attr_s("node", SubEl),
|
||||
case {acl:match_rule(configure, From), Type, Self, Node} of
|
||||
{_, set, _, _} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
||||
{allow, set} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
||||
{allow, get} ->
|
||||
case xml:get_tag_attr_s("node", SubEl) of
|
||||
"" ->
|
||||
IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "query",
|
||||
[{"xmlns", ?NS_DISCO_ITEMS}],
|
||||
get_user_resources(User)
|
||||
}]};
|
||||
_ ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
|
||||
end
|
||||
{_, get, true, []} ->
|
||||
Nodes = lists:map(fun({Nod, Name, _, _}) ->
|
||||
node_to_xml(User,
|
||||
Nod,
|
||||
translate:translate(Lang, Name))
|
||||
end, ets:tab2list(disco_sm_nodes)),
|
||||
IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "query",
|
||||
[{"xmlns", ?NS_DISCO_ITEMS}],
|
||||
get_user_resources(User) ++ Nodes}]};
|
||||
{allow, get, _, []} ->
|
||||
Nodes = lists:map(fun({Nod, Name, _, _}) ->
|
||||
node_to_xml(User,
|
||||
Nod,
|
||||
translate:translate(Lang, Name))
|
||||
end, ets:tab2list(disco_sm_nodes)),
|
||||
IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "query",
|
||||
[{"xmlns", ?NS_DISCO_ITEMS}],
|
||||
get_user_resources(User) ++ Nodes}]};
|
||||
{A, get, S, _} when (A == allow) or (S == true) ->
|
||||
case ets:lookup(disco_sm_nodes, Node) of
|
||||
[] ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]};
|
||||
[{Node, _Name, Module, Function}] ->
|
||||
case Module:Function(From, To, IQ) of
|
||||
{error, Err} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, Err]};
|
||||
{result, Res} ->
|
||||
IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "query",
|
||||
[{"xmlns", ?NS_DISCO_ITEMS},
|
||||
{"node", Node}],
|
||||
Res}]}
|
||||
end
|
||||
end;
|
||||
{_, get, _, _} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]};
|
||||
_ ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
||||
end.
|
||||
|
||||
|
||||
process_sm_iq_info(From, To, #iq{type = Type, xmlns = XMLNS,
|
||||
sub_el = SubEl} = IQ) ->
|
||||
case {acl:match_rule(configure, From), Type} of
|
||||
{deny, _} ->
|
||||
#jid{luser = LTo} = To,
|
||||
#jid{luser = LFrom, lserver = LServer} = From,
|
||||
Self = (LTo == LFrom) andalso (LServer == ?MYNAME),
|
||||
Node = xml:get_tag_attr_s("node", SubEl),
|
||||
case {acl:match_rule(configure, From), Type, Self, Node} of
|
||||
{_, set, _, _} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
||||
{allow, set} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
||||
{allow, get} ->
|
||||
case xml:get_tag_attr_s("node", SubEl) of
|
||||
"" ->
|
||||
IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
||||
{allow, get, _, []} ->
|
||||
Features = lists:map(fun feature_to_xml/1,
|
||||
ets:tab2list(disco_sm_features)),
|
||||
IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||
[feature_to_xml({?NS_EJABBERD_CONFIG})] ++
|
||||
Features}]};
|
||||
{_, get, _, []} ->
|
||||
Features = lists:map(fun feature_to_xml/1,
|
||||
ets:tab2list(disco_sm_features)),
|
||||
IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||
Features}]};
|
||||
{A, get, S, _} when (A == allow) or (S == true) ->
|
||||
case ets:lookup(disco_sm_nodes, Node) of
|
||||
[] ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]};
|
||||
_ ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
|
||||
end
|
||||
IQ#iq{type = result, sub_el = [{xmlelement, "query",
|
||||
[{"xmlns", XMLNS},
|
||||
{"node", Node}], []}]}
|
||||
end;
|
||||
{_, get, _, _} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]};
|
||||
_ ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
||||
end.
|
||||
|
||||
|
||||
@ -512,3 +583,8 @@ get_user_resources(User) ->
|
||||
{"name", User}], []}
|
||||
end, lists:sort(Rs)).
|
||||
|
||||
node_to_xml(User, Node, Name) ->
|
||||
{xmlelement, "item", [{"jid", User ++ "@" ++ ?MYNAME},
|
||||
{"node", Node},
|
||||
{"name", Name}], []}.
|
||||
|
||||
|
@ -1079,23 +1079,18 @@ extract_history([{xmlelement, _Name, Attrs, _SubEls} = El | Els], Type) ->
|
||||
[{elem, "history"}, {attr, Type}]),
|
||||
case Type of
|
||||
"since" ->
|
||||
case catch parse_datetime(AttrVal) of
|
||||
{'EXIT', _Err} ->
|
||||
case jlib:datetime_string_to_timestamp(AttrVal) of
|
||||
undefined ->
|
||||
false;
|
||||
Res ->
|
||||
Res
|
||||
TS ->
|
||||
calendar:now_to_universal_time(TS)
|
||||
end;
|
||||
_ ->
|
||||
case catch list_to_integer(AttrVal) of
|
||||
{'EXIT', _} ->
|
||||
false;
|
||||
IntVal ->
|
||||
if
|
||||
IntVal >= 0 ->
|
||||
IntVal;
|
||||
true ->
|
||||
false
|
||||
end
|
||||
IntVal when is_integer(IntVal) and IntVal >= 0 ->
|
||||
IntVal;
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
@ -1104,80 +1099,6 @@ extract_history([{xmlelement, _Name, Attrs, _SubEls} = El | Els], Type) ->
|
||||
extract_history([_ | Els], Type) ->
|
||||
extract_history(Els, Type).
|
||||
|
||||
% JEP-0082
|
||||
% yyyy-mm-ddThh:mm:ss[.sss]{Z|{+|-}hh:mm} -> {{yyyy, mm, dd}, {hh, mm, ss}} (UTC)
|
||||
parse_datetime(TimeStr) ->
|
||||
[Date, Time] = string:tokens(TimeStr, "T"),
|
||||
D = parse_date(Date),
|
||||
{T, TZH, TZM} = parse_time(Time),
|
||||
S = calendar:datetime_to_gregorian_seconds({D, T}),
|
||||
calendar:gregorian_seconds_to_datetime(S - TZH * 60 * 60 - TZM * 60).
|
||||
|
||||
% yyyy-mm-dd
|
||||
parse_date(Date) ->
|
||||
YearMonthDay = string:tokens(Date, "-"),
|
||||
[Y, M, D] = lists:map(
|
||||
fun(L)->
|
||||
list_to_integer(L)
|
||||
end, YearMonthDay),
|
||||
{Y, M, D}.
|
||||
|
||||
% hh:mm:ss[.sss]TZD
|
||||
parse_time(Time) ->
|
||||
case string:str(Time, "Z") of
|
||||
0 ->
|
||||
parse_time_with_timezone(Time);
|
||||
_ ->
|
||||
[T | _] = string:tokens(Time, "Z"),
|
||||
{parse_time1(T), 0, 0}
|
||||
end.
|
||||
|
||||
parse_time_with_timezone(Time) ->
|
||||
case string:str(Time, "+") of
|
||||
0 ->
|
||||
case string:str(Time, "-") of
|
||||
0 ->
|
||||
false;
|
||||
_ ->
|
||||
parse_time_with_timezone(Time, "-")
|
||||
end;
|
||||
_ ->
|
||||
parse_time_with_timezone(Time, "+")
|
||||
end.
|
||||
|
||||
parse_time_with_timezone(Time, Delim) ->
|
||||
[T, TZ] = string:tokens(Time, Delim),
|
||||
{TZH, TZM} = parse_timezone(TZ),
|
||||
TT = parse_time1(T),
|
||||
case Delim of
|
||||
"-" ->
|
||||
{TT, -TZH, -TZM};
|
||||
"+" ->
|
||||
{TT, TZH, TZM}
|
||||
end.
|
||||
|
||||
parse_timezone(TZ) ->
|
||||
[H, M] = string:tokens(TZ, ":"),
|
||||
{[H1, M1], true} = check_list([{H, 12}, {M, 60}]),
|
||||
{H1, M1}.
|
||||
|
||||
parse_time1(Time) ->
|
||||
[HMS | _] = string:tokens(Time, "."),
|
||||
[H, M, S] = string:tokens(HMS, ":"),
|
||||
{[H1, M1, S1], true} = check_list([{H, 24}, {M, 60}, {S, 60}]),
|
||||
{H1, M1, S1}.
|
||||
|
||||
check_list(List) ->
|
||||
lists:mapfoldl(
|
||||
fun({L, N}, B)->
|
||||
V = list_to_integer(L),
|
||||
if
|
||||
(V >= 0) and (V =< N) ->
|
||||
{V, B};
|
||||
true ->
|
||||
{false, false}
|
||||
end
|
||||
end, true, List).
|
||||
|
||||
send_update_presence(JID, StateData) ->
|
||||
LJID = jlib:jid_tolower(JID),
|
||||
@ -2316,7 +2237,14 @@ check_invitation(From, Els, StateData) ->
|
||||
jlib:jid_to_string(From)}],
|
||||
[{xmlelement, "reason", [],
|
||||
[{xmlcdata, Reason}]}]}],
|
||||
PasswdEl = [],
|
||||
PasswdEl =
|
||||
case (StateData#state.config)#config.password_protected of
|
||||
true ->
|
||||
[{xmlelement, "password", [],
|
||||
[{xmlcdata, (StateData#state.config)#config.password}]}];
|
||||
_ ->
|
||||
[]
|
||||
end,
|
||||
Msg =
|
||||
{xmlelement, "message",
|
||||
[{"type", "normal"}],
|
||||
|
@ -452,6 +452,8 @@ iq_pubsub(Host, From, Type, SubEl) ->
|
||||
[{xmlelement, "value", [], [{xmlcdata, Val}]}]}).
|
||||
|
||||
|
||||
%% Create new pubsub nodes
|
||||
%% This function is used during init to create the first bootstrap nodes
|
||||
create_new_node(Host, Node, Owner) ->
|
||||
case Node of
|
||||
[] ->
|
||||
@ -867,7 +869,7 @@ set_entities(OJID, Node, EntitiesEls) ->
|
||||
(Subscription == false) ->
|
||||
error;
|
||||
true ->
|
||||
[{JID,
|
||||
[{jlib:jid_tolower(JID),
|
||||
#entity{
|
||||
affiliation = Affiliation,
|
||||
subscription = Subscription}} |
|
||||
@ -984,7 +986,7 @@ subscription_to_string(Subscription) ->
|
||||
|
||||
check_create_permission(Host, Node, Owner) ->
|
||||
if
|
||||
#jid{lserver = Host} == Owner ->
|
||||
Owner#jid.lserver == Host ->
|
||||
true;
|
||||
true ->
|
||||
#jid{luser = User, lserver = Server} = Owner,
|
||||
|
@ -64,6 +64,7 @@ start(Opts) ->
|
||||
?MODULE, process_local_iq, IQDisc),
|
||||
gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_VCARD,
|
||||
?MODULE, process_sm_iq, IQDisc),
|
||||
catch mod_disco:register_sm_feature(?NS_VCARD),
|
||||
Host = gen_mod:get_opt(host, Opts, "vjud." ++ ?MYNAME),
|
||||
Search = gen_mod:get_opt(search, Opts, true),
|
||||
register(ejabberd_mod_vcard, spawn(?MODULE, init, [Host, Search])).
|
||||
@ -98,6 +99,7 @@ loop(Host) ->
|
||||
stop() ->
|
||||
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_VCARD),
|
||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_VCARD),
|
||||
catch mod_disco:unregister_sm_feature(?NS_VCARD),
|
||||
ejabberd_mod_vcard ! stop,
|
||||
ok.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user