mirror of
https://github.com/processone/ejabberd.git
synced 2025-01-03 18:02:28 +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>
|
2007-12-22 Badlop <badlop@process-one.net>
|
||||||
|
|
||||||
* src/mod_caps.erl: Bugfix in timeout checking. Check for timeout
|
* src/mod_caps.erl: Bugfix in timeout checking. Check for timeout
|
||||||
|
@ -1385,6 +1385,7 @@ process_presence_probe(From, To, StateData) ->
|
|||||||
deny ->
|
deny ->
|
||||||
ok;
|
ok;
|
||||||
allow ->
|
allow ->
|
||||||
|
ejabberd_hooks:run(presence_probe_hook, StateData#state.server, [From, To, Packet]),
|
||||||
ejabberd_router:route(To, From, Packet)
|
ejabberd_router:route(To, From, Packet)
|
||||||
end;
|
end;
|
||||||
Cond2 ->
|
Cond2 ->
|
||||||
|
@ -386,9 +386,7 @@ do_route(From, To, Packet) ->
|
|||||||
From,
|
From,
|
||||||
jlib:jid_replace_resource(To, R),
|
jlib:jid_replace_resource(To, R),
|
||||||
Packet)
|
Packet)
|
||||||
end, PResources),
|
end, PResources);
|
||||||
ejabberd_hooks:run(incoming_presence_hook, LServer,
|
|
||||||
[From, To, Packet]);
|
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
%%% TODO
|
%%% TODO
|
||||||
%%% plugin: generate Reply (do not use broadcast atom anymore)
|
%%% plugin: generate Reply (do not use broadcast atom anymore)
|
||||||
%%% to be implemented: deliver_notifications
|
|
||||||
|
|
||||||
-module(mod_pubsub).
|
-module(mod_pubsub).
|
||||||
-version('1.10-01').
|
-version('1.10-01').
|
||||||
@ -40,9 +39,7 @@
|
|||||||
-define(PEPNODE, "pep").
|
-define(PEPNODE, "pep").
|
||||||
|
|
||||||
%% exports for hooks
|
%% exports for hooks
|
||||||
-export([set_presence/4,
|
-export([presence_probe/3,
|
||||||
unset_presence/4,
|
|
||||||
incoming_presence/3,
|
|
||||||
remove_user/2,
|
remove_user/2,
|
||||||
disco_local_identity/5,
|
disco_local_identity/5,
|
||||||
disco_local_features/5,
|
disco_local_features/5,
|
||||||
@ -142,9 +139,6 @@ init([ServerHost, Opts]) ->
|
|||||||
Host = gen_mod:get_opt_host(ServerHost, Opts, "pubsub.@HOST@"),
|
Host = gen_mod:get_opt_host(ServerHost, Opts, "pubsub.@HOST@"),
|
||||||
ServedHosts = gen_mod:get_opt(served_hosts, Opts, []),
|
ServedHosts = gen_mod:get_opt(served_hosts, Opts, []),
|
||||||
Access = gen_mod:get_opt(access_createnode, Opts, all),
|
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),
|
mod_disco:register_feature(ServerHost, ?NS_PUBSUB),
|
||||||
ejabberd_hooks:add(disco_local_identity, ServerHost, ?MODULE, disco_local_identity, 75),
|
ejabberd_hooks:add(disco_local_identity, ServerHost, ?MODULE, disco_local_identity, 75),
|
||||||
ejabberd_hooks:add(disco_local_features, ServerHost, ?MODULE, disco_local_features, 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_identity, ServerHost, ?MODULE, disco_sm_identity, 75),
|
||||||
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 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(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||||
ejabberd_hooks:add(incoming_presence_hook, ServerHost, ?MODULE, incoming_presence, 50),
|
ejabberd_hooks:add(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 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(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
@ -218,12 +210,12 @@ terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
|
|||||||
ok.
|
ok.
|
||||||
|
|
||||||
init_nodes(Host, ServerHost, ServedHosts) ->
|
init_nodes(Host, ServerHost, ServedHosts) ->
|
||||||
create_node(Host, ServerHost, ["pubsub"], ?PUBSUB_JID, ?STDNODE),
|
create_node(Host, ServerHost, ["pubsub"], service_jid(Host), ?STDNODE),
|
||||||
create_node(Host, ServerHost, ["pubsub", "nodes"], ?PUBSUB_JID, ?STDNODE),
|
create_node(Host, ServerHost, ["pubsub", "nodes"], service_jid(Host), ?STDNODE),
|
||||||
create_node(Host, ServerHost, ["home"], ?PUBSUB_JID, ?STDNODE),
|
create_node(Host, ServerHost, ["home"], service_jid(Host), ?STDNODE),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(H) ->
|
fun(H) ->
|
||||||
create_node(Host, ServerHost, ["home", H], ?PUBSUB_JID, ?STDNODE)
|
create_node(Host, ServerHost, ["home", H], service_jid(Host), ?STDNODE)
|
||||||
end, [ServerHost | ServedHosts]),
|
end, [ServerHost | ServedHosts]),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@ -390,13 +382,7 @@ disco_sm_items(Acc, _From, To, Node, _Lang) ->
|
|||||||
%% presence hooks handling functions
|
%% presence hooks handling functions
|
||||||
%%
|
%%
|
||||||
|
|
||||||
set_presence(User, Server, Resource, Presence) ->
|
presence_probe(#jid{lserver = Host} = From, To, Packet) ->
|
||||||
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) ->
|
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
gen_server:cast(Proc, {presence, From, To, Packet}).
|
gen_server:cast(Proc, {presence, From, To, Packet}).
|
||||||
|
|
||||||
@ -438,102 +424,70 @@ handle_call(stop, _From, State) ->
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% @private
|
%% @private
|
||||||
handle_cast({presence, From, To, Packet}, State) ->
|
handle_cast({presence, From, To, Packet}, State) ->
|
||||||
Plugins = State#state.plugins,
|
%% A new resource is available. send last published items
|
||||||
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),
|
JID = jlib:jid_tolower(From),
|
||||||
Host = State#state.host,
|
Host = State#state.host,
|
||||||
ServerHost = State#state.server_host,
|
ServerHost = State#state.server_host,
|
||||||
lists:foreach(
|
if From == To ->
|
||||||
fun(Type) ->
|
%% 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]),
|
{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(
|
lists:foreach(
|
||||||
fun({Node, Subscription}) ->
|
fun({Node, subscribed}) ->
|
||||||
if
|
case tree_action(Host, get_node, [Host, Node]) of
|
||||||
Subscription /= none, Subscription /= pending, SendLast == on_sub_and_presence ->
|
#pubsub_node{options = Options} ->
|
||||||
|
case get_option(Options, send_last_published_item) of
|
||||||
|
on_sub_and_presence ->
|
||||||
send_last_item(Host, Node, JID);
|
send_last_item(Host, Node, JID);
|
||||||
SendLast == on_sub_and_presence ->
|
_ ->
|
||||||
|
ok
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
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(
|
{PresenceSubscription, RosterGroup} = get_roster_info(
|
||||||
To#jid.luser, To#jid.lserver, JID, AllowedGroups),
|
To#jid.luser, To#jid.lserver, JID, AllowedGroups),
|
||||||
Features = case catch mod_caps:get_features(ServerHost, mod_caps:read_caps(element(4, Packet))) of
|
Subscribed = case get_option(Options, access_model) of
|
||||||
F when is_list(F) -> F;
|
|
||||||
_ -> []
|
|
||||||
end,
|
|
||||||
case lists:member(Node ++ "+notify", Features) of
|
|
||||||
true ->
|
|
||||||
MaySubscribe =
|
|
||||||
case AccessModel of
|
|
||||||
open -> true;
|
open -> true;
|
||||||
presence -> PresenceSubscription;
|
presence -> PresenceSubscription;
|
||||||
whitelist -> false; % subscribers are added manually
|
whitelist -> false; % subscribers are added manually
|
||||||
authorize -> false; % likewise
|
authorize -> false; % likewise
|
||||||
roster -> RosterGroup
|
roster -> RosterGroup
|
||||||
end,
|
end,
|
||||||
if MaySubscribe ->
|
if Subscribed ->
|
||||||
send_last_item(Host, Node, JID);
|
send_last_item(PepKey, Node, JID);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
true ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end;
|
end
|
||||||
(_) ->
|
end, tree_action(Host, get_nodes, [PepKey])),
|
||||||
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) ->
|
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
handle_cast({remove, User, Server}, State) ->
|
handle_cast({remove, User, Server}, State) ->
|
||||||
Owner = jlib:make_jid(User, Server, ""),
|
Owner = jlib:make_jid(User, Server, ""),
|
||||||
delete_nodes(Server, Owner, State#state.plugins),
|
delete_nodes(Server, Owner),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
handle_cast(_Msg, 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_identity, ServerHost, ?MODULE, disco_sm_identity, 75),
|
||||||
ejabberd_hooks:delete(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 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(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||||
ejabberd_hooks:delete(incoming_presence_hook, ServerHost, ?MODULE, incoming_presence, 50),
|
ejabberd_hooks:delete(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 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(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||||
lists:foreach(fun({NS,Mod}) ->
|
lists:foreach(fun({NS,Mod}) ->
|
||||||
gen_iq_handler:remove_iq_handler(Mod, ServerHost, NS)
|
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,
|
Res = IQ#iq{type = result,
|
||||||
sub_el = [{xmlelement, "vCard", [{"xmlns", XMLNS}],
|
sub_el = [{xmlelement, "vCard", [{"xmlns", XMLNS}],
|
||||||
iq_get_vcard(Lang)}]},
|
iq_get_vcard(Lang)}]},
|
||||||
ejabberd_router:route(To,
|
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
||||||
From,
|
|
||||||
jlib:iq_to_xml(Res));
|
|
||||||
#iq{} ->
|
#iq{} ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet,
|
Packet,
|
||||||
@ -678,7 +628,7 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) ->
|
|||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
"presence" ->
|
"presence" ->
|
||||||
incoming_presence(From, To, Packet),
|
presence_probe(From, To, Packet),
|
||||||
ok;
|
ok;
|
||||||
"message" ->
|
"message" ->
|
||||||
case xml:get_attr_s("type", Attrs) of
|
case xml:get_attr_s("type", Attrs) of
|
||||||
@ -1022,8 +972,7 @@ send_authorization_request(Host, Node, Subscriber) ->
|
|||||||
#pubsub_node{owners = Owners} ->
|
#pubsub_node{owners = Owners} ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Owner) ->
|
fun(Owner) ->
|
||||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(Owner),
|
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza}
|
||||||
Stanza)
|
|
||||||
end, Owners),
|
end, Owners),
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
@ -1096,7 +1045,8 @@ handle_authorization_response(Host, From, To, Packet, XFields) ->
|
|||||||
end,
|
end,
|
||||||
case transaction(Host, Node, Action, sync_dirty) of
|
case transaction(Host, Node, Action, sync_dirty) of
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
ejabberd_router:route(To, From,
|
ejabberd_router:route(
|
||||||
|
To, From,
|
||||||
jlib:make_error_reply(Packet, Error));
|
jlib:make_error_reply(Packet, Error));
|
||||||
{result, _NewSubscription} ->
|
{result, _NewSubscription} ->
|
||||||
%% XXX: notify about subscription state change, section 12.11
|
%% XXX: notify about subscription state change, section 12.11
|
||||||
@ -1312,25 +1262,12 @@ delete_node(Host, Node, Owner) ->
|
|||||||
{result, Result} ->
|
{result, Result} ->
|
||||||
{result, Result}
|
{result, Result}
|
||||||
end.
|
end.
|
||||||
delete_nodes(Host, Owner, Plugins) ->
|
delete_nodes(Host, Owner) ->
|
||||||
%% This removes only PEP nodes when user is removed
|
%% This removes only PEP nodes when user is removed
|
||||||
OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
|
OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
|
||||||
lists:foreach(fun(#pubsub_node{nodeid={NodeKey, NodeName}}) ->
|
lists:foreach(fun(#pubsub_node{nodeid={NodeKey, NodeName}}) ->
|
||||||
delete_node(NodeKey, NodeName, Owner)
|
delete_node(NodeKey, NodeName, Owner)
|
||||||
end, tree_action(Host, get_nodes, [OwnerKey])).
|
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) ->
|
%% @spec (Host, Node, From, JID) ->
|
||||||
%% {error, Reason::stanzaError()} |
|
%% {error, Reason::stanzaError()} |
|
||||||
@ -1407,7 +1344,6 @@ subscribe_node(Host, Node, From, JID) ->
|
|||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
{error, Error};
|
{error, Error};
|
||||||
{result, {Result, subscribed, send_last}} ->
|
{result, {Result, subscribed, send_last}} ->
|
||||||
%% TODO was send_last_published_item
|
|
||||||
send_all_items(Host, Node, Subscriber),
|
send_all_items(Host, Node, Subscriber),
|
||||||
case Result of
|
case Result of
|
||||||
default -> {result, Reply(subscribed)};
|
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])
|
node_call(Type, publish_item, [Host, Node, Publisher, Model, MaxItems, ItemId, Payload])
|
||||||
end
|
end
|
||||||
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 = [],
|
Reply = [],
|
||||||
case transaction(Host, Node, Action, sync_dirty) of
|
case transaction(Host, Node, Action, sync_dirty) of
|
||||||
{error, ?ERR_ITEM_NOT_FOUND} ->
|
{error, ?ERR_ITEM_NOT_FOUND} ->
|
||||||
@ -1741,7 +1677,7 @@ send_items(Host, Node, LJID, Number) ->
|
|||||||
[{xmlelement, "x", [{"xmlns", ?NS_PUBSUB_EVENT}],
|
[{xmlelement, "x", [{"xmlns", ?NS_PUBSUB_EVENT}],
|
||||||
[{xmlelement, "items", [{"node", node_to_string(Node)}],
|
[{xmlelement, "items", [{"node", node_to_string(Node)}],
|
||||||
ItemsEls}]}]},
|
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}
|
%% @spec (Host, JID, Plugins) -> {error, Reason} | {result, Response}
|
||||||
%% Host = host()
|
%% Host = host()
|
||||||
@ -2055,18 +1991,30 @@ node_to_string(Node) ->
|
|||||||
string_to_node(SNode) ->
|
string_to_node(SNode) ->
|
||||||
string:tokens(SNode, "/").
|
string:tokens(SNode, "/").
|
||||||
|
|
||||||
%% @spec (Host, JID, PresenceDelivery) -> boolean()
|
%% @spec (Host) -> jid()
|
||||||
%% Host = host()
|
%% 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()
|
%% PresenceDelivery = boolean()
|
||||||
%% @doc <p>Check if a notification must be delivered or not
|
%% @doc <p>Check if a notification must be delivered or not
|
||||||
to_be_delivered(_Host, _JID, false) ->
|
is_to_delivered(_, none, _) -> false;
|
||||||
% default is true
|
is_to_delivered(_, pending, _) -> false;
|
||||||
true;
|
is_to_delivered(_, _, false) -> true;
|
||||||
to_be_delivered(Host, JID, true) ->
|
is_to_delivered({User, Server, _}, _, true) ->
|
||||||
case mnesia:dirty_read(pubsub_presence, {Host, element(1, JID), element(2, JID)}) of
|
case mnesia:dirty_match_object({session, '_', '_', {User, Server}, '_', '_'}) of
|
||||||
[_] -> true;
|
[] -> false;
|
||||||
[] -> false
|
Ss ->
|
||||||
|
lists:foldl(fun({session, _, _, _, undefined, _}, Acc) -> Acc;
|
||||||
|
({session, _, _, _, _Priority, _}, _Acc) -> true
|
||||||
|
end, false, Ss)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%%%% broadcast functions
|
%%%%%% broadcast functions
|
||||||
@ -2094,22 +2042,19 @@ broadcast_publish_item(Host, Node, ItemId, _From, Payload) ->
|
|||||||
[{xmlelement, "items", [{"node", node_to_string(Node)}],
|
[{xmlelement, "items", [{"node", node_to_string(Node)}],
|
||||||
[{xmlelement, "item", ItemAttrs, Content}]}]}]},
|
[{xmlelement, "item", ItemAttrs, Content}]}]}]},
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(#pubsub_state{stateid = {JID, _},
|
fun(#pubsub_state{stateid = {LJID, _},
|
||||||
subscription = Subscription}) ->
|
subscription = Subscription}) ->
|
||||||
ToBeSent = to_be_delivered(Host, JID, PresenceDelivery),
|
case is_to_delivered(LJID, Subscription, PresenceDelivery) of
|
||||||
if
|
true ->
|
||||||
(Subscription /= none) and
|
|
||||||
(Subscription /= pending) and
|
|
||||||
ToBeSent ->
|
|
||||||
DestJIDs = case BroadcastAll of
|
DestJIDs = case BroadcastAll of
|
||||||
true -> ejabberd_sm:get_user_resources(element(1, JID), element(2, JID));
|
true -> ejabberd_sm:get_user_resources(element(1, LJID), element(2, LJID));
|
||||||
false -> [JID]
|
false -> [LJID]
|
||||||
end,
|
end,
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(DestJID) ->
|
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);
|
end, DestJIDs);
|
||||||
true ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
end, States),
|
end, States),
|
||||||
@ -2148,7 +2093,7 @@ broadcast_retract_item(Host, Node, ItemId, ForceNotify) ->
|
|||||||
subscription = Subscription}) ->
|
subscription = Subscription}) ->
|
||||||
if (Subscription /= none) and
|
if (Subscription /= none) and
|
||||||
(Subscription /= pending) ->
|
(Subscription /= pending) ->
|
||||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza};
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
@ -2181,7 +2126,7 @@ broadcast_purge_node(Host, Node) ->
|
|||||||
subscription = Subscription}) ->
|
subscription = Subscription}) ->
|
||||||
if (Subscription /= none) and
|
if (Subscription /= none) and
|
||||||
(Subscription /= pending) ->
|
(Subscription /= pending) ->
|
||||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza};
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
@ -2213,7 +2158,7 @@ broadcast_removed_node(Host, Removed) ->
|
|||||||
subscription = Subscription}) ->
|
subscription = Subscription}) ->
|
||||||
if (Subscription /= none) and
|
if (Subscription /= none) and
|
||||||
(Subscription /= pending) ->
|
(Subscription /= pending) ->
|
||||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza};
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
@ -2253,14 +2198,12 @@ broadcast_config_notification(Host, Node, Lang) ->
|
|||||||
[{xmlelement, "item", [{"id", "configuration"}],
|
[{xmlelement, "item", [{"id", "configuration"}],
|
||||||
Content}]}]}]},
|
Content}]}]}]},
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(#pubsub_state{stateid = {JID, _},
|
fun(#pubsub_state{stateid = {LJID, _},
|
||||||
subscription = Subscription}) ->
|
subscription = Subscription}) ->
|
||||||
ToBeSent = to_be_delivered(Host, JID, PresenceDelivery),
|
case is_to_delivered(LJID, Subscription, PresenceDelivery) of
|
||||||
if (Subscription /= none) and
|
|
||||||
(Subscription /= pending) and
|
|
||||||
ToBeSent ->
|
|
||||||
ejabberd_router:route(?PUBSUB_JID, jlib:make_jid(JID), Stanza);
|
|
||||||
true ->
|
true ->
|
||||||
|
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(LJID), Stanza};
|
||||||
|
false ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
end, States),
|
end, States),
|
||||||
@ -2298,11 +2241,10 @@ broadcast_config_notification(Host, Node, Lang) ->
|
|||||||
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]),
|
?DEBUG("looking for pid of ~p@~p/~p", [LUser, LServer, LResource]),
|
||||||
%% We need to know the resource, so we can ask for presence data.
|
%% 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
|
SenderResource = case LResource of
|
||||||
"" ->
|
"" ->
|
||||||
%% If we don't know the resource, just pick one.
|
%% If we don't know the resource, just pick one.
|
||||||
case SenderResources of
|
case ejabberd_sm:get_user_resources(LUser, LServer) of
|
||||||
[R|_] ->
|
[R|_] ->
|
||||||
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
|
case catch ejabberd_c2s:get_subscribed_and_online(C2SPid) of
|
||||||
ContactsWithCaps when is_list(ContactsWithCaps) ->
|
ContactsWithCaps when is_list(ContactsWithCaps) ->
|
||||||
?DEBUG("found contacts with caps: ~p", [ContactsWithCaps]),
|
?DEBUG("found contacts with caps: ~p", [ContactsWithCaps]),
|
||||||
LookingFor = Node ++ "+notify",
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({JID, Caps}) ->
|
fun({JID, Caps}) ->
|
||||||
case catch mod_caps:get_features(LServer, Caps) of
|
case is_caps_notify(LServer, Node, Caps) of
|
||||||
Features when is_list(Features) ->
|
|
||||||
case lists:member(LookingFor, Features) of
|
|
||||||
true ->
|
true ->
|
||||||
To = jlib:make_jid(JID),
|
To = jlib:make_jid(JID),
|
||||||
ejabberd_router:route(Sender, To, Stanza);
|
ejabberd_router ! {route, Sender, To, Stanza};
|
||||||
_ ->
|
false ->
|
||||||
ok
|
|
||||||
end;
|
|
||||||
_ ->
|
|
||||||
%% couldn't get entity capabilities.
|
|
||||||
%% nothing to do about that...
|
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
end, ContactsWithCaps);
|
end, ContactsWithCaps);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
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;
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
@ -2359,6 +2284,12 @@ broadcast_by_caps({LUser, LServer, LResource}, Node, _Type, Stanza) ->
|
|||||||
broadcast_by_caps(_, _, _, _) ->
|
broadcast_by_caps(_, _, _, _) ->
|
||||||
ok.
|
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
|
%%%%%%% Configuration handling
|
||||||
|
|
||||||
%%<p>There are several reasons why the default node configuration options request might fail:</p>
|
%%<p>There are several reasons why the default node configuration options request might fail:</p>
|
||||||
|
@ -188,7 +188,7 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
|
|||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
case Owner of
|
case Owner of
|
||||||
?PUBSUB_JID -> true;
|
{jid, "", _, "", "", _, ""} -> true;
|
||||||
_ -> false
|
_ -> false
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
%%% ====================================================================
|
%%% ====================================================================
|
||||||
%%% This software is copyright 2006, Process-one.
|
%%% This software is copyright 2007, Process-one.
|
||||||
%%%
|
%%%
|
||||||
%%% This file contains pubsub types definition.
|
%%% This file contains pubsub types definition.
|
||||||
%%% ====================================================================
|
%%% ====================================================================
|
||||||
|
|
||||||
%% -------------------------------
|
%% -------------------------------
|
||||||
%% Pubsub constants
|
%% Pubsub constants
|
||||||
-define(PUBSUB_JID, {jid, "", Host, "", "", Host, ""}).
|
|
||||||
-define(ERR_EXTENDED(E,C), mod_pubsub:extended_error(E,C)).
|
-define(ERR_EXTENDED(E,C), mod_pubsub:extended_error(E,C)).
|
||||||
|
|
||||||
%% this is currently a hard limit.
|
%% this is currently a hard limit.
|
||||||
|
Loading…
Reference in New Issue
Block a user