mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-22 17:28:25 +01:00
several pubsub/pep bugfix
SVN Revision: 1096
This commit is contained in:
parent
43fc8b3329
commit
02eaf9eaec
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
||||
2007-12-22 Christophe Romain <christophe.romain@process-one.net>
|
||||
|
||||
* src/ejabberd_sm.erl: change incoming_presence_hook to
|
||||
presence_probe_hook
|
||||
* src/ejabberd_c2s.erl: Likewise
|
||||
|
||||
* src/mod_pubsub/mod_pubsub.erl: send last pep item bugfix and
|
||||
broadcast optimization (EJAB-468) (EJAB-467) (EJAB-460)
|
||||
* src/mod_pubsub/pubsub.hrl: Likewise
|
||||
* src/mod_pubsub/node_default.erl: Likewise
|
||||
|
||||
2007-12-22 Badlop <badlop@process-one.net>
|
||||
|
||||
* src/mod_caps.erl: Bugfix in timeout checking. Check for timeout
|
||||
|
@ -1385,6 +1385,7 @@ process_presence_probe(From, To, StateData) ->
|
||||
deny ->
|
||||
ok;
|
||||
allow ->
|
||||
ejabberd_hooks:run(presence_probe_hook, StateData#state.server, [From, To, Packet]),
|
||||
ejabberd_router:route(To, From, Packet)
|
||||
end;
|
||||
Cond2 ->
|
||||
|
@ -386,9 +386,7 @@ do_route(From, To, Packet) ->
|
||||
From,
|
||||
jlib:jid_replace_resource(To, R),
|
||||
Packet)
|
||||
end, PResources),
|
||||
ejabberd_hooks:run(incoming_presence_hook, LServer,
|
||||
[From, To, Packet]);
|
||||
end, PResources);
|
||||
true ->
|
||||
ok
|
||||
end;
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
%%% TODO
|
||||
%%% plugin: generate Reply (do not use broadcast atom anymore)
|
||||
%%% to be implemented: deliver_notifications
|
||||
|
||||
-module(mod_pubsub).
|
||||
-version('1.10-01').
|
||||
@ -40,9 +39,7 @@
|
||||
-define(PEPNODE, "pep").
|
||||
|
||||
%% exports for hooks
|
||||
-export([set_presence/4,
|
||||
unset_presence/4,
|
||||
incoming_presence/3,
|
||||
-export([presence_probe/3,
|
||||
remove_user/2,
|
||||
disco_local_identity/5,
|
||||
disco_local_features/5,
|
||||
@ -142,9 +139,6 @@ init([ServerHost, Opts]) ->
|
||||
Host = gen_mod:get_opt_host(ServerHost, Opts, "pubsub.@HOST@"),
|
||||
ServedHosts = gen_mod:get_opt(served_hosts, Opts, []),
|
||||
Access = gen_mod:get_opt(access_createnode, Opts, all),
|
||||
mnesia:create_table(pubsub_presence,
|
||||
[{disc_copies, [node()]},
|
||||
{attributes, record_info(fields, pubsub_presence)}]),
|
||||
mod_disco:register_feature(ServerHost, ?NS_PUBSUB),
|
||||
ejabberd_hooks:add(disco_local_identity, ServerHost, ?MODULE, disco_local_identity, 75),
|
||||
ejabberd_hooks:add(disco_local_features, ServerHost, ?MODULE, disco_local_features, 75),
|
||||
@ -152,9 +146,7 @@ init([ServerHost, Opts]) ->
|
||||
ejabberd_hooks:add(disco_sm_identity, ServerHost, ?MODULE, disco_sm_identity, 75),
|
||||
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
||||
ejabberd_hooks:add(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||
ejabberd_hooks:add(incoming_presence_hook, ServerHost, ?MODULE, incoming_presence, 50),
|
||||
%%ejabberd_hooks:add(set_presence_hook, ServerHost, ?MODULE, set_presence, 50),
|
||||
%%ejabberd_hooks:add(unset_presence_hook, ServerHost, ?MODULE, unset_presence, 50),
|
||||
ejabberd_hooks:add(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
||||
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||
lists:foreach(
|
||||
@ -218,12 +210,12 @@ terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
|
||||
ok.
|
||||
|
||||
init_nodes(Host, ServerHost, ServedHosts) ->
|
||||
create_node(Host, ServerHost, ["pubsub"], ?PUBSUB_JID, ?STDNODE),
|
||||
create_node(Host, ServerHost, ["pubsub", "nodes"], ?PUBSUB_JID, ?STDNODE),
|
||||
create_node(Host, ServerHost, ["home"], ?PUBSUB_JID, ?STDNODE),
|
||||
create_node(Host, ServerHost, ["pubsub"], service_jid(Host), ?STDNODE),
|
||||
create_node(Host, ServerHost, ["pubsub", "nodes"], service_jid(Host), ?STDNODE),
|
||||
create_node(Host, ServerHost, ["home"], service_jid(Host), ?STDNODE),
|
||||
lists:foreach(
|
||||
fun(H) ->
|
||||
create_node(Host, ServerHost, ["home", H], ?PUBSUB_JID, ?STDNODE)
|
||||
create_node(Host, ServerHost, ["home", H], service_jid(Host), ?STDNODE)
|
||||
end, [ServerHost | ServedHosts]),
|
||||
ok.
|
||||
|
||||
@ -390,13 +382,7 @@ disco_sm_items(Acc, _From, To, Node, _Lang) ->
|
||||
%% presence hooks handling functions
|
||||
%%
|
||||
|
||||
set_presence(User, Server, Resource, Presence) ->
|
||||
Proc = gen_mod:get_module_proc(Server, ?PROCNAME),
|
||||
gen_server:cast(Proc, {set_presence, User, Server, Resource, Presence}).
|
||||
unset_presence(User, Server, Resource, Status) ->
|
||||
Proc = gen_mod:get_module_proc(Server, ?PROCNAME),
|
||||
gen_server:cast(Proc, {unset_presence, User, Server, Resource, Status}).
|
||||
incoming_presence(From, #jid{lserver = Host} = To, Packet) ->
|
||||
presence_probe(#jid{lserver = Host} = From, To, Packet) ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
gen_server:cast(Proc, {presence, From, To, Packet}).
|
||||
|
||||
@ -438,102 +424,70 @@ handle_call(stop, _From, State) ->
|
||||
%%--------------------------------------------------------------------
|
||||
%% @private
|
||||
handle_cast({presence, From, To, Packet}, State) ->
|
||||
Plugins = State#state.plugins,
|
||||
Key = {To#jid.lserver, From#jid.luser, From#jid.lserver},
|
||||
Record = #pubsub_presence{key = Key, resource = From#jid.lresource},
|
||||
Priority = case xml:get_subtag(Packet, "priority") of
|
||||
false -> 0;
|
||||
SubEl ->
|
||||
case catch list_to_integer(xml:get_tag_cdata(SubEl)) of
|
||||
P when is_integer(P) -> P;
|
||||
_ -> 0
|
||||
end
|
||||
end,
|
||||
PresenceType = case xml:get_tag_attr_s("type", Packet) of
|
||||
"" ->
|
||||
if Priority < 0 -> unavailable;
|
||||
true -> available
|
||||
end;
|
||||
"unavailable" -> unavailable;
|
||||
"error" -> unavailable;
|
||||
_ -> none
|
||||
end,
|
||||
PreviouslyAvailable =
|
||||
lists:member(From#jid.lresource,
|
||||
lists:map(fun(#pubsub_presence{resource = R}) -> R end,
|
||||
case catch mnesia:dirty_read(pubsub_presence, Key) of
|
||||
Result when is_list(Result) -> Result;
|
||||
_ -> []
|
||||
end)),
|
||||
case PresenceType of
|
||||
available -> mnesia:dirty_write(Record);
|
||||
unavailable -> mnesia:dirty_delete_object(Record);
|
||||
_ -> ok
|
||||
end,
|
||||
if PreviouslyAvailable == false,
|
||||
PresenceType == available ->
|
||||
%% A new resource is available. Loop through all subscriptions
|
||||
%% and if the node is so configured, send the last item.
|
||||
JID = jlib:jid_tolower(From),
|
||||
Host = State#state.host,
|
||||
ServerHost = State#state.server_host,
|
||||
%% A new resource is available. send last published items
|
||||
JID = jlib:jid_tolower(From),
|
||||
Host = State#state.host,
|
||||
ServerHost = State#state.server_host,
|
||||
if From == To ->
|
||||
%% for each node From is subscribed to
|
||||
%% and if the node is so configured, send the last published item to From
|
||||
lists:foreach(fun(Type) ->
|
||||
{result, Subscriptions} = node_action(Type, get_entity_subscriptions, [Host, From]),
|
||||
lists:foreach(
|
||||
fun(Type) ->
|
||||
{result, Subscriptions} = node_action(Type, get_entity_subscriptions, [Host, From]),
|
||||
Options = node_options(Type),
|
||||
SendLast = get_option(Options, send_last_published_item),
|
||||
AccessModel = get_option(Options, access_model),
|
||||
AllowedGroups = get_option(Options, roster_groups_allowed),
|
||||
lists:foreach(
|
||||
fun({Node, Subscription}) ->
|
||||
if
|
||||
Subscription /= none, Subscription /= pending, SendLast == on_sub_and_presence ->
|
||||
fun({Node, subscribed}) ->
|
||||
case tree_action(Host, get_node, [Host, Node]) of
|
||||
#pubsub_node{options = Options} ->
|
||||
case get_option(Options, send_last_published_item) of
|
||||
on_sub_and_presence ->
|
||||
send_last_item(Host, Node, JID);
|
||||
SendLast == on_sub_and_presence ->
|
||||
{PresenceSubscription, RosterGroup} = get_roster_info(
|
||||
To#jid.luser, To#jid.lserver, JID, AllowedGroups),
|
||||
Features = case catch mod_caps:get_features(ServerHost, mod_caps:read_caps(element(4, Packet))) of
|
||||
F when is_list(F) -> F;
|
||||
_ -> []
|
||||
end,
|
||||
case lists:member(Node ++ "+notify", Features) of
|
||||
true ->
|
||||
MaySubscribe =
|
||||
case AccessModel of
|
||||
open -> true;
|
||||
presence -> PresenceSubscription;
|
||||
whitelist -> false; % subscribers are added manually
|
||||
authorize -> false; % likewise
|
||||
roster -> RosterGroup
|
||||
end,
|
||||
if MaySubscribe ->
|
||||
send_last_item(Host, Node, JID);
|
||||
true ->
|
||||
ok
|
||||
end;
|
||||
false ->
|
||||
ok
|
||||
end;
|
||||
true ->
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
(_) ->
|
||||
_ ->
|
||||
ok
|
||||
end, Subscriptions)
|
||||
end, Plugins),
|
||||
{noreply, State};
|
||||
true ->
|
||||
{noreply, State}
|
||||
end;
|
||||
|
||||
handle_cast({set_presence, _User, _Server, _Resource, _Presence}, State) ->
|
||||
{noreply, State};
|
||||
handle_cast({unset_presence, _User, _Server, _Resource, _Status}, State) ->
|
||||
end;
|
||||
(_) ->
|
||||
ok
|
||||
end, Subscriptions)
|
||||
end, State#state.plugins);
|
||||
true ->
|
||||
ok
|
||||
end,
|
||||
%% and send to From last PEP events published by To
|
||||
PepKey = jlib:jid_tolower(jlib:jid_remove_resource(To)),
|
||||
Caps = mod_caps:read_caps(element(4, Packet)),
|
||||
lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, options = Options}) ->
|
||||
case get_option(Options, send_last_published_item) of
|
||||
on_sub_and_presence ->
|
||||
case is_caps_notify(ServerHost, Node, Caps) of
|
||||
true ->
|
||||
AllowedGroups = get_option(Options, roster_groups_allowed),
|
||||
{PresenceSubscription, RosterGroup} = get_roster_info(
|
||||
To#jid.luser, To#jid.lserver, JID, AllowedGroups),
|
||||
Subscribed = case get_option(Options, access_model) of
|
||||
open -> true;
|
||||
presence -> PresenceSubscription;
|
||||
whitelist -> false; % subscribers are added manually
|
||||
authorize -> false; % likewise
|
||||
roster -> RosterGroup
|
||||
end,
|
||||
if Subscribed ->
|
||||
send_last_item(PepKey, Node, JID);
|
||||
true ->
|
||||
ok
|
||||
end;
|
||||
false ->
|
||||
ok
|
||||
end;
|
||||
_ ->
|
||||
ok
|
||||
end
|
||||
end, tree_action(Host, get_nodes, [PepKey])),
|
||||
{noreply, State};
|
||||
|
||||
handle_cast({remove, User, Server}, State) ->
|
||||
Owner = jlib:make_jid(User, Server, ""),
|
||||
delete_nodes(Server, Owner, State#state.plugins),
|
||||
delete_nodes(Server, Owner),
|
||||
{noreply, State};
|
||||
|
||||
handle_cast(_Msg, State) ->
|
||||
@ -578,9 +532,7 @@ terminate(_Reason, #state{host = Host,
|
||||
ejabberd_hooks:delete(disco_sm_identity, ServerHost, ?MODULE, disco_sm_identity, 75),
|
||||
ejabberd_hooks:delete(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
||||
ejabberd_hooks:delete(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||
ejabberd_hooks:delete(incoming_presence_hook, ServerHost, ?MODULE, incoming_presence, 50),
|
||||
%%ejabberd_hooks:delete(set_presence_hook, ServerHost, ?MODULE, set_presence, 50),
|
||||
%%ejabberd_hooks:delete(unset_presence_hook, ServerHost, ?MODULE, unset_presence, 50),
|
||||
ejabberd_hooks:delete(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
||||
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||
lists:foreach(fun({NS,Mod}) ->
|
||||
gen_iq_handler:remove_iq_handler(Mod, ServerHost, NS)
|
||||
@ -666,9 +618,7 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) ->
|
||||
Res = IQ#iq{type = result,
|
||||
sub_el = [{xmlelement, "vCard", [{"xmlns", XMLNS}],
|
||||
iq_get_vcard(Lang)}]},
|
||||
ejabberd_router:route(To,
|
||||
From,
|
||||
jlib:iq_to_xml(Res));
|
||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
||||
#iq{} ->
|
||||
Err = jlib:make_error_reply(
|
||||
Packet,
|
||||
@ -678,7 +628,7 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) ->
|
||||
ok
|
||||
end;
|
||||
"presence" ->
|
||||
incoming_presence(From, To, Packet),
|
||||
presence_probe(From, To, Packet),
|
||||
ok;
|
||||
"message" ->
|
||||
case xml:get_attr_s("type", Attrs) of
|
||||
@ -1022,8 +972,7 @@ send_authorization_request(Host, Node, Subscriber) ->
|
||||
#pubsub_node{owners = Owners} ->
|
||||
lists:foreach(
|
||||
fun(Owner) ->
|
||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(Owner),
|
||||
Stanza)
|
||||
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza}
|
||||
end, Owners),
|
||||
ok;
|
||||
_ ->
|
||||
@ -1096,8 +1045,9 @@ handle_authorization_response(Host, From, To, Packet, XFields) ->
|
||||
end,
|
||||
case transaction(Host, Node, Action, sync_dirty) of
|
||||
{error, Error} ->
|
||||
ejabberd_router:route(To, From,
|
||||
jlib:make_error_reply(Packet, Error));
|
||||
ejabberd_router:route(
|
||||
To, From,
|
||||
jlib:make_error_reply(Packet, Error));
|
||||
{result, _NewSubscription} ->
|
||||
%% XXX: notify about subscription state change, section 12.11
|
||||
ok;
|
||||
@ -1312,25 +1262,12 @@ delete_node(Host, Node, Owner) ->
|
||||
{result, Result} ->
|
||||
{result, Result}
|
||||
end.
|
||||
delete_nodes(Host, Owner, Plugins) ->
|
||||
delete_nodes(Host, Owner) ->
|
||||
%% This removes only PEP nodes when user is removed
|
||||
OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
|
||||
lists:foreach(fun(#pubsub_node{nodeid={NodeKey, NodeName}}) ->
|
||||
delete_node(NodeKey, NodeName, Owner)
|
||||
end, tree_action(Host, get_nodes, [OwnerKey])).
|
||||
% TODO: may be best to use the generic following code
|
||||
% lists:foreach(fun(Type) ->
|
||||
% {result, Affiliations} = node_action(Type, get_entity_affiliations, [Host, Owner]),
|
||||
% NodeKey = case Type of
|
||||
% ?PEPNODE -> OwnerKey;
|
||||
% _ -> Host
|
||||
% end,
|
||||
% lists:foreach(
|
||||
% fun({NodeId, owner}) -> delete_node(NodeKey, NodeId, Owner);
|
||||
% (_) -> ok
|
||||
% end
|
||||
% end, Affiliations)
|
||||
% end, Plugins),
|
||||
|
||||
%% @spec (Host, Node, From, JID) ->
|
||||
%% {error, Reason::stanzaError()} |
|
||||
@ -1407,7 +1344,6 @@ subscribe_node(Host, Node, From, JID) ->
|
||||
{error, Error} ->
|
||||
{error, Error};
|
||||
{result, {Result, subscribed, send_last}} ->
|
||||
%% TODO was send_last_published_item
|
||||
send_all_items(Host, Node, Subscriber),
|
||||
case Result of
|
||||
default -> {result, Reply(subscribed)};
|
||||
@ -1505,7 +1441,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
|
||||
node_call(Type, publish_item, [Host, Node, Publisher, Model, MaxItems, ItemId, Payload])
|
||||
end
|
||||
end,
|
||||
%%ejabberd_hooks:run(pubsub_publish_item, Host, [Host, Node, JID, ?PUBSUB_JID, ItemId, Payload]),
|
||||
%%ejabberd_hooks:run(pubsub_publish_item, Host, [Host, Node, JID, service_jid(Host), ItemId, Payload]),
|
||||
Reply = [],
|
||||
case transaction(Host, Node, Action, sync_dirty) of
|
||||
{error, ?ERR_ITEM_NOT_FOUND} ->
|
||||
@ -1741,7 +1677,7 @@ send_items(Host, Node, LJID, Number) ->
|
||||
[{xmlelement, "x", [{"xmlns", ?NS_PUBSUB_EVENT}],
|
||||
[{xmlelement, "items", [{"node", node_to_string(Node)}],
|
||||
ItemsEls}]}]},
|
||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(LJID), Stanza).
|
||||
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(LJID), Stanza}.
|
||||
|
||||
%% @spec (Host, JID, Plugins) -> {error, Reason} | {result, Response}
|
||||
%% Host = host()
|
||||
@ -2055,18 +1991,30 @@ node_to_string(Node) ->
|
||||
string_to_node(SNode) ->
|
||||
string:tokens(SNode, "/").
|
||||
|
||||
%% @spec (Host, JID, PresenceDelivery) -> boolean()
|
||||
%% @spec (Host) -> jid()
|
||||
%% Host = host()
|
||||
%% JID = jid()
|
||||
%% @doc <p>Generate pubsub service JID.</p>
|
||||
service_jid(Host) ->
|
||||
case Host of
|
||||
{U,S,_} -> {jid, U, S, "", U, S, ""};
|
||||
_ -> {jid, "", Host, "", "", Host, ""}
|
||||
end.
|
||||
|
||||
%% @spec (LJID, PresenceDelivery) -> boolean()
|
||||
%% LJID = jid()
|
||||
%% Subscription = atom()
|
||||
%% PresenceDelivery = boolean()
|
||||
%% @doc <p>Check if a notification must be delivered or not
|
||||
to_be_delivered(_Host, _JID, false) ->
|
||||
% default is true
|
||||
true;
|
||||
to_be_delivered(Host, JID, true) ->
|
||||
case mnesia:dirty_read(pubsub_presence, {Host, element(1, JID), element(2, JID)}) of
|
||||
[_] -> true;
|
||||
[] -> false
|
||||
is_to_delivered(_, none, _) -> false;
|
||||
is_to_delivered(_, pending, _) -> false;
|
||||
is_to_delivered(_, _, false) -> true;
|
||||
is_to_delivered({User, Server, _}, _, true) ->
|
||||
case mnesia:dirty_match_object({session, '_', '_', {User, Server}, '_', '_'}) of
|
||||
[] -> false;
|
||||
Ss ->
|
||||
lists:foldl(fun({session, _, _, _, undefined, _}, Acc) -> Acc;
|
||||
({session, _, _, _, _Priority, _}, _Acc) -> true
|
||||
end, false, Ss)
|
||||
end.
|
||||
|
||||
%%%%%% broadcast functions
|
||||
@ -2094,22 +2042,19 @@ broadcast_publish_item(Host, Node, ItemId, _From, Payload) ->
|
||||
[{xmlelement, "items", [{"node", node_to_string(Node)}],
|
||||
[{xmlelement, "item", ItemAttrs, Content}]}]}]},
|
||||
lists:foreach(
|
||||
fun(#pubsub_state{stateid = {JID, _},
|
||||
fun(#pubsub_state{stateid = {LJID, _},
|
||||
subscription = Subscription}) ->
|
||||
ToBeSent = to_be_delivered(Host, JID, PresenceDelivery),
|
||||
if
|
||||
(Subscription /= none) and
|
||||
(Subscription /= pending) and
|
||||
ToBeSent ->
|
||||
case is_to_delivered(LJID, Subscription, PresenceDelivery) of
|
||||
true ->
|
||||
DestJIDs = case BroadcastAll of
|
||||
true -> ejabberd_sm:get_user_resources(element(1, JID), element(2, JID));
|
||||
false -> [JID]
|
||||
true -> ejabberd_sm:get_user_resources(element(1, LJID), element(2, LJID));
|
||||
false -> [LJID]
|
||||
end,
|
||||
lists:foreach(
|
||||
fun(DestJID) ->
|
||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(DestJID), Stanza)
|
||||
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(DestJID), Stanza}
|
||||
end, DestJIDs);
|
||||
true ->
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
end, States),
|
||||
@ -2148,7 +2093,7 @@ broadcast_retract_item(Host, Node, ItemId, ForceNotify) ->
|
||||
subscription = Subscription}) ->
|
||||
if (Subscription /= none) and
|
||||
(Subscription /= pending) ->
|
||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
||||
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza};
|
||||
true ->
|
||||
ok
|
||||
end
|
||||
@ -2181,7 +2126,7 @@ broadcast_purge_node(Host, Node) ->
|
||||
subscription = Subscription}) ->
|
||||
if (Subscription /= none) and
|
||||
(Subscription /= pending) ->
|
||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
||||
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza};
|
||||
true ->
|
||||
ok
|
||||
end
|
||||
@ -2213,7 +2158,7 @@ broadcast_removed_node(Host, Removed) ->
|
||||
subscription = Subscription}) ->
|
||||
if (Subscription /= none) and
|
||||
(Subscription /= pending) ->
|
||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
||||
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza};
|
||||
true ->
|
||||
ok
|
||||
end
|
||||
@ -2253,14 +2198,12 @@ broadcast_config_notification(Host, Node, Lang) ->
|
||||
[{xmlelement, "item", [{"id", "configuration"}],
|
||||
Content}]}]}]},
|
||||
lists:foreach(
|
||||
fun(#pubsub_state{stateid = {JID, _},
|
||||
fun(#pubsub_state{stateid = {LJID, _},
|
||||
subscription = Subscription}) ->
|
||||
ToBeSent = to_be_delivered(Host, JID, PresenceDelivery),
|
||||
if (Subscription /= none) and
|
||||
(Subscription /= pending) and
|
||||
ToBeSent ->
|
||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
||||
true ->
|
||||
case is_to_delivered(LJID, Subscription, PresenceDelivery) of
|
||||
true ->
|
||||
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(LJID), Stanza};
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
end, States),
|
||||
@ -2298,11 +2241,10 @@ broadcast_config_notification(Host, Node, Lang) ->
|
||||
broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
||||
?DEBUG("looking for pid of ~p@~p/~p", [LUser, LServer, LResource]),
|
||||
%% We need to know the resource, so we can ask for presence data.
|
||||
SenderResources = ejabberd_sm:get_user_resources(LUser, LServer),
|
||||
SenderResource = case LResource of
|
||||
"" ->
|
||||
%% If we don't know the resource, just pick one.
|
||||
case SenderResources of
|
||||
case ejabberd_sm:get_user_resources(LUser, LServer) of
|
||||
[R|_] ->
|
||||
R;
|
||||
[] ->
|
||||
@ -2322,36 +2264,19 @@ broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
||||
case catch ejabberd_c2s:get_subscribed_and_online(C2SPid) of
|
||||
ContactsWithCaps when is_list(ContactsWithCaps) ->
|
||||
?DEBUG("found contacts with caps: ~p", [ContactsWithCaps]),
|
||||
LookingFor = Node ++ "+notify",
|
||||
lists:foreach(
|
||||
fun({JID, Caps}) ->
|
||||
case catch mod_caps:get_features(LServer, Caps) of
|
||||
Features when is_list(Features) ->
|
||||
case lists:member(LookingFor, Features) of
|
||||
true ->
|
||||
To = jlib:make_jid(JID),
|
||||
ejabberd_router:route(Sender, To, Stanza);
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
_ ->
|
||||
%% couldn't get entity capabilities.
|
||||
%% nothing to do about that...
|
||||
ok
|
||||
end
|
||||
case is_caps_notify(LServer, Node, Caps) of
|
||||
true ->
|
||||
To = jlib:make_jid(JID),
|
||||
ejabberd_router ! {route, Sender, To, Stanza};
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
end, ContactsWithCaps);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
%% also send a notification to any
|
||||
%% of the account owner's available resources.
|
||||
%% See: XEP-0163 1.1 section 3
|
||||
%% Note: ejabberd_c2s:get_subscribed_and_online already returns owner online resources
|
||||
%% this loop should be deleted
|
||||
% lists:foreach(fun(Resource) ->
|
||||
% To = jlib:make_jid(LUser, LServer, Resource),
|
||||
% ejabberd_router:route(Sender, To, Stanza)
|
||||
% end, SenderResources),
|
||||
ok;
|
||||
_ ->
|
||||
ok
|
||||
@ -2359,6 +2284,12 @@ broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
||||
broadcast_by_caps(_, _, _, _) ->
|
||||
ok.
|
||||
|
||||
is_caps_notify(Host, Node, Caps) ->
|
||||
case catch mod_caps:get_features(Host, Caps) of
|
||||
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features);
|
||||
_ -> false
|
||||
end.
|
||||
|
||||
%%%%%%% Configuration handling
|
||||
|
||||
%%<p>There are several reasons why the default node configuration options request might fail:</p>
|
||||
|
@ -177,21 +177,21 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
|
||||
LOwner = jlib:jid_tolower(Owner),
|
||||
{User, Server, _Resource} = LOwner,
|
||||
Allowed = case acl:match_rule(ServerHost, Access, LOwner) of
|
||||
allow ->
|
||||
if Server == Host -> %% Server == ServerHost ??
|
||||
true;
|
||||
true ->
|
||||
case Node of
|
||||
["home", Server, User | _] -> true;
|
||||
_ -> false
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
case Owner of
|
||||
?PUBSUB_JID -> true;
|
||||
_ -> false
|
||||
end
|
||||
end,
|
||||
allow ->
|
||||
if Server == Host -> %% Server == ServerHost ??
|
||||
true;
|
||||
true ->
|
||||
case Node of
|
||||
["home", Server, User | _] -> true;
|
||||
_ -> false
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
case Owner of
|
||||
{jid, "", _, "", "", _, ""} -> true;
|
||||
_ -> false
|
||||
end
|
||||
end,
|
||||
ChildOK = true, %% TODO test with ParentNode
|
||||
{result, Allowed and ChildOK}.
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
%%% ====================================================================
|
||||
%%% This software is copyright 2006, Process-one.
|
||||
%%% This software is copyright 2007, Process-one.
|
||||
%%%
|
||||
%%% This file contains pubsub types definition.
|
||||
%%% ====================================================================
|
||||
|
||||
%% -------------------------------
|
||||
%% Pubsub constants
|
||||
-define(PUBSUB_JID, {jid, "", Host, "", "", Host, ""}).
|
||||
-define(ERR_EXTENDED(E,C), mod_pubsub:extended_error(E,C)).
|
||||
|
||||
%% this is currently a hard limit.
|
||||
|
Loading…
Reference in New Issue
Block a user