aboutsummaryrefslogtreecommitdiff
path: root/src/jlib.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jlib.erl')
-rw-r--r--src/jlib.erl131
1 files changed, 91 insertions, 40 deletions
diff --git a/src/jlib.erl b/src/jlib.erl
index be1da3fd0..dd2cc38dc 100644
--- a/src/jlib.erl
+++ b/src/jlib.erl
@@ -41,10 +41,11 @@
jid_remove_resource/1, jid_replace_resource/2,
get_iq_namespace/1, iq_query_info/1,
iq_query_or_response_info/1, is_iq_request_type/1,
- iq_to_xml/1, parse_xdata_submit/1, timestamp_to_iso/1,
- timestamp_to_iso/2, timestamp_to_xml/4,
- timestamp_to_xml/1, now_to_utc_string/1,
- now_to_local_string/1, datetime_string_to_timestamp/1,
+ iq_to_xml/1, parse_xdata_submit/1,
+ add_delay_info/3, add_delay_info/4,
+ timestamp_to_iso/1, timestamp_to_iso/2,
+ now_to_utc_string/1, now_to_local_string/1,
+ datetime_string_to_timestamp/1,
term_to_base64/1, base64_to_term/1,
decode_base64/1, encode_base64/1, ip_to_list/1,
rsm_encode/1, rsm_encode/2, rsm_decode/1,
@@ -600,6 +601,77 @@ rsm_encode_count(Count, Arr) ->
children = [{xmlcdata, i2l(Count)}]}
| Arr].
+-spec add_delay_info(xmlel(), erlang:timestamp(), binary()) -> xmlel().
+
+add_delay_info(El, From, Time) ->
+ add_delay_info(El, From, Time, <<"">>).
+
+-spec add_delay_info(xmlel(), erlang:timestamp(), binary(),
+ binary()) -> xmlel().
+
+add_delay_info(El, From, Time, Desc) ->
+ %% TODO: Remove support for <x/>, XEP-0091 is obsolete.
+ El1 = add_delay_info(El, From, Time, Desc, <<"delay">>, ?NS_DELAY),
+ El2 = add_delay_info(El1, From, Time, Desc, <<"x">>, ?NS_DELAY91),
+ El2.
+
+-spec add_delay_info(xmlel(), erlang:timestamp(), binary(), binary(), binary(),
+ binary()) -> xmlel().
+
+add_delay_info(El, From, Time, Desc, Name, XMLNS) ->
+ case xml:get_subtag_with_xmlns(El, Name, XMLNS) of
+ false ->
+ %% Add new tag
+ DelayTag = create_delay_tag(Time, From, Desc, XMLNS),
+ xml:append_subtags(El, [DelayTag]);
+ DelayTag ->
+ %% Update existing tag
+ NewDelayTag =
+ case {xml:get_tag_cdata(DelayTag), Desc} of
+ {<<"">>, <<"">>} ->
+ DelayTag;
+ {OldDesc, <<"">>} ->
+ DelayTag#xmlel{children = [{xmlcdata, OldDesc}]};
+ {<<"">>, NewDesc} ->
+ DelayTag#xmlel{children = [{xmlcdata, NewDesc}]};
+ {OldDesc, NewDesc} ->
+ case binary:match(OldDesc, NewDesc) of
+ nomatch ->
+ FinalDesc = <<OldDesc/binary, ", ", NewDesc/binary>>,
+ DelayTag#xmlel{children = [{xmlcdata, FinalDesc}]};
+ _ ->
+ DelayTag#xmlel{children = [{xmlcdata, OldDesc}]}
+ end
+ end,
+ NewEl = xml:remove_subtags(El, Name, {<<"xmlns">>, XMLNS}),
+ xml:append_subtags(NewEl, [NewDelayTag])
+ end.
+
+-spec create_delay_tag(erlang:timestamp(), jid() | binary(), binary(),
+ binary()) -> xmlel() | error.
+
+create_delay_tag(TimeStamp, FromJID, Desc, XMLNS) when is_tuple(FromJID) ->
+ From = jlib:jid_to_string(FromJID),
+ {Name, Stamp} = case XMLNS of
+ ?NS_DELAY ->
+ {<<"delay">>, now_to_utc_string(TimeStamp, 3)};
+ ?NS_DELAY91 ->
+ DateTime = calendar:now_to_universal_time(TimeStamp),
+ {<<"x">>, timestamp_to_iso(DateTime)}
+ end,
+ Children = case Desc of
+ <<"">> -> [];
+ _ -> [{xmlcdata, Desc}]
+ end,
+ #xmlel{name = Name,
+ attrs =
+ [{<<"xmlns">>, XMLNS}, {<<"from">>, From},
+ {<<"stamp">>, Stamp}],
+ children = Children};
+create_delay_tag(DateTime, Host, Desc, XMLNS) when is_binary(Host) ->
+ FromJID = jlib:make_jid(<<"">>, Host, <<"">>),
+ create_delay_tag(DateTime, FromJID, Desc, XMLNS).
+
-type tz() :: {binary(), {integer(), integer()}} | {integer(), integer()} | utc.
%% Timezone = utc | {Sign::string(), {Hours, Minutes}} | {Hours, Minutes}
@@ -611,18 +683,18 @@ timestamp_to_iso({{Year, Month, Day},
{Hour, Minute, Second}},
Timezone) ->
Timestamp_string =
- lists:flatten(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w",
+ lists:flatten(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",
[Year, Month, Day, Hour, Minute, Second])),
Timezone_string = case Timezone of
utc -> "Z";
{Sign, {TZh, TZm}} ->
- io_lib:format("~s~2..0w:~2..0w", [Sign, TZh, TZm]);
+ io_lib:format("~s~2..0B:~2..0B", [Sign, TZh, TZm]);
{TZh, TZm} ->
Sign = case TZh >= 0 of
true -> "+";
false -> "-"
end,
- io_lib:format("~s~2..0w:~2..0w",
+ io_lib:format("~s~2..0B:~2..0B",
[Sign, abs(TZh), TZm])
end,
{iolist_to_binary(Timestamp_string), iolist_to_binary(Timezone_string)}.
@@ -631,46 +703,25 @@ timestamp_to_iso({{Year, Month, Day},
timestamp_to_iso({{Year, Month, Day},
{Hour, Minute, Second}}) ->
- iolist_to_binary(io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w",
+ iolist_to_binary(io_lib:format("~4..0B~2..0B~2..0BT~2..0B:~2..0B:~2..0B",
[Year, Month, Day, Hour, Minute, Second])).
--spec timestamp_to_xml(calendar:datetime(), tz(), jid(), binary()) -> xmlel().
-
-timestamp_to_xml(DateTime, Timezone, FromJID, Desc) ->
- {T_string, Tz_string} = timestamp_to_iso(DateTime,
- Timezone),
- Text = [{xmlcdata, Desc}],
- From = jlib:jid_to_string(FromJID),
-%% TODO: Remove this function once XEP-0091 is Obsolete
- #xmlel{name = <<"delay">>,
- attrs =
- [{<<"xmlns">>, ?NS_DELAY}, {<<"from">>, From},
- {<<"stamp">>, <<T_string/binary, Tz_string/binary>>}],
- children = Text}.
-
--spec timestamp_to_xml(calendar:datetime()) -> xmlel().
-
-timestamp_to_xml({{Year, Month, Day},
- {Hour, Minute, Second}}) ->
- #xmlel{name = <<"x">>,
- attrs =
- [{<<"xmlns">>, ?NS_DELAY91},
- {<<"stamp">>,
- iolist_to_binary(io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w",
- [Year, Month, Day, Hour, Minute,
- Second]))}],
- children = []}.
-
-spec now_to_utc_string(erlang:timestamp()) -> binary().
now_to_utc_string({MegaSecs, Secs, MicroSecs}) ->
+ now_to_utc_string({MegaSecs, Secs, MicroSecs}, 6).
+
+-spec now_to_utc_string(erlang:timestamp(), 1..6) -> binary().
+
+now_to_utc_string({MegaSecs, Secs, MicroSecs}, Precision) ->
{{Year, Month, Day}, {Hour, Minute, Second}} =
calendar:now_to_universal_time({MegaSecs, Secs,
MicroSecs}),
- list_to_binary(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6."
- ".0wZ",
+ FracOfSec = round(MicroSecs / math:pow(10, 6 - Precision)),
+ list_to_binary(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B.~*."
+ ".0BZ",
[Year, Month, Day, Hour, Minute, Second,
- MicroSecs])).
+ Precision, FracOfSec])).
-spec now_to_local_string(erlang:timestamp()) -> binary().
@@ -688,8 +739,8 @@ now_to_local_string({MegaSecs, Secs, MicroSecs}) ->
end,
{{Year, Month, Day}, {Hour, Minute, Second}} =
LocalTime,
- list_to_binary(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6."
- ".0w~s~2..0w:~2..0w",
+ list_to_binary(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B.~6."
+ ".0B~s~2..0B:~2..0B",
[Year, Month, Day, Hour, Minute, Second,
MicroSecs, Sign, H, M])).