Subscription = get_subscription(To, From),
if IsAnotherResource orelse
Subscription == both orelse Subscription == from ->
- Packet = xmpp_util:add_delay_info(LastPres, To, TS),
+ Packet = misc:add_delay_info(LastPres, To, TS),
case privacy_check_packet(State, Packet, out) of
deny ->
ok;
-module(misc).
%% API
--export([tolower/1, term_to_base64/1, base64_to_term/1, ip_to_list/1,
+-export([add_delay_info/3, add_delay_info/4,
+ unwrap_carbon/1, is_standalone_chat_state/1,
+ tolower/1, term_to_base64/1, base64_to_term/1, ip_to_list/1,
hex_to_bin/1, hex_to_base64/1, url_encode/1, expand_keyword/3,
atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1,
l2i/1, i2l/1, i2l/2, expr_to_term/1, term_to_expr/1,
{encode_base64, 1}]).
-include("logger.hrl").
+-include("xmpp.hrl").
-include_lib("kernel/include/file.hrl").
%%%===================================================================
%%% API
%%%===================================================================
+-spec add_delay_info(stanza(), jid(), erlang:timestamp()) -> stanza().
+add_delay_info(Stz, From, Time) ->
+ add_delay_info(Stz, From, Time, <<"">>).
+
+-spec add_delay_info(stanza(), jid(), erlang:timestamp(), binary()) -> stanza().
+add_delay_info(Stz, From, Time, Desc) ->
+ NewDelay = #delay{stamp = Time, from = From, desc = Desc},
+ case xmpp:get_subtag(Stz, #delay{stamp = {0,0,0}}) of
+ #delay{from = OldFrom} when is_record(OldFrom, jid) ->
+ case jid:tolower(From) == jid:tolower(OldFrom) of
+ true ->
+ Stz;
+ false ->
+ xmpp:append_subtags(Stz, [NewDelay])
+ end;
+ _ ->
+ xmpp:append_subtags(Stz, [NewDelay])
+ end.
+
+-spec unwrap_carbon(stanza()) -> xmpp_element().
+unwrap_carbon(#message{} = Msg) ->
+ try
+ case xmpp:get_subtag(Msg, #carbons_sent{forwarded = #forwarded{}}) of
+ #carbons_sent{forwarded = #forwarded{sub_els = [El]}} ->
+ xmpp:decode(El, ?NS_CLIENT, [ignore_els]);
+ _ ->
+ case xmpp:get_subtag(Msg, #carbons_received{
+ forwarded = #forwarded{}}) of
+ #carbons_received{forwarded = #forwarded{sub_els = [El]}} ->
+ xmpp:decode(El, ?NS_CLIENT, [ignore_els]);
+ _ ->
+ Msg
+ end
+ end
+ catch _:{xmpp_codec, _} ->
+ Msg
+ end;
+unwrap_carbon(Stanza) -> Stanza.
+
+-spec is_standalone_chat_state(stanza()) -> boolean().
+is_standalone_chat_state(Stanza) ->
+ case unwrap_carbon(Stanza) of
+ #message{body = [], subject = [], sub_els = Els} ->
+ IgnoreNS = [?NS_CHATSTATES, ?NS_DELAY, ?NS_EVENT],
+ Stripped = [El || El <- Els,
+ not lists:member(xmpp:get_ns(El), IgnoreNS)],
+ Stripped == [];
+ _ ->
+ false
+ end.
+
-spec tolower(binary()) -> binary().
tolower(B) ->
iolist_to_binary(tolower_s(binary_to_list(B))).
Acc;
filter_chat_states({#message{from = From, to = To} = Msg,
#{csi_state := inactive} = C2SState} = Acc) ->
- case xmpp_util:is_standalone_chat_state(Msg) of
+ case misc:is_standalone_chat_state(Msg) of
true ->
case {From, To} of
{#jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}} ->
-spec add_delay_info(stanza(), binary(), csi_timestamp()) -> stanza().
add_delay_info(Stanza, LServer, {_Seq, TimeStamp}) ->
- Stanza1 = xmpp_util:add_delay_info(
+ Stanza1 = misc:add_delay_info(
Stanza, jid:make(LServer), TimeStamp,
<<"Client Inactive">>),
xmpp:put_meta(Stanza1, csi_resend, true).
jid = FromJID}]},
xmpp:set_subtag(Packet, Addresses)
end,
- TSPacket = xmpp_util:add_delay_info(
+ TSPacket = misc:add_delay_info(
AddrPacket, StateData#state.jid, TimeStamp),
SPacket = xmpp:set_from_to(
TSPacket,
false ->
Packet#message.body /= [];
unless_chat_state ->
- not xmpp_util:is_standalone_chat_state(Packet)
+ not misc:is_standalone_chat_state(Packet)
end
end;
true ->
_ -> TS
end,
Packet1 = xmpp:put_meta(Packet, from_offline, true),
- xmpp_util:add_delay_info(Packet1, jid:make(LServer), NewTS,
- <<"Offline storage">>).
+ misc:add_delay_info(Packet1, jid:make(LServer), NewTS,
+ <<"Offline storage">>).
-spec get_priority_from_presence(presence()) -> integer().
get_priority_from_presence(#presence{priority = Prio}) ->
From = M#offline_msg.from,
To = M#offline_msg.to,
Packet = xmpp:set_from_to(M#offline_msg.packet, From, To),
- NewPacket = xmpp_util:add_delay_info(
+ NewPacket = misc:add_delay_info(
Packet, jid:make(LServer),
M#offline_msg.timestamp,
<<"Offline Storage">>),
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
Packet ->
Packet1 = xmpp:set_from_to(Packet, From, To),
- Packet2 = xmpp_util:add_delay_info(
+ Packet2 = misc:add_delay_info(
Packet1, jid:make(LServer),
TimeStamp, <<"Offline Storage">>),
XML = fxml:element_to_binary(xmpp:encode(Packet2)),
-spec unwrap_carbon(stanza()) -> stanza().
unwrap_carbon(#message{meta = #{carbon_copy := true}} = Msg) ->
- xmpp_util:unwrap_carbon(Msg);
+ misc:unwrap_carbon(Msg);
unwrap_carbon(Stanza) ->
Stanza.
(state(), xmlel(), erlang:timestamp()) -> xmlel().
add_resent_delay_info(#{lserver := LServer}, El, Time)
when is_record(El, message); is_record(El, presence) ->
- xmpp_util:add_delay_info(El, jid:make(LServer), Time, <<"Resent">>);
+ misc:add_delay_info(El, jid:make(LServer), Time, <<"Resent">>);
add_resent_delay_info(_State, El, _Time) ->
%% TODO
El.