]> granicus.if.org Git - ejabberd/commitdiff
Improve pubsub code
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 8 Sep 2016 12:49:27 +0000 (15:49 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 8 Sep 2016 12:49:27 +0000 (15:49 +0300)
14 files changed:
include/xmpp_codec.hrl
src/adhoc.erl [deleted file]
src/mod_pubsub.erl
src/node_dag.erl
src/node_dispatch.erl
src/node_flat.erl
src/node_flat_sql.erl
src/nodetree_dag.erl
src/nodetree_tree.erl
src/nodetree_tree_sql.erl
src/pubsub_db_sql.erl
src/pubsub_subscription.erl
src/pubsub_subscription_sql.erl
tools/xmpp_codec.spec

index 7eabdab8f002df1d40b298c7e590fd904ec00c3b..d2acf316c8ca63e9d6a7dc42f3302fdf681a8ba3 100644 (file)
                         'presence-subscription-required' | 'subid-required' |
                         'too-many-subscriptions' | 'unsupported' |
                         'unsupported-access-model'.
--type ps_error_feature() :: 'access-authorize' | 'access-open' |
-                           'access-presence' | 'access-roster' |
-                           'access-whitelist' | 'auto-create' |
-                           'auto-subscribe' | 'collections' | 'config-node' |
-                           'create-and-configure' | 'create-nodes' |
-                           'delete-items' | 'delete-nodes' |
-                           'filtered-notifications' | 'get-pending' |
-                           'instant-nodes' | 'item-ids' | 'last-published' |
-                           'leased-subscription' | 'manage-subscriptions' |
-                           'member-affiliation' | 'meta-data' |
-                           'modify-affiliations' | 'multi-collection' |
-                           'multi-subscribe' | 'outcast-affiliation' |
-                           'persistent-items' | 'presence-notifications' |
-                           'presence-subscribe' | 'publish' |
-                           'publish-options' | 'publish-only-affiliation' |
-                           'publisher-affiliation' | 'purge-nodes' |
-                           'retract-items' | 'retrieve-affiliations' |
-                           'retrieve-default' | 'retrieve-items' |
-                           'retrieve-subscriptions' | 'subscribe' |
-                           'subscription-options' | 'subscription-notifications'.
--record(ps_error, {type :: ps_error_type(), feature :: ps_error_feature()}).
+-type ps_feature() :: 'access-authorize' | 'access-open' |
+                     'access-presence' | 'access-roster' |
+                     'access-whitelist' | 'auto-create' |
+                     'auto-subscribe' | 'collections' | 'config-node' |
+                     'create-and-configure' | 'create-nodes' |
+                     'delete-items' | 'delete-nodes' |
+                     'filtered-notifications' | 'get-pending' |
+                     'instant-nodes' | 'item-ids' | 'last-published' |
+                     'leased-subscription' | 'manage-subscriptions' |
+                     'member-affiliation' | 'meta-data' |
+                     'modify-affiliations' | 'multi-collection' |
+                     'multi-subscribe' | 'outcast-affiliation' |
+                     'persistent-items' | 'presence-notifications' |
+                     'presence-subscribe' | 'publish' |
+                     'publish-options' | 'publish-only-affiliation' |
+                     'publisher-affiliation' | 'purge-nodes' |
+                     'retract-items' | 'retrieve-affiliations' |
+                     'retrieve-default' | 'retrieve-items' |
+                     'retrieve-subscriptions' | 'subscribe' |
+                     'subscription-options' | 'subscription-notifications'.
+-record(ps_error, {type :: ps_error_type(), feature :: ps_feature()}).
 -type ps_error() :: #ps_error{}.
 
 -record(chatstate, {type :: active | composing | gone | inactive | paused}).
diff --git a/src/adhoc.erl b/src/adhoc.erl
deleted file mode 100644 (file)
index 6970584..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File    : adhoc.erl
-%%% Author  : Magnus Henoch <henoch@dtek.chalmers.se>
-%%% Purpose : Provide helper functions for ad-hoc commands (XEP-0050)
-%%% Created : 31 Oct 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2016   ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License along
-%%% with this program; if not, write to the Free Software Foundation, Inc.,
-%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-%%%
-%%%----------------------------------------------------------------------
-
--module(adhoc).
-
--author('henoch@dtek.chalmers.se').
-
--export([
-    parse_request/1,
-    produce_response/2,
-    produce_response/1
-]).
-
--include("ejabberd.hrl").
--include("logger.hrl").
--include("jlib.hrl").
--include("adhoc.hrl").
-
-%% Parse an ad-hoc request.  Return either an adhoc_request record or
-%% an {error, ErrorType} tuple.
-%%
--spec parse_request(IQ :: iq_request()) -> adhoc_response() | {error, _}.
-
-parse_request(#iq{type = set, lang = Lang, sub_el = SubEl, xmlns = ?NS_COMMANDS}) ->
-    ?DEBUG("entering parse_request...", []),
-    Node = fxml:get_tag_attr_s(<<"node">>, SubEl),
-    SessionID = fxml:get_tag_attr_s(<<"sessionid">>, SubEl),
-    Action = fxml:get_tag_attr_s(<<"action">>, SubEl),
-    XData = find_xdata_el(SubEl),
-    #xmlel{children = AllEls} = SubEl,
-    Others = case XData of
-        false -> AllEls;
-        _     -> lists:delete(XData, AllEls)
-    end,
-    #adhoc_request{
-        lang      = Lang,
-        node      = Node,
-        sessionid = SessionID,
-        action    = Action,
-        xdata     = XData,
-        others    = Others
-    };
-parse_request(#iq{lang = Lang}) ->
-    Text = <<"Failed to parse ad-hoc command request">>,
-    {error, ?ERRT_BAD_REQUEST(Lang, Text)}.
-
-%% Borrowed from mod_vcard.erl
-find_xdata_el(#xmlel{children = SubEls}) ->
-    find_xdata_el1(SubEls).
-
-find_xdata_el1([]) -> false;
-find_xdata_el1([El | Els]) when is_record(El, xmlel) ->
-    case fxml:get_tag_attr_s(<<"xmlns">>, El) of
-        ?NS_XDATA -> El;
-        _         -> find_xdata_el1(Els)
-    end;
-find_xdata_el1([_ | Els]) -> find_xdata_el1(Els).
-
-%% Produce a <command/> node to use as response from an adhoc_response
-%% record, filling in values for language, node and session id from
-%% the request.
-%%
--spec produce_response(Adhoc_Request :: adhoc_request(),
-                      Adhoc_Response :: adhoc_response()) ->
-                             Xmlel::xmlel().
-
-%% Produce a <command/> node to use as response from an adhoc_response
-%% record.
-produce_response(#adhoc_request{lang = Lang, node = Node, sessionid = SessionID},
-  Adhoc_Response) ->
-    produce_response(Adhoc_Response#adhoc_response{
-        lang = Lang, node = Node, sessionid = SessionID
-    }).
-
-%%
--spec produce_response(Adhoc_Response::adhoc_response()) -> Xmlel::xmlel().
-
-produce_response(
-  #adhoc_response{
-   %lang          = _Lang,
-    node          = Node,
-    sessionid     = ProvidedSessionID,
-    status        = Status,
-    defaultaction = DefaultAction,
-    actions       = Actions,
-    notes         = Notes,
-    elements      = Elements
-  }) ->
-    SessionID = if is_binary(ProvidedSessionID),
-        ProvidedSessionID /= <<"">> -> ProvidedSessionID;
-        true                        -> jlib:now_to_utc_string(p1_time_compat:timestamp())
-    end,
-    case Actions of
-        [] ->
-            ActionsEls = [];
-        _ ->
-            case DefaultAction of
-                <<"">> -> ActionsElAttrs = [];
-                _      -> ActionsElAttrs = [{<<"execute">>, DefaultAction}]
-            end,
-            ActionsEls = [
-                #xmlel{
-                    name = <<"actions">>,
-                    attrs = ActionsElAttrs,
-                    children = [
-                        #xmlel{name = Action, attrs = [], children = []}
-                            || Action <- Actions]
-                }
-            ]
-    end,
-    NotesEls = lists:map(fun({Type, Text}) ->
-        #xmlel{
-            name     = <<"note">>,
-            attrs    = [{<<"type">>, Type}],
-            children = [{xmlcdata, Text}]
-        }
-    end, Notes),
-    #xmlel{
-        name     = <<"command">>,
-        attrs    = [
-            {<<"xmlns">>,     ?NS_COMMANDS},
-            {<<"sessionid">>, SessionID},
-            {<<"node">>,      Node},
-            {<<"status">>,    iolist_to_binary(atom_to_list(Status))}
-        ],
-        children = ActionsEls ++ NotesEls ++ Elements
-    }.
index c84fb5fe88523f64a81bca6c734e3eb2a59794c2..a7a0e2d88fdaca16d9980dc0cb6258a4cb8ee6b4 100644 (file)
@@ -41,8 +41,6 @@
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
-%%-include("adhoc.hrl").
-%%-include("jlib.hrl").
 -include("xmpp.hrl").
 -include("pubsub.hrl").
 
@@ -1199,11 +1197,14 @@ iq_get_vcard(Lang) ->
 iq_pubsub(Host, Access, #iq{from = From, type = IQType, lang = Lang,
                            sub_els = [SubEl]}) ->
     case {IQType, SubEl} of
-       {set, #pubsub{create = Node, configure = {_, XData},
+       {set, #pubsub{create = Node, configure = Configure,
                      _ = undefined}} when is_binary(Node) ->
            ServerHost = serverhost(Host),
            Plugins = config(ServerHost, plugins),
-           Config = get_xdata_fields(XData),
+           Config = case Configure of
+                        {_, XData} -> get_xdata_fields(XData);
+                        undefined -> []
+                    end,
            Type = hd(Plugins),
            create_node(Host, ServerHost, Node, From, Type, Access, Config);
        {set, #pubsub{publish = #ps_publish{node = Node, items = Items},
@@ -1223,7 +1224,12 @@ iq_pubsub(Host, Access, #iq{from = From, type = IQType, lang = Lang,
                      _ = undefined}} ->
            case Items of
                [#ps_item{id = ItemId}] ->
-                   delete_item(Host, Node, From, ItemId, Notify);
+                   if ItemId /= <<>> ->
+                           delete_item(Host, Node, From, ItemId, Notify);
+                      true ->
+                           {error, extended_error(xmpp:err_bad_request(),
+                                                  err_item_required())}
+                   end;
                [] ->
                    {error, extended_error(xmpp:err_bad_request(), err_item_required())};
                _ ->
@@ -1259,11 +1265,14 @@ iq_pubsub(Host, Access, #iq{from = From, type = IQType, lang = Lang,
                                            jid = JID, xdata = XData},
                      _ = undefined}} ->
            set_options(Host, Node, JID, SubId, get_xdata_fields(XData));
+       {set, #pubsub{}} ->
+           {error, xmpp:err_bad_request()};
        _ ->
            {error, xmpp:err_feature_not_implemented()}
     end.
 
--spec iq_pubsub_owner(binary() | ljid(), iq()) -> {result, pubsub()} | {error, error()}.
+-spec iq_pubsub_owner(binary() | ljid(), iq()) -> {result, pubsub_owner() | undefined} |
+                                                 {error, error()}.
 iq_pubsub_owner(Host, #iq{type = IQType, from = From,
                          lang = Lang, sub_els = [SubEl]}) ->
     case {IQType, SubEl} of
@@ -1275,7 +1284,7 @@ iq_pubsub_owner(Host, #iq{type = IQType, from = From,
                undefined ->
                    {error, xmpp:err_bad_request(<<"No data form found">>, Lang)};
                #xdata{type = cancel} ->
-                   {result, #pubsub{}};
+                   {result, #pubsub_owner{}};
                #xdata{type = submit} ->
                    Config = get_xdata_fields(XData),
                    set_configure(Host, Node, From, Config, Lang);
@@ -1684,7 +1693,7 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
 %%<li>The node is the root collection node, which cannot be deleted.</li>
 %%<li>The specified node does not exist.</li>
 %%</ul>
--spec delete_node(host(), binary(), jid()) -> {result, pubsub()} | {error, error()}.
+-spec delete_node(host(), binary(), jid()) -> {result, pubsub_owner()} | {error, error()}.
 delete_node(_Host, <<>>, _Owner) ->
     {error, xmpp:err_not_allowed(<<"No node specified">>, ?MYLANG)};
 delete_node(Host, Node, Owner) ->
@@ -1701,7 +1710,7 @@ delete_node(Host, Node, Owner) ->
                    {error, xmpp:err_forbidden(<<"Owner privileges required">>, ?MYLANG)}
            end
     end,
-    Reply = [],
+    Reply = undefined,
     ServerHost = serverhost(Host),
     case transaction(Host, Node, Action, transaction) of
        {result, {_, {SubsByDepth, {Result, broadcast, Removed}}}} ->
@@ -2566,8 +2575,8 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
            Error
     end.
 
--spec get_subscriptions(binary(), binary(), jid()) -> {result, pubsub()} |
-                                                     {error, error()}.
+-spec get_subscriptions(host(), binary(), jid()) -> {result, pubsub_owner()} |
+                                                   {error, error()}.
 get_subscriptions(Host, Node, JID) ->
     Action = fun (#pubsub_node{type = Type, id = Nidx}) ->
            Features = plugin_features(Host, Type),
@@ -2595,7 +2604,7 @@ get_subscriptions(Host, Node, JID) ->
                        ({AJID, Sub, SubId}) ->
                          [#ps_subscription{jid = AJID, type = Sub, subid = SubId}]
                  end, Subs),
-           {result, #pubsub{subscriptions = {Node, Entities}}};
+           {result, #pubsub_owner{subscriptions = {Node, Entities}}};
        Error ->
            Error
     end.
@@ -2623,6 +2632,8 @@ get_subscriptions_for_send_last(Host, PType, sql, JID, LJID, BJID) ->
 get_subscriptions_for_send_last(_Host, _PType, _, _JID, _LJID, _BJID) ->
     [].
 
+-spec set_subscriptions(host(), binary(), jid(), [ps_subscription()]) ->
+                              {result, undefined} | {error, error()}.
 set_subscriptions(Host, Node, From, Entities) ->
     Owner = jid:tolower(jid:remove_resource(From)),
     Notify = fun(#ps_subscription{jid = JID, type = Sub}) ->
@@ -3152,7 +3163,7 @@ user_resource(_, _, Resource) ->
 
 %%%%%%% Configuration handling
 -spec get_configure(host(), binary(), binary(), jid(),
-                   binary()) -> {error, error()} | {result, pubsub()}.
+                   binary()) -> {error, error()} | {result, pubsub_owner()}.
 get_configure(Host, ServerHost, Node, From, Lang) ->
     Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx}) ->
            case node_call(Host, Type, get_affiliation, [Nidx, From]) of
@@ -3171,7 +3182,7 @@ get_configure(Host, ServerHost, Node, From, Lang) ->
        Other -> Other
     end.
 
--spec get_default(host(), binary(), jid(), binary()) -> {result, pubsub()}.
+-spec get_default(host(), binary(), jid(), binary()) -> {result, pubsub_owner()}.
 get_default(Host, Node, _From, Lang) ->
     Type = select_type(Host, Host, Node),
     Options = node_options(Host, Type),
@@ -3371,6 +3382,8 @@ get_configure_xfields(_Type, Options, Lang, Groups) ->
 %%</ul>
 -spec set_configure(host(), binary(), jid(), [{binary(), [binary()]}],
                    binary()) -> {result, undefined} | {error, error()}.
+set_configure(_Host, <<>>, _From, _Config, _Lang) ->
+    {error, extended_error(xmpp:err_bad_request(), err_nodeid_required())};
 set_configure(Host, Node, From, Config, Lang) ->
     Action =
        fun(#pubsub_node{options = Options, type = Type, id = Nidx} = N) ->
@@ -3664,26 +3677,28 @@ select_type(ServerHost, Host, Node, Type) ->
 select_type(ServerHost, Host, Node) ->
     select_type(ServerHost, Host, Node, hd(plugins(Host))).
 
+-spec feature(binary()) -> binary().
 feature(<<"rsm">>) -> ?NS_RSM;
 feature(Feature) -> <<(?NS_PUBSUB)/binary, "#", Feature/binary>>.
 
+-spec features() -> [binary()].
 features() ->
     [% see plugin "access-authorize",   % OPTIONAL
-       <<"access-open">>,   % OPTIONAL this relates to access_model option in node_hometree
-       <<"access-presence">>,   % OPTIONAL this relates to access_model option in node_pep
-       <<"access-whitelist">>,   % OPTIONAL
-       <<"collections">>,   % RECOMMENDED
-       <<"config-node">>,   % RECOMMENDED
-       <<"create-and-configure">>,   % RECOMMENDED
-       <<"item-ids">>,   % RECOMMENDED
-       <<"last-published">>,   % RECOMMENDED
-       <<"member-affiliation">>,   % RECOMMENDED
-       <<"presence-notifications">>,   % OPTIONAL
-       <<"presence-subscribe">>,   % RECOMMENDED
-       <<"publisher-affiliation">>,   % RECOMMENDED
-       <<"publish-only-affiliation">>,   % OPTIONAL
-       <<"retrieve-default">>,
-       <<"shim">>].   % RECOMMENDED
+     <<"access-open">>,   % OPTIONAL this relates to access_model option in node_hometree
+     <<"access-presence">>,   % OPTIONAL this relates to access_model option in node_pep
+     <<"access-whitelist">>,   % OPTIONAL
+     <<"collections">>,   % RECOMMENDED
+     <<"config-node">>,   % RECOMMENDED
+     <<"create-and-configure">>,   % RECOMMENDED
+     <<"item-ids">>,   % RECOMMENDED
+     <<"last-published">>,   % RECOMMENDED
+     <<"member-affiliation">>,   % RECOMMENDED
+     <<"presence-notifications">>,   % OPTIONAL
+     <<"presence-subscribe">>,   % RECOMMENDED
+     <<"publisher-affiliation">>,   % RECOMMENDED
+     <<"publish-only-affiliation">>,   % OPTIONAL
+     <<"retrieve-default">>,
+     <<"shim">>].   % RECOMMENDED
 
 % see plugin "retrieve-items",   % RECOMMENDED
 % see plugin "retrieve-subscriptions",   % RECOMMENDED
@@ -3920,7 +3935,7 @@ err_subid_required() ->
 err_too_many_subscriptions() ->
     #ps_error{type = 'too-many-subscriptions'}.
 
--spec err_unsupported(ps_error_feature()) -> ps_error().
+-spec err_unsupported(ps_feature()) -> ps_error().
 err_unsupported(Feature) ->
     #ps_error{type = 'unsupported', feature = Feature}.
 
index afb610ca79976fde49c9d2cad34eeb6cc273f4c5..45f8ade6352f5b4242a20831c9c4b06e0f4d3143 100644 (file)
@@ -28,7 +28,7 @@
 -author('bjc@kublai.com').
 
 -include("pubsub.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -export([init/3, terminate/2, options/0, features/0,
     create_node_permission/6, create_node/2, delete_node/1,
@@ -78,8 +78,9 @@ publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload, PubOpts) ->
            case find_opt(node_type, Options) of
                collection ->
                    Txt = <<"Publishing items to collection node is not allowed">>,
-                   {error,
-                    ?ERR_EXTENDED(?ERRT_NOT_ALLOWED(?MYLANG, Txt), <<"publish">>)};
+                   {error, mod_pubsub:extended_error(
+                             xmpp:err_not_allowed(Txt, ?MYLANG),
+                             mod_pubsub:err_unsupported('publish'))};
                _ ->
                    node_hometree:publish_item(Nidx, Publisher, Model,
                        MaxItems, ItemId, Payload, PubOpts)
index b3af69cd19d02e52c121bfee4fb82da0c3429efc..0a72b18d53dc5b0c78db1a133d9116331ef19397 100644 (file)
@@ -34,7 +34,7 @@
 -author('christophe.romain@process-one.net').
 
 -include("pubsub.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -export([init/3, terminate/2, options/0, features/0,
     create_node_permission/6, create_node/2, delete_node/1,
@@ -94,10 +94,12 @@ delete_node(Nodes) ->
 
 subscribe_node(_Nidx, _Sender, _Subscriber, _AccessModel, _SendLast, _PresenceSubscription,
            _RosterGroup, _Options) ->
-    {error, ?ERR_FORBIDDEN}.
+    {error, mod_pubsub:extended_error(xmpp:err_feature_not_implemented(),
+                                     mod_pubsub:err_unsupported('subscribe'))}.
 
 unsubscribe_node(_Nidx, _Sender, _Subscriber, _SubId) ->
-    {error, ?ERR_FORBIDDEN}.
+    {error, mod_pubsub:extended_error(xmpp:err_feature_not_implemented(),
+                                     mod_pubsub:err_unsupported('subscribe'))}.
 
 publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload,
             PubOpts) ->
@@ -118,10 +120,12 @@ remove_extra_items(_Nidx, _MaxItems, ItemIds) ->
     {result, {ItemIds, []}}.
 
 delete_item(_Nidx, _Publisher, _PublishModel, _ItemId) ->
-    {error, ?ERR_ITEM_NOT_FOUND}.
+    {error, mod_pubsub:extended_error(xmpp:err_feature_not_implemented(),
+                                     mod_pubsub:err_unsupported('delete-items'))}.
 
 purge_node(_Nidx, _Owner) ->
-    {error, ?ERR_FORBIDDEN}.
+    {error, mod_pubsub:extended_error(xmpp:err_feature_not_implemented(),
+                                     mod_pubsub:err_unsupported('purge-nodes'))}.
 
 get_entity_affiliations(_Host, _Owner) ->
     {result, []}.
index 2fb24ee69059ab360fb2acb6dfcf80ed43f5f4f1..2ec9afe54cf93592545fcd24600dc879ac1ab8d1 100644 (file)
@@ -34,7 +34,7 @@
 -author('christophe.romain@process-one.net').
 
 -include("pubsub.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -export([init/3, terminate/2, options/0, features/0,
     create_node_permission/6, create_node/2, delete_node/1,
@@ -107,8 +107,8 @@ features() ->
        <<"retrieve-items">>,
        <<"retrieve-subscriptions">>,
        <<"subscribe">>,
+        %%<<"subscription-options">>,
        <<"subscription-notifications">>].
-%%<<"subscription-options">>
 
 %% @doc Checks if the current user has the permission to create the requested node
 %% <p>In flat node, any unused node name is allowed. The access parameter is also
@@ -196,27 +196,27 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel,
     Owner = Affiliation == owner,
     if not Authorized ->
            {error,
-               ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)};
+               mod_pubsub:extended_error((xmpp:err_bad_request()), mod_pubsub:err_invalid_jid())};
        (Affiliation == outcast) or (Affiliation == publish_only) ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        PendingSubscription ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)};
+               mod_pubsub:extended_error((xmpp:err_not_authorized()), mod_pubsub:err_pending_subscription())};
        (AccessModel == presence) and (not PresenceSubscription) and (not Owner) ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)};
+               mod_pubsub:extended_error((xmpp:err_not_authorized()), mod_pubsub:err_presence_subscription_required())};
        (AccessModel == roster) and (not RosterGroup) and (not Owner) ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)};
+               mod_pubsub:extended_error((xmpp:err_not_authorized()), mod_pubsub:err_not_in_roster_group())};
        (AccessModel == whitelist) and (not Whitelisted) and (not Owner) ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)};
+               mod_pubsub:extended_error((xmpp:err_not_allowed()), mod_pubsub:err_closed_node())};
        %%MustPay ->
        %%        % Payment is required for a subscription
        %%        {error, ?ERR_PAYMENT_REQUIRED};
        %%ForbiddenAnonymous ->
        %%        % Requesting entity is anonymous
-       %%        {error, ?ERR_FORBIDDEN};
+       %%        {error, xmpp:err_forbidden()};
        true ->
            %%SubId = pubsub_subscription:add_subscription(Subscriber, Nidx, Options),
            {NewSub, SubId} = case Subscriptions of
@@ -265,17 +265,17 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) ->
     if
        %% Requesting entity is prohibited from unsubscribing entity
        not Authorized ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        %% Entity did not specify SubId
        %%SubId == "", ?? ->
-       %%        {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
+       %%        {error, mod_pubsub:extended_error(xmpp:err_bad_request(), "subid-required")};
        %% Invalid subscription identifier
        %%InvalidSubId ->
-       %%        {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
+       %%        {error, mod_pubsub:extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
        %% Requesting entity is not a subscriber
        Subscriptions == [] ->
            {error,
-               ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)};
+               mod_pubsub:extended_error(xmpp:err_unexpected_request(), mod_pubsub:err_not_subscribed())};
        %% Subid supplied, so use that.
        SubIdExists ->
            Sub = first_in_list(fun
@@ -289,7 +289,7 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) ->
                    {result, default};
                false ->
                    {error,
-                       ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}
+                       mod_pubsub:extended_error(xmpp:err_unexpected_request(), mod_pubsub:err_not_subscribed())}
            end;
        %% Asking to remove all subscriptions to the given node
        SubId == all ->
@@ -302,7 +302,7 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) ->
        %% No subid and more than one possible subscription match.
        true ->
            {error,
-               ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}
+               mod_pubsub:extended_error((xmpp:err_bad_request()), mod_pubsub:err_subid_required())}
     end.
 
 delete_subscriptions(SubKey, Nidx, Subscriptions, SubState) ->
@@ -366,7 +366,7 @@ publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload,
                        or (Affiliation == publisher)
                        or (Affiliation == publish_only))
                    or (Subscribed == true)) ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        true ->
            if MaxItems > 0 ->
                    Now = p1_time_compat:timestamp(),
@@ -425,7 +425,7 @@ delete_item(Nidx, Publisher, PublishModel, ItemId) ->
        _ -> false
     end,
     if not Allowed ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        true ->
            case lists:member(ItemId, Items) of
                true ->
@@ -450,9 +450,9 @@ delete_item(Nidx, Publisher, PublishModel, ItemId) ->
                                    (_, Res) ->
                                        Res
                                end,
-                               {error, ?ERR_ITEM_NOT_FOUND}, States);
+                               {error, xmpp:err_item_not_found()}, States);
                        _ ->
-                           {error, ?ERR_ITEM_NOT_FOUND}
+                           {error, xmpp:err_item_not_found()}
                    end
            end
     end.
@@ -474,7 +474,7 @@ purge_node(Nidx, Owner) ->
                States),
            {result, {default, broadcast}};
        _ ->
-           {error, ?ERR_FORBIDDEN}
+           {error, xmpp:err_forbidden()}
     end.
 
 %% @doc <p>Return the current affiliations for the given user</p>
@@ -581,7 +581,7 @@ set_subscriptions(Nidx, Owner, Subscription, SubId) ->
            case Subscription of
                none ->
                    {error,
-                       ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)};
+                       mod_pubsub:extended_error((xmpp:err_bad_request()), mod_pubsub:err_not_subscribed())};
                _ ->
                    new_subscription(Nidx, Owner, Subscription, SubState)
            end;
@@ -592,7 +592,7 @@ set_subscriptions(Nidx, Owner, Subscription, SubId) ->
            end;
        {<<>>, [_ | _]} ->
            {error,
-               ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)};
+               mod_pubsub:extended_error((xmpp:err_bad_request()), mod_pubsub:err_subid_required())};
        _ ->
            case Subscription of
                none -> unsub_with_subid(Nidx, SubId, SubState);
@@ -721,23 +721,23 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM
                  can_fetch_item(Affiliation, FullSubscriptions),
     if %%SubId == "", ?? ->
        %% Entity has multiple subscriptions to the node but does not specify a subscription ID
-       %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
+       %{error, mod_pubsub:extended_error(xmpp:err_bad_request(), "subid-required")};
        %%InvalidSubId ->
        %% Entity is subscribed but specifies an invalid subscription ID
-       %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
+       %{error, mod_pubsub:extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
        (Affiliation == outcast) or (Affiliation == publish_only) ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        (AccessModel == presence) and not PresenceSubscription ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)};
+               mod_pubsub:extended_error((xmpp:err_not_authorized()), mod_pubsub:err_presence_subscription_required())};
        (AccessModel == roster) and not RosterGroup ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)};
+               mod_pubsub:extended_error((xmpp:err_not_authorized()), mod_pubsub:err_not_in_roster_group())};
        (AccessModel == whitelist) and not Whitelisted ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)};
+               mod_pubsub:extended_error((xmpp:err_not_allowed()), mod_pubsub:err_closed_node())};
        (AccessModel == authorize) and not Whitelisted ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        %%MustPay ->
        %%        % Payment is required for a subscription
        %%        {error, ?ERR_PAYMENT_REQUIRED};
@@ -750,7 +750,7 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM
 get_item(Nidx, ItemId) ->
     case mnesia:read({pubsub_item, {ItemId, Nidx}}) of
        [Item] when is_record(Item, pubsub_item) -> {result, Item};
-       _ -> {error, ?ERR_ITEM_NOT_FOUND}
+       _ -> {error, xmpp:err_item_not_found()}
     end.
 
 get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) ->
@@ -762,23 +762,23 @@ get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _Sub
     Whitelisted = can_fetch_item(Affiliation, Subscriptions),
     if %%SubId == "", ?? ->
        %% Entity has multiple subscriptions to the node but does not specify a subscription ID
-       %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
+       %{error, mod_pubsub:extended_error(xmpp:err_bad_request(), "subid-required")};
        %%InvalidSubId ->
        %% Entity is subscribed but specifies an invalid subscription ID
-       %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
+       %{error, mod_pubsub:extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
        (Affiliation == outcast) or (Affiliation == publish_only) ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        (AccessModel == presence) and not PresenceSubscription ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)};
+               mod_pubsub:extended_error((xmpp:err_not_authorized()), mod_pubsub:err_presence_subscription_required())};
        (AccessModel == roster) and not RosterGroup ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)};
+               mod_pubsub:extended_error((xmpp:err_not_authorized()), mod_pubsub:err_not_in_roster_group())};
        (AccessModel == whitelist) and not Whitelisted ->
            {error,
-               ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)};
+               mod_pubsub:extended_error((xmpp:err_not_allowed()), mod_pubsub:err_closed_node())};
        (AccessModel == authorize) and not Whitelisted ->
-           {error, ?ERR_FORBIDDEN};
+           {error, xmpp:err_forbidden()};
        %%MustPay ->
        %%        % Payment is required for a subscription
        %%        {error, ?ERR_PAYMENT_REQUIRED};
index 2a468c69addcc52c8d8204884f0b9dceab667673..025f6caa8578c2697156bd8dd21cd6a43c2ceb42 100644 (file)
@@ -677,7 +677,7 @@ get_items(Nidx, _From, #rsm_set{max = Max, index = IncIndex,
                          "where exists ( select count(*) as count1 "
                          "from pubsub_item where nodeid='">>, SNidx,
                        <<"' and modification > pi.modification having count1 = ">>,
-                       IncIndex, <<" );">>]) of
+                       integer_to_binary(IncIndex), <<" );">>]) of
                    {selected, [_], [[O]]} ->
                        [<<"modification">>, <<"'", O/binary, "'">>];
                    _ ->
@@ -699,7 +699,7 @@ get_items(Nidx, _From, #rsm_set{max = Max, index = IncIndex,
            end,
     Query = fun(mssql, _) ->
                    ejabberd_sql:sql_query_t(
-                     [<<"select top ">>, Max,
+                     [<<"select top ">>, integer_to_binary(Max),
                       <<" itemid, publisher, creation, modification, payload "
                         "from pubsub_item where nodeid='">>, SNidx,
                       <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>,
@@ -709,7 +709,8 @@ get_items(Nidx, _From, #rsm_set{max = Max, index = IncIndex,
                      [<<"select itemid, publisher, creation, modification, payload "
                         "from pubsub_item where nodeid='">>, SNidx,
                       <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>,
-                      AttrName, <<" ">>, Order, <<" limit ">>, Max, <<" ;">>])
+                      AttrName, <<" ">>, Order, <<" limit ">>,
+                      integer_to_binary(Max), <<" ;">>])
            end,
     case ejabberd_sql:sql_query_t(Query) of
        {selected, [<<"itemid">>, <<"publisher">>, <<"creation">>,
index 387d98413d9a6165a380fa31d898b741b991abe0..f17f2846d37b887915ec8183156367eaa6cf9591 100644 (file)
@@ -30,7 +30,7 @@
 -include_lib("stdlib/include/qlc.hrl").
 
 -include("pubsub.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -export([init/3, terminate/2, options/0, set_node/1,
     get_node/3, get_node/2, get_node/1, get_nodes/2,
@@ -69,13 +69,13 @@ create_node(Key, Node, Type, Owner, Options, Parents) ->
                Other -> Other
            end;
        _ ->
-           {error, ?ERRT_CONFLICT(?MYLANG, <<"Node already exists">>)}
+           {error, xmpp:err_conflict(<<"Node already exists">>, ?MYLANG)}
     end.
 
 delete_node(Key, Node) ->
     case find_node(Key, Node) of
        false ->
-           {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)};
+           {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)};
        Record ->
            lists:foreach(fun (#pubsub_node{options = Opts} = Child) ->
                        NewOpts = remove_config_parent(Node, Opts),
@@ -99,7 +99,7 @@ get_node(Host, Node, _From) ->
 
 get_node(Host, Node) ->
     case find_node(Host, Node) of
-       false -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)};
+       false -> {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)};
        Record -> Record
     end.
 
@@ -115,7 +115,7 @@ get_nodes(Key) ->
 get_parentnodes(Host, Node, _From) ->
     case find_node(Host, Node) of
        false ->
-           {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)};
+           {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)};
        #pubsub_node{parents = Parents} ->
            Q = qlc:q([N
                        || #pubsub_node{nodeid = {NHost, NNode}} = N
@@ -139,7 +139,7 @@ get_subnodes(Host, <<>>) ->
     get_subnodes_helper(Host, <<>>);
 get_subnodes(Host, Node) ->
     case find_node(Host, Node) of
-       false -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)};
+       false -> {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)};
        _ -> get_subnodes_helper(Host, Node)
     end.
 
@@ -226,13 +226,13 @@ validate_parentage(Key, Owners, [<<>> | T]) ->
 validate_parentage(Key, Owners, [ParentID | T]) ->
     case find_node(Key, ParentID) of
        false ->
-           {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)};
+           {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)};
        #pubsub_node{owners = POwners, options = POptions} ->
            NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions),
            MutualOwners = [O || O <- Owners, PO <- POwners, O == PO],
            case {MutualOwners, NodeType} of
-               {[], _} -> {error, ?ERR_FORBIDDEN};
+               {[], _} -> {error, xmpp:err_forbidden()};
                {_, collection} -> validate_parentage(Key, Owners, T);
-               {_, _} -> {error, ?ERR_NOT_ALLOWED}
+               {_, _} -> {error, xmpp:err_not_allowed()}
            end
     end.
index 69b50ff9f40f92e100e75f3e3ecf244a1a39d071..81972ca3c1db35afd4fd81e8b440a2a027877769 100644 (file)
@@ -40,7 +40,7 @@
 -include_lib("stdlib/include/qlc.hrl").
 
 -include("pubsub.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -export([init/3, terminate/2, options/0, set_node/1,
     get_node/3, get_node/2, get_node/1, get_nodes/2,
@@ -76,13 +76,13 @@ get_node(Host, Node, _From) ->
 get_node(Host, Node) ->
     case mnesia:read({pubsub_node, {Host, Node}}) of
        [Record] when is_record(Record, pubsub_node) -> Record;
-       _ -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}
+       _ -> {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)}
     end.
 
 get_node(Nidx) ->
     case mnesia:index_read(pubsub_node, Nidx, #pubsub_node.id) of
        [Record] when is_record(Record, pubsub_node) -> Record;
-       _ -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}
+       _ -> {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)}
     end.
 
 get_nodes(Host, _From) ->
@@ -180,10 +180,10 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
                            options = Options}),
                    {ok, Nidx};
                false ->
-                   {error, ?ERR_FORBIDDEN}
+                   {error, xmpp:err_forbidden()}
            end;
        _ ->
-           {error, ?ERRT_CONFLICT(?MYLANG, <<"Node already exists">>)}
+           {error, xmpp:err_conflict(<<"Node already exists">>, ?MYLANG)}
     end.
 
 delete_node(Host, Node) ->
index edfdbc1d5f5404693ea02742652c933bc58d9c75..c292c775552429c2b3369205ebbcd26d52cbe810 100644 (file)
@@ -40,7 +40,7 @@
 -compile([{parse_transform, ejabberd_sql_pt}]).
 
 -include("pubsub.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 -include("ejabberd_sql_pt.hrl").
 
 -export([init/3, terminate/2, options/0, set_node/1,
@@ -97,7 +97,7 @@ set_node(Record) when is_record(Record, pubsub_node) ->
     case Nidx of
        none ->
            Txt = <<"Node index not found">>,
-           {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, Txt)};
+           {error, xmpp:err_internal_server_error(Txt, ?MYLANG)};
        _ ->
            lists:foreach(fun ({Key, Value}) ->
                        SKey = iolist_to_binary(atom_to_list(Key)),
@@ -125,9 +125,9 @@ get_node(Host, Node) ->
        {selected, [RItem]} ->
            raw_to_node(Host, RItem);
        {'EXIT', _Reason} ->
-           {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)};
+           {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)};
        _ ->
-           {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}
+           {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)}
     end.
 
 get_node(Nidx) ->
@@ -139,9 +139,9 @@ get_node(Nidx) ->
        {selected, [{Host, Node, Parent, Type}]} ->
            raw_to_node(Host, {Node, Parent, Type, Nidx});
        {'EXIT', _Reason} ->
-           {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)};
+           {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)};
        _ ->
-           {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}
+           {error, xmpp:err_item_not_found(<<"Node not found">>, ?MYLANG)}
     end.
 
 get_nodes(Host, _From) ->
@@ -249,12 +249,12 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
                        Other -> Other
                    end;
                false ->
-                   {error, ?ERR_FORBIDDEN}
+                   {error, xmpp:err_forbidden()}
            end;
        {result, _} ->
-           {error, ?ERRT_CONFLICT(?MYLANG, <<"Node already exists">>)};
+           {error, xmpp:err_conflict(<<"Node already exists">>, ?MYLANG)};
        {error, db_fail} ->
-           {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)}
+           {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)}
     end.
 
 delete_node(Host, Node) ->
index b910a5e7db48bdda17fcaff4a377e49bb01a427b..a6f8888a92af88e82965610a12251f1df4f26212 100644 (file)
@@ -75,27 +75,27 @@ add_subscription(#pubsub_subscription{subid = SubId, options = Opts}) ->
        Opts),
     ok.
 
-subscription_opt_from_sql({<<"DELIVER">>, Value}) ->
+subscription_opt_from_sql([<<"DELIVER">>, Value]) ->
     {deliver, sql_to_boolean(Value)};
-subscription_opt_from_sql({<<"DIGEST">>, Value}) ->
+subscription_opt_from_sql([<<"DIGEST">>, Value]) ->
     {digest, sql_to_boolean(Value)};
-subscription_opt_from_sql({<<"DIGEST_FREQUENCY">>, Value}) ->
+subscription_opt_from_sql([<<"DIGEST_FREQUENCY">>, Value]) ->
     {digest_frequency, sql_to_integer(Value)};
-subscription_opt_from_sql({<<"EXPIRE">>, Value}) ->
+subscription_opt_from_sql([<<"EXPIRE">>, Value]) ->
     {expire, sql_to_timestamp(Value)};
-subscription_opt_from_sql({<<"INCLUDE_BODY">>, Value}) ->
+subscription_opt_from_sql([<<"INCLUDE_BODY">>, Value]) ->
     {include_body, sql_to_boolean(Value)};
 %%TODO: might be > than 1 show_values value??.
 %%      need to use compact all in only 1 opt.
-subscription_opt_from_sql({<<"SHOW_VALUES">>, Value}) ->
+subscription_opt_from_sql([<<"SHOW_VALUES">>, Value]) ->
     {show_values, Value};
-subscription_opt_from_sql({<<"SUBSCRIPTION_TYPE">>, Value}) ->
+subscription_opt_from_sql([<<"SUBSCRIPTION_TYPE">>, Value]) ->
     {subscription_type,
        case Value of
            <<"items">> -> items;
            <<"nodes">> -> nodes
        end};
-subscription_opt_from_sql({<<"SUBSCRIPTION_DEPTH">>, Value}) ->
+subscription_opt_from_sql([<<"SUBSCRIPTION_DEPTH">>, Value]) ->
     {subscription_depth,
        case Value of
            <<"all">> -> all;
index 3ab502184b961fa73855a4c54978de008d810b9e..33c884afb49bf9ddc0d58453fce88357b6c0378c 100644 (file)
@@ -39,7 +39,7 @@
 
 -include("pubsub.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -define(PUBSUB_DELIVER, <<"pubsub#deliver">>).
 -define(PUBSUB_DIGEST, <<"pubsub#digest">>).
@@ -112,30 +112,15 @@ get_options_xform(Lang, Options) ->
     Keys = [deliver, show_values, subscription_type, subscription_depth],
     XFields = [get_option_xfield(Lang, Key, Options) || Key <- Keys],
     {result,
-       #xmlel{name = <<"x">>,
-           attrs = [{<<"xmlns">>, ?NS_XDATA}],
-           children =
-           [#xmlel{name = <<"field">>,
-                   attrs =
-                   [{<<"var">>, <<"FORM_TYPE">>},
-                       {<<"type">>, <<"hidden">>}],
-                   children =
-                   [#xmlel{name = <<"value">>, attrs = [],
-                           children =
-                           [{xmlcdata, ?NS_PUBSUB_SUB_OPTIONS}]}]}]
-           ++ XFields}}.
+     #xdata{type = form,
+           fields = [#xdata_field{type = hidden,
+                                  var = <<"FORM_TYPE">>,
+                                  values = [?NS_PUBSUB_SUB_OPTIONS]}|
+                     XFields]}}.
 
 parse_options_xform(XFields) ->
-    case fxml:remove_cdata(XFields) of
-       [#xmlel{name = <<"x">>} = XEl] ->
-           case jlib:parse_xdata_submit(XEl) of
-               XData when is_list(XData) ->
-                   Opts = set_xoption(XData, []),
-                   {result, Opts};
-               Other -> Other
-           end;
-       _ -> {result, []}
-    end.
+    Opts = set_xoption(XFields, []),
+    {result, Opts}.
 
 %%====================================================================
 %% Internal functions
@@ -223,9 +208,17 @@ val_xfield(digest_frequency = Opt, [Val]) ->
        _ ->
            Txt = <<"Value of '~s' should be integer">>,
            ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])),
-           {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}
+           {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)}
+    end;
+val_xfield(expire = Opt, [Val]) ->
+    case jlib:datetime_string_to_timestamp(Val) of
+       undefined ->
+           Txt = <<"Value of '~s' should be datetime string">>,
+           ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])),
+           {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)};
+       Timestamp ->
+           Timestamp
     end;
-val_xfield(expire, [Val]) -> jlib:datetime_string_to_timestamp(Val);
 val_xfield(include_body = Opt, [Val]) -> xopt_to_bool(Opt, Val);
 val_xfield(show_values, Vals) -> Vals;
 val_xfield(subscription_type, [<<"items">>]) -> items;
@@ -237,7 +230,7 @@ val_xfield(subscription_depth = Opt, [Depth]) ->
        _ ->
            Txt = <<"Value of '~s' should be integer">>,
            ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])),
-           {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}
+           {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)}
     end.
 
 %% Convert XForm booleans to Erlang booleans.
@@ -248,10 +241,7 @@ xopt_to_bool(_, <<"true">>) -> true;
 xopt_to_bool(Option, _) ->
     Txt = <<"Value of '~s' should be boolean">>,
     ErrTxt = iolist_to_binary(io_lib:format(Txt, [Option])),
-    {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}.
-
--spec get_option_xfield(Lang :: binary(), Key :: atom(),
-                       Options :: mod_pubsub:subOptions()) -> xmlel().
+    {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)}.
 
 %% Return a field for an XForm for Key, with data filled in, if
 %% applicable, from Options.
@@ -261,33 +251,22 @@ get_option_xfield(Lang, Key, Options) ->
     {Type, OptEls} = type_and_options(xfield_type(Key), Lang),
     Vals = case lists:keysearch(Key, 1, Options) of
        {value, {_, Val}} ->
-           [tr_xfield_values(Vals)
-               || Vals <- xfield_val(Key, Val)];
-       false -> []
+                  [xfield_val(Key, Val)];
+              false ->
+                  []
     end,
-    #xmlel{name = <<"field">>,
-       attrs =
-       [{<<"var">>, Var}, {<<"type">>, Type},
-           {<<"label">>, translate:translate(Lang, Label)}],
-       children = OptEls ++ Vals}.
+    #xdata_field{type = Type, var = Var,
+                label = translate:translate(Lang, Label),
+                values = Vals,
+                options = OptEls}.
 
 type_and_options({Type, Options}, Lang) ->
     {Type, [tr_xfield_options(O, Lang) || O <- Options]};
 type_and_options(Type, _Lang) -> {Type, []}.
 
 tr_xfield_options({Value, Label}, Lang) ->
-    #xmlel{name = <<"option">>,
-       attrs =
-       [{<<"label">>, translate:translate(Lang, Label)}],
-       children =
-       [#xmlel{name = <<"value">>, attrs = [],
-               children = [{xmlcdata, Value}]}]}.
-
-tr_xfield_values(Value) ->
-    %% Return the XForm variable name for a subscription option key.
-    %% Return the XForm variable type for a subscription option key.
-    #xmlel{name = <<"value">>, attrs = [],
-       children = [{xmlcdata, Value}]}.
+    #xdata_option{label = translate:translate(Lang, Label),
+                 value = Value}.
 
 xfield_var(deliver) -> ?PUBSUB_DELIVER;
 %xfield_var(digest) -> ?PUBSUB_DIGEST;
@@ -298,24 +277,24 @@ xfield_var(show_values) -> ?PUBSUB_SHOW_VALUES;
 xfield_var(subscription_type) -> ?PUBSUB_SUBSCRIPTION_TYPE;
 xfield_var(subscription_depth) -> ?PUBSUB_SUBSCRIPTION_DEPTH.
 
-xfield_type(deliver) -> <<"boolean">>;
-%xfield_type(digest) -> <<"boolean">>;
-%xfield_type(digest_frequency) -> <<"text-single">>;
-%xfield_type(expire) -> <<"text-single">>;
-%xfield_type(include_body) -> <<"boolean">>;
+xfield_type(deliver) -> boolean;
+%xfield_type(digest) -> boolean;
+%xfield_type(digest_frequency) -> 'text-single';
+%xfield_type(expire) -> 'text-single';
+%xfield_type(include_body) -> boolean;
 xfield_type(show_values) ->
-    {<<"list-multi">>,
+    {'list-multi',
        [{<<"away">>, ?SHOW_VALUE_AWAY_LABEL},
            {<<"chat">>, ?SHOW_VALUE_CHAT_LABEL},
            {<<"dnd">>, ?SHOW_VALUE_DND_LABEL},
            {<<"online">>, ?SHOW_VALUE_ONLINE_LABEL},
            {<<"xa">>, ?SHOW_VALUE_XA_LABEL}]};
 xfield_type(subscription_type) ->
-    {<<"list-single">>,
+    {'list-single',
        [{<<"items">>, ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL},
            {<<"nodes">>, ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]};
 xfield_type(subscription_depth) ->
-    {<<"list-single">>,
+    {'list-single',
        [{<<"1">>, ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL},
            {<<"all">>, ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}.
 
index 6e598320ca2d41506293676491258f247b4c29f1..7c067095772911c904b7324702abed16e15d0467 100644 (file)
@@ -35,7 +35,7 @@
 
 -include("pubsub.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -define(PUBSUB_DELIVER, <<"pubsub#deliver">>).
 -define(PUBSUB_DIGEST, <<"pubsub#digest">>).
@@ -117,30 +117,15 @@ get_options_xform(Lang, Options) ->
     Keys = [deliver, show_values, subscription_type, subscription_depth],
     XFields = [get_option_xfield(Lang, Key, Options) || Key <- Keys],
     {result,
-       #xmlel{name = <<"x">>,
-           attrs = [{<<"xmlns">>, ?NS_XDATA}],
-           children =
-           [#xmlel{name = <<"field">>,
-                   attrs =
-                   [{<<"var">>, <<"FORM_TYPE">>},
-                       {<<"type">>, <<"hidden">>}],
-                   children =
-                   [#xmlel{name = <<"value">>, attrs = [],
-                           children =
-                           [{xmlcdata, ?NS_PUBSUB_SUB_OPTIONS}]}]}]
-           ++ XFields}}.
+     #xdata{type = form,
+           fields = [#xdata_field{type = hidden,
+                                  var = <<"FORM_TYPE">>,
+                                  values = [?NS_PUBSUB_SUB_OPTIONS]}|
+                     XFields]}}.
 
 parse_options_xform(XFields) ->
-    case fxml:remove_cdata(XFields) of
-       [#xmlel{name = <<"x">>} = XEl] ->
-           case jlib:parse_xdata_submit(XEl) of
-               XData when is_list(XData) ->
-                   Opts = set_xoption(XData, []),
-                   {result, Opts};
-               Other -> Other
-           end;
-       _ -> {result, []}
-    end.
+    Opts = set_xoption(XFields, []),
+    {result, Opts}.
 
 %%====================================================================
 %% Internal functions
@@ -188,9 +173,17 @@ val_xfield(digest_frequency = Opt, [Val]) ->
        _ ->
            Txt = <<"Value of '~s' should be integer">>,
            ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])),
-           {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}
+           {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)}
+    end;
+val_xfield(expire = Opt, [Val]) ->
+    case jlib:datetime_string_to_timestamp(Val) of
+       undefined ->
+           Txt = <<"Value of '~s' should be datetime string">>,
+           ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])),
+           {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)};
+       Timestamp ->
+           Timestamp
     end;
-val_xfield(expire, [Val]) -> jlib:datetime_string_to_timestamp(Val);
 val_xfield(include_body = Opt, [Val]) -> xopt_to_bool(Opt, Val);
 val_xfield(show_values, Vals) -> Vals;
 val_xfield(subscription_type, [<<"items">>]) -> items;
@@ -202,7 +195,7 @@ val_xfield(subscription_depth = Opt, [Depth]) ->
        _ ->
            Txt = <<"Value of '~s' should be integer">>,
            ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])),
-           {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}
+           {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)}
     end.
 
 %% Convert XForm booleans to Erlang booleans.
@@ -213,7 +206,7 @@ xopt_to_bool(_, <<"true">>) -> true;
 xopt_to_bool(Option, _) ->
     Txt = <<"Value of '~s' should be boolean">>,
     ErrTxt = iolist_to_binary(io_lib:format(Txt, [Option])),
-    {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}.
+    {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)}.
 
 %% Return a field for an XForm for Key, with data filled in, if
 %% applicable, from Options.
@@ -222,34 +215,23 @@ get_option_xfield(Lang, Key, Options) ->
     Label = xfield_label(Key),
     {Type, OptEls} = type_and_options(xfield_type(Key), Lang),
     Vals = case lists:keysearch(Key, 1, Options) of
-       {value, {_, Val}} ->
-           [tr_xfield_values(Vals)
-               || Vals <- xfield_val(Key, Val)];
-       false -> []
-    end,
-    #xmlel{name = <<"field">>,
-       attrs =
-       [{<<"var">>, Var}, {<<"type">>, Type},
-           {<<"label">>, translate:translate(Lang, Label)}],
-       children = OptEls ++ Vals}.
+              {value, {_, Val}} ->
+                  [xfield_val(Key, Val)];
+              false ->
+                  []
+          end,
+    #xdata_field{type = Type, var = Var,
+                label = translate:translate(Lang, Label),
+                values = Vals,
+                options = OptEls}.
 
 type_and_options({Type, Options}, Lang) ->
     {Type, [tr_xfield_options(O, Lang) || O <- Options]};
 type_and_options(Type, _Lang) -> {Type, []}.
 
 tr_xfield_options({Value, Label}, Lang) ->
-    #xmlel{name = <<"option">>,
-       attrs =
-       [{<<"label">>, translate:translate(Lang, Label)}],
-       children =
-       [#xmlel{name = <<"value">>, attrs = [],
-               children = [{xmlcdata, Value}]}]}.
-
-tr_xfield_values(Value) ->
-    %% Return the XForm variable name for a subscription option key.
-    %% Return the XForm variable type for a subscription option key.
-    #xmlel{name = <<"value">>, attrs = [],
-       children = [{xmlcdata, Value}]}.
+    #xdata_option{label = translate:translate(Lang, Label),
+                 value = Value}.
 
 xfield_var(deliver) -> ?PUBSUB_DELIVER;
 %xfield_var(digest) -> ?PUBSUB_DIGEST;
@@ -260,26 +242,26 @@ xfield_var(show_values) -> ?PUBSUB_SHOW_VALUES;
 xfield_var(subscription_type) -> ?PUBSUB_SUBSCRIPTION_TYPE;
 xfield_var(subscription_depth) -> ?PUBSUB_SUBSCRIPTION_DEPTH.
 
-xfield_type(deliver) -> <<"boolean">>;
-%xfield_type(digest) -> <<"boolean">>;
-%xfield_type(digest_frequency) -> <<"text-single">>;
-%xfield_type(expire) -> <<"text-single">>;
-%xfield_type(include_body) -> <<"boolean">>;
+xfield_type(deliver) -> boolean;
+%xfield_type(digest) -> boolean;
+%xfield_type(digest_frequency) -> 'text-single';
+%xfield_type(expire) -> 'text-single';
+%xfield_type(include_body) -> boolean;
 xfield_type(show_values) ->
-    {<<"list-multi">>,
-       [{<<"away">>, ?SHOW_VALUE_AWAY_LABEL},
-           {<<"chat">>, ?SHOW_VALUE_CHAT_LABEL},
-           {<<"dnd">>, ?SHOW_VALUE_DND_LABEL},
-           {<<"online">>, ?SHOW_VALUE_ONLINE_LABEL},
-           {<<"xa">>, ?SHOW_VALUE_XA_LABEL}]};
+    {'list-multi',
+     [{<<"away">>, ?SHOW_VALUE_AWAY_LABEL},
+      {<<"chat">>, ?SHOW_VALUE_CHAT_LABEL},
+      {<<"dnd">>, ?SHOW_VALUE_DND_LABEL},
+      {<<"online">>, ?SHOW_VALUE_ONLINE_LABEL},
+      {<<"xa">>, ?SHOW_VALUE_XA_LABEL}]};
 xfield_type(subscription_type) ->
-    {<<"list-single">>,
-       [{<<"items">>, ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL},
-           {<<"nodes">>, ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]};
+    {'list-single',
+     [{<<"items">>, ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL},
+      {<<"nodes">>, ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]};
 xfield_type(subscription_depth) ->
-    {<<"list-single">>,
-       [{<<"1">>, ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL},
-           {<<"all">>, ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}.
+    {'list-single',
+     [{<<"1">>, ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL},
+      {<<"all">>, ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}.
 
 %% Return the XForm variable label for a subscription option key.
 xfield_label(deliver) -> ?DELIVER_LABEL;
index 445d9a716d6a6751ca262ac9f7c774504a4a519d..a11c8dd76502debc1a2104597f8cf36c57dec0fb 100644 (file)
                         'presence-subscription-required' | 'subid-required' |
                         'too-many-subscriptions' | 'unsupported' |
                         'unsupported-access-model'.
--type ps_error_feature() :: 'access-authorize' | 'access-open' |
-                           'access-presence' | 'access-roster' |
-                           'access-whitelist' | 'auto-create' |
-                           'auto-subscribe' | 'collections' | 'config-node' |
-                           'create-and-configure' | 'create-nodes' |
-                           'delete-items' | 'delete-nodes' |
-                           'filtered-notifications' | 'get-pending' |
-                           'instant-nodes' | 'item-ids' | 'last-published' |
-                           'leased-subscription' | 'manage-subscriptions' |
-                           'member-affiliation' | 'meta-data' |
-                           'modify-affiliations' | 'multi-collection' |
-                           'multi-subscribe' | 'outcast-affiliation' |
-                           'persistent-items' | 'presence-notifications' |
-                           'presence-subscribe' | 'publish' |
-                           'publish-options' | 'publish-only-affiliation' |
-                           'publisher-affiliation' | 'purge-nodes' |
-                           'retract-items' | 'retrieve-affiliations' |
-                           'retrieve-default' | 'retrieve-items' |
-                           'retrieve-subscriptions' | 'subscribe' |
-                           'subscription-options' | 'subscription-notifications'.
--record(ps_error, {type :: ps_error_type(), feature :: ps_error_feature()}).
+-type ps_feature() :: 'access-authorize' | 'access-open' |
+                     'access-presence' | 'access-roster' |
+                     'access-whitelist' | 'auto-create' |
+                     'auto-subscribe' | 'collections' | 'config-node' |
+                     'create-and-configure' | 'create-nodes' |
+                     'delete-items' | 'delete-nodes' |
+                     'filtered-notifications' | 'get-pending' |
+                     'instant-nodes' | 'item-ids' | 'last-published' |
+                     'leased-subscription' | 'manage-subscriptions' |
+                     'member-affiliation' | 'meta-data' |
+                     'modify-affiliations' | 'multi-collection' |
+                     'multi-subscribe' | 'outcast-affiliation' |
+                     'persistent-items' | 'presence-notifications' |
+                     'presence-subscribe' | 'publish' |
+                     'publish-options' | 'publish-only-affiliation' |
+                     'publisher-affiliation' | 'purge-nodes' |
+                     'retract-items' | 'retrieve-affiliations' |
+                     'retrieve-default' | 'retrieve-items' |
+                     'retrieve-subscriptions' | 'subscribe' |
+                     'subscription-options' | 'subscription-notifications'.
+-record(ps_error, {type :: ps_error_type(), feature :: ps_feature()}).
 -type ps_error() :: #ps_error{}.
 
 -xml(pubsub_error_closed_node,