diff options
author | Christophe Romain <christophe.romain@process-one.net> | 2008-07-03 09:56:31 +0000 |
---|---|---|
committer | Christophe Romain <christophe.romain@process-one.net> | 2008-07-03 09:56:31 +0000 |
commit | 35d25d3420c267b52c33b6d46956c8e05920b17e (patch) | |
tree | ce69b2d9b5bf5e62a2462fd5133cd9fad4481144 /src/mod_pubsub/mod_pubsub.erl | |
parent | * src/ejabberd_ctl.erl: Web Admin and Ad-hoc admin: dump only (diff) |
PubSub improvements, and solves (EJAB-453) (EJAB-608)
SVN Revision: 1408
Diffstat (limited to 'src/mod_pubsub/mod_pubsub.erl')
-rw-r--r-- | src/mod_pubsub/mod_pubsub.erl | 102 |
1 files changed, 75 insertions, 27 deletions
diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index 349c7ad4f..92f5cf959 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -30,16 +30,17 @@ %%% %%% @reference See <a href="http://www.xmpp.org/extensions/xep-0060.html">XEP-0060: Pubsub</a> for %%% the latest version of the PubSub specification. -%%% This module uses version 1.10 of the specification as a base. +%%% This module uses version 1.11 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 (mangeATfreemail.hu) +%%% Functions concerning configuration should be rewritten. +%%% Code is derivated from the original pubsub v1.7, by Alexey Shchepin <alexey@process-one.net> %%% TODO %%% plugin: generate Reply (do not use broadcast atom anymore) -module(mod_pubsub). --version('1.10-01'). +-author('christophe.romain@process-one.net'). +-version('1.11-01'). -behaviour(gen_server). -behaviour(gen_mod). @@ -912,7 +913,17 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, _Lang, Access, Plugins) -> unsubscribe_node(Host, Node, From, JID, SubId); {get, "items"} -> MaxItems = xml:get_attr_s("max_items", Attrs), - get_items(Host, Node, From, MaxItems); + SubId = xml:get_attr_s("subid", Attrs), + ItemIDs = lists:foldl(fun + ({xmlelement, "item", ItemAttrs, _}, Acc) -> + case xml:get_attr_s("id", ItemAttrs) of + "" -> Acc; + ItemID -> ItemID + end; + (_, Acc) -> + Acc + end, [], xml:remove_cdata(Els)), + get_items(Host, Node, From, SubId, MaxItems, ItemIDs); {get, "subscriptions"} -> get_subscriptions(Host, From, Plugins); {get, "affiliations"} -> @@ -1436,7 +1447,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> Action = fun(#pubsub_node{options = Options, type = Type}) -> Features = features(Type), PublishFeature = lists:member("publish", Features), - Model = get_option(Options, publish_model), + PublishModel = get_option(Options, publish_model), MaxItems = max_items(Options), PayloadSize = size(term_to_binary(Payload)), PayloadMaxSize = get_option(Options, max_payload_size), @@ -1459,7 +1470,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> %% % Publisher attempts to publish to transient notification node with item %% {error, extended_error(?ERR_BAD_REQUEST, "item-forbidden")}; true -> - node_call(Type, publish_item, [Host, Node, Publisher, Model, MaxItems, ItemId, Payload]) + node_call(Type, publish_item, [Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload]) end end, %%ejabberd_hooks:run(pubsub_publish_item, Host, [Host, Node, JID, service_jid(Host), ItemId, Payload]), @@ -1622,7 +1633,7 @@ purge_node(Host, Node, Owner) -> %% <p>The permission are not checked in this function.</p> %% @todo We probably need to check that the user doing the query has the right %% to read the items. -get_items(Host, Node, _JID, SMaxItems) -> +get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> MaxItems = if SMaxItems == "" -> ?MAXITEMS; @@ -1636,24 +1647,60 @@ get_items(Host, Node, _JID, SMaxItems) -> {error, Error} -> {error, Error}; _ -> - case get_items(Host, Node) of - [] -> - {error, ?ERR_ITEM_NOT_FOUND}; - Items -> + Action = fun(#pubsub_node{options = Options, type = Type}) -> + Features = features(Type), + RetreiveFeature = lists:member("retrieve-items", Features), + PersistentFeature = lists:member("persistent-items", Features), + AccessModel = get_option(Options, access_model), + AllowedGroups = get_option(Options, roster_groups_allowed), + {PresenceSubscription, RosterGroup} = + case Host of + {OUser, OServer, _} -> + get_roster_info(OUser, OServer, + jlib:jid_tolower(From), AllowedGroups); + _ -> + {true, true} + end, + if + not RetreiveFeature -> + %% Item Retrieval Not Supported + {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "retrieve-items")}; + not PersistentFeature -> + %% Persistent Items Not Supported + {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "persistent-items")}; + true -> + node_call(Type, get_items, + [Host, Node, From, + AccessModel, PresenceSubscription, RosterGroup, + SubId]) + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {error, Reason} -> + {error, Reason}; + {result, Items} -> + SendItems = case ItemIDs of + [] -> + Items; + _ -> + lists:filter(fun(Item) -> + lists:member(Item, ItemIDs) + end, Items) + end, %% Generate the XML response (Item list), limiting the %% number of items sent to MaxItems: ItemsEls = lists:map( - fun(#pubsub_item{itemid = {ItemId, _}, - payload = Payload}) -> - ItemAttrs = case ItemId of - "" -> []; - _ -> [{"id", ItemId}] - end, - {xmlelement, "item", ItemAttrs, Payload} - end, lists:sublist(Items, MaxItems)), + fun(#pubsub_item{itemid = {ItemId, _}, + payload = Payload}) -> + ItemAttrs = case ItemId of + "" -> []; + _ -> [{"id", ItemId}] + end, + {xmlelement, "item", ItemAttrs, Payload} + end, lists:sublist(SendItems, MaxItems)), {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], - [{xmlelement, "items", [{"node", node_to_string(Node)}], - ItemsEls}]}]} + [{xmlelement, "items", [{"node", node_to_string(Node)}], + ItemsEls}]}]} end end. @@ -1809,7 +1856,7 @@ set_affiliations(Host, Node, From, EntitiesEls) -> end, Entities), {result, []}; _ -> - {error, ?ERR_NOT_ALLOWED} + {error, ?ERR_FORBIDDEN} end end, transaction(Host, Node, Action, sync_dirty) @@ -1870,7 +1917,7 @@ get_subscriptions(Host, Node, JID) -> %% Service does not support manage subscriptions {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "manage-affiliations")}; Affiliation /= {result, owner} -> - % Entity is not an owner + %% Entity is not an owner {error, ?ERR_FORBIDDEN}; true -> node_call(Type, get_node_subscriptions, [Host, Node]) @@ -1938,7 +1985,7 @@ set_subscriptions(Host, Node, From, EntitiesEls) -> end, Entities), {result, []}; _ -> - {error, ?ERR_NOT_ALLOWED} + {error, ?ERR_FORBIDDEN} end end, transaction(Host, Node, Action, sync_dirty) @@ -2438,6 +2485,7 @@ get_configure_xfields(_Type, Options, Lang, _Owners) -> ?BOOL_CONFIG_FIELD("Notify subscribers when the node is deleted", notify_delete), ?BOOL_CONFIG_FIELD("Notify subscribers when items are removed from the node", notify_retract), ?BOOL_CONFIG_FIELD("Persist items to storage", persist_items), + ?STRING_CONFIG_FIELD("A friendly name for the node", title), ?INTEGER_CONFIG_FIELD("Max # of items to persist", max_items), ?BOOL_CONFIG_FIELD("Whether to allow subscriptions", subscribe), ?ALIST_CONFIG_FIELD("Specify the access model", access_model, @@ -2605,7 +2653,7 @@ features() -> [ %"access-authorize", % OPTIONAL "access-open", % OPTIONAL this relates to access_model option in node_default - %"access-presence", % OPTIONAL + "access-presence", % OPTIONAL this relates to access_model option in node_pep %"access-roster", % OPTIONAL %"access-whitelist", % OPTIONAL % see plugin "auto-create", % OPTIONAL @@ -2619,7 +2667,7 @@ features() -> % see plugin "filtered-notifications", % RECOMMENDED %TODO "get-pending", % OPTIONAL % see plugin "instant-nodes", % RECOMMENDED - %TODO "item-ids", % RECOMMENDED + "item-ids", % RECOMMENDED "last-published", % RECOMMENDED %TODO "cache-last-item", %TODO "leased-subscription", % OPTIONAL |