From: Evgeniy Khramtsov Date: Fri, 20 Jan 2017 20:21:06 +0000 (+0300) Subject: Add stanza-id to every archived message (#1477) X-Git-Tag: 17.03-beta~89 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=56ef6079043c3dd9beb459ee408ef40440c3dc13;p=ejabberd Add stanza-id to every archived message (#1477) --- diff --git a/src/mod_mam.erl b/src/mod_mam.erl index f55c1ccf2..68fe714a0 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -750,14 +750,19 @@ select(_LServer, JidRequestor, JidArchive, Query, RSM, case match_interval(Now, Start, End) and match_rsm(Now, RSM) of true -> - [{integer_to_binary(TS), TS, - msg_to_el(#archive_msg{ - type = groupchat, - timestamp = Now, - peer = undefined, - nick = Nick, - packet = Pkt}, - MsgType, JidRequestor, JidArchive)}]; + case msg_to_el(#archive_msg{ + id = integer_to_binary(TS), + type = groupchat, + timestamp = Now, + peer = undefined, + nick = Nick, + packet = Pkt}, + MsgType, JidRequestor, JidArchive) of + {ok, Msg} -> + [{integer_to_binary(TS), TS, Msg}]; + {error, _} -> + [] + end; false -> [] end @@ -776,25 +781,23 @@ select(LServer, JidRequestor, JidArchive, Query, RSM, MsgType) -> Mod = gen_mod:db_mod(LServer, ?MODULE), Mod:select(LServer, JidRequestor, JidArchive, Query, RSM, MsgType). -msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, +msg_to_el(#archive_msg{timestamp = TS, packet = El, nick = Nick, + peer = Peer, id = ID}, MsgType, JidRequestor, #jid{lserver = LServer} = JidArchive) -> - Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, JidArchive, Peer, MsgType, - Nick), - El = case Pkt2 of - #xmlel{attrs = Attrs} -> - Attrs1 = lists:keystore(<<"xmlns">>, 1, Attrs, - {<<"xmlns">>, ?NS_CLIENT}), - Pkt2#xmlel{attrs = Attrs1}; - _ -> - xmpp:encode(Pkt2) - end, - #forwarded{xml_els = [El], - delay = #delay{stamp = TS, from = jid:make(LServer)}}. - -maybe_update_from_to(#xmlel{} = El, JidRequestor, JidArchive, Peer, - {groupchat, _, _} = MsgType, Nick) -> - Pkt = xmpp:decode(El, ?NS_CLIENT, [ignore_els]), - maybe_update_from_to(Pkt, JidRequestor, JidArchive, Peer, MsgType, Nick); + try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of + Pkt1 -> + Pkt2 = set_stanza_id(Pkt1, JidArchive, ID), + Pkt3 = maybe_update_from_to( + Pkt2, JidRequestor, JidArchive, Peer, MsgType, Nick), + Delay = #delay{stamp = TS, from = jid:make(LServer)}, + {ok, #forwarded{xml_els = [xmpp:encode(Pkt3)], delay = Delay}} + catch _:{xmpp_codec, Why} -> + ?ERROR_MSG("Failed to decode raw element ~p from message " + "archive of user ~s: ~s", + [El, jid:to_string(JidArchive), xmpp:format_error(Why)]), + {error, invalid_xml} + end. + maybe_update_from_to(#message{sub_els = Els} = Pkt, JidRequestor, JidArchive, Peer, {groupchat, Role, #state{config = #config{anonymous = Anon}}}, diff --git a/src/mod_mam_mnesia.erl b/src/mod_mam_mnesia.erl index 6b296f772..f498bc3c7 100644 --- a/src/mod_mam_mnesia.erl +++ b/src/mod_mam_mnesia.erl @@ -160,12 +160,17 @@ select(_LServer, JidRequestor, SortedMsgs = lists:keysort(#archive_msg.timestamp, Msgs), {FilteredMsgs, IsComplete} = filter_by_rsm(SortedMsgs, RSM), Count = length(Msgs), - Result = {lists:map( + Result = {lists:flatmap( fun(Msg) -> - {Msg#archive_msg.id, - binary_to_integer(Msg#archive_msg.id), - mod_mam:msg_to_el(Msg, MsgType, JidRequestor, - JidArchive)} + case mod_mam:msg_to_el( + Msg, MsgType, JidRequestor, JidArchive) of + {ok, El} -> + [{Msg#archive_msg.id, + binary_to_integer(Msg#archive_msg.id), + El}]; + {error, _} -> + [] + end end, FilteredMsgs), IsComplete, Count}, erlang:garbage_collect(), Result. diff --git a/src/mod_mam_sql.erl b/src/mod_mam_sql.erl index a99c359c6..d553c2e64 100644 --- a/src/mod_mam_sql.erl +++ b/src/mod_mam_sql.erl @@ -168,28 +168,12 @@ select(LServer, JidRequestor, #jid{luser = LUser} = JidArchive, end, {lists:flatmap( fun([TS, XML, PeerBin, Kind, Nick]) -> - try - #xmlel{} = El = fxml_stream:parse_element(XML), - Now = usec_to_now(binary_to_integer(TS)), - PeerJid = jid:tolower(jid:from_string(PeerBin)), - T = case Kind of - <<"">> -> chat; - null -> chat; - _ -> jlib:binary_to_atom(Kind) - end, - [{TS, binary_to_integer(TS), - mod_mam:msg_to_el(#archive_msg{timestamp = Now, - packet = El, - type = T, - nick = Nick, - peer = PeerJid}, - MsgType, JidRequestor, JidArchive)}] - catch _:Err -> - ?ERROR_MSG("failed to parse data from SQL: ~p. " - "The data was: " - "timestamp = ~s, xml = ~s, " - "peer = ~s, kind = ~s, nick = ~s", - [Err, TS, XML, PeerBin, Kind, Nick]), + case make_archive_el( + TS, XML, PeerBin, Kind, Nick, + MsgType, JidRequestor, JidArchive) of + {ok, El} -> + [{TS, binary_to_integer(TS), El}]; + {error, _} -> [] end end, Res1), IsComplete, binary_to_integer(Count)}; @@ -319,3 +303,51 @@ get_max_direction_id(RSM) -> _ -> {undefined, undefined, <<>>} end. + +-spec make_archive_el(binary(), binary(), binary(), binary(), + binary(), _, jid(), jid()) -> + {ok, xmpp_element()} | {error, invalid_jid | + invalid_timestamp | + invalid_xml}. +make_archive_el(TS, XML, Peer, Kind, Nick, MsgType, JidRequestor, JidArchive) -> + case fxml_stream:parse_element(XML) of + #xmlel{} = El -> + try binary_to_integer(TS) of + TSInt -> + case jid:from_string(Peer) of + #jid{} = PeerJID -> + Now = usec_to_now(TSInt), + PeerLJID = jid:tolower(PeerJID), + T = case Kind of + <<"">> -> chat; + null -> chat; + _ -> jlib:binary_to_atom(Kind) + end, + mod_mam:msg_to_el( + #archive_msg{timestamp = Now, + id = TS, + packet = El, + type = T, + nick = Nick, + peer = PeerLJID}, + MsgType, JidRequestor, JidArchive); + error -> + ?ERROR_MSG("Malformed 'peer' field with value " + "'~s' detected for user ~s in table " + "'archive': invalid JID", + [Peer, jid:to_string(JidArchive)]), + {error, invalid_jid} + end + catch _:_ -> + ?ERROR_MSG("Malformed 'timestamp' field with value '~s' " + "detected for user ~s in table 'archive': " + "not an integer", + [TS, jid:to_string(JidArchive)]), + {error, invalid_timestamp} + end; + {error, {_, Reason}} -> + ?ERROR_MSG("Malformed 'xml' field with value '~s' detected " + "for user ~s in table 'archive': ~s", + [XML, jid:to_string(JidArchive), Reason]), + {error, invalid_xml} + end.