%%% This module uses version 1.10 of the specification as a base.
%%% Most of the specification is implemented.
%%% Code is derivated from the original pubsub v1.7, functions concerning config may be rewritten.
-%%% Code also inspired from the original PEP patch by Magnus Henoch <mange@freemail.hu>
+%%% Code also inspired from the original PEP patch by Magnus Henoch (mangeATfreemail.hu)
%%% TODO
%%% plugin: generate Reply (do not use broadcast atom anymore)
nodetree = NodeTree,
plugins = Plugins}}.
-%% @spec (Host, Opts) -> Plugins
+%% @spec (Host, ServerHost, Opts) -> Plugins
%% Host = mod_pubsub:host() Opts = [{Key,Value}]
%% ServerHost = host()
%% Key = atom()
%% @doc <p>Create new pubsub nodes</p>
%%<p>In addition to method-specific error conditions, there are several general reasons why the node creation request might fail:</p>
%%<ul>
-%%<li>The service does not support node creation.
-%%<li>Only entities that are registered with the service are allowed to create nodes but the requesting entity is not registered.
-%%<li>The requesting entity does not have sufficient privileges to create nodes.
-%%<li>The requested NodeID already exists.
-%%<li>The request did not include a NodeID and "instant nodes" are not supported.
+%%<li>The service does not support node creation.</li>
+%%<li>Only entities that are registered with the service are allowed to create nodes but the requesting entity is not registered.</li>
+%%<li>The requesting entity does not have sufficient privileges to create nodes.</li>
+%%<li>The requested NodeID already exists.</li>
+%%<li>The request did not include a NodeID and "instant nodes" are not supported.</li>
%%</ul>
%%<p>ote: node creation is a particular case, error return code is evaluated at many places:</p>
%%<ul>
-%%<li>iq_pubsub checks if service supports node creation (type exists)
-%%<li>create_node checks if instant nodes are supported
-%%<li>create_node asks node plugin if entity have sufficient privilege
-%%<li>nodetree create_node checks if nodeid already exists
-%%<li>node plugin create_node just sets default affiliation/subscription
+%%<li>iq_pubsub checks if service supports node creation (type exists)</li>
+%%<li>create_node checks if instant nodes are supported</li>
+%%<li>create_node asks node plugin if entity have sufficient privilege</li>
+%%<li>nodetree create_node checks if nodeid already exists</li>
+%%<li>node plugin create_node just sets default affiliation/subscription</li>
%%</ul>
create_node(Host, ServerHost, Node, Owner, Type) ->
create_node(Host, ServerHost, Node, Owner, Type, all, []).
%% @doc <p>Delete specified node and all childs.</p>
%%<p>There are several reasons why the node deletion request might fail:</p>
%%<ul>
-%%<li>The requesting entity does not have sufficient privileges to delete the node.
-%%<li>The node is the root collection node, which cannot be deleted.
-%%<li>The specified node does not exist.
+%%<li>The requesting entity does not have sufficient privileges to delete the node.</li>
+%%<li>The node is the root collection node, which cannot be deleted.</li>
+%%<li>The specified node does not exist.</li>
%%</ul>
delete_node(_Host, [], _Owner) ->
%% Node is the root
%% Node = pubsubNode()
%% From = jid()
%% JID = jid()
-%% @doc <p>Accepts or rejects subcription requests on a PubSub node.</p>
%% @see node_default:subscribe_node/5
+%% @doc <p>Accepts or rejects subcription requests on a PubSub node.</p>
%%<p>There are several reasons why the subscription request might fail:</p>
%%<ul>
-%%<li>The bare JID portions of the JIDs do not match.
-%%<li>The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.
-%%<li>The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.
-%%<li>The node has an access model of "whitelist" and the requesting entity is not on the whitelist.
-%%<li>The service requires payment for subscriptions to the node.
-%%<li>The requesting entity is anonymous and the service does not allow anonymous entities to subscribe.
-%%<li>The requesting entity has a pending subscription.
-%%<li>The requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast).
-%%<li>The node does not support subscriptions.
-%%<li>The node does not exist.
+%%<li>The bare JID portions of the JIDs do not match.</li>
+%%<li>The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.</li>
+%%<li>The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.</li>
+%%<li>The node has an access model of "whitelist" and the requesting entity is not on the whitelist.</li>
+%%<li>The service requires payment for subscriptions to the node.</li>
+%%<li>The requesting entity is anonymous and the service does not allow anonymous entities to subscribe.</li>
+%%<li>The requesting entity has a pending subscription.</li>
+%%<li>The requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast).</li>
+%%<li>The node does not support subscriptions.</li>
+%%<li>The node does not exist.</li>
%%</ul>
subscribe_node(Host, Node, From, JID) ->
Subscriber = case jlib:string_to_jid(JID) of
{result, Result}
end.
-%% @spec (Host, Noce, From, JID) -> {error, Reason} | {result, []}
+%% @spec (Host, Noce, From, JID, SubId) -> {error, Reason} | {result, []}
%% Host = host()
%% Node = pubsubNode()
%% From = jid()
%% @doc <p>Unsubscribe <tt>JID</tt> from the <tt>Node</tt>.</p>
%%<p>There are several reasons why the unsubscribe request might fail:</p>
%%<ul>
-%%<li>The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.
-%%<li>The request does not specify an existing subscriber.
-%%<li>The requesting entity does not have sufficient privileges to unsubscribe the specified JID.
-%%<li>The node does not exist.
-%%<li>The request specifies a subscription ID that is not valid or current.
-%%</il>
+%%<li>The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.</li>
+%%<li>The request does not specify an existing subscriber.</li>
+%%<li>The requesting entity does not have sufficient privileges to unsubscribe the specified JID.</li>
+%%<li>The node does not exist.</li>
+%%<li>The request specifies a subscription ID that is not valid or current.</li>
+%%</ul>
unsubscribe_node(Host, Node, From, JID, SubId) ->
Subscriber = case jlib:string_to_jid(JID) of
error -> {"", "", ""};
%% <p>The permission to publish an item must be verified by the plugin implementation.</p>
%%<p>There are several reasons why the publish request might fail:</p>
%%<ul>
-%%<li>The requesting entity does not have sufficient privileges to publish.
-%%<li>The node does not support item publication.
-%%<li>The node does not exist.
-%%<li>The payload size exceeds a service-defined limit.
-%%<li>The item contains more than one payload element or the namespace of the root payload element does not match the configured namespace for the node.
-%%<li>The request does not match the node configuration.
+%%<li>The requesting entity does not have sufficient privileges to publish.</li>
+%%<li>The node does not support item publication.</li>
+%%<li>The node does not exist.</li>
+%%<li>The payload size exceeds a service-defined limit.</li>
+%%<li>The item contains more than one payload element or the namespace of the root payload element does not match the configured namespace for the node.</li>
+%%<li>The request does not match the node configuration.</li>
%%</ul>
publish_item(Host, ServerHost, Node, Publisher, "", Payload) ->
%% if publisher does not specify an ItemId, the service MUST generate the ItemId
%% <p>The permission to delete an item must be verified by the plugin implementation.</p>
%%<p>There are several reasons why the item retraction request might fail:</p>
%%<ul>
-%%<li>The publisher does not have sufficient privileges to delete the requested item.
-%%<li>The node or item does not exist.
-%%<li>The request does not specify a node.
-%%<li>The request does not include an <item/> element or the <item/> element does not specify an ItemId.
-%%<li>The node does not support persistent items.
-%%<li>The service does not support the deletion of items.
+%%<li>The publisher does not have sufficient privileges to delete the requested item.</li>
+%%<li>The node or item does not exist.</li>
+%%<li>The request does not specify a node.</li>
+%%<li>The request does not include an <item/> element or the <item/> element does not specify an ItemId.</li>
+%%<li>The node does not support persistent items.</li>
+%%<li>The service does not support the deletion of items.</li>
%%</ul>
delete_item(Host, Node, Publisher, ItemId) ->
delete_item(Host, Node, Publisher, ItemId, false).
%% @doc <p>Delete all items of specified node owned by JID.</p>
%%<p>There are several reasons why the node purge request might fail:</p>
%%<ul>
-%%<li>The node or service does not support node purging.
-%%<li>The requesting entity does not have sufficient privileges to purge the node.
-%%<li>The node is not configured to persist items.
-%%<li>The specified node does not exist.
+%%<li>The node or service does not support node purging.</li>
+%%<li>The requesting entity does not have sufficient privileges to purge the node.</li>
+%%<li>The node is not configured to persist items.</li>
+%%<li>The specified node does not exist.</li>
%%</ul>
purge_node(Host, Node, Owner) ->
Action = fun(#pubsub_node{type = Type, options = Options}) ->
%% @spec (Host, Node, LJID) -> any()
%% Host = host()
%% Node = pubsubNode()
-%% LJID = {U,S,""}
+%% LJID = {U, S, []}
%% @doc <p>Resend the items of a node to the user.</p>
send_all_items(Host, Node, LJID) ->
send_items(Host, Node, LJID, all).
end.
-% @spec (OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, _}, AllowedGroups)
+%% @spec (OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, SubscriberResource}, AllowedGroups)
+%% -> {PresenceSubscription, RosterGroup}
get_roster_info(OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, _}, AllowedGroups) ->
{Subscription, Groups} =
ejabberd_hooks:run_fold(
_ -> {jid, "", Host, "", "", Host, ""}
end.
-%% @spec (LJID, PresenceDelivery) -> boolean()
+%% @spec (LJID, Subscription, PresenceDelivery) -> boolean()
%% LJID = jid()
%% Subscription = atom()
%% PresenceDelivery = boolean()
-%% @doc <p>Check if a notification must be delivered or not
+%% @doc <p>Check if a notification must be delivered or not.</p>
is_to_delivered(_, none, _) -> false;
is_to_delivered(_, pending, _) -> false;
is_to_delivered(_, _, false) -> true;
%%<p>There are several reasons why the default node configuration options request might fail:</p>
%%<ul>
-%%<li>The service does not support node configuration.
-%%<li>The service does not support retrieval of default node configuration.
+%%<li>The service does not support node configuration.</li>
+%%<li>The service does not support retrieval of default node configuration.</li>
%%</ul>
get_configure(Host, Node, From, Lang) ->
Action =
%%<p>There are several reasons why the node configuration request might fail:</p>
%%<ul>
-%%<li>The service does not support node configuration.
-%%<li>The requesting entity does not have sufficient privileges to configure the node.
-%%<li>The request did not specify a node.
-%%<li>The node has no configuration options.
-%%<li>The specified node does not exist.
+%%<li>The service does not support node configuration.</li>
+%%<li>The requesting entity does not have sufficient privileges to configure the node.</li>
+%%<li>The request did not specify a node.</li>
+%%<li>The node has no configuration options.</li>
+%%<li>The specified node does not exist.</li>
%%</ul>
set_configure(Host, Node, From, Els, Lang) ->
case xml:remove_cdata(Els) of
%% API definition
%% ================
-%% @spec (Host) -> any()
+%% @spec (Host, ServerHost, Opts) -> any()
%% Host = mod_pubsub:host()
-%% ServerHost = host()
+%% ServerHost = mod_pubsub:host()
%% Opts = list()
%% @doc <p>Called during pubsub modules initialisation. Any pubsub plugin must
%% implement this function. It can return anything.</p>
end,
ok.
-%% @spec (Host) -> any()
+%% @spec (Host, ServerHost) -> any()
%% Host = mod_pubsub:host()
+%% ServerHost = host()
%% @doc <p>Called during pubsub modules termination. Any pubsub plugin must
%% implement this function. It can return anything.</p>
terminate(_Host, _ServerHost) ->
"subscription-notifications"
].
-%% @spec (Host, Node, Owner, Access) -> bool()
+%% @spec (Host, ServerHost, Node, ParentNode, Owner, Access) -> bool()
%% Host = mod_pubsub:host()
%% ServerHost = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode()
+%% ParentNode = mod_pubsub:pubsubNode()
%% Owner = mod_pubsub:jid()
%% Access = all | atom()
%% @doc Checks if the current user has the permission to create the requested node
end, Removed),
{result, {default, broadcast, Removed}}.
-%% @spec (Host, Node, Sender, Subscriber, AccessModel, SendLast) ->
+%% @spec (Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
%% {error, Reason} | {result, Result}
%% @doc <p>Accepts or rejects subcription requests on a PubSub node.</p>
%% <p>The mechanism works as follow:
end
end.
-%% @spec (TODO)
+%% @spec (Host, Node, Owner) ->
+%% {error, Reason::stanzaError()} |
+%% {result, {default, broadcast}}
+%% Host = mod_pubsub:host()
+%% Node = mod_pubsub:pubsubNode()
+%% Owner = mod_pubsub:jid()
purge_node(Host, Node, Owner) ->
OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
case get_state(Host, Node, OwnerKey) of
set_state(Record),
ok.
-%% @spec (Host) -> [{Node,Subscription}]
+%% @spec (Host, Owner) -> [{Node,Subscription}]
%% Host = host()
-%% JID = mod_pubsub:jid()
+%% Owner = mod_pubsub:jid()
+%% Node = mod_pubsub:pubsubNode()
%% @doc <p>Return the current subscriptions for the given user</p>
%% <p>The default module reads subscriptions in the main Mnesia
%% <tt>pubsub_state</tt> table. If a plugin stores its data in the same
{error, ?ERR_ITEM_NOT_FOUND}
end.
-%% @spec (State) -> ok | {error, ?ERR_INTERNAL_SERVER_ERROR}
+%% @spec (State) -> ok | {error, Reason::stanzaError()}
%% State = mod_pubsub:pubsubStates()
%% @doc <p>Write a state into database.</p>
set_state(State) when is_record(State, pubsub_state) ->
{error, ?ERR_ITEM_NOT_FOUND}
end.
-%% @spec (Item) -> ok | {error, ?ERR_INTERNAL_SERVER_ERROR}
+%% @spec (Item) -> ok | {error, Reason::stanzaError()}
%% Item = mod_pubsub:pubsubItems()
%% @doc <p>Write a state into database.</p>
set_item(Item) when is_record(Item, pubsub_item) ->