mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-02 21:17:12 +02:00
Apply patch from Evgeniy Khramtsov
This commit is contained in:
parent
499b884c67
commit
ff57c8a58c
|
@ -256,109 +256,140 @@ normal_state({route, From, "",
|
||||||
From, Err),
|
From, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
Type when (Type == "") or (Type == "normal") ->
|
Type when (Type == "") or (Type == "normal") ->
|
||||||
IsInvitation = is_invitation(Els),
|
IsInvitation = is_invitation(Els),
|
||||||
IsVoiceRequest = is_voice_request(Els) and is_visitor(From, StateData),
|
IsVoiceRequest = is_voice_request(Els)
|
||||||
IsVoiceApprovement = is_voice_approvement(Els) and not is_visitor(From, StateData),
|
and is_visitor(From, StateData),
|
||||||
if
|
IsVoiceApprovement = is_voice_approvement(Els)
|
||||||
IsInvitation ->
|
and not is_visitor(From, StateData),
|
||||||
case catch check_invitation(From, Els, Lang, StateData) of
|
if IsInvitation ->
|
||||||
|
case catch check_invitation(From, Els, Lang, StateData) of
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, Error),
|
Packet, Error),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From, Err),
|
From, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
IJID ->
|
IJID ->
|
||||||
Config = StateData#state.config,
|
Config = StateData#state.config,
|
||||||
case Config#config.members_only of
|
case Config#config.members_only of
|
||||||
true ->
|
true ->
|
||||||
case get_affiliation(IJID, StateData) of
|
case get_affiliation(IJID, StateData) of
|
||||||
none ->
|
none ->
|
||||||
NSD = set_affiliation(
|
NSD = set_affiliation(
|
||||||
IJID,
|
IJID,
|
||||||
member,
|
member,
|
||||||
StateData),
|
StateData),
|
||||||
case (NSD#state.config)#config.persistent of
|
case (NSD#state.config)#config.persistent of
|
||||||
true ->
|
true ->
|
||||||
mod_muc:store_room(
|
mod_muc:store_room(
|
||||||
NSD#state.host,
|
NSD#state.host,
|
||||||
NSD#state.room,
|
NSD#state.room,
|
||||||
make_opts(NSD));
|
make_opts(NSD));
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
{next_state, normal_state, NSD};
|
{next_state, normal_state, NSD};
|
||||||
_ ->
|
_ ->
|
||||||
{next_state, normal_state,
|
{next_state, normal_state,
|
||||||
StateData}
|
StateData}
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
IsVoiceRequest ->
|
IsVoiceRequest ->
|
||||||
NewStateData = case (StateData#state.config)#config.allow_voice_requests of
|
NewStateData =
|
||||||
true ->
|
case (StateData#state.config)#config.allow_voice_requests of
|
||||||
MinInterval = (StateData#state.config)#config.voice_request_min_interval,
|
true ->
|
||||||
BareFrom = jlib:jid_remove_resource(jlib:jid_tolower(From)),
|
MinInterval = (StateData#state.config)
|
||||||
LastTime = last_voice_request_time(BareFrom, StateData),
|
#config.voice_request_min_interval,
|
||||||
TimeFromLastRequest = timer:now_diff(erlang:now(), LastTime),
|
BareFrom = jlib:jid_remove_resource(
|
||||||
if
|
jlib:jid_tolower(From)),
|
||||||
TimeFromLastRequest > MinInterval*1000000 ->
|
LastTime = last_voice_request_time(
|
||||||
send_voice_request(From, StateData),
|
BareFrom, StateData),
|
||||||
update_voice_request_time(BareFrom, StateData);
|
TimeFromLastRequest =
|
||||||
true ->
|
timer:now_diff(
|
||||||
ErrText = "Please, wait for a while before sending new voice request",
|
now(), LastTime) div 1000000,
|
||||||
Err = jlib:make_error_reply(
|
if TimeFromLastRequest > MinInterval ->
|
||||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
send_voice_request(
|
||||||
|
From, StateData),
|
||||||
|
update_voice_request_time(
|
||||||
|
BareFrom, StateData);
|
||||||
|
true ->
|
||||||
|
ErrText = "Please, wait for "
|
||||||
|
"a while before sending "
|
||||||
|
"new voice request",
|
||||||
|
Err = jlib:make_error_reply(
|
||||||
|
Packet,
|
||||||
|
?ERRT_NOT_ACCEPTABLE(
|
||||||
|
Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
StateData#state.jid, From, Err),
|
StateData#state.jid,
|
||||||
|
From, Err),
|
||||||
StateData
|
StateData
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
ErrText = "Voice requests are disabled in this room",
|
ErrText = "Voice requests are "
|
||||||
|
"disabled in this room",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
Packet,
|
||||||
|
?ERRT_FORBIDDEN(
|
||||||
|
Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
StateData#state.jid, From, Err),
|
StateData#state.jid, From, Err),
|
||||||
StateData
|
StateData
|
||||||
end,
|
end,
|
||||||
{next_state, normal_state, NewStateData};
|
{next_state, normal_state, NewStateData};
|
||||||
IsVoiceApprovement ->
|
IsVoiceApprovement ->
|
||||||
NewStateData = case is_moderator(From, StateData) of
|
NewStateData =
|
||||||
true ->
|
case is_moderator(From, StateData) of
|
||||||
|
true ->
|
||||||
case extract_jid_from_voice_approvement(Els) of
|
case extract_jid_from_voice_approvement(Els) of
|
||||||
{error, _} ->
|
error ->
|
||||||
ErrText = "Failed to extract JID from your voice request approvement",
|
ErrText = "Failed to extract "
|
||||||
|
"JID from your voice "
|
||||||
|
"request approvement",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)),
|
Packet,
|
||||||
|
?ERRT_BAD_REQUEST(
|
||||||
|
Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
StateData#state.jid, From, Err),
|
StateData#state.jid,
|
||||||
|
From, Err),
|
||||||
StateData;
|
StateData;
|
||||||
TargetJid ->
|
{ok, TargetJid} ->
|
||||||
case is_visitor(TargetJid, StateData) of
|
case is_visitor(
|
||||||
true ->
|
TargetJid, StateData) of
|
||||||
|
true ->
|
||||||
Reason = [],
|
Reason = [],
|
||||||
NSD = set_role(TargetJid, participant, StateData),
|
NSD = set_role(
|
||||||
catch send_new_presence(TargetJid, Reason, NSD),
|
TargetJid,
|
||||||
|
participant,
|
||||||
|
StateData),
|
||||||
|
catch send_new_presence(
|
||||||
|
TargetJid,
|
||||||
|
Reason, NSD),
|
||||||
NSD;
|
NSD;
|
||||||
_ ->
|
_ ->
|
||||||
StateData
|
StateData
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
ErrText = "Only moderators can approve voice requests",
|
ErrText = "Only moderators can "
|
||||||
|
"approve voice requests",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)),
|
Packet,
|
||||||
|
?ERRT_NOT_ALLOWED(
|
||||||
|
Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
StateData#state.jid, From, Err),
|
StateData#state.jid, From, Err),
|
||||||
StateData
|
StateData
|
||||||
end,
|
end,
|
||||||
{next_state, normal_state, NewStateData};
|
{next_state, normal_state, NewStateData};
|
||||||
true ->
|
true ->
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
ErrText = "Improper message type",
|
ErrText = "Improper message type",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
|
@ -3713,153 +3744,121 @@ get_mucroom_disco_items(StateData) ->
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Voice request support
|
% Voice request support
|
||||||
|
|
||||||
is_voice_request({xmlelement, "x", _, _} = Elem) ->
|
|
||||||
case xml:get_tag_attr_s("xmlns", Elem) of
|
|
||||||
?NS_XDATA ->
|
|
||||||
Fields = jlib:parse_xdata_submit(Elem),
|
|
||||||
lists:foldl(
|
|
||||||
fun(X,Y) ->
|
|
||||||
check_voice_request_fields(X,Y)
|
|
||||||
end,
|
|
||||||
true, Fields);
|
|
||||||
_ ->
|
|
||||||
false
|
|
||||||
end;
|
|
||||||
is_voice_request(Els) ->
|
is_voice_request(Els) ->
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun(_, true) ->
|
fun({xmlelement, "x", Attrs, _} = El, false) ->
|
||||||
true;
|
case xml:get_attr_s("xmlns", Attrs) of
|
||||||
({xmlelement, "x", _, _} = X, false) ->
|
?NS_XDATA ->
|
||||||
is_voice_request(X);
|
case jlib:parse_xdata_submit(El) of
|
||||||
(_, _) ->
|
[_|_] = Fields ->
|
||||||
false
|
case {lists:keysearch("FORM_TYPE", 1, Fields),
|
||||||
end, false, Els).
|
lists:keysearch("muc#role", 1, Fields)} of
|
||||||
|
{["http://jabber.org/protocol/muc#request"],
|
||||||
check_voice_request_fields(_, false) ->
|
["participant"]} ->
|
||||||
false;
|
true;
|
||||||
check_voice_request_fields({"FORM_TYPE", ["http://jabber.org/protocol/muc#request"]}, true) ->
|
_ ->
|
||||||
true;
|
false
|
||||||
check_voice_request_fields({"FORM_TYPE", _}, _) ->
|
end;
|
||||||
false;
|
_ ->
|
||||||
check_voice_request_fields({"muc#role", ["participant"]}, true) ->
|
false
|
||||||
true;
|
end;
|
||||||
check_voice_request_fields({"muc#role", _}, _) ->
|
_ ->
|
||||||
false;
|
false
|
||||||
check_voice_request_fields(_, true) ->
|
end;
|
||||||
true. % silently ignore any extra fields
|
(_, Acc) ->
|
||||||
|
Acc
|
||||||
|
end, false, Els).
|
||||||
|
|
||||||
prepare_request_form(Requester, Nick, Lang) ->
|
prepare_request_form(Requester, Nick, Lang) ->
|
||||||
{xmlelement, "message", [{"type", "normal"}], [
|
{xmlelement, "message", [{"type", "normal"}],
|
||||||
{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
|
[{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
|
||||||
[
|
[{xmlelement, "title", [],
|
||||||
{xmlelement, "title", [],
|
[{xmlcdata, translate:translate(Lang, "Voice request")}]},
|
||||||
[{xmlcdata, translate:translate(Lang, "Voice request")}]},
|
{xmlelement, "instructions", [],
|
||||||
{xmlelement, "instructions", [],
|
[{xmlcdata,
|
||||||
[{xmlcdata, translate:translate(Lang, "To approve this request for voice, select the \"Grant voice to this person?\" checkbox and click OK. To skip this request, click the cancel button.")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"var", "FORM_TYPE"}, {"type", "hidden"}],
|
Lang, "To approve this request for voice, select the "
|
||||||
[{xmlelement, "value", [],
|
"\"Grant voice to this person?\" checkbox and click OK. "
|
||||||
[{xmlcdata, "http://jabber.org/protocol/muc#request"}]}]},
|
"To skip this request, click the cancel button.")}]},
|
||||||
?STRINGXFIELD("Requested role", "muc#role", "participant"),
|
{xmlelement, "field", [{"var", "FORM_TYPE"}, {"type", "hidden"}],
|
||||||
?STRINGXFIELD("User JID", "muc#jid", jlib:jid_to_string(Requester)),
|
[{xmlelement, "value", [],
|
||||||
?STRINGXFIELD("Nickname", "muc#roomnick", Nick),
|
[{xmlcdata, "http://jabber.org/protocol/muc#request"}]}]},
|
||||||
?BOOLXFIELD("Grant voice to this person?", "muc#request_allow", false)
|
?STRINGXFIELD("Requested role", "muc#role", "participant"),
|
||||||
]
|
?STRINGXFIELD("User JID", "muc#jid", jlib:jid_to_string(Requester)),
|
||||||
}]}.
|
?STRINGXFIELD("Nickname", "muc#roomnick", Nick),
|
||||||
|
?BOOLXFIELD("Grant voice to this person?", "muc#request_allow", false)
|
||||||
|
]}]}.
|
||||||
|
|
||||||
send_voice_request(From, StateData) ->
|
send_voice_request(From, StateData) ->
|
||||||
Moderators = search_role(moderator, StateData),
|
Moderators = search_role(moderator, StateData),
|
||||||
FromNick = find_nick_by_jid(From, StateData),
|
FromNick = find_nick_by_jid(From, StateData),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({_, User}) ->
|
fun({_, User}) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
User#user.jid,
|
User#user.jid,
|
||||||
prepare_request_form(From, FromNick, ""))
|
prepare_request_form(From, FromNick, ""))
|
||||||
end, Moderators).
|
end, Moderators).
|
||||||
|
|
||||||
is_voice_approvement({xmlelement, "x", _, _} = Elem) ->
|
|
||||||
case xml:get_tag_attr_s("xmlns", Elem) of
|
|
||||||
?NS_XDATA ->
|
|
||||||
Fields = jlib:parse_xdata_submit(Elem),
|
|
||||||
lists:foldl(
|
|
||||||
fun(X,Y) ->
|
|
||||||
check_voice_approvement_fields(X,Y)
|
|
||||||
end,
|
|
||||||
true, Fields);
|
|
||||||
_ ->
|
|
||||||
false
|
|
||||||
end;
|
|
||||||
is_voice_approvement(Els) ->
|
is_voice_approvement(Els) ->
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun(_, true) ->
|
fun({xmlelement, "x", Attrs, _} = El, false) ->
|
||||||
true;
|
case xml:get_attr_s("xmlns", Attrs) of
|
||||||
({xmlelement, "x", _, _} = X, false) ->
|
?NS_XDATA ->
|
||||||
is_voice_approvement(X);
|
case jlib:parse_xdata_submit(El) of
|
||||||
(_, _) ->
|
[_|_] = Fs ->
|
||||||
false
|
case {lists:keysearch("FORM_TYPE", 1, Fs),
|
||||||
end, false, Els).
|
lists:keysearch("muc#role", 1, Fs),
|
||||||
|
lists:keysearch("muc#request_allow", 1, Fs)} of
|
||||||
check_voice_approvement_fields(_, false) ->
|
{["http://jabber.org/protocol/muc#request"],
|
||||||
false;
|
["participant"], [Flag]}
|
||||||
check_voice_approvement_fields({"FORM_TYPE", ["http://jabber.org/protocol/muc#request"]}, true) ->
|
when Flag == "true"; Flag == "1" ->
|
||||||
true;
|
true;
|
||||||
check_voice_approvement_fields({"FORM_TYPE", _}, _) ->
|
_ ->
|
||||||
false;
|
false
|
||||||
check_voice_approvement_fields({"muc#role", ["participant"]}, true) ->
|
end;
|
||||||
true;
|
_ ->
|
||||||
check_voice_approvement_fields({"muc#role", _}, _) ->
|
false
|
||||||
false;
|
end;
|
||||||
check_voice_approvement_fields({"muc#request_allow", ["true"]}, true) ->
|
_ ->
|
||||||
true;
|
false
|
||||||
check_voice_approvement_fields({"muc#request_allow", ["1"]}, true) ->
|
end;
|
||||||
true;
|
(_, Acc) ->
|
||||||
check_voice_approvement_fields({"muc#request_allow", _}, _) ->
|
Acc
|
||||||
false;
|
end, false, Els).
|
||||||
check_voice_approvement_fields(_, true) ->
|
|
||||||
true. % do not check any other fields
|
|
||||||
|
|
||||||
extract_jid_from_voice_approvement(Els) ->
|
extract_jid_from_voice_approvement(Els) ->
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun(X, Acc) ->
|
fun({xmlelement, "x", _, _} = El, error) ->
|
||||||
case Acc of
|
Fields = case jlib:parse_xdata_submit(El) of
|
||||||
{error, _} ->
|
invalid -> [];
|
||||||
case X of
|
Res -> Res
|
||||||
{xmlelement, "x", _, _} ->
|
end,
|
||||||
Fields = jlib:parse_xdata_submit(X),
|
lists:foldl(
|
||||||
Jid = lists:foldl(
|
fun({"muc#jid", [JIDStr]}, error) ->
|
||||||
fun(T, Acc2) ->
|
case jlib:string_to_jid(JIDStr) of
|
||||||
case Acc2 of
|
error -> error;
|
||||||
{error, _} ->
|
J -> {ok, J}
|
||||||
case T of
|
end;
|
||||||
{"muc#jid", [Jid]} ->
|
(_, Acc) ->
|
||||||
Jid;
|
Acc
|
||||||
_ ->
|
end, error, Fields);
|
||||||
Acc2
|
(_, Acc) ->
|
||||||
end;
|
Acc
|
||||||
_ ->
|
end, error, Els).
|
||||||
Acc2
|
|
||||||
end
|
|
||||||
end, {error, jid_not_found}, Fields),
|
|
||||||
jlib:string_to_jid(Jid);
|
|
||||||
_ ->
|
|
||||||
Acc
|
|
||||||
end;
|
|
||||||
_ ->
|
|
||||||
Acc
|
|
||||||
end
|
|
||||||
end, {error, jid_not_found}, Els).
|
|
||||||
|
|
||||||
last_voice_request_time(BareJID, StateData) ->
|
last_voice_request_time(BareJID, StateData) ->
|
||||||
case treap:lookup(BareJID, StateData#state.last_voice_request_time) of
|
case treap:lookup(BareJID, StateData#state.last_voice_request_time) of
|
||||||
{ok, _, Value} ->
|
{ok, _, Value} ->
|
||||||
Value;
|
Value;
|
||||||
error ->
|
error ->
|
||||||
{0, 0, 0}
|
{0, 0, 0}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
update_voice_request_time(BareJID, StateData) ->
|
update_voice_request_time(BareJID, StateData) ->
|
||||||
NewDict = treap:insert(BareJID, {0, 0}, erlang:now(), StateData#state.last_voice_request_time),
|
NewDict = treap:insert(BareJID, {0, 0}, erlang:now(),
|
||||||
StateData#state{last_voice_request_time = NewDict}.
|
StateData#state.last_voice_request_time),
|
||||||
|
StateData#state{last_voice_request_time = NewDict}.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Invitation support
|
% Invitation support
|
||||||
|
|
Loading…
Reference in New Issue
Block a user