]> granicus.if.org Git - ejabberd/commitdiff
Rewrite mod_register to use XML generator
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 27 Jul 2016 15:06:54 +0000 (18:06 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Wed, 27 Jul 2016 15:06:54 +0000 (18:06 +0300)
src/mod_register.erl

index 45cd78fefd4e9a6911b4416952c2babf8ad49d04..3f9c33123d9f9e1160f5d4e92e6f97b62f15f371 100644 (file)
 
 -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(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} = IQ) ->
+    process_iq(IQ, jid:tolower(From)).
+
+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) ->