diff options
Diffstat (limited to '')
-rw-r--r-- | src/mod_pubsub.erl | 136 |
1 files changed, 89 insertions, 47 deletions
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 -> |