summaryrefslogtreecommitdiff
path: root/src/mod_pubsub.erl
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mod_pubsub.erl136
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 ->