diff --git a/include/xmpp_codec.hrl b/include/xmpp_codec.hrl index 3424ec3b9..7eabdab8f 100644 --- a/include/xmpp_codec.hrl +++ b/include/xmpp_codec.hrl @@ -5,6 +5,47 @@ hash :: binary()}). -type vcard_xupdate() :: #vcard_xupdate{}. +-record(ps_affiliation, {xmlns = <<>> :: binary(), + node = <<>> :: binary(), + type :: member | none | outcast | + owner | publisher | 'publish-only', + jid :: jid:jid()}). +-type ps_affiliation() :: #ps_affiliation{}. + +-type ps_error_type() :: 'closed-node' | 'configuration-required' | + 'invalid-jid' | 'invalid-options' | + 'invalid-payload' | 'invalid-subid' | + 'item-forbidden' | 'item-required' | 'jid-required' | + 'max-items-exceeded' | 'max-nodes-exceeded' | + 'nodeid-required' | 'not-in-roster-group' | + 'not-subscribed' | 'payload-too-big' | + 'payload-required' | 'pending-subscription' | + '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_error() :: #ps_error{}. + -record(chatstate, {type :: active | composing | gone | inactive | paused}). -type chatstate() :: #chatstate{}. @@ -77,10 +118,10 @@ -record(muc_unsubscribe, {}). -type muc_unsubscribe() :: #muc_unsubscribe{}. --record(pubsub_unsubscribe, {node = <<>> :: binary(), - jid :: jid:jid(), - subid = <<>> :: binary()}). --type pubsub_unsubscribe() :: #pubsub_unsubscribe{}. +-record(ps_unsubscribe, {node = <<>> :: binary(), + jid :: jid:jid(), + subid = <<>> :: binary()}). +-type ps_unsubscribe() :: #ps_unsubscribe{}. -record(mix_leave, {}). -type mix_leave() :: #mix_leave{}. @@ -105,10 +146,6 @@ height :: non_neg_integer()}). -type thumbnail() :: #thumbnail{}. --record(pubsub_affiliation, {node = <<>> :: binary(), - type :: 'member' | 'none' | 'outcast' | 'owner' | 'publish-only' | 'publisher'}). --type pubsub_affiliation() :: #pubsub_affiliation{}. - -record(muc_decline, {reason = <<>> :: binary(), from :: jid:jid(), to :: jid:jid()}). @@ -195,13 +232,16 @@ -record(feature_sm, {xmlns = <<>> :: binary()}). -type feature_sm() :: #feature_sm{}. --record(pubsub_item, {id = <<>> :: binary(), - xml_els = [] :: [fxml:xmlel()]}). --type pubsub_item() :: #pubsub_item{}. +-record(ps_item, {xmlns = <<>> :: binary(), + id = <<>> :: binary(), + xml_els = [] :: [fxml:xmlel()], + node = <<>> :: binary(), + publisher = <<>> :: binary()}). +-type ps_item() :: #ps_item{}. --record(pubsub_publish, {node = <<>> :: binary(), - items = [] :: [#pubsub_item{}]}). --type pubsub_publish() :: #pubsub_publish{}. +-record(ps_publish, {node = <<>> :: binary(), + items = [] :: [#ps_item{}]}). +-type ps_publish() :: #ps_publish{}. -record(roster_item, {jid :: jid:jid(), name = <<>> :: binary(), @@ -214,12 +254,6 @@ ver :: binary()}). -type roster_query() :: #roster_query{}. --record(pubsub_event_item, {id = <<>> :: binary(), - node = <<>> :: binary(), - publisher = <<>> :: binary(), - xml_els = [] :: [fxml:xmlel()]}). --type pubsub_event_item() :: #pubsub_event_item{}. - -record(sm_r, {xmlns = <<>> :: binary()}). -type sm_r() :: #sm_r{}. @@ -263,14 +297,6 @@ xmlns = <<>> :: binary()}). -type sm_enabled() :: #sm_enabled{}. --record(pubsub_event_items, {node = <<>> :: binary(), - retract = [] :: [binary()], - items = [] :: [#pubsub_event_item{}]}). --type pubsub_event_items() :: #pubsub_event_items{}. - --record(pubsub_event, {items = [] :: [#pubsub_event_items{}]}). --type pubsub_event() :: #pubsub_event{}. - -record(muc_unique, {name = <<>> :: binary()}). -type muc_unique() :: #muc_unique{}. @@ -283,9 +309,9 @@ resource :: binary()}). -type legacy_auth() :: #legacy_auth{}. --record(pubsub_subscribe, {node = <<>> :: binary(), - jid :: jid:jid()}). --type pubsub_subscribe() :: #pubsub_subscribe{}. +-record(ps_subscribe, {node = <<>> :: binary(), + jid :: jid:jid()}). +-type ps_subscribe() :: #ps_subscribe{}. -record(message, {id = <<>> :: binary(), type = normal :: 'chat' | 'error' | 'groupchat' | 'headline' | 'normal', @@ -325,11 +351,13 @@ -record(muc_subscriptions, {list = [] :: [jid:jid()]}). -type muc_subscriptions() :: #muc_subscriptions{}. --record(pubsub_subscription, {jid :: jid:jid(), - node = <<>> :: binary(), - subid = <<>> :: binary(), - type :: 'none' | 'pending' | 'subscribed' | 'unconfigured'}). --type pubsub_subscription() :: #pubsub_subscription{}. +-record(ps_subscription, {xmlns = <<>> :: binary(), + jid :: jid:jid(), + type :: 'none' | 'pending' | 'subscribed' | 'unconfigured', + node = <<>> :: binary(), + subid = <<>> :: binary(), + expiry :: erlang:timestamp()}). +-type ps_subscription() :: #ps_subscription{}. -record(bob_data, {cid = <<>> :: binary(), 'max-age' :: non_neg_integer(), @@ -375,11 +403,13 @@ node = <<>> :: binary()}). -type stats() :: #stats{}. --record(pubsub_items, {node = <<>> :: binary(), - max_items :: non_neg_integer(), - subid = <<>> :: binary(), - items = [] :: [#pubsub_item{}]}). --type pubsub_items() :: #pubsub_items{}. +-record(ps_items, {xmlns = <<>> :: binary(), + node = <<>> :: binary(), + items = [] :: [#ps_item{}], + max_items :: non_neg_integer(), + subid = <<>> :: binary(), + retract :: binary()}). +-type ps_items() :: #ps_items{}. -record(presence, {id = <<>> :: binary(), type = available :: 'available' | 'error' | 'probe' | 'subscribe' | 'subscribed' | 'unavailable' | 'unsubscribe' | 'unsubscribed', @@ -438,10 +468,10 @@ -record(carbons_received, {forwarded :: #forwarded{}}). -type carbons_received() :: #carbons_received{}. --record(pubsub_retract, {node = <<>> :: binary(), - notify = false :: boolean(), - items = [] :: [#pubsub_item{}]}). --type pubsub_retract() :: #pubsub_retract{}. +-record(ps_retract, {node = <<>> :: binary(), + notify = false :: boolean(), + items = [] :: [#ps_item{}]}). +-type ps_retract() :: #ps_retract{}. -record(upload_slot, {get :: binary(), put :: binary(), @@ -707,22 +737,46 @@ xdata :: #xdata{}}). -type mam_query() :: #mam_query{}. --record(pubsub_options, {node = <<>> :: binary(), - jid :: jid:jid(), - subid = <<>> :: binary(), - xdata :: #xdata{}}). --type pubsub_options() :: #pubsub_options{}. +-record(pubsub_owner, {affiliations :: {binary(),[#ps_affiliation{}]}, + configure :: {binary(),'undefined' | #xdata{}}, + default :: {binary(),'undefined' | #xdata{}}, + delete :: {binary(),binary()}, + purge :: binary(), + subscriptions :: {binary(),[#ps_subscription{}]}}). +-type pubsub_owner() :: #pubsub_owner{}. --record(pubsub, {subscriptions :: {binary(),[#pubsub_subscription{}]}, - affiliations :: [#pubsub_affiliation{}], - publish :: #pubsub_publish{}, - subscribe :: #pubsub_subscribe{}, - unsubscribe :: #pubsub_unsubscribe{}, - options :: #pubsub_options{}, - items :: #pubsub_items{}, - retract :: #pubsub_retract{}}). +-record(ps_options, {node = <<>> :: binary(), + jid :: jid:jid(), + subid = <<>> :: binary(), + xdata :: #xdata{}}). +-type ps_options() :: #ps_options{}. + +-record(pubsub, {subscriptions :: {binary(),[#ps_subscription{}]}, + subscription :: #ps_subscription{}, + affiliations :: {binary(),[#ps_affiliation{}]}, + publish :: #ps_publish{}, + publish_options :: #xdata{}, + subscribe :: #ps_subscribe{}, + unsubscribe :: #ps_unsubscribe{}, + options :: #ps_options{}, + items :: #ps_items{}, + retract :: #ps_retract{}, + create :: binary(), + configure :: {binary(),'undefined' | #xdata{}}, + default :: {binary(),'undefined' | #xdata{}}, + delete :: {binary(),binary()}, + purge :: binary(), + rsm :: #rsm_set{}}). -type pubsub() :: #pubsub{}. +-record(ps_event, {items :: #ps_items{}, + purge :: binary(), + subscription :: #ps_subscription{}, + delete :: {binary(),binary()}, + create :: binary(), + configuration :: {binary(),'undefined' | #xdata{}}}). +-type ps_event() :: #ps_event{}. + -record(register, {registered = false :: boolean(), remove = false :: boolean(), instructions :: binary(), @@ -852,21 +906,27 @@ -type xmpp_element() :: muc_admin() | compression() | - pubsub_subscription() | + ps_subscription() | xdata_option() | version() | - pubsub_affiliation() | + ps_affiliation() | mam_fin() | sm_a() | bob_data() | media() | + stanza_id() | + starttls_proceed() | + client_id() | + sm_resumed() | + forwarded() | + xevent() | + privacy_list() | carbons_sent() | mam_archived() | p1_rebind() | sasl_abort() | db_result() | carbons_received() | - pubsub_retract() | upload_slot() | mix_participant() | compressed() | @@ -875,31 +935,20 @@ 'see-other-host'() | hint() | stream_start() | - stanza_id() | - starttls_proceed() | - client_id() | - sm_resumed() | - forwarded() | - xevent() | - privacy_list() | text() | vcard_org() | shim() | search_item() | offline_item() | feature_sm() | - pubsub_item() | roster_item() | - pubsub_event_item() | muc_item() | vcard_temp() | address() | sasl_success() | addresses() | - pubsub_event_items() | muc_subscriptions() | disco_items() | - pubsub_options() | compress() | bytestreams() | adhoc_actions() | @@ -912,9 +961,16 @@ vcard_tel() | vcard_geo() | vcard_photo() | + pubsub_owner() | pubsub() | muc_owner() | muc_actor() | + ps_error() | + starttls_failure() | + sasl_challenge() | + x_conference() | + private() | + sasl_failure() | vcard_name() | adhoc_note() | rosterver_feature() | @@ -924,18 +980,15 @@ bookmark_conference() | offline() | time() | + ps_subscribe() | sm_enable() | - starttls_failure() | - sasl_challenge() | handshake() | - x_conference() | - private() | compress_failure() | - sasl_failure() | bookmark_storage() | muc_decline() | legacy_auth() | search() | + ps_publish() | nick() | p1_ack() | block() | @@ -946,11 +999,12 @@ xcaptcha() | streamhost() | bind() | + ps_retract() | last() | redirect() | sm_enabled() | - pubsub_event() | vcard_sound() | + ps_event() | mam_result() | rsm_first() | stat() | @@ -961,15 +1015,17 @@ ping() | privacy_item() | disco_item() | + ps_item() | + mam_prefs() | + sasl_mechanisms() | caps() | muc() | stream_features() | stats() | - pubsub_items() | + ps_items() | sic() | + ps_options() | starttls() | - mam_prefs() | - sasl_mechanisms() | media_uri() | muc_destroy() | vcard_key() | @@ -990,23 +1046,21 @@ stream_error() | muc_user() | vcard_adr() | + gone() | carbons_private() | mix_leave() | muc_subscribe() | muc_unique() | sasl_response() | - pubsub_subscribe() | message() | presence() | - gone() | sm_resume() | carbons_enable() | expire() | muc_unsubscribe() | - pubsub_unsubscribe() | + ps_unsubscribe() | chatstate() | sasl_auth() | p1_push() | oob_x() | - pubsub_publish() | unblock(). diff --git a/src/gen_pubsub_node.erl b/src/gen_pubsub_node.erl index 27cb032bd..cc94ea147 100644 --- a/src/gen_pubsub_node.erl +++ b/src/gen_pubsub_node.erl @@ -25,7 +25,7 @@ -module(gen_pubsub_node). --include("jlib.hrl"). +-include("xmpp.hrl"). -type(host() :: mod_pubsub:host()). -type(nodeId() :: mod_pubsub:nodeId()). @@ -175,20 +175,13 @@ ok | {error, xmlel()}. --callback get_items(NodeIdx :: nodeIdx(), - JID :: jid(), - AccessModel :: accessModel(), - Presence_Subscription :: boolean(), - RosterGroup :: boolean(), - SubId :: subId(), - RSM :: none | rsm_in()) -> - {result, {[pubsubItem()], none | rsm_out()}} | - {error, xmlel()}. +-callback get_items(nodeIdx(), jid(), accessModel(), + boolean(), boolean(), binary(), + undefined | rsm_set()) -> + {result, {[pubsubItem()], undefined | rsm_set()}} | {error, error()}. --callback get_items(NodeIdx :: nodeIdx(), - From :: jid(), - RSM :: none | rsm_in()) -> - {result, {[pubsubItem()], none | rsm_out()}}. +-callback get_items(nodeIdx(), jid(), undefined | rsm_set()) -> + {result, {[pubsubItem()], undefined | rsm_set()}}. -callback get_item(NodeIdx :: nodeIdx(), ItemId :: itemId(), diff --git a/src/mod_caps.erl b/src/mod_caps.erl index e57bc7928..a388b085f 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -406,13 +406,15 @@ feature_response(_IQResult, Host, From, Caps, [_SubNode | SubNodes]) -> feature_request(Host, From, Caps, SubNodes). --spec caps_read_fun(binary(), {binary(), binary()}) -> function(). +-spec caps_read_fun(binary(), {binary(), binary()}) + -> fun(() -> {ok, [binary()] | non_neg_integer()} | error). caps_read_fun(Host, Node) -> LServer = jid:nameprep(Host), Mod = gen_mod:db_mod(LServer, ?MODULE), fun() -> Mod:caps_read(LServer, Node) end. --spec caps_write_fun(binary(), {binary(), binary()}, [binary()]) -> function(). +-spec caps_write_fun(binary(), {binary(), binary()}, + [binary()] | non_neg_integer()) -> fun(). caps_write_fun(Host, Node, Features) -> LServer = jid:nameprep(Host), Mod = gen_mod:db_mod(LServer, ?MODULE), diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 042c59702..f72f334f3 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -287,8 +287,8 @@ get_pep_node(#message{from = #jid{luser = <<>>}}) -> %% It's not PEP. undefined; get_pep_node(#message{} = Msg) -> - case xmpp:get_subtag(Msg, #pubsub_event{}) of - #pubsub_event{items = [#pubsub_event_items{node = Node}]} -> + case xmpp:get_subtag(Msg, #ps_event{}) of + #ps_event{items = #ps_items{node = Node}} -> Node; _ -> undefined diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index b470c093e..2f2962b97 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -4377,12 +4377,12 @@ send_wrapped(From, To, Packet, Node, State) -> wrap(From, To, Packet, Node) -> El = xmpp:encode(xmpp:set_from_to(Packet, From, To)), #message{ - sub_els = [#pubsub_event{ - items = [#pubsub_event_items{ - node = Node, - items = [#pubsub_event_item{ - id = randoms:get_string(), - xml_els = [El]}]}]}]}. + sub_els = [#ps_event{ + items = #ps_items{ + node = Node, + items = [#ps_item{ + id = randoms:get_string(), + xml_els = [El]}]}}]}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Multicast diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index fadc7720c..c84fb5fe8 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -41,8 +41,9 @@ -include("ejabberd.hrl"). -include("logger.hrl"). --include("adhoc.hrl"). --include("jlib.hrl"). +%%-include("adhoc.hrl"). +%%-include("jlib.hrl"). +-include("xmpp.hrl"). -include("pubsub.hrl"). -define(STDTREE, <<"tree">>). @@ -58,7 +59,9 @@ disco_sm_features/5, disco_sm_items/5]). %% exported iq handlers --export([iq_sm/3]). +-export([iq_sm/1, process_disco_info/1, process_disco_items/1, + process_pubsub/1, process_pubsub_owner/1, process_vcard/1, + process_commands/1]). %% exports for console debug manual use -export([create_node/5, create_node/7, delete_node/3, @@ -70,10 +73,21 @@ %% general helpers for plugins -export([subscription_to_string/1, affiliation_to_string/1, string_to_subscription/1, string_to_affiliation/1, - extended_error/2, extended_error/3, service_jid/1, + extended_error/2, service_jid/1, tree/1, tree/2, plugin/2, plugins/1, config/3, host/1, serverhost/1]). +%% pubsub#errors +-export([err_closed_node/0, err_configuration_required/0, + err_invalid_jid/0, err_invalid_options/0, err_invalid_payload/0, + err_invalid_subid/0, err_item_forbidden/0, err_item_required/0, + err_jid_required/0, err_max_items_exceeded/0, err_max_nodes_exceeded/0, + err_nodeid_required/0, err_not_in_roster_group/0, err_not_subscribed/0, + err_payload_too_big/0, err_payload_required/0, + err_pending_subscription/0, err_presence_subscription_required/0, + err_subid_required/0, err_too_many_subscriptions/0, err_unsupported/1, + err_unsupported_access_model/0]). + %% API and gen_server callbacks -export([start_link/2, start/2, stop/1, init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -295,6 +309,18 @@ init([ServerHost, Opts]) -> ?MODULE, remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, ServerHost, ?MODULE, remove_user, 50), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO, + ?MODULE, process_disco_info, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS, + ?MODULE, process_disco_items, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PUBSUB, + ?MODULE, process_pubsub, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PUBSUB_OWNER, + ?MODULE, process_pubsub_owner, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD, + ?MODULE, process_vcard, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS, + ?MODULE, process_commands, IQDisc), case lists:member(?PEPNODE, Plugins) of true -> ejabberd_hooks:add(caps_add, ServerHost, @@ -489,27 +515,21 @@ send_loop(State) -> %% disco hooks handling functions %% --spec disco_local_identity(Acc :: [xmlel()], _From :: jid(), - To :: jid(), Node :: <<>> | mod_pubsub:nodeId(), - Lang :: binary()) -> [xmlel()]. - +-spec disco_local_identity([identity()], jid(), jid(), + binary(), binary()) -> [identity()]. disco_local_identity(Acc, _From, To, <<>>, _Lang) -> case lists:member(?PEPNODE, plugins(host(To#jid.lserver))) of true -> - [#xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}]} - | Acc]; + [#identity{category = <<"pubsub">>, type = <<"pep">>} | Acc]; false -> Acc end; disco_local_identity(Acc, _From, _To, _Node, _Lang) -> Acc. --spec disco_local_features(Acc :: [xmlel()], _From :: jid(), - To :: jid(), Node :: <<>> | mod_pubsub:nodeId(), - Lang :: binary()) -> [binary(),...]. - +-spec disco_local_features({error, error()} | {result, [binary()]} | empty, + jid(), jid(), binary(), binary()) -> + {error, error()} | {result, [binary()]} | empty. disco_local_features(Acc, _From, To, <<>>, _Lang) -> Host = host(To#jid.lserver), Feats = case Acc of @@ -520,88 +540,83 @@ disco_local_features(Acc, _From, To, <<>>, _Lang) -> disco_local_features(Acc, _From, _To, _Node, _Lang) -> Acc. +-spec disco_local_items({error, error()} | {result, [disco_item()]} | empty, + jid(), jid(), binary(), binary()) -> + {error, error()} | {result, [disco_item()]} | empty. disco_local_items(Acc, _From, _To, <<>>, _Lang) -> Acc; disco_local_items(Acc, _From, _To, _Node, _Lang) -> Acc. -%disco_sm_identity(Acc, From, To, Node, Lang) -% when is_binary(Node) -> -% disco_sm_identity(Acc, From, To, iolist_to_binary(Node), -% Lang); --spec disco_sm_identity(Acc :: empty | [xmlel()], From :: jid(), - To :: jid(), Node :: mod_pubsub:nodeId(), - Lang :: binary()) -> [xmlel()]. - -disco_sm_identity(empty, From, To, Node, Lang) -> - disco_sm_identity([], From, To, Node, Lang); +-spec disco_sm_identity([identity()], jid(), jid(), + binary(), binary()) -> [identity()]. disco_sm_identity(Acc, From, To, Node, _Lang) -> disco_identity(jid:tolower(jid:remove_resource(To)), Node, From) ++ Acc. +-spec disco_identity(binary(), binary(), jid()) -> [identity()]. disco_identity(_Host, <<>>, _From) -> - [#xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}]}]; + [#identity{category = <<"pubsub">>, type = <<"pep">>}]; disco_identity(Host, Node, From) -> - Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> - Owners = node_owners_call(Host, Type, Nidx, O), - case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of - {result, _} -> - {result, [#xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}]}, - #xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"leaf">>} - | case get_option(Options, title) of - false -> []; - [Title] -> [{<<"name">>, Title}] - end]}]}; - _ -> - {result, []} - end - end, + Action = + fun(#pubsub_node{id = Nidx, type = Type, + options = Options, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, Type, + Options, Owners) of + {result, _} -> + {result, [#identity{category = <<"pubsub">>, + type = <<"pep">>}, + #identity{category = <<"pubsub">>, + type = <<"leaf">>, + name = case get_option(Options, title) of + false -> <<>>; + [Title] -> Title + end}]}; + _ -> + {result, []} + end + end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> Result; _ -> [] end. --spec disco_sm_features(Acc :: empty | {result, Features::[Feature::binary()]}, - From :: jid(), To :: jid(), Node :: mod_pubsub:nodeId(), - Lang :: binary()) -> {result, Features::[Feature::binary()]}. -%disco_sm_features(Acc, From, To, Node, Lang) -% when is_binary(Node) -> -% disco_sm_features(Acc, From, To, iolist_to_binary(Node), -% Lang); +-spec disco_sm_features({error, error()} | {result, [binary()]} | empty, + jid(), jid(), binary(), binary()) -> + {error, error()} | {result, [binary()]}. disco_sm_features(empty, From, To, Node, Lang) -> disco_sm_features({result, []}, From, To, Node, Lang); disco_sm_features({result, OtherFeatures} = _Acc, From, To, Node, _Lang) -> {result, - OtherFeatures ++ - disco_features(jid:tolower(jid:remove_resource(To)), Node, From)}; + OtherFeatures ++ + disco_features(jid:tolower(jid:remove_resource(To)), Node, From)}; disco_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. +-spec disco_features(ljid(), binary(), jid()) -> [binary()]. disco_features(Host, <<>>, _From) -> [?NS_PUBSUB | [feature(F) || F <- plugin_features(Host, <<"pep">>)]]; disco_features(Host, Node, From) -> - Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> - Owners = node_owners_call(Host, Type, Nidx, O), - case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of - {result, _} -> {result, [?NS_PUBSUB | [feature(F) || F <- plugin_features(Host, <<"pep">>)]]}; - _ -> {result, []} - end - end, + Action = + fun(#pubsub_node{id = Nidx, type = Type, + options = Options, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, + Type, Options, Owners) of + {result, _} -> + {result, + [?NS_PUBSUB | + [feature(F) || F <- plugin_features(Host, <<"pep">>)]]}; + _ -> + {result, []} + end + end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> Result; _ -> [] end. --spec disco_sm_items(Acc :: empty | {result, [xmlel()]}, From :: jid(), - To :: jid(), Node :: mod_pubsub:nodeId(), - Lang :: binary()) -> {result, [xmlel()]}. -%disco_sm_items(Acc, From, To, Node, Lang) -% when is_binary(Node) -> -% disco_sm_items(Acc, From, To, iolist_to_binary(Node), -% Lang); +-spec disco_sm_items({error, error()} | {result, [disco_item()]} | empty, + jid(), jid(), binary(), binary()) -> + {error, error()} | {result, [disco_item()]}. disco_sm_items(empty, From, To, Node, Lang) -> disco_sm_items({result, []}, From, To, Node, Lang); disco_sm_items({result, OtherItems}, From, To, Node, _Lang) -> @@ -609,48 +624,48 @@ disco_sm_items({result, OtherItems}, From, To, Node, _Lang) -> disco_items(jid:tolower(jid:remove_resource(To)), Node, From))}; disco_sm_items(Acc, _From, _To, _Node, _Lang) -> Acc. --spec disco_items(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - From :: jid()) -> [xmlel()]. +-spec disco_items(ljid(), binary(), jid()) -> [disco_item()]. disco_items(Host, <<>>, From) -> - Action = fun (#pubsub_node{nodeid = {_, Node}, - options = Options, type = Type, id = Nidx, owners = O}, - Acc) -> - Owners = node_owners_call(Host, Type, Nidx, O), - case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of - {result, _} -> - [#xmlel{name = <<"item">>, - attrs = [{<<"node">>, (Node)}, - {<<"jid">>, jid:to_string(Host)} - | case get_option(Options, title) of - false -> []; - [Title] -> [{<<"name">>, Title}] - end]} - | Acc]; - _ -> - Acc - end - end, + Action = + fun(#pubsub_node{nodeid = {_, Node}, options = Options, + type = Type, id = Nidx, owners = O}, Acc) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, + Type, Options, Owners) of + {result, _} -> + [#disco_item{node = Node, + jid = jid:make(Host), + name = case get_option(Options, title) of + false -> <<>>; + [Title] -> Title + end} | Acc]; + _ -> + Acc + end + end, NodeBloc = fun() -> - {result, - lists:foldl(Action, [], tree_call(Host, get_nodes, [Host]))} - end, + {result, + lists:foldl(Action, [], tree_call(Host, get_nodes, [Host]))} + end, case transaction(Host, NodeBloc, sync_dirty) of {result, Items} -> Items; _ -> [] end; disco_items(Host, Node, From) -> - Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> - Owners = node_owners_call(Host, Type, Nidx, O), - case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of - {result, Items} -> - {result, [#xmlel{name = <<"item">>, - attrs = [{<<"jid">>, jid:to_string(Host)}, - {<<"name">>, ItemId}]} - || #pubsub_item{itemid = {ItemId, _}} <- Items]}; - _ -> - {result, []} - end - end, + Action = + fun(#pubsub_node{id = Nidx, type = Type, + options = Options, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, + Type, Options, Owners) of + {result, Items} -> + {result, [#disco_item{jid = jid:make(Host), + name = ItemId} + || #pubsub_item{itemid = {ItemId, _}} <- Items]}; + _ -> + {result, []} + end + end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> Result; _ -> [] @@ -836,9 +851,6 @@ handle_call(stop, _From, State) -> %% @private handle_cast(_Msg, State) -> {noreply, State}. --spec handle_info(_ :: {route, From::jid(), To::jid(), Packet::xmlel()}, - State :: state()) -> {noreply, state()}. - %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | %% {noreply, State, Timeout} | @@ -846,9 +858,12 @@ handle_cast(_Msg, State) -> {noreply, State}. %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- %% @private -handle_info({route, From, To, Packet}, - #state{server_host = ServerHost, access = Access, plugins = Plugins} = State) -> - case catch do_route(ServerHost, Access, Plugins, To#jid.lserver, From, To, Packet) of +handle_info({route, From, To, #iq{} = IQ}, + State) when To#jid.lresource == <<"">> -> + ejabberd_router:process_iq(From, To, IQ), + {noreply, State}; +handle_info({route, From, To, Packet}, State) -> + case catch do_route(To#jid.lserver, From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); _ -> ok end, @@ -903,6 +918,12 @@ terminate(_Reason, ?MODULE, remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, ?MODULE, remove_user, 50), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PUBSUB), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PUBSUB_OWNER), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_COMMANDS), mod_disco:unregister_feature(ServerHost, ?NS_PUBSUB), case whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) of undefined -> @@ -920,187 +941,163 @@ terminate(_Reason, %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. --spec do_route(ServerHost :: binary(), Access :: atom(), - Plugins :: [binary(),...], Host :: mod_pubsub:hostPubsub(), - From :: jid(), To :: jid(), Packet :: xmlel()) -> ok. - %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- -do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> - #xmlel{name = Name, attrs = Attrs} = Packet, - case To of - #jid{luser = <<>>, lresource = <<>>} -> - case Name of - <<"iq">> -> - case jlib:iq_query_info(Packet) of - #iq{type = get, xmlns = ?NS_DISCO_INFO, sub_el = SubEl, lang = Lang} = IQ -> - #xmlel{attrs = QAttrs} = SubEl, - Node = fxml:get_attr_s(<<"node">>, QAttrs), - Info = ejabberd_hooks:run_fold(disco_info, ServerHost, - [], - [ServerHost, ?MODULE, <<>>, <<>>]), - Res = case iq_disco_info(Host, Node, From, Lang) of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = - [#xmlel{name = <<"query">>, - attrs = QAttrs, - children = IQRes ++ Info}]}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = get, xmlns = ?NS_DISCO_ITEMS, sub_el = SubEl} = IQ -> - #xmlel{attrs = QAttrs} = SubEl, - Node = fxml:get_attr_s(<<"node">>, QAttrs), - Res = case iq_disco_items(Host, Node, From, jlib:rsm_decode(IQ)) of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = - [#xmlel{name = <<"query">>, - attrs = QAttrs, - children = IQRes}]}) - %{error, Error} -> - % jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = IQType, xmlns = ?NS_PUBSUB, lang = Lang, sub_el = SubEl} = IQ -> - Res = case iq_pubsub(Host, ServerHost, From, IQType, - SubEl, Lang, Access, Plugins) - of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, sub_el = IQRes}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = IQType, xmlns = ?NS_PUBSUB_OWNER, lang = Lang, sub_el = SubEl} = IQ -> - Res = case iq_pubsub_owner(Host, ServerHost, From, - IQType, SubEl, Lang) - of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, sub_el = IQRes}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = get, xmlns = (?NS_VCARD) = XMLNS, lang = Lang, sub_el = _SubEl} = IQ -> - Res = IQ#iq{type = result, - sub_el = - [#xmlel{name = <<"vCard">>, - attrs = [{<<"xmlns">>, XMLNS}], - children = iq_get_vcard(Lang)}]}, - ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); - #iq{type = set, xmlns = ?NS_COMMANDS} = IQ -> - Res = case iq_command(Host, ServerHost, From, IQ, Access, Plugins) of - {error, Error} -> - jlib:make_error_reply(Packet, Error); - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, sub_el = IQRes}) - end, - ejabberd_router:route(To, From, Res); - #iq{} -> - Err = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED), - ejabberd_router:route(To, From, Err); - _ -> - ok - end; - <<"message">> -> - case fxml:get_attr_s(<<"type">>, Attrs) of - <<"error">> -> - ok; - _ -> - case find_authorization_response(Packet) of - none -> - ok; - invalid -> - Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), - Txt = <<"Incorrect authorization response">>, - Err = jlib:make_error_reply( - Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), - ejabberd_router:route(To, From, Err); - XFields -> - handle_authorization_response(Host, From, To, Packet, XFields) - end - end; - _ -> - ok - end; - _ -> - case fxml:get_attr_s(<<"type">>, Attrs) of - <<"error">> -> - ok; - <<"result">> -> - ok; - _ -> - Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND), - ejabberd_router:route(To, From, Err) - end +-spec process_disco_info(iq()) -> iq(). +process_disco_info(#iq{type = set, lang = Lang} = IQ) -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)); +process_disco_info(#iq{from = From, to = To, lang = Lang, type = get, + sub_els = [#disco_info{node = Node}]} = IQ) -> + Host = To#jid.lserver, + ServerHost = ejabberd_router:host_of_route(Host), + Info = ejabberd_hooks:run_fold(disco_info, ServerHost, + [], + [ServerHost, ?MODULE, <<>>, <<>>]), + case iq_disco_info(Host, Node, From, Lang) of + {result, IQRes} -> + xmpp:make_iq_result(IQ, IQRes#disco_info{node = Node, xdata = Info}); + {error, Error} -> + xmpp:make_error(IQ, Error) end. -command_disco_info(_Host, ?NS_COMMANDS, _From) -> - IdentityEl = #xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"automation">>}, - {<<"type">>, <<"command-list">>}]}, - {result, [IdentityEl]}; -command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING, _From) -> - IdentityEl = #xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"automation">>}, - {<<"type">>, <<"command-node">>}]}, - FeaturesEl = #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_COMMANDS}]}, - {result, [IdentityEl, FeaturesEl]}. +-spec process_disco_items(iq()) -> iq(). +process_disco_items(#iq{type = set, lang = Lang} = IQ) -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)); +process_disco_items(#iq{type = get, from = From, to = To, + sub_els = [#disco_items{node = Node} = SubEl]} = IQ) -> + Host = To#jid.lserver, + case iq_disco_items(Host, Node, From, SubEl#disco_items.rsm) of + {result, IQRes} -> + xmpp:make_iq_result(IQ, IQRes#disco_items{node = Node}); + {error, Error} -> + xmpp:make_error(IQ, Error) + end. +-spec process_pubsub(iq()) -> iq(). +process_pubsub(#iq{to = To} = IQ) -> + Host = To#jid.lserver, + ServerHost = ejabberd_router:host_of_route(Host), + Access = config(ServerHost, access), + case iq_pubsub(Host, Access, IQ) of + {result, IQRes} -> + xmpp:make_iq_result(IQ, IQRes); + {error, Error} -> + xmpp:make_error(IQ, Error) + end. + +-spec process_pubsub_owner(iq()) -> iq(). +process_pubsub_owner(#iq{to = To} = IQ) -> + Host = To#jid.lserver, + case iq_pubsub_owner(Host, IQ) of + {result, IQRes} -> + xmpp:make_iq_result(IQ, IQRes); + {error, Error} -> + xmpp:make_error(IQ, Error) + end. + +-spec process_vcard(iq()) -> iq(). +process_vcard(#iq{type = get, lang = Lang} = IQ) -> + xmpp:make_iq_result(IQ, iq_get_vcard(Lang)); +process_vcard(#iq{type = set, lang = Lang} = IQ) -> + Txt = <<"Value 'set' of 'type' attribute is not allowed">>, + xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)). + +-spec process_commands(iq()) -> iq(). +process_commands(#iq{type = set, to = To, from = From, + sub_els = [#adhoc_command{} = Request]} = IQ) -> + Host = To#jid.lserver, + ServerHost = ejabberd_router:host_of_route(Host), + Plugins = config(ServerHost, plugins), + Access = config(ServerHost, access), + case adhoc_request(Host, ServerHost, From, Request, Access, Plugins) of + {error, Error} -> + xmpp:make_error(IQ, Error); + Response -> + xmpp:make_iq_result( + IQ, xmpp_util:make_adhoc_response(Request, Response)) + end; +process_commands(#iq{type = get, lang = Lang} = IQ) -> + Txt = <<"Value 'get' of 'type' attribute is not allowed">>, + xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)). + +-spec do_route(binary(), jid(), jid(), stanza()) -> ok. +do_route(Host, From, To, Packet) -> + case To of + #jid{luser = <<>>, lresource = <<>>} -> + case Packet of + #message{type = T} when T /= error -> + case find_authorization_response(Packet) of + undefined -> + ok; + XData -> + handle_authorization_response(Host, From, To, Packet, XData) + end; + _ -> + Err = xmpp:err_service_unavailable(), + ejabberd_router:route_error(To, From, Packet, Err) + end; + _ -> + Err = xmpp:err_item_not_found(), + ejabberd_router:route_error(To, From, Packet, Err) + end. + +-spec command_disco_info(binary(), binary(), jid()) -> {result, disco_info()}. +command_disco_info(_Host, ?NS_COMMANDS, _From) -> + {result, #disco_info{identities = [#identity{category = <<"automation">>, + type = <<"command-list">>}]}}; +command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING, _From) -> + {result, #disco_info{identities = [#identity{category = <<"automation">>, + type = <<"command-node">>}], + features = [?NS_COMMANDS]}}. + +-spec node_disco_info(binary(), binary(), jid()) -> {result, disco_info()} | + {error, error()}. node_disco_info(Host, Node, From) -> node_disco_info(Host, Node, From, true, true). +-spec node_disco_info(binary(), binary(), jid(), boolean(), boolean()) -> + {result, disco_info()} | {error, error()}. node_disco_info(Host, Node, _From, _Identity, _Features) -> - Action = fun (#pubsub_node{type = Type, options = Options}) -> - NodeType = case get_option(Options, node_type) of - collection -> <<"collection">>; - _ -> <<"leaf">> - end, - I = #xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"pubsub">>}, - {<<"type">>, NodeType}]}, - F = [#xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_PUBSUB}]} - | [#xmlel{name = <<"feature">>, - attrs = [{<<"var">>, feature(F)}]} - || F <- plugin_features(Host, Type)]], - {result, [I | F]} - end, + Action = + fun(#pubsub_node{type = Type, options = Options}) -> + NodeType = case get_option(Options, node_type) of + collection -> <<"collection">>; + _ -> <<"leaf">> + end, + Is = [#identity{category = <<"pubsub">>, type = NodeType}], + Fs = [?NS_PUBSUB | [feature(F) || F <- plugin_features(Host, Type)]], + {result, #disco_info{identities = Is, features = Fs}} + end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> {result, Result}; Other -> Other end. +-spec iq_disco_info(binary(), binary(), jid(), binary()) + -> {result, disco_info()} | {error, error()}. iq_disco_info(Host, SNode, From, Lang) -> [Node | _] = case SNode of - <<>> -> [<<>>]; - _ -> str:tokens(SNode, <<"!">>) - end, - % Node = string_to_node(RealSNode), + <<>> -> [<<>>]; + _ -> str:tokens(SNode, <<"!">>) + end, case Node of <<>> -> - {result, [#xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"service">>}, - {<<"name">>, translate:translate(Lang, <<"Publish-Subscribe">>)}]}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_DISCO_INFO}]}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_DISCO_ITEMS}]}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_PUBSUB}]}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_COMMANDS}]}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_VCARD}]}] - ++ [#xmlel{name = <<"feature">>, - attrs = [{<<"var">>, feature(F)}]} - || F <- features(Host, Node)]}; + {result, + #disco_info{ + identities = [#identity{ + category = <<"pubsub">>, + type = <<"service">>, + name = translate:translate( + Lang, <<"Publish-Subscribe">>)}], + features = [?NS_DISCO_INFO, + ?NS_DISCO_ITEMS, + ?NS_PUBSUB, + ?NS_COMMANDS, + ?NS_VCARD | + [feature(F) || F <- features(Host, Node)]]}}; ?NS_COMMANDS -> command_disco_info(Host, Node, From); ?NS_PUBSUB_GET_PENDING -> @@ -1109,34 +1106,34 @@ iq_disco_info(Host, SNode, From, Lang) -> node_disco_info(Host, Node, From) end. --spec iq_disco_items(Host :: mod_pubsub:host(), Node :: <<>> | mod_pubsub:nodeId(), - From :: jid(), Rsm :: none | rsm_in()) -> {result, [xmlel()]}. +-spec iq_disco_items(host(), binary(), jid(), undefined | rsm_set()) -> + {result, disco_items()} | {error, error()}. iq_disco_items(Host, <<>>, From, _RSM) -> - {result, - lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, options = Options}) -> - Attrs = case get_option(Options, title) of - false -> - [{<<"jid">>, Host} - | nodeAttr(SubNode)]; - Title -> - [{<<"jid">>, Host}, - {<<"name">>, Title} - | nodeAttr(SubNode)] - end, - #xmlel{name = <<"item">>, attrs = Attrs} - end, - tree_action(Host, get_subnodes, [Host, <<>>, From]))}; + Items = + lists:map( + fun(#pubsub_node{nodeid = {_, SubNode}, options = Options}) -> + case get_option(Options, title) of + false -> + #disco_item{jid = jid:make(Host), + node = SubNode}; + Title -> + #disco_item{jid = jid:make(Host), + name = Title, + node = SubNode} + end + end, tree_action(Host, get_subnodes, [Host, <<>>, From])), + {result, #disco_items{items = Items}}; iq_disco_items(Host, ?NS_COMMANDS, _From, _RSM) -> - {result, [#xmlel{name = <<"item">>, - attrs = [{<<"jid">>, Host}, - {<<"node">>, ?NS_PUBSUB_GET_PENDING}, - {<<"name">>, <<"Get Pending">>}]}]}; + {result, + #disco_items{items = [#disco_item{jid = jid:make(Host), + node = ?NS_PUBSUB_GET_PENDING, + name = <<"Get Pending">>}]}}; iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From, _RSM) -> - {result, []}; + {result, #disco_items{}}; iq_disco_items(Host, Item, From, RSM) -> case str:tokens(Item, <<"!">>) of [_Node, _ItemId] -> - {result, []}; + {result, #disco_items{}}; [Node] -> Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> Owners = node_owners_call(Host, Type, Nidx, O), @@ -1144,28 +1141,28 @@ iq_disco_items(Host, Item, From, RSM) -> From, Type, Options, Owners, RSM) of {result, R} -> R; - _ -> {[], none} + _ -> {[], undefined} end, - Nodes = lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> - Attrs = case get_option(SubOptions, title) of - false -> - [{<<"jid">>, Host} - | nodeAttr(SubNode)]; - Title -> - [{<<"jid">>, Host}, - {<<"name">>, Title} - | nodeAttr(SubNode)] - end, - #xmlel{name = <<"item">>, attrs = Attrs} - end, - tree_call(Host, get_subnodes, [Host, Node, From])), - Items = lists:map(fun (#pubsub_item{itemid = {RN, _}}) -> - {result, Name} = node_call(Host, Type, get_item_name, [Host, Node, RN]), - #xmlel{name = <<"item">>, - attrs = [{<<"jid">>, Host}, {<<"name">>, Name}]} - end, - NodeItems), - {result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)} + Nodes = lists:map( + fun(#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> + case get_option(SubOptions, title) of + false -> + #disco_item{jid = jid:make(Host), + node = SubNode}; + Title -> + #disco_item{jid = jid:make(Host), + name = Title, + node = SubNode} + end + end, tree_call(Host, get_subnodes, [Host, Node, From])), + Items = lists:map( + fun(#pubsub_item{itemid = {RN, _}}) -> + {result, Name} = node_call(Host, Type, get_item_name, [Host, Node, RN]), + #disco_item{jid = jid:make(Host), name = Name} + end, NodeItems), + {result, + #disco_items{items = Nodes ++ Items, + rsm = RsmOut}} end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> {result, Result}; @@ -1173,477 +1170,348 @@ iq_disco_items(Host, Item, From, RSM) -> end end. --spec iq_sm(From :: jid(), To :: jid(), IQ :: iq_request()) -> iq_result() | iq_error(). -iq_sm(From, To, #iq{type = Type, sub_el = SubEl, xmlns = XMLNS, lang = Lang} = IQ) -> - ServerHost = To#jid.lserver, +-spec iq_sm(iq()) -> iq(). +iq_sm(#iq{to = To, sub_els = [SubEl]} = IQ) -> LOwner = jid:tolower(jid:remove_resource(To)), - Res = case XMLNS of - ?NS_PUBSUB -> - iq_pubsub(LOwner, ServerHost, From, Type, SubEl, Lang); - ?NS_PUBSUB_OWNER -> - iq_pubsub_owner(LOwner, ServerHost, From, Type, SubEl, Lang) - end, + Res = case xmpp:get_ns(SubEl) of + ?NS_PUBSUB -> + iq_pubsub(LOwner, all, IQ); + ?NS_PUBSUB_OWNER -> + iq_pubsub_owner(LOwner, IQ) + end, case Res of - {result, IQRes} -> IQ#iq{type = result, sub_el = IQRes}; - {error, Error} -> IQ#iq{type = error, sub_el = [Error, SubEl]} + {result, IQRes} -> + xmpp:make_iq_result(IQ, IQRes); + {error, Error} -> + xmpp:make_error(IQ, Error) end. +-spec iq_get_vcard(binary()) -> vcard_temp(). iq_get_vcard(Lang) -> - [#xmlel{name = <<"FN">>, attrs = [], - children = [{xmlcdata, <<"ejabberd/mod_pubsub">>}]}, - #xmlel{name = <<"URL">>, attrs = [], - children = [{xmlcdata, ?EJABBERD_URI}]}, - #xmlel{name = <<"DESC">>, attrs = [], - children = [{xmlcdata, - <<(translate:translate(Lang, <<"ejabberd Publish-Subscribe module">>))/binary, - "\nCopyright (c) 2004-2016 ProcessOne">>}]}]. + Desc = translate:translate(Lang, <<"ejabberd Publish-Subscribe module">>), + Copyright = <<"Copyright (c) 2004-2016 ProcessOne">>, + #vcard_temp{fn = <<"ejabberd/mod_pubsub">>, + url = ?EJABBERD_URI, + desc = <>}. --spec iq_pubsub(Host :: mod_pubsub:host(), ServerHost :: binary(), From :: jid(), - IQType :: 'get' | 'set', SubEl :: xmlel(), Lang :: binary()) -> - {result, [xmlel()]} | {error, xmlel()}. - -iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) -> - iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, all, plugins(Host)). - --spec iq_pubsub(Host :: mod_pubsub:host(), ServerHost :: binary(), From :: jid(), - IQType :: 'get' | 'set', SubEl :: xmlel(), Lang :: binary(), - Access :: atom(), Plugins :: [binary(),...]) -> - {result, [xmlel()]} | {error, xmlel()}. - -iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> - #xmlel{children = SubEls} = SubEl, - case fxml:remove_cdata(SubEls) of - [#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] -> - Node = fxml:get_attr_s(<<"node">>, Attrs), - case {IQType, Name} of - {set, <<"create">>} -> - Config = case Rest of - [#xmlel{name = <<"configure">>, children = C}] -> C; - _ -> [] - end, - Type = case fxml:get_attr_s(<<"type">>, Attrs) of - <<>> -> hd(Plugins); - T -> T - end, - case lists:member(Type, Plugins) of - false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"create-nodes">>)}; - true -> - create_node(Host, ServerHost, Node, From, Type, Access, Config) - end; - {set, <<"publish">>} -> - case fxml:remove_cdata(Els) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs, - children = Payload}] -> - ItemId = fxml:get_attr_s(<<"id">>, ItemAttrs), - PubOpts = case [C || #xmlel{name = <<"publish-options">>, - children = [C]} <- Rest] of - [XEl] -> - case jlib:parse_xdata_submit(XEl) of - invalid -> []; - Form -> Form - end; - _ -> [] - end, - publish_item(Host, ServerHost, Node, From, ItemId, Payload, PubOpts, Access); - [] -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; - _ -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)} - end; - {set, <<"retract">>} -> - ForceNotify = case fxml:get_attr_s(<<"notify">>, Attrs) of - <<"1">> -> true; - <<"true">> -> true; - _ -> false - end, - case fxml:remove_cdata(Els) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs}] -> - ItemId = fxml:get_attr_s(<<"id">>, ItemAttrs), - delete_item(Host, Node, From, ItemId, ForceNotify); - _ -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)} - end; - {set, <<"subscribe">>} -> - Config = case Rest of - [#xmlel{name = <<"options">>, children = C}] -> C; - _ -> [] - end, - JID = fxml:get_attr_s(<<"jid">>, Attrs), - subscribe_node(Host, Node, From, JID, Config); - {set, <<"unsubscribe">>} -> - JID = fxml:get_attr_s(<<"jid">>, Attrs), - SubId = fxml:get_attr_s(<<"subid">>, Attrs), - unsubscribe_node(Host, Node, From, JID, SubId); - {get, <<"items">>} -> - MaxItems = fxml:get_attr_s(<<"max_items">>, Attrs), - SubId = fxml:get_attr_s(<<"subid">>, Attrs), - ItemIds = lists:foldl(fun - (#xmlel{name = <<"item">>, attrs = ItemAttrs}, Acc) -> - case fxml:get_attr_s(<<"id">>, ItemAttrs) of - <<>> -> Acc; - ItemId -> [ItemId | Acc] - end; - (_, Acc) -> - Acc - end, - [], fxml:remove_cdata(Els)), - get_items(Host, Node, From, SubId, MaxItems, ItemIds, jlib:rsm_decode(SubEl)); - {get, <<"subscriptions">>} -> - get_subscriptions(Host, Node, From, Plugins); - {get, <<"affiliations">>} -> - get_affiliations(Host, Node, From, Plugins); - {get, <<"options">>} -> - SubId = fxml:get_attr_s(<<"subid">>, Attrs), - JID = fxml:get_attr_s(<<"jid">>, Attrs), - get_options(Host, Node, JID, SubId, Lang); - {set, <<"options">>} -> - SubId = fxml:get_attr_s(<<"subid">>, Attrs), - JID = fxml:get_attr_s(<<"jid">>, Attrs), - set_options(Host, Node, JID, SubId, Els); +-spec iq_pubsub(binary() | ljid(), atom(), iq()) -> + {result, pubsub()} | {error, error()}. +iq_pubsub(Host, Access, #iq{from = From, type = IQType, lang = Lang, + sub_els = [SubEl]}) -> + case {IQType, SubEl} of + {set, #pubsub{create = Node, configure = {_, XData}, + _ = undefined}} when is_binary(Node) -> + ServerHost = serverhost(Host), + Plugins = config(ServerHost, plugins), + Config = get_xdata_fields(XData), + Type = hd(Plugins), + create_node(Host, ServerHost, Node, From, Type, Access, Config); + {set, #pubsub{publish = #ps_publish{node = Node, items = Items}, + publish_options = XData, _ = undefined}} -> + ServerHost = serverhost(Host), + case Items of + [#ps_item{id = ItemId, xml_els = Payload}] -> + PubOpts = get_xdata_fields(XData), + publish_item(Host, ServerHost, Node, From, ItemId, + Payload, PubOpts, Access); + [] -> + {error, extended_error(xmpp:err_bad_request(), err_item_required())}; _ -> - {error, ?ERR_FEATURE_NOT_IMPLEMENTED} + {error, extended_error(xmpp:err_bad_request(), err_invalid_payload())} end; - Other -> - ?INFO_MSG("Too many actions: ~p", [Other]), - {error, ?ERR_BAD_REQUEST} - end. - - --spec iq_pubsub_owner(Host :: mod_pubsub:host(), ServerHost :: binary(), From :: jid(), - IQType :: 'get' | 'set', SubEl :: xmlel(), Lang :: binary()) -> - {result, [xmlel()]} | {error, xmlel()}. - -iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> - #xmlel{children = SubEls} = SubEl, - Action = fxml:remove_cdata(SubEls), - case Action of - [#xmlel{name = Name, attrs = Attrs, children = Els}] -> - Node = fxml:get_attr_s(<<"node">>, Attrs), - case {IQType, Name} of - {get, <<"configure">>} -> - get_configure(Host, ServerHost, Node, From, Lang); - {set, <<"configure">>} -> - set_configure(Host, Node, From, Els, Lang); - {get, <<"default">>} -> - get_default(Host, Node, From, Lang); - {set, <<"delete">>} -> - delete_node(Host, Node, From); - {set, <<"purge">>} -> - purge_node(Host, Node, From); - {get, <<"subscriptions">>} -> - get_subscriptions(Host, Node, From); - {set, <<"subscriptions">>} -> - set_subscriptions(Host, Node, From, fxml:remove_cdata(Els)); - {get, <<"affiliations">>} -> - get_affiliations(Host, Node, From); - {set, <<"affiliations">>} -> - set_affiliations(Host, Node, From, fxml:remove_cdata(Els)); + {set, #pubsub{retract = #ps_retract{node = Node, notify = Notify, items = Items}, + _ = undefined}} -> + case Items of + [#ps_item{id = ItemId}] -> + delete_item(Host, Node, From, ItemId, Notify); + [] -> + {error, extended_error(xmpp:err_bad_request(), err_item_required())}; _ -> - {error, ?ERR_FEATURE_NOT_IMPLEMENTED} + {error, extended_error(xmpp:err_bad_request(), err_invalid_payload())} end; + {set, #pubsub{subscribe = #ps_subscribe{node = Node, jid = JID}, + options = Options, _ = undefined}} -> + Config = case Options of + #ps_options{xdata = XData} -> get_xdata_fields(XData); + _ -> [] + end, + subscribe_node(Host, Node, From, JID, Config); + {set, #pubsub{unsubscribe = #ps_unsubscribe{node = Node, jid = JID, subid = SubId}, + _ = undefined}} -> + unsubscribe_node(Host, Node, From, JID, SubId); + {get, #pubsub{items = #ps_items{node = Node, + max_items = MaxItems, + subid = SubId, + items = Items}, + rsm = RSM, _ = undefined}} -> + ItemIds = [ItemId || #ps_item{id = ItemId} <- Items, ItemId /= <<>>], + get_items(Host, Node, From, SubId, MaxItems, ItemIds, RSM); + {get, #pubsub{subscriptions = {Node, _}, _ = undefined}} -> + Plugins = config(serverhost(Host), plugins), + get_subscriptions(Host, Node, From, Plugins); + {get, #pubsub{affiliations = {Node, _}, _ = undefined}} -> + Plugins = config(serverhost(Host), plugins), + get_affiliations(Host, Node, From, Plugins); + {get, #pubsub{options = #ps_options{node = Node, subid = SubId, jid = JID}, + _ = undefined}} -> + get_options(Host, Node, JID, SubId, Lang); + {set, #pubsub{options = #ps_options{node = Node, subid = SubId, + jid = JID, xdata = XData}, + _ = undefined}} -> + set_options(Host, Node, JID, SubId, get_xdata_fields(XData)); _ -> - ?INFO_MSG("Too many actions: ~p", [Action]), - {error, ?ERR_BAD_REQUEST} + {error, xmpp:err_feature_not_implemented()} end. -iq_command(Host, ServerHost, From, IQ, Access, Plugins) -> - case adhoc:parse_request(IQ) of - Req when is_record(Req, adhoc_request) -> - case adhoc_request(Host, ServerHost, From, Req, Access, Plugins) of - Resp when is_record(Resp, adhoc_response) -> - {result, [adhoc:produce_response(Req, Resp)]}; - Error -> - Error +-spec iq_pubsub_owner(binary() | ljid(), iq()) -> {result, pubsub()} | {error, error()}. +iq_pubsub_owner(Host, #iq{type = IQType, from = From, + lang = Lang, sub_els = [SubEl]}) -> + case {IQType, SubEl} of + {get, #pubsub_owner{configure = {Node, undefined}, _ = undefined}} -> + ServerHost = serverhost(Host), + get_configure(Host, ServerHost, Node, From, Lang); + {set, #pubsub_owner{configure = {Node, XData}, _ = undefined}} -> + case XData of + undefined -> + {error, xmpp:err_bad_request(<<"No data form found">>, Lang)}; + #xdata{type = cancel} -> + {result, #pubsub{}}; + #xdata{type = submit} -> + Config = get_xdata_fields(XData), + set_configure(Host, Node, From, Config, Lang); + #xdata{} -> + {error, xmpp:err_bad_request(<<"Incorrect data form">>, Lang)} end; - Err -> Err + {get, #pubsub_owner{default = {Node, undefined}, _ = undefined}} -> + get_default(Host, Node, From, Lang); + {set, #pubsub_owner{delete = {Node, _}, _ = undefined}} -> + delete_node(Host, Node, From); + {set, #pubsub_owner{purge = Node, _ = undefined}} when Node /= undefined -> + purge_node(Host, Node, From); + {get, #pubsub_owner{subscriptions = {Node, []}, _ = undefined}} -> + get_subscriptions(Host, Node, From); + {set, #pubsub_owner{subscriptions = {Node, Subs}, _ = undefined}} -> + set_subscriptions(Host, Node, From, Subs); + {get, #pubsub_owner{affiliations = {Node, []}, _ = undefined}} -> + get_affiliations(Host, Node, From); + {set, #pubsub_owner{affiliations = {Node, Affs}, _ = undefined}} -> + set_affiliations(Host, Node, From, Affs); + {_, #pubsub_owner{}} -> + {error, xmpp:err_bad_request()}; + _ -> + {error, xmpp:err_feature_not_implemented()} end. -%% @doc

Processes an Ad Hoc Command.

+-spec adhoc_request(binary(), binary(), jid(), adhoc_command(), + atom(), [binary()]) -> adhoc_command() | {error, error()}. adhoc_request(Host, _ServerHost, Owner, - #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, - lang = Lang, action = <<"execute">>, - xdata = false}, - _Access, Plugins) -> + #adhoc_command{node = ?NS_PUBSUB_GET_PENDING, lang = Lang, + action = execute, xdata = undefined}, + _Access, Plugins) -> send_pending_node_form(Host, Owner, Lang, Plugins); adhoc_request(Host, _ServerHost, Owner, - #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, - action = <<"execute">>, xdata = XData, lang = Lang}, - _Access, _Plugins) -> - ParseOptions = case XData of - #xmlel{name = <<"x">>} = XEl -> - case jlib:parse_xdata_submit(XEl) of - invalid -> - Txt = <<"Incorrect data form">>, - {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; - XData2 -> - case set_xoption(Host, XData2, []) of - NewOpts when is_list(NewOpts) -> {result, NewOpts}; - Err -> Err - end - end; - _ -> - Txt = <<"No data form found">>, - {error, ?ERRT_BAD_REQUEST(Lang, Txt)} - end, - case ParseOptions of - {result, XForm} -> + #adhoc_command{node = ?NS_PUBSUB_GET_PENDING, lang = Lang, + action = execute, xdata = #xdata{} = XData}, + _Access, _Plugins) -> + Config = get_xdata_fields(XData), + case set_xoption(Host, Config, []) of + XForm when is_list(XForm) -> case lists:keysearch(node, 1, XForm) of - {value, {_, Node}} -> send_pending_auth_events(Host, Node, Owner); - false -> {error, extended_error(?ERR_BAD_REQUEST, <<"bad-payload">>)} + {value, {_, Node}} -> + send_pending_auth_events(Host, Node, Owner, Lang); + false -> + {error, extended_error(xmpp:err_bad_request(), err_invalid_payload())} end; - Error -> Error + Err -> + Err end; adhoc_request(_Host, _ServerHost, _Owner, - #adhoc_request{action = <<"cancel">>}, _Access, - _Plugins) -> - #adhoc_response{status = canceled}; -adhoc_request(Host, ServerHost, Owner, - #adhoc_request{action = <<>>} = R, Access, Plugins) -> - adhoc_request(Host, ServerHost, Owner, - R#adhoc_request{action = <<"execute">>}, Access, - Plugins); + #adhoc_command{action = cancel}, _Access, _Plugins) -> + #adhoc_command{status = canceled}; adhoc_request(_Host, _ServerHost, _Owner, Other, _Access, _Plugins) -> ?DEBUG("Couldn't process ad hoc command:~n~p", [Other]), - {error, ?ERR_ITEM_NOT_FOUND}. + {error, xmpp:err_item_not_found()}. -%% @doc

Sends the process pending subscriptions XForm for Host to Owner.

+-spec send_pending_node_form(binary(), jid(), binary(), + [binary()]) -> adhoc_command() | {error, error()}. send_pending_node_form(Host, Owner, _Lang, Plugins) -> Filter = fun (Type) -> lists:member(<<"get-pending">>, plugin_features(Host, Type)) end, case lists:filter(Filter, Plugins) of [] -> - Err = extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"get-pending">>), + Err = extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('get-pending')), {error, Err}; Ps -> - XOpts = [#xmlel{name = <<"option">>, attrs = [], - children = [#xmlel{name = <<"value">>, - attrs = [], - children = [{xmlcdata, Node}]}]} - || Node <- get_pending_nodes(Host, Owner, Ps)], - XForm = #xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = [#xmlel{name = <<"field">>, - attrs = [{<<"type">>, <<"list-single">>}, - {<<"var">>, <<"pubsub#node">>}], - children = lists:usort(XOpts)}]}, - #adhoc_response{status = executing, - defaultaction = <<"execute">>, elements = [XForm]} + case get_pending_nodes(Host, Owner, Ps) of + {ok, Nodes} -> + XOpts = [#xdata_option{value = Node} || Node <- Nodes], + XForm = #xdata{type = form, + fields = [#xdata_field{ + type = 'list-single', + var = <<"pubsub#node">>, + options = lists:usort(XOpts)}]}, + #adhoc_command{status = executing, action = execute, + xdata = XForm}; + Err -> + Err + end end. +-spec get_pending_nodes(binary(), jid(), [binary()]) -> {ok, [binary()]} | + {error, error()}. get_pending_nodes(Host, Owner, Plugins) -> Tr = fun (Type) -> case node_call(Host, Type, get_pending_nodes, [Host, Owner]) of {result, Nodes} -> Nodes; _ -> [] end - end, + end, Action = fun() -> {result, lists:flatmap(Tr, Plugins)} end, case transaction(Host, Action, sync_dirty) of - {result, Res} -> Res; + {result, Res} -> {ok, Res}; Err -> Err end. %% @doc

Send a subscription approval form to Owner for all pending %% subscriptions on Host and Node.

-send_pending_auth_events(Host, Node, Owner) -> +-spec send_pending_auth_events(binary(), binary(), jid(), + binary()) -> adhoc_command() | {error, error()}. +send_pending_auth_events(Host, Node, Owner, Lang) -> ?DEBUG("Sending pending auth events for ~s on ~s:~s", - [jid:to_string(Owner), Host, Node]), - Action = fun (#pubsub_node{id = Nidx, type = Type}) -> - case lists:member(<<"get-pending">>, plugin_features(Host, Type)) of - true -> - case node_call(Host, Type, get_affiliation, [Nidx, Owner]) of - {result, owner} -> node_call(Host, Type, get_node_subscriptions, [Nidx]); - _ -> {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} - end; - false -> - {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"get-pending">>)} - end - end, + [jid:to_string(Owner), Host, Node]), + Action = + fun(#pubsub_node{id = Nidx, type = Type}) -> + case lists:member(<<"get-pending">>, plugin_features(Host, Type)) of + true -> + case node_call(Host, Type, get_affiliation, [Nidx, Owner]) of + {result, owner} -> + node_call(Host, Type, get_node_subscriptions, [Nidx]); + _ -> + {error, xmpp:err_forbidden( + <<"Owner privileges required">>, Lang)} + end; + false -> + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('get-pending'))} + end + end, case transaction(Host, Node, Action, sync_dirty) of {result, {N, Subs}} -> - lists:foreach(fun - ({J, pending, _SubId}) -> send_authorization_request(N, jid:make(J)); - ({J, pending}) -> send_authorization_request(N, jid:make(J)); - (_) -> ok - end, - Subs), - #adhoc_response{}; + lists:foreach( + fun({J, pending, _SubId}) -> send_authorization_request(N, jid:make(J)); + ({J, pending}) -> send_authorization_request(N, jid:make(J)); + (_) -> ok + end, Subs), + #adhoc_command{}; Err -> Err end. %%% authorization handling - -send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = Nidx, owners = O}, - Subscriber) -> +-spec send_authorization_request(#pubsub_node{}, jid()) -> ok. +send_authorization_request(#pubsub_node{nodeid = {Host, Node}, + type = Type, id = Nidx, owners = O}, + Subscriber) -> + %% TODO: pass lang to this function Lang = <<"en">>, - Stanza = #xmlel{name = <<"message">>, attrs = [], - children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - [#xmlel{name = <<"title">>, attrs = [], - children = - [{xmlcdata, - translate:translate(Lang, <<"PubSub subscriber request">>)}]}, - #xmlel{name = <<"instructions">>, - attrs = [], - children = - [{xmlcdata, - translate:translate(Lang, - <<"Choose whether to approve this entity's " - "subscription.">>)}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"FORM_TYPE">>}, - {<<"type">>, <<"hidden">>}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, ?NS_PUBSUB_SUB_AUTH}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"pubsub#node">>}, - {<<"type">>, - <<"text-single">>}, - {<<"label">>, translate:translate(Lang, <<"Node ID">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Node}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, - <<"pubsub#subscriber_jid">>}, - {<<"type">>, <<"jid-single">>}, - {<<"label">>, - translate:translate(Lang, <<"Subscriber Address">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, jid:to_string(Subscriber)}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, - <<"pubsub#allow">>}, - {<<"type">>, <<"boolean">>}, - {<<"label">>, - translate:translate(Lang, - <<"Allow this Jabber ID to subscribe to " - "this pubsub node?">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, <<"false">>}]}]}]}]}, - lists:foreach(fun (Owner) -> - ejabberd_router:route(service_jid(Host), jid:make(Owner), Stanza) - end, - node_owners_action(Host, Type, Nidx, O)). + Fs = [#xdata_field{var = <<"FORM_TYPE">>, + type = hidden, + values = [?NS_PUBSUB_SUB_AUTH]}, + #xdata_field{var = <<"pubsub#node">>, + type = 'text-single', + label = translate:translate(Lang, <<"Node ID">>), + values = [Node]}, + #xdata_field{var = <<"pubsub#subscriber_jid">>, + type = 'jid-single', + label = translate:translate(Lang, <<"Subscriber Address">>), + values = [jid:to_string(Subscriber)]}, + #xdata_field{var = <<"pubsub#allow">>, + type = boolean, + label = translate:translate( + Lang, + <<"Allow this Jabber ID to subscribe to " + "this pubsub node?">>), + values = [<<"false">>]}], + X = #xdata{type = form, + title = translate:translate( + Lang, <<"PubSub subscriber request">>), + instructions = [translate:translate( + Lang, + <<"Choose whether to approve this entity's " + "subscription.">>)], + fields = Fs}, + Stanza = #message{sub_els = [X]}, + lists:foreach( + fun (Owner) -> + ejabberd_router:route(service_jid(Host), jid:make(Owner), Stanza) + end, node_owners_action(Host, Type, Nidx, O)). +-spec find_authorization_response(message()) -> undefined | xdata(). find_authorization_response(Packet) -> - #xmlel{children = Els} = Packet, - XData1 = lists:map(fun - (#xmlel{name = <<"x">>, attrs = XAttrs} = XEl) -> - case fxml:get_attr_s(<<"xmlns">>, XAttrs) of - ?NS_XDATA -> - case fxml:get_attr_s(<<"type">>, XAttrs) of - <<"cancel">> -> none; - _ -> jlib:parse_xdata_submit(XEl) - end; - _ -> - none - end; - (_) -> - none - end, - fxml:remove_cdata(Els)), - XData = lists:filter(fun (E) -> E /= none end, XData1), - case XData of - [invalid] -> - invalid; - [] -> - none; - [XFields] when is_list(XFields) -> - ?DEBUG("XFields: ~p", [XFields]), - case lists:keysearch(<<"FORM_TYPE">>, 1, XFields) of - {value, {_, [?NS_PUBSUB_SUB_AUTH]}} -> XFields; - _ -> invalid - end + case xmpp:get_subtag(Packet, #xdata{}) of + #xdata{type = submit} = X -> + case xmpp_util:get_xdata_values(<<"FORM_TYPE">>, X) of + [?NS_PUBSUB_SUB_AUTH] -> X; + _ -> undefined + end; + _ -> + undefined end. %% @doc Send a message to JID with the supplied Subscription +-spec send_authorization_approval(binary(), jid(), binary(), subscribed | none) -> ok. send_authorization_approval(Host, JID, SNode, Subscription) -> - SubAttrs = case Subscription of - %{S, SID} -> - % [{<<"subscription">>, subscription_to_string(S)}, - % {<<"subid">>, SID}]; - S -> - [{<<"subscription">>, subscription_to_string(S)}] - end, - Stanza = event_stanza(<<"subscription">>, - [{<<"jid">>, jid:to_string(JID)} - | nodeAttr(SNode)] - ++ SubAttrs), + Event = #ps_event{subscription = + #ps_subscription{jid = JID, + node = SNode, + type = Subscription}}, + Stanza = #message{sub_els = [Event]}, ejabberd_router:route(service_jid(Host), JID, Stanza). -handle_authorization_response(Host, From, To, Packet, XFields) -> - Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), - case {lists:keysearch(<<"pubsub#node">>, 1, XFields), - lists:keysearch(<<"pubsub#subscriber_jid">>, 1, XFields), - lists:keysearch(<<"pubsub#allow">>, 1, XFields)} - of - {{value, {_, [Node]}}, - {value, {_, [SSubscriber]}}, - {value, {_, [SAllow]}}} -> +-spec handle_authorization_response(binary(), jid(), jid(), message(), xdata()) -> ok. +handle_authorization_response(Host, From, To, Packet, X) -> + Lang = xmpp:get_lang(Packet), + case {xmpp_util:get_xdata_values(<<"pubsub#node">>, X), + xmpp_util:get_xdata_values(<<"pubsub#subscriber_jid">>, X), + xmpp_util:get_xdata_values(<<"pubsub#allow">>, X)} of + {[Node], [SSubscriber], [SAllow]} -> FromLJID = jid:tolower(jid:remove_resource(From)), Subscriber = jid:from_string(SSubscriber), Allow = case SAllow of - <<"1">> -> true; - <<"true">> -> true; - _ -> false - end, - Action = fun (#pubsub_node{type = Type, id = Nidx, owners = O}) -> - Owners = node_owners_call(Host, Type, Nidx, O), - case lists:member(FromLJID, Owners) of - true -> - {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), - update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs); - false -> - {error, ?ERRT_FORBIDDEN(Lang, <<"You're not an owner">>)} - end - end, + <<"1">> -> true; + <<"true">> -> true; + _ -> false + end, + Action = + fun(#pubsub_node{type = Type, id = Nidx, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case lists:member(FromLJID, Owners) of + true -> + {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), + update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs); + false -> + {error, xmpp:err_forbidden(<<"Owner privileges required">>, Lang)} + end + end, case transaction(Host, Node, Action, sync_dirty) of {error, Error} -> - Err = jlib:make_error_reply(Packet, Error), - ejabberd_router:route(To, From, Err); + ejabberd_router:route_error(To, From, Packet, Error); {result, {_, _NewSubscription}} -> %% XXX: notify about subscription state change, section 12.11 ok; _ -> - Err = jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR), - ejabberd_router:route(To, From, Err) + Err = xmpp:err_internal_server_error(), + ejabberd_router:route_error(To, From, Packet, Err) end; _ -> - Txt = <<"Incorrect data form">>, - Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)), - ejabberd_router:route(To, From, Err) + Err = xmpp:err_not_acceptable(<<"Incorrect data form">>, Lang), + ejabberd_router:route_error(To, From, Packet, Err) end. +-spec update_auth(binary(), binary(), _, _, jid() | error, boolean(), _) -> + {result, ok} | {error, error()}. update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> Sub= lists:filter(fun ({pending, _}) -> true; @@ -1661,67 +1529,47 @@ update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> {result, ok}; _ -> Txt = <<"No pending subscriptions found">>, - {error, ?ERRT_UNEXPECTED_REQUEST(?MYLANG, Txt)} + {error, xmpp:err_unexpected_request(Txt, ?MYLANG)} end. -define(XFIELD(Type, Label, Var, Val), - #xmlel{name = <<"field">>, - attrs = [{<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]}]}). + #xdata_field{type = Type, + label = translate:translate(Lang, Label), + var = Var, + values = [Val]}). -define(BOOLXFIELD(Label, Var, Val), - ?XFIELD(<<"boolean">>, Label, Var, - case Val of - true -> <<"1">>; - _ -> <<"0">> - end)). + ?XFIELD(boolean, Label, Var, + case Val of + true -> <<"1">>; + _ -> <<"0">> + end)). -define(STRINGXFIELD(Label, Var, Val), - ?XFIELD(<<"text-single">>, Label, Var, Val)). + ?XFIELD('text-single', Label, Var, Val)). -define(STRINGMXFIELD(Label, Var, Vals), - #xmlel{name = <<"field">>, - attrs = [{<<"type">>, <<"text-multi">>}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, V}]} - || V <- Vals]}). + #xdata_field{type = 'text-multi', + label = translate:translate(Lang, Label), + var = Var, + values = Vals}). -define(XFIELDOPT(Type, Label, Var, Val, Opts), - #xmlel{name = <<"field">>, - attrs = [{<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = [#xmlel{name = <<"option">>, attrs = [], - children = [#xmlel{name = <<"value">>, - attrs = [], - children = [{xmlcdata, Opt}]}]} - || Opt <- Opts] - ++ - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]}]}). + #xdata_field{type = Type, + label = translate:translate(Lang, Label), + var = Var, + options = [#xdata_option{value = Opt} || Opt <- Opts], + values = [Val]}). -define(LISTXFIELD(Label, Var, Val, Opts), - ?XFIELDOPT(<<"list-single">>, Label, Var, Val, Opts)). + ?XFIELDOPT('list-single', Label, Var, Val, Opts)). -define(LISTMXFIELD(Label, Var, Vals, Opts), - #xmlel{name = <<"field">>, - attrs = [{<<"type">>, <<"list-multi">>}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = [#xmlel{name = <<"option">>, attrs = [], - children = [#xmlel{name = <<"value">>, - attrs = [], - children = [{xmlcdata, Opt}]}]} - || Opt <- Opts] - ++ - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]} - || Val <- Vals]}). + #xdata_field{type = 'list-multi', + label = translate:translate(Lang, Label), + var = Var, + options = [#xdata_option{value = Opt} || Opt <- Opts], + values = Vals}). %% @doc

Create new pubsub nodes

%%

In addition to method-specific error conditions, there are several general reasons why the node creation request might fail:

@@ -1740,97 +1588,69 @@ update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> %%
  • nodetree create_node checks if nodeid already exists
  • %%
  • node plugin create_node just sets default affiliation/subscription
  • %% --spec create_node(Host :: mod_pubsub:host(), ServerHost :: binary(), - Node :: <<>> | mod_pubsub:nodeId(), Owner :: jid(), - Type :: binary()) -> {result, [xmlel(),...]} | {error, xmlel()}. +-spec create_node(host(), binary(), binary(), jid(), + binary()) -> {result, pubsub()} | {error, error()}. create_node(Host, ServerHost, Node, Owner, Type) -> create_node(Host, ServerHost, Node, Owner, Type, all, []). --spec create_node(Host :: mod_pubsub:host(), ServerHost :: binary(), - Node :: <<>> | mod_pubsub:nodeId(), Owner :: jid(), - Type :: binary(), Access :: atom(), Configuration :: [xmlel()]) -> - {result, [xmlel(),...]} | {error, xmlel()}. - +-spec create_node(host(), binary(), binary(), jid(), binary(), + atom(), [{binary(), [binary()]}]) -> {result, pubsub()} | {error, error()}. create_node(Host, ServerHost, <<>>, Owner, Type, Access, Configuration) -> case lists:member(<<"instant-nodes">>, plugin_features(Host, Type)) of true -> Node = randoms:get_string(), case create_node(Host, ServerHost, Node, Owner, Type, Access, Configuration) of {result, _} -> - {result, [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"create">>, - attrs = nodeAttr(Node)}]}]}; + {result, #pubsub{create = Node}}; Error -> Error end; false -> - {error, extended_error(?ERR_NOT_ACCEPTABLE, <<"nodeid-required">>)} + {error, extended_error(xmpp:err_not_acceptable(), err_nodeid_required())} end; create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> Type = select_type(ServerHost, Host, Node, GivenType), - ParseOptions = case fxml:remove_cdata(Configuration) of - [] -> - {result, node_options(Host, Type)}; - [#xmlel{name = <<"x">>} = XEl] -> - case jlib:parse_xdata_submit(XEl) of - invalid -> - Txt = <<"Incorrect data form">>, - {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)}; - XData -> - case set_xoption(Host, XData, node_options(Host, Type)) of - NewOpts when is_list(NewOpts) -> {result, NewOpts}; - Err -> Err - end - end; - _ -> - ?INFO_MSG("Node ~p; bad configuration: ~p", [Node, Configuration]), - Txt = <<"No data form found">>, - {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)} - end, - case ParseOptions of - {result, NodeOptions} -> - CreateNode = fun () -> - Parent = case node_call(Host, Type, node_to_path, [Node]) of - {result, [Node]} -> - <<>>; - {result, Path} -> - element(2, node_call(Host, Type, path_to_node, [lists:sublist(Path, length(Path)-1)])) - end, - Parents = case Parent of - <<>> -> []; - _ -> [Parent] - end, - case node_call(Host, Type, create_node_permission, - [Host, ServerHost, Node, Parent, Owner, Access]) - of - {result, true} -> - case tree_call(Host, create_node, - [Host, Node, Type, Owner, NodeOptions, Parents]) - of - {ok, Nidx} -> - SubsByDepth = get_node_subs_by_depth(Host, Node, Owner), - case node_call(Host, Type, create_node, [Nidx, Owner]) of - {result, Result} -> {result, {Nidx, SubsByDepth, Result}}; - Error -> Error - end; - {error, {virtual, Nidx}} -> - case node_call(Host, Type, create_node, [Nidx, Owner]) of - {result, Result} -> {result, {Nidx, [], Result}}; - Error -> Error - end; - Error -> - Error - end; - _ -> - Txt1 = <<"You're not allowed to create nodes">>, - {error, ?ERRT_FORBIDDEN(?MYLANG, Txt1)} - end - end, - Reply = [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"create">>, - attrs = nodeAttr(Node)}]}], + case set_xoption(Host, Configuration, node_options(Host, Type)) of + NodeOptions when is_list(NodeOptions) -> + CreateNode = + fun() -> + Parent = case node_call(Host, Type, node_to_path, [Node]) of + {result, [Node]} -> + <<>>; + {result, Path} -> + element(2, node_call(Host, Type, path_to_node, + [lists:sublist(Path, length(Path)-1)])) + end, + Parents = case Parent of + <<>> -> []; + _ -> [Parent] + end, + case node_call(Host, Type, create_node_permission, + [Host, ServerHost, Node, Parent, Owner, Access]) of + {result, true} -> + case tree_call(Host, create_node, + [Host, Node, Type, Owner, NodeOptions, Parents]) + of + {ok, Nidx} -> + SubsByDepth = get_node_subs_by_depth(Host, Node, Owner), + case node_call(Host, Type, create_node, [Nidx, Owner]) of + {result, Result} -> {result, {Nidx, SubsByDepth, Result}}; + Error -> Error + end; + {error, {virtual, Nidx}} -> + case node_call(Host, Type, create_node, [Nidx, Owner]) of + {result, Result} -> {result, {Nidx, [], Result}}; + Error -> Error + end; + Error -> + Error + end; + _ -> + Txt = <<"You're not allowed to create nodes">>, + {error, xmpp:err_forbidden(Txt, ?MYLANG)} + end + end, + Reply = #pubsub{create = Node}, case transaction(Host, CreateNode, transaction) of {result, {Nidx, SubsByDepth, {Result, broadcast}}} -> broadcast_created_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth), @@ -1864,10 +1684,9 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> %%
  • The node is the root collection node, which cannot be deleted.
  • %%
  • The specified node does not exist.
  • %% --spec delete_node(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - Owner :: jid()) -> {result, [xmlel(),...]} | {error, xmlel()}. +-spec delete_node(host(), binary(), jid()) -> {result, pubsub()} | {error, error()}. delete_node(_Host, <<>>, _Owner) -> - {error, ?ERRT_NOT_ALLOWED(?MYLANG, <<"No node specified">>)}; + {error, xmpp:err_not_allowed(<<"No node specified">>, ?MYLANG)}; delete_node(Host, Node, Owner) -> Action = fun (#pubsub_node{type = Type, id = Nidx}) -> case node_call(Host, Type, get_affiliation, [Nidx, Owner]) of @@ -1879,7 +1698,7 @@ delete_node(Host, Node, Owner) -> Error -> Error end; _ -> - {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} + {error, xmpp:err_forbidden(<<"Owner privileges required">>, ?MYLANG)} end end, Reply = [], @@ -1941,16 +1760,15 @@ delete_node(Host, Node, Owner) -> %%
  • The node does not support subscriptions.
  • %%
  • The node does not exist.
  • %% --spec subscribe_node(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - From :: jid(), JID :: binary(), Configuration :: [xmlel()]) -> - {result, [xmlel(),...]} | {error, xmlel()}. +-spec subscribe_node(host(), binary(), jid(), binary(), [{binary(), [binary()]}]) -> + {result, pubsub()} | {error, error()}. subscribe_node(Host, Node, From, JID, Configuration) -> SubModule = subscription_plugin(Host), SubOpts = case SubModule:parse_options_xform(Configuration) of {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid end, - Subscriber = string_to_ljid(JID), + Subscriber = jid:tolower(JID), Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx, owners = O}) -> Features = plugin_features(Host, Type), SubscribeFeature = lists:member(<<"subscribe">>, Features), @@ -1976,21 +1794,21 @@ subscribe_node(Host, Node, From, JID, Configuration) -> true end, if not SubscribeFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscribe">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('subscribe'))}; not SubscribeConfig -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscribe">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('subscribe'))}; HasOptions andalso not OptionsFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscription-options">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('subscription-options'))}; SubOpts == invalid -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-options">>)}; + {error, extended_error(xmpp:err_bad_request(), + err_invalid_options())}; not CanSubscribe -> %% fallback to closest XEP compatible result, assume we are not allowed to subscribe - {error, - extended_error(?ERR_NOT_ALLOWED, <<"closed-node">>)}; + {error, extended_error(xmpp:err_not_allowed(), + err_closed_node())}; true -> Owners = node_owners_call(Host, Type, Nidx, O), {PS, RG} = get_presence_and_roster_permissions(Host, Subscriber, @@ -2001,19 +1819,13 @@ subscribe_node(Host, Node, From, JID, Configuration) -> end end, Reply = fun (Subscription) -> - SubAttrs = case Subscription of - {subscribed, SubId} -> - [{<<"subscription">>, subscription_to_string(subscribed)}, - {<<"subid">>, SubId}, {<<"node">>, Node}]; - Other -> - [{<<"subscription">>, subscription_to_string(Other)}, - {<<"node">>, Node}] - end, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"subscription">>, - attrs = [{<<"jid">>, jid:to_string(Subscriber)} - | SubAttrs]}]}] + Sub = case Subscription of + {subscribed, SubId} -> + #ps_subscription{type = subscribed, subid = SubId}; + Other -> + #ps_subscription{type = Other} + end, + #pubsub{subscription = Sub#ps_subscription{jid = Subscriber, node = Node}} end, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, subscribed, SubId, send_last}}} -> @@ -2052,14 +1864,10 @@ subscribe_node(Host, Node, From, JID, Configuration) -> %%
  • The node does not exist.
  • %%
  • The request specifies a subscription ID that is not valid or current.
  • %% --spec unsubscribe_node(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - From :: jid(), JID :: binary() | ljid(), - SubId :: mod_pubsub:subId()) -> - {result, []} | {error, xmlel()}. - -unsubscribe_node(Host, Node, From, JID, SubId) when is_binary(JID) -> - unsubscribe_node(Host, Node, From, string_to_ljid(JID), SubId); -unsubscribe_node(Host, Node, From, Subscriber, SubId) -> +-spec unsubscribe_node(host(), binary(), jid(), jid(), binary()) -> + {result, undefined} | {error, error()}. +unsubscribe_node(Host, Node, From, JID, SubId) -> + Subscriber = jid:tolower(JID), Action = fun (#pubsub_node{type = Type, id = Nidx}) -> node_call(Host, Type, unsubscribe_node, [Nidx, From, Subscriber, SubId]) end, @@ -2067,9 +1875,8 @@ unsubscribe_node(Host, Node, From, Subscriber, SubId) -> {result, {_, default}} -> ServerHost = serverhost(Host), ejabberd_hooks:run(pubsub_unsubscribe_node, ServerHost, - [ServerHost, Host, Node, Subscriber, SubId]), - {result, []}; - % {result, {_, Result}} -> {result, Result}; + [ServerHost, Host, Node, Subscriber, SubId]), + {result, undefined}; Error -> Error end. @@ -2084,12 +1891,8 @@ unsubscribe_node(Host, Node, From, Subscriber, SubId) -> %%
  • 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.
  • %%
  • The request does not match the node configuration.
  • %% --spec publish_item(Host :: mod_pubsub:host(), ServerHost :: binary(), - Node :: mod_pubsub:nodeId(), Publisher :: jid(), - ItemId :: <<>> | mod_pubsub:itemId(), - Payload :: mod_pubsub:payload()) -> - {result, [xmlel(),...]} | {error, xmlel()}. - +-spec publish_item(host(), binary(), binary(), jid(), binary(), + [xmlel()]) -> {result, pubsub()} | {error, error()}. publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, [], all). publish_item(Host, ServerHost, Node, Publisher, <<>>, Payload, PubOpts, Access) -> @@ -2106,34 +1909,31 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, PubOpts, Access PayloadSize = byte_size(term_to_binary(Payload)) - 2, PayloadMaxSize = get_option(Options, max_payload_size), if not PublishFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"publish">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported(publish))}; PayloadSize > PayloadMaxSize -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"payload-too-big">>)}; + {error, extended_error(xmpp:err_not_acceptable(), + err_payload_too_big())}; (PayloadCount == 0) and (Payload == []) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"payload-required">>)}; + {error, extended_error(xmpp:err_bad_request(), + err_payload_required())}; (PayloadCount > 1) or (PayloadCount == 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)}; + {error, extended_error(xmpp:err_bad_request(), + err_invalid_payload())}; (DeliverPayloads == false) and (PersistItems == false) and (PayloadSize > 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-forbidden">>)}; + {error, extended_error(xmpp:err_bad_request(), + err_item_forbidden())}; ((DeliverPayloads == true) or (PersistItems == true)) and (PayloadSize == 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; + {error, extended_error(xmpp:err_bad_request(), + err_item_required())}; true -> node_call(Host, Type, publish_item, [Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload, PubOpts]) end end, - Reply = [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"publish">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"item">>, - attrs = itemAttr(ItemId)}]}]}], + Reply = #pubsub{publish = #ps_publish{node = Node, + items = [#ps_item{id = ItemId}]}}, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, Broadcast, Removed}}} -> Nidx = TNode#pubsub_node.id, @@ -2175,29 +1975,20 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, PubOpts, Access {result, Reply}; {result, {_, Result}} -> {result, Result}; - {error, _} = Error -> - case is_item_not_found(Error) of + {error, #error{reason = 'item-not-found'}} -> + Type = select_type(ServerHost, Host, Node), + case lists:member(<<"auto-create">>, plugin_features(Host, Type)) of true -> - Type = select_type(ServerHost, Host, Node), - case lists:member(<<"auto-create">>, plugin_features(Host, Type)) of - true -> - case create_node(Host, ServerHost, Node, Publisher, Type, Access, []) of - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"create">>, - attrs = [{<<"node">>, NewNode}]}]}]} -> + case create_node(Host, ServerHost, Node, Publisher, Type, Access, []) of + {result, #pubsub{create = NewNode}} -> publish_item(Host, ServerHost, NewNode, Publisher, ItemId, - Payload, PubOpts, Access); - _ -> - {error, ?ERR_ITEM_NOT_FOUND} - end; - false -> - Txt = <<"Automatic node creation is not enabled">>, - {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, Txt)} + Payload, PubOpts, Access); + _ -> + {error, xmpp:err_item_not_found()} end; false -> - Error + Txt = <<"Automatic node creation is not enabled">>, + {error, xmpp:err_item_not_found(Txt, ?MYLANG)} end; Error -> Error @@ -2214,14 +2005,12 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, PubOpts, Access %%
  • The node does not support persistent items.
  • %%
  • The service does not support the deletion of items.
  • %% --spec delete_item(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - Publisher :: jid(), ItemId :: mod_pubsub:itemId()) -> - {result, []} | {error, xmlel()}. - +-spec delete_item(host(), binary(), jid(), binary()) -> {result, undefined} | + {error, error()}. delete_item(Host, Node, Publisher, ItemId) -> delete_item(Host, Node, Publisher, ItemId, false). delete_item(_, <<>>, _, _, _) -> - {error, extended_error(?ERR_BAD_REQUEST, <<"node-required">>)}; + {error, extended_error(xmpp:err_bad_request(), err_nodeid_required())}; delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx}) -> Features = plugin_features(Host, Type), @@ -2232,16 +2021,16 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %% %% Request does not specify an item %% {error, extended_error(?ERR_BAD_REQUEST, "item-required")}; not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('persistent-items'))}; not DeleteFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"delete-items">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('delete-items'))}; true -> node_call(Host, Type, delete_item, [Nidx, Publisher, PublishModel, ItemId]) end end, - Reply = [], + Reply = undefined, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, broadcast}}} -> Nidx = TNode#pubsub_node.id, @@ -2272,10 +2061,8 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %%
  • The node is not configured to persist items.
  • %%
  • The specified node does not exist.
  • %% --spec purge_node(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - Owner :: jid()) -> - {result, []} | {error, xmlel()}. - +-spec purge_node(mod_pubsub:host(), binary(), jid()) -> {result, undefined} | + {error, error()}. purge_node(Host, Node, Owner) -> Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx}) -> Features = plugin_features(Host, Type), @@ -2283,18 +2070,18 @@ purge_node(Host, Node, Owner) -> PersistentFeature = lists:member(<<"persistent-items">>, Features), PersistentConfig = get_option(Options, persist_items), if not PurgeFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"purge-nodes">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('purge-nodes'))}; not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('persistent-items'))}; not PersistentConfig -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('persistent-items'))}; true -> node_call(Host, Type, purge_node, [Nidx, Owner]) end end, - Reply = [], + Reply = undefined, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, broadcast}}} -> Nidx = TNode#pubsub_node.id, @@ -2319,71 +2106,57 @@ purge_node(Host, Node, Owner) -> %%

    The permission are not checked in this function.

    %% @todo We probably need to check that the user doing the query has the right %% to read the items. --spec get_items(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - From :: jid(), SubId :: mod_pubsub:subId(), - SMaxItems :: binary(), ItemIds :: [mod_pubsub:itemId()], - Rsm :: none | rsm_in()) -> - {result, [xmlel(),...]} | {error, xmlel()}. - +-spec get_items(host(), binary(), jid(), binary(), + binary(), [binary()], undefined | rsm_set()) -> + {result, pubsub()} | {error, error()}. get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> - MaxItems = if SMaxItems == <<>> -> - case get_max_items_node(Host) of - undefined -> ?MAXITEMS; - Max -> Max - end; - true -> - case catch jlib:binary_to_integer(SMaxItems) of - {'EXIT', _} -> - Txt = <<"Value of 'max_items' should be integer">>, - {error, ?ERRT_BAD_REQUEST(?MYLANG, Txt)}; - Val -> Val - end - end, - case MaxItems of - {error, Error} -> - {error, Error}; - _ -> - Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx, owners = O}) -> - Features = plugin_features(Host, 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, []), - if not RetreiveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"retrieve-items">>)}; - not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; - true -> - Owners = node_owners_call(Host, Type, Nidx, O), - {PS, RG} = get_presence_and_roster_permissions(Host, From, Owners, - AccessModel, AllowedGroups), - node_call(Host, Type, get_items, - [Nidx, From, AccessModel, PS, RG, SubId, RSM]) - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, {Items, RsmOut}}} -> - SendItems = case ItemIds of - [] -> - Items; - _ -> - lists:filter(fun (#pubsub_item{itemid = {ItemId, _}}) -> - lists:member(ItemId, ItemIds) - end, - Items) - end, - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = itemsEls(lists:sublist(SendItems, MaxItems))} - | jlib:rsm_encode(RsmOut)]}]}; - Error -> - Error - end + MaxItems = if SMaxItems == undefined -> + case get_max_items_node(Host) of + undefined -> ?MAXITEMS; + Max -> Max + end; + true -> + SMaxItems + end, + Action = + fun(#pubsub_node{options = Options, type = Type, + id = Nidx, owners = O}) -> + Features = plugin_features(Host, 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, []), + if not RetreiveFeature -> + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('retrieve-items'))}; + not PersistentFeature -> + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('persistent-items'))}; + true -> + Owners = node_owners_call(Host, Type, Nidx, O), + {PS, RG} = get_presence_and_roster_permissions( + Host, From, Owners, AccessModel, AllowedGroups), + node_call(Host, Type, get_items, + [Nidx, From, AccessModel, PS, RG, SubId, RSM]) + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, {Items, RsmOut}}} -> + SendItems = case ItemIds of + [] -> + Items; + _ -> + lists:filter( + fun(#pubsub_item{itemid = {ItemId, _}}) -> + lists:member(ItemId, ItemIds) + end, Items) + end, + {result, + #pubsub{items = #ps_items{node = Node, + items = itemsEls(lists:sublist(SendItems, MaxItems))}, + rsm = RsmOut}}; + Error -> + Error end. get_items(Host, Node) -> @@ -2487,227 +2260,200 @@ dispatch_items(From, To, _Node, Stanza) -> ejabberd_router:route(service_jid(From), jid:make(To), Stanza). %% @doc

    Return the list of affiliations as an XMPP response.

    --spec get_affiliations(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - JID :: jid(), Plugins :: [binary()]) -> - {result, [xmlel(),...]} | {error, xmlel()}. - +-spec get_affiliations(host(), binary(), jid(), [binary()]) -> + {result, pubsub()} | {error, error()}. get_affiliations(Host, Node, JID, Plugins) when is_list(Plugins) -> - Result = lists:foldl( fun (Type, {Status, Acc}) -> - Features = plugin_features(Host, Type), - RetrieveFeature = lists:member(<<"retrieve-affiliations">>, Features), - if not RetrieveFeature -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"retrieve-affiliations">>)}, - Acc}; - true -> - {result, Affs} = node_action(Host, Type, - get_entity_affiliations, - [Host, JID]), - {Status, [Affs | Acc]} - end - end, - {ok, []}, Plugins), + Result = + lists:foldl( + fun(Type, {Status, Acc}) -> + Features = plugin_features(Host, Type), + RetrieveFeature = lists:member(<<"retrieve-affiliations">>, Features), + if not RetrieveFeature -> + {{error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('retrieve-affiliations'))}, + Acc}; + true -> + {result, Affs} = node_action(Host, Type, + get_entity_affiliations, + [Host, JID]), + {Status, [Affs | Acc]} + end + end, + {ok, []}, Plugins), case Result of {ok, Affs} -> - Entities = lists:flatmap(fun - ({_, none}) -> - []; - ({#pubsub_node{nodeid = {_, NodeId}}, Aff}) -> - if (Node == <<>>) or (Node == NodeId) -> - [#xmlel{name = <<"affiliation">>, - attrs = [{<<"affiliation">>, affiliation_to_string(Aff)} - | nodeAttr(NodeId)]}]; - true -> - [] - end; - (_) -> - [] - end, - lists:usort(lists:flatten(Affs))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"affiliations">>, attrs = [], - children = Entities}]}]}; + Entities = lists:flatmap( + fun({_, none}) -> + []; + ({#pubsub_node{nodeid = {_, NodeId}}, Aff}) -> + if (Node == <<>>) or (Node == NodeId) -> + [#ps_affiliation{node = NodeId, + type = Aff}]; + true -> + [] + end; + (_) -> + [] + end, lists:usort(lists:flatten(Affs))), + {result, #pubsub{affiliations = {<<>>, Entities}}}; {Error, _} -> Error end. --spec get_affiliations(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - JID :: jid()) -> - {result, [xmlel(),...]} | {error, xmlel()}. - +-spec get_affiliations(host(), binary(), jid()) -> + {result, pubsub_owner()} | {error, error()}. get_affiliations(Host, Node, JID) -> - Action = fun (#pubsub_node{type = Type, id = Nidx}) -> - Features = plugin_features(Host, Type), - RetrieveFeature = lists:member(<<"modify-affiliations">>, Features), - {result, Affiliation} = node_call(Host, Type, get_affiliation, [Nidx, JID]), - if not RetrieveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"modify-affiliations">>)}; - Affiliation /= owner -> - {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)}; - true -> - node_call(Host, Type, get_node_affiliations, [Nidx]) - end - end, + Action = + fun(#pubsub_node{type = Type, id = Nidx}) -> + Features = plugin_features(Host, Type), + RetrieveFeature = lists:member(<<"modify-affiliations">>, Features), + {result, Affiliation} = node_call(Host, Type, get_affiliation, [Nidx, JID]), + if not RetrieveFeature -> + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('modify-affiliations'))}; + Affiliation /= owner -> + {error, xmpp:err_forbidden(<<"Owner privileges required">>, ?MYLANG)}; + true -> + node_call(Host, Type, get_node_affiliations, [Nidx]) + end + end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, []}} -> - {error, ?ERR_ITEM_NOT_FOUND}; + {error, xmpp:err_item_not_found()}; {result, {_, Affs}} -> - Entities = lists:flatmap(fun - ({_, none}) -> - []; - ({AJID, Aff}) -> - [#xmlel{name = <<"affiliation">>, - attrs = [{<<"jid">>, jid:to_string(AJID)}, - {<<"affiliation">>, affiliation_to_string(Aff)}]}] - end, - Affs), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = [#xmlel{name = <<"affiliations">>, - attrs = nodeAttr(Node), children = Entities}]}]}; + Entities = lists:flatmap( + fun({_, none}) -> + []; + ({AJID, Aff}) -> + [#ps_affiliation{jid = AJID, type = Aff}] + end, Affs), + {result, #pubsub_owner{affiliations = {Node, Entities}}}; Error -> Error end. --spec set_affiliations(Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), - From :: jid(), EntitiesEls :: [xmlel()]) -> - {result, []} | {error, xmlel()}. - -set_affiliations(Host, Node, From, EntitiesEls) -> +-spec set_affiliations(host(), binary(), jid(), [ps_affiliation()]) -> + {result, undefined} | {error, error()}. +set_affiliations(Host, Node, From, Affs) -> Owner = jid:tolower(jid:remove_resource(From)), - Entities = lists:foldl(fun - (_, error) -> - error; - (El, Acc) -> - case El of - #xmlel{name = <<"affiliation">>, attrs = Attrs} -> - JID = jid:from_string(fxml:get_attr_s(<<"jid">>, Attrs)), - Affiliation = string_to_affiliation(fxml:get_attr_s(<<"affiliation">>, Attrs)), - if (JID == error) or (Affiliation == false) -> error; - true -> [{jid:tolower(JID), Affiliation} | Acc] - end - end - end, - [], EntitiesEls), - case Entities of - error -> - {error, ?ERR_BAD_REQUEST}; - _ -> - Action = fun (#pubsub_node{type = Type, id = Nidx, owners = O} = N) -> - Owners = node_owners_call(Host, Type, Nidx, O), - case lists:member(Owner, Owners) of - true -> - OwnerJID = jid:make(Owner), - FilteredEntities = case Owners of - [Owner] -> [E || E <- Entities, element(1, E) =/= OwnerJID]; - _ -> Entities + Action = + fun(#pubsub_node{type = Type, id = Nidx, owners = O} = N) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case lists:member(Owner, Owners) of + true -> + OwnerJID = jid:make(Owner), + FilteredAffs = + case Owners of + [Owner] -> + [Aff || Aff <- Affs, + Aff#ps_affiliation.jid /= OwnerJID]; + _ -> + Affs end, - lists:foreach(fun ({JID, Affiliation}) -> - node_call(Host, Type, set_affiliation, [Nidx, JID, Affiliation]), - case Affiliation of - owner -> - NewOwner = jid:tolower(jid:remove_resource(JID)), - NewOwners = [NewOwner | Owners], - tree_call(Host, + lists:foreach( + fun(#ps_affiliation{jid = JID, type = Affiliation}) -> + node_call(Host, Type, set_affiliation, [Nidx, JID, Affiliation]), + case Affiliation of + owner -> + NewOwner = jid:tolower(jid:remove_resource(JID)), + NewOwners = [NewOwner | Owners], + tree_call(Host, set_node, [N#pubsub_node{owners = NewOwners}]); - none -> - OldOwner = jid:tolower(jid:remove_resource(JID)), - case lists:member(OldOwner, Owners) of - true -> - NewOwners = Owners -- [OldOwner], - tree_call(Host, + none -> + OldOwner = jid:tolower(jid:remove_resource(JID)), + case lists:member(OldOwner, Owners) of + true -> + NewOwners = Owners -- [OldOwner], + tree_call(Host, set_node, [N#pubsub_node{owners = NewOwners}]); - _ -> - ok - end; - _ -> - ok - end - end, - FilteredEntities), - {result, []}; - _ -> - {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end + _ -> + ok + end; + _ -> + ok + end + end, FilteredAffs), + {result, undefined}; + _ -> + {error, xmpp:err_forbidden( + <<"Owner privileges required">>, ?MYLANG)} + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other end. +-spec get_options(binary(), binary(), jid(), binary(), binary()) -> + {result, xdata()} | {error, error()}. get_options(Host, Node, JID, SubId, Lang) -> Action = fun (#pubsub_node{type = Type, id = Nidx}) -> case lists:member(<<"subscription-options">>, plugin_features(Host, Type)) of true -> get_options_helper(Host, JID, Lang, Node, Nidx, SubId, Type); false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscription-options">>)} + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('subscription-options'))} end end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_Node, XForm}} -> {result, [XForm]}; + {result, {_Node, XForm}} -> {result, XForm}; Error -> Error end. +-spec get_options_helper(binary(), jid(), binary(), binary(), _, binary(), + binary()) -> {result, pubsub()} | {error, error()}. get_options_helper(Host, JID, Lang, Node, Nidx, SubId, Type) -> - Subscriber = string_to_ljid(JID), + Subscriber = jid:tolower(JID), {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), SubIds = [Id || {Sub, Id} <- Subs, Sub == subscribed], case {SubId, SubIds} of {_, []} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"not-subscribed">>)}; + {error, extended_error(xmpp:err_not_acceptable(), + err_not_subscribed())}; {<<>>, [SID]} -> read_sub(Host, Node, Nidx, Subscriber, SID, Lang); {<<>>, _} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"subid-required">>)}; + {error, extended_error(xmpp:err_not_acceptable(), + err_subid_required())}; {_, _} -> ValidSubId = lists:member(SubId, SubIds), if ValidSubId -> read_sub(Host, Node, Nidx, Subscriber, SubId, Lang); true -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)} + {error, extended_error(xmpp:err_not_acceptable(), + err_invalid_subid())} end end. +-spec read_sub(binary(), binary(), nodeIdx(), ljid(), binary(), binary()) -> {result, pubsub()}. read_sub(Host, Node, Nidx, Subscriber, SubId, Lang) -> SubModule = subscription_plugin(Host), - Children = case SubModule:get_subscription(Subscriber, Nidx, SubId) of - {error, notfound} -> - []; - {result, #pubsub_subscription{options = Options}} -> - {result, XdataEl} = SubModule:get_options_xform(Lang, Options), - [XdataEl] - end, - OptionsEl = #xmlel{name = <<"options">>, - attrs = [{<<"jid">>, jid:to_string(Subscriber)}, - {<<"subid">>, SubId} - | nodeAttr(Node)], - children = Children}, - PubsubEl = #xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [OptionsEl]}, - {result, PubsubEl}. + XData = case SubModule:get_subscription(Subscriber, Nidx, SubId) of + {error, notfound} -> + undefined; + {result, #pubsub_subscription{options = Options}} -> + {result, X} = SubModule:get_options_xform(Lang, Options), + X + end, + {result, #pubsub{options = #ps_options{jid = jid:make(Subscriber), + subid = SubId, + node = Node, + xdata = XData}}}. +-spec set_options(binary(), binary(), jid(), binary(), + [{binary(), [binary()]}]) -> + {result, undefined} | {error, error()}. set_options(Host, Node, JID, SubId, Configuration) -> Action = fun (#pubsub_node{type = Type, id = Nidx}) -> case lists:member(<<"subscription-options">>, plugin_features(Host, Type)) of true -> set_options_helper(Host, Configuration, JID, Nidx, SubId, Type); false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscription-options">>)} + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('subscription-options'))} end end, case transaction(Host, Node, Action, sync_dirty) of @@ -2715,56 +2461,53 @@ set_options(Host, Node, JID, SubId, Configuration) -> Error -> Error end. +-spec set_options_helper(binary(), [{binary(), [binary()]}], jid(), + nodeIdx(), binary(), binary()) -> + {result, undefined} | {error, error()}. set_options_helper(Host, Configuration, JID, Nidx, SubId, Type) -> SubModule = subscription_plugin(Host), SubOpts = case SubModule:parse_options_xform(Configuration) of {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid end, - Subscriber = string_to_ljid(JID), + Subscriber = jid:tolower(JID), {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), SubIds = [Id || {Sub, Id} <- Subs, Sub == subscribed], case {SubId, SubIds} of {_, []} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"not-subscribed">>)}; + {error, extended_error(xmpp:err_not_acceptable(), err_not_subscribed())}; {<<>>, [SID]} -> write_sub(Host, Nidx, Subscriber, SID, SubOpts); {<<>>, _} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"subid-required">>)}; + {error, extended_error(xmpp:err_not_acceptable(), err_subid_required())}; {_, _} -> write_sub(Host, Nidx, Subscriber, SubId, SubOpts) end. +-spec write_sub(binary(), nodeIdx(), ljid(), binary(), _) -> {result, undefined} | + {error, error()}. write_sub(_Host, _Nidx, _Subscriber, _SubId, invalid) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-options">>)}; + {error, extended_error(xmpp:err_bad_request(), err_invalid_options())}; write_sub(_Host, _Nidx, _Subscriber, _SubId, []) -> - {result, []}; + {result, undefined}; write_sub(Host, Nidx, Subscriber, SubId, Options) -> SubModule = subscription_plugin(Host), case SubModule:set_subscription(Subscriber, Nidx, SubId, Options) of - {result, _} -> {result, []}; - {error, _} -> {error, extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)} + {result, _} -> {result, undefined}; + {error, _} -> {error, extended_error(xmpp:err_not_acceptable(), + err_invalid_subid())} end. -%% @spec (Host, Node, JID, Plugins) -> {error, Reason} | {result, Response} -%% Host = host() -%% Node = pubsubNode() -%% JID = jid() -%% Plugins = [Plugin::string()] -%% Reason = stanzaError() -%% Response = [pubsubIQResponse()] %% @doc

    Return the list of subscriptions as an XMPP response.

    +-spec get_subscriptions(host(), binary(), jid(), [binary()]) -> + {result, pubsub()} | {error, error()}. get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> Result = lists:foldl(fun (Type, {Status, Acc}) -> Features = plugin_features(Host, Type), RetrieveFeature = lists:member(<<"retrieve-subscriptions">>, Features), if not RetrieveFeature -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"retrieve-subscriptions">>)}, + {{error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('retrieve-subscriptions'))}, Acc}; true -> Subscriber = jid:remove_resource(JID), @@ -2783,14 +2526,9 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Sub}) -> case Node of <<>> -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"subscription">>, subscription_to_string(Sub)} - | nodeAttr(SubsNode)]}]; + [#ps_subscription{node = SubsNode, type = Sub}]; SubsNode -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"subscription">>, subscription_to_string(Sub)}]}]; + [#ps_subscription{type = Sub}]; _ -> [] end; @@ -2799,88 +2537,65 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Sub, SubId, SubJID}) -> case Node of <<>> -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jid:to_string(SubJID)}, - {<<"subid">>, SubId}, - {<<"subscription">>, subscription_to_string(Sub)} - | nodeAttr(SubsNode)]}]; + [#ps_subscription{jid = SubJID, + subid = SubId, + type = Sub, + node = SubsNode}]; SubsNode -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jid:to_string(SubJID)}, - {<<"subid">>, SubId}, - {<<"subscription">>, subscription_to_string(Sub)}]}]; + [#ps_subscription{jid = SubJID, + subid = SubId, + type = Sub}]; _ -> [] end; ({#pubsub_node{nodeid = {_, SubsNode}}, Sub, SubJID}) -> case Node of <<>> -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jid:to_string(SubJID)}, - {<<"subscription">>, subscription_to_string(Sub)} - | nodeAttr(SubsNode)]}]; + [#ps_subscription{jid = SubJID, + type = Sub, + node = SubsNode}]; SubsNode -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jid:to_string(SubJID)}, - {<<"subscription">>, subscription_to_string(Sub)}]}]; + [#ps_subscription{jid = SubJID, type = Sub}]; _ -> [] end end, lists:usort(lists:flatten(Subs))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"subscriptions">>, attrs = [], - children = Entities}]}]}; + {result, #pubsub{subscriptions = {<<>>, Entities}}}; {Error, _} -> Error end. +-spec get_subscriptions(binary(), binary(), jid()) -> {result, pubsub()} | + {error, error()}. get_subscriptions(Host, Node, JID) -> Action = fun (#pubsub_node{type = Type, id = Nidx}) -> Features = plugin_features(Host, Type), RetrieveFeature = lists:member(<<"manage-subscriptions">>, Features), {result, Affiliation} = node_call(Host, Type, get_affiliation, [Nidx, JID]), if not RetrieveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"manage-subscriptions">>)}; + {error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('manage-subscriptions'))}; Affiliation /= owner -> - {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)}; + {error, xmpp:err_forbidden(<<"Owner privileges required">>, ?MYLANG)}; true -> node_call(Host, Type, get_node_subscriptions, [Nidx]) end end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Subs}} -> - Entities = lists:flatmap(fun - ({_, none}) -> - []; - ({_, pending, _}) -> - []; - ({AJID, Sub}) -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jid:to_string(AJID)}, - {<<"subscription">>, subscription_to_string(Sub)}]}]; + Entities = + lists:flatmap( + fun({_, none}) -> + []; + ({_, pending, _}) -> + []; + ({AJID, Sub}) -> + [#ps_subscription{jid = AJID, type = Sub}]; ({AJID, Sub, SubId}) -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jid:to_string(AJID)}, - {<<"subscription">>, subscription_to_string(Sub)}, - {<<"subid">>, SubId}]}] - end, - Subs), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = [#xmlel{name = <<"subscriptions">>, - attrs = nodeAttr(Node), - children = Entities}]}]}; + [#ps_subscription{jid = AJID, type = Sub, subid = SubId}] + end, Subs), + {result, #pubsub{subscriptions = {Node, Entities}}}; Error -> Error end. @@ -2908,78 +2623,55 @@ get_subscriptions_for_send_last(Host, PType, sql, JID, LJID, BJID) -> get_subscriptions_for_send_last(_Host, _PType, _, _JID, _LJID, _BJID) -> []. -set_subscriptions(Host, Node, From, EntitiesEls) -> +set_subscriptions(Host, Node, From, Entities) -> Owner = jid:tolower(jid:remove_resource(From)), - Entities = lists:foldl(fun - (_, error) -> - error; - (El, Acc) -> - case El of - #xmlel{name = <<"subscription">>, attrs = Attrs} -> - JID = jid:from_string(fxml:get_attr_s(<<"jid">>, Attrs)), - Sub = string_to_subscription(fxml:get_attr_s(<<"subscription">>, Attrs)), - SubId = fxml:get_attr_s(<<"subid">>, Attrs), - if (JID == error) or (Sub == false) -> error; - true -> [{jid:tolower(JID), Sub, SubId} | Acc] - end - end - end, - [], EntitiesEls), - case Entities of - error -> - {error, ?ERR_BAD_REQUEST}; - _ -> - Notify = fun (JID, Sub, _SubId) -> - Stanza = #xmlel{name = <<"message">>, attrs = [], - children = - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"subscription">>, - attrs = [{<<"jid">>, jid:to_string(JID)}, - {<<"subscription">>, subscription_to_string(Sub)} - | nodeAttr(Node)]}]}]}, - ejabberd_router:route(service_jid(Host), jid:make(JID), Stanza) - end, - Action = fun (#pubsub_node{type = Type, id = Nidx, owners = O}) -> - Owners = node_owners_call(Host, Type, Nidx, O), - case lists:member(Owner, Owners) of - true -> - Result = lists:foldl(fun ({JID, Sub, SubId}, Acc) -> - case - node_call(Host, Type, - set_subscriptions, - [Nidx, JID, Sub, SubId]) - of - {error, Err} -> - [{error, Err} | Acc]; - _ -> - Notify(JID, Sub, SubId), - Acc - end - end, - [], Entities), - case Result of - [] -> {result, []}; - [{error, E}|_] -> {error, E} - end; - _ -> - {error, ?ERRT_FORBIDDEN(?MYLANG, <<"You're not an owner">>)} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end + Notify = fun(#ps_subscription{jid = JID, type = Sub}) -> + Stanza = #message{ + sub_els = [#pubsub{ + subscription = #ps_subscription{ + jid = JID, + type = Sub, + node = Node}}]}, + ejabberd_router:route(service_jid(Host), JID, Stanza) + end, + Action = + fun(#pubsub_node{type = Type, id = Nidx, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case lists:member(Owner, Owners) of + true -> + Result = + lists:foldl( + fun(_, {error, _} = Err) -> + Err; + (#ps_subscription{jid = JID, type = Sub, + subid = SubId} = Entity, _) -> + case node_call(Host, Type, + set_subscriptions, + [Nidx, JID, Sub, SubId]) of + {error, _} = Err -> + Err; + _ -> + Notify(Entity) + end + end, ok, Entities), + case Result of + ok -> {result, undefined}; + {error, _} = Err -> Err + end; + _ -> + {error, xmpp:err_forbidden( + <<"Owner privileges required">>, ?MYLANG)} + + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other end. --spec get_presence_and_roster_permissions(Host :: mod_pubsub:host(), - From :: ljid(), Owners :: [ljid(),...], - AccessModel :: mod_pubsub:accessModel(), - AllowedGroups :: [binary()]) -> - {PresenceSubscription::boolean(), - RosterGroup::boolean()}. - +-spec get_presence_and_roster_permissions( + host(), ljid(), [ljid()], accessModel(), + [binary()]) -> {boolean(), boolean()}. get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) -> if (AccessModel == presence) or (AccessModel == roster) -> case Host of @@ -3037,10 +2729,10 @@ subscription_to_string(pending) -> <<"pending">>; subscription_to_string(unconfigured) -> <<"unconfigured">>; subscription_to_string(_) -> <<"none">>. --spec service_jid(Host :: mod_pubsub:host()) -> jid(). +-spec service_jid(jid() | ljid() | binary()) -> jid(). service_jid(#jid{} = Jid) -> Jid; service_jid({U, S, R}) -> jid:make(U, S, R); -service_jid(Host) -> jid:make(<<>>, Host, <<>>). +service_jid(Host) -> jid:make(Host). %% @spec (LJID, NotifyType, Depth, NodeOptions, SubOptions) -> boolean() %% LJID = jid() @@ -3071,7 +2763,7 @@ sub_option_can_deliver(_, _, {deliver, false}) -> false; sub_option_can_deliver(_, _, {expire, When}) -> p1_time_compat:timestamp() < When; sub_option_can_deliver(_, _, _) -> true. --spec presence_can_deliver(Entity :: ljid(), _ :: boolean()) -> boolean(). +-spec presence_can_deliver(ljid(), boolean()) -> boolean(). presence_can_deliver(_, false) -> true; presence_can_deliver({User, Server, Resource}, true) -> @@ -3092,10 +2784,7 @@ presence_can_deliver({User, Server, Resource}, true) -> false, Ss) end. --spec state_can_deliver(Entity::ljid(), - SubOptions :: mod_pubsub:subOptions() | []) -> - [ljid()]. - +-spec state_can_deliver(ljid(), subOptions() | []) -> [ljid()]. state_can_deliver({U, S, R}, []) -> [{U, S, R}]; state_can_deliver({U, S, R}, SubOptions) -> case lists:keysearch(show_values, 1, SubOptions) of @@ -3115,10 +2804,7 @@ state_can_deliver({U, S, R}, SubOptions) -> [], Resources) end. --spec get_resource_state(Entity :: ljid(), ShowValues :: [binary()], - JIDs :: [ljid()]) -> - [ljid()]. - +-spec get_resource_state(ljid(), [binary()], [ljid()]) -> [ljid()]. get_resource_state({U, S, R}, ShowValues, JIDs) -> case ejabberd_sm:get_session_pid(U, S, R) of none -> @@ -3137,8 +2823,7 @@ get_resource_state({U, S, R}, ShowValues, JIDs) -> end end. --spec payload_xmlelements(Payload :: mod_pubsub:payload()) -> - Count :: non_neg_integer(). +-spec payload_xmlelements([xmlel()]) -> non_neg_integer(). payload_xmlelements(Payload) -> payload_xmlelements(Payload, 0). @@ -3152,63 +2837,55 @@ items_event_stanza(Node, Options, Items) -> MoreEls = case Items of [LastItem] -> {ModifNow, ModifUSR} = LastItem#pubsub_item.modification, - DateTime = calendar:now_to_datetime(ModifNow), - {T_string, Tz_string} = jlib:timestamp_to_iso(DateTime, utc), - [#xmlel{name = <<"delay">>, attrs = [{<<"xmlns">>, ?NS_DELAY}, - {<<"from">>, jid:to_string(ModifUSR)}, - {<<"stamp">>, <>}], - children = [{xmlcdata, <<>>}]}]; + [#delay{stamp = ModifNow, from = jid:make(ModifUSR)}]; _ -> [] end, - BaseStanza = event_stanza_with_els([#xmlel{name = <<"items">>, - attrs = nodeAttr(Node), - children = itemsEls(Items)}], - MoreEls), + BaseStanza = #message{ + sub_els = [#ps_event{items = #ps_items{ + node = Node, + items = itemsEls(Items)}} + | MoreEls]}, NotificationType = get_option(Options, notification_type, headline), add_message_type(BaseStanza, NotificationType). -event_stanza(Els) -> - event_stanza_with_els(Els, []). -event_stanza_with_els(Els, MoreEls) -> - #xmlel{name = <<"message">>, attrs = [], - children = [#xmlel{name = <<"event">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}], - children = Els} - | MoreEls]}. - -event_stanza(Event, EvAttr) -> - event_stanza_with_els([#xmlel{name = Event, attrs = EvAttr}], []). - %%%%%% broadcast functions broadcast_publish_item(Host, Node, Nidx, Type, NodeOptions, ItemId, From, Payload, Removed) -> case get_collection_subscriptions(Host, Node) of SubsByDepth when is_list(SubsByDepth) -> - Content = case get_option(NodeOptions, deliver_payloads) of - true -> Payload; - false -> [] - end, - Attrs = case get_option(NodeOptions, itemreply, none) of - owner -> itemAttr(ItemId); %% owner not supported - publisher -> itemAttr(ItemId, {<<"publisher">>, jid:to_string(From)}); - none -> itemAttr(ItemId) - end, - Stanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"item">>, attrs = Attrs, - children = Content}]}]), + EventItem0 = case get_option(NodeOptions, deliver_payloads) of + true -> #ps_item{xml_els = Payload, id = ItemId}; + false -> #ps_item{id = ItemId} + end, + EventItem = case get_option(NodeOptions, itemreply, none) of + owner -> %% owner not supported + EventItem0; + publisher -> + EventItem0#ps_item{ + publisher = jid:to_string(From)}; + none -> + EventItem0 + end, + Stanza = #message{ + sub_els = + [#ps_event{items = + #ps_items{node = Node, + items = [EventItem]}}]}, broadcast_stanza(Host, From, Node, Nidx, Type, - NodeOptions, SubsByDepth, items, Stanza, true), + NodeOptions, SubsByDepth, items, Stanza, true), case Removed of [] -> ok; _ -> case get_option(NodeOptions, notify_retract) of true -> - RetractStanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"retract">>, attrs = itemAttr(RId)} || RId <- Removed]}]), + RetractStanza = #message{ + sub_els = + [#ps_event{ + items = #ps_items{ + node = Node, + retract = Removed}}]}, broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, items, RetractStanza, true); @@ -3230,9 +2907,12 @@ broadcast_retract_items(Host, Node, Nidx, Type, NodeOptions, ItemIds, ForceNotif true -> case get_collection_subscriptions(Host, Node) of SubsByDepth when is_list(SubsByDepth) -> - Stanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"retract">>, attrs = itemAttr(ItemId)} || ItemId <- ItemIds]}]), + Stanza = #message{ + sub_els = + [#ps_event{ + items = #ps_items{ + node = Node, + retract = ItemIds}}]}, broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, items, Stanza, true), {result, true}; @@ -3248,8 +2928,7 @@ broadcast_purge_node(Host, Node, Nidx, Type, NodeOptions) -> true -> case get_collection_subscriptions(Host, Node) of SubsByDepth when is_list(SubsByDepth) -> - Stanza = event_stanza( - [#xmlel{name = <<"purge">>, attrs = nodeAttr(Node)}]), + Stanza = #message{sub_els = [#ps_event{purge = Node}]}, broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true}; @@ -3267,8 +2946,7 @@ broadcast_removed_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth) -> [] -> {result, false}; _ -> - Stanza = event_stanza( - [#xmlel{name = <<"delete">>, attrs = nodeAttr(Node)}]), + Stanza = #message{sub_els = [#ps_event{delete = {Node, <<>>}}]}, broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true} @@ -3280,7 +2958,7 @@ broadcast_removed_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth) -> broadcast_created_node(_, _, _, _, _, []) -> {result, false}; broadcast_created_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth) -> - Stanza = event_stanza([#xmlel{name = <<"create">>, attrs = nodeAttr(Node)}]), + Stanza = #message{sub_els = [#ps_event{create = Node}]}, broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, true), {result, true}. @@ -3291,13 +2969,15 @@ broadcast_config_notification(Host, Node, Nidx, Type, NodeOptions, Lang) -> SubsByDepth when is_list(SubsByDepth) -> Content = case get_option(NodeOptions, deliver_payloads) of true -> - [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], - children = get_configure_xfields(Type, NodeOptions, Lang, [])}]; + #xdata{type = result, + fields = get_configure_xfields( + Type, NodeOptions, Lang, [])}; false -> - [] + undefined end, - Stanza = event_stanza( - [#xmlel{name = <<"configuration">>, attrs = nodeAttr(Node), children = Content}]), + Stanza = #message{ + sub_els = [#ps_event{ + configuration = {Node, Content}}]}, broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true}; @@ -3389,8 +3069,9 @@ broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, Nidx, Type, NodeO ejabberd_c2s:broadcast(C2SPid, {pep_message, <<((Node))/binary, "+notify">>}, _Sender = jid:make(LUser, LServer, <<"">>), - _StanzaToSend = add_extended_headers(Stanza, - _ReplyTo = extended_headers([jid:to_string(Publisher)]))); + _StanzaToSend = add_extended_headers( + Stanza, + _ReplyTo = extended_headers([Publisher]))); _ -> ?DEBUG("~p@~p has no session; can't deliver ~p to contacts", [LUser, LServer, BaseStanza]) end; @@ -3456,9 +3137,11 @@ subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> {_, JIDSubs} = lists:foldl(DepthsToDeliver, {[], []}, SubsByDepth), JIDSubs. +-spec user_resources(binary(), binary()) -> [binary()]. user_resources(User, Server) -> ejabberd_sm:get_user_resources(User, Server). +-spec user_resource(binary(), binary(), binary()) -> binary(). user_resource(User, Server, <<>>) -> case user_resources(User, Server) of [R | _] -> R; @@ -3468,26 +3151,19 @@ user_resource(_, _, Resource) -> Resource. %%%%%%% Configuration handling - +-spec get_configure(host(), binary(), binary(), jid(), + binary()) -> {error, error()} | {result, pubsub()}. 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 {result, owner} -> Groups = ejabberd_hooks:run_fold(roster_groups, ServerHost, [], [ServerHost]), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"configure">>, - attrs = nodeAttr(Node), - children = - [#xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - get_configure_xfields(Type, Options, Lang, Groups)}]}]}]}; + Fs = get_configure_xfields(Type, Options, Lang, Groups), + {result, #pubsub_owner{ + configure = + {Node, #xdata{type = form, fields = Fs}}}}; _ -> - {error, ?ERRT_FORBIDDEN(Lang, <<"You're not an owner">>)} + {error, xmpp:err_forbidden(<<"Owner privileges required">>, Lang)} end end, case transaction(Host, Node, Action, sync_dirty) of @@ -3495,20 +3171,14 @@ get_configure(Host, ServerHost, Node, From, Lang) -> Other -> Other end. +-spec get_default(host(), binary(), jid(), binary()) -> {result, pubsub()}. get_default(Host, Node, _From, Lang) -> Type = select_type(Host, Host, Node), Options = node_options(Host, Type), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"default">>, attrs = [], - children = - [#xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = get_configure_xfields(Type, Options, Lang, [])}]}]}]}. + Fs = get_configure_xfields(Type, Options, Lang, []), + {result, #pubsub_owner{default = {<<>>, #xdata{type = form, fields = Fs}}}}. +-spec match_option(#pubsub_node{} | [{atom(), any()}], atom(), any()) -> boolean(). match_option(Node, Var, Val) when is_record(Node, pubsub_node) -> match_option(Node#pubsub_node.options, Var, Val); match_option(Options, Var, Val) when is_list(Options) -> @@ -3516,21 +3186,26 @@ match_option(Options, Var, Val) when is_list(Options) -> match_option(_, _, _) -> false. +-spec get_option([{atom(), any()}], atom()) -> any(). get_option([], _) -> false; get_option(Options, Var) -> get_option(Options, Var, false). +-spec get_option([{atom(), any()}], atom(), any()) -> any(). get_option(Options, Var, Def) -> case lists:keysearch(Var, 1, Options) of {value, {_Val, Ret}} -> Ret; _ -> Def end. +-spec node_options(host(), binary()) -> [{atom(), any()}]. node_options(Host, Type) -> case config(Host, default_node_config) of undefined -> node_plugin_options(Host, Type); [] -> node_plugin_options(Host, Type); Config -> Config end. + +-spec node_plugin_options(host(), binary()) -> [{atom(), any()}]. node_plugin_options(Host, Type) -> Module = plugin(Host, Type), case catch Module:options() of @@ -3540,12 +3215,15 @@ node_plugin_options(Host, Type) -> Result -> Result end. + +-spec filter_node_options([{atom(), any()}], [{atom(), any()}]) -> [{atom(), any()}]. filter_node_options(Options, BaseOptions) -> lists:foldl(fun({Key, Val}, Acc) -> DefaultValue = proplists:get_value(Key, Options, Val), [{Key, DefaultValue}|Acc] end, [], BaseOptions). +-spec node_owners_action(host(), binary(), nodeIdx(), [ljid()]) -> [ljid()]. node_owners_action(Host, Type, Nidx, []) -> case gen_mod:db_type(serverhost(Host), ?MODULE) of sql -> @@ -3559,6 +3237,7 @@ node_owners_action(Host, Type, Nidx, []) -> node_owners_action(_Host, _Type, _Nidx, Owners) -> Owners. +-spec node_owners_call(host(), binary(), nodeIdx(), [ljid()]) -> [ljid()]. node_owners_call(Host, Type, Nidx, []) -> case gen_mod:db_type(serverhost(Host), ?MODULE) of sql -> @@ -3583,6 +3262,7 @@ node_owners_call(_Host, _Type, _Nidx, Owners) -> %% @todo In practice, the current data structure means that we cannot manage %% millions of items on a given node. This should be addressed in a new %% version. +-spec max_items(host(), [{atom(), any()}]) -> non_neg_integer(). max_items(Host, Options) -> case get_option(Options, persist_items) of true -> @@ -3625,10 +3305,10 @@ max_items(Host, Options) -> [jid:to_string(O) || O <- Opts])). -define(ALIST_CONFIG_FIELD(Label, Var, Opts), - ?LISTXFIELD(Label, - <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, - (atom_to_binary(get_option(Options, Var), latin1)), - [atom_to_binary(O, latin1) || O <- Opts])). + ?LISTXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + (atom_to_binary(get_option(Options, Var), latin1)), + [atom_to_binary(O, latin1) || O <- Opts])). -define(LISTM_CONFIG_FIELD(Label, Var, Opts), ?LISTMXFIELD(Label, @@ -3641,45 +3321,45 @@ max_items(Host, Options) -> get_option(Options, Var, []))). get_configure_xfields(_Type, Options, Lang, Groups) -> - [?XFIELD(<<"hidden">>, <<>>, <<"FORM_TYPE">>, (?NS_PUBSUB_NODE_CONFIG)), - ?BOOL_CONFIG_FIELD(<<"Deliver payloads with event notifications">>, - deliver_payloads), - ?BOOL_CONFIG_FIELD(<<"Deliver event notifications">>, - deliver_notifications), - ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node configuration changes">>, - notify_config), - ?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, [open, authorize, presence, roster, whitelist]), - ?LISTM_CONFIG_FIELD(<<"Roster groups allowed to subscribe">>, - roster_groups_allowed, Groups), - ?ALIST_CONFIG_FIELD(<<"Specify the publisher model">>, - publish_model, [publishers, subscribers, open]), - ?BOOL_CONFIG_FIELD(<<"Purge all items when the relevant publisher goes offline">>, - purge_offline), - ?ALIST_CONFIG_FIELD(<<"Specify the event message type">>, - notification_type, [headline, normal]), - ?INTEGER_CONFIG_FIELD(<<"Max payload size in bytes">>, - max_payload_size), - ?ALIST_CONFIG_FIELD(<<"When to send the last published item">>, - send_last_published_item, [never, on_sub, on_sub_and_presence]), - ?BOOL_CONFIG_FIELD(<<"Only deliver notifications to available users">>, - presence_based_delivery), - ?NLIST_CONFIG_FIELD(<<"The collections with which a node is affiliated">>, - collection), - ?ALIST_CONFIG_FIELD(<<"Whether owners or publisher should receive replies to items">>, - itemreply, [none, owner, publisher])]. + [?XFIELD(hidden, <<>>, <<"FORM_TYPE">>, ?NS_PUBSUB_NODE_CONFIG), + ?BOOL_CONFIG_FIELD(<<"Deliver payloads with event notifications">>, + deliver_payloads), + ?BOOL_CONFIG_FIELD(<<"Deliver event notifications">>, + deliver_notifications), + ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node configuration changes">>, + notify_config), + ?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, [open, authorize, presence, roster, whitelist]), + ?LISTM_CONFIG_FIELD(<<"Roster groups allowed to subscribe">>, + roster_groups_allowed, Groups), + ?ALIST_CONFIG_FIELD(<<"Specify the publisher model">>, + publish_model, [publishers, subscribers, open]), + ?BOOL_CONFIG_FIELD(<<"Purge all items when the relevant publisher goes offline">>, + purge_offline), + ?ALIST_CONFIG_FIELD(<<"Specify the event message type">>, + notification_type, [headline, normal]), + ?INTEGER_CONFIG_FIELD(<<"Max payload size in bytes">>, + max_payload_size), + ?ALIST_CONFIG_FIELD(<<"When to send the last published item">>, + send_last_published_item, [never, on_sub, on_sub_and_presence]), + ?BOOL_CONFIG_FIELD(<<"Only deliver notifications to available users">>, + presence_based_delivery), + ?NLIST_CONFIG_FIELD(<<"The collections with which a node is affiliated">>, + collection), + ?ALIST_CONFIG_FIELD(<<"Whether owners or publisher should receive replies to items">>, + itemreply, [none, owner, publisher])]. %%

    There are several reasons why the node configuration request might fail:

    %% -set_configure(Host, Node, From, Els, Lang) -> - case fxml:remove_cdata(Els) of - [#xmlel{name = <<"x">>} = XEl] -> - case {fxml:get_tag_attr_s(<<"xmlns">>, XEl), fxml:get_tag_attr_s(<<"type">>, XEl)} of - {?NS_XDATA, <<"cancel">>} -> - {result, []}; - {?NS_XDATA, <<"submit">>} -> - Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx} = N) -> - case node_call(Host, Type, get_affiliation, [Nidx, From]) of - {result, owner} -> - case jlib:parse_xdata_submit(XEl) of - invalid -> - Txt = <<"Incorrect data form">>, - {error, ?ERRT_BAD_REQUEST(Lang, Txt)}; - XData -> - OldOpts = case Options of - [] -> node_options(Host, Type); - _ -> Options - end, - case set_xoption(Host, XData, OldOpts) of - NewOpts when is_list(NewOpts) -> - case tree_call(Host, - set_node, - [N#pubsub_node{options = NewOpts}]) - of - {result, Nidx} -> {result, ok}; - ok -> {result, ok}; - Err -> Err - end; - Error -> - Error - end - end; - _ -> - Txt = <<"You're not an owner">>, - {error, ?ERRT_FORBIDDEN(Lang, Txt)} - end - end, - case transaction(Host, Node, Action, transaction) of - {result, {TNode, ok}} -> - Nidx = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_config_notification(Host, Node, Nidx, Type, Options, Lang), - {result, []}; - Other -> - Other - end; - _ -> - Txt = <<"Incorrect data form">>, - {error, ?ERRT_BAD_REQUEST(Lang, Txt)} - end; - _ -> - Txt = <<"No data form found">>, - {error, ?ERRT_BAD_REQUEST(Lang, Txt)} +-spec set_configure(host(), binary(), jid(), [{binary(), [binary()]}], + binary()) -> {result, undefined} | {error, error()}. +set_configure(Host, Node, From, Config, Lang) -> + Action = + fun(#pubsub_node{options = Options, type = Type, id = Nidx} = N) -> + case node_call(Host, Type, get_affiliation, [Nidx, From]) of + {result, owner} -> + OldOpts = case Options of + [] -> node_options(Host, Type); + _ -> Options + end, + case set_xoption(Host, Config, OldOpts) of + NewOpts when is_list(NewOpts) -> + case tree_call(Host, + set_node, + [N#pubsub_node{options = NewOpts}]) + of + {result, Nidx} -> {result, ok}; + ok -> {result, ok}; + Err -> Err + end; + Error -> + Error + end; + _ -> + {error, xmpp:err_forbidden( + <<"Owner privileges required">>, Lang)} + end + end, + case transaction(Host, Node, Action, transaction) of + {result, {TNode, ok}} -> + Nidx = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_config_notification(Host, Node, Nidx, Type, Options, Lang), + {result, undefined}; + Other -> + Other end. +-spec add_opt(atom(), any(), [{atom(), any()}]) -> [{atom(), any()}]. add_opt(Key, Value, Opts) -> - [{Key, Value} | lists:keydelete(Key, 1, Opts)]. + lists:keystore(Key, 1, Opts, {Key, Value}). -define(SET_BOOL_XOPT(Opt, Val), BoolVal = case Val of @@ -3761,7 +3425,7 @@ add_opt(Key, Value, Opts) -> error -> Txt = <<"Value of '~s' should be boolean">>, ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), - {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)}; + {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)}; _ -> set_xoption(Host, Opts, add_opt(Opt, BoolVal, NewOpts)) end). @@ -3769,20 +3433,20 @@ add_opt(Key, Value, Opts) -> set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). -define(SET_INTEGER_XOPT(Opt, Val, Min, Max), - case catch jlib:binary_to_integer(Val) of - IVal when is_integer(IVal), IVal >= Min -> - if (Max =:= undefined) orelse (IVal =< Max) -> - set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); - true -> - Txt = <<"Incorrect value of '~s'">>, + case catch jlib:binary_to_integer(Val) of + IVal when is_integer(IVal), IVal >= Min -> + if (Max =:= undefined) orelse (IVal =< Max) -> + set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); + true -> + Txt = <<"Incorrect value of '~s'">>, + ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)} + end; + _ -> + Txt = <<"Value of '~s' should be integer">>, ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), - {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} - end; - _ -> - Txt = <<"Value of '~s' should be integer">>, - ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), - {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} - end). + {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)} + end). -define(SET_ALIST_XOPT(Opt, Val, Vals), case lists:member(Val, [atom_to_binary(V, latin1) || V <- Vals]) of @@ -3791,12 +3455,13 @@ add_opt(Key, Value, Opts) -> false -> Txt = <<"Incorrect value of '~s'">>, ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), - {error, ?ERRT_NOT_ACCEPTABLE(?MYLANG, ErrTxt)} + {error, xmpp:err_not_acceptable(ErrTxt, ?MYLANG)} end). -define(SET_LIST_XOPT(Opt, Val), - set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). + set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). +-spec set_xoption(host(), [{binary(), [binary()]}], [{atom(), any()}]) -> [{atom(), any()}]. set_xoption(_Host, [], NewOpts) -> NewOpts; set_xoption(Host, [{<<"FORM_TYPE">>, _} | Opts], NewOpts) -> set_xoption(Host, Opts, NewOpts); @@ -3852,17 +3517,26 @@ set_xoption(Host, [{<<"pubsub#itemreply">>, [Val]} | Opts], NewOpts) -> set_xoption(Host, [_ | Opts], NewOpts) -> set_xoption(Host, Opts, NewOpts). +-spec get_xdata_fields(undefined | xdata()) -> [{binary(), [binary()]}]. +get_xdata_fields(undefined) -> + []; +get_xdata_fields(#xdata{fields = Fs}) -> + [{Var, Vals} || #xdata_field{var = Var, values = Vals} <- Fs]. + +-spec get_max_items_node(host()) -> undefined | non_neg_integer(). get_max_items_node(Host) -> config(Host, max_items_node, undefined). +-spec get_max_subscriptions_node(host()) -> undefined | non_neg_integer(). get_max_subscriptions_node(Host) -> config(Host, max_subscriptions_node, undefined). %%%% last item cache handling - +-spec is_last_item_cache_enabled(host()) -> boolean(). is_last_item_cache_enabled(Host) -> config(Host, last_item_cache, false). +-spec set_cached_item(host(), nodeIdx(), binary(), binary(), [xmlel()]) -> ok. set_cached_item({_, ServerHost, _}, Nidx, ItemId, Publisher, Payload) -> set_cached_item(ServerHost, Nidx, ItemId, Publisher, Payload); set_cached_item(Host, Nidx, ItemId, Publisher, Payload) -> @@ -3873,6 +3547,7 @@ set_cached_item(Host, Nidx, ItemId, Publisher, Payload) -> _ -> ok end. +-spec unset_cached_item(host(), nodeIdx()) -> ok. unset_cached_item({_, ServerHost, _}, Nidx) -> unset_cached_item(ServerHost, Nidx); unset_cached_item(Host, Nidx) -> @@ -3881,9 +3556,7 @@ unset_cached_item(Host, Nidx) -> _ -> ok end. --spec get_cached_item(Host :: mod_pubsub:host(), Nidx :: mod_pubsub:nodeIdx()) -> - undefined | mod_pubsub:pubsubItem(). - +-spec get_cached_item(host(), nodeIdx()) -> undefined | pubsubItem(). get_cached_item({_, ServerHost, _}, Nidx) -> get_cached_item(ServerHost, Nidx); get_cached_item(Host, Nidx) -> @@ -3904,21 +3577,24 @@ get_cached_item(Host, Nidx) -> end. %%%% plugin handling - +-spec host(binary()) -> binary(). host(ServerHost) -> config(ServerHost, host, <<"pubsub.", ServerHost/binary>>). +-spec serverhost(host()) -> binary(). serverhost({_U, ServerHost, _R})-> serverhost(ServerHost); serverhost(Host) -> ejabberd_router:host_of_route(Host). +-spec tree(host()) -> atom(). tree(Host) -> case config(Host, nodetree) of undefined -> tree(Host, ?STDTREE); Tree -> Tree end. +-spec tree(host(), binary() | atom()) -> atom(). tree(_Host, <<"virtual">>) -> nodetree_virtual; % special case, virtual does not use any backend tree(Host, Name) -> @@ -3928,6 +3604,7 @@ tree(Host, Name) -> _ -> Name end. +-spec plugin(host(), binary() | atom()) -> atom(). plugin(Host, Name) -> case gen_mod:db_type(serverhost(Host), ?MODULE) of mnesia -> jlib:binary_to_atom(<<"node_", Name/binary>>); @@ -3935,6 +3612,7 @@ plugin(Host, Name) -> _ -> Name end. +-spec plugins(host()) -> [binary()]. plugins(Host) -> case config(Host, plugins) of undefined -> [?STDNODE]; @@ -3942,6 +3620,9 @@ plugins(Host) -> Plugins -> Plugins end. +-spec subscription_plugin(host()) -> pubsub_subscription | + pubsub_subscription_sql | + none. subscription_plugin(Host) -> case gen_mod:db_type(serverhost(Host), ?MODULE) of mnesia -> pubsub_subscription; @@ -3949,9 +3630,11 @@ subscription_plugin(Host) -> _ -> none end. +-spec config(binary(), any()) -> any(). config(ServerHost, Key) -> config(ServerHost, Key, undefined). +-spec config(host(), any(), any()) -> any(). config({_User, Host, _Resource}, Key, Default) -> config(Host, Key, Default); config(ServerHost, Key, Default) -> @@ -3960,6 +3643,7 @@ config(ServerHost, Key, Default) -> _ -> Default end. +-spec select_type(binary(), host(), binary(), binary()) -> binary(). select_type(ServerHost, Host, Node, Type) -> SelectedType = case Host of {_User, _Server, _Resource} -> @@ -3976,6 +3660,7 @@ select_type(ServerHost, Host, Node, Type) -> false -> hd(ConfiguredTypes) end. +-spec select_type(binary(), host(), binary()) -> binary(). select_type(ServerHost, Host, Node) -> select_type(ServerHost, Host, Node, hd(plugins(Host))). @@ -4005,7 +3690,7 @@ features() -> % see plugin "subscribe", % REQUIRED % see plugin "subscription-options", % OPTIONAL % see plugin "subscription-notifications" % OPTIONAL - +-spec plugin_features(binary(), binary()) -> [binary()]. plugin_features(Host, Type) -> Module = plugin(Host, Type), case catch Module:features() of @@ -4013,6 +3698,7 @@ plugin_features(Host, Type) -> Result -> Result end. +-spec features(binary(), binary()) -> [binary()]. features(Host, <<>>) -> lists:usort(lists:foldl(fun (Plugin, Acc) -> Acc ++ plugin_features(Host, Plugin) @@ -4048,11 +3734,13 @@ tree_action(Host, Function, Args) -> Result; {aborted, Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR} + ErrTxt = <<"Database failure">>, + {error, xmpp:err_internal_server_error(ErrTxt, ?MYLANG)} end; Other -> ?ERROR_MSG("unsupported backend: ~p~n", [Other]), - {error, ?ERR_INTERNAL_SERVER_ERROR} + ErrTxt = <<"Database failure">>, + {error, xmpp:err_internal_server_error(ErrTxt, ?MYLANG)} end. %% @doc

    node plugin call.

    @@ -4108,7 +3796,7 @@ transaction(Host, Fun, Trans) -> transaction_retry(Host, ServerHost, Fun, Trans, DBType, Retry). transaction_retry(_Host, _ServerHost, _Fun, _Trans, _DBType, 0) -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)}; transaction_retry(Host, ServerHost, Fun, Trans, DBType, Count) -> Res = case DBType of mnesia -> @@ -4133,75 +3821,126 @@ transaction_retry(Host, ServerHost, Fun, Trans, DBType, Count) -> {error, Error}; {aborted, Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)}; {'EXIT', {timeout, _} = Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [Reason]), transaction_retry(Host, ServerHost, Fun, Trans, DBType, Count - 1); {'EXIT', Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR}; + {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)}; Other -> ?ERROR_MSG("transaction return internal error: ~p~n", [Other]), - {error, ?ERR_INTERNAL_SERVER_ERROR} + {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)} end. %%%% helpers %% Add pubsub-specific error element -extended_error(Error, Ext) -> - extended_error(Error, Ext, [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}]). +-spec extended_error(error(), ps_error()) -> error(). +extended_error(StanzaErr, PubSubErr) -> + StanzaErr#error{sub_els = [PubSubErr]}. -extended_error(Error, unsupported, Feature) -> - %% Give a uniq identifier - extended_error(Error, <<"unsupported">>, - [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}, - {<<"feature">>, Feature}]); -extended_error(#xmlel{name = Error, attrs = Attrs, children = SubEls}, Ext, ExtAttrs) -> - #xmlel{name = Error, attrs = Attrs, - children = lists:reverse([#xmlel{name = Ext, attrs = ExtAttrs} | SubEls])}. +-spec err_closed_node() -> ps_error(). +err_closed_node() -> + #ps_error{type = 'closed-node'}. -is_item_not_found({error, ErrEl}) -> - case fxml:get_subtag_with_xmlns( - ErrEl, <<"item-not-found">>, ?NS_STANZAS) of - #xmlel{} -> true; - _ -> false - end. +-spec err_configuration_required() -> ps_error(). +err_configuration_required() -> + #ps_error{type = 'configuration-required'}. -string_to_ljid(JID) -> - case jid:from_string(JID) of - error -> - {<<>>, <<>>, <<>>}; - J -> - case jid:tolower(J) of - error -> {<<>>, <<>>, <<>>}; - J1 -> J1 - end - end. +-spec err_invalid_jid() -> ps_error(). +err_invalid_jid() -> + #ps_error{type = 'invalid-jid'}. + +-spec err_invalid_options() -> ps_error(). +err_invalid_options() -> + #ps_error{type = 'invalid-options'}. + +-spec err_invalid_payload() -> ps_error(). +err_invalid_payload() -> + #ps_error{type = 'invalid-payload'}. + +-spec err_invalid_subid() -> ps_error(). +err_invalid_subid() -> + #ps_error{type = 'invalid-subid'}. + +-spec err_item_forbidden() -> ps_error(). +err_item_forbidden() -> + #ps_error{type = 'item-forbidden'}. + +-spec err_item_required() -> ps_error(). +err_item_required() -> + #ps_error{type = 'item-required'}. + +-spec err_jid_required() -> ps_error(). +err_jid_required() -> + #ps_error{type = 'jid-required'}. + +-spec err_max_items_exceeded() -> ps_error(). +err_max_items_exceeded() -> + #ps_error{type = 'max-items-exceeded'}. + +-spec err_max_nodes_exceeded() -> ps_error(). +err_max_nodes_exceeded() -> + #ps_error{type = 'max-nodes-exceeded'}. + +-spec err_nodeid_required() -> ps_error(). +err_nodeid_required() -> + #ps_error{type = 'nodeid-required'}. + +-spec err_not_in_roster_group() -> ps_error(). +err_not_in_roster_group() -> + #ps_error{type = 'not-in-roster-group'}. + +-spec err_not_subscribed() -> ps_error(). +err_not_subscribed() -> + #ps_error{type = 'not-subscribed'}. + +-spec err_payload_too_big() -> ps_error(). +err_payload_too_big() -> + #ps_error{type = 'payload-too-big'}. + +-spec err_payload_required() -> ps_error(). +err_payload_required() -> + #ps_error{type = 'payload-required'}. + +-spec err_pending_subscription() -> ps_error(). +err_pending_subscription() -> + #ps_error{type = 'pending-subscription'}. + +-spec err_presence_subscription_required() -> ps_error(). +err_presence_subscription_required() -> + #ps_error{type = 'presence-subscription-required'}. + +-spec err_subid_required() -> ps_error(). +err_subid_required() -> + #ps_error{type = 'subid-required'}. + +-spec err_too_many_subscriptions() -> ps_error(). +err_too_many_subscriptions() -> + #ps_error{type = 'too-many-subscriptions'}. + +-spec err_unsupported(ps_error_feature()) -> ps_error(). +err_unsupported(Feature) -> + #ps_error{type = 'unsupported', feature = Feature}. + +-spec err_unsupported_access_model() -> ps_error(). +err_unsupported_access_model() -> + #ps_error{type = 'unsupported-access-model'}. -spec uniqid() -> mod_pubsub:itemId(). uniqid() -> {T1, T2, T3} = p1_time_compat:timestamp(), iolist_to_binary(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). -nodeAttr(Node) -> [{<<"node">>, Node}]. - -itemAttr([]) -> []; -itemAttr(ItemId) -> [{<<"id">>, ItemId}]. -itemAttr(ItemId, From) -> [{<<"id">>, ItemId}, From]. - +-spec itemsEls([#pubsub_item{}]) -> [ps_item()]. itemsEls(Items) -> - [#xmlel{name = <<"item">>, attrs = itemAttr(ItemId), children = Payload} - || #pubsub_item{itemid = {ItemId, _}, payload = Payload} <- Items]. + [#ps_item{id = ItemId, xml_els = Payload} + || #pubsub_item{itemid = {ItemId, _}, payload = Payload} <- Items]. --spec add_message_type(Message :: xmlel(), Type :: atom()) -> xmlel(). - -add_message_type(Message, normal) -> Message; -add_message_type(#xmlel{name = <<"message">>, attrs = Attrs, children = Els}, Type) -> - #xmlel{name = <<"message">>, - attrs = [{<<"type">>, jlib:atom_to_binary(Type)} | Attrs], - children = Els}; -add_message_type(XmlEl, _Type) -> - XmlEl. +-spec add_message_type(message(), message_type()) -> message(). +add_message_type(#message{} = Message, Type) -> + Message#message{type = Type}. %% Place of changed at the bottom of the stanza %% cf. http://xmpp.org/extensions/xep-0060.html#publisher-publish-success-subid @@ -4209,32 +3948,24 @@ add_message_type(XmlEl, _Type) -> %% "[SHIM Headers] SHOULD be included after the event notification information %% (i.e., as the last child of the stanza)". -add_shim_headers(Stanza, HeaderEls) -> - add_headers(Stanza, <<"headers">>, ?NS_SHIM, HeaderEls). +-spec add_shim_headers(stanza(), [{binary(), binary()}]) -> stanza(). +add_shim_headers(Stanza, Headers) -> + xmpp:set_subtag(Stanza, #shim{headers = Headers}). -add_extended_headers(Stanza, HeaderEls) -> - add_headers(Stanza, <<"addresses">>, ?NS_ADDRESS, HeaderEls). - -add_headers(#xmlel{name = Name, attrs = Attrs, children = Els}, HeaderName, HeaderNS, HeaderEls) -> - HeaderEl = #xmlel{name = HeaderName, - attrs = [{<<"xmlns">>, HeaderNS}], - children = HeaderEls}, - #xmlel{name = Name, attrs = Attrs, - children = lists:append(Els, [HeaderEl])}. +-spec add_extended_headers(stanza(), [address()]) -> stanza(). +add_extended_headers(Stanza, Addrs) -> + xmpp:set_subtag(Stanza, #addresses{list = Addrs}). +-spec subid_shim([binary()]) -> [{binary(), binary()}]. subid_shim(SubIds) -> - [#xmlel{name = <<"header">>, - attrs = [{<<"name">>, <<"SubId">>}], - children = [{xmlcdata, SubId}]} - || SubId <- SubIds]. + [{<<"SubId">>, SubId} || SubId <- SubIds]. %% The argument is a list of Jids because this function could be used %% with the 'pubsub#replyto' (type=jid-multi) node configuration. +-spec extended_headers([jid()]) -> [address()]. extended_headers(Jids) -> - [#xmlel{name = <<"address">>, - attrs = [{<<"type">>, <<"replyto">>}, {<<"jid">>, Jid}]} - || Jid <- Jids]. + [#address{type = replyto, jid = Jid} || Jid <- Jids]. -spec on_user_offline(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> ok. on_user_offline(_, JID, _) -> @@ -4244,6 +3975,7 @@ on_user_offline(_, JID, _) -> _ -> ok end. +-spec purge_offline(ljid()) -> ok. purge_offline(LJID) -> Host = host(element(2, LJID)), Plugins = plugins(Host), @@ -4251,8 +3983,8 @@ purge_offline(LJID) -> Features = plugin_features(Host, Type), case lists:member(<<"retrieve-affiliations">>, plugin_features(Host, Type)) of false -> - {{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"retrieve-affiliations">>)}, + {{error, extended_error(xmpp:err_feature_not_implemented(), + err_unsupported('retrieve-affiliations'))}, Acc}; true -> Items = lists:member(<<"retract-items">>, Features) @@ -4286,6 +4018,7 @@ purge_offline(LJID) -> ?DEBUG("on_user_offline ~p", [Error]) end. +-spec purge_offline(host(), ljid(), binary()) -> ok | {error, error()}. purge_offline(Host, LJID, Node) -> Nidx = Node#pubsub_node.id, Type = Node#pubsub_node.type, diff --git a/src/node_flat_sql.erl b/src/node_flat_sql.erl index fa4af4d57..2a468c69a 100644 --- a/src/node_flat_sql.erl +++ b/src/node_flat_sql.erl @@ -36,7 +36,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, features/0, @@ -81,27 +81,27 @@ create_node(Nidx, Owner) -> J = encode_jid(OwnerKey), A = encode_affiliation(owner), S = encode_subscriptions([]), - catch ejabberd_sql:sql_query_t( - ?SQL("insert into pubsub_state(" - "nodeid, jid, affiliation, subscriptions) " - "values (%(Nidx)d, %(J)s, %(A)s, %(S)s)")), + ejabberd_sql:sql_query_t( + ?SQL("insert into pubsub_state(" + "nodeid, jid, affiliation, subscriptions) " + "values (%(Nidx)d, %(J)s, %(A)s, %(S)s)")), {result, {default, broadcast}}. delete_node(Nodes) -> - Reply = lists:map(fun (#pubsub_node{id = Nidx} = PubsubNode) -> - Subscriptions = case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(jid)s, @(subscriptions)s " - "from pubsub_state where nodeid=%(Nidx)d")) - of - {selected, RItems} -> - [{decode_jid(SJID), decode_subscriptions(Subs)} || - {SJID, Subs} <- RItems]; - _ -> - [] - end, - {PubsubNode, Subscriptions} - end, Nodes), + Reply = lists:map( + fun(#pubsub_node{id = Nidx} = PubsubNode) -> + Subscriptions = + case ejabberd_sql:sql_query_t( + ?SQL("select @(jid)s, @(subscriptions)s " + "from pubsub_state where nodeid=%(Nidx)d")) of + {selected, RItems} -> + [{decode_jid(SJID), decode_subscriptions(Subs)} + || {SJID, Subs} <- RItems]; + _ -> + [] + end, + {PubsubNode, Subscriptions} + end, Nodes), {result, {default, broadcast, Reply}}. subscribe_node(Nidx, Sender, Subscriber, AccessModel, @@ -118,22 +118,25 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, Subscriptions), Owner = Affiliation == owner, if not Authorized -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; + {error, 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">>)}; + {error, 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">>)}; + {error, 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">>)}; + {error, 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">>)}; + {error, mod_pubsub:extended_error( + xmpp:err_not_allowed(), mod_pubsub:err_closed_node())}; %%MustPay -> %% % Payment is required for a subscription %% {error, ?ERR_PAYMENT_REQUIRED}; @@ -177,7 +180,7 @@ 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")}; @@ -186,8 +189,9 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; %% Requesting entity is not a subscriber Subscriptions == [] -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}; + {error, mod_pubsub:extended_error( + xmpp:err_unexpected_request(), + mod_pubsub:err_not_subscribed())}; %% Subid supplied, so use that. SubIdExists -> Sub = first_in_list(fun @@ -200,8 +204,9 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> delete_subscription(SubKey, Nidx, S, Affiliation, Subscriptions), {result, default}; false -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)} + {error, 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 -> @@ -214,8 +219,8 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> {result, default}; %% No subid and more than one possible subscription match. true -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} + {error, mod_pubsub:extended_error( + xmpp:err_bad_request(), mod_pubsub:err_subid_required())} end. delete_subscription(SubKey, Nidx, {Subscription, SubId}, Affiliation, Subscriptions) -> @@ -241,7 +246,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 -> PubId = {p1_time_compat:timestamp(), SubKey}, @@ -277,11 +282,11 @@ delete_item(Nidx, Publisher, PublishModel, ItemId) -> _ -> false end, if not Allowed -> - {error, ?ERR_FORBIDDEN}; + {error, xmpp:err_forbidden()}; true -> case del_item(Nidx, ItemId) of {updated, 1} -> {result, {default, broadcast}}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} + _ -> {error, xmpp:err_item_not_found()} end end. @@ -299,7 +304,7 @@ purge_node(Nidx, Owner) -> States), {result, {default, broadcast}}; _ -> - {error, ?ERR_FORBIDDEN} + {error, xmpp:err_forbidden()} end. get_entity_affiliations(Host, Owner) -> @@ -307,48 +312,42 @@ get_entity_affiliations(Host, Owner) -> GenKey = jid:remove_resource(SubKey), H = encode_host(Host), J = encode_jid(GenKey), - Reply = case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(node)s, @(type)s, @(i.nodeid)d, @(affiliation)s " - "from pubsub_state i, pubsub_node n where " - "i.nodeid = n.nodeid and jid=%(J)s and host=%(H)s")) - of - {selected, RItems} -> - [{nodetree_tree_sql:raw_to_node(Host, {N, <<"">>, T, I}), decode_affiliation(A)} - || {N, T, I, A} <- RItems]; - _ -> - [] - end, - {result, Reply}. + {result, + case ejabberd_sql:sql_query_t( + ?SQL("select @(node)s, @(type)s, @(i.nodeid)d, @(affiliation)s " + "from pubsub_state i, pubsub_node n where " + "i.nodeid = n.nodeid and jid=%(J)s and host=%(H)s")) of + {selected, RItems} -> + [{nodetree_tree_sql:raw_to_node(Host, {N, <<"">>, T, I}), + decode_affiliation(A)} || {N, T, I, A} <- RItems]; + _ -> + [] + end}. get_node_affiliations(Nidx) -> - Reply = case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(jid)s, @(affiliation)s from pubsub_state " - "where nodeid=%(Nidx)d")) - of - {selected, RItems} -> - [{decode_jid(J), decode_affiliation(A)} || {J, A} <- RItems]; - _ -> - [] - end, - {result, Reply}. + {result, + case ejabberd_sql:sql_query_t( + ?SQL("select @(jid)s, @(affiliation)s from pubsub_state " + "where nodeid=%(Nidx)d")) of + {selected, RItems} -> + [{decode_jid(J), decode_affiliation(A)} || {J, A} <- RItems]; + _ -> + [] + end}. get_affiliation(Nidx, Owner) -> SubKey = jid:tolower(Owner), GenKey = jid:remove_resource(SubKey), J = encode_jid(GenKey), - Reply = case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(affiliation)s from pubsub_state " - "where nodeid=%(Nidx)d and jid=%(J)s")) - of - {selected, [{A}]} -> - decode_affiliation(A); - _ -> - none - end, - {result, Reply}. + {result, + case ejabberd_sql:sql_query_t( + ?SQL("select @(affiliation)s from pubsub_state " + "where nodeid=%(Nidx)d and jid=%(J)s")) of + {selected, [{A}]} -> + decode_affiliation(A); + _ -> + none + end}. set_affiliation(Nidx, Owner, Affiliation) -> SubKey = jid:tolower(Owner), @@ -382,26 +381,26 @@ get_entity_subscriptions(Host, Owner) -> "where i.nodeid = n.nodeid and" " jid in (%(SJ)s, %(GJ)s) and host=%(H)s") end, - Reply = case catch ejabberd_sql:sql_query_t(Query) of - {selected, RItems} -> - lists:foldl(fun ({N, T, I, J, S}, Acc) -> - Node = nodetree_tree_sql:raw_to_node(Host, {N, <<"">>, T, I}), - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> - [{Node, none, Jid} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, Jid} | Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> - [] - end, - {result, Reply}. + {result, + case ejabberd_sql:sql_query_t(Query) of + {selected, RItems} -> + lists:foldl( + fun({N, T, I, J, S}, Acc) -> + Node = nodetree_tree_sql:raw_to_node(Host, {N, <<"">>, T, I}), + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Node, none, Jid} | Acc]; + Subs -> + lists:foldl( + fun({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, Jid} | Acc2] + end, Acc, Subs) + end + end, [], RItems); + _ -> + [] + end}. -spec get_entity_subscriptions_for_send_last(Host :: mod_pubsub:hostPubsub(), Owner :: jid()) -> @@ -435,66 +434,62 @@ get_entity_subscriptions_for_send_last(Host, Owner) -> "and val='on_sub_and_presence' and" " jid in (%(SJ)s, %(GJ)s) and host=%(H)s") end, - Reply = case catch ejabberd_sql:sql_query_t(Query) of - {selected, RItems} -> - lists:foldl(fun ({N, T, I, J, S}, Acc) -> - Node = nodetree_tree_sql:raw_to_node(Host, {N, <<"">>, T, I}), - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> - [{Node, none, Jid} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, Jid}| Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> - [] - end, - {result, Reply}. + {result, + case ejabberd_sql:sql_query_t(Query) of + {selected, RItems} -> + lists:foldl( + fun ({N, T, I, J, S}, Acc) -> + Node = nodetree_tree_sql:raw_to_node(Host, {N, <<"">>, T, I}), + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Node, none, Jid} | Acc]; + Subs -> + lists:foldl( + fun ({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, Jid}| Acc2] + end, Acc, Subs) + end + end, [], RItems); + _ -> + [] + end}. get_node_subscriptions(Nidx) -> - Reply = case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(jid)s, @(subscriptions)s from pubsub_state " - "where nodeid=%(Nidx)d")) - of - {selected, RItems} -> - lists:foldl(fun ({J, S}, Acc) -> - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> - [{Jid, none} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Jid, Sub, SubId} | Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> - [] - end, - {result, Reply}. + {result, + case ejabberd_sql:sql_query_t( + ?SQL("select @(jid)s, @(subscriptions)s from pubsub_state " + "where nodeid=%(Nidx)d")) of + {selected, RItems} -> + lists:foldl( + fun ({J, S}, Acc) -> + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Jid, none} | Acc]; + Subs -> + lists:foldl( + fun ({Sub, SubId}, Acc2) -> + [{Jid, Sub, SubId} | Acc2] + end, Acc, Subs) + end + end, [], RItems); + _ -> + [] + end}. get_subscriptions(Nidx, Owner) -> SubKey = jid:tolower(Owner), J = encode_jid(SubKey), - Reply = case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(subscriptions)s from pubsub_state" - " where nodeid=%(Nidx)d and jid=%(J)s")) - of - {selected, [{S}]} -> - decode_subscriptions(S); - _ -> - [] - end, - {result, Reply}. + {result, + case ejabberd_sql:sql_query_t( + ?SQL("select @(subscriptions)s from pubsub_state" + " where nodeid=%(Nidx)d and jid=%(J)s")) of + {selected, [{S}]} -> + decode_subscriptions(S); + _ -> + [] + end}. set_subscriptions(Nidx, Owner, Subscription, SubId) -> SubKey = jid:tolower(Owner), @@ -503,8 +498,9 @@ set_subscriptions(Nidx, Owner, Subscription, SubId) -> {_, []} -> case Subscription of none -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)}; + {error, mod_pubsub:extended_error( + xmpp:err_bad_request(), + mod_pubsub:err_not_subscribed())}; _ -> new_subscription(Nidx, Owner, Subscription, SubState) end; @@ -514,8 +510,9 @@ set_subscriptions(Nidx, Owner, Subscription, SubId) -> _ -> replace_subscription({Subscription, SID}, SubState) end; {<<>>, [_ | _]} -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}; + {error, mod_pubsub:extended_error( + xmpp:err_bad_request(), + mod_pubsub:err_subid_required())}; _ -> case Subscription of none -> unsub_with_subid(Nidx, SubId, SubState); @@ -585,21 +582,19 @@ get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs} end. get_states(Nidx) -> - case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(jid)s, @(affiliation)s, @(subscriptions)s " - "from pubsub_state where nodeid=%(Nidx)d")) - of + case ejabberd_sql:sql_query_t( + ?SQL("select @(jid)s, @(affiliation)s, @(subscriptions)s " + "from pubsub_state where nodeid=%(Nidx)d")) of {selected, RItems} -> {result, - lists:map(fun ({SJID, Aff, Subs}) -> - JID = decode_jid(SJID), - #pubsub_state{stateid = {JID, Nidx}, - items = itemids(Nidx, JID), - affiliation = decode_affiliation(Aff), - subscriptions = decode_subscriptions(Subs)} - end, - RItems)}; + lists:map( + fun({SJID, Aff, Subs}) -> + JID = decode_jid(SJID), + #pubsub_state{stateid = {JID, Nidx}, + items = itemids(Nidx, JID), + affiliation = decode_affiliation(Aff), + subscriptions = decode_subscriptions(Subs)} + end, RItems)}; _ -> {result, []} end. @@ -614,16 +609,14 @@ get_state(Nidx, JID) -> get_state_without_itemids(Nidx, JID) -> J = encode_jid(JID), - case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(jid)s, @(affiliation)s, @(subscriptions)s " - "from pubsub_state " - "where nodeid=%(Nidx)d and jid=%(J)s")) - of + case ejabberd_sql:sql_query_t( + ?SQL("select @(jid)s, @(affiliation)s, @(subscriptions)s " + "from pubsub_state " + "where nodeid=%(Nidx)d and jid=%(J)s")) of {selected, [{SJID, Aff, Subs}]} -> #pubsub_state{stateid = {decode_jid(SJID), Nidx}, - affiliation = decode_affiliation(Aff), - subscriptions = decode_subscriptions(Subs)}; + affiliation = decode_affiliation(Aff), + subscriptions = decode_subscriptions(Subs)}; _ -> #pubsub_state{stateid = {JID, Nidx}} end. @@ -653,73 +646,60 @@ del_state(Nidx, JID) -> " where jid=%(J)s and nodeid=%(Nidx)d")), ok. -%get_items(Nidx, _From) -> -% case catch -% ejabberd_sql:sql_query_t([<<"select itemid, publisher, creation, modification, payload " -% "from pubsub_item where nodeid='">>, Nidx, -% <<"' order by modification desc;">>]) -% of -% {selected, -% [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> -% {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; -% _ -> -% {result, []} -% end. - -get_items(Nidx, From, none) -> - MaxItems = case catch - ejabberd_sql:sql_query_t( - ?SQL("select @(val)s from pubsub_node_option " - "where nodeid=%(Nidx)d and name='max_items'")) - of - {selected, [{Value}]} -> - jlib:expr_to_term(Value); - _ -> - ?MAXITEMS - end, - get_items(Nidx, From, #rsm_in{max = MaxItems}); -get_items(Nidx, _From, - #rsm_in{max = M, direction = Direction, id = I, index = IncIndex}) -> - Max = ejabberd_sql:escape(jlib:i2l(M)), - {Way, Order} = case Direction of - aft when I == <<>> -> {<<"is not">>, <<"desc">>}; - aft -> {<<"<">>, <<"desc">>}; - before when I == <<>> -> {<<"is not">>, <<"asc">>}; - before -> {<<">">>, <<"asc">>}; - _ -> {<<"is not">>, <<"desc">>} - end, +get_items(Nidx, From, undefined) -> + MaxItems = case ejabberd_sql:sql_query_t( + ?SQL("select @(val)s from pubsub_node_option " + "where nodeid=%(Nidx)d and name='max_items'")) of + {selected, [{Value}]} -> + jlib:expr_to_term(Value); + _ -> + ?MAXITEMS + end, + get_items(Nidx, From, #rsm_set{max = MaxItems}); +get_items(Nidx, _From, #rsm_set{max = Max, index = IncIndex, + 'after' = After, before = Before}) -> + {Way, Order} = if After == <<>> -> {<<"is not">>, <<"desc">>}; + After /= undefined -> {<<"<">>, <<"desc">>}; + Before == <<>> -> {<<"is not">>, <<"asc">>}; + Before /= undefined -> {<<">">>, <<"asc">>}; + true -> {<<"is not">>, <<"desc">>} + end, SNidx = integer_to_binary(Nidx), - [AttrName, Id] = case I of - undefined when IncIndex =/= undefined -> - case catch - ejabberd_sql:sql_query_t([<<"select modification from pubsub_item pi " - "where exists ( select count(*) as count1 " - "from pubsub_item where nodeid='">>, SNidx, + I = if After /= undefined -> After; + Before /= undefined -> Before; + true -> undefined + end, + [AttrName, Id] = + case I of + undefined when IncIndex =/= undefined -> + case ejabberd_sql:sql_query_t( + [<<"select modification from pubsub_item pi " + "where exists ( select count(*) as count1 " + "from pubsub_item where nodeid='">>, SNidx, <<"' and modification > pi.modification having count1 = ">>, - ejabberd_sql:escape(jlib:i2l(IncIndex)), <<" );">>]) - of - {selected, [_], [[O]]} -> - [<<"modification">>, <<"'", O/binary, "'">>]; - _ -> - [<<"modification">>, <<"null">>] - end; - undefined -> - [<<"modification">>, <<"null">>]; - <<>> -> - [<<"modification">>, <<"null">>]; - I -> - [A, B] = str:tokens(ejabberd_sql:escape(jlib:i2l(I)), <<"@">>), - [A, <<"'", B/binary, "'">>] - end, - Count = case catch - ejabberd_sql:sql_query_t([<<"select count(*) from pubsub_item where nodeid='">>, SNidx, <<"';">>]) - of - {selected, [_], [[C]]} -> C; - _ -> <<"0">> - end, + IncIndex, <<" );">>]) of + {selected, [_], [[O]]} -> + [<<"modification">>, <<"'", O/binary, "'">>]; + _ -> + [<<"modification">>, <<"null">>] + end; + undefined -> + [<<"modification">>, <<"null">>]; + <<>> -> + [<<"modification">>, <<"null">>]; + I -> + [A, B] = str:tokens(ejabberd_sql:escape(I), <<"@">>), + [A, <<"'", B/binary, "'">>] + end, + Count = case ejabberd_sql:sql_query_t( + [<<"select count(*) from pubsub_item where nodeid='">>, + SNidx, <<"';">>]) of + {selected, [_], [[C]]} -> binary_to_integer(C); + _ -> 0 + end, Query = fun(mssql, _) -> ejabberd_sql:sql_query_t( - [<<"select top ">>, jlib:i2l(Max), + [<<"select top ">>, Max, <<" itemid, publisher, creation, modification, payload " "from pubsub_item where nodeid='">>, SNidx, <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, @@ -729,32 +709,33 @@ get_items(Nidx, _From, [<<"select itemid, publisher, creation, modification, payload " "from pubsub_item where nodeid='">>, SNidx, <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, - AttrName, <<" ">>, Order, <<" limit ">>, jlib:i2l(Max), <<" ;">>]) + AttrName, <<" ">>, Order, <<" limit ">>, Max, <<" ;">>]) end, - case catch ejabberd_sql:sql_query_t(Query) of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> + case ejabberd_sql:sql_query_t(Query) of + {selected, [<<"itemid">>, <<"publisher">>, <<"creation">>, + <<"modification">>, <<"payload">>], RItems} -> case RItems of [[_, _, _, F, _]|_] -> - Index = case catch - ejabberd_sql:sql_query_t([<<"select count(*) from pubsub_item " - "where nodeid='">>, SNidx, <<"' and ">>, - AttrName, <<" > '">>, F, <<"';">>]) - of - %{selected, [_], [{C}, {In}]} -> [string:strip(C, both, $"), string:strip(In, both, $")]; - {selected, [_], [[In]]} -> In; - _ -> <<"0">> - end, + Index = case catch ejabberd_sql:sql_query_t( + [<<"select count(*) from pubsub_item " + "where nodeid='">>, SNidx, <<"' and ">>, + AttrName, <<" > '">>, F, <<"';">>]) of + {selected, [_], [[In]]} -> binary_to_integer(In); + _ -> 0 + end, [_, _, _, L, _] = lists:last(RItems), - RsmOut = #rsm_out{count = Count, index = Index, - first = <<"modification@", F/binary>>, - last = <<"modification@", (jlib:i2l(L))/binary>>}, + RsmOut = #rsm_set{count = Count, + index = Index, + first = #rsm_first{ + index = Index, + data = <<"modification@", F/binary>>}, + last = <<"modification@", L/binary>>}, {result, {[raw_to_item(Nidx, RItem) || RItem <- RItems], RsmOut}}; [] -> - {result, {[], #rsm_out{count = Count}}} + {result, {[], #rsm_set{count = Count}}} end; _ -> - {result, {[], none}} + {result, {[], undefined}} end. get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> @@ -769,18 +750,20 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?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">>)}; + {error, 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">>)}; + {error, 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">>)}; + {error, 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}; @@ -820,9 +803,9 @@ get_item(Nidx, ItemId) -> {selected, [RItem]} -> {result, raw_to_item(Nidx, RItem)}; {selected, []} -> - {error, ?ERR_ITEM_NOT_FOUND}; + {error, xmpp:err_item_not_found()}; {'EXIT', _} -> - {error, ?ERRT_INTERNAL_SERVER_ERROR(?MYLANG, <<"Database failure">>)} + {error, xmpp:err_internal_server_error(<<"Database failure">>, ?MYLANG)} end. get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> @@ -837,18 +820,20 @@ get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _Sub %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?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">>)}; + {error, 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">>)}; + {error, 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">>)}; + {error, 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}; diff --git a/src/xmpp.erl b/src/xmpp.erl index 8dbc49532..10872b341 100644 --- a/src/xmpp.erl +++ b/src/xmpp.erl @@ -10,7 +10,7 @@ %% API -export([make_iq_result/1, make_iq_result/2, make_error/2, - decode/1, decode/2, decode_tags_by_ns/2, encode/1, + decode/1, decode/2, encode/1, get_type/1, get_to/1, get_from/1, get_id/1, get_lang/1, get_error/1, get_els/1, get_ns/1, set_type/2, set_to/2, set_from/2, set_id/2, @@ -252,6 +252,10 @@ decode(Pkt, _Opts) -> decode_els(Stanza) -> decode_els(Stanza, fun xmpp_codec:is_known_tag/1). +-type match_fun() :: fun((xmlel()) -> boolean()). +-spec decode_els(iq(), match_fun()) -> iq(); + (message(), match_fun()) -> message(); + (presence(), match_fun()) -> presence(). decode_els(Stanza, MatchFun) -> Els = lists:map( fun(#xmlel{} = El) -> @@ -268,10 +272,6 @@ decode_els(Stanza, MatchFun) -> encode(Pkt) -> xmpp_codec:encode(Pkt). --spec decode_tags_by_ns([xmpp_element() | xmlel()], [binary()]) -> [xmpp_element()]. -decode_tags_by_ns(Els, NSList) -> - [xmpp_codec:decode(El) || El <- Els, lists:member(get_ns(El), NSList)]. - format_error(Reason) -> xmpp_codec:format_error(Reason). diff --git a/src/xmpp_codec.erl b/src/xmpp_codec.erl index afe6ff1ad..135a2acbb 100644 --- a/src/xmpp_codec.erl +++ b/src/xmpp_codec.erl @@ -520,10 +520,166 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> {<<"header">>, <<"http://jabber.org/protocol/shim">>} -> decode_shim_header(<<"http://jabber.org/protocol/shim">>, IgnoreEls, _el); + {<<"unsupported-access-model">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_unsupported_access_model(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"unsupported">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_unsupported(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"too-many-subscriptions">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_too_many_subscriptions(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"subid-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_subid_required(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"presence-subscription-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_presence_subscription_required(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"pending-subscription">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_pending_subscription(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"payload-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_payload_required(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"payload-too-big">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_payload_too_big(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"not-subscribed">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_not_subscribed(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"not-in-roster-group">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_not_in_roster_group(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"nodeid-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_nodeid_required(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"max-nodes-exceeded">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_max_nodes_exceeded(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"max-items-exceeded">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_max_items_exceeded(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"jid-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_jid_required(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"item-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_item_required(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"item-forbidden">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_item_forbidden(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"invalid-subid">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_invalid_subid(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"invalid-payload">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_invalid_payload(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"invalid-options">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_invalid_options(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"invalid-jid">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_invalid_jid(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"configuration-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_configuration_required(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"closed-node">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + decode_pubsub_error_closed_node(<<"http://jabber.org/protocol/pubsub#errors">>, + IgnoreEls, _el); + {<<"pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_owner(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); {<<"pubsub">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); + {<<"purge">>, + <<"http://jabber.org/protocol/pubsub">>} -> + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub">>, + IgnoreEls, _el); + {<<"purge">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); + {<<"purge">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); + {<<"delete">>, + <<"http://jabber.org/protocol/pubsub">>} -> + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub">>, + IgnoreEls, _el); + {<<"delete">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); + {<<"delete">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); + {<<"redirect">>, + <<"http://jabber.org/protocol/pubsub">>} -> + decode_pubsub_redirect(<<"http://jabber.org/protocol/pubsub">>, + IgnoreEls, _el); + {<<"redirect">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_redirect(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); + {<<"redirect">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_redirect(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); + {<<"default">>, + <<"http://jabber.org/protocol/pubsub">>} -> + decode_pubsub_default(<<"http://jabber.org/protocol/pubsub">>, + IgnoreEls, _el); + {<<"default">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_default(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); + {<<"publish-options">>, + <<"http://jabber.org/protocol/pubsub">>} -> + decode_pubsub_publish_options(<<"http://jabber.org/protocol/pubsub">>, + IgnoreEls, _el); + {<<"configure">>, + <<"http://jabber.org/protocol/pubsub">>} -> + decode_pubsub_configure(<<"http://jabber.org/protocol/pubsub">>, + IgnoreEls, _el); + {<<"configure">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_configure(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); + {<<"create">>, + <<"http://jabber.org/protocol/pubsub">>} -> + decode_pubsub_create(<<"http://jabber.org/protocol/pubsub">>, + IgnoreEls, _el); + {<<"create">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_create(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); {<<"retract">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_retract(<<"http://jabber.org/protocol/pubsub">>, @@ -544,6 +700,10 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_subscribe(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); + {<<"affiliations">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_owner_affiliations(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); {<<"affiliations">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_affiliations(<<"http://jabber.org/protocol/pubsub">>, @@ -552,29 +712,41 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); + {<<"subscriptions">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); {<<"event">>, <<"http://jabber.org/protocol/pubsub#event">>} -> decode_pubsub_event(<<"http://jabber.org/protocol/pubsub#event">>, IgnoreEls, _el); - {<<"items">>, - <<"http://jabber.org/protocol/pubsub#event">>} -> - decode_pubsub_event_items(<<"http://jabber.org/protocol/pubsub#event">>, - IgnoreEls, _el); - {<<"item">>, - <<"http://jabber.org/protocol/pubsub#event">>} -> - decode_pubsub_event_item(<<"http://jabber.org/protocol/pubsub#event">>, - IgnoreEls, _el); - {<<"retract">>, - <<"http://jabber.org/protocol/pubsub#event">>} -> - decode_pubsub_event_retract(<<"http://jabber.org/protocol/pubsub#event">>, - IgnoreEls, _el); {<<"items">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_items(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); + {<<"items">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_items(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); {<<"item">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); + {<<"item">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_item(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); + {<<"retract">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_event_retract(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); + {<<"configuration">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_event_configuration(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); + {<<"affiliation">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_owner_affiliation(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); {<<"affiliation">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_affiliation(<<"http://jabber.org/protocol/pubsub">>, @@ -583,6 +755,14 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); + {<<"subscription">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#owner">>, + IgnoreEls, _el); + {<<"subscription">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#event">>, + IgnoreEls, _el); {<<"x">>, <<"jabber:x:data">>} -> decode_xdata(<<"jabber:x:data">>, IgnoreEls, _el); {<<"item">>, <<"jabber:x:data">>} -> @@ -1654,9 +1834,126 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) -> true; {<<"header">>, <<"http://jabber.org/protocol/shim">>} -> true; + {<<"unsupported-access-model">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"unsupported">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"too-many-subscriptions">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"subid-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"presence-subscription-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"pending-subscription">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"payload-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"payload-too-big">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"not-subscribed">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"not-in-roster-group">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"nodeid-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"max-nodes-exceeded">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"max-items-exceeded">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"jid-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"item-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"item-forbidden">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"invalid-subid">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"invalid-payload">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"invalid-options">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"invalid-jid">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"configuration-required">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"closed-node">>, + <<"http://jabber.org/protocol/pubsub#errors">>} -> + true; + {<<"pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; {<<"pubsub">>, <<"http://jabber.org/protocol/pubsub">>} -> true; + {<<"purge">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; + {<<"purge">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; + {<<"purge">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + true; + {<<"delete">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; + {<<"delete">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; + {<<"delete">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + true; + {<<"redirect">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; + {<<"redirect">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; + {<<"redirect">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + true; + {<<"default">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; + {<<"default">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; + {<<"publish-options">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; + {<<"configure">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; + {<<"configure">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; + {<<"create">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; + {<<"create">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + true; {<<"retract">>, <<"http://jabber.org/protocol/pubsub">>} -> true; @@ -1672,28 +1969,40 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) -> {<<"subscribe">>, <<"http://jabber.org/protocol/pubsub">>} -> true; + {<<"affiliations">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; {<<"affiliations">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"subscriptions">>, <<"http://jabber.org/protocol/pubsub">>} -> true; + {<<"subscriptions">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; {<<"event">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; + {<<"items">>, + <<"http://jabber.org/protocol/pubsub">>} -> + true; {<<"items">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; + {<<"item">>, <<"http://jabber.org/protocol/pubsub">>} -> + true; {<<"item">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; {<<"retract">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; - {<<"items">>, - <<"http://jabber.org/protocol/pubsub">>} -> + {<<"configuration">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> true; - {<<"item">>, <<"http://jabber.org/protocol/pubsub">>} -> + {<<"affiliation">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> true; {<<"affiliation">>, <<"http://jabber.org/protocol/pubsub">>} -> @@ -1701,6 +2010,12 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) -> {<<"subscription">>, <<"http://jabber.org/protocol/pubsub">>} -> true; + {<<"subscription">>, + <<"http://jabber.org/protocol/pubsub#owner">>} -> + true; + {<<"subscription">>, + <<"http://jabber.org/protocol/pubsub#event">>} -> + true; {<<"x">>, <<"jabber:x:data">>} -> true; {<<"item">>, <<"jabber:x:data">>} -> true; {<<"reported">>, <<"jabber:x:data">>} -> true; @@ -2410,59 +2725,162 @@ encode({xdata_field, _, _, _, _, _, _, _, _} = Field) -> [{<<"xmlns">>, <<"jabber:x:data">>}]); encode({xdata, _, _, _, _, _, _} = X) -> encode_xdata(X, [{<<"xmlns">>, <<"jabber:x:data">>}]); -encode({pubsub_subscription, _, _, _, _} = +encode({ps_subscription, _, _, _, _, _, _} = Subscription) -> - encode_pubsub_subscription(Subscription, - [{<<"xmlns">>, - <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_affiliation, _, _} = Affiliation) -> - encode_pubsub_affiliation(Affiliation, - [{<<"xmlns">>, - <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_item, _, _} = Item) -> - encode_pubsub_item(Item, - [{<<"xmlns">>, - <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_items, _, _, _, _} = Items) -> - encode_pubsub_items(Items, - [{<<"xmlns">>, - <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_event_item, _, _, _, _} = Item) -> - encode_pubsub_event_item(Item, - [{<<"xmlns">>, - <<"http://jabber.org/protocol/pubsub#event">>}]); -encode({pubsub_event_items, _, _, _} = Items) -> - encode_pubsub_event_items(Items, - [{<<"xmlns">>, - <<"http://jabber.org/protocol/pubsub#event">>}]); -encode({pubsub_event, _} = Event) -> + encode_pubsub_subscription(Subscription, []); +encode({ps_affiliation, + <<"http://jabber.org/protocol/pubsub">>, _, _, _} = + Affiliation) -> + encode_pubsub_affiliation(Affiliation, []); +encode({ps_affiliation, + <<"http://jabber.org/protocol/pubsub#owner">>, _, _, + _} = + Affiliation) -> + encode_pubsub_owner_affiliation(Affiliation, []); +encode({ps_item, _, _, _, _, _} = Item) -> + encode_pubsub_item(Item, []); +encode({ps_items, _, _, _, _, _, _} = Items) -> + encode_pubsub_items(Items, []); +encode({ps_event, _, _, _, _, _, _} = Event) -> encode_pubsub_event(Event, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub#event">>}]); -encode({pubsub_subscribe, _, _} = Subscribe) -> +encode({ps_subscribe, _, _} = Subscribe) -> encode_pubsub_subscribe(Subscribe, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_unsubscribe, _, _, _} = Unsubscribe) -> +encode({ps_unsubscribe, _, _, _} = Unsubscribe) -> encode_pubsub_unsubscribe(Unsubscribe, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_publish, _, _} = Publish) -> +encode({ps_publish, _, _} = Publish) -> encode_pubsub_publish(Publish, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_options, _, _, _, _} = Options) -> +encode({ps_options, _, _, _, _} = Options) -> encode_pubsub_options(Options, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_retract, _, _, _} = Retract) -> +encode({ps_retract, _, _, _} = Retract) -> encode_pubsub_retract(Retract, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub, _, _, _, _, _, _, _, _} = Pubsub) -> +encode({pubsub, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _} = + Pubsub) -> encode_pubsub(Pubsub, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); +encode({pubsub_owner, _, _, _, _, _, _} = Pubsub) -> + encode_pubsub_owner(Pubsub, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#owner">>}]); +encode({ps_error, 'closed-node', _} = Closed_node) -> + encode_pubsub_error_closed_node(Closed_node, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'configuration-required', _} = + Configuration_required) -> + encode_pubsub_error_configuration_required(Configuration_required, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'invalid-jid', _} = Invalid_jid) -> + encode_pubsub_error_invalid_jid(Invalid_jid, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'invalid-options', _} = + Invalid_options) -> + encode_pubsub_error_invalid_options(Invalid_options, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'invalid-payload', _} = + Invalid_payload) -> + encode_pubsub_error_invalid_payload(Invalid_payload, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'invalid-subid', _} = + Invalid_subid) -> + encode_pubsub_error_invalid_subid(Invalid_subid, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'item-forbidden', _} = + Item_forbidden) -> + encode_pubsub_error_item_forbidden(Item_forbidden, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'item-required', _} = + Item_required) -> + encode_pubsub_error_item_required(Item_required, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'jid-required', _} = Jid_required) -> + encode_pubsub_error_jid_required(Jid_required, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'max-items-exceeded', _} = + Max_items_exceeded) -> + encode_pubsub_error_max_items_exceeded(Max_items_exceeded, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'max-nodes-exceeded', _} = + Max_nodes_exceeded) -> + encode_pubsub_error_max_nodes_exceeded(Max_nodes_exceeded, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'nodeid-required', _} = + Nodeid_required) -> + encode_pubsub_error_nodeid_required(Nodeid_required, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'not-in-roster-group', _} = + Not_in_roster_group) -> + encode_pubsub_error_not_in_roster_group(Not_in_roster_group, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'not-subscribed', _} = + Not_subscribed) -> + encode_pubsub_error_not_subscribed(Not_subscribed, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'payload-too-big', _} = + Payload_too_big) -> + encode_pubsub_error_payload_too_big(Payload_too_big, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'payload-required', _} = + Payload_required) -> + encode_pubsub_error_payload_required(Payload_required, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'pending-subscription', _} = + Pending_subscription) -> + encode_pubsub_error_pending_subscription(Pending_subscription, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'presence-subscription-required', _} = + Presence_subscription_required) -> + encode_pubsub_error_presence_subscription_required(Presence_subscription_required, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'subid-required', _} = + Subid_required) -> + encode_pubsub_error_subid_required(Subid_required, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'too-many-subscriptions', _} = + Too_many_subscriptions) -> + encode_pubsub_error_too_many_subscriptions(Too_many_subscriptions, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, unsupported, _} = Unsupported) -> + encode_pubsub_error_unsupported(Unsupported, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); +encode({ps_error, 'unsupported-access-model', _} = + Unsupported_access_model) -> + encode_pubsub_error_unsupported_access_model(Unsupported_access_model, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/pubsub#errors">>}]); encode({shim, _} = Headers) -> encode_shim_headers(Headers, [{<<"xmlns">>, <<"http://jabber.org/protocol/shim">>}]); @@ -2581,7 +2999,7 @@ encode({carbons_received, _} = Received) -> encode({carbons_sent, _} = Sent) -> encode_carbons_sent(Sent, [{<<"xmlns">>, <<"urn:xmpp:carbons:2">>}]); -encode({feature_csi, _} = Csi) -> +encode({feature_csi, <<"urn:xmpp:csi:0">>} = Csi) -> encode_feature_csi(Csi, []); encode({csi, active} = Active) -> encode_csi_active(Active, @@ -2717,357 +3135,280 @@ encode({thumbnail, _, _, _, _} = Thumbnail) -> encode_thumbnail(Thumbnail, [{<<"xmlns">>, <<"urn:xmpp:thumbs:1">>}]). -get_name({last, _, _}) -> <<"query">>; -get_name({version, _, _, _}) -> <<"query">>; -get_name({roster_item, _, _, _, _, _}) -> <<"item">>; -get_name({roster_query, _, _}) -> <<"query">>; -get_name({rosterver_feature}) -> <<"ver">>; -get_name({privacy_item, _, _, _, _, _, _, _, _}) -> - <<"item">>; -get_name({privacy_list, _, _}) -> <<"list">>; -get_name({privacy_query, _, _, _}) -> <<"query">>; +get_name({address, _, _, _, _, _}) -> <<"address">>; +get_name({addresses, _}) -> <<"addresses">>; +get_name({adhoc_actions, _, _, _, _}) -> <<"actions">>; +get_name({adhoc_command, _, _, _, _, _, _, _, _}) -> + <<"command">>; +get_name({adhoc_note, _, _}) -> <<"note">>; +get_name({bind, _, _}) -> <<"bind">>; get_name({block, _}) -> <<"block">>; -get_name({unblock, _}) -> <<"unblock">>; get_name({block_list, _}) -> <<"blocklist">>; -get_name({identity, _, _, _, _}) -> <<"identity">>; -get_name({disco_info, _, _, _, _}) -> <<"query">>; -get_name({disco_item, _, _, _}) -> <<"item">>; -get_name({disco_items, _, _, _}) -> <<"query">>; -get_name({private, _}) -> <<"query">>; +get_name({bob_data, _, _, _, _}) -> <<"data">>; get_name({bookmark_conference, _, _, _, _, _}) -> <<"conference">>; -get_name({bookmark_url, _, _}) -> <<"url">>; get_name({bookmark_storage, _, _}) -> <<"storage">>; -get_name({stat_error, _, _}) -> <<"error">>; -get_name({stat, _, _, _, _}) -> <<"stat">>; -get_name({stats, _, _}) -> <<"query">>; -get_name({iq, _, _, _, _, _, _}) -> <<"iq">>; -get_name({message, _, _, _, _, _, _, _, _, _}) -> - <<"message">>; -get_name({presence, _, _, _, _, _, _, _, _, _}) -> - <<"presence">>; -get_name({gone, _}) -> <<"gone">>; -get_name({redirect, _}) -> <<"redirect">>; -get_name({error, _, _, _, _, _, _}) -> <<"error">>; -get_name({bind, _, _}) -> <<"bind">>; -get_name({legacy_auth, _, _, _, _}) -> <<"query">>; -get_name({sasl_auth, _, _}) -> <<"auth">>; -get_name({sasl_abort}) -> <<"abort">>; -get_name({sasl_challenge, _}) -> <<"challenge">>; -get_name({sasl_response, _}) -> <<"response">>; -get_name({sasl_success, _}) -> <<"success">>; -get_name({sasl_failure, _, _}) -> <<"failure">>; -get_name({sasl_mechanisms, _}) -> <<"mechanisms">>; -get_name({starttls, _}) -> <<"starttls">>; -get_name({starttls_proceed}) -> <<"proceed">>; -get_name({starttls_failure}) -> <<"failure">>; -get_name({compress_failure, _}) -> <<"failure">>; -get_name({compress, _}) -> <<"compress">>; -get_name({compressed}) -> <<"compressed">>; -get_name({compression, _}) -> <<"compression">>; -get_name({stream_features, _}) -> <<"stream:features">>; -get_name({p1_push}) -> <<"push">>; -get_name({p1_rebind}) -> <<"rebind">>; -get_name({p1_ack}) -> <<"ack">>; -get_name({caps, _, _, _, _}) -> <<"c">>; -get_name({feature_register}) -> <<"register">>; -get_name({register, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _}) -> - <<"query">>; -get_name({xmpp_session, _}) -> <<"session">>; -get_name({ping}) -> <<"ping">>; -get_name({time, _, _}) -> <<"time">>; -get_name({text, _, _}) -> <<"text">>; -get_name({'see-other-host', _}) -> <<"see-other-host">>; -get_name({stream_error, _, _}) -> <<"stream:error">>; -get_name({vcard_name, _, _, _, _, _}) -> <<"N">>; -get_name({vcard_adr, _, _, _, _, _, _, _, _, _, _, _, _, - _, _}) -> - <<"ADR">>; -get_name({vcard_label, _, _, _, _, _, _, _, _}) -> - <<"LABEL">>; -get_name({vcard_tel, _, _, _, _, _, _, _, _, _, _, _, _, - _, _}) -> - <<"TEL">>; -get_name({vcard_email, _, _, _, _, _, _}) -> - <<"EMAIL">>; -get_name({vcard_geo, _, _}) -> <<"GEO">>; -get_name({vcard_logo, _, _, _}) -> <<"LOGO">>; -get_name({vcard_photo, _, _, _}) -> <<"PHOTO">>; -get_name({vcard_org, _, _}) -> <<"ORG">>; -get_name({vcard_sound, _, _, _}) -> <<"SOUND">>; -get_name({vcard_key, _, _}) -> <<"KEY">>; -get_name({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _}) -> - <<"vCard">>; -get_name({vcard_xupdate, _, _}) -> <<"x">>; -get_name({xdata_option, _, _}) -> <<"option">>; -get_name({xdata_field, _, _, _, _, _, _, _, _}) -> - <<"field">>; -get_name({xdata, _, _, _, _, _, _}) -> <<"x">>; -get_name({pubsub_subscription, _, _, _, _}) -> - <<"subscription">>; -get_name({pubsub_affiliation, _, _}) -> - <<"affiliation">>; -get_name({pubsub_item, _, _}) -> <<"item">>; -get_name({pubsub_items, _, _, _, _}) -> <<"items">>; -get_name({pubsub_event_item, _, _, _, _}) -> <<"item">>; -get_name({pubsub_event_items, _, _, _}) -> <<"items">>; -get_name({pubsub_event, _}) -> <<"event">>; -get_name({pubsub_subscribe, _, _}) -> <<"subscribe">>; -get_name({pubsub_unsubscribe, _, _, _}) -> - <<"unsubscribe">>; -get_name({pubsub_publish, _, _}) -> <<"publish">>; -get_name({pubsub_options, _, _, _, _}) -> <<"options">>; -get_name({pubsub_retract, _, _, _}) -> <<"retract">>; -get_name({pubsub, _, _, _, _, _, _, _, _}) -> - <<"pubsub">>; -get_name({shim, _}) -> <<"headers">>; -get_name({chatstate, active}) -> <<"active">>; -get_name({chatstate, composing}) -> <<"composing">>; -get_name({chatstate, gone}) -> <<"gone">>; -get_name({chatstate, inactive}) -> <<"inactive">>; -get_name({chatstate, paused}) -> <<"paused">>; -get_name({delay, _, _, _}) -> <<"delay">>; -get_name({streamhost, _, _, _}) -> <<"streamhost">>; +get_name({bookmark_url, _, _}) -> <<"url">>; get_name({bytestreams, _, _, _, _, _, _}) -> <<"query">>; -get_name({muc_history, _, _, _, _}) -> <<"history">>; -get_name({muc_decline, _, _, _}) -> <<"decline">>; -get_name({muc_destroy, _, _, _, _}) -> <<"destroy">>; -get_name({muc_invite, _, _, _, _}) -> <<"invite">>; -get_name({muc_user, _, _, _, _, _, _}) -> <<"x">>; -get_name({muc_owner, _, _, _}) -> <<"query">>; -get_name({muc_item, _, _, _, _, _, _, _}) -> <<"item">>; -get_name({muc_actor, _, _}) -> <<"actor">>; -get_name({muc_admin, _}) -> <<"query">>; -get_name({muc, _, _}) -> <<"x">>; -get_name({muc_unique, _}) -> <<"unique">>; -get_name({x_conference, _, _, _, _, _}) -> <<"x">>; -get_name({muc_subscriptions, _}) -> <<"subscriptions">>; -get_name({muc_subscribe, _, _}) -> <<"subscribe">>; -get_name({muc_unsubscribe}) -> <<"unsubscribe">>; -get_name({rsm_first, _, _}) -> <<"first">>; -get_name({rsm_set, _, _, _, _, _, _, _}) -> <<"set">>; -get_name({mam_query, _, _, _, _, _, _, _, _}) -> - <<"query">>; -get_name({mam_archived, _, _}) -> <<"archived">>; -get_name({mam_result, _, _, _, _}) -> <<"result">>; -get_name({mam_prefs, _, _, _, _}) -> <<"prefs">>; -get_name({mam_fin, _, _, _, _}) -> <<"fin">>; -get_name({forwarded, _, _}) -> <<"forwarded">>; +get_name({caps, _, _, _, _}) -> <<"c">>; get_name({carbons_disable}) -> <<"disable">>; get_name({carbons_enable}) -> <<"enable">>; get_name({carbons_private}) -> <<"private">>; get_name({carbons_received, _}) -> <<"received">>; get_name({carbons_sent, _}) -> <<"sent">>; -get_name({feature_csi, _}) -> <<"csi">>; +get_name({chatstate, active}) -> <<"active">>; +get_name({chatstate, composing}) -> <<"composing">>; +get_name({chatstate, gone}) -> <<"gone">>; +get_name({chatstate, inactive}) -> <<"inactive">>; +get_name({chatstate, paused}) -> <<"paused">>; +get_name({client_id, _}) -> <<"client-id">>; +get_name({compress, _}) -> <<"compress">>; +get_name({compress_failure, _}) -> <<"failure">>; +get_name({compressed}) -> <<"compressed">>; +get_name({compression, _}) -> <<"compression">>; get_name({csi, active}) -> <<"active">>; get_name({csi, inactive}) -> <<"inactive">>; -get_name({feature_sm, _}) -> <<"sm">>; -get_name({sm_enable, _, _, _}) -> <<"enable">>; -get_name({sm_enabled, _, _, _, _, _}) -> <<"enabled">>; -get_name({sm_resume, _, _, _}) -> <<"resume">>; -get_name({sm_resumed, _, _, _}) -> <<"resumed">>; -get_name({sm_r, _}) -> <<"r">>; -get_name({sm_a, _, _}) -> <<"a">>; -get_name({sm_failed, _, _, _}) -> <<"failed">>; -get_name({offline_item, _, _}) -> <<"item">>; -get_name({offline, _, _, _}) -> <<"offline">>; -get_name({mix_join, _, _}) -> <<"join">>; -get_name({mix_leave}) -> <<"leave">>; -get_name({mix_participant, _, _}) -> <<"participant">>; -get_name({hint, 'no-copy'}) -> <<"no-copy">>; -get_name({hint, 'no-store'}) -> <<"no-store">>; -get_name({hint, 'no-storage'}) -> <<"no-storage">>; -get_name({hint, store}) -> <<"store">>; -get_name({hint, 'no-permanent-store'}) -> - <<"no-permanent-store">>; -get_name({hint, 'no-permanent-storage'}) -> - <<"no-permanent-storage">>; -get_name({search_item, _, _, _, _, _}) -> <<"item">>; -get_name({search, _, _, _, _, _, _, _}) -> <<"query">>; -get_name({xevent, _, _, _, _, _}) -> <<"x">>; -get_name({expire, _, _}) -> <<"x">>; -get_name({nick, _}) -> <<"nick">>; -get_name({address, _, _, _, _, _}) -> <<"address">>; -get_name({addresses, _}) -> <<"addresses">>; -get_name({stanza_id, _, _}) -> <<"stanza-id">>; -get_name({client_id, _}) -> <<"client-id">>; -get_name({adhoc_actions, _, _, _, _}) -> <<"actions">>; -get_name({adhoc_note, _, _}) -> <<"note">>; -get_name({adhoc_command, _, _, _, _, _, _, _, _}) -> - <<"command">>; get_name({db_result, _, _, _, _, _}) -> <<"db:result">>; get_name({db_verify, _, _, _, _, _, _}) -> <<"db:verify">>; +get_name({delay, _, _, _}) -> <<"delay">>; +get_name({disco_info, _, _, _, _}) -> <<"query">>; +get_name({disco_item, _, _, _}) -> <<"item">>; +get_name({disco_items, _, _, _}) -> <<"query">>; +get_name({error, _, _, _, _, _, _}) -> <<"error">>; +get_name({expire, _, _}) -> <<"x">>; +get_name({feature_csi, _}) -> <<"csi">>; +get_name({feature_register}) -> <<"register">>; +get_name({feature_sm, _}) -> <<"sm">>; +get_name({forwarded, _, _}) -> <<"forwarded">>; +get_name({gone, _}) -> <<"gone">>; get_name({handshake, _}) -> <<"handshake">>; +get_name({hint, 'no-copy'}) -> <<"no-copy">>; +get_name({hint, 'no-permanent-storage'}) -> + <<"no-permanent-storage">>; +get_name({hint, 'no-permanent-store'}) -> + <<"no-permanent-store">>; +get_name({hint, 'no-storage'}) -> <<"no-storage">>; +get_name({hint, 'no-store'}) -> <<"no-store">>; +get_name({hint, store}) -> <<"store">>; +get_name({identity, _, _, _, _}) -> <<"identity">>; +get_name({iq, _, _, _, _, _, _}) -> <<"iq">>; +get_name({last, _, _}) -> <<"query">>; +get_name({legacy_auth, _, _, _, _}) -> <<"query">>; +get_name({mam_archived, _, _}) -> <<"archived">>; +get_name({mam_fin, _, _, _, _}) -> <<"fin">>; +get_name({mam_prefs, _, _, _, _}) -> <<"prefs">>; +get_name({mam_query, _, _, _, _, _, _, _, _}) -> + <<"query">>; +get_name({mam_result, _, _, _, _}) -> <<"result">>; +get_name({media, _, _, _}) -> <<"media">>; +get_name({media_uri, _, _}) -> <<"uri">>; +get_name({message, _, _, _, _, _, _, _, _, _}) -> + <<"message">>; +get_name({mix_join, _, _}) -> <<"join">>; +get_name({mix_leave}) -> <<"leave">>; +get_name({mix_participant, _, _}) -> <<"participant">>; +get_name({muc, _, _}) -> <<"x">>; +get_name({muc_actor, _, _}) -> <<"actor">>; +get_name({muc_admin, _}) -> <<"query">>; +get_name({muc_decline, _, _, _}) -> <<"decline">>; +get_name({muc_destroy, _, _, _, _}) -> <<"destroy">>; +get_name({muc_history, _, _, _, _}) -> <<"history">>; +get_name({muc_invite, _, _, _, _}) -> <<"invite">>; +get_name({muc_item, _, _, _, _, _, _, _}) -> <<"item">>; +get_name({muc_owner, _, _, _}) -> <<"query">>; +get_name({muc_subscribe, _, _}) -> <<"subscribe">>; +get_name({muc_subscriptions, _}) -> <<"subscriptions">>; +get_name({muc_unique, _}) -> <<"unique">>; +get_name({muc_unsubscribe}) -> <<"unsubscribe">>; +get_name({muc_user, _, _, _, _, _, _}) -> <<"x">>; +get_name({nick, _}) -> <<"nick">>; +get_name({offline, _, _, _}) -> <<"offline">>; +get_name({offline_item, _, _}) -> <<"item">>; +get_name({oob_x, _, _, _}) -> <<"x">>; +get_name({p1_ack}) -> <<"ack">>; +get_name({p1_push}) -> <<"push">>; +get_name({p1_rebind}) -> <<"rebind">>; +get_name({ping}) -> <<"ping">>; +get_name({presence, _, _, _, _, _, _, _, _, _}) -> + <<"presence">>; +get_name({privacy_item, _, _, _, _, _, _, _, _}) -> + <<"item">>; +get_name({privacy_list, _, _}) -> <<"list">>; +get_name({privacy_query, _, _, _}) -> <<"query">>; +get_name({private, _}) -> <<"query">>; +get_name({ps_affiliation, _, _, _, _}) -> + <<"affiliation">>; +get_name({ps_error, 'closed-node', _}) -> + <<"closed-node">>; +get_name({ps_error, 'configuration-required', _}) -> + <<"configuration-required">>; +get_name({ps_error, 'invalid-jid', _}) -> + <<"invalid-jid">>; +get_name({ps_error, 'invalid-options', _}) -> + <<"invalid-options">>; +get_name({ps_error, 'invalid-payload', _}) -> + <<"invalid-payload">>; +get_name({ps_error, 'invalid-subid', _}) -> + <<"invalid-subid">>; +get_name({ps_error, 'item-forbidden', _}) -> + <<"item-forbidden">>; +get_name({ps_error, 'item-required', _}) -> + <<"item-required">>; +get_name({ps_error, 'jid-required', _}) -> + <<"jid-required">>; +get_name({ps_error, 'max-items-exceeded', _}) -> + <<"max-items-exceeded">>; +get_name({ps_error, 'max-nodes-exceeded', _}) -> + <<"max-nodes-exceeded">>; +get_name({ps_error, 'nodeid-required', _}) -> + <<"nodeid-required">>; +get_name({ps_error, 'not-in-roster-group', _}) -> + <<"not-in-roster-group">>; +get_name({ps_error, 'not-subscribed', _}) -> + <<"not-subscribed">>; +get_name({ps_error, 'payload-required', _}) -> + <<"payload-required">>; +get_name({ps_error, 'payload-too-big', _}) -> + <<"payload-too-big">>; +get_name({ps_error, 'pending-subscription', _}) -> + <<"pending-subscription">>; +get_name({ps_error, 'presence-subscription-required', + _}) -> + <<"presence-subscription-required">>; +get_name({ps_error, 'subid-required', _}) -> + <<"subid-required">>; +get_name({ps_error, 'too-many-subscriptions', _}) -> + <<"too-many-subscriptions">>; +get_name({ps_error, unsupported, _}) -> + <<"unsupported">>; +get_name({ps_error, 'unsupported-access-model', _}) -> + <<"unsupported-access-model">>; +get_name({ps_event, _, _, _, _, _, _}) -> <<"event">>; +get_name({ps_item, _, _, _, _, _}) -> <<"item">>; +get_name({ps_items, _, _, _, _, _, _}) -> <<"items">>; +get_name({ps_options, _, _, _, _}) -> <<"options">>; +get_name({ps_publish, _, _}) -> <<"publish">>; +get_name({ps_retract, _, _, _}) -> <<"retract">>; +get_name({ps_subscribe, _, _}) -> <<"subscribe">>; +get_name({ps_subscription, _, _, _, _, _, _}) -> + <<"subscription">>; +get_name({ps_unsubscribe, _, _, _}) -> + <<"unsubscribe">>; +get_name({pubsub, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _}) -> + <<"pubsub">>; +get_name({pubsub_owner, _, _, _, _, _, _}) -> + <<"pubsub">>; +get_name({redirect, _}) -> <<"redirect">>; +get_name({register, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _}) -> + <<"query">>; +get_name({roster_item, _, _, _, _, _}) -> <<"item">>; +get_name({roster_query, _, _}) -> <<"query">>; +get_name({rosterver_feature}) -> <<"ver">>; +get_name({rsm_first, _, _}) -> <<"first">>; +get_name({rsm_set, _, _, _, _, _, _, _}) -> <<"set">>; +get_name({sasl_abort}) -> <<"abort">>; +get_name({sasl_auth, _, _}) -> <<"auth">>; +get_name({sasl_challenge, _}) -> <<"challenge">>; +get_name({sasl_failure, _, _}) -> <<"failure">>; +get_name({sasl_mechanisms, _}) -> <<"mechanisms">>; +get_name({sasl_response, _}) -> <<"response">>; +get_name({sasl_success, _}) -> <<"success">>; +get_name({search, _, _, _, _, _, _, _}) -> <<"query">>; +get_name({search_item, _, _, _, _, _}) -> <<"item">>; +get_name({'see-other-host', _}) -> <<"see-other-host">>; +get_name({shim, _}) -> <<"headers">>; +get_name({sic, _, _, _}) -> <<"address">>; +get_name({sm_a, _, _}) -> <<"a">>; +get_name({sm_enable, _, _, _}) -> <<"enable">>; +get_name({sm_enabled, _, _, _, _, _}) -> <<"enabled">>; +get_name({sm_failed, _, _, _}) -> <<"failed">>; +get_name({sm_r, _}) -> <<"r">>; +get_name({sm_resume, _, _, _}) -> <<"resume">>; +get_name({sm_resumed, _, _, _}) -> <<"resumed">>; +get_name({stanza_id, _, _}) -> <<"stanza-id">>; +get_name({starttls, _}) -> <<"starttls">>; +get_name({starttls_failure}) -> <<"failure">>; +get_name({starttls_proceed}) -> <<"proceed">>; +get_name({stat, _, _, _, _}) -> <<"stat">>; +get_name({stat_error, _, _}) -> <<"error">>; +get_name({stats, _, _}) -> <<"query">>; +get_name({stream_error, _, _}) -> <<"stream:error">>; +get_name({stream_features, _}) -> <<"stream:features">>; get_name({stream_start, _, _, _, _, _, _, _, _}) -> <<"stream:stream">>; -get_name({bob_data, _, _, _, _}) -> <<"data">>; -get_name({xcaptcha, _}) -> <<"captcha">>; -get_name({media_uri, _, _}) -> <<"uri">>; -get_name({media, _, _, _}) -> <<"media">>; -get_name({oob_x, _, _, _}) -> <<"x">>; -get_name({sic, _, _, _}) -> <<"address">>; +get_name({streamhost, _, _, _}) -> <<"streamhost">>; +get_name({text, _, _}) -> <<"text">>; +get_name({thumbnail, _, _, _, _}) -> <<"thumbnail">>; +get_name({time, _, _}) -> <<"time">>; +get_name({unblock, _}) -> <<"unblock">>; get_name({upload_request, _, _, _, _}) -> <<"request">>; get_name({upload_slot, _, _, _}) -> <<"slot">>; -get_name({thumbnail, _, _, _, _}) -> <<"thumbnail">>. +get_name({vcard_adr, _, _, _, _, _, _, _, _, _, _, _, _, + _, _}) -> + <<"ADR">>; +get_name({vcard_email, _, _, _, _, _, _}) -> + <<"EMAIL">>; +get_name({vcard_geo, _, _}) -> <<"GEO">>; +get_name({vcard_key, _, _}) -> <<"KEY">>; +get_name({vcard_label, _, _, _, _, _, _, _, _}) -> + <<"LABEL">>; +get_name({vcard_logo, _, _, _}) -> <<"LOGO">>; +get_name({vcard_name, _, _, _, _, _}) -> <<"N">>; +get_name({vcard_org, _, _}) -> <<"ORG">>; +get_name({vcard_photo, _, _, _}) -> <<"PHOTO">>; +get_name({vcard_sound, _, _, _}) -> <<"SOUND">>; +get_name({vcard_tel, _, _, _, _, _, _, _, _, _, _, _, _, + _, _}) -> + <<"TEL">>; +get_name({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _}) -> + <<"vCard">>; +get_name({vcard_xupdate, _, _}) -> <<"x">>; +get_name({version, _, _, _}) -> <<"query">>; +get_name({x_conference, _, _, _, _, _}) -> <<"x">>; +get_name({xcaptcha, _}) -> <<"captcha">>; +get_name({xdata, _, _, _, _, _, _}) -> <<"x">>; +get_name({xdata_field, _, _, _, _, _, _, _, _}) -> + <<"field">>; +get_name({xdata_option, _, _}) -> <<"option">>; +get_name({xevent, _, _, _, _, _}) -> <<"x">>; +get_name({xmpp_session, _}) -> <<"session">>. -get_ns({last, _, _}) -> <<"jabber:iq:last">>; -get_ns({version, _, _, _}) -> <<"jabber:iq:version">>; -get_ns({roster_item, _, _, _, _, _}) -> - <<"jabber:iq:roster">>; -get_ns({roster_query, _, _}) -> <<"jabber:iq:roster">>; -get_ns({rosterver_feature}) -> - <<"urn:xmpp:features:rosterver">>; -get_ns({privacy_item, _, _, _, _, _, _, _, _}) -> - <<"jabber:iq:privacy">>; -get_ns({privacy_list, _, _}) -> <<"jabber:iq:privacy">>; -get_ns({privacy_query, _, _, _}) -> - <<"jabber:iq:privacy">>; -get_ns({block, _}) -> <<"urn:xmpp:blocking">>; -get_ns({unblock, _}) -> <<"urn:xmpp:blocking">>; -get_ns({block_list, _}) -> <<"urn:xmpp:blocking">>; -get_ns({identity, _, _, _, _}) -> - <<"http://jabber.org/protocol/disco#info">>; -get_ns({disco_info, _, _, _, _}) -> - <<"http://jabber.org/protocol/disco#info">>; -get_ns({disco_item, _, _, _}) -> - <<"http://jabber.org/protocol/disco#items">>; -get_ns({disco_items, _, _, _}) -> - <<"http://jabber.org/protocol/disco#items">>; -get_ns({private, _}) -> <<"jabber:iq:private">>; -get_ns({bookmark_conference, _, _, _, _, _}) -> - <<"storage:bookmarks">>; -get_ns({bookmark_url, _, _}) -> <<"storage:bookmarks">>; -get_ns({bookmark_storage, _, _}) -> - <<"storage:bookmarks">>; -get_ns({stat_error, _, _}) -> - <<"http://jabber.org/protocol/stats">>; -get_ns({stat, _, _, _, _}) -> - <<"http://jabber.org/protocol/stats">>; -get_ns({stats, _, _}) -> - <<"http://jabber.org/protocol/stats">>; -get_ns({iq, _, _, _, _, _, _}) -> <<"jabber:client">>; -get_ns({message, _, _, _, _, _, _, _, _, _}) -> - <<"jabber:client">>; -get_ns({presence, _, _, _, _, _, _, _, _, _}) -> - <<"jabber:client">>; -get_ns({gone, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-stanzas">>; -get_ns({redirect, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-stanzas">>; -get_ns({error, _, _, _, _, _, _}) -> - <<"jabber:client">>; +get_ns({address, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/address">>; +get_ns({addresses, _}) -> + <<"http://jabber.org/protocol/address">>; +get_ns({adhoc_actions, _, _, _, _}) -> + <<"http://jabber.org/protocol/commands">>; +get_ns({adhoc_command, _, _, _, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/commands">>; +get_ns({adhoc_note, _, _}) -> + <<"http://jabber.org/protocol/commands">>; get_ns({bind, _, _}) -> <<"urn:ietf:params:xml:ns:xmpp-bind">>; -get_ns({legacy_auth, _, _, _, _}) -> - <<"jabber:iq:auth">>; -get_ns({sasl_auth, _, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-sasl">>; -get_ns({sasl_abort}) -> - <<"urn:ietf:params:xml:ns:xmpp-sasl">>; -get_ns({sasl_challenge, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-sasl">>; -get_ns({sasl_response, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-sasl">>; -get_ns({sasl_success, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-sasl">>; -get_ns({sasl_failure, _, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-sasl">>; -get_ns({sasl_mechanisms, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-sasl">>; -get_ns({starttls, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-tls">>; -get_ns({starttls_proceed}) -> - <<"urn:ietf:params:xml:ns:xmpp-tls">>; -get_ns({starttls_failure}) -> - <<"urn:ietf:params:xml:ns:xmpp-tls">>; -get_ns({compress_failure, _}) -> - <<"http://jabber.org/protocol/compress">>; -get_ns({compress, _}) -> - <<"http://jabber.org/protocol/compress">>; -get_ns({compressed}) -> - <<"http://jabber.org/protocol/compress">>; -get_ns({compression, _}) -> - <<"http://jabber.org/features/compress">>; -get_ns({stream_features, _}) -> - <<"http://etherx.jabber.org/streams">>; -get_ns({p1_push}) -> <<"p1:push">>; -get_ns({p1_rebind}) -> <<"p1:rebind">>; -get_ns({p1_ack}) -> <<"p1:ack">>; +get_ns({block, _}) -> <<"urn:xmpp:blocking">>; +get_ns({block_list, _}) -> <<"urn:xmpp:blocking">>; +get_ns({bob_data, _, _, _, _}) -> <<"urn:xmpp:bob">>; +get_ns({bookmark_conference, _, _, _, _, _}) -> + <<"storage:bookmarks">>; +get_ns({bookmark_storage, _, _}) -> + <<"storage:bookmarks">>; +get_ns({bookmark_url, _, _}) -> <<"storage:bookmarks">>; +get_ns({bytestreams, _, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/bytestreams">>; get_ns({caps, _, _, _, _}) -> <<"http://jabber.org/protocol/caps">>; -get_ns({feature_register}) -> - <<"http://jabber.org/features/iq-register">>; -get_ns({register, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _}) -> - <<"jabber:iq:register">>; -get_ns({xmpp_session, _}) -> - <<"urn:ietf:params:xml:ns:xmpp-session">>; -get_ns({ping}) -> <<"urn:xmpp:ping">>; -get_ns({time, _, _}) -> <<"urn:xmpp:time">>; -get_ns({'see-other-host', _}) -> - <<"urn:ietf:params:xml:ns:xmpp-streams">>; -get_ns({stream_error, _, _}) -> - <<"http://etherx.jabber.org/streams">>; -get_ns({vcard_name, _, _, _, _, _}) -> <<"vcard-temp">>; -get_ns({vcard_adr, _, _, _, _, _, _, _, _, _, _, _, _, - _, _}) -> - <<"vcard-temp">>; -get_ns({vcard_label, _, _, _, _, _, _, _, _}) -> - <<"vcard-temp">>; -get_ns({vcard_tel, _, _, _, _, _, _, _, _, _, _, _, _, - _, _}) -> - <<"vcard-temp">>; -get_ns({vcard_email, _, _, _, _, _, _}) -> - <<"vcard-temp">>; -get_ns({vcard_geo, _, _}) -> <<"vcard-temp">>; -get_ns({vcard_logo, _, _, _}) -> <<"vcard-temp">>; -get_ns({vcard_photo, _, _, _}) -> <<"vcard-temp">>; -get_ns({vcard_org, _, _}) -> <<"vcard-temp">>; -get_ns({vcard_sound, _, _, _}) -> <<"vcard-temp">>; -get_ns({vcard_key, _, _}) -> <<"vcard-temp">>; -get_ns({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> - <<"vcard-temp">>; -get_ns({vcard_xupdate, _, _}) -> - <<"vcard-temp:x:update">>; -get_ns({xdata_option, _, _}) -> <<"jabber:x:data">>; -get_ns({xdata_field, _, _, _, _, _, _, _, _}) -> - <<"jabber:x:data">>; -get_ns({xdata, _, _, _, _, _, _}) -> - <<"jabber:x:data">>; -get_ns({pubsub_subscription, _, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_affiliation, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_item, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_items, _, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_event_item, _, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub#event">>; -get_ns({pubsub_event_items, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub#event">>; -get_ns({pubsub_event, _}) -> - <<"http://jabber.org/protocol/pubsub#event">>; -get_ns({pubsub_subscribe, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_unsubscribe, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_publish, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_options, _, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_retract, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub, _, _, _, _, _, _, _, _}) -> - <<"http://jabber.org/protocol/pubsub">>; -get_ns({shim, _}) -> - <<"http://jabber.org/protocol/shim">>; +get_ns({carbons_disable}) -> <<"urn:xmpp:carbons:2">>; +get_ns({carbons_enable}) -> <<"urn:xmpp:carbons:2">>; +get_ns({carbons_private}) -> <<"urn:xmpp:carbons:2">>; +get_ns({carbons_received, _}) -> + <<"urn:xmpp:carbons:2">>; +get_ns({carbons_sent, _}) -> <<"urn:xmpp:carbons:2">>; get_ns({chatstate, active}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({chatstate, composing}) -> @@ -3078,117 +3419,281 @@ get_ns({chatstate, inactive}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({chatstate, paused}) -> <<"http://jabber.org/protocol/chatstates">>; -get_ns({delay, _, _, _}) -> <<"urn:xmpp:delay">>; -get_ns({streamhost, _, _, _}) -> - <<"http://jabber.org/protocol/bytestreams">>; -get_ns({bytestreams, _, _, _, _, _, _}) -> - <<"http://jabber.org/protocol/bytestreams">>; -get_ns({muc_history, _, _, _, _}) -> - <<"http://jabber.org/protocol/muc">>; -get_ns({muc_decline, _, _, _}) -> - <<"http://jabber.org/protocol/muc#user">>; -get_ns({muc_destroy, Xmlns, _, _, _}) -> Xmlns; -get_ns({muc_invite, _, _, _, _}) -> - <<"http://jabber.org/protocol/muc#user">>; -get_ns({muc_user, _, _, _, _, _, _}) -> - <<"http://jabber.org/protocol/muc#user">>; -get_ns({muc_owner, _, _, _}) -> - <<"http://jabber.org/protocol/muc#owner">>; -get_ns({muc_admin, _}) -> - <<"http://jabber.org/protocol/muc#admin">>; -get_ns({muc, _, _}) -> - <<"http://jabber.org/protocol/muc">>; -get_ns({muc_unique, _}) -> - <<"http://jabber.org/protocol/muc#unique">>; -get_ns({x_conference, _, _, _, _, _}) -> - <<"jabber:x:conference">>; -get_ns({muc_subscriptions, _}) -> - <<"urn:xmpp:mucsub:0">>; -get_ns({muc_subscribe, _, _}) -> - <<"urn:xmpp:mucsub:0">>; -get_ns({muc_unsubscribe}) -> <<"urn:xmpp:mucsub:0">>; -get_ns({rsm_first, _, _}) -> - <<"http://jabber.org/protocol/rsm">>; -get_ns({rsm_set, _, _, _, _, _, _, _}) -> - <<"http://jabber.org/protocol/rsm">>; -get_ns({mam_query, Xmlns, _, _, _, _, _, _, _}) -> - Xmlns; -get_ns({mam_archived, _, _}) -> <<"urn:xmpp:mam:tmp">>; -get_ns({mam_result, Xmlns, _, _, _}) -> Xmlns; -get_ns({mam_prefs, Xmlns, _, _, _}) -> Xmlns; -get_ns({mam_fin, _, _, _, _}) -> <<"urn:xmpp:mam:0">>; -get_ns({forwarded, _, _}) -> <<"urn:xmpp:forward:0">>; -get_ns({carbons_disable}) -> <<"urn:xmpp:carbons:2">>; -get_ns({carbons_enable}) -> <<"urn:xmpp:carbons:2">>; -get_ns({carbons_private}) -> <<"urn:xmpp:carbons:2">>; -get_ns({carbons_received, _}) -> - <<"urn:xmpp:carbons:2">>; -get_ns({carbons_sent, _}) -> <<"urn:xmpp:carbons:2">>; -get_ns({feature_csi, Xmlns}) -> Xmlns; +get_ns({client_id, _}) -> <<"urn:xmpp:sid:0">>; +get_ns({compress, _}) -> + <<"http://jabber.org/protocol/compress">>; +get_ns({compress_failure, _}) -> + <<"http://jabber.org/protocol/compress">>; +get_ns({compressed}) -> + <<"http://jabber.org/protocol/compress">>; +get_ns({compression, _}) -> + <<"http://jabber.org/features/compress">>; get_ns({csi, active}) -> <<"urn:xmpp:csi:0">>; get_ns({csi, inactive}) -> <<"urn:xmpp:csi:0">>; -get_ns({feature_sm, Xmlns}) -> Xmlns; -get_ns({sm_enable, _, _, Xmlns}) -> Xmlns; -get_ns({sm_enabled, _, _, _, _, Xmlns}) -> Xmlns; -get_ns({sm_resume, _, _, Xmlns}) -> Xmlns; -get_ns({sm_resumed, _, _, Xmlns}) -> Xmlns; -get_ns({sm_r, Xmlns}) -> Xmlns; -get_ns({sm_a, _, Xmlns}) -> Xmlns; -get_ns({sm_failed, _, _, Xmlns}) -> Xmlns; -get_ns({offline_item, _, _}) -> - <<"http://jabber.org/protocol/offline">>; -get_ns({offline, _, _, _}) -> - <<"http://jabber.org/protocol/offline">>; -get_ns({mix_join, _, _}) -> <<"urn:xmpp:mix:0">>; -get_ns({mix_leave}) -> <<"urn:xmpp:mix:0">>; -get_ns({mix_participant, _, _}) -> <<"urn:xmpp:mix:0">>; -get_ns({hint, 'no-copy'}) -> <<"urn:xmpp:hints">>; -get_ns({hint, 'no-store'}) -> <<"urn:xmpp:hints">>; -get_ns({hint, 'no-storage'}) -> <<"urn:xmpp:hints">>; -get_ns({hint, store}) -> <<"urn:xmpp:hints">>; -get_ns({hint, 'no-permanent-store'}) -> - <<"urn:xmpp:hints">>; -get_ns({hint, 'no-permanent-storage'}) -> - <<"urn:xmpp:hints">>; -get_ns({search_item, _, _, _, _, _}) -> - <<"jabber:iq:search">>; -get_ns({search, _, _, _, _, _, _, _}) -> - <<"jabber:iq:search">>; -get_ns({xevent, _, _, _, _, _}) -> <<"jabber:x:event">>; -get_ns({expire, _, _}) -> <<"jabber:x:expire">>; -get_ns({nick, _}) -> - <<"http://jabber.org/protocol/nick">>; -get_ns({address, _, _, _, _, _}) -> - <<"http://jabber.org/protocol/address">>; -get_ns({addresses, _}) -> - <<"http://jabber.org/protocol/address">>; -get_ns({stanza_id, _, _}) -> <<"urn:xmpp:sid:0">>; -get_ns({client_id, _}) -> <<"urn:xmpp:sid:0">>; -get_ns({adhoc_actions, _, _, _, _}) -> - <<"http://jabber.org/protocol/commands">>; -get_ns({adhoc_note, _, _}) -> - <<"http://jabber.org/protocol/commands">>; -get_ns({adhoc_command, _, _, _, _, _, _, _, _}) -> - <<"http://jabber.org/protocol/commands">>; get_ns({db_result, _, _, _, _, _}) -> <<"jabber:client">>; get_ns({db_verify, _, _, _, _, _, _}) -> <<"jabber:client">>; +get_ns({delay, _, _, _}) -> <<"urn:xmpp:delay">>; +get_ns({disco_info, _, _, _, _}) -> + <<"http://jabber.org/protocol/disco#info">>; +get_ns({disco_item, _, _, _}) -> + <<"http://jabber.org/protocol/disco#items">>; +get_ns({disco_items, _, _, _}) -> + <<"http://jabber.org/protocol/disco#items">>; +get_ns({error, _, _, _, _, _, _}) -> + <<"jabber:client">>; +get_ns({expire, _, _}) -> <<"jabber:x:expire">>; +get_ns({feature_csi, Xmlns}) -> Xmlns; +get_ns({feature_register}) -> + <<"http://jabber.org/features/iq-register">>; +get_ns({feature_sm, Xmlns}) -> Xmlns; +get_ns({forwarded, _, _}) -> <<"urn:xmpp:forward:0">>; +get_ns({gone, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-stanzas">>; get_ns({handshake, _}) -> <<"jabber:client">>; -get_ns({stream_start, _, _, _, _, Xmlns, _, _, _}) -> +get_ns({hint, 'no-copy'}) -> <<"urn:xmpp:hints">>; +get_ns({hint, 'no-permanent-storage'}) -> + <<"urn:xmpp:hints">>; +get_ns({hint, 'no-permanent-store'}) -> + <<"urn:xmpp:hints">>; +get_ns({hint, 'no-storage'}) -> <<"urn:xmpp:hints">>; +get_ns({hint, 'no-store'}) -> <<"urn:xmpp:hints">>; +get_ns({hint, store}) -> <<"urn:xmpp:hints">>; +get_ns({identity, _, _, _, _}) -> + <<"http://jabber.org/protocol/disco#info">>; +get_ns({iq, _, _, _, _, _, _}) -> <<"jabber:client">>; +get_ns({last, _, _}) -> <<"jabber:iq:last">>; +get_ns({legacy_auth, _, _, _, _}) -> + <<"jabber:iq:auth">>; +get_ns({mam_archived, _, _}) -> <<"urn:xmpp:mam:tmp">>; +get_ns({mam_fin, _, _, _, _}) -> <<"urn:xmpp:mam:0">>; +get_ns({mam_prefs, Xmlns, _, _, _}) -> Xmlns; +get_ns({mam_query, Xmlns, _, _, _, _, _, _, _}) -> Xmlns; -get_ns({bob_data, _, _, _, _}) -> <<"urn:xmpp:bob">>; -get_ns({xcaptcha, _}) -> <<"urn:xmpp:captcha">>; -get_ns({media_uri, _, _}) -> - <<"urn:xmpp:media-element">>; +get_ns({mam_result, Xmlns, _, _, _}) -> Xmlns; get_ns({media, _, _, _}) -> <<"urn:xmpp:media-element">>; +get_ns({media_uri, _, _}) -> + <<"urn:xmpp:media-element">>; +get_ns({message, _, _, _, _, _, _, _, _, _}) -> + <<"jabber:client">>; +get_ns({mix_join, _, _}) -> <<"urn:xmpp:mix:0">>; +get_ns({mix_leave}) -> <<"urn:xmpp:mix:0">>; +get_ns({mix_participant, _, _}) -> <<"urn:xmpp:mix:0">>; +get_ns({muc, _, _}) -> + <<"http://jabber.org/protocol/muc">>; +get_ns({muc_admin, _}) -> + <<"http://jabber.org/protocol/muc#admin">>; +get_ns({muc_decline, _, _, _}) -> + <<"http://jabber.org/protocol/muc#user">>; +get_ns({muc_destroy, Xmlns, _, _, _}) -> Xmlns; +get_ns({muc_history, _, _, _, _}) -> + <<"http://jabber.org/protocol/muc">>; +get_ns({muc_invite, _, _, _, _}) -> + <<"http://jabber.org/protocol/muc#user">>; +get_ns({muc_owner, _, _, _}) -> + <<"http://jabber.org/protocol/muc#owner">>; +get_ns({muc_subscribe, _, _}) -> + <<"urn:xmpp:mucsub:0">>; +get_ns({muc_subscriptions, _}) -> + <<"urn:xmpp:mucsub:0">>; +get_ns({muc_unique, _}) -> + <<"http://jabber.org/protocol/muc#unique">>; +get_ns({muc_unsubscribe}) -> <<"urn:xmpp:mucsub:0">>; +get_ns({muc_user, _, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/muc#user">>; +get_ns({nick, _}) -> + <<"http://jabber.org/protocol/nick">>; +get_ns({offline, _, _, _}) -> + <<"http://jabber.org/protocol/offline">>; +get_ns({offline_item, _, _}) -> + <<"http://jabber.org/protocol/offline">>; get_ns({oob_x, _, _, _}) -> <<"jabber:x:oob">>; +get_ns({p1_ack}) -> <<"p1:ack">>; +get_ns({p1_push}) -> <<"p1:push">>; +get_ns({p1_rebind}) -> <<"p1:rebind">>; +get_ns({ping}) -> <<"urn:xmpp:ping">>; +get_ns({presence, _, _, _, _, _, _, _, _, _}) -> + <<"jabber:client">>; +get_ns({privacy_item, _, _, _, _, _, _, _, _}) -> + <<"jabber:iq:privacy">>; +get_ns({privacy_list, _, _}) -> <<"jabber:iq:privacy">>; +get_ns({privacy_query, _, _, _}) -> + <<"jabber:iq:privacy">>; +get_ns({private, _}) -> <<"jabber:iq:private">>; +get_ns({ps_affiliation, Xmlns, _, _, _}) -> Xmlns; +get_ns({ps_error, 'closed-node', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'configuration-required', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'invalid-jid', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'invalid-options', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'invalid-payload', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'invalid-subid', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'item-forbidden', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'item-required', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'jid-required', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'max-items-exceeded', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'max-nodes-exceeded', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'nodeid-required', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'not-in-roster-group', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'not-subscribed', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'payload-required', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'payload-too-big', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'pending-subscription', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'presence-subscription-required', + _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'subid-required', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'too-many-subscriptions', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, unsupported, _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_error, 'unsupported-access-model', _}) -> + <<"http://jabber.org/protocol/pubsub#errors">>; +get_ns({ps_event, _, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/pubsub#event">>; +get_ns({ps_item, Xmlns, _, _, _, _}) -> Xmlns; +get_ns({ps_items, Xmlns, _, _, _, _, _}) -> Xmlns; +get_ns({ps_options, _, _, _, _}) -> + <<"http://jabber.org/protocol/pubsub">>; +get_ns({ps_publish, _, _}) -> + <<"http://jabber.org/protocol/pubsub">>; +get_ns({ps_retract, _, _, _}) -> + <<"http://jabber.org/protocol/pubsub">>; +get_ns({ps_subscribe, _, _}) -> + <<"http://jabber.org/protocol/pubsub">>; +get_ns({ps_subscription, Xmlns, _, _, _, _, _}) -> + Xmlns; +get_ns({ps_unsubscribe, _, _, _}) -> + <<"http://jabber.org/protocol/pubsub">>; +get_ns({pubsub, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _}) -> + <<"http://jabber.org/protocol/pubsub">>; +get_ns({pubsub_owner, _, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/pubsub#owner">>; +get_ns({redirect, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-stanzas">>; +get_ns({register, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _}) -> + <<"jabber:iq:register">>; +get_ns({roster_item, _, _, _, _, _}) -> + <<"jabber:iq:roster">>; +get_ns({roster_query, _, _}) -> <<"jabber:iq:roster">>; +get_ns({rosterver_feature}) -> + <<"urn:xmpp:features:rosterver">>; +get_ns({rsm_first, _, _}) -> + <<"http://jabber.org/protocol/rsm">>; +get_ns({rsm_set, _, _, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/rsm">>; +get_ns({sasl_abort}) -> + <<"urn:ietf:params:xml:ns:xmpp-sasl">>; +get_ns({sasl_auth, _, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-sasl">>; +get_ns({sasl_challenge, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-sasl">>; +get_ns({sasl_failure, _, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-sasl">>; +get_ns({sasl_mechanisms, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-sasl">>; +get_ns({sasl_response, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-sasl">>; +get_ns({sasl_success, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-sasl">>; +get_ns({search, _, _, _, _, _, _, _}) -> + <<"jabber:iq:search">>; +get_ns({search_item, _, _, _, _, _}) -> + <<"jabber:iq:search">>; +get_ns({'see-other-host', _}) -> + <<"urn:ietf:params:xml:ns:xmpp-streams">>; +get_ns({shim, _}) -> + <<"http://jabber.org/protocol/shim">>; get_ns({sic, _, _, Xmlns}) -> Xmlns; +get_ns({sm_a, _, Xmlns}) -> Xmlns; +get_ns({sm_enable, _, _, Xmlns}) -> Xmlns; +get_ns({sm_enabled, _, _, _, _, Xmlns}) -> Xmlns; +get_ns({sm_failed, _, _, Xmlns}) -> Xmlns; +get_ns({sm_r, Xmlns}) -> Xmlns; +get_ns({sm_resume, _, _, Xmlns}) -> Xmlns; +get_ns({sm_resumed, _, _, Xmlns}) -> Xmlns; +get_ns({stanza_id, _, _}) -> <<"urn:xmpp:sid:0">>; +get_ns({starttls, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-tls">>; +get_ns({starttls_failure}) -> + <<"urn:ietf:params:xml:ns:xmpp-tls">>; +get_ns({starttls_proceed}) -> + <<"urn:ietf:params:xml:ns:xmpp-tls">>; +get_ns({stat, _, _, _, _}) -> + <<"http://jabber.org/protocol/stats">>; +get_ns({stat_error, _, _}) -> + <<"http://jabber.org/protocol/stats">>; +get_ns({stats, _, _}) -> + <<"http://jabber.org/protocol/stats">>; +get_ns({stream_error, _, _}) -> + <<"http://etherx.jabber.org/streams">>; +get_ns({stream_features, _}) -> + <<"http://etherx.jabber.org/streams">>; +get_ns({stream_start, _, _, _, _, Xmlns, _, _, _}) -> + Xmlns; +get_ns({streamhost, _, _, _}) -> + <<"http://jabber.org/protocol/bytestreams">>; +get_ns({thumbnail, _, _, _, _}) -> + <<"urn:xmpp:thumbs:1">>; +get_ns({time, _, _}) -> <<"urn:xmpp:time">>; +get_ns({unblock, _}) -> <<"urn:xmpp:blocking">>; get_ns({upload_request, _, _, _, Xmlns}) -> Xmlns; get_ns({upload_slot, _, _, Xmlns}) -> Xmlns; -get_ns({thumbnail, _, _, _, _}) -> - <<"urn:xmpp:thumbs:1">>. +get_ns({vcard_adr, _, _, _, _, _, _, _, _, _, _, _, _, + _, _}) -> + <<"vcard-temp">>; +get_ns({vcard_email, _, _, _, _, _, _}) -> + <<"vcard-temp">>; +get_ns({vcard_geo, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_key, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_label, _, _, _, _, _, _, _, _}) -> + <<"vcard-temp">>; +get_ns({vcard_logo, _, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_name, _, _, _, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_org, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_photo, _, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_sound, _, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_tel, _, _, _, _, _, _, _, _, _, _, _, _, + _, _}) -> + <<"vcard-temp">>; +get_ns({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> + <<"vcard-temp">>; +get_ns({vcard_xupdate, _, _}) -> + <<"vcard-temp:x:update">>; +get_ns({version, _, _, _}) -> <<"jabber:iq:version">>; +get_ns({x_conference, _, _, _, _, _}) -> + <<"jabber:x:conference">>; +get_ns({xcaptcha, _}) -> <<"urn:xmpp:captcha">>; +get_ns({xdata, _, _, _, _, _, _}) -> + <<"jabber:x:data">>; +get_ns({xdata_field, _, _, _, _, _, _, _, _}) -> + <<"jabber:x:data">>; +get_ns({xdata_option, _, _}) -> <<"jabber:x:data">>; +get_ns({xevent, _, _, _, _, _}) -> <<"jabber:x:event">>; +get_ns({xmpp_session, _}) -> + <<"urn:ietf:params:xml:ns:xmpp-session">>. dec_int(Val) -> dec_int(Val, infinity, infinity). @@ -3337,22 +3842,27 @@ pp(xdata_field, 8) -> sub_els]; pp(xdata, 6) -> [type, instructions, title, reported, items, fields]; -pp(pubsub_subscription, 4) -> [jid, node, subid, type]; -pp(pubsub_affiliation, 2) -> [node, type]; -pp(pubsub_item, 2) -> [id, xml_els]; -pp(pubsub_items, 4) -> [node, max_items, subid, items]; -pp(pubsub_event_item, 4) -> - [id, node, publisher, xml_els]; -pp(pubsub_event_items, 3) -> [node, retract, items]; -pp(pubsub_event, 1) -> [items]; -pp(pubsub_subscribe, 2) -> [node, jid]; -pp(pubsub_unsubscribe, 3) -> [node, jid, subid]; -pp(pubsub_publish, 2) -> [node, items]; -pp(pubsub_options, 4) -> [node, jid, subid, xdata]; -pp(pubsub_retract, 3) -> [node, notify, items]; -pp(pubsub, 8) -> - [subscriptions, affiliations, publish, subscribe, - unsubscribe, options, items, retract]; +pp(ps_subscription, 6) -> + [xmlns, jid, type, node, subid, expiry]; +pp(ps_item, 5) -> [xmlns, id, xml_els, node, publisher]; +pp(ps_items, 6) -> + [xmlns, node, items, max_items, subid, retract]; +pp(ps_event, 6) -> + [items, purge, subscription, delete, create, + configuration]; +pp(ps_subscribe, 2) -> [node, jid]; +pp(ps_unsubscribe, 3) -> [node, jid, subid]; +pp(ps_publish, 2) -> [node, items]; +pp(ps_options, 4) -> [node, jid, subid, xdata]; +pp(ps_retract, 3) -> [node, notify, items]; +pp(pubsub, 16) -> + [subscriptions, subscription, affiliations, publish, + publish_options, subscribe, unsubscribe, options, items, + retract, create, configure, default, delete, purge, + rsm]; +pp(pubsub_owner, 6) -> + [affiliations, configure, default, delete, purge, + subscriptions]; pp(shim, 1) -> [headers]; pp(delay, 3) -> [stamp, from, desc]; pp(streamhost, 3) -> [jid, host, port]; @@ -12187,237 +12697,1244 @@ encode_shim_header_cdata(<<>>, _acc) -> _acc; encode_shim_header_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. +decode_pubsub_error_unsupported_access_model(__TopXMLNS, + __IgnoreEls, + {xmlel, + <<"unsupported-access-model">>, + _attrs, _els}) -> + {ps_error, 'unsupported-access-model', undefined}. + +encode_pubsub_error_unsupported_access_model({ps_error, + 'unsupported-access-model', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"unsupported-access-model">>, _attrs, _els}. + +decode_pubsub_error_unsupported(__TopXMLNS, __IgnoreEls, + {xmlel, <<"unsupported">>, _attrs, _els}) -> + Feature = + decode_pubsub_error_unsupported_attrs(__TopXMLNS, + _attrs, undefined), + {ps_error, unsupported, Feature}. + +decode_pubsub_error_unsupported_attrs(__TopXMLNS, + [{<<"feature">>, _val} | _attrs], + _Feature) -> + decode_pubsub_error_unsupported_attrs(__TopXMLNS, + _attrs, _val); +decode_pubsub_error_unsupported_attrs(__TopXMLNS, + [_ | _attrs], Feature) -> + decode_pubsub_error_unsupported_attrs(__TopXMLNS, + _attrs, Feature); +decode_pubsub_error_unsupported_attrs(__TopXMLNS, [], + Feature) -> + decode_pubsub_error_unsupported_attr_feature(__TopXMLNS, + Feature). + +encode_pubsub_error_unsupported({ps_error, unsupported, + Feature}, + _xmlns_attrs) -> + _els = [], + _attrs = + encode_pubsub_error_unsupported_attr_feature(Feature, + _xmlns_attrs), + {xmlel, <<"unsupported">>, _attrs, _els}. + +decode_pubsub_error_unsupported_attr_feature(__TopXMLNS, + undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"feature">>, <<"unsupported">>, + __TopXMLNS}}); +decode_pubsub_error_unsupported_attr_feature(__TopXMLNS, + _val) -> + case catch dec_enum(_val, + ['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']) + of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"feature">>, <<"unsupported">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_pubsub_error_unsupported_attr_feature(_val, + _acc) -> + [{<<"feature">>, enc_enum(_val)} | _acc]. + +decode_pubsub_error_too_many_subscriptions(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"too-many-subscriptions">>, + _attrs, _els}) -> + {ps_error, 'too-many-subscriptions', undefined}. + +encode_pubsub_error_too_many_subscriptions({ps_error, + 'too-many-subscriptions', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"too-many-subscriptions">>, _attrs, _els}. + +decode_pubsub_error_subid_required(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"subid-required">>, _attrs, + _els}) -> + {ps_error, 'subid-required', undefined}. + +encode_pubsub_error_subid_required({ps_error, + 'subid-required', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"subid-required">>, _attrs, _els}. + +decode_pubsub_error_presence_subscription_required(__TopXMLNS, + __IgnoreEls, + {xmlel, + <<"presence-subscription-required">>, + _attrs, _els}) -> + {ps_error, 'presence-subscription-required', undefined}. + +encode_pubsub_error_presence_subscription_required({ps_error, + 'presence-subscription-required', + _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"presence-subscription-required">>, _attrs, + _els}. + +decode_pubsub_error_pending_subscription(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"pending-subscription">>, + _attrs, _els}) -> + {ps_error, 'pending-subscription', undefined}. + +encode_pubsub_error_pending_subscription({ps_error, + 'pending-subscription', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"pending-subscription">>, _attrs, _els}. + +decode_pubsub_error_payload_required(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"payload-required">>, _attrs, + _els}) -> + {ps_error, 'payload-required', undefined}. + +encode_pubsub_error_payload_required({ps_error, + 'payload-required', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"payload-required">>, _attrs, _els}. + +decode_pubsub_error_payload_too_big(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"payload-too-big">>, _attrs, + _els}) -> + {ps_error, 'payload-too-big', undefined}. + +encode_pubsub_error_payload_too_big({ps_error, + 'payload-too-big', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"payload-too-big">>, _attrs, _els}. + +decode_pubsub_error_not_subscribed(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"not-subscribed">>, _attrs, + _els}) -> + {ps_error, 'not-subscribed', undefined}. + +encode_pubsub_error_not_subscribed({ps_error, + 'not-subscribed', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"not-subscribed">>, _attrs, _els}. + +decode_pubsub_error_not_in_roster_group(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"not-in-roster-group">>, + _attrs, _els}) -> + {ps_error, 'not-in-roster-group', undefined}. + +encode_pubsub_error_not_in_roster_group({ps_error, + 'not-in-roster-group', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"not-in-roster-group">>, _attrs, _els}. + +decode_pubsub_error_nodeid_required(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"nodeid-required">>, _attrs, + _els}) -> + {ps_error, 'nodeid-required', undefined}. + +encode_pubsub_error_nodeid_required({ps_error, + 'nodeid-required', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"nodeid-required">>, _attrs, _els}. + +decode_pubsub_error_max_nodes_exceeded(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"max-nodes-exceeded">>, _attrs, + _els}) -> + {ps_error, 'max-nodes-exceeded', undefined}. + +encode_pubsub_error_max_nodes_exceeded({ps_error, + 'max-nodes-exceeded', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"max-nodes-exceeded">>, _attrs, _els}. + +decode_pubsub_error_max_items_exceeded(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"max-items-exceeded">>, _attrs, + _els}) -> + {ps_error, 'max-items-exceeded', undefined}. + +encode_pubsub_error_max_items_exceeded({ps_error, + 'max-items-exceeded', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"max-items-exceeded">>, _attrs, _els}. + +decode_pubsub_error_jid_required(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"jid-required">>, _attrs, _els}) -> + {ps_error, 'jid-required', undefined}. + +encode_pubsub_error_jid_required({ps_error, + 'jid-required', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"jid-required">>, _attrs, _els}. + +decode_pubsub_error_item_required(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"item-required">>, _attrs, _els}) -> + {ps_error, 'item-required', undefined}. + +encode_pubsub_error_item_required({ps_error, + 'item-required', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"item-required">>, _attrs, _els}. + +decode_pubsub_error_item_forbidden(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"item-forbidden">>, _attrs, + _els}) -> + {ps_error, 'item-forbidden', undefined}. + +encode_pubsub_error_item_forbidden({ps_error, + 'item-forbidden', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"item-forbidden">>, _attrs, _els}. + +decode_pubsub_error_invalid_subid(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"invalid-subid">>, _attrs, _els}) -> + {ps_error, 'invalid-subid', undefined}. + +encode_pubsub_error_invalid_subid({ps_error, + 'invalid-subid', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"invalid-subid">>, _attrs, _els}. + +decode_pubsub_error_invalid_payload(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"invalid-payload">>, _attrs, + _els}) -> + {ps_error, 'invalid-payload', undefined}. + +encode_pubsub_error_invalid_payload({ps_error, + 'invalid-payload', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"invalid-payload">>, _attrs, _els}. + +decode_pubsub_error_invalid_options(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"invalid-options">>, _attrs, + _els}) -> + {ps_error, 'invalid-options', undefined}. + +encode_pubsub_error_invalid_options({ps_error, + 'invalid-options', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"invalid-options">>, _attrs, _els}. + +decode_pubsub_error_invalid_jid(__TopXMLNS, __IgnoreEls, + {xmlel, <<"invalid-jid">>, _attrs, _els}) -> + {ps_error, 'invalid-jid', undefined}. + +encode_pubsub_error_invalid_jid({ps_error, + 'invalid-jid', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"invalid-jid">>, _attrs, _els}. + +decode_pubsub_error_configuration_required(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"configuration-required">>, + _attrs, _els}) -> + {ps_error, 'configuration-required', undefined}. + +encode_pubsub_error_configuration_required({ps_error, + 'configuration-required', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"configuration-required">>, _attrs, _els}. + +decode_pubsub_error_closed_node(__TopXMLNS, __IgnoreEls, + {xmlel, <<"closed-node">>, _attrs, _els}) -> + {ps_error, 'closed-node', undefined}. + +encode_pubsub_error_closed_node({ps_error, + 'closed-node', _}, + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"closed-node">>, _attrs, _els}. + +decode_pubsub_owner(__TopXMLNS, __IgnoreEls, + {xmlel, <<"pubsub">>, _attrs, _els}) -> + {Subscriptions, Affiliations, Default, Purge, Delete, + Configure} = + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + undefined, undefined, undefined, undefined, + undefined, undefined), + {pubsub_owner, Affiliations, Configure, Default, Delete, + Purge, Subscriptions}. + +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, [], + Subscriptions, Affiliations, Default, Purge, Delete, + Configure) -> + {Subscriptions, Affiliations, Default, Purge, Delete, + Configure}; +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"affiliations">>, _attrs, _} = _el | _els], + Subscriptions, Affiliations, Default, Purge, Delete, + Configure) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, + decode_pubsub_owner_affiliations(__TopXMLNS, + __IgnoreEls, + _el), + Default, Purge, Delete, Configure); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, + decode_pubsub_owner_affiliations(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, + _el), + Default, Purge, Delete, Configure); + _ -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, Configure) + end; +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"configure">>, _attrs, _} = _el | _els], + Subscriptions, Affiliations, Default, Purge, Delete, + Configure) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, + decode_pubsub_configure(__TopXMLNS, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, + decode_pubsub_configure(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, + decode_pubsub_configure(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, Configure) + end; +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"default">>, _attrs, _} = _el | _els], + Subscriptions, Affiliations, Default, Purge, Delete, + Configure) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, + decode_pubsub_default(__TopXMLNS, __IgnoreEls, + _el), + Purge, Delete, Configure); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, + decode_pubsub_default(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Purge, Delete, Configure); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, + decode_pubsub_default(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Purge, Delete, Configure); + _ -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, Configure) + end; +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"delete">>, _attrs, _} = _el | _els], + Subscriptions, Affiliations, Default, Purge, Delete, + Configure) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + decode_pubsub_delete(__TopXMLNS, __IgnoreEls, + _el), + Configure); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Configure); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Configure); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Configure); + _ -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, Configure) + end; +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"purge">>, _attrs, _} = _el | _els], + Subscriptions, Affiliations, Default, Purge, Delete, + Configure) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, + decode_pubsub_purge(__TopXMLNS, __IgnoreEls, + _el), + Delete, Configure); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Delete, Configure); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Delete, Configure); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Delete, Configure); + _ -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, Configure) + end; +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"subscriptions">>, _attrs, _} = _el | _els], + Subscriptions, Affiliations, Default, Purge, Delete, + Configure) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_subscriptions(__TopXMLNS, + __IgnoreEls, _el), + Affiliations, Default, Purge, Delete, + Configure); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Affiliations, Default, Purge, Delete, + Configure); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Affiliations, Default, Purge, Delete, + Configure); + _ -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, + Delete, Configure) + end; +decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Subscriptions, Affiliations, Default, Purge, + Delete, Configure) -> + decode_pubsub_owner_els(__TopXMLNS, __IgnoreEls, _els, + Subscriptions, Affiliations, Default, Purge, Delete, + Configure). + +encode_pubsub_owner({pubsub_owner, Affiliations, + Configure, Default, Delete, Purge, Subscriptions}, + _xmlns_attrs) -> + _els = + lists:reverse('encode_pubsub_owner_$subscriptions'(Subscriptions, + 'encode_pubsub_owner_$affiliations'(Affiliations, + 'encode_pubsub_owner_$default'(Default, + 'encode_pubsub_owner_$purge'(Purge, + 'encode_pubsub_owner_$delete'(Delete, + 'encode_pubsub_owner_$configure'(Configure, + []))))))), + _attrs = _xmlns_attrs, + {xmlel, <<"pubsub">>, _attrs, _els}. + +'encode_pubsub_owner_$subscriptions'(undefined, _acc) -> + _acc; +'encode_pubsub_owner_$subscriptions'(Subscriptions, + _acc) -> + [encode_pubsub_subscriptions(Subscriptions, []) | _acc]. + +'encode_pubsub_owner_$affiliations'(undefined, _acc) -> + _acc; +'encode_pubsub_owner_$affiliations'(Affiliations, + _acc) -> + [encode_pubsub_owner_affiliations(Affiliations, []) + | _acc]. + +'encode_pubsub_owner_$default'(undefined, _acc) -> _acc; +'encode_pubsub_owner_$default'(Default, _acc) -> + [encode_pubsub_default(Default, []) | _acc]. + +'encode_pubsub_owner_$purge'(undefined, _acc) -> _acc; +'encode_pubsub_owner_$purge'(Purge, _acc) -> + [encode_pubsub_purge(Purge, []) | _acc]. + +'encode_pubsub_owner_$delete'(undefined, _acc) -> _acc; +'encode_pubsub_owner_$delete'(Delete, _acc) -> + [encode_pubsub_delete(Delete, []) | _acc]. + +'encode_pubsub_owner_$configure'(undefined, _acc) -> + _acc; +'encode_pubsub_owner_$configure'(Configure, _acc) -> + [encode_pubsub_configure(Configure, []) | _acc]. + decode_pubsub(__TopXMLNS, __IgnoreEls, {xmlel, <<"pubsub">>, _attrs, _els}) -> - {Items, Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish} = + {Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription} = decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined, undefined, undefined, - undefined, undefined, undefined), - {pubsub, Subscriptions, Affiliations, Publish, - Subscribe, Unsubscribe, Options, Items, Retract}. + undefined, undefined, undefined, undefined, undefined, + undefined, undefined, undefined, undefined, undefined, + undefined), + {pubsub, Subscriptions, Subscription, Affiliations, + Publish, Publish_options, Subscribe, Unsubscribe, + Options, Items, Retract, Create, Configure, Default, + Delete, Purge, Rsm}. -decode_pubsub_els(__TopXMLNS, __IgnoreEls, [], Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> - {Items, Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish}; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, [], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + {Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription}; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subscriptions">>, _attrs, _} = _el | _els], - Items, Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, decode_pubsub_subscriptions(__TopXMLNS, __IgnoreEls, _el), - Retract, Unsubscribe, Subscribe, Publish); + Default, Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el), - Retract, Unsubscribe, Subscribe, Publish); + Default, Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Default, Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"affiliations">>, _attrs, _} = _el | _els], - Items, Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, decode_pubsub_affiliations(__TopXMLNS, __IgnoreEls, _el), - Subscriptions, Retract, Unsubscribe, Subscribe, - Publish); + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, decode_pubsub_affiliations(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el), - Subscriptions, Retract, Unsubscribe, Subscribe, - Publish); + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subscribe">>, _attrs, _} = _el | _els], - Items, Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, decode_pubsub_subscribe(__TopXMLNS, __IgnoreEls, _el), - Publish); + Publish, Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, decode_pubsub_subscribe(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el), - Publish); + Publish, Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unsubscribe">>, _attrs, _} = _el | _els], - Items, Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, decode_pubsub_unsubscribe(__TopXMLNS, __IgnoreEls, _el), - Subscribe, Publish); + Subscribe, Publish, Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, decode_pubsub_unsubscribe(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el), - Subscribe, Publish); + Subscribe, Publish, Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"options">>, _attrs, _} = _el | _els], Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + [{xmlel, <<"options">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, decode_pubsub_options(__TopXMLNS, __IgnoreEls, _el), - Affiliations, Subscriptions, Retract, Unsubscribe, - Subscribe, Publish); + Affiliations, Subscriptions, Default, Retract, + Purge, Delete, Configure, Create, Unsubscribe, + Subscribe, Publish, Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, decode_pubsub_options(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el), - Affiliations, Subscriptions, Retract, Unsubscribe, - Subscribe, Publish); + Affiliations, Subscriptions, Default, Retract, + Purge, Delete, Configure, Create, Unsubscribe, + Subscribe, Publish, Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"items">>, _attrs, _} = _el | _els], Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + [{xmlel, <<"items">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, decode_pubsub_items(__TopXMLNS, __IgnoreEls, _el), - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish); + Options, Affiliations, Subscriptions, Default, + Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, decode_pubsub_items(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el), - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish); + Options, Affiliations, Subscriptions, Default, + Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, + decode_pubsub_items(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Options, Affiliations, Subscriptions, Default, + Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"retract">>, _attrs, _} = _el | _els], Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + [{xmlel, <<"retract">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, decode_pubsub_retract(__TopXMLNS, __IgnoreEls, _el), - Unsubscribe, Subscribe, Publish); + Purge, Delete, Configure, Create, Unsubscribe, + Subscribe, Publish, Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, decode_pubsub_retract(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el), - Unsubscribe, Subscribe, Publish); + Purge, Delete, Configure, Create, Unsubscribe, + Subscribe, Publish, Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"publish">>, _attrs, _} = _el | _els], Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> + [{xmlel, <<"create">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, - decode_pubsub_publish(__TopXMLNS, __IgnoreEls, - _el)); + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, + decode_pubsub_create(__TopXMLNS, __IgnoreEls, _el), + Unsubscribe, Subscribe, Publish, Rsm, Subscription); <<"http://jabber.org/protocol/pubsub">> -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, - decode_pubsub_publish(<<"http://jabber.org/protocol/pubsub">>, - __IgnoreEls, _el)); + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, + decode_pubsub_create(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, + decode_pubsub_create(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Unsubscribe, Subscribe, Publish, Rsm, Subscription); _ -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"configure">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + decode_pubsub_configure(__TopXMLNS, __IgnoreEls, + _el), + Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + decode_pubsub_configure(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + decode_pubsub_configure(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"publish-options">>, _attrs, _} = _el + | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_publish_options(__TopXMLNS, + __IgnoreEls, _el), + Items, Options, Affiliations, Subscriptions, + Default, Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_publish_options(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Items, Options, Affiliations, Subscriptions, + Default, Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"default">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, + decode_pubsub_default(__TopXMLNS, __IgnoreEls, _el), + Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, + decode_pubsub_default(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, + decode_pubsub_default(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Retract, Purge, Delete, Configure, Create, + Unsubscribe, Subscribe, Publish, Rsm, Subscription); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"delete">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, + decode_pubsub_delete(__TopXMLNS, __IgnoreEls, _el), + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"purge">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, + decode_pubsub_purge(__TopXMLNS, __IgnoreEls, _el), + Delete, Configure, Create, Unsubscribe, Subscribe, + Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Delete, Configure, Create, Unsubscribe, Subscribe, + Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Delete, Configure, Create, Unsubscribe, Subscribe, + Publish, Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Delete, Configure, Create, Unsubscribe, Subscribe, + Publish, Rsm, Subscription); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"subscription">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, + decode_pubsub_subscription(__TopXMLNS, __IgnoreEls, + _el)); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"set">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"http://jabber.org/protocol/rsm">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + decode_rsm_set(<<"http://jabber.org/protocol/rsm">>, + __IgnoreEls, _el), + Subscription); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) + end; +decode_pubsub_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"publish">>, _attrs, _} = _el | _els], + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, + decode_pubsub_publish(__TopXMLNS, __IgnoreEls, _el), + Rsm, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, + decode_pubsub_publish(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Rsm, Subscription); + _ -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, + Rsm, Subscription) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [_ | _els], - Items, Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish) -> - decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, - Options, Affiliations, Subscriptions, Retract, - Unsubscribe, Subscribe, Publish). + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription) -> + decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, + Publish_options, Items, Options, Affiliations, + Subscriptions, Default, Retract, Purge, Delete, + Configure, Create, Unsubscribe, Subscribe, Publish, Rsm, + Subscription). -encode_pubsub({pubsub, Subscriptions, Affiliations, - Publish, Subscribe, Unsubscribe, Options, Items, - Retract}, +encode_pubsub({pubsub, Subscriptions, Subscription, + Affiliations, Publish, Publish_options, Subscribe, + Unsubscribe, Options, Items, Retract, Create, Configure, + Default, Delete, Purge, Rsm}, _xmlns_attrs) -> - _els = lists:reverse('encode_pubsub_$items'(Items, - 'encode_pubsub_$options'(Options, - 'encode_pubsub_$affiliations'(Affiliations, - 'encode_pubsub_$subscriptions'(Subscriptions, - 'encode_pubsub_$retract'(Retract, - 'encode_pubsub_$unsubscribe'(Unsubscribe, - 'encode_pubsub_$subscribe'(Subscribe, - 'encode_pubsub_$publish'(Publish, - []))))))))), + _els = + lists:reverse('encode_pubsub_$publish_options'(Publish_options, + 'encode_pubsub_$items'(Items, + 'encode_pubsub_$options'(Options, + 'encode_pubsub_$affiliations'(Affiliations, + 'encode_pubsub_$subscriptions'(Subscriptions, + 'encode_pubsub_$default'(Default, + 'encode_pubsub_$retract'(Retract, + 'encode_pubsub_$purge'(Purge, + 'encode_pubsub_$delete'(Delete, + 'encode_pubsub_$configure'(Configure, + 'encode_pubsub_$create'(Create, + 'encode_pubsub_$unsubscribe'(Unsubscribe, + 'encode_pubsub_$subscribe'(Subscribe, + 'encode_pubsub_$publish'(Publish, + 'encode_pubsub_$rsm'(Rsm, + 'encode_pubsub_$subscription'(Subscription, + []))))))))))))))))), _attrs = _xmlns_attrs, {xmlel, <<"pubsub">>, _attrs, _els}. +'encode_pubsub_$publish_options'(undefined, _acc) -> + _acc; +'encode_pubsub_$publish_options'(Publish_options, + _acc) -> + [encode_pubsub_publish_options(Publish_options, []) + | _acc]. + 'encode_pubsub_$items'(undefined, _acc) -> _acc; 'encode_pubsub_$items'(Items, _acc) -> [encode_pubsub_items(Items, []) | _acc]. @@ -12434,10 +13951,30 @@ encode_pubsub({pubsub, Subscriptions, Affiliations, 'encode_pubsub_$subscriptions'(Subscriptions, _acc) -> [encode_pubsub_subscriptions(Subscriptions, []) | _acc]. +'encode_pubsub_$default'(undefined, _acc) -> _acc; +'encode_pubsub_$default'(Default, _acc) -> + [encode_pubsub_default(Default, []) | _acc]. + 'encode_pubsub_$retract'(undefined, _acc) -> _acc; 'encode_pubsub_$retract'(Retract, _acc) -> [encode_pubsub_retract(Retract, []) | _acc]. +'encode_pubsub_$purge'(undefined, _acc) -> _acc; +'encode_pubsub_$purge'(Purge, _acc) -> + [encode_pubsub_purge(Purge, []) | _acc]. + +'encode_pubsub_$delete'(undefined, _acc) -> _acc; +'encode_pubsub_$delete'(Delete, _acc) -> + [encode_pubsub_delete(Delete, []) | _acc]. + +'encode_pubsub_$configure'(undefined, _acc) -> _acc; +'encode_pubsub_$configure'(Configure, _acc) -> + [encode_pubsub_configure(Configure, []) | _acc]. + +'encode_pubsub_$create'(undefined, _acc) -> _acc; +'encode_pubsub_$create'(Create, _acc) -> + [encode_pubsub_create(Create, []) | _acc]. + 'encode_pubsub_$unsubscribe'(undefined, _acc) -> _acc; 'encode_pubsub_$unsubscribe'(Unsubscribe, _acc) -> [encode_pubsub_unsubscribe(Unsubscribe, []) | _acc]. @@ -12450,13 +13987,354 @@ encode_pubsub({pubsub, Subscriptions, Affiliations, 'encode_pubsub_$publish'(Publish, _acc) -> [encode_pubsub_publish(Publish, []) | _acc]. +'encode_pubsub_$rsm'(undefined, _acc) -> _acc; +'encode_pubsub_$rsm'(Rsm, _acc) -> + [encode_rsm_set(Rsm, + [{<<"xmlns">>, <<"http://jabber.org/protocol/rsm">>}]) + | _acc]. + +'encode_pubsub_$subscription'(undefined, _acc) -> _acc; +'encode_pubsub_$subscription'(Subscription, _acc) -> + [encode_pubsub_subscription(Subscription, []) | _acc]. + +decode_pubsub_purge(__TopXMLNS, __IgnoreEls, + {xmlel, <<"purge">>, _attrs, _els}) -> + Node = decode_pubsub_purge_attrs(__TopXMLNS, _attrs, + undefined), + Node. + +decode_pubsub_purge_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_purge_attrs(__TopXMLNS, _attrs, _val); +decode_pubsub_purge_attrs(__TopXMLNS, [_ | _attrs], + Node) -> + decode_pubsub_purge_attrs(__TopXMLNS, _attrs, Node); +decode_pubsub_purge_attrs(__TopXMLNS, [], Node) -> + decode_pubsub_purge_attr_node(__TopXMLNS, Node). + +encode_pubsub_purge(Node, _xmlns_attrs) -> + _els = [], + _attrs = encode_pubsub_purge_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"purge">>, _attrs, _els}. + +decode_pubsub_purge_attr_node(__TopXMLNS, undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"node">>, <<"purge">>, __TopXMLNS}}); +decode_pubsub_purge_attr_node(__TopXMLNS, _val) -> _val. + +encode_pubsub_purge_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + +decode_pubsub_delete(__TopXMLNS, __IgnoreEls, + {xmlel, <<"delete">>, _attrs, _els}) -> + Uri = decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Node = decode_pubsub_delete_attrs(__TopXMLNS, _attrs, + undefined), + {Node, Uri}. + +decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, [], + Uri) -> + Uri; +decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"redirect">>, _attrs, _} = _el | _els], + Uri) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">>; + __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">>; + __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_redirect(__TopXMLNS, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_redirect(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_redirect(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_redirect(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, _els, + Uri) + end; +decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Uri) -> + decode_pubsub_delete_els(__TopXMLNS, __IgnoreEls, _els, + Uri). + +decode_pubsub_delete_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_delete_attrs(__TopXMLNS, _attrs, _val); +decode_pubsub_delete_attrs(__TopXMLNS, [_ | _attrs], + Node) -> + decode_pubsub_delete_attrs(__TopXMLNS, _attrs, Node); +decode_pubsub_delete_attrs(__TopXMLNS, [], Node) -> + decode_pubsub_delete_attr_node(__TopXMLNS, Node). + +encode_pubsub_delete({Node, Uri}, _xmlns_attrs) -> + _els = lists:reverse('encode_pubsub_delete_$uri'(Uri, + [])), + _attrs = encode_pubsub_delete_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"delete">>, _attrs, _els}. + +'encode_pubsub_delete_$uri'(<<>>, _acc) -> _acc; +'encode_pubsub_delete_$uri'(Uri, _acc) -> + [encode_pubsub_redirect(Uri, []) | _acc]. + +decode_pubsub_delete_attr_node(__TopXMLNS, undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"node">>, <<"delete">>, __TopXMLNS}}); +decode_pubsub_delete_attr_node(__TopXMLNS, _val) -> + _val. + +encode_pubsub_delete_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + +decode_pubsub_redirect(__TopXMLNS, __IgnoreEls, + {xmlel, <<"redirect">>, _attrs, _els}) -> + Uri = decode_pubsub_redirect_attrs(__TopXMLNS, _attrs, + undefined), + Uri. + +decode_pubsub_redirect_attrs(__TopXMLNS, + [{<<"uri">>, _val} | _attrs], _Uri) -> + decode_pubsub_redirect_attrs(__TopXMLNS, _attrs, _val); +decode_pubsub_redirect_attrs(__TopXMLNS, [_ | _attrs], + Uri) -> + decode_pubsub_redirect_attrs(__TopXMLNS, _attrs, Uri); +decode_pubsub_redirect_attrs(__TopXMLNS, [], Uri) -> + decode_pubsub_redirect_attr_uri(__TopXMLNS, Uri). + +encode_pubsub_redirect(Uri, _xmlns_attrs) -> + _els = [], + _attrs = encode_pubsub_redirect_attr_uri(Uri, + _xmlns_attrs), + {xmlel, <<"redirect">>, _attrs, _els}. + +decode_pubsub_redirect_attr_uri(__TopXMLNS, + undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"uri">>, <<"redirect">>, __TopXMLNS}}); +decode_pubsub_redirect_attr_uri(__TopXMLNS, _val) -> + _val. + +encode_pubsub_redirect_attr_uri(_val, _acc) -> + [{<<"uri">>, _val} | _acc]. + +decode_pubsub_default(__TopXMLNS, __IgnoreEls, + {xmlel, <<"default">>, _attrs, _els}) -> + Xdata = decode_pubsub_default_els(__TopXMLNS, + __IgnoreEls, _els, undefined), + Node = decode_pubsub_default_attrs(__TopXMLNS, _attrs, + undefined), + {Node, Xdata}. + +decode_pubsub_default_els(__TopXMLNS, __IgnoreEls, [], + Xdata) -> + Xdata; +decode_pubsub_default_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"jabber:x:data">> -> + decode_pubsub_default_els(__TopXMLNS, __IgnoreEls, _els, + decode_xdata(<<"jabber:x:data">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_default_els(__TopXMLNS, __IgnoreEls, _els, + Xdata) + end; +decode_pubsub_default_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Xdata) -> + decode_pubsub_default_els(__TopXMLNS, __IgnoreEls, _els, + Xdata). + +decode_pubsub_default_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_default_attrs(__TopXMLNS, _attrs, _val); +decode_pubsub_default_attrs(__TopXMLNS, [_ | _attrs], + Node) -> + decode_pubsub_default_attrs(__TopXMLNS, _attrs, Node); +decode_pubsub_default_attrs(__TopXMLNS, [], Node) -> + decode_pubsub_default_attr_node(__TopXMLNS, Node). + +encode_pubsub_default({Node, Xdata}, _xmlns_attrs) -> + _els = + lists:reverse('encode_pubsub_default_$xdata'(Xdata, + [])), + _attrs = encode_pubsub_default_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"default">>, _attrs, _els}. + +'encode_pubsub_default_$xdata'(undefined, _acc) -> _acc; +'encode_pubsub_default_$xdata'(Xdata, _acc) -> + [encode_xdata(Xdata, + [{<<"xmlns">>, <<"jabber:x:data">>}]) + | _acc]. + +decode_pubsub_default_attr_node(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_default_attr_node(__TopXMLNS, _val) -> + _val. + +encode_pubsub_default_attr_node(<<>>, _acc) -> _acc; +encode_pubsub_default_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + +decode_pubsub_publish_options(__TopXMLNS, __IgnoreEls, + {xmlel, <<"publish-options">>, _attrs, _els}) -> + Xdata = decode_pubsub_publish_options_els(__TopXMLNS, + __IgnoreEls, _els, undefined), + Xdata. + +decode_pubsub_publish_options_els(__TopXMLNS, + __IgnoreEls, [], Xdata) -> + Xdata; +decode_pubsub_publish_options_els(__TopXMLNS, + __IgnoreEls, + [{xmlel, <<"x">>, _attrs, _} = _el | _els], + Xdata) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"jabber:x:data">> -> + decode_pubsub_publish_options_els(__TopXMLNS, + __IgnoreEls, _els, + decode_xdata(<<"jabber:x:data">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_publish_options_els(__TopXMLNS, + __IgnoreEls, _els, Xdata) + end; +decode_pubsub_publish_options_els(__TopXMLNS, + __IgnoreEls, [_ | _els], Xdata) -> + decode_pubsub_publish_options_els(__TopXMLNS, + __IgnoreEls, _els, Xdata). + +encode_pubsub_publish_options(Xdata, _xmlns_attrs) -> + _els = + lists:reverse('encode_pubsub_publish_options_$xdata'(Xdata, + [])), + _attrs = _xmlns_attrs, + {xmlel, <<"publish-options">>, _attrs, _els}. + +'encode_pubsub_publish_options_$xdata'(undefined, + _acc) -> + _acc; +'encode_pubsub_publish_options_$xdata'(Xdata, _acc) -> + [encode_xdata(Xdata, + [{<<"xmlns">>, <<"jabber:x:data">>}]) + | _acc]. + +decode_pubsub_configure(__TopXMLNS, __IgnoreEls, + {xmlel, <<"configure">>, _attrs, _els}) -> + Xdata = decode_pubsub_configure_els(__TopXMLNS, + __IgnoreEls, _els, undefined), + Node = decode_pubsub_configure_attrs(__TopXMLNS, _attrs, + undefined), + {Node, Xdata}. + +decode_pubsub_configure_els(__TopXMLNS, __IgnoreEls, [], + Xdata) -> + Xdata; +decode_pubsub_configure_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"x">>, _attrs, _} = _el | _els], + Xdata) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"jabber:x:data">> -> + decode_pubsub_configure_els(__TopXMLNS, __IgnoreEls, + _els, + decode_xdata(<<"jabber:x:data">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_configure_els(__TopXMLNS, __IgnoreEls, + _els, Xdata) + end; +decode_pubsub_configure_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Xdata) -> + decode_pubsub_configure_els(__TopXMLNS, __IgnoreEls, + _els, Xdata). + +decode_pubsub_configure_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_configure_attrs(__TopXMLNS, _attrs, _val); +decode_pubsub_configure_attrs(__TopXMLNS, [_ | _attrs], + Node) -> + decode_pubsub_configure_attrs(__TopXMLNS, _attrs, Node); +decode_pubsub_configure_attrs(__TopXMLNS, [], Node) -> + decode_pubsub_configure_attr_node(__TopXMLNS, Node). + +encode_pubsub_configure({Node, Xdata}, _xmlns_attrs) -> + _els = + lists:reverse('encode_pubsub_configure_$xdata'(Xdata, + [])), + _attrs = encode_pubsub_configure_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"configure">>, _attrs, _els}. + +'encode_pubsub_configure_$xdata'(undefined, _acc) -> + _acc; +'encode_pubsub_configure_$xdata'(Xdata, _acc) -> + [encode_xdata(Xdata, + [{<<"xmlns">>, <<"jabber:x:data">>}]) + | _acc]. + +decode_pubsub_configure_attr_node(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_configure_attr_node(__TopXMLNS, _val) -> + _val. + +encode_pubsub_configure_attr_node(<<>>, _acc) -> _acc; +encode_pubsub_configure_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + +decode_pubsub_create(__TopXMLNS, __IgnoreEls, + {xmlel, <<"create">>, _attrs, _els}) -> + Node = decode_pubsub_create_attrs(__TopXMLNS, _attrs, + undefined), + Node. + +decode_pubsub_create_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_create_attrs(__TopXMLNS, _attrs, _val); +decode_pubsub_create_attrs(__TopXMLNS, [_ | _attrs], + Node) -> + decode_pubsub_create_attrs(__TopXMLNS, _attrs, Node); +decode_pubsub_create_attrs(__TopXMLNS, [], Node) -> + decode_pubsub_create_attr_node(__TopXMLNS, Node). + +encode_pubsub_create(Node, _xmlns_attrs) -> + _els = [], + _attrs = encode_pubsub_create_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"create">>, _attrs, _els}. + +decode_pubsub_create_attr_node(__TopXMLNS, undefined) -> + <<>>; +decode_pubsub_create_attr_node(__TopXMLNS, _val) -> + _val. + +encode_pubsub_create_attr_node(<<>>, _acc) -> _acc; +encode_pubsub_create_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + decode_pubsub_retract(__TopXMLNS, __IgnoreEls, {xmlel, <<"retract">>, _attrs, _els}) -> Items = decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els, []), {Node, Notify} = decode_pubsub_retract_attrs(__TopXMLNS, _attrs, undefined, undefined), - {pubsub_retract, Node, Notify, Items}. + {ps_retract, Node, Notify, Items}. decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, [], Items) -> @@ -12477,6 +14355,11 @@ decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el) | Items]); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els, + [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el) + | Items]); _ -> decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els, Items) @@ -12503,8 +14386,7 @@ decode_pubsub_retract_attrs(__TopXMLNS, [], Node, {decode_pubsub_retract_attr_node(__TopXMLNS, Node), decode_pubsub_retract_attr_notify(__TopXMLNS, Notify)}. -encode_pubsub_retract({pubsub_retract, Node, Notify, - Items}, +encode_pubsub_retract({ps_retract, Node, Notify, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_retract_$items'(Items, @@ -12552,7 +14434,7 @@ decode_pubsub_options(__TopXMLNS, __IgnoreEls, {Node, Subid, Jid} = decode_pubsub_options_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), - {pubsub_options, Node, Jid, Subid, Xdata}. + {ps_options, Node, Jid, Subid, Xdata}. decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, [], Xdata) -> @@ -12596,7 +14478,7 @@ decode_pubsub_options_attrs(__TopXMLNS, [], Node, Subid, decode_pubsub_options_attr_subid(__TopXMLNS, Subid), decode_pubsub_options_attr_jid(__TopXMLNS, Jid)}. -encode_pubsub_options({pubsub_options, Node, Jid, Subid, +encode_pubsub_options({ps_options, Node, Jid, Subid, Xdata}, _xmlns_attrs) -> _els = @@ -12655,7 +14537,7 @@ decode_pubsub_publish(__TopXMLNS, __IgnoreEls, __IgnoreEls, _els, []), Node = decode_pubsub_publish_attrs(__TopXMLNS, _attrs, undefined), - {pubsub_publish, Node, Items}. + {ps_publish, Node, Items}. decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, [], Items) -> @@ -12676,6 +14558,11 @@ decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el) | Items]); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els, + [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el) + | Items]); _ -> decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els, Items) @@ -12694,7 +14581,7 @@ decode_pubsub_publish_attrs(__TopXMLNS, [_ | _attrs], decode_pubsub_publish_attrs(__TopXMLNS, [], Node) -> decode_pubsub_publish_attr_node(__TopXMLNS, Node). -encode_pubsub_publish({pubsub_publish, Node, Items}, +encode_pubsub_publish({ps_publish, Node, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_publish_$items'(Items, @@ -12723,7 +14610,7 @@ decode_pubsub_unsubscribe(__TopXMLNS, __IgnoreEls, {Node, Subid, Jid} = decode_pubsub_unsubscribe_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), - {pubsub_unsubscribe, Node, Jid, Subid}. + {ps_unsubscribe, Node, Jid, Subid}. decode_pubsub_unsubscribe_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node, Subid, @@ -12750,8 +14637,8 @@ decode_pubsub_unsubscribe_attrs(__TopXMLNS, [], Node, decode_pubsub_unsubscribe_attr_subid(__TopXMLNS, Subid), decode_pubsub_unsubscribe_attr_jid(__TopXMLNS, Jid)}. -encode_pubsub_unsubscribe({pubsub_unsubscribe, Node, - Jid, Subid}, +encode_pubsub_unsubscribe({ps_unsubscribe, Node, Jid, + Subid}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_unsubscribe_attr_jid(Jid, @@ -12803,7 +14690,7 @@ decode_pubsub_subscribe(__TopXMLNS, __IgnoreEls, {xmlel, <<"subscribe">>, _attrs, _els}) -> {Node, Jid} = decode_pubsub_subscribe_attrs(__TopXMLNS, _attrs, undefined, undefined), - {pubsub_subscribe, Node, Jid}. + {ps_subscribe, Node, Jid}. decode_pubsub_subscribe_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node, Jid) -> @@ -12822,7 +14709,7 @@ decode_pubsub_subscribe_attrs(__TopXMLNS, [], Node, {decode_pubsub_subscribe_attr_node(__TopXMLNS, Node), decode_pubsub_subscribe_attr_jid(__TopXMLNS, Jid)}. -encode_pubsub_subscribe({pubsub_subscribe, Node, Jid}, +encode_pubsub_subscribe({ps_subscribe, Node, Jid}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_subscribe_attr_jid(Jid, @@ -12857,12 +14744,108 @@ decode_pubsub_subscribe_attr_jid(__TopXMLNS, _val) -> encode_pubsub_subscribe_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. +decode_pubsub_owner_affiliations(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"affiliations">>, _attrs, _els}) -> + Affiliations = + decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, _els, []), + Node = + decode_pubsub_owner_affiliations_attrs(__TopXMLNS, + _attrs, undefined), + {Node, Affiliations}. + +decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, [], Affiliations) -> + lists:reverse(Affiliations); +decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, + [{xmlel, <<"affiliation">>, _attrs, _} = + _el + | _els], + Affiliations) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, _els, + [decode_pubsub_owner_affiliation(__TopXMLNS, + __IgnoreEls, + _el) + | Affiliations]); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, _els, + [decode_pubsub_owner_affiliation(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, + _el) + | Affiliations]); + _ -> + decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, _els, Affiliations) + end; +decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, [_ | _els], Affiliations) -> + decode_pubsub_owner_affiliations_els(__TopXMLNS, + __IgnoreEls, _els, Affiliations). + +decode_pubsub_owner_affiliations_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_owner_affiliations_attrs(__TopXMLNS, + _attrs, _val); +decode_pubsub_owner_affiliations_attrs(__TopXMLNS, + [_ | _attrs], Node) -> + decode_pubsub_owner_affiliations_attrs(__TopXMLNS, + _attrs, Node); +decode_pubsub_owner_affiliations_attrs(__TopXMLNS, [], + Node) -> + decode_pubsub_owner_affiliations_attr_node(__TopXMLNS, + Node). + +encode_pubsub_owner_affiliations({Node, Affiliations}, + _xmlns_attrs) -> + _els = + lists:reverse('encode_pubsub_owner_affiliations_$affiliations'(Affiliations, + [])), + _attrs = + encode_pubsub_owner_affiliations_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"affiliations">>, _attrs, _els}. + +'encode_pubsub_owner_affiliations_$affiliations'([], + _acc) -> + _acc; +'encode_pubsub_owner_affiliations_$affiliations'([Affiliations + | _els], + _acc) -> + 'encode_pubsub_owner_affiliations_$affiliations'(_els, + [encode_pubsub_owner_affiliation(Affiliations, + []) + | _acc]). + +decode_pubsub_owner_affiliations_attr_node(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_owner_affiliations_attr_node(__TopXMLNS, + _val) -> + _val. + +encode_pubsub_owner_affiliations_attr_node(<<>>, + _acc) -> + _acc; +encode_pubsub_owner_affiliations_attr_node(_val, + _acc) -> + [{<<"node">>, _val} | _acc]. + decode_pubsub_affiliations(__TopXMLNS, __IgnoreEls, {xmlel, <<"affiliations">>, _attrs, _els}) -> Affiliations = decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, _els, []), - Affiliations. + Node = decode_pubsub_affiliations_attrs(__TopXMLNS, + _attrs, undefined), + {Node, Affiliations}. decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, [], Affiliations) -> @@ -12897,12 +14880,25 @@ decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, _els, Affiliations). -encode_pubsub_affiliations(Affiliations, +decode_pubsub_affiliations_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_affiliations_attrs(__TopXMLNS, _attrs, + _val); +decode_pubsub_affiliations_attrs(__TopXMLNS, + [_ | _attrs], Node) -> + decode_pubsub_affiliations_attrs(__TopXMLNS, _attrs, + Node); +decode_pubsub_affiliations_attrs(__TopXMLNS, [], + Node) -> + decode_pubsub_affiliations_attr_node(__TopXMLNS, Node). + +encode_pubsub_affiliations({Node, Affiliations}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_affiliations_$affiliations'(Affiliations, [])), - _attrs = _xmlns_attrs, + _attrs = encode_pubsub_affiliations_attr_node(Node, + _xmlns_attrs), {xmlel, <<"affiliations">>, _attrs, _els}. 'encode_pubsub_affiliations_$affiliations'([], _acc) -> @@ -12915,6 +14911,18 @@ encode_pubsub_affiliations(Affiliations, []) | _acc]). +decode_pubsub_affiliations_attr_node(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_affiliations_attr_node(__TopXMLNS, + _val) -> + _val. + +encode_pubsub_affiliations_attr_node(<<>>, _acc) -> + _acc; +encode_pubsub_affiliations_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + decode_pubsub_subscriptions(__TopXMLNS, __IgnoreEls, {xmlel, <<"subscriptions">>, _attrs, _els}) -> Subscriptions = @@ -12934,7 +14942,9 @@ decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == - <<"http://jabber.org/protocol/pubsub">> -> + <<"http://jabber.org/protocol/pubsub">>; + __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#owner">> -> decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_subscription(__TopXMLNS, @@ -12948,6 +14958,20 @@ decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, __IgnoreEls, _el) | Subscriptions]); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, + _els, + [decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, + _el) + | Subscriptions]); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, + _els, + [decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, + _el) + | Subscriptions]); _ -> decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, _els, Subscriptions) @@ -13003,358 +15027,368 @@ encode_pubsub_subscriptions_attr_node(_val, _acc) -> decode_pubsub_event(__TopXMLNS, __IgnoreEls, {xmlel, <<"event">>, _attrs, _els}) -> - Items = decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, - _els, []), - {pubsub_event, Items}. + {Items, Create, Delete, Purge, Configuration, + Subscription} = + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + undefined, undefined, undefined, undefined, + undefined, undefined), + {ps_event, Items, Purge, Subscription, Delete, Create, + Configuration}. decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, [], - Items) -> - lists:reverse(Items); + Items, Create, Delete, Purge, Configuration, + Subscription) -> + {Items, Create, Delete, Purge, Configuration, + Subscription}; decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"items">>, _attrs, _} = _el | _els], - Items) -> + [{xmlel, <<"items">>, _attrs, _} = _el | _els], Items, + Create, Delete, Purge, Configuration, Subscription) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"http://jabber.org/protocol/pubsub#event">> -> decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, - [decode_pubsub_event_items(__TopXMLNS, - __IgnoreEls, _el) - | Items]); + decode_pubsub_items(__TopXMLNS, __IgnoreEls, + _el), + Create, Delete, Purge, Configuration, + Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + decode_pubsub_items(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Create, Delete, Purge, Configuration, + Subscription); <<"http://jabber.org/protocol/pubsub#event">> -> decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, - [decode_pubsub_event_items(<<"http://jabber.org/protocol/pubsub#event">>, - __IgnoreEls, _el) - | Items]); + decode_pubsub_items(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Create, Delete, Purge, Configuration, + Subscription); _ -> decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, - Items) + Items, Create, Delete, Purge, Configuration, + Subscription) end; decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, - [_ | _els], Items) -> + [{xmlel, <<"subscription">>, _attrs, _} = _el | _els], + Items, Create, Delete, Purge, Configuration, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + decode_pubsub_subscription(__TopXMLNS, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el)); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + Subscription) + end; +decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"purge">>, _attrs, _} = _el | _els], Items, + Create, Delete, Purge, Configuration, Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, + decode_pubsub_purge(__TopXMLNS, __IgnoreEls, + _el), + Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, + decode_pubsub_purge(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Configuration, Subscription); + _ -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + Subscription) + end; +decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"delete">>, _attrs, _} = _el | _els], Items, + Create, Delete, Purge, Configuration, Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, + decode_pubsub_delete(__TopXMLNS, __IgnoreEls, + _el), + Purge, Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Purge, Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub#owner">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#owner">>, + __IgnoreEls, _el), + Purge, Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, + decode_pubsub_delete(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Purge, Configuration, Subscription); + _ -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + Subscription) + end; +decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"create">>, _attrs, _} = _el | _els], Items, + Create, Delete, Purge, Configuration, Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, + decode_pubsub_create(__TopXMLNS, __IgnoreEls, + _el), + Delete, Purge, Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, + decode_pubsub_create(<<"http://jabber.org/protocol/pubsub">>, + __IgnoreEls, _el), + Delete, Purge, Configuration, Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, + decode_pubsub_create(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el), + Delete, Purge, Configuration, Subscription); + _ -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + Subscription) + end; +decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"configuration">>, _attrs, _} = _el | _els], + Items, Create, Delete, Purge, Configuration, + Subscription) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, + decode_pubsub_event_configuration(__TopXMLNS, + __IgnoreEls, + _el), + Subscription); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, + decode_pubsub_event_configuration(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, + _el), + Subscription); + _ -> + decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, + Items, Create, Delete, Purge, Configuration, + Subscription) + end; +decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Items, Create, Delete, Purge, Configuration, + Subscription) -> decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, - Items). + Items, Create, Delete, Purge, Configuration, + Subscription). -encode_pubsub_event({pubsub_event, Items}, +encode_pubsub_event({ps_event, Items, Purge, + Subscription, Delete, Create, Configuration}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_event_$items'(Items, - [])), + 'encode_pubsub_event_$create'(Create, + 'encode_pubsub_event_$delete'(Delete, + 'encode_pubsub_event_$purge'(Purge, + 'encode_pubsub_event_$configuration'(Configuration, + 'encode_pubsub_event_$subscription'(Subscription, + []))))))), _attrs = _xmlns_attrs, {xmlel, <<"event">>, _attrs, _els}. -'encode_pubsub_event_$items'([], _acc) -> _acc; -'encode_pubsub_event_$items'([Items | _els], _acc) -> - 'encode_pubsub_event_$items'(_els, - [encode_pubsub_event_items(Items, []) | _acc]). +'encode_pubsub_event_$items'(undefined, _acc) -> _acc; +'encode_pubsub_event_$items'(Items, _acc) -> + [encode_pubsub_items(Items, []) | _acc]. -decode_pubsub_event_items(__TopXMLNS, __IgnoreEls, - {xmlel, <<"items">>, _attrs, _els}) -> - {Items, Retract} = - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, [], []), - Node = decode_pubsub_event_items_attrs(__TopXMLNS, - _attrs, undefined), - {pubsub_event_items, Node, Retract, Items}. +'encode_pubsub_event_$create'(undefined, _acc) -> _acc; +'encode_pubsub_event_$create'(Create, _acc) -> + [encode_pubsub_create(Create, []) | _acc]. -decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - [], Items, Retract) -> - {lists:reverse(Items), lists:reverse(Retract)}; -decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"retract">>, _attrs, _} = _el | _els], - Items, Retract) -> - case get_attr(<<"xmlns">>, _attrs) of - <<"">> - when __TopXMLNS == - <<"http://jabber.org/protocol/pubsub#event">> -> - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, Items, - [decode_pubsub_event_retract(__TopXMLNS, - __IgnoreEls, - _el) - | Retract]); - <<"http://jabber.org/protocol/pubsub#event">> -> - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, Items, - [decode_pubsub_event_retract(<<"http://jabber.org/protocol/pubsub#event">>, - __IgnoreEls, - _el) - | Retract]); - _ -> - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, Items, Retract) - end; -decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"item">>, _attrs, _} = _el | _els], - Items, Retract) -> - case get_attr(<<"xmlns">>, _attrs) of - <<"">> - when __TopXMLNS == - <<"http://jabber.org/protocol/pubsub#event">> -> - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, - [decode_pubsub_event_item(__TopXMLNS, - __IgnoreEls, - _el) - | Items], - Retract); - <<"http://jabber.org/protocol/pubsub#event">> -> - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, - [decode_pubsub_event_item(<<"http://jabber.org/protocol/pubsub#event">>, - __IgnoreEls, - _el) - | Items], - Retract); - _ -> - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, Items, Retract) - end; -decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - [_ | _els], Items, Retract) -> - decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, - _els, Items, Retract). +'encode_pubsub_event_$delete'(undefined, _acc) -> _acc; +'encode_pubsub_event_$delete'(Delete, _acc) -> + [encode_pubsub_delete(Delete, []) | _acc]. -decode_pubsub_event_items_attrs(__TopXMLNS, - [{<<"node">>, _val} | _attrs], _Node) -> - decode_pubsub_event_items_attrs(__TopXMLNS, _attrs, - _val); -decode_pubsub_event_items_attrs(__TopXMLNS, - [_ | _attrs], Node) -> - decode_pubsub_event_items_attrs(__TopXMLNS, _attrs, - Node); -decode_pubsub_event_items_attrs(__TopXMLNS, [], Node) -> - decode_pubsub_event_items_attr_node(__TopXMLNS, Node). +'encode_pubsub_event_$purge'(undefined, _acc) -> _acc; +'encode_pubsub_event_$purge'(Purge, _acc) -> + [encode_pubsub_purge(Purge, []) | _acc]. -encode_pubsub_event_items({pubsub_event_items, Node, - Retract, Items}, - _xmlns_attrs) -> - _els = - lists:reverse('encode_pubsub_event_items_$items'(Items, - 'encode_pubsub_event_items_$retract'(Retract, - []))), - _attrs = encode_pubsub_event_items_attr_node(Node, - _xmlns_attrs), - {xmlel, <<"items">>, _attrs, _els}. - -'encode_pubsub_event_items_$items'([], _acc) -> _acc; -'encode_pubsub_event_items_$items'([Items | _els], - _acc) -> - 'encode_pubsub_event_items_$items'(_els, - [encode_pubsub_event_item(Items, []) - | _acc]). - -'encode_pubsub_event_items_$retract'([], _acc) -> _acc; -'encode_pubsub_event_items_$retract'([Retract | _els], - _acc) -> - 'encode_pubsub_event_items_$retract'(_els, - [encode_pubsub_event_retract(Retract, - []) - | _acc]). - -decode_pubsub_event_items_attr_node(__TopXMLNS, - undefined) -> - erlang:error({xmpp_codec, - {missing_attr, <<"node">>, <<"items">>, __TopXMLNS}}); -decode_pubsub_event_items_attr_node(__TopXMLNS, _val) -> - _val. - -encode_pubsub_event_items_attr_node(_val, _acc) -> - [{<<"node">>, _val} | _acc]. - -decode_pubsub_event_item(__TopXMLNS, __IgnoreEls, - {xmlel, <<"item">>, _attrs, _els}) -> - __Xmls = decode_pubsub_event_item_els(__TopXMLNS, - __IgnoreEls, _els, []), - {Id, Node, Publisher} = - decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, - undefined, undefined, undefined), - {pubsub_event_item, Id, Node, Publisher, __Xmls}. - -decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, - [], __Xmls) -> - lists:reverse(__Xmls); -decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, - [{xmlel, _, _, _} = _el | _els], __Xmls) -> - decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, - _els, [_el | __Xmls]); -decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, - [_ | _els], __Xmls) -> - decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, - _els, __Xmls). - -decode_pubsub_event_item_attrs(__TopXMLNS, - [{<<"id">>, _val} | _attrs], _Id, Node, - Publisher) -> - decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, _val, - Node, Publisher); -decode_pubsub_event_item_attrs(__TopXMLNS, - [{<<"node">>, _val} | _attrs], Id, _Node, - Publisher) -> - decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, Id, - _val, Publisher); -decode_pubsub_event_item_attrs(__TopXMLNS, - [{<<"publisher">>, _val} | _attrs], Id, Node, - _Publisher) -> - decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, Id, - Node, _val); -decode_pubsub_event_item_attrs(__TopXMLNS, [_ | _attrs], - Id, Node, Publisher) -> - decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, Id, - Node, Publisher); -decode_pubsub_event_item_attrs(__TopXMLNS, [], Id, Node, - Publisher) -> - {decode_pubsub_event_item_attr_id(__TopXMLNS, Id), - decode_pubsub_event_item_attr_node(__TopXMLNS, Node), - decode_pubsub_event_item_attr_publisher(__TopXMLNS, - Publisher)}. - -encode_pubsub_event_item({pubsub_event_item, Id, Node, - Publisher, __Xmls}, - _xmlns_attrs) -> - _els = __Xmls, - _attrs = - encode_pubsub_event_item_attr_publisher(Publisher, - encode_pubsub_event_item_attr_node(Node, - encode_pubsub_event_item_attr_id(Id, - _xmlns_attrs))), - {xmlel, <<"item">>, _attrs, _els}. - -decode_pubsub_event_item_attr_id(__TopXMLNS, - undefined) -> - <<>>; -decode_pubsub_event_item_attr_id(__TopXMLNS, _val) -> - _val. - -encode_pubsub_event_item_attr_id(<<>>, _acc) -> _acc; -encode_pubsub_event_item_attr_id(_val, _acc) -> - [{<<"id">>, _val} | _acc]. - -decode_pubsub_event_item_attr_node(__TopXMLNS, - undefined) -> - <<>>; -decode_pubsub_event_item_attr_node(__TopXMLNS, _val) -> - _val. - -encode_pubsub_event_item_attr_node(<<>>, _acc) -> _acc; -encode_pubsub_event_item_attr_node(_val, _acc) -> - [{<<"node">>, _val} | _acc]. - -decode_pubsub_event_item_attr_publisher(__TopXMLNS, - undefined) -> - <<>>; -decode_pubsub_event_item_attr_publisher(__TopXMLNS, - _val) -> - _val. - -encode_pubsub_event_item_attr_publisher(<<>>, _acc) -> +'encode_pubsub_event_$configuration'(undefined, _acc) -> _acc; -encode_pubsub_event_item_attr_publisher(_val, _acc) -> - [{<<"publisher">>, _val} | _acc]. +'encode_pubsub_event_$configuration'(Configuration, + _acc) -> + [encode_pubsub_event_configuration(Configuration, []) + | _acc]. -decode_pubsub_event_retract(__TopXMLNS, __IgnoreEls, - {xmlel, <<"retract">>, _attrs, _els}) -> - Id = decode_pubsub_event_retract_attrs(__TopXMLNS, - _attrs, undefined), - Id. - -decode_pubsub_event_retract_attrs(__TopXMLNS, - [{<<"id">>, _val} | _attrs], _Id) -> - decode_pubsub_event_retract_attrs(__TopXMLNS, _attrs, - _val); -decode_pubsub_event_retract_attrs(__TopXMLNS, - [_ | _attrs], Id) -> - decode_pubsub_event_retract_attrs(__TopXMLNS, _attrs, - Id); -decode_pubsub_event_retract_attrs(__TopXMLNS, [], Id) -> - decode_pubsub_event_retract_attr_id(__TopXMLNS, Id). - -encode_pubsub_event_retract(Id, _xmlns_attrs) -> - _els = [], - _attrs = encode_pubsub_event_retract_attr_id(Id, - _xmlns_attrs), - {xmlel, <<"retract">>, _attrs, _els}. - -decode_pubsub_event_retract_attr_id(__TopXMLNS, - undefined) -> - erlang:error({xmpp_codec, - {missing_attr, <<"id">>, <<"retract">>, __TopXMLNS}}); -decode_pubsub_event_retract_attr_id(__TopXMLNS, _val) -> - _val. - -encode_pubsub_event_retract_attr_id(_val, _acc) -> - [{<<"id">>, _val} | _acc]. +'encode_pubsub_event_$subscription'(undefined, _acc) -> + _acc; +'encode_pubsub_event_$subscription'(Subscription, + _acc) -> + [encode_pubsub_subscription(Subscription, []) | _acc]. decode_pubsub_items(__TopXMLNS, __IgnoreEls, {xmlel, <<"items">>, _attrs, _els}) -> - Items = decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, - _els, []), - {Max_items, Node, Subid} = + {Items, Retract} = decode_pubsub_items_els(__TopXMLNS, + __IgnoreEls, _els, [], + undefined), + {Xmlns, Max_items, Node, Subid} = decode_pubsub_items_attrs(__TopXMLNS, _attrs, undefined, - undefined, undefined), - {pubsub_items, Node, Max_items, Subid, Items}. + undefined, undefined, undefined), + {ps_items, Xmlns, Node, Items, Max_items, Subid, + Retract}. decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, [], - Items) -> - lists:reverse(Items); + Items, Retract) -> + {lists:reverse(Items), Retract}; decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, - [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> + [{xmlel, <<"retract">>, _attrs, _} = _el | _els], Items, + Retract) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == - <<"http://jabber.org/protocol/pubsub">> -> + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, + Items, + decode_pubsub_event_retract(__TopXMLNS, + __IgnoreEls, + _el)); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, + Items, + decode_pubsub_event_retract(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, + _el)); + _ -> + decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, + Items, Retract) + end; +decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items, + Retract) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == + <<"http://jabber.org/protocol/pubsub">>; + __TopXMLNS == + <<"http://jabber.org/protocol/pubsub#event">> -> decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_item(__TopXMLNS, __IgnoreEls, _el) - | Items]); + | Items], + Retract); <<"http://jabber.org/protocol/pubsub">> -> decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>, __IgnoreEls, _el) - | Items]); + | Items], + Retract); + <<"http://jabber.org/protocol/pubsub#event">> -> + decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, + [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub#event">>, + __IgnoreEls, _el) + | Items], + Retract); _ -> decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, - Items) + Items, Retract) end; decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, - [_ | _els], Items) -> + [_ | _els], Items, Retract) -> decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, - Items). + Items, Retract). decode_pubsub_items_attrs(__TopXMLNS, - [{<<"max_items">>, _val} | _attrs], _Max_items, Node, - Subid) -> - decode_pubsub_items_attrs(__TopXMLNS, _attrs, _val, - Node, Subid); -decode_pubsub_items_attrs(__TopXMLNS, - [{<<"node">>, _val} | _attrs], Max_items, _Node, - Subid) -> - decode_pubsub_items_attrs(__TopXMLNS, _attrs, Max_items, - _val, Subid); -decode_pubsub_items_attrs(__TopXMLNS, - [{<<"subid">>, _val} | _attrs], Max_items, Node, - _Subid) -> - decode_pubsub_items_attrs(__TopXMLNS, _attrs, Max_items, - Node, _val); -decode_pubsub_items_attrs(__TopXMLNS, [_ | _attrs], - Max_items, Node, Subid) -> - decode_pubsub_items_attrs(__TopXMLNS, _attrs, Max_items, - Node, Subid); -decode_pubsub_items_attrs(__TopXMLNS, [], Max_items, + [{<<"xmlns">>, _val} | _attrs], _Xmlns, Max_items, Node, Subid) -> - {decode_pubsub_items_attr_max_items(__TopXMLNS, + decode_pubsub_items_attrs(__TopXMLNS, _attrs, _val, + Max_items, Node, Subid); +decode_pubsub_items_attrs(__TopXMLNS, + [{<<"max_items">>, _val} | _attrs], Xmlns, _Max_items, + Node, Subid) -> + decode_pubsub_items_attrs(__TopXMLNS, _attrs, Xmlns, + _val, Node, Subid); +decode_pubsub_items_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], Xmlns, Max_items, + _Node, Subid) -> + decode_pubsub_items_attrs(__TopXMLNS, _attrs, Xmlns, + Max_items, _val, Subid); +decode_pubsub_items_attrs(__TopXMLNS, + [{<<"subid">>, _val} | _attrs], Xmlns, Max_items, + Node, _Subid) -> + decode_pubsub_items_attrs(__TopXMLNS, _attrs, Xmlns, + Max_items, Node, _val); +decode_pubsub_items_attrs(__TopXMLNS, [_ | _attrs], + Xmlns, Max_items, Node, Subid) -> + decode_pubsub_items_attrs(__TopXMLNS, _attrs, Xmlns, + Max_items, Node, Subid); +decode_pubsub_items_attrs(__TopXMLNS, [], Xmlns, + Max_items, Node, Subid) -> + {decode_pubsub_items_attr_xmlns(__TopXMLNS, Xmlns), + decode_pubsub_items_attr_max_items(__TopXMLNS, Max_items), decode_pubsub_items_attr_node(__TopXMLNS, Node), decode_pubsub_items_attr_subid(__TopXMLNS, Subid)}. -encode_pubsub_items({pubsub_items, Node, Max_items, - Subid, Items}, +encode_pubsub_items({ps_items, Xmlns, Node, Items, + Max_items, Subid, Retract}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_items_$items'(Items, - [])), + 'encode_pubsub_items_$retract'(Retract, + []))), _attrs = encode_pubsub_items_attr_subid(Subid, encode_pubsub_items_attr_node(Node, encode_pubsub_items_attr_max_items(Max_items, - _xmlns_attrs))), + encode_pubsub_items_attr_xmlns(Xmlns, + _xmlns_attrs)))), {xmlel, <<"items">>, _attrs, _els}. 'encode_pubsub_items_$items'([], _acc) -> _acc; @@ -13362,6 +15396,19 @@ encode_pubsub_items({pubsub_items, Node, Max_items, 'encode_pubsub_items_$items'(_els, [encode_pubsub_item(Items, []) | _acc]). +'encode_pubsub_items_$retract'(undefined, _acc) -> _acc; +'encode_pubsub_items_$retract'(Retract, _acc) -> + [encode_pubsub_event_retract(Retract, []) | _acc]. + +decode_pubsub_items_attr_xmlns(__TopXMLNS, undefined) -> + <<>>; +decode_pubsub_items_attr_xmlns(__TopXMLNS, _val) -> + _val. + +encode_pubsub_items_attr_xmlns(<<>>, _acc) -> _acc; +encode_pubsub_items_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + decode_pubsub_items_attr_max_items(__TopXMLNS, undefined) -> undefined; @@ -13400,9 +15447,10 @@ decode_pubsub_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> __Xmls = decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, _els, []), - Id = decode_pubsub_item_attrs(__TopXMLNS, _attrs, - undefined), - {pubsub_item, Id, __Xmls}. + {Id, Xmlns, Node, Publisher} = + decode_pubsub_item_attrs(__TopXMLNS, _attrs, undefined, + undefined, undefined, undefined), + {ps_item, Xmlns, Id, __Xmls, Node, Publisher}. decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, [], __Xmls) -> @@ -13417,18 +15465,46 @@ decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, __Xmls). decode_pubsub_item_attrs(__TopXMLNS, - [{<<"id">>, _val} | _attrs], _Id) -> - decode_pubsub_item_attrs(__TopXMLNS, _attrs, _val); -decode_pubsub_item_attrs(__TopXMLNS, [_ | _attrs], - Id) -> - decode_pubsub_item_attrs(__TopXMLNS, _attrs, Id); -decode_pubsub_item_attrs(__TopXMLNS, [], Id) -> - decode_pubsub_item_attr_id(__TopXMLNS, Id). + [{<<"id">>, _val} | _attrs], _Id, Xmlns, Node, + Publisher) -> + decode_pubsub_item_attrs(__TopXMLNS, _attrs, _val, + Xmlns, Node, Publisher); +decode_pubsub_item_attrs(__TopXMLNS, + [{<<"xmlns">>, _val} | _attrs], Id, _Xmlns, Node, + Publisher) -> + decode_pubsub_item_attrs(__TopXMLNS, _attrs, Id, _val, + Node, Publisher); +decode_pubsub_item_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], Id, Xmlns, _Node, + Publisher) -> + decode_pubsub_item_attrs(__TopXMLNS, _attrs, Id, Xmlns, + _val, Publisher); +decode_pubsub_item_attrs(__TopXMLNS, + [{<<"publisher">>, _val} | _attrs], Id, Xmlns, Node, + _Publisher) -> + decode_pubsub_item_attrs(__TopXMLNS, _attrs, Id, Xmlns, + Node, _val); +decode_pubsub_item_attrs(__TopXMLNS, [_ | _attrs], Id, + Xmlns, Node, Publisher) -> + decode_pubsub_item_attrs(__TopXMLNS, _attrs, Id, Xmlns, + Node, Publisher); +decode_pubsub_item_attrs(__TopXMLNS, [], Id, Xmlns, + Node, Publisher) -> + {decode_pubsub_item_attr_id(__TopXMLNS, Id), + decode_pubsub_item_attr_xmlns(__TopXMLNS, Xmlns), + decode_pubsub_item_attr_node(__TopXMLNS, Node), + decode_pubsub_item_attr_publisher(__TopXMLNS, + Publisher)}. -encode_pubsub_item({pubsub_item, Id, __Xmls}, +encode_pubsub_item({ps_item, Xmlns, Id, __Xmls, Node, + Publisher}, _xmlns_attrs) -> _els = __Xmls, - _attrs = encode_pubsub_item_attr_id(Id, _xmlns_attrs), + _attrs = encode_pubsub_item_attr_publisher(Publisher, + encode_pubsub_item_attr_node(Node, + encode_pubsub_item_attr_xmlns(Xmlns, + encode_pubsub_item_attr_id(Id, + _xmlns_attrs)))), {xmlel, <<"item">>, _attrs, _els}. decode_pubsub_item_attr_id(__TopXMLNS, undefined) -> @@ -13439,40 +15515,287 @@ encode_pubsub_item_attr_id(<<>>, _acc) -> _acc; encode_pubsub_item_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. +decode_pubsub_item_attr_xmlns(__TopXMLNS, undefined) -> + <<>>; +decode_pubsub_item_attr_xmlns(__TopXMLNS, _val) -> _val. + +encode_pubsub_item_attr_xmlns(<<>>, _acc) -> _acc; +encode_pubsub_item_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + +decode_pubsub_item_attr_node(__TopXMLNS, undefined) -> + <<>>; +decode_pubsub_item_attr_node(__TopXMLNS, _val) -> _val. + +encode_pubsub_item_attr_node(<<>>, _acc) -> _acc; +encode_pubsub_item_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + +decode_pubsub_item_attr_publisher(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_item_attr_publisher(__TopXMLNS, _val) -> + _val. + +encode_pubsub_item_attr_publisher(<<>>, _acc) -> _acc; +encode_pubsub_item_attr_publisher(_val, _acc) -> + [{<<"publisher">>, _val} | _acc]. + +decode_pubsub_event_retract(__TopXMLNS, __IgnoreEls, + {xmlel, <<"retract">>, _attrs, _els}) -> + Id = decode_pubsub_event_retract_attrs(__TopXMLNS, + _attrs, undefined), + Id. + +decode_pubsub_event_retract_attrs(__TopXMLNS, + [{<<"id">>, _val} | _attrs], _Id) -> + decode_pubsub_event_retract_attrs(__TopXMLNS, _attrs, + _val); +decode_pubsub_event_retract_attrs(__TopXMLNS, + [_ | _attrs], Id) -> + decode_pubsub_event_retract_attrs(__TopXMLNS, _attrs, + Id); +decode_pubsub_event_retract_attrs(__TopXMLNS, [], Id) -> + decode_pubsub_event_retract_attr_id(__TopXMLNS, Id). + +encode_pubsub_event_retract(Id, _xmlns_attrs) -> + _els = [], + _attrs = encode_pubsub_event_retract_attr_id(Id, + _xmlns_attrs), + {xmlel, <<"retract">>, _attrs, _els}. + +decode_pubsub_event_retract_attr_id(__TopXMLNS, + undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"id">>, <<"retract">>, __TopXMLNS}}); +decode_pubsub_event_retract_attr_id(__TopXMLNS, _val) -> + _val. + +encode_pubsub_event_retract_attr_id(_val, _acc) -> + [{<<"id">>, _val} | _acc]. + +decode_pubsub_event_configuration(__TopXMLNS, + __IgnoreEls, + {xmlel, <<"configuration">>, _attrs, _els}) -> + Xdata = + decode_pubsub_event_configuration_els(__TopXMLNS, + __IgnoreEls, _els, undefined), + Node = + decode_pubsub_event_configuration_attrs(__TopXMLNS, + _attrs, undefined), + {Node, Xdata}. + +decode_pubsub_event_configuration_els(__TopXMLNS, + __IgnoreEls, [], Xdata) -> + Xdata; +decode_pubsub_event_configuration_els(__TopXMLNS, + __IgnoreEls, + [{xmlel, <<"x">>, _attrs, _} = _el + | _els], + Xdata) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"jabber:x:data">> -> + decode_pubsub_event_configuration_els(__TopXMLNS, + __IgnoreEls, _els, + decode_xdata(<<"jabber:x:data">>, + __IgnoreEls, _el)); + _ -> + decode_pubsub_event_configuration_els(__TopXMLNS, + __IgnoreEls, _els, Xdata) + end; +decode_pubsub_event_configuration_els(__TopXMLNS, + __IgnoreEls, [_ | _els], Xdata) -> + decode_pubsub_event_configuration_els(__TopXMLNS, + __IgnoreEls, _els, Xdata). + +decode_pubsub_event_configuration_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_pubsub_event_configuration_attrs(__TopXMLNS, + _attrs, _val); +decode_pubsub_event_configuration_attrs(__TopXMLNS, + [_ | _attrs], Node) -> + decode_pubsub_event_configuration_attrs(__TopXMLNS, + _attrs, Node); +decode_pubsub_event_configuration_attrs(__TopXMLNS, [], + Node) -> + decode_pubsub_event_configuration_attr_node(__TopXMLNS, + Node). + +encode_pubsub_event_configuration({Node, Xdata}, + _xmlns_attrs) -> + _els = + lists:reverse('encode_pubsub_event_configuration_$xdata'(Xdata, + [])), + _attrs = + encode_pubsub_event_configuration_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"configuration">>, _attrs, _els}. + +'encode_pubsub_event_configuration_$xdata'(undefined, + _acc) -> + _acc; +'encode_pubsub_event_configuration_$xdata'(Xdata, + _acc) -> + [encode_xdata(Xdata, + [{<<"xmlns">>, <<"jabber:x:data">>}]) + | _acc]. + +decode_pubsub_event_configuration_attr_node(__TopXMLNS, + undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"node">>, <<"configuration">>, + __TopXMLNS}}); +decode_pubsub_event_configuration_attr_node(__TopXMLNS, + _val) -> + _val. + +encode_pubsub_event_configuration_attr_node(_val, + _acc) -> + [{<<"node">>, _val} | _acc]. + +decode_pubsub_owner_affiliation(__TopXMLNS, __IgnoreEls, + {xmlel, <<"affiliation">>, _attrs, _els}) -> + {Jid, Xmlns, Type} = + decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + _attrs, undefined, undefined, + undefined), + {ps_affiliation, Xmlns, <<>>, Type, Jid}. + +decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + [{<<"jid">>, _val} | _attrs], _Jid, Xmlns, + Type) -> + decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + _attrs, _val, Xmlns, Type); +decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + [{<<"xmlns">>, _val} | _attrs], Jid, + _Xmlns, Type) -> + decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + _attrs, Jid, _val, Type); +decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + [{<<"affiliation">>, _val} | _attrs], Jid, + Xmlns, _Type) -> + decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + _attrs, Jid, Xmlns, _val); +decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + [_ | _attrs], Jid, Xmlns, Type) -> + decode_pubsub_owner_affiliation_attrs(__TopXMLNS, + _attrs, Jid, Xmlns, Type); +decode_pubsub_owner_affiliation_attrs(__TopXMLNS, [], + Jid, Xmlns, Type) -> + {decode_pubsub_owner_affiliation_attr_jid(__TopXMLNS, + Jid), + decode_pubsub_owner_affiliation_attr_xmlns(__TopXMLNS, + Xmlns), + decode_pubsub_owner_affiliation_attr_affiliation(__TopXMLNS, + Type)}. + +encode_pubsub_owner_affiliation({ps_affiliation, Xmlns, + _, Type, Jid}, + _xmlns_attrs) -> + _els = [], + _attrs = + encode_pubsub_owner_affiliation_attr_affiliation(Type, + encode_pubsub_owner_affiliation_attr_xmlns(Xmlns, + encode_pubsub_owner_affiliation_attr_jid(Jid, + _xmlns_attrs))), + {xmlel, <<"affiliation">>, _attrs, _els}. + +decode_pubsub_owner_affiliation_attr_jid(__TopXMLNS, + undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"jid">>, <<"affiliation">>, + __TopXMLNS}}); +decode_pubsub_owner_affiliation_attr_jid(__TopXMLNS, + _val) -> + case catch dec_jid(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"jid">>, <<"affiliation">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_pubsub_owner_affiliation_attr_jid(_val, _acc) -> + [{<<"jid">>, enc_jid(_val)} | _acc]. + +decode_pubsub_owner_affiliation_attr_xmlns(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_owner_affiliation_attr_xmlns(__TopXMLNS, + _val) -> + _val. + +encode_pubsub_owner_affiliation_attr_xmlns(<<>>, + _acc) -> + _acc; +encode_pubsub_owner_affiliation_attr_xmlns(_val, + _acc) -> + [{<<"xmlns">>, _val} | _acc]. + +decode_pubsub_owner_affiliation_attr_affiliation(__TopXMLNS, + undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"affiliation">>, <<"affiliation">>, + __TopXMLNS}}); +decode_pubsub_owner_affiliation_attr_affiliation(__TopXMLNS, + _val) -> + case catch dec_enum(_val, + [member, none, outcast, owner, publisher, + 'publish-only']) + of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"affiliation">>, <<"affiliation">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_pubsub_owner_affiliation_attr_affiliation(_val, + _acc) -> + [{<<"affiliation">>, enc_enum(_val)} | _acc]. + decode_pubsub_affiliation(__TopXMLNS, __IgnoreEls, {xmlel, <<"affiliation">>, _attrs, _els}) -> - {Node, Type} = + {Node, Xmlns, Type} = decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, - undefined, undefined), - {pubsub_affiliation, Node, Type}. + undefined, undefined, undefined), + {ps_affiliation, Xmlns, Node, Type, undefined}. decode_pubsub_affiliation_attrs(__TopXMLNS, - [{<<"node">>, _val} | _attrs], _Node, Type) -> + [{<<"node">>, _val} | _attrs], _Node, Xmlns, + Type) -> decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, - _val, Type); + _val, Xmlns, Type); +decode_pubsub_affiliation_attrs(__TopXMLNS, + [{<<"xmlns">>, _val} | _attrs], Node, _Xmlns, + Type) -> + decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, + Node, _val, Type); decode_pubsub_affiliation_attrs(__TopXMLNS, [{<<"affiliation">>, _val} | _attrs], Node, - _Type) -> + Xmlns, _Type) -> decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, - Node, _val); + Node, Xmlns, _val); decode_pubsub_affiliation_attrs(__TopXMLNS, - [_ | _attrs], Node, Type) -> + [_ | _attrs], Node, Xmlns, Type) -> decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, - Node, Type); + Node, Xmlns, Type); decode_pubsub_affiliation_attrs(__TopXMLNS, [], Node, - Type) -> + Xmlns, Type) -> {decode_pubsub_affiliation_attr_node(__TopXMLNS, Node), + decode_pubsub_affiliation_attr_xmlns(__TopXMLNS, Xmlns), decode_pubsub_affiliation_attr_affiliation(__TopXMLNS, Type)}. -encode_pubsub_affiliation({pubsub_affiliation, Node, - Type}, +encode_pubsub_affiliation({ps_affiliation, Xmlns, Node, + Type, _}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_affiliation_attr_affiliation(Type, - encode_pubsub_affiliation_attr_node(Node, - _xmlns_attrs)), + encode_pubsub_affiliation_attr_xmlns(Xmlns, + encode_pubsub_affiliation_attr_node(Node, + _xmlns_attrs))), {xmlel, <<"affiliation">>, _attrs, _els}. decode_pubsub_affiliation_attr_node(__TopXMLNS, @@ -13486,6 +15809,18 @@ decode_pubsub_affiliation_attr_node(__TopXMLNS, _val) -> encode_pubsub_affiliation_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. +decode_pubsub_affiliation_attr_xmlns(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_affiliation_attr_xmlns(__TopXMLNS, + _val) -> + _val. + +encode_pubsub_affiliation_attr_xmlns(<<>>, _acc) -> + _acc; +encode_pubsub_affiliation_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + decode_pubsub_affiliation_attr_affiliation(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, @@ -13510,57 +15845,86 @@ encode_pubsub_affiliation_attr_affiliation(_val, decode_pubsub_subscription(__TopXMLNS, __IgnoreEls, {xmlel, <<"subscription">>, _attrs, _els}) -> - {Jid, Node, Subid, Type} = + {Xmlns, Jid, Node, Subid, Type, Expiry} = decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, - undefined), - {pubsub_subscription, Jid, Node, Subid, Type}. + undefined, undefined, undefined), + {ps_subscription, Xmlns, Jid, Type, Node, Subid, + Expiry}. decode_pubsub_subscription_attrs(__TopXMLNS, - [{<<"jid">>, _val} | _attrs], _Jid, Node, - Subid, Type) -> + [{<<"xmlns">>, _val} | _attrs], _Xmlns, Jid, + Node, Subid, Type, Expiry) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, - _val, Node, Subid, Type); + _val, Jid, Node, Subid, Type, Expiry); decode_pubsub_subscription_attrs(__TopXMLNS, - [{<<"node">>, _val} | _attrs], Jid, _Node, - Subid, Type) -> + [{<<"jid">>, _val} | _attrs], Xmlns, _Jid, + Node, Subid, Type, Expiry) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, - Jid, _val, Subid, Type); + Xmlns, _val, Node, Subid, Type, Expiry); decode_pubsub_subscription_attrs(__TopXMLNS, - [{<<"subid">>, _val} | _attrs], Jid, Node, - _Subid, Type) -> + [{<<"node">>, _val} | _attrs], Xmlns, Jid, + _Node, Subid, Type, Expiry) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, - Jid, Node, _val, Type); + Xmlns, Jid, _val, Subid, Type, Expiry); decode_pubsub_subscription_attrs(__TopXMLNS, - [{<<"subscription">>, _val} | _attrs], Jid, - Node, Subid, _Type) -> + [{<<"subid">>, _val} | _attrs], Xmlns, Jid, + Node, _Subid, Type, Expiry) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, - Jid, Node, Subid, _val); + Xmlns, Jid, Node, _val, Type, Expiry); decode_pubsub_subscription_attrs(__TopXMLNS, - [_ | _attrs], Jid, Node, Subid, Type) -> + [{<<"subscription">>, _val} | _attrs], Xmlns, + Jid, Node, Subid, _Type, Expiry) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, - Jid, Node, Subid, Type); -decode_pubsub_subscription_attrs(__TopXMLNS, [], Jid, - Node, Subid, Type) -> - {decode_pubsub_subscription_attr_jid(__TopXMLNS, Jid), + Xmlns, Jid, Node, Subid, _val, Expiry); +decode_pubsub_subscription_attrs(__TopXMLNS, + [{<<"expiry">>, _val} | _attrs], Xmlns, Jid, + Node, Subid, Type, _Expiry) -> + decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, + Xmlns, Jid, Node, Subid, Type, _val); +decode_pubsub_subscription_attrs(__TopXMLNS, + [_ | _attrs], Xmlns, Jid, Node, Subid, Type, + Expiry) -> + decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, + Xmlns, Jid, Node, Subid, Type, Expiry); +decode_pubsub_subscription_attrs(__TopXMLNS, [], Xmlns, + Jid, Node, Subid, Type, Expiry) -> + {decode_pubsub_subscription_attr_xmlns(__TopXMLNS, + Xmlns), + decode_pubsub_subscription_attr_jid(__TopXMLNS, Jid), decode_pubsub_subscription_attr_node(__TopXMLNS, Node), decode_pubsub_subscription_attr_subid(__TopXMLNS, Subid), decode_pubsub_subscription_attr_subscription(__TopXMLNS, - Type)}. + Type), + decode_pubsub_subscription_attr_expiry(__TopXMLNS, + Expiry)}. -encode_pubsub_subscription({pubsub_subscription, Jid, - Node, Subid, Type}, +encode_pubsub_subscription({ps_subscription, Xmlns, Jid, + Type, Node, Subid, Expiry}, _xmlns_attrs) -> _els = [], - _attrs = - encode_pubsub_subscription_attr_subscription(Type, - encode_pubsub_subscription_attr_subid(Subid, - encode_pubsub_subscription_attr_node(Node, - encode_pubsub_subscription_attr_jid(Jid, - _xmlns_attrs)))), + _attrs = encode_pubsub_subscription_attr_expiry(Expiry, + encode_pubsub_subscription_attr_subscription(Type, + encode_pubsub_subscription_attr_subid(Subid, + encode_pubsub_subscription_attr_node(Node, + encode_pubsub_subscription_attr_jid(Jid, + encode_pubsub_subscription_attr_xmlns(Xmlns, + _xmlns_attrs)))))), {xmlel, <<"subscription">>, _attrs, _els}. +decode_pubsub_subscription_attr_xmlns(__TopXMLNS, + undefined) -> + <<>>; +decode_pubsub_subscription_attr_xmlns(__TopXMLNS, + _val) -> + _val. + +encode_pubsub_subscription_attr_xmlns(<<>>, _acc) -> + _acc; +encode_pubsub_subscription_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + decode_pubsub_subscription_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, @@ -13624,6 +15988,25 @@ encode_pubsub_subscription_attr_subscription(_val, _acc) -> [{<<"subscription">>, enc_enum(_val)} | _acc]. +decode_pubsub_subscription_attr_expiry(__TopXMLNS, + undefined) -> + undefined; +decode_pubsub_subscription_attr_expiry(__TopXMLNS, + _val) -> + case catch dec_utc(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"expiry">>, <<"subscription">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_pubsub_subscription_attr_expiry(undefined, + _acc) -> + _acc; +encode_pubsub_subscription_attr_expiry(_val, _acc) -> + [{<<"expiry">>, enc_utc(_val)} | _acc]. + decode_xdata(__TopXMLNS, __IgnoreEls, {xmlel, <<"x">>, _attrs, _els}) -> {Fields, Items, Instructions, Reported, Title} = diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index d410a7613..445d9a716 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -1646,27 +1646,40 @@ -xml(pubsub_subscription, #elem{name = <<"subscription">>, - xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_subscription, '$jid', '$node', '$subid', - '$type'}, - attrs = [#attr{name = <<"jid">>, - required = true, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>, + <<"http://jabber.org/protocol/pubsub#event">>], + result = {ps_subscription, '$xmlns', '$jid', '$type', + '$node', '$subid', '$expiry'}, + attrs = [#attr{name = <<"xmlns">>}, + #attr{name = <<"jid">>, + required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}, - #attr{name = <<"node">>}, + #attr{name = <<"node">>}, #attr{name = <<"subid">>}, #attr{name = <<"subscription">>, label = '$type', dec = {dec_enum, [[none, pending, subscribed, unconfigured]]}, - enc = {enc_enum, []}}]}). + enc = {enc_enum, []}}, + #attr{name = <<"expiry">>, + dec = {dec_utc, []}, + enc = {enc_utc, []}}]}). + +-record(ps_affiliation, {xmlns = <<>> :: binary(), + node = <<>> :: binary(), + type :: member | none | outcast | + owner | publisher | 'publish-only', + jid :: jid:jid()}). +-type ps_affiliation() :: #ps_affiliation{}. -xml(pubsub_affiliation, #elem{name = <<"affiliation">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_affiliation, '$node', '$type'}, - attrs = [#attr{name = <<"node">>, - required = true}, + result = {ps_affiliation, '$xmlns', '$node', '$type', '$_'}, + attrs = [#attr{name = <<"node">>, required = true}, + #attr{name = <<"xmlns">>}, #attr{name = <<"affiliation">>, label = '$type', required = true, @@ -1674,24 +1687,28 @@ publisher, 'publish-only']]}, enc = {enc_enum, []}}]}). --xml(pubsub_item, - #elem{name = <<"item">>, - xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_item, '$id', '$_xmls'}, - attrs = [#attr{name = <<"id">>}]}). +-xml(pubsub_owner_affiliation, + #elem{name = <<"affiliation">>, + xmlns = <<"http://jabber.org/protocol/pubsub#owner">>, + result = {ps_affiliation, '$xmlns', '$_', '$type', '$jid'}, + attrs = [#attr{name = <<"jid">>, + required = true, + dec = {dec_jid, []}, + enc = {enc_jid, []}}, + #attr{name = <<"xmlns">>}, + #attr{name = <<"affiliation">>, + label = '$type', + required = true, + dec = {dec_enum, [[member, none, outcast, owner, + publisher, 'publish-only']]}, + enc = {enc_enum, []}}]}). --xml(pubsub_items, - #elem{name = <<"items">>, - xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_items, '$node', '$max_items', - '$subid', '$items'}, - attrs = [#attr{name = <<"max_items">>, - dec = {dec_int, [0, infinity]}, - enc = {enc_int, []}}, - #attr{name = <<"node">>, - required = true}, - #attr{name = <<"subid">>}], - refs = [#ref{name = pubsub_item, label = '$items'}]}). +-xml(pubsub_event_configuration, + #elem{name = <<"configuration">>, + xmlns = <<"http://jabber.org/protocol/pubsub#event">>, + result = {'$node', '$xdata'}, + attrs = [#attr{name = <<"node">>, required = true}], + refs = [#ref{name = xdata, min = 0, max = 1}]}). -xml(pubsub_event_retract, #elem{name = <<"retract">>, @@ -1699,32 +1716,55 @@ result = '$id', attrs = [#attr{name = <<"id">>, required = true}]}). --xml(pubsub_event_item, +-xml(pubsub_item, #elem{name = <<"item">>, - xmlns = <<"http://jabber.org/protocol/pubsub#event">>, - result = {pubsub_event_item, '$id', '$node', '$publisher', '$_xmls'}, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#event">>], + result = {ps_item, '$xmlns', '$id', '$_xmls', '$node', '$publisher'}, attrs = [#attr{name = <<"id">>}, + #attr{name = <<"xmlns">>}, #attr{name = <<"node">>}, #attr{name = <<"publisher">>}]}). --xml(pubsub_event_items, +-xml(pubsub_items, #elem{name = <<"items">>, - xmlns = <<"http://jabber.org/protocol/pubsub#event">>, - result = {pubsub_event_items, '$node', '$retract', '$items'}, - attrs = [#attr{name = <<"node">>, - required = true}], - refs = [#ref{name = pubsub_event_retract, label = '$retract'}, - #ref{name = pubsub_event_item, label = '$items'}]}). + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#event">>], + result = {ps_items, '$xmlns', '$node', '$items', '$max_items', + '$subid', '$retract'}, + attrs = [#attr{name = <<"xmlns">>}, + #attr{name = <<"max_items">>, + dec = {dec_int, [0, infinity]}, + enc = {enc_int, []}}, + #attr{name = <<"node">>, + required = true}, + #attr{name = <<"subid">>}], + refs = [#ref{name = pubsub_event_retract, label = '$retract', + min = 0, max = 1}, + #ref{name = pubsub_item, label = '$items'}]}). -xml(pubsub_event, #elem{name = <<"event">>, xmlns = <<"http://jabber.org/protocol/pubsub#event">>, - result = {pubsub_event, '$items'}, - refs = [#ref{name = pubsub_event_items, label = '$items'}]}). + result = {ps_event, '$items', '$purge', '$subscription', '$delete', + '$create', '$configuration'}, + refs = [#ref{name = pubsub_items, label = '$items', + min = 0, max = 1}, + #ref{name = pubsub_subscription, min = 0, max = 1, + label = '$subscription'}, + #ref{name = pubsub_purge, min = 0, max = 1, + label = '$purge'}, + #ref{name = pubsub_delete, min = 0, max = 1, + label = '$delete'}, + #ref{name = pubsub_create, min = 0, max = 1, + label = '$create'}, + #ref{name = pubsub_event_configuration, min = 0, max = 1, + label = '$configuration'}]}). -xml(pubsub_subscriptions, #elem{name = <<"subscriptions">>, - xmlns = <<"http://jabber.org/protocol/pubsub">>, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>], result = {'$node', '$subscriptions'}, attrs = [#attr{name = <<"node">>}], refs = [#ref{name = pubsub_subscription, label = '$subscriptions'}]}). @@ -1732,13 +1772,21 @@ -xml(pubsub_affiliations, #elem{name = <<"affiliations">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = '$affiliations', + result = {'$node', '$affiliations'}, + attrs = [#attr{name = <<"node">>}], refs = [#ref{name = pubsub_affiliation, label = '$affiliations'}]}). +-xml(pubsub_owner_affiliations, + #elem{name = <<"affiliations">>, + xmlns = <<"http://jabber.org/protocol/pubsub#owner">>, + result = {'$node', '$affiliations'}, + attrs = [#attr{name = <<"node">>}], + refs = [#ref{name = pubsub_owner_affiliation, label = '$affiliations'}]}). + -xml(pubsub_subscribe, #elem{name = <<"subscribe">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_subscribe, '$node', '$jid'}, + result = {ps_subscribe, '$node', '$jid'}, attrs = [#attr{name = <<"node">>}, #attr{name = <<"jid">>, required = true, @@ -1748,7 +1796,7 @@ -xml(pubsub_unsubscribe, #elem{name = <<"unsubscribe">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_unsubscribe, '$node', '$jid', '$subid'}, + result = {ps_unsubscribe, '$node', '$jid', '$subid'}, attrs = [#attr{name = <<"node">>}, #attr{name = <<"subid">>}, #attr{name = <<"jid">>, @@ -1759,7 +1807,7 @@ -xml(pubsub_publish, #elem{name = <<"publish">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_publish, '$node', '$items'}, + result = {ps_publish, '$node', '$items'}, attrs = [#attr{name = <<"node">>, required = true}], refs = [#ref{name = pubsub_item, label = '$items'}]}). @@ -1767,7 +1815,7 @@ -xml(pubsub_options, #elem{name = <<"options">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_options, '$node', '$jid', '$subid', '$xdata'}, + result = {ps_options, '$node', '$jid', '$subid', '$xdata'}, attrs = [#attr{name = <<"node">>}, #attr{name = <<"subid">>}, #attr{name = <<"jid">>, @@ -1780,7 +1828,7 @@ -xml(pubsub_retract, #elem{name = <<"retract">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub_retract, '$node', '$notify', '$items'}, + result = {ps_retract, '$node', '$notify', '$items'}, attrs = [#attr{name = <<"node">>, required = true}, #attr{name = <<"notify">>, @@ -1789,12 +1837,69 @@ enc = {enc_bool, []}}], refs = [#ref{name = pubsub_item, label = '$items'}]}). +-xml(pubsub_create, + #elem{name = <<"create">>, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#event">>], + result = '$node', + attrs = [#attr{name = <<"node">>}]}). + +-xml(pubsub_configure, + #elem{name = <<"configure">>, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>], + result = {'$node', '$xdata'}, + attrs = [#attr{name = <<"node">>}], + refs = [#ref{name = xdata, min = 0, max = 1}]}). + +-xml(pubsub_publish_options, + #elem{name = <<"publish-options">>, + xmlns = <<"http://jabber.org/protocol/pubsub">>, + result = '$xdata', + refs = [#ref{name = xdata, min = 0, max = 1}]}). + +-xml(pubsub_default, + #elem{name = <<"default">>, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>], + result = {'$node', '$xdata'}, + attrs = [#attr{name = <<"node">>}], + refs = [#ref{name = xdata, min = 0, max = 1}]}). + +-xml(pubsub_redirect, + #elem{name = <<"redirect">>, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>, + <<"http://jabber.org/protocol/pubsub#event">>], + result = '$uri', + attrs = [#attr{name = <<"uri">>, required = true}]}). + +-xml(pubsub_delete, + #elem{name = <<"delete">>, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>, + <<"http://jabber.org/protocol/pubsub#event">>], + result = {'$node', '$uri'}, + attrs = [#attr{name = <<"node">>, required = true}], + refs = [#ref{name = pubsub_redirect, min = 0, max = 1, + label = '$uri', default = <<>>}]}). + +-xml(pubsub_purge, + #elem{name = <<"purge">>, + xmlns = [<<"http://jabber.org/protocol/pubsub">>, + <<"http://jabber.org/protocol/pubsub#owner">>, + <<"http://jabber.org/protocol/pubsub#event">>], + result = '$node', + attrs = [#attr{name = <<"node">>, required = true}]}). + -xml(pubsub, #elem{name = <<"pubsub">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, - result = {pubsub, '$subscriptions', '$affiliations', '$publish', - '$subscribe', '$unsubscribe', '$options', '$items', - '$retract'}, + result = {pubsub, '$subscriptions', '$subscription', + '$affiliations', '$publish', '$publish_options', + '$subscribe', '$unsubscribe', '$options', '$items', + '$retract', '$create', '$configure', '$default', '$delete', + '$purge', '$rsm'}, refs = [#ref{name = pubsub_subscriptions, label = '$subscriptions', min = 0, max = 1}, #ref{name = pubsub_affiliations, label = '$affiliations', @@ -1809,9 +1914,209 @@ min = 0, max = 1}, #ref{name = pubsub_retract, label = '$retract', min = 0, max = 1}, + #ref{name = pubsub_create, label = '$create', + min = 0, max = 1}, + #ref{name = pubsub_configure, label = '$configure', + min = 0, max = 1}, + #ref{name = pubsub_publish_options, min = 0, max = 1, + label = '$publish_options'}, + #ref{name = pubsub_default, label = '$default', + min = 0, max = 1}, + #ref{name = pubsub_delete, label = '$delete', + min = 0, max = 1}, + #ref{name = pubsub_purge, label = '$purge', + min = 0, max = 1}, + #ref{name = pubsub_subscription, label = '$subscription', + min = 0, max = 1}, + #ref{name = rsm_set, min = 0, max = 1, label = '$rsm'}, #ref{name = pubsub_publish, label = '$publish', min = 0, max = 1}]}). +-xml(pubsub_owner, + #elem{name = <<"pubsub">>, + xmlns = <<"http://jabber.org/protocol/pubsub#owner">>, + result = {pubsub_owner, '$affiliations', '$configure', '$default', + '$delete', '$purge', '$subscriptions'}, + refs = [#ref{name = pubsub_owner_affiliations, + label = '$affiliations', min = 0, max = 1}, + #ref{name = pubsub_configure, label = '$configure', + min = 0, max = 1}, + #ref{name = pubsub_default, label = '$default', + min = 0, max = 1}, + #ref{name = pubsub_delete, label = '$delete', + min = 0, max = 1}, + #ref{name = pubsub_purge, label = '$purge', + min = 0, max = 1}, + #ref{name = pubsub_subscriptions, + label = '$subscriptions', min = 0, max = 1}]}). + +-type ps_error_type() :: 'closed-node' | 'configuration-required' | + 'invalid-jid' | 'invalid-options' | + 'invalid-payload' | 'invalid-subid' | + 'item-forbidden' | 'item-required' | 'jid-required' | + 'max-items-exceeded' | 'max-nodes-exceeded' | + 'nodeid-required' | 'not-in-roster-group' | + 'not-subscribed' | 'payload-too-big' | + 'payload-required' | 'pending-subscription' | + '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_error() :: #ps_error{}. + +-xml(pubsub_error_closed_node, + #elem{name = <<"closed-node">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'closed-node', '$_'}}). +-xml(pubsub_error_configuration_required, + #elem{name = <<"configuration-required">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'configuration-required', '$_'}}). +-xml(pubsub_error_invalid_jid, + #elem{name = <<"invalid-jid">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'invalid-jid', '$_'}}). +-xml(pubsub_error_invalid_options, + #elem{name = <<"invalid-options">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'invalid-options', '$_'}}). +-xml(pubsub_error_invalid_payload, + #elem{name = <<"invalid-payload">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'invalid-payload', '$_'}}). +-xml(pubsub_error_invalid_subid, + #elem{name = <<"invalid-subid">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'invalid-subid', '$_'}}). +-xml(pubsub_error_item_forbidden, + #elem{name = <<"item-forbidden">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'item-forbidden', '$_'}}). +-xml(pubsub_error_item_required, + #elem{name = <<"item-required">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'item-required', '$_'}}). +-xml(pubsub_error_jid_required, + #elem{name = <<"jid-required">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'jid-required', '$_'}}). +-xml(pubsub_error_max_items_exceeded, + #elem{name = <<"max-items-exceeded">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'max-items-exceeded', '$_'}}). +-xml(pubsub_error_max_nodes_exceeded, + #elem{name = <<"max-nodes-exceeded">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'max-nodes-exceeded', '$_'}}). +-xml(pubsub_error_nodeid_required, + #elem{name = <<"nodeid-required">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'nodeid-required', '$_'}}). +-xml(pubsub_error_not_in_roster_group, + #elem{name = <<"not-in-roster-group">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'not-in-roster-group', '$_'}}). +-xml(pubsub_error_not_subscribed, + #elem{name = <<"not-subscribed">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'not-subscribed', '$_'}}). +-xml(pubsub_error_payload_too_big, + #elem{name = <<"payload-too-big">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'payload-too-big', '$_'}}). +-xml(pubsub_error_payload_required, + #elem{name = <<"payload-required">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'payload-required', '$_'}}). +-xml(pubsub_error_pending_subscription, + #elem{name = <<"pending-subscription">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'pending-subscription', '$_'}}). +-xml(pubsub_error_presence_subscription_required, + #elem{name = <<"presence-subscription-required">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'presence-subscription-required', '$_'}}). +-xml(pubsub_error_subid_required, + #elem{name = <<"subid-required">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'subid-required', '$_'}}). +-xml(pubsub_error_too_many_subscriptions, + #elem{name = <<"too-many-subscriptions">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'too-many-subscriptions', '$_'}}). +-xml(pubsub_error_unsupported, + #elem{name = <<"unsupported">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'unsupported', '$feature'}, + attrs = [#attr{name = <<"feature">>, required = true, + dec = {dec_enum, [['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']]}, + enc = {enc_enum, []}}]}). +-xml(pubsub_error_unsupported_access_model, + #elem{name = <<"unsupported-access-model">>, + xmlns = <<"http://jabber.org/protocol/pubsub#errors">>, + result = {ps_error, 'unsupported-access-model', '$_'}}). + -xml(shim_header, #elem{name = <<"header">>, xmlns = <<"http://jabber.org/protocol/shim">>,