mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-26 16:26:24 +01:00
merge to lattest trunk r1716
SVN Revision: 1720
This commit is contained in:
parent
3bfb2b5cc1
commit
9f2fda6060
@ -42,7 +42,9 @@ behaviour_info(callbacks) ->
|
|||||||
{terminate, 2},
|
{terminate, 2},
|
||||||
{options, 0},
|
{options, 0},
|
||||||
{set_node, 1},
|
{set_node, 1},
|
||||||
|
{get_node, 3},
|
||||||
{get_node, 2},
|
{get_node, 2},
|
||||||
|
{get_nodes, 2},
|
||||||
{get_nodes, 1},
|
{get_nodes, 1},
|
||||||
{get_subnodes, 3},
|
{get_subnodes, 3},
|
||||||
{get_subnodes_tree, 2},
|
{get_subnodes_tree, 2},
|
||||||
|
@ -356,11 +356,11 @@ disco_sm_features(Acc, From, To, Node, _Lang) ->
|
|||||||
Acc
|
Acc
|
||||||
end.
|
end.
|
||||||
|
|
||||||
disco_sm_items(Acc, _From, To, [], _Lang) ->
|
disco_sm_items(Acc, From, To, [], _Lang) ->
|
||||||
%% TODO, use iq_disco_items(Host, [], From)
|
%% TODO, use iq_disco_items(Host, [], From)
|
||||||
Host = To#jid.ldomain,
|
Host = To#jid.ldomain,
|
||||||
LJID = jlib:short_prepd_bare_jid(To),
|
LJID = jlib:short_prepd_bare_jid(To),
|
||||||
case tree_action(Host, get_nodes, [Host]) of
|
case tree_action(Host, get_nodes, [Host, From]) of
|
||||||
[] ->
|
[] ->
|
||||||
Acc;
|
Acc;
|
||||||
Nodes ->
|
Nodes ->
|
||||||
@ -460,7 +460,7 @@ handle_cast({presence, JID, Pid}, State) ->
|
|||||||
{result, Subscriptions} = node_action(Type, get_entity_subscriptions, [Host, JID]),
|
{result, Subscriptions} = node_action(Type, get_entity_subscriptions, [Host, JID]),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({Node, subscribed}) ->
|
fun({Node, subscribed}) ->
|
||||||
case tree_action(Host, get_node, [Host, Node]) of
|
case tree_action(Host, get_node, [Host, Node, JID]) of
|
||||||
#pubsub_node{options = Options} ->
|
#pubsub_node{options = Options} ->
|
||||||
case get_option(Options, send_last_published_item) of
|
case get_option(Options, send_last_published_item) of
|
||||||
on_sub_and_presence ->
|
on_sub_and_presence ->
|
||||||
@ -477,17 +477,14 @@ handle_cast({presence, JID, Pid}, State) ->
|
|||||||
end, State#state.plugins),
|
end, State#state.plugins),
|
||||||
%% and send to From last PEP events published by its contacts
|
%% and send to From last PEP events published by its contacts
|
||||||
case catch ejabberd_c2s:get_subscribed(Pid) of
|
case catch ejabberd_c2s:get_subscribed(Pid) of
|
||||||
ContactsWithCaps when is_list(ContactsWithCaps) ->
|
Contacts when is_list(Contacts) ->
|
||||||
Caps = proplists:get_value(LJID, ContactsWithCaps),
|
|
||||||
ContactsUsers = lists:usort(lists:map(
|
|
||||||
fun({{User, Server, _}, _}) -> {User, Server} end, ContactsWithCaps)),
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({User, Server}) ->
|
fun({User, Server, _}) ->
|
||||||
PepKey = {User, Server, undefined},
|
Owner = {User, Server, undefined},
|
||||||
lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, options = Options}) ->
|
lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, options = Options}) ->
|
||||||
case get_option(Options, send_last_published_item) of
|
case get_option(Options, send_last_published_item) of
|
||||||
on_sub_and_presence ->
|
on_sub_and_presence ->
|
||||||
case is_caps_notify(ServerHost, Node, Caps) of
|
case is_caps_notify(ServerHost, Node, LJID) of
|
||||||
true ->
|
true ->
|
||||||
Subscribed = case get_option(Options, access_model) of
|
Subscribed = case get_option(Options, access_model) of
|
||||||
open -> true;
|
open -> true;
|
||||||
@ -499,8 +496,7 @@ handle_cast({presence, JID, Pid}, State) ->
|
|||||||
element(2, get_roster_info(User, Server, LJID, Grps))
|
element(2, get_roster_info(User, Server, LJID, Grps))
|
||||||
end,
|
end,
|
||||||
if Subscribed ->
|
if Subscribed ->
|
||||||
?DEBUG("send ~s's ~s event to ~s",[exmpp_jid:jid_to_list(User, Server),Node,exmpp_jid:jid_to_list(JID)]),
|
send_last_item(Owner, Node, LJID);
|
||||||
send_last_item(PepKey, Node, LJID);
|
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
@ -510,8 +506,8 @@ handle_cast({presence, JID, Pid}, State) ->
|
|||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
end, tree_action(Host, get_nodes, [PepKey]))
|
end, tree_action(Host, get_nodes, [Owner, JID]))
|
||||||
end, ContactsUsers);
|
end, Contacts);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
@ -786,7 +782,7 @@ iq_disco_items(Host, Item, From) ->
|
|||||||
Node = string_to_node(SNode),
|
Node = string_to_node(SNode),
|
||||||
%% Note: Multiple Node Discovery not supported (mask on pubsub#type)
|
%% Note: Multiple Node Discovery not supported (mask on pubsub#type)
|
||||||
%% TODO this code is also back-compatible with pubsub v1.8 (for client issue)
|
%% TODO this code is also back-compatible with pubsub v1.8 (for client issue)
|
||||||
%% TODO make it pubsub v1.10 compliant (this breaks client compatibility)
|
%% TODO make it pubsub v1.12 compliant (breaks client compatibility ?)
|
||||||
%% TODO That is, remove name attribute
|
%% TODO That is, remove name attribute
|
||||||
Action =
|
Action =
|
||||||
fun(#pubsub_node{type = Type}) ->
|
fun(#pubsub_node{type = Type}) ->
|
||||||
@ -951,6 +947,10 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, _Lang, Access, Plugins) ->
|
|||||||
get_subscriptions(Host, From, Plugins);
|
get_subscriptions(Host, From, Plugins);
|
||||||
{get, 'affiliations'} ->
|
{get, 'affiliations'} ->
|
||||||
get_affiliations(Host, From, Plugins);
|
get_affiliations(Host, From, Plugins);
|
||||||
|
{get, "options"} ->
|
||||||
|
{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "subscription-options")};
|
||||||
|
{set, "options"} ->
|
||||||
|
{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "subscription-options")};
|
||||||
_ ->
|
_ ->
|
||||||
{error, 'feature-not-implemented'}
|
{error, 'feature-not-implemented'}
|
||||||
end;
|
end;
|
||||||
@ -1024,7 +1024,7 @@ send_authorization_request(Host, Node, Subscriber) ->
|
|||||||
#xmlattr{name = 'type', value = "boolean"},
|
#xmlattr{name = 'type', value = "boolean"},
|
||||||
#xmlattr{name = 'label', value = translate:translate(Lang, "Allow this JID to subscribe to this pubsub node?")}], children =
|
#xmlattr{name = 'label', value = translate:translate(Lang, "Allow this JID to subscribe to this pubsub node?")}], children =
|
||||||
[#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = <<"false">>}]}]}]}]},
|
[#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = <<"false">>}]}]}]}]},
|
||||||
case tree_action(Host, get_node, [Host, Node]) of
|
case tree_action(Host, get_node, [Host, Node, Subscriber]) of
|
||||||
#pubsub_node{owners = Owners} ->
|
#pubsub_node{owners = Owners} ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({U1, S1, R1}) ->
|
fun({U1, S1, R1}) ->
|
||||||
@ -1053,19 +1053,37 @@ find_authorization_response(Packet) ->
|
|||||||
[] -> none;
|
[] -> none;
|
||||||
[XFields] when is_list(XFields) ->
|
[XFields] when is_list(XFields) ->
|
||||||
case lists:keysearch("FORM_TYPE", 1, XFields) of
|
case lists:keysearch("FORM_TYPE", 1, XFields) of
|
||||||
{value, {_, ?NS_PUBSUB_SUBSCRIBE_AUTH_s}} ->
|
{value, {_, [?NS_PUBSUB_SUBSCRIBE_AUTH_s]}} ->
|
||||||
XFields;
|
XFields;
|
||||||
_ ->
|
_ ->
|
||||||
invalid
|
invalid
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% @spec (Host, JID, Node, Subscription) -> void
|
||||||
|
%% Host = mod_pubsub:host()
|
||||||
|
%% JID = jlib:jid()
|
||||||
|
%% Node = string()
|
||||||
|
%% Subscription = atom()
|
||||||
|
%% Plugins = [Plugin::string()]
|
||||||
|
%% @doc Send a message to JID with the supplied Subscription
|
||||||
|
send_authorization_approval(Host, JID, Node, Subscription) ->
|
||||||
|
Stanza = {xmlelement, "message",
|
||||||
|
[],
|
||||||
|
[{xmlelement, "event", [{"xmlns", ?NS_PUBSUB_EVENT}],
|
||||||
|
[{xmlelement, "subscription",
|
||||||
|
[{"node", Node},
|
||||||
|
{"jid", jlib:jid_to_string(JID)},
|
||||||
|
{"subscription", subscription_to_string(Subscription)}],
|
||||||
|
[]}]}]},
|
||||||
|
ejabberd_router ! {route, service_jid(Host), JID, Stanza}.
|
||||||
|
|
||||||
handle_authorization_response(Host, From, To, Packet, XFields) ->
|
handle_authorization_response(Host, From, To, Packet, XFields) ->
|
||||||
case {lists:keysearch("pubsub#node", 1, XFields),
|
case {lists:keysearch("pubsub#node", 1, XFields),
|
||||||
lists:keysearch("pubsub#subscriber_jid", 1, XFields),
|
lists:keysearch("pubsub#subscriber_jid", 1, XFields),
|
||||||
lists:keysearch("pubsub#allow", 1, XFields)} of
|
lists:keysearch("pubsub#allow", 1, XFields)} of
|
||||||
{{value, {_, SNode}}, {value, {_, SSubscriber}},
|
{{value, {_, [SNode]}}, {value, {_, [SSubscriber]}},
|
||||||
{value, {_, SAllow}}} ->
|
{value, {_, [SAllow]}}} ->
|
||||||
Node = case Host of
|
Node = case Host of
|
||||||
{_, _, _} -> [SNode];
|
{_, _, _} -> [SNode];
|
||||||
_ -> string:tokens(SNode, "/")
|
_ -> string:tokens(SNode, "/")
|
||||||
@ -1080,7 +1098,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) ->
|
|||||||
%%options = Options,
|
%%options = Options,
|
||||||
owners = Owners}) ->
|
owners = Owners}) ->
|
||||||
IsApprover = lists:member(jlib:short_prepd_bare_jid(From), Owners),
|
IsApprover = lists:member(jlib:short_prepd_bare_jid(From), Owners),
|
||||||
Subscription = node_call(Type, get_subscription, [Host, Node, Subscriber]),
|
{result, Subscription} = node_call(Type, get_subscription, [Host, Node, Subscriber]),
|
||||||
if
|
if
|
||||||
not IsApprover ->
|
not IsApprover ->
|
||||||
{error, 'forbidden'};
|
{error, 'forbidden'};
|
||||||
@ -1091,6 +1109,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) ->
|
|||||||
true -> subscribed;
|
true -> subscribed;
|
||||||
false -> none
|
false -> none
|
||||||
end,
|
end,
|
||||||
|
send_authorization_approval(Host, Subscriber, SNode, NewSubscription),
|
||||||
node_call(Type, set_subscription, [Host, Node, Subscriber, NewSubscription])
|
node_call(Type, set_subscription, [Host, Node, Subscriber, NewSubscription])
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
@ -1457,34 +1476,38 @@ publish_item(Host, ServerHost, Node, Publisher, "", Payload) ->
|
|||||||
publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload);
|
publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload);
|
||||||
publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
|
publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
|
||||||
Action = fun(#pubsub_node{options = Options, type = Type}) ->
|
Action = fun(#pubsub_node{options = Options, type = Type}) ->
|
||||||
Features = features(Type),
|
Features = features(Type),
|
||||||
PublishFeature = lists:member("publish", Features),
|
PublishFeature = lists:member("publish", Features),
|
||||||
PublishModel = get_option(Options, publish_model),
|
PublishModel = get_option(Options, publish_model),
|
||||||
MaxItems = max_items(Options),
|
MaxItems = max_items(Options),
|
||||||
PayloadSize = size(term_to_binary(Payload)),
|
PayloadCount = payload_elements(xmlelement, Payload),
|
||||||
PayloadMaxSize = get_option(Options, max_payload_size),
|
PayloadSize = size(term_to_binary(Payload)),
|
||||||
if
|
PayloadMaxSize = get_option(Options, max_payload_size),
|
||||||
not PublishFeature ->
|
% pubsub#deliver_payloads true
|
||||||
%% Node does not support item publication
|
% pubsub#persist_items true -> 1 item; false -> 0 item
|
||||||
{error, extended_error('feature-not-implemented', unsupported, "publish")};
|
if
|
||||||
PayloadSize > PayloadMaxSize ->
|
not PublishFeature ->
|
||||||
%% Entity attempts to publish very large payload
|
%% Node does not support item publication
|
||||||
{error, extended_error('not-acceptable', "payload-too-big")};
|
{error, extended_error('feature-not-implemented', unsupported, "publish")};
|
||||||
%%?? -> iq_pubsub just does that matchs
|
PayloadSize > PayloadMaxSize ->
|
||||||
%% % Entity attempts to publish item with multiple payload elements or namespace does not match
|
%% Entity attempts to publish very large payload
|
||||||
%% {error, extended_error('bad-request', "invalid-payload")};
|
{error, extended_error('not-acceptable', "payload-too-big")};
|
||||||
%% % Publisher attempts to publish to persistent node with no item
|
PayloadCount > 1 ->
|
||||||
%% {error, extended_error('bad-request', "item-required")};
|
%% Entity attempts to publish item with multiple payload elements
|
||||||
Payload == "" ->
|
{error, extended_error('bad-request', "invalid-payload")};
|
||||||
%% Publisher attempts to publish to payload node with no payload
|
Payload == "" ->
|
||||||
{error, extended_error('bad-request', "payload-required")};
|
%% Publisher attempts to publish to payload node with no payload
|
||||||
%%?? ->
|
{error, extended_error('bad-request', "payload-required")};
|
||||||
%% % Publisher attempts to publish to transient notification node with item
|
(MaxItems == 0) and (PayloadSize > 0) ->
|
||||||
%% {error, extended_error('bad-request', "item-forbidden")};
|
% Publisher attempts to publish to transient notification node with item
|
||||||
true ->
|
{error, extended_error('bad-request', "item-forbidden")};
|
||||||
node_call(Type, publish_item, [Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload])
|
(MaxItems > 0) and (PayloadSize == 0) ->
|
||||||
end
|
% Publisher attempts to publish to persistent node with no item
|
||||||
end,
|
{error, extended_error('bad-request', "item-required")};
|
||||||
|
true ->
|
||||||
|
node_call(Type, publish_item, [Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload])
|
||||||
|
end
|
||||||
|
end,
|
||||||
ejabberd_hooks:run(pubsub_publish_item, ServerHost, [ServerHost, Node, Publisher, service_jid(Host), ItemId, Payload]),
|
ejabberd_hooks:run(pubsub_publish_item, ServerHost, [ServerHost, Node, Publisher, service_jid(Host), ItemId, Payload]),
|
||||||
Reply = [],
|
Reply = [],
|
||||||
case transaction(Host, Node, Action, sync_dirty) of
|
case transaction(Host, Node, Action, sync_dirty) of
|
||||||
@ -1556,7 +1579,7 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) ->
|
|||||||
PersistentFeature = lists:member("persistent-items", Features),
|
PersistentFeature = lists:member("persistent-items", Features),
|
||||||
DeleteFeature = lists:member("delete-nodes", Features),
|
DeleteFeature = lists:member("delete-nodes", Features),
|
||||||
if
|
if
|
||||||
%%?? -> iq_pubsub just does that matchs
|
%%-> iq_pubsub just does that matchs
|
||||||
%% %% Request does not specify an item
|
%% %% Request does not specify an item
|
||||||
%% {error, extended_error('bad-request', "item-required")};
|
%% {error, extended_error('bad-request', "item-required")};
|
||||||
not PersistentFeature ->
|
not PersistentFeature ->
|
||||||
@ -1735,7 +1758,7 @@ send_items(Host, Node, {LU, LS, LR} = LJID, Number) ->
|
|||||||
[];
|
[];
|
||||||
Items ->
|
Items ->
|
||||||
case Number of
|
case Number of
|
||||||
last -> lists:sublist(lists:reverse(Items), 1);
|
last -> lists:last(Items);
|
||||||
all -> Items;
|
all -> Items;
|
||||||
N when N > 0 -> lists:nthtail(length(Items)-N, Items);
|
N when N > 0 -> lists:nthtail(length(Items)-N, Items);
|
||||||
_ -> Items
|
_ -> Items
|
||||||
@ -2098,6 +2121,15 @@ is_to_delivered({User, Server, _}, _, true) ->
|
|||||||
end, false, Ss)
|
end, false, Ss)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% @spec (Elem, Payload) -> int()
|
||||||
|
%% Elem = atom()
|
||||||
|
%% Payload = term()
|
||||||
|
%% @doc <p>Count occurence of given element in payload.</p>
|
||||||
|
payload_elements(Elem, Payload) -> payload_elements(Elem, Payload, 0).
|
||||||
|
payload_elements(_, [], Count) -> Count;
|
||||||
|
payload_elements(Elem, [Elem|Tail], Count) -> payload_elements(Elem, Tail, Count+1);
|
||||||
|
payload_elements(Elem, [_|Tail], Count) -> payload_elements(Elem, Tail, Count).
|
||||||
|
|
||||||
%%%%%% broadcast functions
|
%%%%%% broadcast functions
|
||||||
|
|
||||||
broadcast_publish_item(Host, Node, ItemId, _From, Payload) ->
|
broadcast_publish_item(Host, Node, ItemId, _From, Payload) ->
|
||||||
@ -2324,58 +2356,52 @@ broadcast_config_notification(Host, Node, Lang) ->
|
|||||||
%% broadcast Stanza to all contacts of the user that are advertising
|
%% broadcast Stanza to all contacts of the user that are advertising
|
||||||
%% interest in this kind of Node.
|
%% interest in this kind of Node.
|
||||||
broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
||||||
?DEBUG("looking for pid of ~p@~p/~p", [LUser, LServer, LResource]),
|
SenderResource = user_resource(LUser, LServer, LResource),
|
||||||
%% We need to know the resource, so we can ask for presence data.
|
case ejabberd_sm:get_session_pid(LUser, LServer, SenderResource) of
|
||||||
SenderResource = case LResource of
|
C2SPid when is_pid(C2SPid) ->
|
||||||
undefined ->
|
%% set the from address on the notification to the bare JID of the account owner
|
||||||
%% If we don't know the resource, just pick one.
|
%% Also, add "replyto" if entity has presence subscription to the account owner
|
||||||
case ejabberd_sm:get_user_resources(LUser, LServer) of
|
%% See XEP-0163 1.1 section 4.3.1
|
||||||
[R|_] ->
|
Sender = exmpp_jid:make_jid(LUser, LServer),
|
||||||
R;
|
%%ReplyTo = jlib:make_jid(LUser, LServer, SenderResource), % This has to be used
|
||||||
[] ->
|
case catch ejabberd_c2s:get_subscribed(C2SPid) of
|
||||||
undefined
|
Contacts when is_list(Contacts) ->
|
||||||
end;
|
Online = lists:foldl(fun({U, S, R}, Acc) ->
|
||||||
_ ->
|
case user_resource(U, S, R) of
|
||||||
LResource
|
[] -> Acc;
|
||||||
end,
|
OR -> [{U, S, OR}|Acc]
|
||||||
case SenderResource of
|
|
||||||
undefined ->
|
|
||||||
?DEBUG("~p@~p is offline; can't deliver ~p to contacts", [LUser, LServer, Stanza]),
|
|
||||||
ok;
|
|
||||||
_ ->
|
|
||||||
case ejabberd_sm:get_session_pid(LUser, LServer, SenderResource) of
|
|
||||||
C2SPid when is_pid(C2SPid) ->
|
|
||||||
%% set the from address on the notification to the bare JID of the account owner
|
|
||||||
%% Also, add "replyto" if entity has presence subscription to the account owner
|
|
||||||
%% See XEP-0163 1.1 section 4.3.1
|
|
||||||
Sender = exmpp_jid:make_jid(LUser, LServer),
|
|
||||||
%%ReplyTo = jlib:make_jid(LUser, LServer, SenderResource), % This has to be used
|
|
||||||
case catch ejabberd_c2s:get_subscribed_and_online(C2SPid) of
|
|
||||||
ContactsWithCaps when is_list(ContactsWithCaps) ->
|
|
||||||
?DEBUG("found contacts with caps: ~p", [ContactsWithCaps]),
|
|
||||||
lists:foreach(
|
|
||||||
fun({{U1, S1, R1}, Caps}) ->
|
|
||||||
case is_caps_notify(LServer, Node, Caps) of
|
|
||||||
true ->
|
|
||||||
To = exmpp_jid:make_jid(U1, S1, R1),
|
|
||||||
ejabberd_router ! {route, Sender, To, Stanza};
|
|
||||||
false ->
|
|
||||||
ok
|
|
||||||
end
|
end
|
||||||
end, ContactsWithCaps);
|
end, [], Contacts),
|
||||||
_ ->
|
lists:foreach(fun({U, S, R}) ->
|
||||||
ok
|
case is_caps_notify(LServer, Node, {U, S, R}) of
|
||||||
end,
|
true ->
|
||||||
ok;
|
ejabberd_router ! {route, Sender, exmpp_jlib:make_jid(U, S, R), Stanza};
|
||||||
_ ->
|
false ->
|
||||||
?DEBUG("~p@~p has no session; can't deliver ~p to contacts", [LUser, LServer, Stanza]),
|
ok
|
||||||
ok
|
end
|
||||||
end
|
end, Online);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
ok;
|
||||||
|
_ ->
|
||||||
|
?DEBUG("~p@~p has no session; can't deliver ~p to contacts", [LUser, LServer, Stanza]),
|
||||||
|
ok
|
||||||
end;
|
end;
|
||||||
broadcast_by_caps(_, _, _, _) ->
|
broadcast_by_caps(_, _, _, _) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
is_caps_notify(Host, Node, Caps) ->
|
user_resource(LUser, LServer, []) ->
|
||||||
|
%% If we don't know the resource, just pick first if any
|
||||||
|
case ejabberd_sm:get_user_resources(LUser, LServer) of
|
||||||
|
[R|_] -> R;
|
||||||
|
[] -> []
|
||||||
|
end;
|
||||||
|
user_resource(_, _, LResource) ->
|
||||||
|
LResource.
|
||||||
|
|
||||||
|
is_caps_notify(Host, Node, LJID) ->
|
||||||
|
Caps = mod_caps:get_caps(LJID),
|
||||||
case catch mod_caps:get_features(Host, Caps) of
|
case catch mod_caps:get_features(Host, Caps) of
|
||||||
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features);
|
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features);
|
||||||
_ -> false
|
_ -> false
|
||||||
@ -2408,7 +2434,7 @@ get_configure(Host, Node, From, Lang) ->
|
|||||||
transaction(Host, Node, Action, sync_dirty).
|
transaction(Host, Node, Action, sync_dirty).
|
||||||
|
|
||||||
get_default(Host, Node, _From, Lang) ->
|
get_default(Host, Node, _From, Lang) ->
|
||||||
Type=select_type(Host, Host, Node),
|
Type = select_type(Host, Host, Node),
|
||||||
Options = node_options(Type),
|
Options = node_options(Type),
|
||||||
{result, [#xmlel{ns = ?NS_PUBSUB_OWNER, name = 'pubsub', children =
|
{result, [#xmlel{ns = ?NS_PUBSUB_OWNER, name = 'pubsub', children =
|
||||||
[#xmlel{ns = ?NS_PUBSUB_OWNER, name = 'default', children =
|
[#xmlel{ns = ?NS_PUBSUB_OWNER, name = 'default', children =
|
||||||
@ -2647,7 +2673,8 @@ set_xoption([{"pubsub#type", Value} | Opts], NewOpts) ->
|
|||||||
set_xoption([{"pubsub#body_xslt", Value} | Opts], NewOpts) ->
|
set_xoption([{"pubsub#body_xslt", Value} | Opts], NewOpts) ->
|
||||||
?SET_STRING_XOPT(body_xslt, Value);
|
?SET_STRING_XOPT(body_xslt, Value);
|
||||||
set_xoption([_ | _Opts], _NewOpts) ->
|
set_xoption([_ | _Opts], _NewOpts) ->
|
||||||
{error, 'not-acceptable'}.
|
% skip unknown field
|
||||||
|
set_xoption(Opts, NewOpts).
|
||||||
|
|
||||||
%%%% plugin handling
|
%%%% plugin handling
|
||||||
|
|
||||||
@ -2657,18 +2684,18 @@ plugins(Host) ->
|
|||||||
_ -> [?STDNODE]
|
_ -> [?STDNODE]
|
||||||
end.
|
end.
|
||||||
select_type(ServerHost, Host, Node, Type)->
|
select_type(ServerHost, Host, Node, Type)->
|
||||||
?DEBUG("SELECT_TYPE : ~p~n", [Node]),
|
?DEBUG("SELECT_TYPE : ~p~n", [[ServerHost, Host, Node, Type]]),
|
||||||
case Host of
|
case Host of
|
||||||
{_User, _Server, _Resource} ->
|
{_User, _Server, _Resource} ->
|
||||||
case ets:lookup(gen_mod:get_module_proc(ServerHost, pubsub_state), pep_mapping) of
|
case ets:lookup(gen_mod:get_module_proc(ServerHost, pubsub_state), pep_mapping) of
|
||||||
[{pep_mapping, PM}] -> ?DEBUG("SELECT_TYPE : ~p~n", [PM]), proplists:get_value(Node, PM,?PEPNODE);
|
[{pep_mapping, PM}] -> ?DEBUG("SELECT_TYPE : ~p~n", [PM]), proplists:get_value(Node, PM, ?PEPNODE);
|
||||||
R -> ?DEBUG("SELECT_TYPE why ?: ~p~n", [R]), ?PEPNODE
|
R -> ?DEBUG("SELECT_TYPE why ?: ~p~n", [R]), ?PEPNODE
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Type
|
Type
|
||||||
end.
|
end.
|
||||||
select_type(ServerHost, Host, Node) ->
|
select_type(ServerHost, Host, Node) ->
|
||||||
select_type(ServerHost, Host, Node,hd(plugins(ServerHost))).
|
select_type(ServerHost, Host, Node, hd(plugins(ServerHost))).
|
||||||
|
|
||||||
features() ->
|
features() ->
|
||||||
[
|
[
|
||||||
|
@ -382,6 +382,10 @@ unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) ->
|
|||||||
%% Requesting entity is prohibited from unsubscribing entity
|
%% Requesting entity is prohibited from unsubscribing entity
|
||||||
not Authorized ->
|
not Authorized ->
|
||||||
{error, 'forbidden'};
|
{error, 'forbidden'};
|
||||||
|
%% Was just subscriber, remove the record
|
||||||
|
State#pubsub_state.affiliation == none ->
|
||||||
|
mnesia:delete({pubsub_state, State#pubsub_state.stateid}),
|
||||||
|
{result, default};
|
||||||
true ->
|
true ->
|
||||||
set_state(State#pubsub_state{subscription = none}),
|
set_state(State#pubsub_state{subscription = none}),
|
||||||
{result, default}
|
{result, default}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%% ====================================================================
|
%%% ====================================================================
|
||||||
|
|
||||||
-module(node_zoo).
|
-module(node_flat).
|
||||||
-author('christophe.romain@process-one.net').
|
-author('christophe.romain@process-one.net').
|
||||||
|
|
||||||
-include_lib("exmpp/include/exmpp.hrl").
|
-include_lib("exmpp/include/exmpp.hrl").
|
||||||
@ -70,7 +70,7 @@ terminate(Host, ServerHost) ->
|
|||||||
node_default:terminate(Host, ServerHost).
|
node_default:terminate(Host, ServerHost).
|
||||||
|
|
||||||
options() ->
|
options() ->
|
||||||
[{node_type, zoo},
|
[{node_type, flat},
|
||||||
{deliver_payloads, true},
|
{deliver_payloads, true},
|
||||||
{notify_config, false},
|
{notify_config, false},
|
||||||
{notify_delete, false},
|
{notify_delete, false},
|
||||||
@ -99,12 +99,7 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) ->
|
|||||||
true; % pubsub service always allowed
|
true; % pubsub service always allowed
|
||||||
_ ->
|
_ ->
|
||||||
{LU, LS, LR} = LOwner,
|
{LU, LS, LR} = LOwner,
|
||||||
case acl:match_rule(ServerHost, Access, exmpp_jid:make_jid(LU, LS, LR)) of
|
acl:match_rule(ServerHost, Access, exmpp_jid:make_jid(LU, LS, LR)) =:= allow
|
||||||
allow ->
|
|
||||||
true;
|
|
||||||
_ ->
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
{result, Allowed}.
|
{result, Allowed}.
|
||||||
|
|
@ -46,7 +46,9 @@
|
|||||||
terminate/2,
|
terminate/2,
|
||||||
options/0,
|
options/0,
|
||||||
set_node/1,
|
set_node/1,
|
||||||
|
get_node/3,
|
||||||
get_node/2,
|
get_node/2,
|
||||||
|
get_nodes/2,
|
||||||
get_nodes/1,
|
get_nodes/1,
|
||||||
get_subnodes/3,
|
get_subnodes/3,
|
||||||
get_subnodes_tree/2,
|
get_subnodes_tree/2,
|
||||||
@ -98,6 +100,9 @@ set_node(_) ->
|
|||||||
%% @spec (Host, Node) -> pubsubNode() | {error, Reason}
|
%% @spec (Host, Node) -> pubsubNode() | {error, Reason}
|
||||||
%% Host = mod_pubsub:host()
|
%% Host = mod_pubsub:host()
|
||||||
%% Node = mod_pubsub:pubsubNode()
|
%% Node = mod_pubsub:pubsubNode()
|
||||||
|
get_node(Host, Node, _From) ->
|
||||||
|
get_node(Host, Node).
|
||||||
|
|
||||||
get_node(Host, Node) ->
|
get_node(Host, Node) ->
|
||||||
case catch mnesia:read({pubsub_node, {Host, Node}}) of
|
case catch mnesia:read({pubsub_node, {Host, Node}}) of
|
||||||
[Record] when is_record(Record, pubsub_node) -> Record;
|
[Record] when is_record(Record, pubsub_node) -> Record;
|
||||||
@ -107,6 +112,9 @@ get_node(Host, Node) ->
|
|||||||
|
|
||||||
%% @spec (Key) -> [pubsubNode()] | {error, Reason}
|
%% @spec (Key) -> [pubsubNode()] | {error, Reason}
|
||||||
%% Key = mod_pubsub:host() | mod_pubsub:jid()
|
%% Key = mod_pubsub:host() | mod_pubsub:jid()
|
||||||
|
get_nodes(Key, _From) ->
|
||||||
|
get_nodes(Key).
|
||||||
|
|
||||||
get_nodes(Key) ->
|
get_nodes(Key) ->
|
||||||
mnesia:match_object(#pubsub_node{nodeid = {Key, '_'}, _ = '_'}).
|
mnesia:match_object(#pubsub_node{nodeid = {Key, '_'}, _ = '_'}).
|
||||||
|
|
||||||
|
@ -44,7 +44,9 @@
|
|||||||
terminate/2,
|
terminate/2,
|
||||||
options/0,
|
options/0,
|
||||||
set_node/1,
|
set_node/1,
|
||||||
|
get_node/3,
|
||||||
get_node/2,
|
get_node/2,
|
||||||
|
get_nodes/2,
|
||||||
get_nodes/1,
|
get_nodes/1,
|
||||||
get_subnodes/3,
|
get_subnodes/3,
|
||||||
get_subnodes_tree/2,
|
get_subnodes_tree/2,
|
||||||
@ -87,6 +89,9 @@ set_node(_NodeRecord) ->
|
|||||||
%% Node = mod_pubsub:pubsubNode()
|
%% Node = mod_pubsub:pubsubNode()
|
||||||
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered
|
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered
|
||||||
%% as existing. Node record contains default values.</p>
|
%% as existing. Node record contains default values.</p>
|
||||||
|
get_node(Host, Node, _From) ->
|
||||||
|
get_node(Host, Node).
|
||||||
|
|
||||||
get_node(Host, Node) ->
|
get_node(Host, Node) ->
|
||||||
#pubsub_node{nodeid = {Host, Node}}.
|
#pubsub_node{nodeid = {Host, Node}}.
|
||||||
|
|
||||||
@ -94,6 +99,9 @@ get_node(Host, Node) ->
|
|||||||
%% Host = mod_pubsub:host() | mod_pubsub:jid()
|
%% Host = mod_pubsub:host() | mod_pubsub:jid()
|
||||||
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered
|
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered
|
||||||
%% as existing. Nodes list can not be determined.</p>
|
%% as existing. Nodes list can not be determined.</p>
|
||||||
|
get_nodes(Key, _From) ->
|
||||||
|
get_nodes(Key).
|
||||||
|
|
||||||
get_nodes(_Key) ->
|
get_nodes(_Key) ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
|
@ -119,13 +119,3 @@
|
|||||||
payload = []
|
payload = []
|
||||||
}).
|
}).
|
||||||
|
|
||||||
|
|
||||||
%% @type pubsubPresence() = #pubsub_presence{
|
|
||||||
%% key = {Host::host(), User::string(), Server::string()},
|
|
||||||
%% presence = list()}.
|
|
||||||
%%% <p>This is the format of the <tt>published presence</tt> table. The type of the
|
|
||||||
%%% table is: <tt>set</tt>,<tt>ram</tt>.</p>
|
|
||||||
-record(pubsub_presence, {key,
|
|
||||||
resource
|
|
||||||
}).
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user