Rewrite mod_register to use XML generator
This commit is contained in:
parent
8275e95a16
commit
96e912b09a
|
@ -35,14 +35,13 @@
|
|||
|
||||
-export([start/2, stop/1, stream_feature_register/2,
|
||||
unauthenticated_iq_register/4, try_register/5,
|
||||
process_iq/3, send_registration_notifications/3,
|
||||
process_iq/1, send_registration_notifications/3,
|
||||
transform_options/1, transform_module_options/1,
|
||||
mod_opt_type/1, opt_type/1, depends/2]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
-include("jlib.hrl").
|
||||
-include("xmpp.hrl").
|
||||
|
||||
start(Host, Opts) ->
|
||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
|
||||
|
@ -79,329 +78,223 @@ stream_feature_register(Acc, Host) ->
|
|||
AF = gen_mod:get_module_opt(Host, ?MODULE, access_from,
|
||||
fun(A) -> A end,
|
||||
all),
|
||||
case (AF /= none) and lists:keymember(<<"mechanisms">>, 2, Acc) of
|
||||
case (AF /= none) and lists:keymember(sasl_mechanisms, 1, Acc) of
|
||||
true ->
|
||||
[#xmlel{name = <<"register">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_FEATURE_IQREGISTER}],
|
||||
children = []}
|
||||
| Acc];
|
||||
[#feature_register{}|Acc];
|
||||
false ->
|
||||
Acc
|
||||
end.
|
||||
|
||||
unauthenticated_iq_register(_Acc, Server,
|
||||
#iq{xmlns = ?NS_REGISTER} = IQ, IP) ->
|
||||
#iq{sub_els = [#register{}]} = IQ, IP) ->
|
||||
Address = case IP of
|
||||
{A, _Port} -> A;
|
||||
_ -> undefined
|
||||
end,
|
||||
ResIQ = process_iq(jid:make(<<"">>, <<"">>,
|
||||
<<"">>),
|
||||
jid:make(<<"">>, Server, <<"">>), IQ, Address),
|
||||
Res1 = jlib:replace_from_to(jid:make(<<"">>,
|
||||
Server, <<"">>),
|
||||
jid:make(<<"">>, <<"">>, <<"">>),
|
||||
jlib:iq_to_xml(ResIQ)),
|
||||
jlib:remove_attr(<<"to">>, Res1);
|
||||
ResIQ = process_iq(xmpp:set_from_to(IQ, jid:make(<<>>), jid:make(Server)),
|
||||
Address),
|
||||
xmpp:set_from_to(ResIQ, jid:make(Server), undefined);
|
||||
unauthenticated_iq_register(Acc, _Server, _IQ, _IP) ->
|
||||
Acc.
|
||||
|
||||
process_iq(From, To, IQ) ->
|
||||
process_iq(From, To, IQ, jid:tolower(From)).
|
||||
process_iq(#iq{from = From} = IQ) ->
|
||||
process_iq(IQ, jid:tolower(From)).
|
||||
|
||||
process_iq(From, To,
|
||||
#iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} =
|
||||
IQ,
|
||||
Source) ->
|
||||
IsCaptchaEnabled = case
|
||||
gen_mod:get_module_opt(To#jid.lserver, ?MODULE,
|
||||
captcha_protected,
|
||||
fun(B) when is_boolean(B) -> B end,
|
||||
false)
|
||||
of
|
||||
true -> true;
|
||||
_ -> false
|
||||
end,
|
||||
case Type of
|
||||
set ->
|
||||
UTag = fxml:get_subtag(SubEl, <<"username">>),
|
||||
PTag = fxml:get_subtag(SubEl, <<"password">>),
|
||||
RTag = fxml:get_subtag(SubEl, <<"remove">>),
|
||||
Server = To#jid.lserver,
|
||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access,
|
||||
fun(A) -> A end,
|
||||
all),
|
||||
AllowRemove = allow ==
|
||||
acl:match_rule(Server, Access, From),
|
||||
if (UTag /= false) and (RTag /= false) and
|
||||
AllowRemove ->
|
||||
User = fxml:get_tag_cdata(UTag),
|
||||
case From of
|
||||
#jid{user = User, lserver = Server} ->
|
||||
ejabberd_auth:remove_user(User, Server),
|
||||
IQ#iq{type = result, sub_el = []};
|
||||
_ ->
|
||||
if PTag /= false ->
|
||||
Password = fxml:get_tag_cdata(PTag),
|
||||
case ejabberd_auth:remove_user(User, Server,
|
||||
Password)
|
||||
of
|
||||
ok -> IQ#iq{type = result, sub_el = []};
|
||||
%% TODO FIXME: This piece of
|
||||
%% code does not work since
|
||||
%% the code have been changed
|
||||
%% to allow several auth
|
||||
%% modules. lists:foreach can
|
||||
%% only return ok:
|
||||
not_allowed ->
|
||||
Txt = <<"Removal is not allowed">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl,
|
||||
?ERRT_NOT_ALLOWED(Lang, Txt)]};
|
||||
not_exists ->
|
||||
Txt = <<"No such user">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el =
|
||||
[SubEl,
|
||||
?ERRT_ITEM_NOT_FOUND(Lang, Txt)]};
|
||||
Err ->
|
||||
?ERROR_MSG("failed to remove user ~s@~s: ~p",
|
||||
[User, Server, Err]),
|
||||
IQ#iq{type = error,
|
||||
sub_el =
|
||||
[SubEl,
|
||||
?ERR_INTERNAL_SERVER_ERROR]}
|
||||
end;
|
||||
true ->
|
||||
Txt = <<"No password in this query">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}
|
||||
end
|
||||
end;
|
||||
(UTag == false) and (RTag /= false) and AllowRemove ->
|
||||
case From of
|
||||
#jid{user = User, lserver = Server,
|
||||
resource = Resource} ->
|
||||
ResIQ = #iq{type = result, xmlns = ?NS_REGISTER,
|
||||
id = ID, sub_el = []},
|
||||
ejabberd_router:route(jid:make(User, Server,
|
||||
Resource),
|
||||
jid:make(User, Server,
|
||||
Resource),
|
||||
jlib:iq_to_xml(ResIQ)),
|
||||
ejabberd_auth:remove_user(User, Server),
|
||||
ignore;
|
||||
_ ->
|
||||
Txt = <<"The query is only allowed from local users">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}
|
||||
end;
|
||||
(UTag /= false) and (PTag /= false) ->
|
||||
User = fxml:get_tag_cdata(UTag),
|
||||
Password = fxml:get_tag_cdata(PTag),
|
||||
try_register_or_set_password(User, Server, Password,
|
||||
From, IQ, SubEl, Source, Lang,
|
||||
not IsCaptchaEnabled);
|
||||
IsCaptchaEnabled ->
|
||||
case ejabberd_captcha:process_reply(SubEl) of
|
||||
ok ->
|
||||
case process_xdata_submit(SubEl) of
|
||||
{ok, User, Password} ->
|
||||
try_register_or_set_password(User, Server,
|
||||
Password, From, IQ,
|
||||
SubEl, Source, Lang,
|
||||
true);
|
||||
_ ->
|
||||
Txt = <<"Incorrect data form">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}
|
||||
end;
|
||||
{error, malformed} ->
|
||||
Txt = <<"Incorrect CAPTCHA submit">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]};
|
||||
_ ->
|
||||
ErrText = <<"The CAPTCHA verification has failed">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, ErrText)]}
|
||||
end;
|
||||
true ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}
|
||||
end;
|
||||
get ->
|
||||
{IsRegistered, UsernameSubels, QuerySubels} = case From
|
||||
of
|
||||
#jid{user = User,
|
||||
lserver =
|
||||
Server} ->
|
||||
case
|
||||
ejabberd_auth:is_user_exists(User,
|
||||
Server)
|
||||
of
|
||||
true ->
|
||||
{true,
|
||||
[{xmlcdata,
|
||||
User}],
|
||||
[#xmlel{name
|
||||
=
|
||||
<<"registered">>,
|
||||
attrs
|
||||
=
|
||||
[],
|
||||
children
|
||||
=
|
||||
[]}]};
|
||||
false ->
|
||||
{false,
|
||||
[{xmlcdata,
|
||||
User}],
|
||||
[]}
|
||||
end;
|
||||
_ -> {false, [], []}
|
||||
end,
|
||||
if IsCaptchaEnabled and not IsRegistered ->
|
||||
TopInstrEl = #xmlel{name = <<"instructions">>,
|
||||
attrs = [],
|
||||
children =
|
||||
[{xmlcdata,
|
||||
translate:translate(Lang,
|
||||
<<"You need a client that supports x:data "
|
||||
"and CAPTCHA to register">>)}]},
|
||||
InstrEl = #xmlel{name = <<"instructions">>, attrs = [],
|
||||
children =
|
||||
[{xmlcdata,
|
||||
translate:translate(Lang,
|
||||
<<"Choose a username and password to register "
|
||||
"with this server">>)}]},
|
||||
UField = #xmlel{name = <<"field">>,
|
||||
attrs =
|
||||
[{<<"type">>, <<"text-single">>},
|
||||
{<<"label">>,
|
||||
translate:translate(Lang, <<"User">>)},
|
||||
{<<"var">>, <<"username">>}],
|
||||
children =
|
||||
[#xmlel{name = <<"required">>, attrs = [],
|
||||
children = []}]},
|
||||
PField = #xmlel{name = <<"field">>,
|
||||
attrs =
|
||||
[{<<"type">>, <<"text-private">>},
|
||||
{<<"label">>,
|
||||
translate:translate(Lang,
|
||||
<<"Password">>)},
|
||||
{<<"var">>, <<"password">>}],
|
||||
children =
|
||||
[#xmlel{name = <<"required">>, attrs = [],
|
||||
children = []}]},
|
||||
case ejabberd_captcha:create_captcha_x(ID, To, Lang,
|
||||
Source,
|
||||
[InstrEl, UField,
|
||||
PField])
|
||||
of
|
||||
{ok, CaptchaEls} ->
|
||||
IQ#iq{type = result,
|
||||
sub_el =
|
||||
[#xmlel{name = <<"query">>,
|
||||
attrs =
|
||||
[{<<"xmlns">>,
|
||||
?NS_REGISTER}],
|
||||
children =
|
||||
[TopInstrEl | CaptchaEls]}]};
|
||||
{error, limit} ->
|
||||
ErrText = <<"Too many CAPTCHA requests">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el =
|
||||
[SubEl,
|
||||
?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)]};
|
||||
_Err ->
|
||||
ErrText = <<"Unable to generate a CAPTCHA">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el =
|
||||
[SubEl,
|
||||
?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)]}
|
||||
end;
|
||||
true ->
|
||||
IQ#iq{type = result,
|
||||
sub_el =
|
||||
[#xmlel{name = <<"query">>,
|
||||
attrs =
|
||||
[{<<"xmlns">>,
|
||||
?NS_REGISTER}],
|
||||
children =
|
||||
[#xmlel{name = <<"instructions">>,
|
||||
attrs = [],
|
||||
children =
|
||||
[{xmlcdata,
|
||||
translate:translate(Lang,
|
||||
<<"Choose a username and password to register "
|
||||
"with this server">>)}]},
|
||||
#xmlel{name = <<"username">>,
|
||||
attrs = [],
|
||||
children = UsernameSubels},
|
||||
#xmlel{name = <<"password">>,
|
||||
attrs = [], children = []}
|
||||
| QuerySubels]}]}
|
||||
end
|
||||
process_iq(#iq{from = From, to = To} = IQ, Source) ->
|
||||
IsCaptchaEnabled =
|
||||
case gen_mod:get_module_opt(To#jid.lserver, ?MODULE,
|
||||
captcha_protected,
|
||||
fun(B) when is_boolean(B) -> B end,
|
||||
false) of
|
||||
true -> true;
|
||||
false -> false
|
||||
end,
|
||||
Server = To#jid.lserver,
|
||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access,
|
||||
fun(A) -> A end, all),
|
||||
AllowRemove = allow == acl:match_rule(Server, Access, From),
|
||||
process_iq(IQ, Source, IsCaptchaEnabled, AllowRemove).
|
||||
|
||||
process_iq(#iq{type = set, lang = Lang,
|
||||
sub_els = [#register{remove = true}]} = IQ,
|
||||
_Source, _IsCaptchaEnabled, _AllowRemove = false) ->
|
||||
Txt = <<"Denied by ACL">>,
|
||||
xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang));
|
||||
process_iq(#iq{type = set, lang = Lang, to = To, from = From,
|
||||
sub_els = [#register{remove = true,
|
||||
username = User,
|
||||
password = Password}]} = IQ,
|
||||
_Source, _IsCaptchaEnabled, _AllowRemove = true) ->
|
||||
Server = To#jid.lserver,
|
||||
if is_binary(User) ->
|
||||
case From of
|
||||
#jid{user = User, lserver = Server} ->
|
||||
ejabberd_auth:remove_user(User, Server),
|
||||
xmpp:make_iq_result(IQ);
|
||||
_ ->
|
||||
if is_binary(Password) ->
|
||||
ejabberd_auth:remove_user(User, Server, Password),
|
||||
xmpp:make_iq_result(IQ);
|
||||
true ->
|
||||
Txt = <<"No 'password' found in this query">>,
|
||||
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang))
|
||||
end
|
||||
end;
|
||||
true ->
|
||||
case From of
|
||||
#jid{user = User, lserver = Server, resource = Resource} ->
|
||||
ResIQ = xmpp:make_iq_result(IQ),
|
||||
ejabberd_router:route(jid:make(User, Server, Resource),
|
||||
jid:make(User, Server, Resource),
|
||||
ResIQ),
|
||||
ejabberd_auth:remove_user(User, Server),
|
||||
ignore;
|
||||
_ ->
|
||||
Txt = <<"The query is only allowed from local users">>,
|
||||
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang))
|
||||
end
|
||||
end;
|
||||
process_iq(#iq{type = set, to = To,
|
||||
sub_els = [#register{username = User,
|
||||
password = Password}]} = IQ,
|
||||
Source, IsCaptchaEnabled, _AllowRemove) when is_binary(User),
|
||||
is_binary(Password) ->
|
||||
Server = To#jid.lserver,
|
||||
try_register_or_set_password(
|
||||
User, Server, Password, IQ, Source, not IsCaptchaEnabled);
|
||||
process_iq(#iq{type = set, to = To,
|
||||
lang = Lang, sub_els = [#register{xdata = #xdata{} = X}]} = IQ,
|
||||
Source, true, _AllowRemove) ->
|
||||
Server = To#jid.lserver,
|
||||
case ejabberd_captcha:process_reply(X) of
|
||||
ok ->
|
||||
case process_xdata_submit(X) of
|
||||
{ok, User, Password} ->
|
||||
try_register_or_set_password(
|
||||
User, Server, Password, IQ, Source, true);
|
||||
_ ->
|
||||
Txt = <<"Incorrect data form">>,
|
||||
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang))
|
||||
end;
|
||||
{error, malformed} ->
|
||||
Txt = <<"Incorrect CAPTCHA submit">>,
|
||||
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
|
||||
_ ->
|
||||
ErrText = <<"The CAPTCHA verification has failed">>,
|
||||
xmpp:make_error(IQ, xmpp:err_not_allowed(ErrText, Lang))
|
||||
end;
|
||||
process_iq(#iq{type = set} = IQ, _Source, _IsCaptchaEnabled, _AllowRemove) ->
|
||||
xmpp:make_error(IQ, xmpp:err_bad_request());
|
||||
process_iq(#iq{type = get, from = From, to = To, id = ID, lang = Lang} = IQ,
|
||||
Source, IsCaptchaEnabled, _AllowRemove) ->
|
||||
Server = To#jid.lserver,
|
||||
{IsRegistered, Username} =
|
||||
case From of
|
||||
#jid{user = User, lserver = Server} ->
|
||||
case ejabberd_auth:is_user_exists(User, Server) of
|
||||
true ->
|
||||
{true, User};
|
||||
false ->
|
||||
{false, User}
|
||||
end;
|
||||
_ ->
|
||||
{false, <<"">>}
|
||||
end,
|
||||
if IsCaptchaEnabled and not IsRegistered ->
|
||||
TopInstr = translate:translate(
|
||||
Lang, <<"You need a client that supports x:data "
|
||||
"and CAPTCHA to register">>),
|
||||
Instr = translate:translate(
|
||||
Lang, <<"Choose a username and password to register "
|
||||
"with this server">>),
|
||||
UField = #xdata_field{type = 'text-single',
|
||||
label = translate:translate(Lang, <<"User">>),
|
||||
var = <<"username">>,
|
||||
required = true},
|
||||
PField = #xdata_field{type = 'text-private',
|
||||
label = translate:translate(Lang, <<"Password">>),
|
||||
var = <<"password">>,
|
||||
required = true},
|
||||
X = #xdata{type = form, instructions = [Instr],
|
||||
fields = [UField, PField]},
|
||||
case ejabberd_captcha:create_captcha_x(ID, To, Lang, Source, X) of
|
||||
{ok, Captcha} ->
|
||||
xmpp:make_iq_result(
|
||||
IQ, #register{instructions = TopInstr,
|
||||
xdata = Captcha});
|
||||
{error, limit} ->
|
||||
ErrText = <<"Too many CAPTCHA requests">>,
|
||||
xmpp:make_error(
|
||||
IQ, xmpp:err_resource_constraint(ErrText, Lang));
|
||||
_Err ->
|
||||
ErrText = <<"Unable to generate a CAPTCHA">>,
|
||||
xmpp:make_error(
|
||||
IQ, xmpp:err_internal_server_error(ErrText, Lang))
|
||||
end;
|
||||
true ->
|
||||
Instr = <<"Choose a username and password to register with this server">>,
|
||||
xmpp:make_iq_result(
|
||||
IQ,
|
||||
#register{instructions = translate:translate(Lang, Instr),
|
||||
username = Username,
|
||||
password = <<"">>,
|
||||
registered = IsRegistered})
|
||||
end.
|
||||
|
||||
try_register_or_set_password(User, Server, Password,
|
||||
From, IQ, SubEl, Source, Lang, CaptchaSucceed) ->
|
||||
#iq{from = From, lang = Lang} = IQ,
|
||||
Source, CaptchaSucceed) ->
|
||||
case From of
|
||||
#jid{user = User, lserver = Server} ->
|
||||
try_set_password(User, Server, Password, IQ, SubEl,
|
||||
Lang);
|
||||
_ when CaptchaSucceed ->
|
||||
case check_from(From, Server) of
|
||||
allow ->
|
||||
case try_register(User, Server, Password, Source, Lang)
|
||||
of
|
||||
ok -> IQ#iq{type = result, sub_el = []};
|
||||
{error, Error} ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
||||
end;
|
||||
deny ->
|
||||
Txt = <<"Denied by ACL">>,
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}
|
||||
end;
|
||||
_ ->
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
||||
#jid{user = User, lserver = Server} ->
|
||||
try_set_password(User, Server, Password, IQ);
|
||||
_ when CaptchaSucceed ->
|
||||
case check_from(From, Server) of
|
||||
allow ->
|
||||
case try_register(User, Server, Password, Source, Lang) of
|
||||
ok ->
|
||||
xmpp:make_iq_result(IQ);
|
||||
{error, Error} ->
|
||||
xmpp:make_error(IQ, Error)
|
||||
end;
|
||||
deny ->
|
||||
Txt = <<"Denied by ACL">>,
|
||||
xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang))
|
||||
end;
|
||||
_ ->
|
||||
xmpp:make_error(IQ, xmpp:err_not_allowed())
|
||||
end.
|
||||
|
||||
%% @doc Try to change password and return IQ response
|
||||
try_set_password(User, Server, Password, IQ, SubEl,
|
||||
Lang) ->
|
||||
try_set_password(User, Server, Password, #iq{lang = Lang} = IQ) ->
|
||||
case is_strong_password(Server, Password) of
|
||||
true ->
|
||||
case ejabberd_auth:set_password(User, Server, Password)
|
||||
of
|
||||
ok -> IQ#iq{type = result, sub_el = []};
|
||||
case ejabberd_auth:set_password(User, Server, Password) of
|
||||
ok ->
|
||||
xmpp:make_iq_result(IQ);
|
||||
{error, empty_password} ->
|
||||
Txt = <<"Empty password">>,
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]};
|
||||
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
|
||||
{error, not_allowed} ->
|
||||
Txt = <<"Changing password is not allowed">>,
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
|
||||
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
||||
{error, invalid_jid} ->
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERR_JID_MALFORMED]};
|
||||
xmpp:make_error(IQ, xmpp:err_jid_malformed());
|
||||
Err ->
|
||||
?ERROR_MSG("failed to register user ~s@~s: ~p",
|
||||
[User, Server, Err]),
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
|
||||
xmpp:make_error(IQ, xmpp:err_internal_server_error())
|
||||
end;
|
||||
error_preparing_password ->
|
||||
ErrText = <<"The password contains unacceptable characters">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)]};
|
||||
xmpp:make_error(IQ, xmpp:err_not_acceptable(ErrText, Lang));
|
||||
false ->
|
||||
ErrText = <<"The password is too weak">>,
|
||||
IQ#iq{type = error,
|
||||
sub_el = [SubEl, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)]}
|
||||
xmpp:make_error(IQ, xmpp:err_not_acceptable(ErrText, Lang))
|
||||
end.
|
||||
|
||||
try_register(User, Server, Password, SourceRaw, Lang) ->
|
||||
case jid:is_nodename(User) of
|
||||
false -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Malformed username">>)};
|
||||
false -> {error, xmpp:err_bad_request(<<"Malformed username">>, Lang)};
|
||||
_ ->
|
||||
JID = jid:make(User, Server, <<"">>),
|
||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access,
|
||||
|
@ -411,8 +304,8 @@ try_register(User, Server, Password, SourceRaw, Lang) ->
|
|||
case {acl:match_rule(Server, Access, JID),
|
||||
check_ip_access(SourceRaw, IPAccess)}
|
||||
of
|
||||
{deny, _} -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)};
|
||||
{_, deny} -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)};
|
||||
{deny, _} -> {error, xmpp:err_forbidden(<<"Denied by ACL">>, Lang)};
|
||||
{_, deny} -> {error, xmpp:err_forbidden(<<"Denied by ACL">>, Lang)};
|
||||
{allow, allow} ->
|
||||
Source = may_remove_resource(SourceRaw),
|
||||
case check_timeout(Source) of
|
||||
|
@ -432,35 +325,35 @@ try_register(User, Server, Password, SourceRaw, Lang) ->
|
|||
case Error of
|
||||
{atomic, exists} ->
|
||||
Txt = <<"User already exists">>,
|
||||
{error, ?ERRT_CONFLICT(Lang, Txt)};
|
||||
{error, xmpp:err_conflict(Txt, Lang)};
|
||||
{error, invalid_jid} ->
|
||||
{error, ?ERR_JID_MALFORMED};
|
||||
{error, xmpp:err_jid_malformed()};
|
||||
{error, not_allowed} ->
|
||||
{error, ?ERR_NOT_ALLOWED};
|
||||
{error, xmpp:err_not_allowed()};
|
||||
{error, too_many_users} ->
|
||||
Txt = <<"Too many users registered">>,
|
||||
{error, ?ERRT_RESOURCE_CONSTRAINT(Lang, Txt)};
|
||||
{error, xmpp:err_resource_constraint(Txt, Lang)};
|
||||
{error, _} ->
|
||||
?ERROR_MSG("failed to register user "
|
||||
"~s@~s: ~p",
|
||||
[User, Server, Error]),
|
||||
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||
{error, xmpp:err_internal_server_error()}
|
||||
end
|
||||
end;
|
||||
error_preparing_password ->
|
||||
remove_timeout(Source),
|
||||
ErrText = <<"The password contains unacceptable characters">>,
|
||||
{error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)};
|
||||
{error, xmpp:err_not_acceptable(ErrText, Lang)};
|
||||
false ->
|
||||
remove_timeout(Source),
|
||||
ErrText = <<"The password is too weak">>,
|
||||
{error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)}
|
||||
{error, xmpp:err_not_acceptable(ErrText, Lang)}
|
||||
end;
|
||||
false ->
|
||||
ErrText =
|
||||
<<"Users are not allowed to register accounts "
|
||||
"so quickly">>,
|
||||
{error, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)}
|
||||
{error, xmpp:err_resource_constraint(ErrText, Lang)}
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
@ -479,20 +372,10 @@ send_welcome_message(JID) ->
|
|||
of
|
||||
{<<"">>, <<"">>} -> ok;
|
||||
{Subj, Body} ->
|
||||
ejabberd_router:route(jid:make(<<"">>, Host,
|
||||
<<"">>),
|
||||
JID,
|
||||
#xmlel{name = <<"message">>,
|
||||
attrs = [{<<"type">>, <<"normal">>}],
|
||||
children =
|
||||
[#xmlel{name = <<"subject">>,
|
||||
attrs = [],
|
||||
children =
|
||||
[{xmlcdata, Subj}]},
|
||||
#xmlel{name = <<"body">>,
|
||||
attrs = [],
|
||||
children =
|
||||
[{xmlcdata, Body}]}]});
|
||||
ejabberd_router:route(
|
||||
jid:make(Host), JID,
|
||||
#message{subject = xmpp:mk_text(Subj),
|
||||
body = xmpp:mk_text(Body)});
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
|
@ -516,13 +399,9 @@ send_registration_notifications(Mod, UJID, Source) ->
|
|||
lists:foreach(
|
||||
fun(JID) ->
|
||||
ejabberd_router:route(
|
||||
jid:make(<<"">>, Host, <<"">>),
|
||||
JID,
|
||||
#xmlel{name = <<"message">>,
|
||||
attrs = [{<<"type">>, <<"chat">>}],
|
||||
children = [#xmlel{name = <<"body">>,
|
||||
attrs = [],
|
||||
children = [{xmlcdata,Body}]}]})
|
||||
jid:make(Host), JID,
|
||||
#message{type = chat,
|
||||
body = xmpp:mk_text(Body)})
|
||||
end, JIDs)
|
||||
end.
|
||||
|
||||
|
@ -633,17 +512,11 @@ write_time({{Y, Mo, D}, {H, Mi, S}}) ->
|
|||
io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
||||
[Y, Mo, D, H, Mi, S]).
|
||||
|
||||
process_xdata_submit(El) ->
|
||||
case fxml:get_subtag(El, <<"x">>) of
|
||||
false -> error;
|
||||
Xdata ->
|
||||
Fields = jlib:parse_xdata_submit(Xdata),
|
||||
case catch {proplists:get_value(<<"username">>, Fields),
|
||||
proplists:get_value(<<"password">>, Fields)}
|
||||
of
|
||||
{[User | _], [Pass | _]} -> {ok, User, Pass};
|
||||
_ -> error
|
||||
end
|
||||
process_xdata_submit(X) ->
|
||||
case {xmpp_util:get_xdata_values(<<"username">>, X),
|
||||
xmpp_util:get_xdata_values(<<"password">>, X)} of
|
||||
{[User], [Pass]} -> {ok, User, Pass};
|
||||
_ -> error
|
||||
end.
|
||||
|
||||
is_strong_password(Server, Password) ->
|
||||
|
|
Loading…
Reference in New Issue