mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-14 22:00:16 +02: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>
|
2004-09-10 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
* tools/ejabberdctl: Added call to "exec" (thanks to Sergei
|
* tools/ejabberdctl: Added call to "exec" (thanks to Sergei
|
||||||
|
|
|
@ -1354,7 +1354,7 @@ update_priority(El, StateData) ->
|
||||||
ejabberd_sm:set_presence(StateData#state.user,
|
ejabberd_sm:set_presence(StateData#state.user,
|
||||||
StateData#state.resource,
|
StateData#state.resource,
|
||||||
Pri).
|
Pri).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
process_privacy_iq(From, To,
|
process_privacy_iq(From, To,
|
||||||
|
|
120
src/jlib.erl
120
src/jlib.erl
|
@ -37,6 +37,9 @@
|
||||||
parse_xdata_submit/1,
|
parse_xdata_submit/1,
|
||||||
timestamp_to_iso/1,
|
timestamp_to_iso/1,
|
||||||
timestamp_to_xml/1,
|
timestamp_to_xml/1,
|
||||||
|
now_to_utc_string/1,
|
||||||
|
now_to_local_string/1,
|
||||||
|
datetime_string_to_timestamp/1,
|
||||||
decode_base64/1,
|
decode_base64/1,
|
||||||
encode_base64/1]).
|
encode_base64/1]).
|
||||||
|
|
||||||
|
@ -438,6 +441,123 @@ timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) ->
|
||||||
[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)
|
% Base64 stuff (based on httpd_util.erl)
|
||||||
|
|
|
@ -21,7 +21,11 @@
|
||||||
register_feature/1,
|
register_feature/1,
|
||||||
unregister_feature/1,
|
unregister_feature/1,
|
||||||
register_extra_domain/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("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
@ -53,6 +57,8 @@ start(Opts) ->
|
||||||
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
|
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
|
||||||
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
|
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
|
||||||
lists:foreach(fun register_extra_domain/1, ExtraDomains),
|
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.
|
ok.
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
|
@ -463,43 +469,108 @@ get_stopped_nodes(Lang) ->
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
process_sm_iq_items(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
register_sm_feature(Feature) ->
|
||||||
#jid{user = User} = To,
|
catch ets:new(disco_sm_features, [named_table, ordered_set, public]),
|
||||||
case {acl:match_rule(configure, From), Type} of
|
ets:insert(disco_sm_features, {Feature}).
|
||||||
{deny, _} ->
|
|
||||||
|
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]};
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
||||||
{allow, set} ->
|
{_, get, true, []} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
Nodes = lists:map(fun({Nod, Name, _, _}) ->
|
||||||
{allow, get} ->
|
node_to_xml(User,
|
||||||
case xml:get_tag_attr_s("node", SubEl) of
|
Nod,
|
||||||
"" ->
|
translate:translate(Lang, Name))
|
||||||
IQ#iq{type = result,
|
end, ets:tab2list(disco_sm_nodes)),
|
||||||
sub_el = [{xmlelement, "query",
|
IQ#iq{type = result,
|
||||||
[{"xmlns", ?NS_DISCO_ITEMS}],
|
sub_el = [{xmlelement, "query",
|
||||||
get_user_resources(User)
|
[{"xmlns", ?NS_DISCO_ITEMS}],
|
||||||
}]};
|
get_user_resources(User) ++ Nodes}]};
|
||||||
_ ->
|
{allow, get, _, []} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
|
Nodes = lists:map(fun({Nod, Name, _, _}) ->
|
||||||
end
|
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.
|
end.
|
||||||
|
|
||||||
|
|
||||||
process_sm_iq_info(From, To, #iq{type = Type, xmlns = XMLNS,
|
process_sm_iq_info(From, To, #iq{type = Type, xmlns = XMLNS,
|
||||||
sub_el = SubEl} = IQ) ->
|
sub_el = SubEl} = IQ) ->
|
||||||
case {acl:match_rule(configure, From), Type} of
|
#jid{luser = LTo} = To,
|
||||||
{deny, _} ->
|
#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]};
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
||||||
{allow, set} ->
|
{allow, get, _, []} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
Features = lists:map(fun feature_to_xml/1,
|
||||||
{allow, get} ->
|
ets:tab2list(disco_sm_features)),
|
||||||
case xml:get_tag_attr_s("node", SubEl) of
|
IQ#iq{type = result,
|
||||||
"" ->
|
sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||||
IQ#iq{type = result,
|
[feature_to_xml({?NS_EJABBERD_CONFIG})] ++
|
||||||
sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}],
|
Features}]};
|
||||||
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
{_, 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]}
|
IQ#iq{type = result, sub_el = [{xmlelement, "query",
|
||||||
end
|
[{"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.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -512,3 +583,8 @@ get_user_resources(User) ->
|
||||||
{"name", User}], []}
|
{"name", User}], []}
|
||||||
end, lists:sort(Rs)).
|
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}]),
|
[{elem, "history"}, {attr, Type}]),
|
||||||
case Type of
|
case Type of
|
||||||
"since" ->
|
"since" ->
|
||||||
case catch parse_datetime(AttrVal) of
|
case jlib:datetime_string_to_timestamp(AttrVal) of
|
||||||
{'EXIT', _Err} ->
|
undefined ->
|
||||||
false;
|
false;
|
||||||
Res ->
|
TS ->
|
||||||
Res
|
calendar:now_to_universal_time(TS)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
case catch list_to_integer(AttrVal) of
|
case catch list_to_integer(AttrVal) of
|
||||||
{'EXIT', _} ->
|
IntVal when is_integer(IntVal) and IntVal >= 0 ->
|
||||||
false;
|
IntVal;
|
||||||
IntVal ->
|
_ ->
|
||||||
if
|
false
|
||||||
IntVal >= 0 ->
|
|
||||||
IntVal;
|
|
||||||
true ->
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -1104,80 +1099,6 @@ extract_history([{xmlelement, _Name, Attrs, _SubEls} = El | Els], Type) ->
|
||||||
extract_history([_ | Els], Type) ->
|
extract_history([_ | 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) ->
|
send_update_presence(JID, StateData) ->
|
||||||
LJID = jlib:jid_tolower(JID),
|
LJID = jlib:jid_tolower(JID),
|
||||||
|
@ -2316,7 +2237,14 @@ check_invitation(From, Els, StateData) ->
|
||||||
jlib:jid_to_string(From)}],
|
jlib:jid_to_string(From)}],
|
||||||
[{xmlelement, "reason", [],
|
[{xmlelement, "reason", [],
|
||||||
[{xmlcdata, Reason}]}]}],
|
[{xmlcdata, Reason}]}]}],
|
||||||
PasswdEl = [],
|
PasswdEl =
|
||||||
|
case (StateData#state.config)#config.password_protected of
|
||||||
|
true ->
|
||||||
|
[{xmlelement, "password", [],
|
||||||
|
[{xmlcdata, (StateData#state.config)#config.password}]}];
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end,
|
||||||
Msg =
|
Msg =
|
||||||
{xmlelement, "message",
|
{xmlelement, "message",
|
||||||
[{"type", "normal"}],
|
[{"type", "normal"}],
|
||||||
|
|
|
@ -452,6 +452,8 @@ iq_pubsub(Host, From, Type, SubEl) ->
|
||||||
[{xmlelement, "value", [], [{xmlcdata, Val}]}]}).
|
[{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) ->
|
create_new_node(Host, Node, Owner) ->
|
||||||
case Node of
|
case Node of
|
||||||
[] ->
|
[] ->
|
||||||
|
@ -867,7 +869,7 @@ set_entities(OJID, Node, EntitiesEls) ->
|
||||||
(Subscription == false) ->
|
(Subscription == false) ->
|
||||||
error;
|
error;
|
||||||
true ->
|
true ->
|
||||||
[{JID,
|
[{jlib:jid_tolower(JID),
|
||||||
#entity{
|
#entity{
|
||||||
affiliation = Affiliation,
|
affiliation = Affiliation,
|
||||||
subscription = Subscription}} |
|
subscription = Subscription}} |
|
||||||
|
@ -984,7 +986,7 @@ subscription_to_string(Subscription) ->
|
||||||
|
|
||||||
check_create_permission(Host, Node, Owner) ->
|
check_create_permission(Host, Node, Owner) ->
|
||||||
if
|
if
|
||||||
#jid{lserver = Host} == Owner ->
|
Owner#jid.lserver == Host ->
|
||||||
true;
|
true;
|
||||||
true ->
|
true ->
|
||||||
#jid{luser = User, lserver = Server} = Owner,
|
#jid{luser = User, lserver = Server} = Owner,
|
||||||
|
|
|
@ -64,6 +64,7 @@ start(Opts) ->
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_VCARD,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_VCARD,
|
||||||
?MODULE, process_sm_iq, IQDisc),
|
?MODULE, process_sm_iq, IQDisc),
|
||||||
|
catch mod_disco:register_sm_feature(?NS_VCARD),
|
||||||
Host = gen_mod:get_opt(host, Opts, "vjud." ++ ?MYNAME),
|
Host = gen_mod:get_opt(host, Opts, "vjud." ++ ?MYNAME),
|
||||||
Search = gen_mod:get_opt(search, Opts, true),
|
Search = gen_mod:get_opt(search, Opts, true),
|
||||||
register(ejabberd_mod_vcard, spawn(?MODULE, init, [Host, Search])).
|
register(ejabberd_mod_vcard, spawn(?MODULE, init, [Host, Search])).
|
||||||
|
@ -98,6 +99,7 @@ loop(Host) ->
|
||||||
stop() ->
|
stop() ->
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_VCARD),
|
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_VCARD),
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_VCARD),
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_VCARD),
|
||||||
|
catch mod_disco:unregister_sm_feature(?NS_VCARD),
|
||||||
ejabberd_mod_vcard ! stop,
|
ejabberd_mod_vcard ! stop,
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user