mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-26 17:38:45 +01:00
parent
64e1cfcbba
commit
6da1bb5b22
@ -73,7 +73,7 @@
|
||||
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.29"}}},
|
||||
{if_var_true, stun,
|
||||
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.2.7"}}}},
|
||||
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.6.1"}}},
|
||||
{xmpp, ".*", {git, "https://github.com/processone/xmpp", "1107d05640ccd352613b2867ab24c5649603a470"}},
|
||||
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.15"}}}
|
||||
]}.
|
||||
|
||||
|
@ -44,7 +44,8 @@
|
||||
mod_options/1, remove_mam_for_user_with_peer/3, remove_mam_for_user/2,
|
||||
is_empty_for_user/2, is_empty_for_room/3, check_create_room/4,
|
||||
process_iq/3, store_mam_message/7, make_id/0, wrap_as_mucsub/2, select/7,
|
||||
delete_old_messages_batch/5, delete_old_messages_status/1, delete_old_messages_abort/1]).
|
||||
delete_old_messages_batch/5, delete_old_messages_status/1, delete_old_messages_abort/1,
|
||||
remove_message_from_archive/3]).
|
||||
|
||||
-include_lib("xmpp/include/xmpp.hrl").
|
||||
-include("logger.hrl").
|
||||
@ -352,6 +353,19 @@ remove_mam_for_user_with_peer(User, Server, Peer) ->
|
||||
{error, <<"Invalid peer JID">>}
|
||||
end.
|
||||
|
||||
-spec remove_message_from_archive(User :: binary(), Server :: binary(), StanzaId :: integer()) ->
|
||||
ok | {error, binary()}.
|
||||
remove_message_from_archive(User, Server, StanzaId) ->
|
||||
Mod = gen_mod:db_mod(Server, ?MODULE),
|
||||
case Mod:remove_from_archive(User, Server, StanzaId) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, Bin} when is_binary(Bin) ->
|
||||
{error, Bin};
|
||||
{error, _} ->
|
||||
{error, <<"Db returned error">>}
|
||||
end.
|
||||
|
||||
get_module_host(LServer) ->
|
||||
try gen_mod:db_mod(LServer, ?MODULE)
|
||||
catch error:{module_not_loaded, ?MODULE, LServer} ->
|
||||
|
@ -81,7 +81,7 @@ remove_from_archive(LUser, LServer, none) ->
|
||||
{atomic, _} -> ok;
|
||||
{aborted, Reason} -> {error, Reason}
|
||||
end;
|
||||
remove_from_archive(LUser, LServer, WithJid) ->
|
||||
remove_from_archive(LUser, LServer, #jid{} = WithJid) ->
|
||||
US = {LUser, LServer},
|
||||
Peer = jid:remove_resource(jid:split(WithJid)),
|
||||
F = fun () ->
|
||||
@ -96,6 +96,22 @@ remove_from_archive(LUser, LServer, WithJid) ->
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, _} -> ok;
|
||||
{aborted, Reason} -> {error, Reason}
|
||||
end;
|
||||
remove_from_archive(LUser, LServer, StanzaId) ->
|
||||
Timestamp = misc:usec_to_now(StanzaId),
|
||||
US = {LUser, LServer},
|
||||
F = fun () ->
|
||||
Msgs = mnesia:select(
|
||||
archive_msg,
|
||||
ets:fun2ms(
|
||||
fun(#archive_msg{us = US1, timestamp = Timestamp1} = Msg)
|
||||
when US1 == US, Timestamp1 == Timestamp -> Msg
|
||||
end)),
|
||||
lists:foreach(fun mnesia:delete_object/1, Msgs)
|
||||
end,
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, _} -> ok;
|
||||
{aborted, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
delete_old_messages(global, TimeStamp, Type) ->
|
||||
|
@ -64,12 +64,18 @@ remove_from_archive(LUser, LServer, none) ->
|
||||
{error, Reason} -> {error, Reason};
|
||||
_ -> ok
|
||||
end;
|
||||
remove_from_archive(LUser, LServer, WithJid) ->
|
||||
remove_from_archive(LUser, LServer, #jid{} = WithJid) ->
|
||||
Peer = jid:encode(jid:remove_resource(WithJid)),
|
||||
case ejabberd_sql:sql_query(LServer,
|
||||
?SQL("delete from archive where username=%(LUser)s and %(LServer)H and bare_peer=%(Peer)s")) of
|
||||
{error, Reason} -> {error, Reason};
|
||||
_ -> ok
|
||||
end;
|
||||
remove_from_archive(LUser, LServer, StanzaId) ->
|
||||
case ejabberd_sql:sql_query(LServer,
|
||||
?SQL("delete from archive where username=%(LUser)s and %(LServer)H and timestamp=%(StanzaId)d")) of
|
||||
{error, Reason} -> {error, Reason};
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
count_messages_to_delete(ServerHost, TimeStamp, Type) ->
|
||||
|
@ -499,6 +499,15 @@ normal_state({route, <<"">>,
|
||||
process_iq_captcha(From, IQ, StateData);
|
||||
#adhoc_command{} ->
|
||||
process_iq_adhoc(From, IQ, StateData);
|
||||
#fasten_apply_to{} = ApplyTo ->
|
||||
case xmpp:get_subtag(ApplyTo, #message_moderate{}) of
|
||||
#message_moderate{} = Moderate ->
|
||||
process_iq_moderate(From, IQ, ApplyTo, Moderate, StateData);
|
||||
_ ->
|
||||
Txt = ?T("The feature requested is not "
|
||||
"supported by the conference"),
|
||||
{error, xmpp:err_service_unavailable(Txt, Lang)}
|
||||
end;
|
||||
_ ->
|
||||
Txt = ?T("The feature requested is not "
|
||||
"supported by the conference"),
|
||||
@ -1059,7 +1068,8 @@ process_groupchat_message(#message{from = From, lang = Lang} = Packet, StateData
|
||||
drop ->
|
||||
{next_state, normal_state, StateData};
|
||||
NewPacket1 ->
|
||||
NewPacket = xmpp:put_meta(xmpp:remove_subtag(NewPacket1, #nick{}),
|
||||
NewPacket = xmpp:put_meta(xmpp:remove_subtag(
|
||||
add_stanza_id(NewPacket1, StateData), #nick{}),
|
||||
muc_sender_real_jid, From),
|
||||
Node = if Subject == [] -> ?NS_MUCSUB_NODES_MESSAGES;
|
||||
true -> ?NS_MUCSUB_NODES_SUBJECT
|
||||
@ -1108,6 +1118,30 @@ process_groupchat_message(#message{from = From, lang = Lang} = Packet, StateData
|
||||
{next_state, normal_state, StateData}
|
||||
end.
|
||||
|
||||
-spec add_stanza_id(Packet :: message(), State :: state()) -> message().
|
||||
add_stanza_id(Packet, #state{jid = JID}) ->
|
||||
{AddId, NewPacket} =
|
||||
case xmpp:get_meta(Packet, stanza_id, false) of
|
||||
false ->
|
||||
GenID = erlang:system_time(microsecond),
|
||||
{true, xmpp:put_meta(Packet, stanza_id, GenID)};
|
||||
_ ->
|
||||
StanzaIds = xmpp:get_subtags(Packet, #stanza_id{}),
|
||||
HasOurStanzaId = lists:any(
|
||||
fun(#stanza_id{by = JID2}) when JID == JID2 -> true;
|
||||
(_) -> false
|
||||
end, StanzaIds),
|
||||
{not HasOurStanzaId, Packet}
|
||||
end,
|
||||
if
|
||||
AddId ->
|
||||
ID = xmpp:get_meta(NewPacket, stanza_id),
|
||||
IDs = integer_to_binary(ID),
|
||||
xmpp:append_subtags(NewPacket, [#stanza_id{by = JID, id = IDs}]);
|
||||
true ->
|
||||
Packet
|
||||
end.
|
||||
|
||||
-spec process_normal_message(jid(), message(), state()) -> state().
|
||||
process_normal_message(From, #message{lang = Lang} = Pkt, StateData) ->
|
||||
Action = lists:foldl(
|
||||
@ -2853,6 +2887,18 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) ->
|
||||
StateData#state{just_created = erlang:system_time(microsecond)}
|
||||
end.
|
||||
|
||||
remove_from_history(StanzaId, #state{history = #lqueue{queue = Queue} = LQueue} = StateData) ->
|
||||
NewQ = p1_queue:foldl(
|
||||
fun({_, Pkt, _, _, _} = Entry, Acc) ->
|
||||
case xmpp:get_meta(Pkt, stanza_id, 0) of
|
||||
V when V == StanzaId ->
|
||||
Acc;
|
||||
_ ->
|
||||
p1_queue:in(Entry, Acc)
|
||||
end
|
||||
end, p1_queue:new(), Queue),
|
||||
StateData#state{history = LQueue#lqueue{queue = NewQ}}.
|
||||
|
||||
-spec send_history(jid(), [lqueue_elem()], state()) -> ok.
|
||||
send_history(JID, History, StateData) ->
|
||||
lists:foreach(
|
||||
@ -4237,7 +4283,7 @@ maybe_forget_room(StateData) ->
|
||||
make_disco_info(_From, StateData) ->
|
||||
Config = StateData#state.config,
|
||||
Feats = [?NS_VCARD, ?NS_MUC, ?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
|
||||
?NS_COMMANDS,
|
||||
?NS_COMMANDS, ?NS_MESSAGE_MODERATE,
|
||||
?CONFIG_OPT_TO_FEATURE((Config#config.public),
|
||||
<<"muc_public">>, <<"muc_hidden">>),
|
||||
?CONFIG_OPT_TO_FEATURE((Config#config.persistent),
|
||||
@ -4991,6 +5037,49 @@ add_presence_hats(JID, Pres, StateData) ->
|
||||
Pres
|
||||
end.
|
||||
|
||||
-spec process_iq_moderate(jid(), iq(), fasten_apply_to(), message_moderate(), state()) ->
|
||||
{result, undefined, state()} |
|
||||
{error, stanza_error()}.
|
||||
process_iq_moderate(_From, #iq{type = get}, _ApplyTo, _Moderate, _StateData) ->
|
||||
{error, xmpp:err_bad_request()};
|
||||
process_iq_moderate(From, #iq{type = set, lang = Lang},
|
||||
#fasten_apply_to{id = Id},
|
||||
#message_moderate{reason = Reason},
|
||||
#state{config = Config, jid = JID, server_host = Server} = StateData) ->
|
||||
FAffiliation = get_affiliation(From, StateData),
|
||||
FRole = get_role(From, StateData),
|
||||
IsModerator = FRole == moderator orelse FAffiliation == owner orelse
|
||||
FAffiliation == admin,
|
||||
case IsModerator of
|
||||
false ->
|
||||
{error, xmpp:err_forbidden(
|
||||
?T("Only moderators are allowed to retract messages"), Lang)};
|
||||
_ ->
|
||||
try binary_to_integer(Id) of
|
||||
StanzaId ->
|
||||
case Config#config.mam of
|
||||
true ->
|
||||
JIDs = jid:encode(JID),
|
||||
mod_mam:remove_message_from_archive(JIDs, Server, StanzaId);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
Packet = #message{type = groupchat,
|
||||
sub_els = [
|
||||
#fasten_apply_to{id = Id, sub_els = [
|
||||
#message_moderated{reason = Reason,
|
||||
retract = #message_retract{}}
|
||||
]}]},
|
||||
send_wrapped_multiple(JID,
|
||||
get_users_and_subscribers_with_node(?NS_MUCSUB_NODES_MESSAGES, StateData),
|
||||
Packet, ?NS_MUCSUB_NODES_MESSAGES, StateData),
|
||||
{result, undefined, remove_from_history(StanzaId, StateData)}
|
||||
catch _:_ ->
|
||||
{error, xmpp:err_bad_request(
|
||||
?T("Stanza id is not valid"), Lang)}
|
||||
end
|
||||
end.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Voice request support
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user