diff options
author | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2016-04-05 13:10:09 +0300 |
---|---|---|
committer | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2016-04-05 13:10:09 +0300 |
commit | 232915184c0301fb11b15662dd23f2fcde55791f (patch) | |
tree | f49301772e5449d825766cfefe5b3492ebf370ba | |
parent | Merge pull request #1046 from processone/commands-update (diff) | |
parent | Replace more ?ERR_* macros with ?ERRT_* (diff) |
Merge branch 'add-error-reason'
42 files changed, 1021 insertions, 621 deletions
diff --git a/src/adhoc.erl b/src/adhoc.erl index 788bf65a..83a113a0 100644 --- a/src/adhoc.erl +++ b/src/adhoc.erl @@ -68,7 +68,9 @@ parse_request(#iq{type = set, lang = Lang, sub_el = SubEl, xmlns = ?NS_COMMANDS} xdata = XData, others = Others }; -parse_request(_) -> {error, ?ERR_BAD_REQUEST}. +parse_request(#iq{lang = Lang}) -> + Text = <<"Failed to parse ad-hoc command request">>, + {error, ?ERRT_BAD_REQUEST(Lang, Text)}. %% Borrowed from mod_vcard.erl find_xdata_el(#xmlel{children = SubEls}) -> diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 936abc7a..3736f7d0 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -619,8 +619,9 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> send_element(StateData, Res), fsm_next_state(wait_for_auth, StateData); {auth, _ID, set, {_U, _P, _D, <<"">>}} -> - Err = jlib:make_error_reply(El, - ?ERR_AUTH_NO_RESOURCE_PROVIDED((StateData#state.lang))), + Lang = StateData#state.lang, + Txt = <<"No resource provided">>, + Err = jlib:make_error_reply(El, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)), send_element(StateData, Err), fsm_next_state(wait_for_auth, StateData); {auth, _ID, set, {U, P, D, R}} -> @@ -685,7 +686,10 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, U, StateData#state.server, StateData#state.ip]), - Err = jlib:make_error_reply(El, ?ERR_NOT_AUTHORIZED), + Lang = StateData#state.lang, + Txt = <<"Legacy authentication failed">>, + Err = jlib:make_error_reply( + El, ?ERRT_NOT_AUTHORIZED(Lang, Txt)), send_element(StateData, Err), fsm_next_state(wait_for_auth, StateData) end; @@ -706,7 +710,9 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, U, StateData#state.server, StateData#state.ip]), - Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), + Lang = StateData#state.lang, + Txt = <<"Legacy authentication forbidden">>, + Err = jlib:make_error_reply(El, ?ERRT_NOT_ALLOWED(Lang, Txt)), send_element(StateData, Err), fsm_next_state(wait_for_auth, StateData) end @@ -1013,7 +1019,7 @@ wait_for_bind({xmlstreamelement, #xmlel{name = Name, attrs = Attrs} = El}, end; wait_for_bind({xmlstreamelement, El}, StateData) -> case jlib:iq_query_info(El) of - #iq{type = set, xmlns = ?NS_BIND, sub_el = SubEl} = + #iq{type = set, lang = Lang, xmlns = ?NS_BIND, sub_el = SubEl} = IQ -> U = StateData#state.user, R1 = fxml:get_path_s(SubEl, @@ -1025,7 +1031,8 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> end, case R of error -> - Err = jlib:make_error_reply(El, ?ERR_BAD_REQUEST), + Txt = <<"Malformed resource">>, + Err = jlib:make_error_reply(El, ?ERRT_BAD_REQUEST(Lang, Txt)), send_element(StateData, Err), fsm_next_state(wait_for_bind, StateData); _ -> @@ -1099,6 +1106,7 @@ open_session(StateData) -> U = StateData#state.user, R = StateData#state.resource, JID = StateData#state.jid, + Lang = StateData#state.lang, case acl:match_rule(StateData#state.server, StateData#state.access, JID) of allow -> @@ -1136,7 +1144,8 @@ open_session(StateData) -> StateData#state.server, [JID]), ?INFO_MSG("(~w) Forbidden session for ~s", [StateData#state.socket, jid:to_string(JID)]), - {error, ?ERR_NOT_ALLOWED} + Txt = <<"Denied by ACL">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt)} end. session_established({xmlstreamelement, #xmlel{name = Name} = El}, StateData) @@ -2275,30 +2284,32 @@ get_priority_from_presence(PresencePacket) -> end. process_privacy_iq(From, To, - #iq{type = Type, sub_el = SubEl} = IQ, StateData) -> - {Res, NewStateData} = case Type of - get -> - R = ejabberd_hooks:run_fold(privacy_iq_get, - StateData#state.server, - {error, - ?ERR_FEATURE_NOT_IMPLEMENTED}, - [From, To, IQ, - StateData#state.privacy_list]), - {R, StateData}; - set -> - case ejabberd_hooks:run_fold(privacy_iq_set, - StateData#state.server, - {error, - ?ERR_FEATURE_NOT_IMPLEMENTED}, - [From, To, IQ]) - of - {result, R, NewPrivList} -> - {{result, R}, - StateData#state{privacy_list = - NewPrivList}}; - R -> {R, StateData} - end - end, + #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ, StateData) -> + Txt = <<"No module is handling this query">>, + {Res, NewStateData} = + case Type of + get -> + R = ejabberd_hooks:run_fold( + privacy_iq_get, + StateData#state.server, + {error, ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)}, + [From, To, IQ, + StateData#state.privacy_list]), + {R, StateData}; + set -> + case ejabberd_hooks:run_fold( + privacy_iq_set, + StateData#state.server, + {error, ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)}, + [From, To, IQ]) + of + {result, R, NewPrivList} -> + {{result, R}, + StateData#state{privacy_list = + NewPrivList}}; + R -> {R, StateData} + end + end, IQRes = case Res of {result, Result} -> IQ#iq{type = result, sub_el = Result}; @@ -2365,15 +2376,16 @@ process_unauthenticated_stanza(StateData, El) -> _ -> El end, case jlib:iq_query_info(NewEl) of - #iq{} = IQ -> + #iq{lang = L} = IQ -> Res = ejabberd_hooks:run_fold(c2s_unauthenticated_iq, StateData#state.server, empty, [StateData#state.server, IQ, StateData#state.ip]), case Res of empty -> + Txt = <<"Authentication required">>, ResIQ = IQ#iq{type = error, - sub_el = [?ERR_SERVICE_UNAVAILABLE]}, + sub_el = [?ERRT_SERVICE_UNAVAILABLE(L, Txt)]}, Res1 = jlib:replace_from_to(jid:make(<<"">>, StateData#state.server, <<"">>), @@ -2879,6 +2891,7 @@ handle_unacked_stanzas(StateData) false end end, + Lang = StateData#state.lang, ReRoute = case ResendOnTimeout of true -> fun(From, To, El, Time) -> @@ -2887,9 +2900,11 @@ handle_unacked_stanzas(StateData) end; false -> fun(From, To, El, _Time) -> + Txt = <<"User session not found">>, Err = - jlib:make_error_reply(El, - ?ERR_SERVICE_UNAVAILABLE), + jlib:make_error_reply( + El, + ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)), ejabberd_router:route(To, From, Err) end end, @@ -2897,7 +2912,9 @@ handle_unacked_stanzas(StateData) ?DEBUG("Dropping presence stanza from ~s", [jid:to_string(From)]); (From, To, #xmlel{name = <<"iq">>} = El, _Time) -> - Err = jlib:make_error_reply(El, ?ERR_SERVICE_UNAVAILABLE), + Txt = <<"User session not found">>, + Err = jlib:make_error_reply( + El, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)), ejabberd_router:route(To, From, Err); (From, To, El, Time) -> %% We'll drop the stanza if it was <forwarded/> by some diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 7c30f3b6..5566073e 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -74,7 +74,7 @@ start_link() -> process_iq(From, To, Packet) -> IQ = jlib:iq_query_info(Packet), case IQ of - #iq{xmlns = XMLNS} -> + #iq{xmlns = XMLNS, lang = Lang} -> Host = To#jid.lserver, case ets:lookup(?IQTABLE, {XMLNS, Host}) of [{_, Module, Function}] -> @@ -87,8 +87,10 @@ process_iq(From, To, Packet) -> gen_iq_handler:handle(Host, Module, Function, Opts, From, To, IQ); [] -> - Err = jlib:make_error_reply(Packet, - ?ERR_FEATURE_NOT_IMPLEMENTED), + Txt = <<"No module is handling this query">>, + Err = jlib:make_error_reply( + Packet, + ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)), ejabberd_router:route(To, From, Err) end; reply -> @@ -166,8 +168,10 @@ refresh_iq_handlers() -> ejabberd_local ! refresh_iq_handlers. bounce_resource_packet(From, To, Packet) -> + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"No available resource found">>, Err = jlib:make_error_reply(Packet, - ?ERR_ITEM_NOT_FOUND), + ?ERRT_ITEM_NOT_FOUND(Lang, Txt)), ejabberd_router:route(To, From, Err), stop. diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 0eab4633..be1ee465 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -312,8 +312,10 @@ do_route(From, To, Packet) -> <<"error">> -> ok; <<"result">> -> ok; _ -> - Err = jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"No s2s connection found">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)), ejabberd_router:route(To, From, Err) end, false diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 5caae610..465fb587 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -280,7 +280,9 @@ stream_established({xmlstreamelement, El}, StateData) -> and (FromJID /= error) -> ejabberd_router:route(FromJID, ToJID, NewEl); true -> - Err = jlib:make_error_reply(NewEl, ?ERR_BAD_REQUEST), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, El), + Txt = <<"Incorrect stanza name or from/to JID">>, + Err = jlib:make_error_reply(NewEl, ?ERRT_BAD_REQUEST(Lang, Txt)), send_element(StateData, Err), error end, @@ -360,7 +362,9 @@ handle_info({route, From, To, Packet}, StateName, attrs = Attrs2, children = Els}), send_text(StateData, Text); deny -> - Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, Txt)), ejabberd_router:route_error(To, From, Err, Packet) end, {next_state, StateName, StateData}; diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 218e657f..4f7cfeea 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -159,8 +159,10 @@ check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) -> -spec bounce_offline_message(jid(), jid(), xmlel()) -> stop. bounce_offline_message(From, To, Packet) -> - Err = jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"User session not found">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)), ejabberd_router:route(To, From, Err), stop. @@ -423,6 +425,7 @@ do_route(From, To, #xmlel{} = Packet) -> #jid{user = User, server = Server, luser = LUser, lserver = LServer, lresource = LResource} = To, #xmlel{name = Name, attrs = Attrs} = Packet, + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), case LResource of <<"">> -> case Name of @@ -496,8 +499,9 @@ do_route(From, To, #xmlel{} = Packet) -> <<"headline">> -> route_message(From, To, Packet, headline); <<"error">> -> ok; <<"groupchat">> -> - Err = jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), + ErrTxt = <<"Incorrect message type">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_SERVICE_UNAVAILABLE(Lang, ErrTxt)), ejabberd_router:route(To, From, Err); _ -> route_message(From, To, Packet, normal) @@ -517,8 +521,10 @@ do_route(From, To, #xmlel{} = Packet) -> <<"">> -> route_message(From, To, Packet, normal); <<"error">> -> ok; _ -> - Err = jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), + ErrTxt = <<"Incorrect message type">>, + Err = jlib:make_error_reply( + Packet, + ?ERRT_SERVICE_UNAVAILABLE(Lang, ErrTxt)), ejabberd_router:route(To, From, Err) end; <<"iq">> -> @@ -526,8 +532,10 @@ do_route(From, To, #xmlel{} = Packet) -> <<"error">> -> ok; <<"result">> -> ok; _ -> - Err = jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), + ErrTxt = <<"User session not found">>, + Err = jlib:make_error_reply( + Packet, + ?ERRT_SERVICE_UNAVAILABLE(Lang, ErrTxt)), ejabberd_router:route(To, From, Err) end; _ -> ?DEBUG("packet dropped~n", []) @@ -684,7 +692,7 @@ get_max_user_sessions(LUser, Host) -> process_iq(From, To, Packet) -> IQ = jlib:iq_query_info(Packet), case IQ of - #iq{xmlns = XMLNS} -> + #iq{xmlns = XMLNS, lang = Lang} -> Host = To#jid.lserver, case ets:lookup(sm_iqtable, {XMLNS, Host}) of [{_, Module, Function}] -> @@ -697,8 +705,10 @@ process_iq(From, To, Packet) -> gen_iq_handler:handle(Host, Module, Function, Opts, From, To, IQ); [] -> - Err = jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), + Txt = <<"No module is handling this query">>, + Err = jlib:make_error_reply( + Packet, + ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)), ejabberd_router:route(To, From, Err) end; reply -> ok; diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index 9947c84a..9e0682f7 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -233,7 +233,7 @@ process_sm_iq(From, To, IQ) -> process_adhoc_request(From, To, IQ, adhoc_sm_commands). process_adhoc_request(From, To, - #iq{sub_el = SubEl} = IQ, Hook) -> + #iq{sub_el = SubEl, lang = Lang} = IQ, Hook) -> ?DEBUG("About to parse ~p...", [IQ]), case adhoc:parse_request(IQ) of {error, Error} -> @@ -245,8 +245,9 @@ process_adhoc_request(From, To, of ignore -> ignore; empty -> + Txt = <<"No hook has processed this command">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}; + sub_el = [SubEl, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]}; Command -> IQ#iq{type = result, sub_el = [Command]} @@ -277,7 +278,9 @@ ping_command(_Acc, _From, _To, [{<<"info">>, translate:translate(Lang, <<"Pong">>)}]}); - true -> {error, ?ERR_BAD_REQUEST} + true -> + Txt = <<"Incorrect value of 'action' attribute">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end; ping_command(Acc, _From, _To, _Request) -> Acc. diff --git a/src/mod_announce.erl b/src/mod_announce.erl index d30cf57f..0cf8c534 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -211,15 +211,15 @@ disco_identity(Acc, _From, _To, Node, Lang) -> %%------------------------------------------------------------------------- --define(INFO_RESULT(Allow, Feats), +-define(INFO_RESULT(Allow, Feats, Lang), case Allow of deny -> - {error, ?ERR_FORBIDDEN}; + {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; allow -> {result, Feats} end). -disco_features(Acc, From, #jid{lserver = LServer} = _To, <<"announce">>, _Lang) -> +disco_features(Acc, From, #jid{lserver = LServer} = _To, <<"announce">>, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; @@ -229,13 +229,14 @@ disco_features(Acc, From, #jid{lserver = LServer} = _To, <<"announce">>, _Lang) case {acl:match_rule(LServer, Access1, From), acl:match_rule(global, Access2, From)} of {deny, deny} -> - {error, ?ERR_FORBIDDEN}; + Txt = <<"Denied by ACL">>, + {error, ?ERRT_FORBIDDEN(Lang, Txt)}; _ -> {result, []} end end; -disco_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> +disco_features(Acc, From, #jid{lserver = LServer} = _To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; @@ -246,25 +247,25 @@ disco_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> AllowGlobal = acl:match_rule(global, AccessGlobal, From), case Node of ?NS_ADMIN_ANNOUNCE -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMIN_ANNOUNCE_ALL -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMIN_SET_MOTD -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMIN_EDIT_MOTD -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMIN_DELETE_MOTD -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMIN_ANNOUNCE_ALLHOSTS -> - ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); + ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS], Lang); ?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS -> - ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); + ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS], Lang); ?NS_ADMIN_SET_MOTD_ALLHOSTS -> - ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); + ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS], Lang); ?NS_ADMIN_EDIT_MOTD_ALLHOSTS -> - ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); + ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS], Lang); ?NS_ADMIN_DELETE_MOTD_ALLHOSTS -> - ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); + ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS], Lang); _ -> Acc end @@ -283,10 +284,10 @@ disco_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> } )). --define(ITEMS_RESULT(Allow, Items), +-define(ITEMS_RESULT(Allow, Items, Lang), case Allow of deny -> - {error, ?ERR_FORBIDDEN}; + {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; allow -> {result, Items} end). @@ -320,7 +321,7 @@ disco_items(Acc, From, #jid{lserver = LServer} = To, <<"announce">>, Lang) -> announce_items(Acc, From, To, Lang) end; -disco_items(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> +disco_items(Acc, From, #jid{lserver = LServer} = _To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; @@ -331,25 +332,25 @@ disco_items(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> AllowGlobal = acl:match_rule(global, AccessGlobal, From), case Node of ?NS_ADMIN_ANNOUNCE -> - ?ITEMS_RESULT(Allow, []); + ?ITEMS_RESULT(Allow, [], Lang); ?NS_ADMIN_ANNOUNCE_ALL -> - ?ITEMS_RESULT(Allow, []); + ?ITEMS_RESULT(Allow, [], Lang); ?NS_ADMIN_SET_MOTD -> - ?ITEMS_RESULT(Allow, []); + ?ITEMS_RESULT(Allow, [], Lang); ?NS_ADMIN_EDIT_MOTD -> - ?ITEMS_RESULT(Allow, []); + ?ITEMS_RESULT(Allow, [], Lang); ?NS_ADMIN_DELETE_MOTD -> - ?ITEMS_RESULT(Allow, []); + ?ITEMS_RESULT(Allow, [], Lang); ?NS_ADMIN_ANNOUNCE_ALLHOSTS -> - ?ITEMS_RESULT(AllowGlobal, []); + ?ITEMS_RESULT(AllowGlobal, [], Lang); ?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS -> - ?ITEMS_RESULT(AllowGlobal, []); + ?ITEMS_RESULT(AllowGlobal, [], Lang); ?NS_ADMIN_SET_MOTD_ALLHOSTS -> - ?ITEMS_RESULT(AllowGlobal, []); + ?ITEMS_RESULT(AllowGlobal, [], Lang); ?NS_ADMIN_EDIT_MOTD_ALLHOSTS -> - ?ITEMS_RESULT(AllowGlobal, []); + ?ITEMS_RESULT(AllowGlobal, [], Lang); ?NS_ADMIN_DELETE_MOTD_ALLHOSTS -> - ?ITEMS_RESULT(AllowGlobal, []); + ?ITEMS_RESULT(AllowGlobal, [], Lang); _ -> Acc end @@ -396,7 +397,8 @@ announce_items(Acc, From, #jid{lserver = LServer, server = Server} = _To, Lang) commands_result(Allow, From, To, Request) -> case Allow of deny -> - {error, ?ERR_FORBIDDEN}; + Lang = Request#adhoc_request.lang, + {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; allow -> announce_commands(From, To, Request) end. @@ -463,12 +465,13 @@ announce_commands(From, To, %% User returns form. case jlib:parse_xdata_submit(XData) of invalid -> - {error, ?ERR_BAD_REQUEST}; + {error, ?ERRT_BAD_REQUEST(Lang, <<"Incorrect data form">>)}; Fields -> handle_adhoc_form(From, To, Request, Fields) end; true -> - {error, ?ERR_BAD_REQUEST} + Txt = <<"Incorrect action or data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end. -define(VVALUE(Val), @@ -688,7 +691,9 @@ announce_all(From, To, Packet) -> Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> Local = jid:make(<<>>, To#jid.server, <<>>), @@ -703,7 +708,9 @@ announce_all_hosts_all(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> Local = jid:make(<<>>, To#jid.server, <<>>), @@ -719,7 +726,9 @@ announce_online(From, To, Packet) -> Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> announce_online1(ejabberd_sm:get_vh_session_list(Host), @@ -731,7 +740,9 @@ announce_all_hosts_online(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> announce_online1(ejabberd_sm:dirty_get_sessions_list(), @@ -752,7 +763,9 @@ announce_motd(From, To, Packet) -> Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> announce_motd(Host, Packet) @@ -762,7 +775,9 @@ announce_all_hosts_motd(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> Hosts = ?MYHOSTS, @@ -815,7 +830,9 @@ announce_motd_update(From, To, Packet) -> Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> announce_motd_update(Host, Packet) @@ -825,7 +842,9 @@ announce_all_hosts_motd_update(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> Hosts = ?MYHOSTS, @@ -861,7 +880,9 @@ announce_motd_delete(From, To, Packet) -> Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> announce_motd_delete(Host) @@ -871,7 +892,9 @@ announce_all_hosts_motd_delete(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"Denied by ACL">>, + Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, Txt)), ejabberd_router:route(To, From, Err); allow -> Hosts = ?MYHOSTS, diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 815884ff..d94b3090 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -64,29 +64,33 @@ process_iq(_From, _To, IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. process_iq_get(_, From, _To, - #iq{xmlns = ?NS_BLOCKING, + #iq{xmlns = ?NS_BLOCKING, lang = Lang, sub_el = #xmlel{name = <<"blocklist">>}}, _) -> #jid{luser = LUser, lserver = LServer} = From, - {stop, process_blocklist_get(LUser, LServer)}; + {stop, process_blocklist_get(LUser, LServer, Lang)}; process_iq_get(Acc, _, _, _, _) -> Acc. process_iq_set(_, From, _To, - #iq{xmlns = ?NS_BLOCKING, + #iq{xmlns = ?NS_BLOCKING, lang = Lang, sub_el = #xmlel{name = SubElName, children = SubEls}}) -> #jid{luser = LUser, lserver = LServer} = From, Res = case {SubElName, fxml:remove_cdata(SubEls)} of - {<<"block">>, []} -> {error, ?ERR_BAD_REQUEST}; + {<<"block">>, []} -> + Txt = <<"No items found in this query">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {<<"block">>, Els} -> JIDs = parse_blocklist_items(Els, []), - process_blocklist_block(LUser, LServer, JIDs); + process_blocklist_block(LUser, LServer, JIDs, Lang); {<<"unblock">>, []} -> - process_blocklist_unblock_all(LUser, LServer); + process_blocklist_unblock_all(LUser, LServer, Lang); {<<"unblock">>, Els} -> JIDs = parse_blocklist_items(Els, []), - process_blocklist_unblock(LUser, LServer, JIDs); - _ -> {error, ?ERR_BAD_REQUEST} + process_blocklist_unblock(LUser, LServer, JIDs, Lang); + _ -> + Txt = <<"Unknown blocking command">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end, {stop, Res}; process_iq_set(Acc, _, _, _) -> Acc. @@ -125,7 +129,7 @@ parse_blocklist_items([#xmlel{name = <<"item">>, parse_blocklist_items([_ | Els], JIDs) -> parse_blocklist_items(Els, JIDs). -process_blocklist_block(LUser, LServer, JIDs) -> +process_blocklist_block(LUser, LServer, JIDs, Lang) -> Filter = fun (List) -> AlreadyBlocked = list_to_blocklist_jids(List, []), lists:foldr(fun (JID, List1) -> @@ -143,8 +147,8 @@ process_blocklist_block(LUser, LServer, JIDs) -> end, List, JIDs) end, - case process_blocklist_block(LUser, LServer, Filter, - gen_mod:db_type(LServer, mod_privacy)) + case process_blocklist_block_db(LUser, LServer, Filter, + gen_mod:db_type(LServer, mod_privacy)) of {atomic, {ok, Default, List}} -> UserList = make_userlist(Default, List), @@ -155,11 +159,11 @@ process_blocklist_block(LUser, LServer, JIDs) -> {result, [], UserList}; _Err -> ?ERROR_MSG("Error processing ~p: ~p", [{LUser, LServer, JIDs}, _Err]), - {error, ?ERR_INTERNAL_SERVER_ERROR} + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)} end. -process_blocklist_block(LUser, LServer, Filter, - mnesia) -> +process_blocklist_block_db(LUser, LServer, Filter, + mnesia) -> F = fun () -> case mnesia:wread({privacy, {LUser, LServer}}) of [] -> @@ -185,8 +189,8 @@ process_blocklist_block(LUser, LServer, Filter, {ok, NewDefault, NewList} end, mnesia:transaction(F); -process_blocklist_block(LUser, LServer, Filter, - riak) -> +process_blocklist_block_db(LUser, LServer, Filter, + riak) -> {atomic, begin case ejabberd_riak:get(privacy, mod_privacy:privacy_schema(), @@ -218,7 +222,7 @@ process_blocklist_block(LUser, LServer, Filter, Err end end}; -process_blocklist_block(LUser, LServer, Filter, odbc) -> +process_blocklist_block_db(LUser, LServer, Filter, odbc) -> F = fun () -> Default = case mod_privacy:sql_get_default_privacy_list_t(LUser) @@ -246,7 +250,7 @@ process_blocklist_block(LUser, LServer, Filter, odbc) -> end, ejabberd_odbc:sql_transaction(LServer, F). -process_blocklist_unblock_all(LUser, LServer) -> +process_blocklist_unblock_all(LUser, LServer, Lang) -> Filter = fun (List) -> lists:filter(fun (#listitem{action = A}) -> A =/= deny end, @@ -263,10 +267,10 @@ process_blocklist_unblock_all(LUser, LServer) -> {result, [], UserList}; _Err -> ?ERROR_MSG("Error processing ~p: ~p", [{LUser, LServer}, _Err]), - {error, ?ERR_INTERNAL_SERVER_ERROR} + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)} end. -process_blocklist_unblock(LUser, LServer, JIDs) -> +process_blocklist_unblock(LUser, LServer, JIDs, Lang) -> Filter = fun (List) -> lists:filter(fun (#listitem{action = deny, type = jid, value = JID}) -> @@ -287,7 +291,7 @@ process_blocklist_unblock(LUser, LServer, JIDs) -> {result, [], UserList}; _Err -> ?ERROR_MSG("Error processing ~p: ~p", [{LUser, LServer, JIDs}, _Err]), - {error, ?ERR_INTERNAL_SERVER_ERROR} + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)} end. unblock_by_filter(LUser, LServer, Filter, mnesia) -> @@ -375,11 +379,12 @@ broadcast_blocklist_event(LUser, LServer, Event) -> ejabberd_sm:route(JID, JID, {broadcast, {blocking, Event}}). -process_blocklist_get(LUser, LServer) -> - case process_blocklist_get(LUser, LServer, - gen_mod:db_type(LServer, mod_privacy)) +process_blocklist_get(LUser, LServer, Lang) -> + case process_blocklist_get_db(LUser, LServer, + gen_mod:db_type(LServer, mod_privacy)) of - error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; + error -> + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)}; List -> JIDs = list_to_blocklist_jids(List, []), Items = lists:map(fun (JID) -> @@ -397,7 +402,7 @@ process_blocklist_get(LUser, LServer) -> children = Items}]} end. -process_blocklist_get(LUser, LServer, mnesia) -> +process_blocklist_get_db(LUser, LServer, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of {'EXIT', _Reason} -> error; @@ -408,7 +413,7 @@ process_blocklist_get(LUser, LServer, mnesia) -> _ -> [] end end; -process_blocklist_get(LUser, LServer, riak) -> +process_blocklist_get_db(LUser, LServer, riak) -> case ejabberd_riak:get(privacy, mod_privacy:privacy_schema(), {LUser, LServer}) of {ok, #privacy{default = Default, lists = Lists}} -> @@ -421,7 +426,7 @@ process_blocklist_get(LUser, LServer, riak) -> {error, _} -> error end; -process_blocklist_get(LUser, LServer, odbc) -> +process_blocklist_get_db(LUser, LServer, odbc) -> case catch mod_privacy:sql_get_default_privacy_list(LUser, LServer) of diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 81cf78a9..1e0499ee 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -102,7 +102,9 @@ iq_handler2(From, To, IQ) -> iq_handler1(From, To, IQ) -> iq_handler(From, To, IQ, ?NS_CARBONS_1). -iq_handler(From, _To, #iq{type=set, sub_el = #xmlel{name = Operation, children = []}} = IQ, CC)-> +iq_handler(From, _To, + #iq{type=set, lang = Lang, + sub_el = #xmlel{name = Operation} = SubEl} = IQ, CC)-> ?DEBUG("carbons IQ received: ~p", [IQ]), {U, S, R} = jid:tolower(From), Result = case Operation of @@ -118,12 +120,14 @@ iq_handler(From, _To, #iq{type=set, sub_el = #xmlel{name = Operation, children ?DEBUG("carbons IQ result: ok", []), IQ#iq{type=result, sub_el=[]}; {error,_Error} -> - ?WARNING_MSG("Error enabling / disabling carbons: ~p", [Result]), - IQ#iq{type=error,sub_el = [?ERR_BAD_REQUEST]} + ?ERROR_MSG("Error enabling / disabling carbons: ~p", [Result]), + Txt = <<"Database failure">>, + IQ#iq{type=error,sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]} end; -iq_handler(_From, _To, IQ, _CC)-> - IQ#iq{type=error, sub_el = [?ERR_NOT_ALLOWED]}. +iq_handler(_From, _To, #iq{lang = Lang, sub_el = SubEl} = IQ, _CC)-> + Txt = <<"Value 'get' of 'type' attribute is not allowed">>, + IQ#iq{type=error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}. user_send_packet(Packet, _C2SState, From, To) -> check_and_forward(From, To, Packet, sent). diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 5e011704..a836c33b 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -198,81 +198,81 @@ get_local_identity(Acc, _From, _To, Node, Lang) -> %%%----------------------------------------------------------------------- --define(INFO_RESULT(Allow, Feats), +-define(INFO_RESULT(Allow, Feats, Lang), case Allow of - deny -> {error, ?ERR_FORBIDDEN}; + deny -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; allow -> {result, Feats} end). get_sm_features(Acc, From, - #jid{lserver = LServer} = _To, Node, _Lang) -> + #jid{lserver = LServer} = _To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Allow = acl:match_rule(LServer, configure, From), case Node of - <<"config">> -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); + <<"config">> -> ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); _ -> Acc end end. get_local_features(Acc, From, - #jid{lserver = LServer} = _To, Node, _Lang) -> + #jid{lserver = LServer} = _To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> LNode = tokenize(Node), Allow = acl:match_rule(LServer, configure, From), case LNode of - [<<"config">>] -> ?INFO_RESULT(Allow, []); - [<<"user">>] -> ?INFO_RESULT(Allow, []); - [<<"online users">>] -> ?INFO_RESULT(Allow, []); - [<<"all users">>] -> ?INFO_RESULT(Allow, []); + [<<"config">>] -> ?INFO_RESULT(Allow, [], Lang); + [<<"user">>] -> ?INFO_RESULT(Allow, [], Lang); + [<<"online users">>] -> ?INFO_RESULT(Allow, [], Lang); + [<<"all users">>] -> ?INFO_RESULT(Allow, [], Lang); [<<"all users">>, <<$@, _/binary>>] -> - ?INFO_RESULT(Allow, []); - [<<"outgoing s2s">> | _] -> ?INFO_RESULT(Allow, []); - [<<"running nodes">>] -> ?INFO_RESULT(Allow, []); - [<<"stopped nodes">>] -> ?INFO_RESULT(Allow, []); + ?INFO_RESULT(Allow, [], Lang); + [<<"outgoing s2s">> | _] -> ?INFO_RESULT(Allow, [], Lang); + [<<"running nodes">>] -> ?INFO_RESULT(Allow, [], Lang); + [<<"stopped nodes">>] -> ?INFO_RESULT(Allow, [], Lang); [<<"running nodes">>, _ENode] -> - ?INFO_RESULT(Allow, [?NS_STATS]); + ?INFO_RESULT(Allow, [?NS_STATS], Lang); [<<"running nodes">>, _ENode, <<"DB">>] -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); [<<"running nodes">>, _ENode, <<"modules">>] -> - ?INFO_RESULT(Allow, []); + ?INFO_RESULT(Allow, [], Lang); [<<"running nodes">>, _ENode, <<"modules">>, _] -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); [<<"running nodes">>, _ENode, <<"backup">>] -> - ?INFO_RESULT(Allow, []); + ?INFO_RESULT(Allow, [], Lang); [<<"running nodes">>, _ENode, <<"backup">>, _] -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); [<<"running nodes">>, _ENode, <<"import">>] -> - ?INFO_RESULT(Allow, []); + ?INFO_RESULT(Allow, [], Lang); [<<"running nodes">>, _ENode, <<"import">>, _] -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); [<<"running nodes">>, _ENode, <<"restart">>] -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); [<<"running nodes">>, _ENode, <<"shutdown">>] -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); [<<"config">>, _] -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"add-user">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"delete-user">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"end-user-session">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"get-user-password">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"change-user-password">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"get-user-lastlogin">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"user-stats">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"get-registered-users-num">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); ?NS_ADMINL(<<"get-online-users-num">>) -> - ?INFO_RESULT(Allow, [?NS_COMMANDS]); + ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang); _ -> Acc end end. @@ -318,7 +318,8 @@ get_sm_items(Acc, From, {result, Items ++ Nodes ++ get_user_resources(User, Server)}; {allow, <<"config">>} -> {result, []}; - {_, <<"config">>} -> {error, ?ERR_FORBIDDEN}; + {_, <<"config">>} -> + {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; _ -> Acc end end. @@ -448,63 +449,64 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To, _ -> LNode = tokenize(Node), Allow = acl:match_rule(LServer, configure, From), + Err = ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>), case LNode of [<<"config">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"user">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"online users">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"all users">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"all users">>, <<$@, _/binary>>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"outgoing s2s">> | _] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"stopped nodes">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"DB">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"modules">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"modules">>, _] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"backup">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"backup">>, _] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"import">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"import">>, _] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"restart">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"running nodes">>, _ENode, <<"shutdown">>] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); [<<"config">>, _] -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"add-user">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"delete-user">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"end-user-session">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"get-user-password">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"change-user-password">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"get-user-lastlogin">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"user-stats">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"get-registered-users-num">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); ?NS_ADMINL(<<"get-online-users-num">>) -> - ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); + ?ITEMS_RESULT(Allow, LNode, {error, Err}); _ -> Acc end end. @@ -562,33 +564,29 @@ get_local_items({_, Host}, [<<"all users">>], _Server, get_local_items({_, Host}, [<<"all users">>, <<$@, Diap/binary>>], _Server, _Lang) -> - case catch ejabberd_auth:get_vh_registered_users(Host) - of - {'EXIT', _Reason} -> ?ERR_INTERNAL_SERVER_ERROR; - Users -> - SUsers = lists:sort([{S, U} || {U, S} <- Users]), - case catch begin - [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>), - N1 = jlib:binary_to_integer(S1), - N2 = jlib:binary_to_integer(S2), - Sub = lists:sublist(SUsers, N1, N2 - N1 + 1), - lists:map(fun ({S, U}) -> - #xmlel{name = <<"item">>, - attrs = - [{<<"jid">>, - <<U/binary, "@", - S/binary>>}, - {<<"name">>, - <<U/binary, "@", - S/binary>>}], - children = []} - end, - Sub) - end - of - {'EXIT', _Reason} -> ?ERR_NOT_ACCEPTABLE; - Res -> {result, Res} - end + Users = ejabberd_auth:get_vh_registered_users(Host), + SUsers = lists:sort([{S, U} || {U, S} <- Users]), + case catch begin + [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>), + N1 = jlib:binary_to_integer(S1), + N2 = jlib:binary_to_integer(S2), + Sub = lists:sublist(SUsers, N1, N2 - N1 + 1), + lists:map(fun ({S, U}) -> + #xmlel{name = <<"item">>, + attrs = + [{<<"jid">>, + <<U/binary, "@", + S/binary>>}, + {<<"name">>, + <<U/binary, "@", + S/binary>>}], + children = []} + end, + Sub) + end + of + {'EXIT', _Reason} -> ?ERR_NOT_ACCEPTABLE; + Res -> {result, Res} end; get_local_items({_, Host}, [<<"outgoing s2s">>], _Server, Lang) -> @@ -826,33 +824,33 @@ get_stopped_nodes(_Lang) -> %%------------------------------------------------------------------------- -define(COMMANDS_RESULT(LServerOrGlobal, From, To, - Request), + Request, Lang), case acl:match_rule(LServerOrGlobal, configure, From) of - deny -> {error, ?ERR_FORBIDDEN}; + deny -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; allow -> adhoc_local_commands(From, To, Request) end). adhoc_local_commands(Acc, From, #jid{lserver = LServer} = To, - #adhoc_request{node = Node} = Request) -> + #adhoc_request{node = Node, lang = Lang} = Request) -> LNode = tokenize(Node), case LNode of [<<"running nodes">>, _ENode, <<"DB">>] -> - ?COMMANDS_RESULT(global, From, To, Request); + ?COMMANDS_RESULT(global, From, To, Request, Lang); [<<"running nodes">>, _ENode, <<"modules">>, _] -> - ?COMMANDS_RESULT(LServer, From, To, Request); + ?COMMANDS_RESULT(LServer, From, To, Request, Lang); [<<"running nodes">>, _ENode, <<"backup">>, _] -> - ?COMMANDS_RESULT(global, From, To, Request); + ?COMMANDS_RESULT(global, From, To, Request, Lang); [<<"running nodes">>, _ENode, <<"import">>, _] -> - ?COMMANDS_RESULT(global, From, To, Request); + ?COMMANDS_RESULT(global, From, To, Request, Lang); [<<"running nodes">>, _ENode, <<"restart">>] -> - ?COMMANDS_RESULT(global, From, To, Request); + ?COMMANDS_RESULT(global, From, To, Request, Lang); [<<"running nodes">>, _ENode, <<"shutdown">>] -> - ?COMMANDS_RESULT(global, From, To, Request); + ?COMMANDS_RESULT(global, From, To, Request, Lang); [<<"config">>, _] -> - ?COMMANDS_RESULT(LServer, From, To, Request); + ?COMMANDS_RESULT(LServer, From, To, Request, Lang); ?NS_ADMINL(_) -> - ?COMMANDS_RESULT(LServer, From, To, Request); + ?COMMANDS_RESULT(LServer, From, To, Request, Lang); _ -> Acc end. @@ -882,7 +880,8 @@ adhoc_local_commands(From, end; XData /= false, ActionIsExecute -> case jlib:parse_xdata_submit(XData) of - invalid -> {error, ?ERR_BAD_REQUEST}; + invalid -> + {error, ?ERRT_BAD_REQUEST(Lang, <<"Incorrect data form">>)}; Fields -> case catch set_form(From, LServer, LNode, Lang, Fields) of @@ -898,7 +897,8 @@ adhoc_local_commands(From, {error, Error} -> {error, Error} end end; - true -> {error, ?ERR_BAD_REQUEST} + true -> + {error, ?ERRT_BAD_REQUEST(Lang, <<"Incorrect action or data form">>)} end. -define(TVFIELD(Type, Var, Val), @@ -980,10 +980,14 @@ adhoc_local_commands(From, get_form(_Host, [<<"running nodes">>, ENode, <<"DB">>], Lang) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of - {badrpc, _Reason} -> + {badrpc, Reason} -> + ?ERROR_MSG("RPC call mnesia:system_info(tables) on node " + "~s failed: ~p", [Node, Reason]), {error, ?ERR_INTERNAL_SERVER_ERROR}; Tables -> STables = lists:sort(Tables), @@ -1023,10 +1027,14 @@ get_form(Host, [<<"running nodes">>, ENode, <<"modules">>, <<"stop">>], Lang) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case ejabberd_cluster:call(Node, gen_mod, loaded_modules, [Host]) of - {badrpc, _Reason} -> + {badrpc, Reason} -> + ?ERROR_MSG("RPC call gen_mod:loaded_modules(~s) on node " + "~s failed: ~p", [Host, Node, Reason]), {error, ?ERR_INTERNAL_SERVER_ERROR}; Modules -> SModules = lists:sort(Modules), @@ -1562,9 +1570,11 @@ get_form(_Host, _, _Lang) -> {error, ?ERR_SERVICE_UNAVAILABLE}. set_form(_From, _Host, - [<<"running nodes">>, ENode, <<"DB">>], _Lang, XData) -> + [<<"running nodes">>, ENode, <<"DB">>], Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> lists:foreach(fun ({SVar, SVals}) -> Table = jlib:binary_to_atom(SVar), @@ -1596,9 +1606,11 @@ set_form(_From, _Host, end; set_form(_From, Host, [<<"running nodes">>, ENode, <<"modules">>, <<"stop">>], - _Lang, XData) -> + Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> lists:foreach(fun ({Var, Vals}) -> case Vals of @@ -1615,12 +1627,16 @@ set_form(_From, Host, set_form(_From, Host, [<<"running nodes">>, ENode, <<"modules">>, <<"start">>], - _Lang, XData) -> + Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case lists:keysearch(<<"modules">>, 1, XData) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'modules' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, {_, Strings}} -> String = lists:foldl(fun (S, Res) -> <<Res/binary, S/binary, "\n">> @@ -1637,98 +1653,143 @@ set_form(_From, Host, end, Modules), {result, []}; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Parse failed">>)} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Scan failed">>)} end end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"backup">>, <<"backup">>], - _Lang, XData) -> + Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case lists:keysearch(<<"path">>, 1, XData) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'path' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, {_, [String]}} -> case ejabberd_cluster:call(Node, mnesia, backup, [String]) of - {badrpc, _Reason} -> + {badrpc, Reason} -> + ?ERROR_MSG("RPC call mnesia:backup(~s) to node ~s " + "failed: ~p", [String, Node, Reason]), + {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, Reason} -> + ?ERROR_MSG("RPC call mnesia:backup(~s) to node ~s " + "failed: ~p", [String, Node, Reason]), {error, ?ERR_INTERNAL_SERVER_ERROR}; - {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; _ -> {result, []} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Incorrect value of 'path' in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"backup">>, <<"restore">>], - _Lang, XData) -> + Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case lists:keysearch(<<"path">>, 1, XData) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'path' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, {_, [String]}} -> case ejabberd_cluster:call(Node, ejabberd_admin, restore, [String]) of - {badrpc, _Reason} -> + {badrpc, Reason} -> + ?ERROR_MSG("RPC call ejabberd_admin:restore(~s) to node " + "~s failed: ~p", [String, Node, Reason]), + {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, Reason} -> + ?ERROR_MSG("RPC call ejabberd_admin:restore(~s) to node " + "~s failed: ~p", [String, Node, Reason]), {error, ?ERR_INTERNAL_SERVER_ERROR}; - {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; _ -> {result, []} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Incorrect value of 'path' in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"backup">>, <<"textfile">>], - _Lang, XData) -> + Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case lists:keysearch(<<"path">>, 1, XData) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'path' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, {_, [String]}} -> case ejabberd_cluster:call(Node, ejabberd_admin, dump_to_textfile, [String]) of - {badrpc, _Reason} -> + {badrpc, Reason} -> + ?ERROR_MSG("RPC call ejabberd_admin:dump_to_textfile(~s) " + "to node ~s failed: ~p", [String, Node, Reason]), + {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, Reason} -> + ?ERROR_MSG("RPC call ejabberd_admin:dump_to_textfile(~s) " + "to node ~s failed: ~p", [String, Node, Reason]), {error, ?ERR_INTERNAL_SERVER_ERROR}; - {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; _ -> {result, []} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Incorrect value of 'path' in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"import">>, <<"file">>], - _Lang, XData) -> + Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case lists:keysearch(<<"path">>, 1, XData) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'path' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, {_, [String]}} -> ejabberd_cluster:call(Node, jd2ejd, import_file, [String]), {result, []}; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Incorrect value of 'path' in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"import">>, <<"dir">>], - _Lang, XData) -> + Lang, XData) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> case lists:keysearch(<<"path">>, 1, XData) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'path' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, {_, [String]}} -> ejabberd_cluster:call(Node, jd2ejd, import_dir, [String]), {result, []}; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Incorrect value of 'path' in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end end; set_form(From, Host, @@ -1739,7 +1800,7 @@ set_form(From, Host, [<<"running nodes">>, ENode, <<"shutdown">>], _Lang, XData) -> stop_node(From, Host, ENode, stop, XData); -set_form(_From, Host, [<<"config">>, <<"acls">>], _Lang, +set_form(_From, Host, [<<"config">>, <<"acls">>], Lang, XData) -> case lists:keysearch(<<"acls">>, 1, XData) of {value, {_, Strings}} -> @@ -1753,14 +1814,16 @@ set_form(_From, Host, [<<"config">>, <<"acls">>], _Lang, {ok, ACLs} -> acl:add_list(Host, ACLs, true), {result, []}; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Parse failed">>)} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Scan failed">>)} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"No 'acls' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end; set_form(_From, Host, [<<"config">>, <<"access">>], - _Lang, XData) -> + Lang, XData) -> SetAccess = fun (Rs) -> mnesia:transaction(fun () -> Os = mnesia:select(local_config, @@ -1803,11 +1866,13 @@ set_form(_From, Host, [<<"config">>, <<"access">>], {atomic, _} -> {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Parse failed">>)} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Scan failed">>)} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"No 'access' found in data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end; set_form(From, Host, ?NS_ADMINL(<<"add-user">>), _Lang, XData) -> @@ -2052,7 +2117,7 @@ adhoc_sm_commands(_Acc, From, action = Action, xdata = XData} = Request) -> case acl:match_rule(LServer, configure, From) of - deny -> {error, ?ERR_FORBIDDEN}; + deny -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; allow -> ActionIsExecute = lists:member(Action, [<<"">>, <<"execute">>, @@ -2071,11 +2136,15 @@ adhoc_sm_commands(_Acc, From, end; XData /= false, ActionIsExecute -> case jlib:parse_xdata_submit(XData) of - invalid -> {error, ?ERR_BAD_REQUEST}; + invalid -> + Txt = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; Fields -> set_sm_form(User, Server, <<"config">>, Request, Fields) end; - true -> {error, ?ERR_BAD_REQUEST} + true -> + Txt = <<"Incorrect action or data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end end; adhoc_sm_commands(Acc, _From, _To, _Request) -> Acc. @@ -2135,12 +2204,16 @@ set_sm_form(User, Server, <<"config">>, {value, {_, [Password]}} -> ejabberd_auth:set_password(User, Server, Password), adhoc:produce_response(Response); - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> + Txt = <<"No 'password' found in data form">>, + {error, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)} end; {value, {_, [<<"remove">>]}} -> catch ejabberd_auth:remove_user(User, Server), adhoc:produce_response(Response); - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> + Txt = <<"Incorrect value of 'action' in data form">>, + {error, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)} end; set_sm_form(_User, _Server, _Node, _Request, _Fields) -> {error, ?ERR_SERVICE_UNAVAILABLE}. diff --git a/src/mod_configure2.erl b/src/mod_configure2.erl index 0acd4a78..a8287b4d 100644 --- a/src/mod_configure2.erl +++ b/src/mod_configure2.erl @@ -56,15 +56,17 @@ stop(Host) -> ?NS_ECONFIGURE). process_local_iq(From, To, - #iq{type = Type, lang = _Lang, sub_el = SubEl} = IQ) -> + #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case acl:match_rule(To#jid.lserver, configure, From) of deny -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Denied by ACL">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; allow -> case Type of set -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}; + sub_el = [SubEl, ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)]}; %%case fxml:get_tag_attr_s("type", SubEl) of %% "cancel" -> %% IQ#iq{type = result, @@ -98,7 +100,7 @@ process_local_iq(From, To, %% sub_el = [SubEl, ?ERR_NOT_ALLOWED]} %%end; get -> - case process_get(SubEl) of + case process_get(SubEl, Lang) of {result, Res} -> IQ#iq{type = result, sub_el = [Res]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} @@ -106,7 +108,7 @@ process_local_iq(From, To, end end. -process_get(#xmlel{name = <<"info">>}) -> +process_get(#xmlel{name = <<"info">>}, _Lang) -> S2SConns = ejabberd_s2s:dirty_get_connections(), TConns = lists:usort([element(2, C) || C <- S2SConns]), Attrs = [{<<"registered-users">>, @@ -130,7 +132,7 @@ process_get(#xmlel{name = <<"info">>}) -> attrs = [{<<"xmlns">>, ?NS_ECONFIGURE} | Attrs], children = []}}; process_get(#xmlel{name = <<"welcome-message">>, - attrs = Attrs}) -> + attrs = Attrs}, _Lang) -> {Subj, Body} = ejabberd_config:get_option( welcome_message, fun({Subj, Body}) -> @@ -146,7 +148,7 @@ process_get(#xmlel{name = <<"welcome-message">>, #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Body}]}]}}; process_get(#xmlel{name = <<"registration-watchers">>, - attrs = Attrs}) -> + attrs = Attrs}, _Lang) -> SubEls = ejabberd_config:get_option( registration_watchers, fun(JIDs) when is_list(JIDs) -> @@ -160,14 +162,14 @@ process_get(#xmlel{name = <<"registration-watchers">>, {result, #xmlel{name = <<"registration_watchers">>, attrs = Attrs, children = SubEls}}; -process_get(#xmlel{name = <<"acls">>, attrs = Attrs}) -> +process_get(#xmlel{name = <<"acls">>, attrs = Attrs}, _Lang) -> Str = iolist_to_binary(io_lib:format("~p.", [ets:tab2list(acl)])), {result, #xmlel{name = <<"acls">>, attrs = Attrs, children = [{xmlcdata, Str}]}}; process_get(#xmlel{name = <<"access">>, - attrs = Attrs}) -> + attrs = Attrs}, _Lang) -> Str = iolist_to_binary(io_lib:format("~p.", [ets:select(local_config, [{{local_config, {access, '$1'}, @@ -178,13 +180,14 @@ process_get(#xmlel{name = <<"access">>, {result, #xmlel{name = <<"access">>, attrs = Attrs, children = [{xmlcdata, Str}]}}; -process_get(#xmlel{name = <<"last">>, attrs = Attrs}) -> +process_get(#xmlel{name = <<"last">>, attrs = Attrs}, Lang) -> case catch mnesia:dirty_select(last_activity, [{{last_activity, '_', '$1', '_'}, [], ['$1']}]) of {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; + Txt = <<"Database failure">>, + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)}; Vals -> TimeStamp = p1_time_compat:system_time(seconds), Str = list_to_binary( @@ -196,7 +199,7 @@ process_get(#xmlel{name = <<"last">>, attrs = Attrs}) -> end; %%process_get({xmlelement, Name, Attrs, SubEls}) -> %% {result, }; -process_get(_) -> {error, ?ERR_BAD_REQUEST}. +process_get(_, _) -> {error, ?ERR_BAD_REQUEST}. mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 734e90d3..0d5abcb4 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -150,7 +150,8 @@ process_local_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> Node = fxml:get_tag_attr_s(<<"node">>, SubEl), Host = To#jid.lserver, @@ -177,7 +178,8 @@ process_local_iq_info(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> Host = To#jid.lserver, Node = fxml:get_tag_attr_s(<<"node">>, SubEl), @@ -229,10 +231,12 @@ get_local_features(Acc, _From, To, <<>>, _Lang) -> ets:select(disco_features, [{{{'_', Host}}, [], ['$_']}]) ++ Feats}; -get_local_features(Acc, _From, _To, _Node, _Lang) -> +get_local_features(Acc, _From, _To, _Node, Lang) -> case Acc of {result, _Features} -> Acc; - empty -> {error, ?ERR_ITEM_NOT_FOUND} + empty -> + Txt = <<"No features available">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)} end. features_to_xml(FeatureList) -> @@ -271,8 +275,8 @@ get_local_services(Acc, _From, To, <<>>, _Lang) -> get_local_services({result, _} = Acc, _From, _To, _Node, _Lang) -> Acc; -get_local_services(empty, _From, _To, _Node, _Lang) -> - {error, ?ERR_ITEM_NOT_FOUND}. +get_local_services(empty, _From, _To, _Node, Lang) -> + {error, ?ERRT_ITEM_NOT_FOUND(Lang, <<"No services available">>)}. get_vh_services(Host) -> Hosts = lists:sort(fun (H1, H2) -> @@ -300,7 +304,8 @@ process_sm_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> case is_presence_subscribed(From, To) of true -> @@ -325,8 +330,9 @@ process_sm_iq_items(From, To, IQ#iq{type = error, sub_el = [SubEl, Error]} end; false -> + Txt = <<"Not subscribed">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]} + sub_el = [SubEl, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)]} end end. @@ -347,12 +353,14 @@ get_sm_items(Acc, From, get_sm_items({result, _} = Acc, _From, _To, _Node, _Lang) -> Acc; -get_sm_items(empty, From, To, _Node, _Lang) -> +get_sm_items(empty, From, To, _Node, Lang) -> #jid{luser = LFrom, lserver = LSFrom} = From, #jid{luser = LTo, lserver = LSTo} = To, case {LFrom, LSFrom} of {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND}; - _ -> {error, ?ERR_NOT_ALLOWED} + _ -> + Txt = <<"Query to another users is forbidden">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt)} end. is_presence_subscribed(#jid{luser = User, lserver = Server}, @@ -373,7 +381,8 @@ process_sm_iq_info(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> case is_presence_subscribed(From, To) of true -> @@ -405,8 +414,9 @@ process_sm_iq_info(From, To, IQ#iq{type = error, sub_el = [SubEl, Error]} end; false -> + Txt = <<"Not subscribed">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]} + sub_el = [SubEl, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)]} end end. @@ -423,12 +433,14 @@ get_sm_identity(Acc, _From, _ -> [] end. -get_sm_features(empty, From, To, _Node, _Lang) -> +get_sm_features(empty, From, To, _Node, Lang) -> #jid{luser = LFrom, lserver = LSFrom} = From, #jid{luser = LTo, lserver = LSTo} = To, case {LFrom, LSFrom} of {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND}; - _ -> {error, ?ERR_NOT_ALLOWED} + _ -> + Txt = <<"Query to another users is forbidden">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt)} end; get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 7184ee4e..7d9f81f8 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -118,7 +118,10 @@ handle_cast(_Msg, State) -> {noreply, State}. handle_info({route, From, To, Packet}, State) -> Packet2 = case From#jid.user of <<"">> -> - jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST); + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), + Txt = <<"User part of JID in 'from' is empty">>, + jlib:make_error_reply( + Packet, ?ERRT_BAD_REQUEST(Lang, Txt)); _ -> Packet end, do_client_version(disabled, To, From), diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 6c029c43..214badca 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -569,7 +569,8 @@ process_iq(From, deny -> ?DEBUG("Denying HTTP upload slot request from ~s", [jid:to_string(From)]), - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} + Txt = <<"Denied by ACL">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]} end; process_iq(_From, #iq{sub_el = SubEl} = IQ, _State) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; @@ -601,7 +602,8 @@ parse_request(#xmlel{name = <<"request">>, attrs = Attrs} = Request, Lang) -> {error, ?ERRT_BAD_REQUEST(Lang, Text)} end; _ -> - {error, ?ERR_BAD_REQUEST} + Text = <<"No or invalid XML namespace">>, + {error, ?ERRT_BAD_REQUEST(Lang, Text)} end; parse_request(_El, _Lang) -> {error, ?ERR_BAD_REQUEST}. @@ -639,7 +641,7 @@ create_slot(#state{service_url = undefined, end; create_slot(#state{service_url = ServiceURL}, #jid{luser = U, lserver = S} = JID, File, Size, ContentType, - _Lang) -> + Lang) -> Options = [{body_format, binary}, {full_result, false}], HttpOptions = [{timeout, ?SERVICE_REQUEST_TIMEOUT}], SizeStr = jlib:integer_to_binary(Size), @@ -659,7 +661,8 @@ create_slot(#state{service_url = ServiceURL}, Lines -> ?ERROR_MSG("Can't parse data received for ~s from <~s>: ~p", [jid:to_string(JID), ServiceURL, Lines]), - {error, ?ERR_SERVICE_UNAVAILABLE} + Txt = <<"Failed to parse HTTP response">>, + {error, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)} end; {ok, {402, _Body}} -> ?INFO_MSG("Got status code 402 for ~s from <~s>", diff --git a/src/mod_irc.erl b/src/mod_irc.erl index d5cd0135..f6e452d8 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -304,8 +304,9 @@ do_route1(Host, ServerHost, From, To, Packet) -> Lang)}]}, Res = jlib:iq_to_xml(ResIQ); _ -> - Res = jlib:make_error_reply(Packet, - ?ERR_ITEM_NOT_FOUND) + Txt = <<"Node not found">>, + Res = jlib:make_error_reply( + Packet, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)) end, ejabberd_router:route(To, From, Res); #iq{xmlns = ?NS_REGISTER} = IQ -> @@ -319,7 +320,7 @@ do_route1(Host, ServerHost, From, To, Packet) -> attrs = [{<<"xmlns">>, XMLNS}], children = iq_get_vcard(Lang)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); - #iq{type = set, xmlns = ?NS_COMMANDS, lang = _Lang, + #iq{type = set, xmlns = ?NS_COMMANDS, lang = Lang, sub_el = SubEl} = IQ -> Request = adhoc:parse_request(IQ), @@ -348,8 +349,9 @@ do_route1(Host, ServerHost, From, To, Packet) -> true -> ok end; _ -> - Err = jlib:make_error_reply(Packet, - ?ERR_ITEM_NOT_FOUND), + Txt = <<"Node not found">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)), ejabberd_router:route(To, From, Err) end; #iq{} = _IQ -> @@ -407,12 +409,14 @@ do_route1(Host, ServerHost, From, To, Packet) -> ok end; _ -> + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), case str:tokens(ChanServ, <<"!">>) of [<<_, _/binary>> = Nick, <<_, _/binary>> = Server] -> case ets:lookup(irc_connection, {From, Server, Host}) of [] -> - Err = jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), + Txt = <<"IRC connection not found">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)), ejabberd_router:route(To, From, Err); [R] -> Pid = R#irc_connection.pid, @@ -421,7 +425,9 @@ do_route1(Host, ServerHost, From, To, Packet) -> ok end; _ -> - Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), + Txt = <<"Failed to parse chanserv">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), ejabberd_router:route(To, From, Err) end end @@ -532,8 +538,9 @@ process_irc_register(ServerHost, Host, From, _To, XDataEl = find_xdata_el(SubEl), case XDataEl of false -> + Txt1 = <<"No data form found">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]}; + sub_el = [SubEl, ?ERRT_NOT_ACCEPTABLE(Lang, Txt1)]}; #xmlel{attrs = Attrs} -> case fxml:get_attr_s(<<"type">>, Attrs) of <<"cancel">> -> @@ -546,8 +553,9 @@ process_irc_register(ServerHost, Host, From, _To, XData = jlib:parse_xdata_submit(XDataEl), case XData of invalid -> + Txt2 = <<"Incorrect data form">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_BAD_REQUEST]}; + sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt2)]}; _ -> Node = str:tokens(fxml:get_tag_attr_s(<<"node">>, SubEl), @@ -567,7 +575,9 @@ process_irc_register(ServerHost, Host, From, _To, end end; _ -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} + Txt3 = <<"Incorrect value of 'type' attribute">>, + IQ#iq{type = error, + sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt3)]} end end; get -> @@ -629,7 +639,9 @@ get_form(ServerHost, Host, From, [], Lang) -> #jid{user = User, server = Server} = From, DefaultEncoding = get_default_encoding(Host), Customs = case get_data(ServerHost, Host, From) of - error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; + error -> + Txt1 = <<"Database failure">>, + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt1)}; empty -> {User, []}; Data -> get_username_and_connection_params(Data) end, @@ -763,7 +775,7 @@ set_data(LServer, Host, From, Data, odbc) -> end, ejabberd_odbc:sql_transaction(LServer, F). -set_form(ServerHost, Host, From, [], _Lang, XData) -> +set_form(ServerHost, Host, From, [], Lang, XData) -> case {lists:keysearch(<<"username">>, 1, XData), lists:keysearch(<<"connections_params">>, 1, XData)} of @@ -781,11 +793,11 @@ set_form(ServerHost, Host, From, [], _Lang, XData) -> {connections_params, ConnectionsParams}]) of {atomic, _} -> {result, []}; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> {error, ?ERRT_NOT_ACCEPTABLE(Lang, <<"Database failure">>)} end; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> {error, ?ERRT_NOT_ACCEPTABLE(Lang, <<"Parse error">>)} end; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> {error, ?ERRT_NOT_ACCEPTABLE(Lang, <<"Scan error">>)} end; _ -> {error, ?ERR_NOT_ACCEPTABLE} end; @@ -909,7 +921,9 @@ adhoc_join(From, To, elements = [Form]}); true -> case jlib:parse_xdata_submit(XData) of - invalid -> {error, ?ERR_BAD_REQUEST}; + invalid -> + Txt1 = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt1)}; Fields -> Channel = case lists:keysearch(<<"channel">>, 1, Fields) of @@ -998,7 +1012,8 @@ adhoc_register(ServerHost, From, To, true -> case jlib:parse_xdata_submit(XData) of invalid -> - Error = {error, ?ERR_BAD_REQUEST}, + Txt1 = <<"Incorrect data form">>, + Error = {error, ?ERRT_BAD_REQUEST(Lang, Txt1)}, Username = false, ConnectionsParams = false; Fields -> @@ -1021,7 +1036,9 @@ adhoc_register(ServerHost, From, To, {atomic, _} -> adhoc:produce_response(Request, #adhoc_response{status = completed}); - _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} + _ -> + Txt2 = <<"Database failure">>, + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt2)} end; true -> Form = generate_adhoc_register_form(Lang, Username, diff --git a/src/mod_last.erl b/src/mod_last.erl index 33f88e02..009a1cb0 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -86,10 +86,11 @@ stop(Host) -> %%% process_local_iq(_From, _To, - #iq{type = Type, sub_el = SubEl} = IQ) -> + #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> Sec = get_node_uptime(), IQ#iq{type = result, @@ -123,10 +124,11 @@ now_to_seconds({MegaSecs, Secs, _MicroSecs}) -> %%% process_sm_iq(From, To, - #iq{type = Type, sub_el = SubEl} = IQ) -> + #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> User = To#jid.luser, Server = To#jid.lserver, @@ -153,7 +155,8 @@ process_sm_iq(From, To, IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end; true -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} + Txt = <<"Not subscribed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]} end end. @@ -193,16 +196,18 @@ get_last(LUser, LServer, odbc) -> Reason -> {error, {invalid_result, Reason}} end. -get_last_iq(IQ, SubEl, LUser, LServer) -> +get_last_iq(#iq{lang = Lang} = IQ, SubEl, LUser, LServer) -> case ejabberd_sm:get_user_resources(LUser, LServer) of [] -> case get_last(LUser, LServer) of {error, _Reason} -> + Txt = <<"Database failure">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; + sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]}; not_found -> + Txt = <<"No info about last activity found">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; + sub_el = [SubEl, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)]}; {ok, TimeStamp, Status} -> TimeStamp2 = p1_time_compat:system_time(seconds), Sec = TimeStamp2 - TimeStamp, diff --git a/src/mod_mam.erl b/src/mod_mam.erl index d212f63c..862adee9 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -447,7 +447,7 @@ process_iq(LServer, #iq{sub_el = #xmlel{attrs = Attrs}} = IQ) -> % Preference setting (both v0.2 & v0.3) process_iq(#jid{luser = LUser, lserver = LServer}, #jid{lserver = LServer}, - #iq{type = set, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) -> + #iq{type = set, lang = Lang, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) -> try {case fxml:get_tag_attr_s(<<"default">>, SubEl) of <<"always">> -> always; <<"never">> -> never; @@ -469,8 +469,9 @@ process_iq(#jid{luser = LUser, lserver = LServer}, NewPrefs = prefs_el(Default, Always, Never, IQ#iq.xmlns), IQ#iq{type = result, sub_el = [NewPrefs]}; _Err -> + Txt = <<"Database failure">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} + sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]} end catch _:_ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} diff --git a/src/mod_mix.erl b/src/mod_mix.erl index d8cf94ac..c0835b74 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -132,8 +132,9 @@ process_iq(From, To, {error, Err} -> IQ#iq{type = error, sub_el = [SubEl, Err]} end; -process_iq(_From, _To, #iq{sub_el = SubEl} = IQ) -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}. +process_iq(_From, _To, #iq{sub_el = SubEl, lang = Lang} = IQ) -> + Txt = <<"Unsupported MIX query">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}. %%%=================================================================== %%% gen_server callbacks diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 0d37a236..9d4b4985 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -1056,7 +1056,9 @@ iq_set_register_info(ServerHost, Host, From, Nick, ErrText = <<"That nickname is registered by another " "person">>, {error, ?ERRT_CONFLICT(Lang, ErrText)}; - _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} + _ -> + Txt = <<"Database failure">>, + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)} end. process_iq_register_set(ServerHost, Host, From, SubEl, @@ -1073,7 +1075,9 @@ process_iq_register_set(ServerHost, Host, From, SubEl, {?NS_XDATA, <<"submit">>} -> XData = jlib:parse_xdata_submit(XEl), case XData of - invalid -> {error, ?ERR_BAD_REQUEST}; + invalid -> + Txt = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; _ -> case lists:keysearch(<<"nick">>, 1, XData) of {value, {_, [Nick]}} when Nick /= <<"">> -> diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 06fdf325..c9c78575 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -252,7 +252,7 @@ normal_state({route, From, <<"">>, IsVoiceApprovement = is_voice_approvement(Els) and not is_visitor(From, StateData), if IsInvitation -> - case catch check_invitation(From, Els, Lang, StateData) + case catch check_invitation(From, Packet, Lang, StateData) of {error, Error} -> Err = jlib:make_error_reply(Packet, Error), @@ -433,9 +433,11 @@ normal_state({route, From, <<"">>, process_iq_owner(From, Type, Lang, SubEl, StateData); ?NS_DISCO_INFO -> case fxml:get_attr(<<"node">>, Attrs) of - false -> process_iq_disco_info(From, Type, Lang, StateData); - {value, _} -> {error, ?ERR_SERVICE_UNAVAILABLE} - end; + false -> process_iq_disco_info(From, Type, Lang, StateData); + {value, _} -> + Txt = <<"Disco info is not available for this node">>, + {error, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)} + end; ?NS_DISCO_ITEMS -> process_iq_disco_items(From, Type, Lang, StateData); ?NS_VCARD -> @@ -817,8 +819,9 @@ handle_info({captcha_failed, From}, normal_state, of {ok, {Nick, Packet}} -> Robots = (?DICT):erase(From, StateData#state.robots), - Err = jlib:make_error_reply(Packet, - ?ERR_NOT_AUTHORIZED), + Txt = <<"The CAPTCHA verification has failed">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_NOT_AUTHORIZED(?MYLANG, Txt)), ejabberd_router:route % TODO: s/Nick/""/ (jid:replace_resource(StateData#state.jid, Nick), @@ -1807,6 +1810,22 @@ add_new_user(From, Nick, StateData#state.host, From, Nick), get_default_role(Affiliation, StateData)} of + {false, _, _, _} when NUsers >= MaxUsers orelse NUsers >= MaxAdminUsers -> + Txt = <<"Too many users in this conference">>, + Err = jlib:make_error_reply(Packet, + ?ERRT_RESOURCE_CONSTRAINT(Lang, Txt)), + ejabberd_router:route % TODO: s/Nick/""/ + (jid:replace_resource(StateData#state.jid, Nick), + From, Err), + StateData; + {false, _, _, _} when NConferences >= MaxConferences -> + Txt = <<"You have joined too many conferences">>, + Err = jlib:make_error_reply(Packet, + ?ERRT_RESOURCE_CONSTRAINT(Lang, Txt)), + ejabberd_router:route % TODO: s/Nick/""/ + (jid:replace_resource(StateData#state.jid, Nick), + From, Err), + StateData; {false, _, _, _} -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), @@ -2555,14 +2574,18 @@ process_iq_admin(From, set, Lang, SubEl, StateData) -> process_admin_items_set(From, Items, Lang, StateData); process_iq_admin(From, get, Lang, SubEl, StateData) -> case fxml:get_subtag(SubEl, <<"item">>) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'item' element found">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; Item -> FAffiliation = get_affiliation(From, StateData), FRole = get_role(From, StateData), case fxml:get_tag_attr(<<"role">>, Item) of false -> case fxml:get_tag_attr(<<"affiliation">>, Item) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'affiliation' attribute found">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; @@ -2583,7 +2606,9 @@ process_iq_admin(From, get, Lang, SubEl, StateData) -> end; {value, StrRole} -> case catch list_to_role(StrRole) of - {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; + {'EXIT', _} -> + Txt = <<"Incorrect value of 'role' attribute">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; SRole -> if FRole == moderator -> Items = items_with_role(SRole, StateData), @@ -2780,7 +2805,9 @@ find_changed_items(UJID, UAffiliation, URole, {error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)}; J -> {value, J} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt1 = <<"No 'nick' attribute found">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt1)} end end, case TJID of @@ -2790,7 +2817,9 @@ find_changed_items(UJID, UAffiliation, URole, case fxml:get_attr(<<"role">>, Attrs) of false -> case fxml:get_attr(<<"affiliation">>, Attrs) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt2 = <<"No 'affiliation' attribute found">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt2)}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of {'EXIT', _} -> @@ -2839,7 +2868,9 @@ find_changed_items(UJID, UAffiliation, URole, find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, [MoreRes | Res]); - false -> {error, ?ERR_NOT_ALLOWED} + false -> + Txt3 = <<"Changing role/affiliation is not allowed">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt3)} end end end; @@ -2885,7 +2916,9 @@ find_changed_items(UJID, UAffiliation, URole, find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, [MoreRes | Res]); - _ -> {error, ?ERR_NOT_ALLOWED} + _ -> + Txt4 = <<"Changing role/affiliation is not allowed">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt4)} end end end; @@ -3143,10 +3176,12 @@ process_iq_owner(From, set, Lang, SubEl, StateData) -> andalso is_password_settings_correct(XEl, StateData) of - true -> set_config(XEl, StateData); + true -> set_config(XEl, StateData, Lang); false -> {error, ?ERR_NOT_ACCEPTABLE} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end; [#xmlel{name = <<"destroy">>} = SubEl1] -> ?INFO_MSG("Destroyed MUC room ~s by the owner ~s", @@ -3170,7 +3205,9 @@ process_iq_owner(From, get, Lang, SubEl, StateData) -> [] -> get_config(Lang, StateData, From); [Item] -> case fxml:get_tag_attr(<<"affiliation">>, Item) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> + Txt = <<"No 'affiliation' attribute found">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of {'EXIT', _} -> @@ -3642,10 +3679,10 @@ get_config(Lang, StateData, From) -> children = Res}], StateData}. -set_config(XEl, StateData) -> +set_config(XEl, StateData, Lang) -> XData = jlib:parse_xdata_submit(XEl), case XData of - invalid -> {error, ?ERR_BAD_REQUEST}; + invalid -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Incorrect data form">>)}; _ -> case set_xoption(XData, StateData#state.config) of #config{} = Config -> @@ -3675,14 +3712,20 @@ set_config(XEl, StateData) -> <<"1">> -> set_xoption(Opts, Config#config{Opt = true}); <<"true">> -> set_xoption(Opts, Config#config{Opt = true}); - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Value of '~s' should be boolean">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_BAD_REQUEST(?MYLANG, ErrTxt)} end). -define(SET_NAT_XOPT(Opt, Val), case catch jlib:binary_to_integer(Val) of I when is_integer(I), I > 0 -> set_xoption(Opts, Config#config{Opt = I}); - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Value of '~s' should be integer">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_BAD_REQUEST(?MYLANG, ErrTxt)} end). -define(SET_STRING_XOPT(Opt, Val), @@ -3735,7 +3778,10 @@ set_xoption([{<<"allow_private_messages_from_visitors">>, <<"nobody">> -> ?SET_STRING_XOPT(allow_private_messages_from_visitors, nobody); - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Value of 'allow_private_messages_from_visitors' " + "should be anyone|moderators|nobody">>, + {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)} end; set_xoption([{<<"muc#roomconfig_allowvisitorstatus">>, [Val]} @@ -3803,7 +3849,10 @@ set_xoption([{<<"muc#roomconfig_presencebroadcast">>, Vals} | Opts], end end, {false, false, false}, Vals), case Roles of - error -> {error, ?ERR_BAD_REQUEST}; + error -> + Txt = <<"Value of 'muc#roomconfig_presencebroadcast' should " + "be moderator|participant|visitor">>, + {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)}; {M, P, V} -> Res = if M -> [moderator]; true -> [] end ++ @@ -3831,7 +3880,10 @@ set_xoption([{<<"muc#roomconfig_whois">>, [Val]} <<"anyone">> -> ?SET_BOOL_XOPT(anonymous, (iolist_to_binary(integer_to_list(0)))); - _ -> {error, ?ERR_BAD_REQUEST} + _ -> + Txt = <<"Value of 'muc#roomconfig_whois' should be " + "moderators|anyone">>, + {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)} end; set_xoption([{<<"muc#roomconfig_maxusers">>, [Val]} | Opts], @@ -3854,8 +3906,10 @@ set_xoption([{<<"muc#roomconfig_captcha_whitelist">>, ?SET_JIDMULTI_XOPT(captcha_whitelist, JIDs); set_xoption([{<<"FORM_TYPE">>, _} | Opts], Config) -> set_xoption(Opts, Config); -set_xoption([_ | _Opts], _Config) -> - {error, ?ERR_BAD_REQUEST}. +set_xoption([{Opt, _Vals} | _Opts], _Config) -> + Txt = <<"Unknown option '~s'">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_BAD_REQUEST(?MYLANG, ErrTxt)}. change_config(Config, StateData) -> send_config_change_info(Config, StateData), @@ -4128,8 +4182,9 @@ destroy_room(DEl, StateData) -> false -> ?FEATURE(Fiffalse) end). -process_iq_disco_info(_From, set, _Lang, _StateData) -> - {error, ?ERR_NOT_ALLOWED}; +process_iq_disco_info(_From, set, Lang, _StateData) -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt)}; process_iq_disco_info(_From, get, Lang, StateData) -> Config = StateData#state.config, {result, @@ -4199,9 +4254,10 @@ iq_disco_info_extras(Lang, StateData) -> <<"muc#roominfo_occupants">>, (iolist_to_binary(integer_to_list(Len))))]}]. -process_iq_disco_items(_From, set, _Lang, _StateData) -> - {error, ?ERR_NOT_ALLOWED}; -process_iq_disco_items(From, get, _Lang, StateData) -> +process_iq_disco_items(_From, set, Lang, _StateData) -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt)}; +process_iq_disco_items(From, get, Lang, StateData) -> case (StateData#state.config)#config.public_list of true -> {result, get_mucroom_disco_items(StateData), StateData}; @@ -4209,18 +4265,26 @@ process_iq_disco_items(From, get, _Lang, StateData) -> case is_occupant_or_admin(From, StateData) of true -> {result, get_mucroom_disco_items(StateData), StateData}; - _ -> {error, ?ERR_FORBIDDEN} + _ -> + Txt = <<"Only occupants or administrators can perform this query">>, + {error, ?ERRT_FORBIDDEN(Lang, Txt)} end end. -process_iq_captcha(_From, get, _Lang, _SubEl, +process_iq_captcha(_From, get, Lang, _SubEl, _StateData) -> - {error, ?ERR_NOT_ALLOWED}; -process_iq_captcha(_From, set, _Lang, SubEl, + Txt = <<"Value 'get' of 'type' attribute is not allowed">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt)}; +process_iq_captcha(_From, set, Lang, SubEl, StateData) -> case ejabberd_captcha:process_reply(SubEl) of ok -> {result, [], StateData}; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + {error, malformed} -> + Txt = <<"Incorrect CAPTCHA submit">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; + _ -> + Txt = <<"The CAPTCHA verification has failed">>, + {error, ?ERRT_NOT_ALLOWED(Lang, Txt)} end. process_iq_vcard(_From, get, _Lang, _SubEl, StateData) -> @@ -4442,33 +4506,38 @@ is_invitation(Els) -> end, false, Els). -check_invitation(From, Els, Lang, StateData) -> +check_invitation(From, Packet, Lang, StateData) -> FAffiliation = get_affiliation(From, StateData), CanInvite = (StateData#state.config)#config.allow_user_invites orelse FAffiliation == admin orelse FAffiliation == owner, - InviteEl = case fxml:remove_cdata(Els) of - [#xmlel{name = <<"x">>, children = Els1} = XEl] -> - case fxml:get_tag_attr_s(<<"xmlns">>, XEl) of - ?NS_MUC_USER -> ok; - _ -> throw({error, ?ERR_BAD_REQUEST}) - end, - case fxml:remove_cdata(Els1) of - [#xmlel{name = <<"invite">>} = InviteEl1] -> InviteEl1; - _ -> throw({error, ?ERR_BAD_REQUEST}) - end; - _ -> throw({error, ?ERR_BAD_REQUEST}) + InviteEl = case fxml:get_subtag_with_xmlns(Packet, <<"x">>, ?NS_MUC_USER) of + false -> + Txt1 = <<"No 'x' element found">>, + throw({error, ?ERRT_BAD_REQUEST(Lang, Txt1)}); + XEl -> + case fxml:get_subtag(XEl, <<"invite">>) of + false -> + Txt2 = <<"No 'invite' element found">>, + throw({error, ?ERRT_BAD_REQUEST(Lang, Txt2)}); + InviteEl1 -> + InviteEl1 + end end, JID = case jid:from_string(fxml:get_tag_attr_s(<<"to">>, InviteEl)) of - error -> throw({error, ?ERR_JID_MALFORMED}); + error -> + Txt = <<"Incorrect value of 'to' attribute">>, + throw({error, ?ERRT_JID_MALFORMED(Lang, Txt)}); JID1 -> JID1 end, case CanInvite of - false -> throw({error, ?ERR_NOT_ALLOWED}); + false -> + Txt3 = <<"Invitations are not allowed in this conference">>, + throw({error, ?ERRT_NOT_ALLOWED(Lang, Txt3)}); true -> Reason = fxml:get_path_s(InviteEl, [{elem, <<"reason">>}, cdata]), diff --git a/src/mod_offline.erl b/src/mod_offline.erl index fa6a961f..54eda165 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -387,8 +387,9 @@ handle_offline_query(#jid{luser = U, lserver = S} = From, end end, IQ#iq{type = result, sub_el = []}; -handle_offline_query(_From, _To, #iq{sub_el = SubEl} = IQ) -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}. +handle_offline_query(_From, _To, #iq{sub_el = SubEl, lang = Lang} = IQ) -> + Txt = <<"Query to another users is forbidden">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}. handle_offline_items_view(JID, #xmlel{children = Items}) -> {U, S, R} = jid:tolower(JID), diff --git a/src/mod_ping.erl b/src/mod_ping.erl index e8a977de..305c6a69 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -204,13 +204,14 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %% Hook callbacks %%==================================================================== iq_ping(_From, _To, - #iq{type = Type, sub_el = SubEl} = IQ) -> + #iq{type = Type, sub_el = SubEl, lang = Lang} = IQ) -> case {Type, SubEl} of {get, #xmlel{name = <<"ping">>}} -> IQ#iq{type = result, sub_el = []}; _ -> + Txt = <<"Ping query is incorrect">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]} + sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]} end. user_online(_SID, JID, _Info) -> diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 193befe8..ea36fed2 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -105,27 +105,29 @@ process_iq(_From, _To, IQ) -> SubEl = IQ#iq.sub_el, IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. -process_iq_get(_, From, _To, #iq{sub_el = SubEl}, +process_iq_get(_, From, _To, #iq{lang = Lang, sub_el = SubEl}, #userlist{name = Active}) -> #jid{luser = LUser, lserver = LServer} = From, #xmlel{children = Els} = SubEl, case fxml:remove_cdata(Els) of - [] -> process_lists_get(LUser, LServer, Active); + [] -> process_lists_get(LUser, LServer, Active, Lang); [#xmlel{name = Name, attrs = Attrs}] -> case Name of <<"list">> -> ListName = fxml:get_attr(<<"name">>, Attrs), - process_list_get(LUser, LServer, ListName); - _ -> {error, ?ERR_BAD_REQUEST} + process_list_get(LUser, LServer, ListName, Lang); + _ -> + Txt = <<"Unsupported tag name">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end; - _ -> {error, ?ERR_BAD_REQUEST} + _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Too many elements">>)} end. -process_lists_get(LUser, LServer, Active) -> - case process_lists_get(LUser, LServer, Active, +process_lists_get(LUser, LServer, Active, Lang) -> + case process_lists_get_db(LUser, LServer, Active, gen_mod:db_type(LServer, ?MODULE)) of - error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; + error -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)}; {_Default, []} -> {result, [#xmlel{name = <<"query">>, @@ -151,7 +153,7 @@ process_lists_get(LUser, LServer, Active) -> children = ADItems}]} end. -process_lists_get(LUser, LServer, _Active, mnesia) -> +process_lists_get_db(LUser, LServer, _Active, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of {'EXIT', _Reason} -> error; @@ -165,7 +167,7 @@ process_lists_get(LUser, LServer, _Active, mnesia) -> Lists), {Default, LItems} end; -process_lists_get(LUser, LServer, _Active, riak) -> +process_lists_get_db(LUser, LServer, _Active, riak) -> case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{default = Default, lists = Lists}} -> LItems = lists:map(fun ({N, _}) -> @@ -180,7 +182,7 @@ process_lists_get(LUser, LServer, _Active, riak) -> {error, _} -> error end; -process_lists_get(LUser, LServer, _Active, odbc) -> +process_lists_get_db(LUser, LServer, _Active, odbc) -> Default = case catch sql_get_default_privacy_list(LUser, LServer) of {selected, []} -> none; {selected, [{DefName}]} -> DefName; @@ -198,11 +200,11 @@ process_lists_get(LUser, LServer, _Active, odbc) -> _ -> error end. -process_list_get(LUser, LServer, {value, Name}) -> - case process_list_get(LUser, LServer, Name, +process_list_get(LUser, LServer, {value, Name}, Lang) -> + case process_list_get_db(LUser, LServer, Name, gen_mod:db_type(LServer, ?MODULE)) of - error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; + error -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)}; not_found -> {error, ?ERR_ITEM_NOT_FOUND}; Items -> LItems = lists:map(fun item_to_xml/1, Items), @@ -213,10 +215,10 @@ process_list_get(LUser, LServer, {value, Name}) -> [#xmlel{name = <<"list">>, attrs = [{<<"name">>, Name}], children = LItems}]}]} end; -process_list_get(_LUser, _LServer, false) -> +process_list_get(_LUser, _LServer, false, _Lang) -> {error, ?ERR_BAD_REQUEST}. -process_list_get(LUser, LServer, Name, mnesia) -> +process_list_get_db(LUser, LServer, Name, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of {'EXIT', _Reason} -> error; @@ -227,7 +229,7 @@ process_list_get(LUser, LServer, Name, mnesia) -> _ -> not_found end end; -process_list_get(LUser, LServer, Name, riak) -> +process_list_get_db(LUser, LServer, Name, riak) -> case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{lists = Lists}} -> case lists:keysearch(Name, 1, Lists) of @@ -239,7 +241,7 @@ process_list_get(LUser, LServer, Name, riak) -> {error, _} -> error end; -process_list_get(LUser, LServer, Name, odbc) -> +process_list_get_db(LUser, LServer, Name, odbc) -> case catch sql_get_privacy_list_id(LUser, LServer, Name) of {selected, []} -> not_found; {selected, [{ID}]} -> @@ -332,7 +334,7 @@ list_to_action(S) -> <<"deny">> -> deny end. -process_iq_set(_, From, _To, #iq{sub_el = SubEl}) -> +process_iq_set(_, From, _To, #iq{lang = Lang, sub_el = SubEl}) -> #jid{luser = LUser, lserver = LServer} = From, #xmlel{children = Els} = SubEl, case fxml:remove_cdata(Els) of @@ -342,27 +344,30 @@ process_iq_set(_, From, _To, #iq{sub_el = SubEl}) -> case Name of <<"list">> -> process_list_set(LUser, LServer, ListName, - fxml:remove_cdata(SubEls)); + fxml:remove_cdata(SubEls), Lang); <<"active">> -> process_active_set(LUser, LServer, ListName); <<"default">> -> - process_default_set(LUser, LServer, ListName); - _ -> {error, ?ERR_BAD_REQUEST} + process_default_set(LUser, LServer, ListName, Lang); + _ -> + Txt = <<"Unsupported tag name">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end; _ -> {error, ?ERR_BAD_REQUEST} end. -process_default_set(LUser, LServer, Value) -> - case process_default_set(LUser, LServer, Value, +process_default_set(LUser, LServer, Value, Lang) -> + case process_default_set_db(LUser, LServer, Value, gen_mod:db_type(LServer, ?MODULE)) of - {atomic, error} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; + {atomic, error} -> + {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)}; {atomic, not_found} -> {error, ?ERR_ITEM_NOT_FOUND}; {atomic, ok} -> {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end. -process_default_set(LUser, LServer, {value, Name}, +process_default_set_db(LUser, LServer, {value, Name}, mnesia) -> F = fun () -> case mnesia:read({privacy, {LUser, LServer}}) of @@ -378,7 +383,7 @@ process_default_set(LUser, LServer, {value, Name}, end end, mnesia:transaction(F); -process_default_set(LUser, LServer, {value, Name}, riak) -> +process_default_set_db(LUser, LServer, {value, Name}, riak) -> {atomic, case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{lists = Lists} = P} -> @@ -393,7 +398,7 @@ process_default_set(LUser, LServer, {value, Name}, riak) -> {error, _} -> not_found end}; -process_default_set(LUser, LServer, {value, Name}, +process_default_set_db(LUser, LServer, {value, Name}, odbc) -> F = fun () -> case sql_get_privacy_list_names_t(LUser) of @@ -406,7 +411,7 @@ process_default_set(LUser, LServer, {value, Name}, end end, odbc_queries:sql_transaction(LServer, F); -process_default_set(LUser, LServer, false, mnesia) -> +process_default_set_db(LUser, LServer, false, mnesia) -> F = fun () -> case mnesia:read({privacy, {LUser, LServer}}) of [] -> ok; @@ -414,7 +419,7 @@ process_default_set(LUser, LServer, false, mnesia) -> end end, mnesia:transaction(F); -process_default_set(LUser, LServer, false, riak) -> +process_default_set_db(LUser, LServer, false, riak) -> {atomic, case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, R} -> @@ -422,7 +427,7 @@ process_default_set(LUser, LServer, false, riak) -> {error, _} -> ok end}; -process_default_set(LUser, LServer, false, odbc) -> +process_default_set_db(LUser, LServer, false, odbc) -> case catch sql_unset_default_privacy_list(LUser, LServer) of @@ -588,14 +593,16 @@ set_privacy_list(LUser, LServer, Name, List, odbc) -> end, odbc_queries:sql_transaction(LServer, F). -process_list_set(LUser, LServer, {value, Name}, Els) -> +process_list_set(LUser, LServer, {value, Name}, Els, Lang) -> case parse_items(Els) of false -> {error, ?ERR_BAD_REQUEST}; remove -> case remove_privacy_list(LUser, LServer, Name, gen_mod:db_type(LServer, ?MODULE)) of - {atomic, conflict} -> {error, ?ERR_CONFLICT}; + {atomic, conflict} -> + Txt = <<"Cannot remove default list">>, + {error, ?ERRT_CONFLICT(Lang, Txt)}; {atomic, ok} -> ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), @@ -605,7 +612,7 @@ process_list_set(LUser, LServer, {value, Name}, Els) -> list = []}, Name}}), {result, []}; - _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} + _ -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)} end; List -> case set_privacy_list(LUser, LServer, Name, List, @@ -622,10 +629,10 @@ process_list_set(LUser, LServer, {value, Name}, Els) -> needdb = NeedDb}, Name}}), {result, []}; - _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} + _ -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)} end end; -process_list_set(_LUser, _LServer, false, _Els) -> +process_list_set(_LUser, _LServer, false, _Els, _Lang) -> {error, ?ERR_BAD_REQUEST}. parse_items([]) -> remove; diff --git a/src/mod_private.erl b/src/mod_private.erl index f3dceeaa..b4b06450 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -73,52 +73,58 @@ stop(Host) -> ?NS_PRIVATE). process_sm_iq(#jid{luser = LUser, lserver = LServer}, - #jid{luser = LUser, lserver = LServer}, IQ) + #jid{luser = LUser, lserver = LServer}, #iq{lang = Lang} = IQ) when IQ#iq.type == set -> case IQ#iq.sub_el of #xmlel{name = <<"query">>, children = Xmlels} -> case filter_xmlels(Xmlels) of [] -> + Txt = <<"No private data found in this query">>, IQ#iq{type = error, - sub_el = [IQ#iq.sub_el, ?ERR_NOT_ACCEPTABLE]}; + sub_el = [IQ#iq.sub_el, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)]}; Data -> set_data(LUser, LServer, Data), IQ#iq{type = result, sub_el = []} end; _ -> + Txt = <<"No query found">>, IQ#iq{type = error, - sub_el = [IQ#iq.sub_el, ?ERR_NOT_ACCEPTABLE]} + sub_el = [IQ#iq.sub_el, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)]} end; %% process_sm_iq(#jid{luser = LUser, lserver = LServer}, - #jid{luser = LUser, lserver = LServer}, IQ) + #jid{luser = LUser, lserver = LServer}, #iq{lang = Lang} = IQ) when IQ#iq.type == get -> case IQ#iq.sub_el of #xmlel{name = <<"query">>, attrs = Attrs, children = Xmlels} -> case filter_xmlels(Xmlels) of [] -> + Txt = <<"No private data found in this query">>, IQ#iq{type = error, - sub_el = [IQ#iq.sub_el, ?ERR_BAD_FORMAT]}; + sub_el = [IQ#iq.sub_el, ?ERRT_BAD_FORMAT(Lang, Txt)]}; Data -> case catch get_data(LUser, LServer, Data) of {'EXIT', _Reason} -> + Txt = <<"Database failure">>, IQ#iq{type = error, sub_el = - [IQ#iq.sub_el, ?ERR_INTERNAL_SERVER_ERROR]}; + [IQ#iq.sub_el, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]}; Storage_Xmlels -> IQ#iq{type = result, sub_el = [?Xmlel_Query(Attrs, Storage_Xmlels)]} end end; _ -> + Txt = <<"No query found">>, IQ#iq{type = error, - sub_el = [IQ#iq.sub_el, ?ERR_BAD_FORMAT]} + sub_el = [IQ#iq.sub_el, ?ERRT_BAD_FORMAT(Lang, Txt)]} end; %% -process_sm_iq(_From, _To, IQ) -> +process_sm_iq(_From, _To, #iq{lang = Lang} = IQ) -> + Txt = <<"Query to another users is forbidden">>, IQ#iq{type = error, - sub_el = [IQ#iq.sub_el, ?ERR_FORBIDDEN]}. + sub_el = [IQ#iq.sub_el, ?ERRT_FORBIDDEN(Lang, Txt)]}. filter_xmlels(Xmlels) -> filter_xmlels(Xmlels, []). diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 8b4644ba..d64afa04 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -150,7 +150,7 @@ process_iq(_, children = iq_vcard(Lang)}]}; %% bytestreams info request process_iq(JID, - #iq{type = get, sub_el = SubEl, + #iq{type = get, sub_el = SubEl, lang = Lang, xmlns = ?NS_BYTESTREAMS} = IQ, #state{acl = ACL, stream_addr = StreamAddr, @@ -165,11 +165,12 @@ process_iq(JID, attrs = [{<<"xmlns">>, ?NS_BYTESTREAMS}], children = StreamHostEl}]}; deny -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} + Txt = <<"Denied by ACL">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]} end; %% bytestream activation request process_iq(InitiatorJID, - #iq{type = set, sub_el = SubEl, + #iq{type = set, sub_el = SubEl, lang = Lang, xmlns = ?NS_BYTESTREAMS} = IQ, #state{acl = ACL, serverhost = ServerHost}) -> @@ -194,22 +195,27 @@ process_iq(InitiatorJID, of ok -> IQ#iq{type = result, sub_el = []}; false -> + Txt = <<"Failed to activate bytestream">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}; + sub_el = [SubEl, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)]}; limit -> + Txt = <<"Too many active bytestreams">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_RESOURCE_CONSTRAINT]}; + sub_el = [SubEl, ?ERRT_RESOURCE_CONSTRAINT(Lang, Txt)]}; conflict -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_CONFLICT]}; + Txt = <<"Bytestream already activated">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_CONFLICT(Lang, Txt)]}; _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end; _ -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} + Txt = <<"Malformed JID">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]} end; deny -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} + Txt = <<"Denied by ACL">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]} end; %% Unknown "set" or "get" request process_iq(_, #iq{type = Type, sub_el = SubEl} = IQ, _) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 6531ed87..247b9f8c 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -1034,7 +1034,10 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> none -> ok; invalid -> - Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), + Txt = <<"Incorrect authorization response">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), ejabberd_router:route(To, From, Err); XFields -> handle_authorization_response(Host, From, To, Packet, XFields) @@ -1418,13 +1421,14 @@ adhoc_request(Host, _ServerHost, Owner, send_pending_node_form(Host, Owner, Lang, Plugins); adhoc_request(Host, _ServerHost, Owner, #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, - action = <<"execute">>, xdata = XData}, + action = <<"execute">>, xdata = XData, lang = Lang}, _Access, _Plugins) -> ParseOptions = case XData of #xmlel{name = <<"x">>} = XEl -> case jlib:parse_xdata_submit(XEl) of invalid -> - {error, ?ERR_BAD_REQUEST}; + Txt = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; XData2 -> case set_xoption(Host, XData2, []) of NewOpts when is_list(NewOpts) -> {result, NewOpts}; @@ -1432,8 +1436,8 @@ adhoc_request(Host, _ServerHost, Owner, end end; _ -> - ?INFO_MSG("Bad XForm: ~p", [XData]), - {error, ?ERR_BAD_REQUEST} + Txt = <<"No data form found">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end, case ParseOptions of {result, XForm} -> @@ -1463,7 +1467,9 @@ send_pending_node_form(Host, Owner, _Lang, Plugins) -> end, case lists:filter(Filter, Plugins) of [] -> - {error, ?ERR_FEATURE_NOT_IMPLEMENTED}; + Err = extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, + unsupported, <<"get-pending">>), + {error, Err}; Ps -> XOpts = [#xmlel{name = <<"option">>, attrs = [], children = [#xmlel{name = <<"value">>, @@ -1504,10 +1510,11 @@ send_pending_auth_events(Host, Node, Owner) -> true -> case node_call(Host, Type, get_affiliation, [Nidx, Owner]) of {result, owner} -> node_call(Host, Type, get_node_subscriptions, [Nidx]); - _ -> {error, ?ERR_FORBIDDEN} + _ -> {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} end; false -> - {error, ?ERR_FEATURE_NOT_IMPLEMENTED} + {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, + unsupported, <<"get-pending">>)} end end, case transaction(Host, Node, Action, sync_dirty) of @@ -1644,6 +1651,7 @@ send_authorization_approval(Host, JID, SNode, Subscription) -> ejabberd_router:route(service_jid(Host), JID, Stanza). handle_authorization_response(Host, From, To, Packet, XFields) -> + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), case {lists:keysearch(<<"pubsub#node">>, 1, XFields), lists:keysearch(<<"pubsub#subscriber_jid">>, 1, XFields), lists:keysearch(<<"pubsub#allow">>, 1, XFields)} @@ -1665,7 +1673,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs); false -> - {error, ?ERR_FORBIDDEN} + {error, ?ERRT_FORBIDDEN(Lang, <<"You're not an owner">>)} end end, case transaction(Host, Node, Action, sync_dirty) of @@ -1680,7 +1688,8 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> ejabberd_router:route(To, From, Err) end; _ -> - Err = jlib:make_error_reply(Packet, ?ERR_NOT_ACCEPTABLE), + Txt = <<"Incorrect data form">>, + Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)), ejabberd_router:route(To, From, Err) end. @@ -1691,7 +1700,7 @@ update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> end, Subs), case Sub of - [{pending, SubId}] -> + [{pending, SubId}|_] -> NewSub = case Allow of true -> subscribed; false -> none @@ -1700,7 +1709,8 @@ update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> send_authorization_approval(Host, Subscriber, Node, NewSub), {result, ok}; _ -> - {error, ?ERR_UNEXPECTED_REQUEST} + Txt = <<"No pending subscriptions found">>, + {error, ?ERRT_UNEXPECTED_REQUEST(?MYLANG, Txt)} end. -define(XFIELD(Type, Label, Var, Val), @@ -1830,7 +1840,8 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> [#xmlel{name = <<"x">>} = XEl] -> case jlib:parse_xdata_submit(XEl) of invalid -> - {error, ?ERR_BAD_REQUEST}; + Txt = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)}; XData -> case set_xoption(Host, XData, node_options(Host, Type)) of NewOpts when is_list(NewOpts) -> {result, NewOpts}; @@ -1839,7 +1850,8 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> end; _ -> ?INFO_MSG("Node ~p; bad configuration: ~p", [Node, Configuration]), - {error, ?ERR_BAD_REQUEST} + Txt = <<"No data form found">>, + {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)} end, case ParseOptions of {result, NodeOptions} -> @@ -1876,7 +1888,8 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> Error end; _ -> - {error, ?ERR_FORBIDDEN} + Txt1 = <<"You're not allowed to create nodes">>, + {error, ?ERRT_FORBIDDEN(?MYLANG, Txt1)} end end, Reply = [#xmlel{name = <<"pubsub">>, @@ -1926,7 +1939,7 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> | {error, xmlel()} ). delete_node(_Host, <<>>, _Owner) -> - {error, ?ERR_NOT_ALLOWED}; + {error, ?ERRT_NOT_ALLOWED(?MYLANG, <<"No node specified">>)}; delete_node(Host, Node, Owner) -> Action = fun (#pubsub_node{type = Type, id = Nidx}) -> case node_call(Host, Type, get_affiliation, [Nidx, Owner]) of @@ -1938,7 +1951,7 @@ delete_node(Host, Node, Owner) -> Error -> Error end; _ -> - {error, ?ERR_FORBIDDEN} + {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} end end, Reply = [], @@ -2247,22 +2260,28 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, Access) -> {result, Reply}; {result, {_, Result}} -> {result, Result}; - {error, ?ERR_ITEM_NOT_FOUND} -> - Type = select_type(ServerHost, Host, Node), - case lists:member(<<"auto-create">>, plugin_features(Host, Type)) of + {error, _} = Error -> + case is_item_not_found(Error) of true -> - case create_node(Host, ServerHost, Node, Publisher, Type, Access, []) of - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"create">>, - attrs = [{<<"node">>, NewNode}]}]}]} -> - publish_item(Host, ServerHost, NewNode, Publisher, ItemId, Payload); - _ -> - {error, ?ERR_ITEM_NOT_FOUND} + Type = select_type(ServerHost, Host, Node), + case lists:member(<<"auto-create">>, plugin_features(Host, Type)) of + true -> + case create_node(Host, ServerHost, Node, Publisher, Type, Access, []) of + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"create">>, + attrs = [{<<"node">>, NewNode}]}]}]} -> + publish_item(Host, ServerHost, NewNode, Publisher, ItemId, Payload); + _ -> + {error, ?ERR_ITEM_NOT_FOUND} + end; + false -> + Txt = <<"Automatic node creation is not enabled">>, + {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, Txt)} end; false -> - {error, ?ERR_ITEM_NOT_FOUND} + Error end; Error -> Error @@ -2416,7 +2435,9 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> end; true -> case catch jlib:binary_to_integer(SMaxItems) of - {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; + {'EXIT', _} -> + Txt = <<"Value of 'max_items' should be integer">>, + {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)}; Val -> Val end end, @@ -2639,7 +2660,7 @@ get_affiliations(Host, Node, JID) -> {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"modify-affiliations">>)}; Affiliation /= owner -> - {error, ?ERR_FORBIDDEN}; + {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)}; true -> node_call(Host, Type, get_node_affiliations, [Nidx]) end @@ -2732,7 +2753,7 @@ set_affiliations(Host, Node, From, EntitiesEls) -> FilteredEntities), {result, []}; _ -> - {error, ?ERR_FORBIDDEN} + {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} end end, case transaction(Host, Node, Action, sync_dirty) of @@ -2948,7 +2969,7 @@ get_subscriptions(Host, Node, JID) -> {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"manage-subscriptions">>)}; Affiliation /= owner -> - {error, ?ERR_FORBIDDEN}; + {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)}; true -> node_call(Host, Type, get_node_subscriptions, [Nidx]) end @@ -3059,10 +3080,10 @@ set_subscriptions(Host, Node, From, EntitiesEls) -> [], Entities), case Result of [] -> {result, []}; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + [{error, E}|_] -> {error, E} end; _ -> - {error, ?ERR_FORBIDDEN} + {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} end end, case transaction(Host, Node, Action, sync_dirty) of @@ -3606,7 +3627,7 @@ get_configure(Host, ServerHost, Node, From, Lang) -> children = get_configure_xfields(Type, Options, Lang, Groups)}]}]}]}; _ -> - {error, ?ERR_FORBIDDEN} + {error, ?ERRT_FORBIDDEN(Lang, <<"You're not an owner">>)} end end, case transaction(Host, Node, Action, sync_dirty) of @@ -3820,7 +3841,8 @@ set_configure(Host, Node, From, Els, Lang) -> {result, owner} -> case jlib:parse_xdata_submit(XEl) of invalid -> - {error, ?ERR_BAD_REQUEST}; + Txt = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; XData -> OldOpts = case Options of [] -> node_options(Host, Type); @@ -3840,7 +3862,8 @@ set_configure(Host, Node, From, Els, Lang) -> end end; _ -> - {error, ?ERR_FORBIDDEN} + Txt = <<"You're not an owner">>, + {error, ?ERRT_FORBIDDEN(Lang, Txt)} end end, case transaction(Host, Node, Action, transaction) of @@ -3854,10 +3877,12 @@ set_configure(Host, Node, From, Els, Lang) -> Other end; _ -> - {error, ?ERR_BAD_REQUEST} + Txt = <<"Incorrect data form">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end; _ -> - {error, ?ERR_BAD_REQUEST} + Txt = <<"No data form found">>, + {error, ?ERRT_BAD_REQUEST(Lang, Txt)} end. add_opt(Key, Value, Opts) -> @@ -3872,7 +3897,10 @@ add_opt(Key, Value, Opts) -> _ -> error end, case BoolVal of - error -> {error, ?ERR_NOT_ACCEPTABLE}; + error -> + Txt = <<"Value of '~s' should be boolean">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}; _ -> set_xoption(Host, Opts, add_opt(Opt, BoolVal, NewOpts)) end). @@ -3885,10 +3913,14 @@ add_opt(Key, Value, Opts) -> if (Max =:= undefined) orelse (IVal =< Max) -> set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); true -> - {error, ?ERR_NOT_ACCEPTABLE} + Txt = <<"Incorrect value of '~s'">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} end; _ -> - {error, ?ERR_NOT_ACCEPTABLE} + Txt = <<"Value of '~s' should be integer">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} end). -define(SET_ALIST_XOPT(Opt, Val, Vals), @@ -3896,7 +3928,9 @@ add_opt(Key, Value, Opts) -> true -> set_xoption(Host, Opts, add_opt(Opt, jlib:binary_to_atom(Val), NewOpts)); false -> - {error, ?ERR_NOT_ACCEPTABLE} + Txt = <<"Incorrect value of '~s'">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} end). -define(SET_LIST_XOPT(Opt, Val), @@ -4139,8 +4173,9 @@ features(Host, Node) when is_binary(Node) -> tree_call({_User, Server, _Resource}, Function, Args) -> tree_call(Server, Function, Args); tree_call(Host, Function, Args) -> - ?DEBUG("tree_call ~p ~p ~p", [Host, Function, Args]), - catch apply(tree(Host), Function, Args). + Tree = tree(Host), + ?DEBUG("tree_call apply(~s, ~s, ~p) @ ~s", [Tree, Function, Args, Host]), + catch apply(Tree, Function, Args). tree_action(Host, Function, Args) -> ?DEBUG("tree_action ~p ~p ~p", [Host, Function, Args]), @@ -4267,6 +4302,13 @@ extended_error(#xmlel{name = Error, attrs = Attrs, children = SubEls}, Ext, ExtA #xmlel{name = Error, attrs = Attrs, children = lists:reverse([#xmlel{name = Ext, attrs = ExtAttrs} | SubEls])}. +is_item_not_found({error, ErrEl}) -> + case fxml:get_subtag_with_xmlns( + ErrEl, <<"item-not-found">>, ?NS_STANZAS) of + #xmlel{} -> true; + _ -> false + end. + string_to_ljid(JID) -> case jid:from_string(JID) of error -> diff --git a/src/mod_register.erl b/src/mod_register.erl index 56c5f720..fee2a228 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -151,21 +151,28 @@ process_iq(From, To, %% modules. lists:foreach can %% only return ok: not_allowed -> + Txt = <<"Removal is not allowed">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + sub_el = [SubEl, + ?ERRT_NOT_ALLOWED(Lang, Txt)]}; not_exists -> + Txt = <<"No such user">>, IQ#iq{type = error, sub_el = - [SubEl, ?ERR_ITEM_NOT_FOUND]}; - _ -> + [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, ?ERR_BAD_REQUEST]} + sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]} end end; (UTag == false) and (RTag /= false) and AllowRemove -> @@ -182,7 +189,9 @@ process_iq(From, To, ejabberd_auth:remove_user(User, Server), ignore; _ -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} + 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), @@ -200,11 +209,14 @@ process_iq(From, To, SubEl, Source, Lang, true); _ -> + Txt = <<"Incorrect data form">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_BAD_REQUEST]} + sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]} end; {error, malformed} -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; + 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, @@ -344,7 +356,8 @@ try_register_or_set_password(User, Server, Password, IQ#iq{type = error, sub_el = [SubEl, Error]} end; deny -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} + 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]} @@ -359,13 +372,17 @@ try_set_password(User, Server, Password, IQ, SubEl, of ok -> IQ#iq{type = result, sub_el = []}; {error, empty_password} -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; + Txt = <<"Empty password">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}; {error, not_allowed} -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Chaning password is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; {error, invalid_jid} -> IQ#iq{type = error, - sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}; - _ -> + sub_el = [SubEl, ?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]} end; @@ -377,7 +394,7 @@ try_set_password(User, Server, Password, IQ, SubEl, try_register(User, Server, Password, SourceRaw, Lang) -> case jid:is_nodename(User) of - false -> {error, ?ERR_BAD_REQUEST}; + false -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Malformed username">>)}; _ -> JID = jid:make(User, Server, <<"">>), Access = gen_mod:get_module_opt(Server, ?MODULE, access, @@ -387,8 +404,8 @@ try_register(User, Server, Password, SourceRaw, Lang) -> case {acl:match_rule(Server, Access, JID), check_ip_access(SourceRaw, IPAccess)} of - {deny, _} -> {error, ?ERR_FORBIDDEN}; - {_, deny} -> {error, ?ERR_FORBIDDEN}; + {deny, _} -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; + {_, deny} -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)}; {allow, allow} -> Source = may_remove_resource(SourceRaw), case check_timeout(Source) of @@ -406,14 +423,20 @@ try_register(User, Server, Password, SourceRaw, Lang) -> Error -> remove_timeout(Source), case Error of - {atomic, exists} -> {error, ?ERR_CONFLICT}; + {atomic, exists} -> + Txt = <<"User already exists">>, + {error, ?ERRT_CONFLICT(Lang, Txt)}; {error, invalid_jid} -> {error, ?ERR_JID_MALFORMED}; {error, not_allowed} -> {error, ?ERR_NOT_ALLOWED}; {error, too_many_users} -> - {error, ?ERR_NOT_ALLOWED}; - {error, _Reason} -> + Txt = <<"Too many users registered">>, + {error, ?ERRT_RESOURCE_CONSTRAINT(Lang, Txt)}; + {error, _} -> + ?ERROR_MSG("failed to register user " + "~s@~s: ~p", + [User, Server, Error]), {error, ?ERR_INTERNAL_SERVER_ERROR} end end; diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 997544b1..35072e5f 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -137,13 +137,14 @@ process_iq(From, To, IQ) when ((From#jid.luser == <<"">>) andalso (From#jid.reso process_iq_manager(From, To, IQ); process_iq(From, To, IQ) -> - #iq{sub_el = SubEl} = IQ, + #iq{sub_el = SubEl, lang = Lang} = IQ, #jid{lserver = LServer} = From, case lists:member(LServer, ?MYHOSTS) of true -> process_local_iq(From, To, IQ); _ -> + Txt = <<"The query is only allowed from local users">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]} + sub_el = [SubEl, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)]} end. process_local_iq(From, To, #iq{type = Type} = IQ) -> @@ -479,12 +480,13 @@ get_roster_by_jid_t(LUser, LServer, LJID, riak) -> exit(Err) end. -try_process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) -> +try_process_iq_set(From, To, #iq{sub_el = SubEl, lang = Lang} = IQ) -> #jid{server = Server} = From, Access = gen_mod:get_module_opt(Server, ?MODULE, access, fun(A) when is_atom(A) -> A end, all), case acl:match_rule(Server, Access, From) of deny -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Denied by ACL">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; allow -> process_iq_set(From, To, IQ) end. @@ -1616,8 +1618,9 @@ process_iq_manager(From, To, IQ) -> true -> process_iq_manager2(MatchDomain, To, IQ); false -> - #iq{sub_el = SubEl} = IQ, - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} + #iq{sub_el = SubEl, lang = Lang} = IQ, + Txt = <<"Roster management is not allowed from this domain">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]} end. process_iq_manager2(MatchDomain, To, IQ) -> diff --git a/src/mod_sic.erl b/src/mod_sic.erl index 3ffd9c91..b4eae0da 100644 --- a/src/mod_sic.erl +++ b/src/mod_sic.erl @@ -60,8 +60,9 @@ process_local_iq(#jid{user = User, server = Server, _To, #iq{type = get, sub_el = _SubEl} = IQ) -> get_ip({User, Server, Resource}, IQ); process_local_iq(_From, _To, - #iq{type = set, sub_el = SubEl} = IQ) -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. + #iq{type = set, sub_el = SubEl, lang = Lang} = IQ) -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}. process_sm_iq(#jid{user = User, server = Server, resource = Resource}, @@ -69,14 +70,17 @@ process_sm_iq(#jid{user = User, server = Server, #iq{type = get, sub_el = _SubEl} = IQ) -> get_ip({User, Server, Resource}, IQ); process_sm_iq(_From, _To, - #iq{type = get, sub_el = SubEl} = IQ) -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}; + #iq{type = get, sub_el = SubEl, lang = Lang} = IQ) -> + Txt = <<"Query to another users is forbidden">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}; process_sm_iq(_From, _To, - #iq{type = set, sub_el = SubEl} = IQ) -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. + #iq{type = set, sub_el = SubEl, lang = Lang} = IQ) -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}. get_ip({User, Server, Resource}, - #iq{sub_el = + #iq{lang = Lang, + sub_el = #xmlel{name = Name, attrs = Attrs} = SubEl} = IQ) -> case ejabberd_sm:get_user_ip(User, Server, Resource) of @@ -88,8 +92,9 @@ get_ip({User, Server, Resource}, [{xmlcdata, iolist_to_binary(jlib:ip_to_list(IP))}]}]}; _ -> + Txt = <<"User session not found">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} + sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]} end. mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; diff --git a/src/mod_stats.erl b/src/mod_stats.erl index 0328aec3..c14cf8d1 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -50,17 +50,18 @@ stop(Host) -> process_local_iq(_From, To, #iq{id = _ID, type = Type, xmlns = XMLNS, - sub_el = SubEl} = + sub_el = SubEl, lang = Lang} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> #xmlel{children = Els} = SubEl, Node = str:tokens(fxml:get_tag_attr_s(<<"node">>, SubEl), <<"/">>), Names = get_names(Els, []), - case get_local_stats(To#jid.server, Node, Names) of + case get_local_stats(To#jid.server, Node, Names, Lang) of {result, Res} -> IQ#iq{type = result, sub_el = @@ -87,18 +88,18 @@ get_names([_ | Els], Res) -> get_names(Els, Res). #xmlel{name = <<"stat">>, attrs = [{<<"name">>, Name}], children = []}). -get_local_stats(_Server, [], []) -> +get_local_stats(_Server, [], [], _Lang) -> {result, [?STAT(<<"users/online">>), ?STAT(<<"users/total">>), ?STAT(<<"users/all-hosts/online">>), ?STAT(<<"users/all-hosts/total">>)]}; -get_local_stats(Server, [], Names) -> +get_local_stats(Server, [], Names, _Lang) -> {result, lists:map(fun (Name) -> get_local_stat(Server, [], Name) end, Names)}; get_local_stats(_Server, [<<"running nodes">>, _], - []) -> + [], _Lang) -> {result, [?STAT(<<"time/uptime">>), ?STAT(<<"time/cputime">>), ?STAT(<<"users/online">>), @@ -107,16 +108,19 @@ get_local_stats(_Server, [<<"running nodes">>, _], ?STAT(<<"transactions/restarted">>), ?STAT(<<"transactions/logged">>)]}; get_local_stats(_Server, [<<"running nodes">>, ENode], - Names) -> + Names, Lang) -> case search_running_node(ENode) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> + Txt = <<"No running node found">>, + {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}; Node -> {result, lists:map(fun (Name) -> get_node_stat(Node, Name) end, Names)} end; -get_local_stats(_Server, _, _) -> - {error, ?ERR_FEATURE_NOT_IMPLEMENTED}. +get_local_stats(_Server, _, _, Lang) -> + Txt = <<"No statistics found for this item">>, + {error, ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)}. -define(STATVAL(Val, Unit), #xmlel{name = <<"stat">>, diff --git a/src/mod_time.erl b/src/mod_time.erl index 8bfe9f9f..740b654a 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -51,10 +51,11 @@ stop(Host) -> ?NS_TIME). process_local_iq(_From, _To, - #iq{type = Type, sub_el = SubEl} = IQ) -> + #iq{type = Type, sub_el = SubEl, lang = Lang} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> Now_universal = calendar:universal_time(), Now_local = calendar:universal_time_to_local_time(Now_universal), diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 256dc5de..4d7c80d5 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -152,7 +152,8 @@ process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> IQ#iq{type = result, sub_el = @@ -176,7 +177,7 @@ process_local_iq(_From, _To, end. process_sm_iq(From, To, - #iq{type = Type, sub_el = SubEl} = IQ) -> + #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> #jid{user = User, lserver = LServer} = From, @@ -185,14 +186,16 @@ process_sm_iq(From, To, set_vcard(User, LServer, SubEl), IQ#iq{type = result, sub_el = []}; false -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} + Txt = <<"The query is only allowed from local users">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]} end; get -> #jid{luser = LUser, lserver = LServer} = To, case get_vcard(LUser, LServer) of error -> + Txt = <<"Database failure">>, IQ#iq{type = error, - sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; + sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]}; [] -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"vCard">>, @@ -422,15 +425,17 @@ do_route(ServerHost, From, To, Packet) -> XDataEl = find_xdata_el(SubEl), case XDataEl of false -> - Err = jlib:make_error_reply(Packet, - ?ERR_BAD_REQUEST), + Txt = <<"Data form not found">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), ejabberd_router:route(To, From, Err); _ -> XData = jlib:parse_xdata_submit(XDataEl), case XData of invalid -> - Err = jlib:make_error_reply(Packet, - ?ERR_BAD_REQUEST), + Txt = <<"Incorrect data form">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), ejabberd_router:route(To, From, Err); _ -> ResIQ = IQ#iq{type = result, @@ -470,7 +475,8 @@ do_route(ServerHost, From, To, Packet) -> #iq{type = Type, xmlns = ?NS_DISCO_INFO, lang = Lang} -> case Type of set -> - Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, Txt)), ejabberd_router:route(To, From, Err); get -> Info = ejabberd_hooks:run_fold(disco_info, ServerHost, @@ -516,10 +522,11 @@ do_route(ServerHost, From, To, Packet) -> ++ Info}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; - #iq{type = Type, xmlns = ?NS_DISCO_ITEMS} -> + #iq{type = Type, lang = Lang, xmlns = ?NS_DISCO_ITEMS} -> case Type of set -> - Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, Txt)), ejabberd_router:route(To, From, Err); get -> ResIQ = IQ#iq{type = result, diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 98aaf936..46f81af0 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -206,7 +206,8 @@ process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> IQ#iq{type = result, sub_el = @@ -240,10 +241,11 @@ process_sm_iq(_From, #jid{lserver = LServer} = To, process_vcard_ldap(To, IQ, Server) -> {ok, State} = eldap_utils:get_state(Server, ?PROCNAME), - #iq{type = Type, sub_el = SubEl} = IQ, + #iq{type = Type, sub_el = SubEl, lang = Lang} = IQ, case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> #jid{luser = LUser} = To, LServer = State#state.serverhost, @@ -455,15 +457,17 @@ route(State, From, To, Packet) -> XDataEl = find_xdata_el(SubEl), case XDataEl of false -> - Err = jlib:make_error_reply(Packet, - ?ERR_BAD_REQUEST), + Txt = <<"Data form not found">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), ejabberd_router:route(To, From, Err); _ -> XData = jlib:parse_xdata_submit(XDataEl), case XData of invalid -> - Err = jlib:make_error_reply(Packet, - ?ERR_BAD_REQUEST), + Txt = <<"Incorrect data form">>, + Err = jlib:make_error_reply( + Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), ejabberd_router:route(To, From, Err); _ -> ResIQ = IQ#iq{type = result, @@ -505,7 +509,8 @@ route(State, From, To, Packet) -> #iq{type = Type, xmlns = ?NS_DISCO_INFO, lang = Lang} -> case Type of set -> - Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, Txt)), ejabberd_router:route(To, From, Err); get -> Info = ejabberd_hooks:run_fold(disco_info, ServerHost, @@ -545,10 +550,11 @@ route(State, From, To, Packet) -> ++ Info}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; - #iq{type = Type, xmlns = ?NS_DISCO_ITEMS} -> + #iq{type = Type, lang = Lang, xmlns = ?NS_DISCO_ITEMS} -> case Type of set -> - Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, Txt)), ejabberd_router:route(To, From, Err); get -> ResIQ = IQ#iq{type = result, diff --git a/src/mod_version.erl b/src/mod_version.erl index 0e3b96bd..7f7759f2 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -52,11 +52,12 @@ stop(Host) -> process_local_iq(_From, To, #iq{id = _ID, type = Type, xmlns = _XMLNS, - sub_el = SubEl} = + sub_el = SubEl, lang = Lang} = IQ) -> case Type of set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}; get -> Host = To#jid.lserver, OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os, diff --git a/src/node_dag.erl b/src/node_dag.erl index cbb8e18c..09ee85f9 100644 --- a/src/node_dag.erl +++ b/src/node_dag.erl @@ -77,8 +77,9 @@ publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> #pubsub_node{options = Options} -> case find_opt(node_type, Options) of collection -> + Txt = <<"Publishing items to collection node is not allowed">>, {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"publish">>)}; + ?ERR_EXTENDED(?ERRT_NOT_ALLOWED(?MYLANG, Txt), <<"publish">>)}; _ -> node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index 5aeb973d..5dd52066 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -800,8 +800,10 @@ get_item(Nidx, ItemId) -> {selected, [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], [RItem]} -> {result, raw_to_item(Nidx, RItem)}; - _ -> - {error, ?ERR_ITEM_NOT_FOUND} + {selected, _, []} -> + {error, ?ERR_ITEM_NOT_FOUND}; + {'EXIT', _} -> + {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)} end. get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> diff --git a/src/nodetree_dag.erl b/src/nodetree_dag.erl index 8ac56b27..a105db83 100644 --- a/src/nodetree_dag.erl +++ b/src/nodetree_dag.erl @@ -69,13 +69,13 @@ create_node(Key, Node, Type, Owner, Options, Parents) -> Other -> Other end; _ -> - {error, ?ERR_CONFLICT} + {error, ?ERRT_CONFLICT(?MYLANG, <<"Node already exists">>)} end. delete_node(Key, Node) -> case find_node(Key, Node) of false -> - {error, ?ERR_ITEM_NOT_FOUND}; + {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}; Record -> lists:foreach(fun (#pubsub_node{options = Opts} = Child) -> NewOpts = remove_config_parent(Node, Opts), @@ -99,7 +99,7 @@ get_node(Host, Node, _From) -> get_node(Host, Node) -> case find_node(Host, Node) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}; Record -> Record end. @@ -115,7 +115,7 @@ get_nodes(Key) -> get_parentnodes(Host, Node, _From) -> case find_node(Host, Node) of false -> - {error, ?ERR_ITEM_NOT_FOUND}; + {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}; #pubsub_node{parents = Parents} -> Q = qlc:q([N || #pubsub_node{nodeid = {NHost, NNode}} = N @@ -139,7 +139,7 @@ get_subnodes(Host, <<>>) -> get_subnodes_helper(Host, <<>>); get_subnodes(Host, Node) -> case find_node(Host, Node) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; + false -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}; _ -> get_subnodes_helper(Host, Node) end. @@ -238,7 +238,7 @@ validate_parentage(Key, Owners, [<<>> | T]) -> validate_parentage(Key, Owners, [ParentID | T]) -> case find_node(Key, ParentID) of false -> - {error, ?ERR_ITEM_NOT_FOUND}; + {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}; #pubsub_node{owners = POwners, options = POptions} -> NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions), MutualOwners = [O || O <- Owners, PO <- POwners, O == PO], diff --git a/src/nodetree_tree.erl b/src/nodetree_tree.erl index e3f7e251..ff8e3f64 100644 --- a/src/nodetree_tree.erl +++ b/src/nodetree_tree.erl @@ -74,15 +74,15 @@ get_node(Host, Node, _From) -> get_node(Host, Node). get_node(Host, Node) -> - case catch mnesia:read({pubsub_node, {Host, Node}}) of + case mnesia:read({pubsub_node, {Host, Node}}) of [Record] when is_record(Record, pubsub_node) -> Record; - _ -> {error, ?ERR_ITEM_NOT_FOUND} + _ -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)} end. get_node(Nidx) -> - case catch mnesia:index_read(pubsub_node, Nidx, #pubsub_node.id) of + case mnesia:index_read(pubsub_node, Nidx, #pubsub_node.id) of [Record] when is_record(Record, pubsub_node) -> Record; - _ -> {error, ?ERR_ITEM_NOT_FOUND} + _ -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)} end. get_nodes(Host, _From) -> @@ -147,7 +147,7 @@ get_subnodes_tree(Host, Node) -> create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jid:tolower(jid:remove_resource(Owner)), - case catch mnesia:read({pubsub_node, {Host, Node}}) of + case mnesia:read({pubsub_node, {Host, Node}}) of [] -> ParentExists = case Host of {_U, _S, _R} -> @@ -183,7 +183,7 @@ create_node(Host, Node, Type, Owner, Options, Parents) -> {error, ?ERR_FORBIDDEN} end; _ -> - {error, ?ERR_CONFLICT} + {error, ?ERRT_CONFLICT(?MYLANG, <<"Node already exists">>)} end. delete_node(Host, Node) -> diff --git a/src/nodetree_tree_odbc.erl b/src/nodetree_tree_odbc.erl index ef1c20b6..6c139ad6 100644 --- a/src/nodetree_tree_odbc.erl +++ b/src/nodetree_tree_odbc.erl @@ -93,7 +93,8 @@ set_node(Record) when is_record(Record, pubsub_node) -> end, case Nidx of none -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; + Txt = <<"Node index not found">>, + {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, Txt)}; _ -> lists:foreach(fun ({Key, Value}) -> SKey = iolist_to_binary(atom_to_list(Key)), @@ -125,9 +126,9 @@ get_node(Host, Node) -> [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], [RItem]} -> raw_to_node(Host, RItem); {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)}; _ -> - {error, ?ERR_ITEM_NOT_FOUND} + {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)} end. get_node(Nidx) -> @@ -140,9 +141,9 @@ get_node(Nidx) -> [<<"host">>, <<"node">>, <<"parent">>, <<"type">>], [[Host, Node, Parent, Type]]} -> raw_to_node(Host, [Node, Parent, Type, Nidx]); {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)}; _ -> - {error, ?ERR_ITEM_NOT_FOUND} + {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)} end. get_nodes(Host, _From) -> @@ -211,7 +212,7 @@ get_subnodes_tree(Host, Node) -> create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jid:tolower(jid:remove_resource(Owner)), case nodeidx(Host, Node) of - {error, ?ERR_ITEM_NOT_FOUND} -> + {error, not_found} -> ParentExists = case Host of {_U, _S, _R} -> %% This is special case for PEP handling @@ -248,9 +249,9 @@ create_node(Host, Node, Type, Owner, Options, Parents) -> {error, ?ERR_FORBIDDEN} end; {result, _} -> - {error, ?ERR_CONFLICT}; - Error -> - Error + {error, ?ERRT_CONFLICT(?MYLANG, <<"Node already exists">>)}; + {error, db_fail} -> + {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)} end. delete_node(Host, Node) -> @@ -303,9 +304,9 @@ nodeidx(Host, Node) -> {selected, [<<"nodeid">>], [[Nidx]]} -> {result, Nidx}; {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, db_fail}; _ -> - {error, ?ERR_ITEM_NOT_FOUND} + {error, not_found} end. nodeowners(Nidx) -> diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index 22c90414..f990f6e3 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -237,31 +237,40 @@ var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> subscription_type; var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> subscription_depth; var_xfield(_) -> {error, badarg}. -val_xfield(deliver, [Val]) -> xopt_to_bool(Val); -val_xfield(digest, [Val]) -> xopt_to_bool(Val); -val_xfield(digest_frequency, [Val]) -> +val_xfield(deliver = Opt, [Val]) -> xopt_to_bool(Opt, Val); +val_xfield(digest = Opt, [Val]) -> xopt_to_bool(Opt, Val); +val_xfield(digest_frequency = Opt, [Val]) -> case catch jlib:binary_to_integer(Val) of N when is_integer(N) -> N; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> + Txt = <<"Value of '~s' should be integer">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} end; val_xfield(expire, [Val]) -> jlib:datetime_string_to_timestamp(Val); -val_xfield(include_body, [Val]) -> xopt_to_bool(Val); +val_xfield(include_body = Opt, [Val]) -> xopt_to_bool(Opt, Val); val_xfield(show_values, Vals) -> Vals; val_xfield(subscription_type, [<<"items">>]) -> items; val_xfield(subscription_type, [<<"nodes">>]) -> nodes; val_xfield(subscription_depth, [<<"all">>]) -> all; -val_xfield(subscription_depth, [Depth]) -> +val_xfield(subscription_depth = Opt, [Depth]) -> case catch jlib:binary_to_integer(Depth) of N when is_integer(N) -> N; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> + Txt = <<"Value of '~s' should be integer">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} end. %% Convert XForm booleans to Erlang booleans. -xopt_to_bool(<<"0">>) -> false; -xopt_to_bool(<<"1">>) -> true; -xopt_to_bool(<<"false">>) -> false; -xopt_to_bool(<<"true">>) -> true; -xopt_to_bool(_) -> {error, ?ERR_NOT_ACCEPTABLE}. +xopt_to_bool(_, <<"0">>) -> false; +xopt_to_bool(_, <<"1">>) -> true; +xopt_to_bool(_, <<"false">>) -> false; +xopt_to_bool(_, <<"true">>) -> true; +xopt_to_bool(Option, _) -> + Txt = <<"Value of '~s' should be boolean">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Option])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}. -spec(get_option_xfield/3 :: ( diff --git a/src/pubsub_subscription_odbc.erl b/src/pubsub_subscription_odbc.erl index 149308ad..afd31c81 100644 --- a/src/pubsub_subscription_odbc.erl +++ b/src/pubsub_subscription_odbc.erl @@ -200,31 +200,40 @@ var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> subscription_type; var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> subscription_depth; var_xfield(_) -> {error, badarg}. -val_xfield(deliver, [Val]) -> xopt_to_bool(Val); -val_xfield(digest, [Val]) -> xopt_to_bool(Val); -val_xfield(digest_frequency, [Val]) -> +val_xfield(deliver = Opt, [Val]) -> xopt_to_bool(Opt, Val); +val_xfield(digest = Opt, [Val]) -> xopt_to_bool(Opt, Val); +val_xfield(digest_frequency = Opt, [Val]) -> case catch jlib:binary_to_integer(Val) of N when is_integer(N) -> N; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> + Txt = <<"Value of '~s' should be integer">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} end; val_xfield(expire, [Val]) -> jlib:datetime_string_to_timestamp(Val); -val_xfield(include_body, [Val]) -> xopt_to_bool(Val); +val_xfield(include_body = Opt, [Val]) -> xopt_to_bool(Opt, Val); val_xfield(show_values, Vals) -> Vals; val_xfield(subscription_type, [<<"items">>]) -> items; val_xfield(subscription_type, [<<"nodes">>]) -> nodes; val_xfield(subscription_depth, [<<"all">>]) -> all; -val_xfield(subscription_depth, [Depth]) -> +val_xfield(subscription_depth = Opt, [Depth]) -> case catch jlib:binary_to_integer(Depth) of N when is_integer(N) -> N; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + _ -> + Txt = <<"Value of '~s' should be integer">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} end. %% Convert XForm booleans to Erlang booleans. -xopt_to_bool(<<"0">>) -> false; -xopt_to_bool(<<"1">>) -> true; -xopt_to_bool(<<"false">>) -> false; -xopt_to_bool(<<"true">>) -> true; -xopt_to_bool(_) -> {error, ?ERR_NOT_ACCEPTABLE}. +xopt_to_bool(_, <<"0">>) -> false; +xopt_to_bool(_, <<"1">>) -> true; +xopt_to_bool(_, <<"false">>) -> false; +xopt_to_bool(_, <<"true">>) -> true; +xopt_to_bool(Option, _) -> + Txt = <<"Value of '~s' should be boolean">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Option])), + {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}. %% Return a field for an XForm for Key, with data filled in, if %% applicable, from Options. |