summaryrefslogtreecommitdiff
path: root/src/mod_mam.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_mam.erl')
-rw-r--r--src/mod_mam.erl178
1 files changed, 101 insertions, 77 deletions
diff --git a/src/mod_mam.erl b/src/mod_mam.erl
index d6e4e936..38642c0c 100644
--- a/src/mod_mam.erl
+++ b/src/mod_mam.erl
@@ -287,7 +287,7 @@ muc_process_iq(#iq{type = set,
sub_el = #xmlel{name = <<"query">>,
attrs = Attrs} = SubEl} = IQ,
MUCState, From, To) ->
- case xml:get_attr_s(<<"xmlns">>, Attrs) of
+ case fxml:get_attr_s(<<"xmlns">>, Attrs) of
NS when NS == ?NS_MAM_0; NS == ?NS_MAM_1 ->
muc_process_iq(IQ, MUCState, From, To, get_xdata_fields(SubEl));
_ ->
@@ -297,7 +297,7 @@ muc_process_iq(#iq{type = get,
sub_el = #xmlel{name = <<"query">>,
attrs = Attrs} = SubEl} = IQ,
MUCState, From, To) ->
- case xml:get_attr_s(<<"xmlns">>, Attrs) of
+ case fxml:get_attr_s(<<"xmlns">>, Attrs) of
?NS_MAM_TMP ->
muc_process_iq(IQ, MUCState, From, To, parse_query_v0_2(SubEl));
NS when NS == ?NS_MAM_0; NS == ?NS_MAM_1 ->
@@ -310,8 +310,8 @@ muc_process_iq(IQ, _MUCState, _From, _To) ->
IQ.
get_xdata_fields(SubEl) ->
- case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA),
- xml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of
+ case {fxml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA),
+ fxml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of
{#xmlel{} = XData, false} ->
jlib:parse_xdata_submit(XData);
{#xmlel{} = XData, #xmlel{}} ->
@@ -407,7 +407,7 @@ delete_old_messages(_TimeStamp, _Type, _Host, _DBType) ->
%%%===================================================================
process_iq(LServer, #iq{sub_el = #xmlel{attrs = Attrs}} = IQ) ->
- NS = case xml:get_attr_s(<<"xmlns">>, Attrs) of
+ NS = case fxml:get_attr_s(<<"xmlns">>, Attrs) of
?NS_MAM_0 ->
?NS_MAM_0;
_ ->
@@ -448,7 +448,7 @@ process_iq(LServer, #iq{sub_el = #xmlel{attrs = Attrs}} = IQ) ->
process_iq(#jid{luser = LUser, lserver = LServer},
#jid{lserver = LServer},
#iq{type = set, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) ->
- try {case xml:get_tag_attr_s(<<"default">>, SubEl) of
+ try {case fxml:get_tag_attr_s(<<"default">>, SubEl) of
<<"always">> -> always;
<<"never">> -> never;
<<"roster">> -> roster
@@ -461,11 +461,13 @@ process_iq(#jid{luser = LUser, lserver = LServer},
(_, {A, N}) ->
{A, N}
end, {[], []}, SubEl#xmlel.children)} of
- {Default, {Always, Never}} ->
- case write_prefs(LUser, LServer, LServer, Default,
- lists:usort(Always), lists:usort(Never)) of
+ {Default, {Always0, Never0}} ->
+ Always = lists:usort(Always0),
+ Never = lists:usort(Never0),
+ case write_prefs(LUser, LServer, LServer, Default, Always, Never) of
ok ->
- IQ#iq{type = result, sub_el = []};
+ NewPrefs = prefs_el(Default, Always, Never, IQ#iq.xmlns),
+ IQ#iq{type = result, sub_el = [NewPrefs]};
_Err ->
IQ#iq{type = error,
sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
@@ -477,21 +479,11 @@ process_iq(#jid{luser = LUser, lserver = LServer},
#jid{lserver = LServer},
#iq{type = get, sub_el = #xmlel{name = <<"prefs">>}} = IQ) ->
Prefs = get_prefs(LUser, LServer),
- Default = jlib:atom_to_binary(Prefs#archive_prefs.default),
- JFun = fun(L) ->
- [#xmlel{name = <<"jid">>,
- children = [{xmlcdata, jid:to_string(J)}]}
- || J <- L]
- end,
- Always = #xmlel{name = <<"always">>,
- children = JFun(Prefs#archive_prefs.always)},
- Never = #xmlel{name = <<"never">>,
- children = JFun(Prefs#archive_prefs.never)},
- IQ#iq{type = result,
- sub_el = [#xmlel{name = <<"prefs">>,
- attrs = [{<<"xmlns">>, IQ#iq.xmlns},
- {<<"default">>, Default}],
- children = [Always, Never]}]};
+ PrefsEl = prefs_el(Prefs#archive_prefs.default,
+ Prefs#archive_prefs.always,
+ Prefs#archive_prefs.never,
+ IQ#iq.xmlns),
+ IQ#iq{type = result, sub_el = [PrefsEl]};
process_iq(_, _, #iq{sub_el = SubEl} = IQ) ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}.
@@ -524,16 +516,13 @@ process_iq(LServer, #jid{luser = LUser} = From, To, IQ, SubEl, Fs, MsgType) ->
{_Start, _End, _With, #rsm_in{index = Index}} when is_integer(Index) ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]};
{Start, End, With, RSM} ->
- NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl),
+ NS = fxml:get_tag_attr_s(<<"xmlns">>, SubEl),
select_and_send(LServer, From, To, Start, End,
With, limit_max(RSM, NS), IQ, MsgType)
end.
-muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ,
- #state{config = #config{members_only = MembersOnly}} = MUCState,
- From, To, Fs) ->
- case not MembersOnly orelse
- mod_muc_room:is_occupant_or_admin(From, MUCState) of
+muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ, MUCState, From, To, Fs) ->
+ case may_enter_room(From, MUCState) of
true ->
LServer = MUCState#state.server_host,
Role = mod_muc_room:get_role(From, MUCState),
@@ -548,13 +537,13 @@ muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ,
parse_query_v0_2(Query) ->
lists:flatmap(
fun (#xmlel{name = <<"start">>} = El) ->
- [{<<"start">>, [xml:get_tag_cdata(El)]}];
+ [{<<"start">>, [fxml:get_tag_cdata(El)]}];
(#xmlel{name = <<"end">>} = El) ->
- [{<<"end">>, [xml:get_tag_cdata(El)]}];
+ [{<<"end">>, [fxml:get_tag_cdata(El)]}];
(#xmlel{name = <<"with">>} = El) ->
- [{<<"with">>, [xml:get_tag_cdata(El)]}];
+ [{<<"with">>, [fxml:get_tag_cdata(El)]}];
(#xmlel{name = <<"withtext">>} = El) ->
- [{<<"withtext">>, [xml:get_tag_cdata(El)]}];
+ [{<<"withtext">>, [fxml:get_tag_cdata(El)]}];
(#xmlel{name = <<"set">>}) ->
[{<<"set">>, Query}];
(_) ->
@@ -562,7 +551,7 @@ parse_query_v0_2(Query) ->
end, Query#xmlel.children).
should_archive(#xmlel{name = <<"message">>} = Pkt, LServer) ->
- case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of
+ case fxml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of
<<"error">> ->
false;
<<"groupchat">> ->
@@ -578,7 +567,7 @@ should_archive(#xmlel{name = <<"message">>} = Pkt, LServer) ->
no_store ->
false;
none ->
- case xml:get_subtag_cdata(Pkt, <<"body">>) of
+ case fxml:get_subtag_cdata(Pkt, <<"body">>) of
<<>> ->
%% Empty body
false;
@@ -596,7 +585,7 @@ strip_my_archived_tag(Pkt, LServer) ->
fun(#xmlel{name = Tag, attrs = Attrs})
when Tag == <<"archived">>; Tag == <<"stanza-id">> ->
case catch jid:nameprep(
- xml:get_attr_s(
+ fxml:get_attr_s(
<<"by">>, Attrs)) of
LServer ->
false;
@@ -612,9 +601,9 @@ strip_x_jid_tags(Pkt) ->
NewEls = lists:filter(
fun(#xmlel{name = <<"x">>} = XEl) ->
not lists:any(fun(ItemEl) ->
- xml:get_tag_attr(<<"jid">>, ItemEl)
+ fxml:get_tag_attr(<<"jid">>, ItemEl)
/= false
- end, xml:get_subtags(XEl, <<"item">>));
+ end, fxml:get_subtags(XEl, <<"item">>));
(_) ->
true
end, Pkt#xmlel.children),
@@ -650,7 +639,7 @@ should_archive_peer(C2SState,
end.
should_archive_muc(Pkt) ->
- case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of
+ case fxml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of
<<"groupchat">> ->
case check_store_hint(Pkt) of
store ->
@@ -658,9 +647,9 @@ should_archive_muc(Pkt) ->
no_store ->
false;
none ->
- case xml:get_subtag_cdata(Pkt, <<"body">>) of
+ case fxml:get_subtag_cdata(Pkt, <<"body">>) of
<<>> ->
- case xml:get_subtag_cdata(Pkt, <<"subject">>) of
+ case fxml:get_subtag_cdata(Pkt, <<"subject">>) of
<<>> ->
false;
_ ->
@@ -688,23 +677,23 @@ check_store_hint(Pkt) ->
end.
has_store_hint(Message) ->
- xml:get_subtag_with_xmlns(Message, <<"store">>, ?NS_HINTS)
+ fxml:get_subtag_with_xmlns(Message, <<"store">>, ?NS_HINTS)
/= false.
has_no_store_hint(Message) ->
- xml:get_subtag_with_xmlns(Message, <<"no-store">>, ?NS_HINTS)
+ fxml:get_subtag_with_xmlns(Message, <<"no-store">>, ?NS_HINTS)
/= false orelse
- xml:get_subtag_with_xmlns(Message, <<"no-storage">>, ?NS_HINTS)
+ fxml:get_subtag_with_xmlns(Message, <<"no-storage">>, ?NS_HINTS)
/= false orelse
- xml:get_subtag_with_xmlns(Message, <<"no-permanent-store">>, ?NS_HINTS)
+ fxml:get_subtag_with_xmlns(Message, <<"no-permanent-store">>, ?NS_HINTS)
/= false orelse
- xml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS)
+ fxml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS)
/= false.
is_resent(Pkt, LServer) ->
- case xml:get_subtag_with_xmlns(Pkt, <<"stanza-id">>, ?NS_SID_0) of
+ case fxml:get_subtag_with_xmlns(Pkt, <<"stanza-id">>, ?NS_SID_0) of
#xmlel{attrs = Attrs} ->
- case xml:get_attr(<<"by">>, Attrs) of
+ case fxml:get_attr(<<"by">>, Attrs) of
{value, LServer} ->
true;
_ ->
@@ -714,6 +703,12 @@ is_resent(Pkt, LServer) ->
false
end.
+may_enter_room(From,
+ #state{config = #config{members_only = false}} = MUCState) ->
+ mod_muc_room:get_affiliation(From, MUCState) /= outcast;
+may_enter_room(From, MUCState) ->
+ mod_muc_room:is_occupant_or_admin(From, MUCState).
+
store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) ->
Prefs = get_prefs(LUser, LServer),
case should_archive_peer(C2SState, Prefs, Peer) of
@@ -766,8 +761,8 @@ store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) ->
jid:remove_resource(Peer))),
LPeer = jid:to_string(
jid:tolower(Peer)),
- XML = xml:element_to_binary(Pkt),
- Body = xml:get_subtag_cdata(Pkt, <<"body">>),
+ XML = fxml:element_to_binary(Pkt),
+ Body = fxml:get_subtag_cdata(Pkt, <<"body">>),
case ejabberd_odbc:sql_query(
LServer,
[<<"insert into archive (username, timestamp, "
@@ -871,6 +866,22 @@ get_prefs(LUser, LServer, odbc) ->
error
end.
+prefs_el(Default, Always, Never, NS) ->
+ Default1 = jlib:atom_to_binary(Default),
+ JFun = fun(L) ->
+ [#xmlel{name = <<"jid">>,
+ children = [{xmlcdata, jid:to_string(J)}]}
+ || J <- L]
+ end,
+ Always1 = #xmlel{name = <<"always">>,
+ children = JFun(Always)},
+ Never1 = #xmlel{name = <<"never">>,
+ children = JFun(Never)},
+ #xmlel{name = <<"prefs">>,
+ attrs = [{<<"xmlns">>, NS},
+ {<<"default">>, Default1}],
+ children = [Always1, Never1]}.
+
maybe_activate_mam(LUser, LServer) ->
ActivateOpt = gen_mod:get_module_opt(LServer, ?MODULE,
request_activates_archiving,
@@ -916,12 +927,12 @@ select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType, DBType) -
select_and_start(LServer, From, To, Start, End, With, RSM, MsgType, DBType) ->
case MsgType of
chat ->
- select(LServer, From, Start, End, With, RSM, MsgType, DBType);
+ select(LServer, From, From, Start, End, With, RSM, MsgType, DBType);
{groupchat, _Role, _MUCState} ->
- select(LServer, To, Start, End, With, RSM, MsgType, DBType)
+ select(LServer, From, To, Start, End, With, RSM, MsgType, DBType)
end.
-select(_LServer, JidRequestor, Start, End, _With, RSM,
+select(_LServer, JidRequestor, JidArchive, Start, End, _With, RSM,
{groupchat, _Role, #state{config = #config{mam = false},
history = History}} = MsgType,
_DBType) ->
@@ -941,8 +952,8 @@ select(_LServer, JidRequestor, Start, End, _With, RSM,
peer = undefined,
nick = Nick,
packet = Pkt},
- MsgType,
- JidRequestor)}], I+1};
+ MsgType, JidRequestor, JidArchive)}],
+ I+1};
false ->
{[], I+1}
end
@@ -958,7 +969,8 @@ select(_LServer, JidRequestor, Start, End, _With, RSM,
_ ->
{Msgs, true, L}
end;
-select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor,
+select(_LServer, JidRequestor,
+ #jid{luser = LUser, lserver = LServer} = JidArchive,
Start, End, With, RSM, MsgType, mnesia) ->
MS = make_matchspec(LUser, LServer, Start, End, With),
Msgs = mnesia:dirty_select(archive_msg, MS),
@@ -969,13 +981,13 @@ select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor,
fun(Msg) ->
{Msg#archive_msg.id,
jlib:binary_to_integer(Msg#archive_msg.id),
- msg_to_el(Msg, MsgType, JidRequestor)}
+ msg_to_el(Msg, MsgType, JidRequestor, JidArchive)}
end, FilteredMsgs), IsComplete, Count};
-select(LServer, #jid{luser = LUser} = JidRequestor,
+select(LServer, JidRequestor, #jid{luser = LUser} = JidArchive,
Start, End, With, RSM, MsgType, {odbc, Host}) ->
User = case MsgType of
chat -> LUser;
- {groupchat, _Role, _MUCState} -> jid:to_string(JidRequestor)
+ {groupchat, _Role, _MUCState} -> jid:to_string(JidArchive)
end,
{Query, CountQuery} = make_sql_query(User, LServer,
Start, End, With, RSM),
@@ -1005,7 +1017,7 @@ select(LServer, #jid{luser = LUser} = JidRequestor,
{lists:flatmap(
fun([TS, XML, PeerBin, Kind, Nick]) ->
try
- #xmlel{} = El = xml_stream:parse_element(XML),
+ #xmlel{} = El = fxml_stream:parse_element(XML),
Now = usec_to_now(jlib:binary_to_integer(TS)),
PeerJid = jid:tolower(jid:from_string(PeerBin)),
T = case Kind of
@@ -1019,8 +1031,7 @@ select(LServer, #jid{luser = LUser} = JidRequestor,
type = T,
nick = Nick,
peer = PeerJid},
- MsgType,
- JidRequestor)}]
+ MsgType, JidRequestor, JidArchive)}]
catch _:Err ->
?ERROR_MSG("failed to parse data from SQL: ~p. "
"The data was: "
@@ -1035,31 +1046,44 @@ select(LServer, #jid{luser = LUser} = JidRequestor,
end.
msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer},
- MsgType, #jid{lserver = LServer} = JidRequestor) ->
- Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, Peer, MsgType, Nick),
+ MsgType, JidRequestor, #jid{lserver = LServer} = JidArchive) ->
+ Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, JidArchive, Peer, MsgType,
+ Nick),
Pkt3 = #xmlel{name = <<"forwarded">>,
attrs = [{<<"xmlns">>, ?NS_FORWARD}],
- children = [xml:replace_tag_attr(
+ children = [fxml:replace_tag_attr(
<<"xmlns">>, <<"jabber:client">>, Pkt2)]},
jlib:add_delay_info(Pkt3, LServer, TS).
-maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor,
- Peer, {groupchat, Role, _MUCState}, Nick) ->
- Items = case Role of
- moderator when Peer /= undefined ->
+maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, JidArchive,
+ Peer, {groupchat, Role,
+ #state{config = #config{anonymous = Anon}}},
+ Nick) ->
+ ExposeJID = case {Peer, JidRequestor} of
+ {undefined, _JidRequestor} ->
+ false;
+ {{U, S, _R}, #jid{luser = U, lserver = S}} ->
+ true;
+ {_Peer, _JidRequestor} when not Anon; Role == moderator ->
+ true;
+ {_Peer, _JidRequestor} ->
+ false
+ end,
+ Items = case ExposeJID of
+ true ->
[#xmlel{name = <<"x">>,
attrs = [{<<"xmlns">>, ?NS_MUC_USER}],
children =
[#xmlel{name = <<"item">>,
attrs = [{<<"jid">>,
jid:to_string(Peer)}]}]}];
- _ ->
+ false ->
[]
end,
Pkt1 = Pkt#xmlel{children = Items ++ Els},
- Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1),
+ Pkt2 = jlib:replace_from(jid:replace_resource(JidArchive, Nick), Pkt1),
jlib:remove_attr(<<"to">>, Pkt2);
-maybe_update_from_to(Pkt, _JidRequestor, _Peer, chat, _Nick) ->
+maybe_update_from_to(Pkt, _JidRequestor, _JidArchive, _Peer, chat, _Nick) ->
Pkt.
is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) ->
@@ -1095,8 +1119,8 @@ is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) ->
end.
send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) ->
- QID = xml:get_tag_attr_s(<<"queryid">>, SubEl),
- NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl),
+ QID = fxml:get_tag_attr_s(<<"queryid">>, SubEl),
+ NS = fxml:get_tag_attr_s(<<"xmlns">>, SubEl),
QIDAttr = if QID /= <<>> ->
[{<<"queryid">>, QID}];
true ->
@@ -1336,7 +1360,7 @@ datetime_to_now(DateTime, USecs) ->
get_jids(Els) ->
lists:flatmap(
fun(#xmlel{name = <<"jid">>} = El) ->
- J = jid:from_string(xml:get_tag_cdata(El)),
+ J = jid:from_string(fxml:get_tag_cdata(El)),
[jid:tolower(jid:remove_resource(J)),
jid:tolower(J)];
(_) ->