%%% ==================================================================== %%% ``The contents of this file are subject to the Erlang Public License, %%% Version 1.1, (the "License"); you may not use this file except in %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2013, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2013, ProcessOne. %%% %%% @copyright 2006-2013 ProcessOne %%% @author Karim Gemayel %%% [http://www.process-one.net/] %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== %%% @headerfile "pubsub_dev.hrl" -module(pubsub_options). -author('karim.gemayel@process-one.net'). -compile(export_all). -include("pubsub_dev.hrl"). -import(xml, [ get_tag_cdata/1, get_tag_attr_s/2, remove_cdata/1 ]). -import(pubsub_tools, [ get_entity_roster/1, is_jid/1 ]). %% -------------------------------------------------------------------- %% Documentation / type definitions. %% -------------------------------------------------------------------- %% Node Options % pubsub#node_config FORM_TYPE % Defined options values %-- Access Model --% -export_type([ access_model/0, access_model_open/0, access_model_presence/0, access_model_roster/0, access_model_authorize/0, access_model_whitelist/0 ]). %% @type access_model_open() = 'open'. -type(access_model_open() :: 'open'). %% @type access_model_presence() = 'presence'. -type(access_model_presence() :: 'presence'). %% @type access_model_roster() = 'roster'. -type(access_model_roster() :: 'roster'). %% @type access_model_authorize() = 'authorize'. -type(access_model_authorize() :: 'authorize'). %% @type access_model_whitelist() = 'whitelist'. -type(access_model_whitelist() :: 'whitelist'). %% @type access_model() = Open | Presence | Roster | Authorize | Whitelist %% Open = pubsub_options:access_model_open() %% Presence = pubsub_options:access_model_presence() %% Roster = pubsub_options:access_model_roster() %% Authorize = pubsub_options:access_model_authorize() %% Whitelist = pubsub_options:access_model_whitelist(). -type(access_model() :: pubsub_options:access_model_open() | pubsub_options:access_model_presence() | pubsub_options:access_model_roster() | pubsub_options:access_model_authorize() | pubsub_options:access_model_whitelist() ). %% %-- Children_Association_Policy --% -export_type([ children_association_policy/0, %% children_association_policy_all/0, children_association_policy_owners/0, children_association_policy_whitelist/0 ]). %% @type children_association_policy_all() = 'all'. -type(children_association_policy_all() :: 'all'). %% @type children_association_policy_owners() = 'owners'. -type(children_association_policy_owners() :: 'owners'). %% @type children_association_policy_whitelist() = 'whitelist'. -type(children_association_policy_whitelist() :: 'whitelist'). %% @type children_association_policy() = All | Owners | Whitelist %% All = pubsub_options:children_association_policy_all() %% Owners = pubsub_options:children_association_policy_owners() %% Whitelist = pubsub_options:children_association_policy_whitelist(). -type(children_association_policy() :: pubsub_options:children_association_policy_all() | pubsub_options:children_association_policy_owners() | pubsub_options:children_association_policy_whitelist() ). %% %-- ItemReply -- %% -export_type([ item_reply/0, item_reply_owner/0, item_reply_publisher/0 ]). %% @type(item_reply_owner() = 'owner'). -type(item_reply_owner() :: 'owner'). %% @type(item_reply_publisher() = 'publisher'). -type(item_reply_publisher() :: 'publisher'). %% @type(item_reply() = Owner | Publisher). -type(item_reply() :: pubsub_options:item_reply_owner() | pubsub_options:item_reply_publisher() ). -export_type([ language/0, description/0, title/0 ]). -type(language() :: binary()). -type(description() :: binary()). -type(title() :: binary()). %% %-- Node types --%% -export_type([ node_type/0, node_type_leaf/0, node_type_collection/0 ]). %% @type node_type_collection() = 'collection'. -type(node_type_collection() :: 'collection'). %% @type node_type_leaf() = 'leaf'. -type(node_type_leaf() :: 'leaf'). %% @type node_type() = Leaf | Collection %% Leaf = pubsub_options:node_type_leaf() %% Collection = pubsub_options:node_type_collection() -type(node_type() :: pubsub_options:node_type_leaf() | pubsub_options:node_type_collection() ). %% %-- Notification Types --%% -export_type([ notification_type/0, notification_type_chat/0, notification_type_headline/0, notification_type_normal/0 ]). -type(notification_type_chat() :: 'chat'). -type(notification_type_headline() :: 'headline'). -type(notification_type_normal() :: 'normal'). -type(notification_type() :: pubsub_options:notification_type_headline() | pubsub_options:notification_type_normal() %| pubsub_options:notification_type_chat() ). %% %-- Publish Model --% -export_type([ publish_model/0, publish_model_publishers/0, publish_model_subscribers/0, publish_model_open/0 ]). %% @type publish_model_publishers() = 'publishers'. -type(publish_model_publishers() :: 'publishers'). %% @type publish_model_subscribers() = 'subscribers'. -type(publish_model_subscribers() :: 'subscribers'). %% @type publish_model_open() = 'open'. -type(publish_model_open() :: 'open'). %% @type publish_model() = Publishers | Subscribers | Open %% Publishers = pubsub_options:publish_model_publishers() %% Subscribers = pubsub_options:publish_model_subscribers() %% Open = pubsub_options:publish_model_open() -type(publish_model() :: pubsub_options:publish_model_publishers() | pubsub_options:publish_model_subscribers() | pubsub_options:publish_model_open() ). -export_type([ roster_group/0, roster_groups/0, roster_groups_allowed/0, rosters_groups_allowed/0 ]). -type(roster_group() :: binary()). -type(roster_groups() :: [pubsub_options:roster_group()]). -type(roster_groups_allowed() :: {Node_Owner::xmpp_jid:usr_bare(), Roster_Groups::pubsub_options:roster_groups()} ). -type(rosters_groups_allowed() :: [Roster_Group_Allowed::pubsub_options:roster_groups_allowed()] ). %% %-- Send Last Published Item --% -export_type([ send_last_published_item/0, %% send_last_published_item_never/0, send_last_published_item_on_sub/0, send_last_published_item_on_sub_and_presence/0 ]). %% @type send_last_published_item_never() = 'never'. -type(send_last_published_item_never() :: 'never'). %% @type send_last_published_item_on_sub() = 'on_sub'. -type(send_last_published_item_on_sub() :: 'on_sub'). %% @type send_last_published_item_on_sub_and_presence() = 'on_sub_and_presence'. -type(send_last_published_item_on_sub_and_presence() :: 'on_sub_and_presence'). %% @type send_last_published_item() = Never | On_Sub | On_Sub_And_Presence %% Never = pubsub_options:send_last_published_item_never() %% On_Sub = pubsub_options:send_last_published_item_on_sub() %% On_Sub_And_Presence = pubsub_options:send_last_published_item_on_sub_and_presence(). -type(send_last_published_item() :: pubsub_options:send_last_published_item_never() | pubsub_options:send_last_published_item_on_sub() | pubsub_options:send_last_published_item_on_sub_and_presence() ). %% -export_type([ option_node_access_model/0, option_node_children_association_policy/0, option_node_children_association_whitelist/0, option_node_children/0, option_node_children_max/0, option_node_collections/0, option_node_children_max_collections/0, option_node_children_max_multi_collections/0, option_node_contact/0, option_node_deliver_notifications/0, option_node_deliver_payloads/0, option_node_description/0, option_node_item_expire/0, option_node_itemreply/0, option_node_language/0, option_node_max_items/0, option_node_max_payload_size/0, option_node_node_type_leaf/0, option_node_node_type_collection/0, option_node_node_type/0, option_node_notification_type/0, option_node_notify_config/0, option_node_notify_delete/0, option_node_notify_retract/0, option_node_notify_sub/0, option_node_persist_items/0, option_node_presence_based_delivery/0, option_node_publish_model/0, option_node_purge_offline/0, option_node_roster_groups_allowed/0, option_node_send_last_published_item/0, option_node_tempsub/0, option_node_subscribe/0, option_node_title/0, option_node_type/0 ]). -type(option_node_access_model() :: {Key :: 'access_model', Value :: pubsub_options:access_model()} ). %-type(option_node_body_xslt() :: % {Key :: 'body_xslt(', % Value :: binary()} %). -type(option_node_children_association_policy() :: {Key :: 'children_association_policy', Value :: pubsub_options:children_association_policy()} ). -type(option_node_children_association_whitelist() :: {Key :: 'children_association_whitelist', Value :: [Jid_Entity::xmpp_jid:raw_jid_entity_bare()]} ). -type(option_node_children() :: {Key :: 'children', Value :: [NodeId::exmpp_pubsub:nodeId()]} ). -type(option_node_children_max() :: {Key :: 'children_max', Value :: undefined | non_neg_integer()} ). -type(option_node_children_max_collections() :: {Key :: 'children_max', Value :: undefined | 0..1} ). -type(option_node_children_max_multi_collections() :: {Key :: 'children_max', Value :: undefined | non_neg_integer()} ). -type(option_node_collections() :: {Key :: 'collection', Value :: [NodeId::exmpp_pubsub:nodeId()]} ). -type(option_node_contact() :: {Key :: 'contact', Value :: [Jid_Entity::xmpp_jid:raw_jid_entity()]} ). %-type(option_node_dataform_xslt() :: % {Key :: 'dataform_xslt', % Value :: binary()} %). -type(option_node_deliver_notifications() :: {Key :: 'deliver_notifications', Value :: boolean()} ). -type(option_node_deliver_payloads() :: {Key :: 'deliver_payloads', Value :: boolean()} ). -type(option_node_description() :: {Key :: 'description', Value :: undefined | pubsub_options:description()} ). -type(option_node_item_expire() :: {Key :: 'item_expire', Value :: undefined | non_neg_integer()} ). -type(option_node_itemreply() :: {Key :: 'itemreply', Value :: pubsub_options:item_reply()} ). -type(option_node_language() :: {Key :: 'language', Value :: undefined | pubsub_options:language()} ). -type(option_node_max_items() :: {Key :: 'max_items', Value :: undefined | non_neg_integer()} ). -type(option_node_max_payload_size() :: {Key :: 'max_payload_size', Value :: undefined | non_neg_integer()} ). -type(option_node_node_type_leaf() :: {Key :: 'node_type', Value :: pubsub_options:node_type_leaf()} ). -type(option_node_node_type_collection() :: {Key :: 'node_type', Value :: pubsub_options:node_type_collection()} ). -type(option_node_node_type() :: pubsub_options:option_node_node_type_leaf() | pubsub_options:option_node_node_type_collection() ). -type(option_node_notification_type() :: {Key :: 'notification_type', Value :: pubsub_options:notification_type()} ). -type(option_node_notify_config() :: {Key :: 'notify_config', Value :: boolean()} ). -type(option_node_notify_delete() :: {Key :: 'notify_delete', Value :: boolean()} ). -type(option_node_notify_retract() :: {Key :: 'notify_retract', Value :: boolean()} ). -type(option_node_notify_sub() :: {Key :: 'notify_sub', Value :: boolean()} ). -type(option_node_persist_items() :: {Key :: 'persist_items', Value :: boolean()} ). -type(option_node_presence_based_delivery() :: {Key :: 'presence_based_delivery', Value :: boolean()} ). -type(option_node_publish_model() :: {Key :: 'publish_model', Value :: pubsub_options:publish_model()} ). -type(option_node_purge_offline() :: {Key :: 'purge_offline', Value :: boolean()} ). -type(option_node_roster_groups_allowed() :: {Key :: 'roster_groups_allowed', Value :: pubsub_options:rosters_groups_allowed()} ). -type(option_node_send_last_published_item() :: {Key :: 'send_last_published_item', Value :: pubsub_options:send_last_published_item()} ). -type(option_node_tempsub() :: {Key :: 'tempsub', Value :: boolean()} ). -type(option_node_subscribe() :: {Key :: 'subscribe', Value :: boolean()} ). -type(option_node_title() :: {Key :: 'title', Value :: undefined | pubsub_options:title()} ). -type(option_node_type() :: {Key :: 'type', Value :: undefined | binary()} ). %-- Node Option Type (local or remote user ; leaf or collection node) --% -export_type([ option_node/0, options_node/0, %% option_node_leaf/0, option_node_collection/0, %% options_node_leaf/0, options_node_collection/0 ]). -type(option_node_leaf() :: pubsub_options:option_node_access_model() | pubsub_options:option_node_collections() | pubsub_options:option_node_contact() | pubsub_options:option_node_deliver_notifications() | pubsub_options:option_node_deliver_payloads() | pubsub_options:option_node_description() | pubsub_options:option_node_item_expire() | pubsub_options:option_node_itemreply() | pubsub_options:option_node_language() | pubsub_options:option_node_max_items() | pubsub_options:option_node_max_payload_size() | pubsub_options:option_node_node_type_leaf() | pubsub_options:option_node_notification_type() | pubsub_options:option_node_notify_config() | pubsub_options:option_node_notify_delete() | pubsub_options:option_node_notify_retract() | pubsub_options:option_node_notify_sub() | pubsub_options:option_node_persist_items() | pubsub_options:option_node_presence_based_delivery() | pubsub_options:option_node_publish_model() | pubsub_options:option_node_purge_offline() | pubsub_options:option_node_roster_groups_allowed() | pubsub_options:option_node_send_last_published_item() | pubsub_options:option_node_tempsub() | pubsub_options:option_node_subscribe() | pubsub_options:option_node_title() | pubsub_options:option_node_type() ). %% -type(option_node_collection() :: pubsub_options:option_node_access_model() | pubsub_options:option_node_children_association_policy() | pubsub_options:option_node_children_association_whitelist() | pubsub_options:option_node_children() | pubsub_options:option_node_children_max() | pubsub_options:option_node_collections() | pubsub_options:option_node_contact() | pubsub_options:option_node_deliver_notifications() | pubsub_options:option_node_deliver_payloads() | pubsub_options:option_node_description() | pubsub_options:option_node_item_expire() | pubsub_options:option_node_itemreply() | pubsub_options:option_node_language() | pubsub_options:option_node_max_items() | pubsub_options:option_node_max_payload_size() | pubsub_options:option_node_node_type_collection() | pubsub_options:option_node_notification_type() | pubsub_options:option_node_notify_config() | pubsub_options:option_node_notify_delete() | pubsub_options:option_node_notify_retract() | pubsub_options:option_node_notify_sub() | pubsub_options:option_node_persist_items() | pubsub_options:option_node_presence_based_delivery() | pubsub_options:option_node_publish_model() | pubsub_options:option_node_purge_offline() | pubsub_options:option_node_roster_groups_allowed() | pubsub_options:option_node_send_last_published_item() | pubsub_options:option_node_tempsub() | pubsub_options:option_node_subscribe() | pubsub_options:option_node_title() | pubsub_options:option_node_type() ). %% -type(option_node() :: pubsub_options:option_node_leaf() | pubsub_options:option_node_collection() ). %% -type(options_node_leaf() :: [pubsub_options:option_node_leaf(),...] ). %% -type(options_node_collection() :: [pubsub_options:option_node_collection(),...] ). %% -type(options_node() :: pubsub_options:options_node_leaf() | pubsub_options:options_node_collection() ). %-- Publish-Options --% %% pubsub#publish-options FORM_TYPE -export_type([ option_item_access_model/0, option_item_deliver_notifications/0, option_item_deliver_payloads/0, option_item_item_expire/0, option_item_itemreply/0, %%option_item_max_payload_size/0, option_item_notification_type/0, option_item_notify_config/0, option_item_notify_retract/0, option_item_persist_items/0, option_item_presence_based_delivery/0, option_item_publish_model/0, option_item_purge_offline/0, option_item_roster_groups_allowed/0, option_item_send_last_published_item/0, option_item_type/0 ]). -type(option_item_access_model() :: {Key :: 'access_model', Value :: pubsub_options:access_model()} ). -type(option_item_deliver_notifications() :: {Key :: 'deliver_notifications', Value :: boolean()} ). -type(option_item_deliver_payloads() :: {Key :: 'deliver_payloads', Value :: boolean()} ). -type(option_item_item_expire() :: {Key :: 'item_expire', Value :: undefined | non_neg_integer()} ). -type(option_item_itemreply() :: {Key :: 'itemreply', Value :: pubsub_options:item_reply()} ). %-type(option_item_max_payload_size() :: % {Key :: 'max_payload_size', % Value :: undefined | non_neg_integer()} %). -type(option_item_notification_type() :: {Key :: 'notification_type', Value :: pubsub_options:notification_type()} ). -type(option_item_notify_config() :: {Key :: 'notify_config', Value :: boolean()} ). -type(option_item_notify_retract() :: {Key :: 'notify_retract', Value :: boolean()} ). -type(option_item_persist_items() :: {Key :: 'persist_items', Value :: boolean()} ). -type(option_item_presence_based_delivery() :: {Key :: 'presence_based_delivery', Value :: boolean()} ). -type(option_item_publish_model() :: {Key :: 'publish_model', Value :: pubsub_options:publish_model()} ). -type(option_item_purge_offline() :: {Key :: 'purge_offline', Value :: boolean()} ). -type(option_item_roster_groups_allowed() :: {Key :: 'roster_groups_allowed', Value :: pubsub_options:rosters_groups_allowed()} ). -type(option_item_send_last_published_item() :: {Key :: 'send_last_published_item', Value :: pubsub_options:send_last_published_item()} ). -type(option_item_type() :: {Key :: 'type', Value :: undefined | binary()} ). -export_type([ option_item/0, options_item/0 ]). -type(option_item() :: pubsub_options:option_item_access_model() | pubsub_options:option_item_deliver_notifications() | pubsub_options:option_item_deliver_payloads() | pubsub_options:option_item_item_expire() | pubsub_options:option_item_itemreply() %% | pubsub_options:option_item_max_payload_size() | pubsub_options:option_item_notification_type() | pubsub_options:option_item_notify_config() | pubsub_options:option_item_notify_retract() | pubsub_options:option_item_persist_items() | pubsub_options:option_item_presence_based_delivery() | pubsub_options:option_item_publish_model() | pubsub_options:option_item_purge_offline() | pubsub_options:option_item_roster_groups_allowed() | pubsub_options:option_item_send_last_published_item() | pubsub_options:option_item_type() ). %% -type(options_item() :: [pubsub_options:option_item(),...] ). %-- Subscription Options --%% -export_type([ option_subscription_deliver/0, option_subscription_expire/0, option_subscription_expire_presence/0, option_subscription_expire_datetime/0, option_subscription_include_body/0, option_subscription_show_values/0, option_subscription_subscription_type/0, option_subscription_subscription_depth/0 ]). %% -type(option_subscription_deliver() :: {Key :: 'deliver', Value :: boolean()} ). %-type(option_subscription_digest() :: % {Key :: 'digest', % Value :: boolean()} %). %-type(option_subscription_digest_frequency() :: % {Key :: 'digest_frequency', % Value :: undefined | non_neg_integer()} %). -type(option_subscription_expire_presence() :: {Key :: 'expire', Value :: undefined | 'presence'} ). -type(option_subscription_expire_datetime() :: {Key :: 'expire', Value :: undefined | erlang:timestamp()} ). -type(option_subscription_expire() :: pubsub_options:option_subscription_expire_presence() | pubsub_options:option_subscription_expire_datetime() ). -type(option_subscription_include_body() :: {Key :: 'include_body', Value :: boolean()} ). -type(option_subscription_show_values() :: {Key :: 'show-values', Value :: ['away' | 'chat' | 'dnd' | 'online' | 'xa']} ). -type(option_subscription_subscription_type() :: {Key :: 'subscription_type', Value :: 'all' | 'items' | 'nodes'} ). -type(option_subscription_subscription_depth() :: {Key :: 'subscription_depth', Value :: 'all' | exmpp_pubsub:level()} ). -export_type([ option_subscription/0, %% option_subscription_leaf/0, option_subscription_collection/0, %% option_subscription_leaf_local/0, option_subscription_leaf_remote/0, %% option_subscription_collection_local/0, option_subscription_collection_remote/0 ]). %% -type(option_subscription_leaf_local() :: pubsub_options:option_subscription_deliver() | pubsub_options:option_subscription_expire() % | pubsub_options:option_subscription_include_body() | pubsub_options:option_subscription_show_values() ). %% -type(option_subscription_leaf_remote() :: pubsub_options:option_subscription_deliver() % | pubsub_options:option_subscription_expire_datetime() % | pubsub_options:option_subscription_include_body() ). %% -type(option_subscription_collection_local() :: pubsub_options:option_subscription_deliver() | pubsub_options:option_subscription_expire() | pubsub_options:option_subscription_expire_presence() | pubsub_options:option_subscription_expire_datetime() %| pubsub_options:option_subscription_include_body() | pubsub_options:option_subscription_show_values() | pubsub_options:option_subscription_subscription_type() | pubsub_options:option_subscription_subscription_depth() ). %% -type(option_subscription_collection_remote() :: pubsub_options:option_subscription_deliver() | pubsub_options:option_subscription_expire_datetime() | pubsub_options:option_subscription_include_body() | pubsub_options:option_subscription_subscription_type() | pubsub_options:option_subscription_subscription_depth() ). %% -type(option_subscription_leaf() :: pubsub_options:option_subscription_leaf_local() | pubsub_options:option_subscription_leaf_remote() ). %% -type(option_subscription_collection() :: pubsub_options:option_subscription_collection_local() | pubsub_options:option_subscription_collection_remote() ). %% -type(option_subscription() :: pubsub_options:option_subscription_leaf() | pubsub_options:option_subscription_collection() ). -export_type([ options_subscription/0, %% options_subscription_leaf/0, options_subscription_collection/0, %% options_subscription_local/0, options_subscription_remote/0, %% options_subscription_leaf_local/0, options_subscription_leaf_remote/0, %% options_subscription_collection_local/0, options_subscription_collection_remote/0 ]). %% -type(options_subscription_leaf_local() :: [pubsub_options:options_subscription_leaf_local(),...] ). %% -type(options_subscription_leaf_remote() :: [pubsub_options:options_subscription_leaf_remote(),...] ). %% -type(options_subscription_collection_local() :: [pubsub_options:options_subscription_collection_local(),...] ). %% -type(options_subscription_collection_remote() :: [pubsub_options:options_subscription_collection_remote(),...] ). %% -type(options_subscription_leaf() :: pubsub_options:options_subscription_leaf_local() | pubsub_options:options_subscription_leaf_remote() ). %% -type(options_subscription_collection() :: pubsub_options:options_subscription_collection_local() | pubsub_options:options_subscription_collection_remote() ). %% -type(options_subscription_local() :: pubsub_options:options_subscription_leaf_local() | pubsub_options:options_subscription_collection_local() ). %% -type(options_subscription_remote() :: pubsub_options:options_subscription_leaf_remote() | pubsub_options:options_subscription_collection_remote() ). -type(options_subscription() :: pubsub_options:options_subscription_leaf() | pubsub_options:options_subscription_collection() ). %% -------------------------------------------------------------------- %% Functions. %% -------------------------------------------------------------------- xmlns(Xmlel) -> get_tag_attr_s(<<"xmlns">>, Xmlel). -define(Is_Xmlel_Field(Xmlel), ( Xmlel#xmlel.name == <<"field">> )). -define(Is_Xmlel_Value(Xmlel), ( Xmlel#xmlel.name == <<"value">> andalso Xmlel#xmlel.attrs == [] )). -define(Is_Xmlel_X(Xmlel), ( Xmlel#xmlel.name == <<"x">> )). -define(Is_Xmlel_X_Submit(Xmlel), ( %Xmlel#xmlel.ns == 'jabber:x:data' andalso Xmlel#xmlel.name == <<"x">> % andalso % Xmlel#xmlel.attrs == [#xmlattr{name = <<"type">>, value = <<"submit">>}] )). -define(Is_Xmlel_X_Form(Xmlel), ( %Xmlel#xmlel.ns == 'jabber:x:data' andalso Xmlel#xmlel.name == <<"x">> andalso Xmlel#xmlel.attrs == [{<<"type">>, <<"form">>}] )). %% %% -define(Is_Default_Subscribe_Option(Option), ( Option == {'deliver', true} orelse Option == {'expire', undefined} orelse Option == {'include_body', false} orelse Option == {'show-values', ['away' , 'chat' , 'dnd' , 'online' , 'xa']} )). %% -spec(trim_subscription_options/1 :: ( Subscription_Options::pubsub_options:options_subscription()) -> Subscription_Options::pubsub_options:options_subscription() ). trim_subscription_options(Subscription_Options) -> trim_subscription_options(Subscription_Options, []). %% -spec(trim_subscription_options/2 :: ( Options :: [] | pubsub_options:options_subscription(), Subscription_Options :: [] | pubsub_options:options_subscription()) -> Subscription_Options :: [] | pubsub_options:options_subscription() ). trim_subscription_options([] = _Options, Subscription_Options) -> Subscription_Options; %% trim_subscription_options([Option | Options], Subscription_Options) when ?Is_Default_Subscribe_Option(Option) -> trim_subscription_options(Options, Subscription_Options); %% trim_subscription_options([Option | Options], Subscription_Options) -> trim_subscription_options(Options, [Option | Subscription_Options]). %% -spec(parse_xmlel_x/5 :: ( Plugin :: exmpp_pubsub:plugin(), Pubsub_Features :: exmpp_pubsub:pubsub_features(), Entity :: xmpp_jid:usr_entity(), Form_Type :: 'node_config' | 'publish-options', Xmlels :: [Xmlel_X::xmlel(),...] | [Xmlel::xmlel()] | []) -> {ok, Options :: pubsub_options:options_node() | pubsub_options:options_item()} %%% | {error, 'not-acceptable'} | {error, 'feature-not-implemented', 'collections'} %%% | {error, 'invalid-options'} | {error, 'jid-malformed'} % | {error, 'not-acceptable'} | {error, 'not-acceptable', 'unsupported-access-model'} % | {error, 'feature-not-implemented', 'collections'} | {error, 'feature-not-implemented', 'multi-collections'} ). parse_xmlel_x(Plugin, _Pubsub_Features, _Entity, 'node_config', []) -> {ok, Plugin:node_options('leaf')}; parse_xmlel_x(_Plugin, _Pubsub_Features, _Entity, 'publish-options', []) -> {ok, []}; %% parse_xmlel_x(Plugin, Pubsub_Features, {U,S,_} = _Entity, Form_Type, [Xmlel_X]) when ?Is_Xmlel_X(Xmlel_X) -> case {xmlns(Xmlel_X), options_type(remove_cdata(Xmlel_X#xmlel.children), Pubsub_Features)} of {?NS_XDATA, {ok, 'node_config' = Form_Type, Node_Type, Xmlels}} -> parse_xmlels_field(Form_Type, Node_Type, Pubsub_Features, {U,S,undefined}, Xmlels, Plugin:node_options(Node_Type)); %% {?NS_XDATA, {ok, 'publish-options' = Form_Type, Node_Type, Xmlels}} -> parse_xmlels_field(Form_Type, Node_Type, Pubsub_Features, {U,S,undefined}, Xmlels, Plugin:item_options()); %% {?NS_XDATA, Error} -> Error; _ -> {error, 'invalid-options'} end; parse_xmlel_x(_Plugin, _Pubsub_Features, _Entity, _Form_Type, _Xmlels) -> {error, 'invalid-options'}. %% -spec(parse_xmlel_x/7 :: ( Plugin :: exmpp_pubsub:plugin(), Pubsub_Features :: exmpp_pubsub:pubsub_features(), Entity :: xmpp_jid:usr_entity(), Entity_Type :: 'local' | 'remote', Form_Type :: 'subscribe_options', Node_Type :: 'leaf' | 'collection', Xmlels :: [Xmlel_X::xmlel(),...] | [Xmlel::xmlel()] | []) -> {ok, Subscription_Options :: [] | pubsub_options:options_subscription_leaf()} %%% | {error, 'invalid-options'} | {error, 'not-acceptable'} ). parse_xmlel_x(Plugin, _Pubsub_Features, _Entity, Entity_Type, 'subscribe_options', Node_Type, []) -> {ok, Plugin:subscription_options(Entity_Type, Node_Type)}; %% parse_xmlel_x(Plugin, Pubsub_Features, {U,S,_} = _Entity, Entity_Type, 'subscribe_options' = Form_Type, Node_Type, [Xmlel_X]) when ?Is_Xmlel_X(Xmlel_X) -> case {xmlns(Xmlel_X), options_type(remove_cdata(Xmlel_X#xmlel.children), 'subscribe_options', [])} of {?NS_XDATA, {ok, 'subscribe_options', Xmlels}} -> parse_xmlels_field(Form_Type, Node_Type, Pubsub_Features, {U,S,undefined}, Entity_Type, Xmlels, Plugin:default_subscription_options(Entity_Type, Node_Type)); {?NS_XDATA, Error} -> Error; _ -> {error, 'invalid-options'} end; %% parse_xmlel_x(_Plugin, _Pubsub_Features, _Entity, _Entity_Type, 'subscribe_options', _Node_Type, _Xmlels) -> {error, 'invalid-options'}. %% -spec(options_type/3 :: ( Xmlels :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()], Form_Type :: 'subscribe_options', Xmlels_Fields :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()]) -> {ok, Form_Type :: 'subscribe_options', Xmlels_Field :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()]} %%% | {error, 'not-acceptable'} ). options_type([] = _Xmlels_Field, 'subscribe_options', _Xmlels) -> {error, 'not-acceptable'}; %% options_type([Xmlel_Field | Xmlels_Field], 'subscribe_options', Xmlels) when ?Is_Xmlel_Field(Xmlel_Field) -> case {xmlns(Xmlel_Field), get_tag_attr_s(<<"var">>, Xmlel_Field)} of {_, <<>>} -> {error, 'not-acceptable'}; {?NS_XDATA, <<"FORM_TYPE">>} -> case remove_cdata(Xmlel_Field#xmlel.children) of [Xmlel_Value] when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, ?NS_PUBSUB_SUBSCRIBE_OPTIONS} -> {ok, 'subscribe_options', Xmlels ++ Xmlels_Field}; _ -> {error, 'not-acceptable'} end; _ -> {error, 'not-acceptable'} end; {?NS_XDATA, _} -> options_type(Xmlels_Field, 'subscribe_options', [Xmlel_Field | Xmlels]); _ -> {error, 'not-acceptable'} end. %% -spec(options_type/2 :: ( Xmlels :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()], Pubsub_Features :: exmpp_pubsub:pubsub_features()) -> {ok, Form_Type :: 'node_config' | 'publish-options', Node_Type :: 'leaf' | 'collection', Xmlels_Field :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()]} %%% | {error, 'not-acceptable'} | {error, 'feature-not-implemented', 'collections'} ). options_type(Xmlels, Pubsub_Features) -> options_type(Xmlels, lists:member(<<"collections">>, Pubsub_Features), undefined, undefined, []). %% -spec(options_type/5 :: ( Xmlels :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()], Collections :: boolean(), Form_Type :: undefined | 'node_config' | 'publish-options', Node_Type :: undefined | 'leaf' | 'collection', Xmlels_Fields :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()]) -> {ok, Form_Type :: 'node_config' | 'publish-options', Node_Type :: 'leaf' | 'collection', Xmlels_Field :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()]} %%% | {error, 'not-acceptable'} | {error, 'feature-not-implemented', 'collections'} ). options_type([] = _Xmlels, _Collections, Form_Type, undefined = _Node_Type, Xmlels_Field) when Form_Type =/= undefined -> {ok, Form_Type, 'leaf', Xmlels_Field}; %% options_type([] = _Xmlels, _Collections, Form_Type, Node_Type, Xmlels_Field) when Form_Type =/= undefined -> {ok, Form_Type, Node_Type, Xmlels_Field}; %% options_type([] = _Xmlels, _Collections, undefined = _Form_Type, _Node_Type, _Xmlels_Field) -> {error, 'bad-options'}; %% options_type(Xmlels, _Collections, Form_Type, Node_Type, Xmlels_Field) when Form_Type =/= undefined andalso Node_Type =/= undefined -> {ok, Form_Type, Node_Type, Xmlels ++ Xmlels_Field}; %% options_type([Xmlel_Field | Xmlels_Field], Collections, Form_Type, Node_Type, Xmlels) when ?Is_Xmlel_Field(Xmlel_Field) -> case {xmlns(Xmlel_Field), get_tag_attr_s(<<"var">>, Xmlel_Field)} of {_, <<>>} -> {error, 'not-acceptable'}; {?NS_XDATA, <<"FORM_TYPE">>} -> case remove_cdata(Xmlel_Field#xmlel.children) of [Xmlel_Value] when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, ?NS_PUBSUB_NODE_CONFIG} -> options_type(Xmlels_Field, Collections, 'node_config', Node_Type, Xmlels); {?NS_XDATA, ?NS_PUBSUB_PUBLISH_OPTIONS} -> options_type(Xmlels_Field, Collections, 'publish-options', Node_Type, Xmlels); _ -> {error, 'not-acceptable'} end; _ -> {error, 'not-acceptable'} end; {?NS_XDATA, <<"pubsub#node_type">>} -> case remove_cdata(Xmlel_Field#xmlel.children) of [Xmlel_Value] when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<"leaf">>} -> options_type(Xmlels_Field, Collections, Form_Type, 'leaf', Xmlels); {?NS_XDATA, <<"collection">>} -> case Collections of true -> options_type(Xmlels_Field, Collections, Form_Type, 'collection', Xmlels); false -> {error, 'feature-not-implemented', 'collections'} end; _ -> {error, 'not-acceptable'} end end; {?NS_XDATA, _Xmlattr} -> options_type(Xmlels_Field, Collections, Form_Type, Node_Type, [Xmlel_Field | Xmlels]); _ -> {error, 'not-acceptable'} end. %% -spec(parse_xmlels_field/6 :: ( Options_Type :: 'node_config' | 'publish-options', Node_Type :: 'leaf' | 'collection', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Entity :: xmpp_jid:usr_entity(), Xmlels :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()], Options :: pubsub_options:options_node() | pubsub_options:options_item() %% | {error, 'invalid-options'} | {error, 'jid-malformed'} % | {error, 'not-acceptable'} | {error, 'not-acceptable', 'unsupported-access-model'} % | {error, 'feature-not-implemented', 'collections'} | {error, 'feature-not-implemented', 'multi-collections'}) -> {ok, Options :: pubsub_options:options_node() | pubsub_options:options_item()} %%% | {error, 'invalid-options'} | {error, 'jid-malformed'} % | {error, 'not-acceptable'} | {error, 'not-acceptable', 'unsupported-access-model'} % | {error, 'feature-not-implemented', 'collections'} | {error, 'feature-not-implemented', 'multi-collections'} ). %% parse_xmlels_field(_Options_Type, _Node_Type, _Pubsub_Features, _Entity, _Xmlels, Error) when is_tuple(Error) -> Error; parse_xmlels_field(_Options_Type, _Node_Type, _Pubsub_Features, _Entity, [] = _Xmlels, Options) -> {ok, Options}; %% parse_xmlels_field(Options_Type, Node_Type, Pubsub_Features, Entity, [Xmlel_Field | Xmlels], Options) when ?Is_Xmlel_Field(Xmlel_Field) -> case xmlns(Xmlel_Field) of ?NS_XDATA -> parse_xmlels_field(Options_Type, Node_Type, Pubsub_Features, Entity, Xmlels, parse_xmlel_field_attrs( get_tag_attr_s(<<"var">>, Xmlel_Field), Options_Type, Node_Type, Pubsub_Features, Entity, remove_cdata(Xmlel_Field#xmlel.children), Options)); _ -> {error, 'invalid-options'} end; %% parse_xmlels_field(_Options_Type, _Node_Type, _Pubsub_Feature, _Entity, _Xmlels, _Options) -> {error, 'invalid-options'}. %% -spec(parse_xmlels_field/7 :: ( Options_Type :: 'subscribe_options', Node_Type :: 'leaf' | 'collection', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Entity :: xmpp_jid:usr_entity(), Entity_Type :: 'local' | 'remote', Xmlels :: [Xmlel_Field::xmlel()] | [Xmlel::xmlel()], Options :: pubsub_options:options_subscription() % | {error, 'invalid-options'} | {error, 'not-acceptable'}) -> {ok, Options :: pubsub_options:options_node() | pubsub_options:options_item()} %%% | {error, 'invalid-options'} | {error, 'not-acceptable'} ). %% parse_xmlels_field(_Options_Type, _Node_Type, _Pubsub_Features, _Entity, _Entity_Type, _Xmlels, Error) when is_tuple(Error) -> Error; parse_xmlels_field(_Options_Type, _Node_Type, _Pubsub_Features, _Entity, _Entity_Type, [] = _Xmlels, Options) -> {ok, trim_subscription_options(Options)}; %% parse_xmlels_field(Options_Type, Node_Type, Pubsub_Features, Entity, Entity_Type, [Xmlel_Field | Xmlels], Options) when ?Is_Xmlel_Field(Xmlel_Field) -> case xmlns(Xmlel_Field) of ?NS_XDATA -> parse_xmlels_field(Options_Type, Node_Type, Pubsub_Features, Entity, Entity_Type, Xmlels, parse_xmlel_field_attrs( get_tag_attr_s(<<"var">>, Xmlel_Field), Options_Type, Node_Type, Pubsub_Features, Entity, Entity_Type, remove_cdata(Xmlel_Field#xmlel.children), Options)); _ -> {error, 'invalid-options'} end; %% parse_xmlels_field(_Options_Type, _Node_Type, _Pubsub_Feature, _Entity, _Entity_Type, _Xmlels, _Options) -> {error, 'invalid-options'}. %% -spec(parse_xmlel_field_attrs/7 :: ( Pubsub_Option :: binary(), Options_Type :: 'node_config' | 'publish-options', Node_Type :: 'leaf' | 'collection', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Entity :: xmpp_jid:usr_entity(), Xmlels :: [Xmlel_Value::xmlel(),...] | [Xmlel::xmlel(),...], Options :: pubsub_options:options_node() | pubsub_options:options_item()) -> Options :: pubsub_options:options_node() | pubsub_options:options_item() %%% | {error, 'invalid-options'} | {error, 'jid-malformed'} % | {error, 'not-acceptable'} | {error, 'not-acceptable', 'unsupported-access-model'} % | {error, 'feature-not-implemented', 'collections'} | {error, 'feature-not-implemented', 'multi-collections'} ). parse_xmlel_field_attrs(<<"pubsub#roster_groups_allowed">>, Options_Type, Node_Type, Pubsub_Features, Entity, Xmlels, Options) when (Options_Type == 'node_config' orelse Options_Type == 'publish-options') andalso (Node_Type == 'leaf' orelse Node_Type == 'collection') -> case lists:member(<<"access-roster">>, Pubsub_Features) of true -> case case Options_Type of 'node_config' -> parse_pubsub_option_node(<<"roster_groups_allowed">>, Node_Type, Pubsub_Features, Xmlels); 'publish-options' -> parse_pubsub_option_item(<<"roster_groups_allowed">>, Pubsub_Features, Xmlels) end of {ok, Roster_Groups_Allowed} -> case lists:keyfind('roster_groups_allowed', 1, Options) of false -> [{Entity, Roster_Groups_Allowed} | Options]; {'roster_groups_allowed', Rosters_Groups_Allowed} -> lists:keyreplace('roster_groups_allowed', 1, Options, {'roster_groups_allowed', _New_Rosters_Groups_Allowed = case lists:keyreplace(Entity, 1, Rosters_Groups_Allowed, {Entity, Roster_Groups_Allowed}) of Rosters_Groups_Allowed -> [{Entity, Roster_Groups_Allowed} | Rosters_Groups_Allowed]; New_Rosters_Groups_Allowed -> New_Rosters_Groups_Allowed end}) end; Error -> Error end; false -> {error, 'invalid-options'} end; %% parse_xmlel_field_attrs(<<"pubsub#", Pubsub_Option/binary>>, 'node_config' = _Options_Type, Node_Type, Pubsub_Features, _Entity, Xmlels, Node_Options) -> case lists:keymember( Key = list_to_atom(binary_to_list(Pubsub_Option)), 1, Node_Options) of true -> case parse_pubsub_option_node(Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) of {ok, Value} -> lists:keyreplace(Key, 1, Node_Options, {Key, Value}); Error -> Error end; false -> Node_Options%{error, 'invalid-options'} end; %% parse_xmlel_field_attrs(<<"pubsub#", Pubsub_Option/binary>>, 'publish-options' = _Options_Type, _Node_Type, Pubsub_Features, _Entity, Xmlels, Item_Options) -> case parse_pubsub_option_item(Pubsub_Option, Pubsub_Features, Xmlels) of {ok, Value} when Value == undefined orelse Value == [] -> lists:keydelete(_Key = list_to_atom(binary_to_list(Pubsub_Option)), 1, Item_Options); {ok, Value} -> Key = list_to_atom(binary_to_list(Pubsub_Option)), case lists:keyreplace(Key, 1, Item_Options, {Key, Value}) of Item_Options -> [{Key, Value} | Item_Options]; New_Item_Options -> New_Item_Options end; Error -> Error end; %% parse_xmlel_field_attrs(_Xmlattr_value, _Options_Type, _Node_Type, _Pubsub_Features, _Entity, _Xmlels, _Options) -> {error, 'invalid-options'}. %% -spec(parse_xmlel_field_attrs/8 :: ( Pubsub_Option :: binary(), Options_Type :: 'subscribe_options', Node_Type :: 'leaf' | 'collection', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Entity :: xmpp_jid:usr_entity(), Entity_Type :: 'local' | 'remote', Xmlels :: [Xmlel_Value::xmlel(),...] | [Xmlel::xmlel(),...], Subscription_Options :: pubsub_options:options_subscription()) -> Subscription_Options :: pubsub_options:options_subscription() %%% | {error, 'invalid-options'} ). parse_xmlel_field_attrs(<<"pubsub#", Pubsub_Option/binary>>, 'subscribe_options' = _Options_Type, Node_Type, Pubsub_Features, _Entity, Entity_Type, Xmlels, Subscription_Options) -> case lists:keymember(Key = list_to_atom(binary_to_list(Pubsub_Option)), 1, Subscription_Options) of true -> case parse_pubsub_option_subscription(Pubsub_Option, Node_Type, Entity_Type, Pubsub_Features, Xmlels) of {ok, Value} when ?Is_Default_Subscribe_Option({Key, Value}) -> lists:keydelete(Key, 1, Subscription_Options); {ok, Value} -> lists:keyreplace(Key, 1, Subscription_Options, {Key, Value}); Error -> Error end; false -> {error, 'invalid-options'} end; %% parse_xmlel_field_attrs(_Xmlattr_value, _Options_Type, _Node_Type, _Pubsub_Features, _Entity, _Entity_Type, _Xmlels, _Options) -> {error, 'invalid-options'}. %% %% -spec(parse_pubsub_option_node/4 :: ( Pubsub_Option :: binary(), Node_Type :: 'collection' | 'leaf', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Xmlels :: [Xmlel_Value::xmlel()] | [Xmlel::xmlel()]) -> {ok, Access_Model :: pubsub_options:access_model()} % | {ok, Body_XSLT :: undefined | binary()} | {ok, Children_Association_Policy :: 'all' | 'owners' | 'whitelist'} | {ok, Children_Association_Whitelist :: [Jid::xmpp_jid:raw_jid_entity_bare()]} | {ok, Children :: [Child_NodeId::exmpp_pubsub:nodeId()]} | {ok, Children_Max :: undefined | non_neg_integer()} | {ok, Collection :: [Parent_NodeId::exmpp_pubsub:nodeId()]} | {ok, Contact :: [Jid::xmpp_jid:raw_jid_entity()]} % | {ok, Dataform_XSLT :: undefined | binary()} | {ok, Deliver_Notifications :: boolean()} | {ok, Deliver_Payloads :: boolean()} | {ok, Description :: undefined | binary()} | {ok, Item_Expire :: undefined | non_neg_integer()} | {ok, ItemReply :: pubsub_options:item_reply()} | {ok, Language :: undefined | binary()} | {ok, Max_Items :: undefined | non_neg_integer()} | {ok, Max_Payload_Size :: undefined | non_neg_integer()} | {ok, Node_Type :: pubsub_options:node_type()} | {ok, Notification_Type :: pubsub_options:notification_type()} | {ok, Notify_Config :: boolean()} | {ok, Notify_Delete :: boolean()} | {ok, Notify_Retract :: boolean()} | {ok, Notify_Sub :: boolean()} | {ok, Persist_Items :: boolean()} | {ok, Presence_Based_Delivery :: boolean()} | {ok, Publish_Model :: pubsub_options:publish_model()} | {ok, Purge_Offline :: boolean()} | {ok, Rosters_Groups_Allowed :: pubsub_options:rosters_groups_allowed()} | {ok, Send_Last_Published_Item :: pubsub_options:send_last_published_item()} | {ok, Tempsub :: boolean()} | {ok, Subscribe :: boolean()} | {ok, Title :: undefined | binary()} | {ok, Type :: undefined | atom()} %%% | {error, 'invalid-options'} | {error, 'jid-malformed'} % | {error, 'not-acceptable'} | {error, 'not-acceptable', 'unsupported-access-model'} % | {error, 'feature-not-implemented', 'collections'} | {error, 'feature-not-implemented', 'multi-collections'} ). parse_pubsub_option_node(<<"access_model">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> parse_xmlel_value({'access_model', Pubsub_Features}, Xmlels); %% %%parse_pubsub_option_node(<<"pubsub#body_xslt">> = _Pubsub_Option, %% 'leaf' = _Node_Type, Pusbub_Features, Xmlels) -> %% case lists:member(<<"publish">>, Pubsub_Features) of %% true -> %% parse_xmlel_value('text-single', Xmlels); %% false -> %% {error, 'invalid-options'} %% end; %% parse_pubsub_option_node(<<"children_association_policy">> = _Pubsub_Option, 'collection' = _Node_Type, _Pubsub_Features, Xmlels) -> parse_xmlel_value({'list-single', 'atom', _Default_Values = ['all', 'owners', 'whitelist']}, Xmlels); %% parse_pubsub_option_node(<<"children_association_whitelist">> = _Pubsub_Option, 'collection' = _Node_Type, _Pubsub_Features, [] = _Xmlels) -> {ok, []}; parse_pubsub_option_node(<<"children_association_whitelist">> = _Pubsub_Option, 'collection' = _Node_Type, _Pubsub_Features, Xmlels) -> parse_xmlel_value({'jid-multi', 'bare'}, Xmlels); %% %% parse_pubsub_option_node(<<"children">> = _Pubsub_Option, 'collection' = _Node_Type, _Pubsub_Features, [] = Xmlels) -> parse_xmlel_value('text-multi', Xmlels); parse_pubsub_option_node(<<"children">> = _Pubsub_Option, 'collection' = _Node_Type, _Pubsub_Features, [_] = Xmlels) -> parse_xmlel_value('text-multi', Xmlels); parse_pubsub_option_node(<<"children">> = _Pubsub_Option, 'collection' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"multi-collections">>, Pubsub_Features) of true -> parse_xmlel_value('text-multi', Xmlels); false -> {error, 'feature-not-implemented', 'multi-collections'} end; %% %% parse_pubsub_option_node(<<"children_max">> = _Pubsub_Option, 'collection' = _Node_Type, _Pubsub_Features, [] = _Xmlels) -> {ok, undefined}; parse_pubsub_option_node(<<"children_max">> = _Pubsub_Option, 'collection' = _Node_Type, Pubsub_Features, [Xmlel_Value]) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> {ok, undefined}; {?NS_XDATA, CData} -> case catch list_to_integer(binary_to_list(CData)) of Integer when Integer == 0 orelse Integer == 1 -> {ok, Integer}; Integer when is_integer(Integer) andalso Integer > 1 -> case lists:member(<<"multi-collections">>, Pubsub_Features) of true -> {ok, Integer}; false -> {error, 'not-acceptable'} end; _ -> {error, 'not-acceptable'} end; _ -> {error, 'not-acceptable'} end; parse_pubsub_option_node(<<"children_max">> = _Pubsub_Option, 'collection' = _Node_Type, _Pubsub_Features, _Xmlels) -> {error, 'not-acceptable'}; %% parse_pubsub_option_node(<<"collection">> = _Pubsub_Option, Node_Type, Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"collections">>, Pubsub_Features) of true -> {ok, []}; false -> {error, 'feature-not-implemented', 'collections'} end; parse_pubsub_option_node(<<"collection">> = _Pubsub_Option, Node_Type, Pubsub_Features, [_] = Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"collections">>, Pubsub_Features) of true -> parse_xmlel_value('text-multi', Xmlels); false -> {error, 'feature-not-implemented', 'collections'} end; parse_pubsub_option_node(<<"collection">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"collections">>, Pubsub_Features) of true -> case lists:member(<<"multi-collections">>, Pubsub_Features) of true -> parse_xmlel_value('text-multi', Xmlels); false -> {error, 'feature-not-implemented', 'multi-collections'} end; false -> {error, 'feature-not-implemented', 'collections'} end; %% parse_pubsub_option_node(<<"contact">> = _Pubsub_Option, Node_Type, _Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> {ok, []}; parse_pubsub_option_node(<<"contact">> = _Pubsub_Option, Node_Type, _Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> parse_xmlel_value({'jid-multi', 'full'}, Xmlels); %% %%parse_pubsub_option_node(<<"pubsub#dataform_xslt">> = _Pubsub_Option, %% 'leaf' = _Node_Type, Pusbub_Features, Xmlels) -> %% case lists:member(<<"publish">>, Pubsub_Features) of %% true -> %% parse_xmlel_value('text-single', Xmlels); %% false -> %% {error, 'invalid-options'} %% end; %% parse_pubsub_option_node(<<"deliver_notifications">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"deliver_payloads">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"description">> = _Pubsub_Option, Node_Type, _Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> {ok, undefined}; parse_pubsub_option_node(<<"description">> = _Pubsub_Option, Node_Type, _Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> parse_xmlel_value('text-single', Xmlels); %% parse_pubsub_option_node(<<"item_expire">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, [] = _Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_node(<<"item_expire">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'text-single', 'integer'}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"itemreply">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'list-single', 'atom', _Default_Values = ['owner', 'publisher']}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"language">> = _Pubsub_Option, Node_Type, _Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> {ok, undefined}; parse_pubsub_option_node(<<"language">> = _Pubsub_Option, Node_Type, _Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> parse_xmlel_value('text-single', Xmlels); %% parse_pubsub_option_node(<<"max_items">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, [] = _Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_node(<<"max_items">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'text-single', 'integer'}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"max_payload_size">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, [] = _Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_node(<<"max_payload_size">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'text-single', 'integer'}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"notification_type">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'list-single', 'atom', _Default_Values = ['headline', 'normal']}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"notify_config">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"config-node">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"notify_delete">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"delete-nodes">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"notify_retract">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"delete-items">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"notify_sub">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"persist_items">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"persistent-items">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"presence_based_delivery">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"publish_model">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'list-single', 'atom', _Default_Values = ['open', 'publishers', 'subscribers']}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"purge_offline">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"purge-nodes">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"roster_groups_allowed">> = _Pubsub_Option, Node_Type, Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"access-roster">>, Pubsub_Features) of true -> {ok, []}; false -> {error, 'invalid-options'} end; parse_pubsub_option_node(<<"roster_groups_allowed">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"access-roster">>, Pubsub_Features) of true -> parse_xmlel_value('list-multi', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"send_last_published_item">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"last-published">>, Pubsub_Features) of true -> parse_xmlel_value({'list-single', 'atom', _Default_Values = case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> ['never', 'on_sub', 'on_sub_and_presence']; false -> ['never', 'on_sub'] end}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"tempsub">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"subscribe">> = _Pubsub_Option, Node_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(<<"title">> = _Pubsub_Option, Node_Type, _Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> {ok, undefined}; parse_pubsub_option_node(<<"title">> = _Pubsub_Option, Node_Type, _Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> parse_xmlel_value('text-single', Xmlels); %% parse_pubsub_option_node(<<"type">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, [] = _Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_node(<<"type">> = _Pubsub_Option, 'leaf' = _Node_Type, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'text-single', 'atom'}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_node(_Pubsub_Option, _Node_Type, _Pubsub_Features, _Xmlels) -> {error, 'invalid-options'}. %% %% -spec(parse_pubsub_option_item/3 :: ( Pubsub_Option :: binary(), Pubsub_Features :: exmpp_pubsub:pubsub_features(), Xmlels :: [Xmlel_Value::xmlel()] | [Xmlel::xmlel()]) -> {ok, Access_Model :: pubsub_options:access_model()} % | {ok, Body_XSLT :: undefined | binary()} % | {ok, Dataform_XSLT :: undefined | binary()} | {ok, Deliver_Notifications :: boolean()} | {ok, Deliver_Payloads :: boolean()} | {ok, Item_Expire :: undefined | non_neg_integer()} | {ok, ItemReply :: pubsub_options:item_reply()} %% | {ok, Max_Payload_Size :: undefined | non_neg_integer()} | {ok, Notification_Type :: pubsub_options:notification_type()} | {ok, Notify_Config :: boolean()} | {ok, Notify_Retract :: boolean()} | {ok, Persist_Items :: boolean()} | {ok, Presence_Based_Delivery :: boolean()} % | {ok, Publish_Model :: pubsub_options:publish_model()} | {ok, Purge_Offline :: boolean()} | {ok, Rosters_Groups_Allowed :: pubsub_options:rosters_groups_allowed()} | {ok, Send_Last_Published_Item :: pubsub_options:send_last_published_item()} | {ok, Type :: undefined | atom()} %%% | {error, 'invalid-options'} % | {error, 'not-acceptable'} | {error, 'not-acceptable', 'unsupported-access-model'} ). parse_pubsub_option_item(<<"access_model">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> parse_xmlel_value({'access_model', Pubsub_Features}, Xmlels); %% %%parse_pubsub_option_item(<<"pubsub#body_xslt">> = _Pubsub_Option, %% Pusbub_Features, Xmlels) -> %% case lists:member(<<"publish">>, Pubsub_Features) of %% true -> %% parse_xmlel_value('text-single', Xmlels); %% false -> %% {error, 'invalid-options'} %% end; %% %%parse_pubsub_option_item(<<"pubsub#dataform_xslt">> = _Pubsub_Option, %% Pusbub_Features, Xmlels) -> %% case lists:member(<<"publish">>, Pubsub_Features) of %% true -> %% parse_xmlel_value('text-single', Xmlels); %% false -> %% {error, 'invalid-options'} %% end; %% parse_pubsub_option_item(<<"deliver_notifications">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"deliver_payloads">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"item_expire">> = _Pubsub_Option, Pubsub_Features, [] = _Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_item(<<"item_expire">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'text-single', 'integer'}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"itemreply">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'list-single', 'atom', _Default_Values = ['owner', 'publisher']}, Xmlels); false -> {error, 'invalid-options'} end; %% %parse_pubsub_option_item(<<"max_payload_size">> = _Pubsub_Option, % Pubsub_Features, Xmlels) -> % case lists:member(<<"publish">>, Pubsub_Features) of % true -> % parse_xmlel_value({'text-single', 'integer'}, Xmlels); % false -> % {error, 'invalid-options'} % end; %% parse_pubsub_option_item(<<"notification_type">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'list-single', 'atom', _Default_Values = ['headline', 'normal']}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"notify_config">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"config-node">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"notify_retract">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"delete-items">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"persist_items">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"persistent-items">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"presence_based_delivery">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% %parse_pubsub_option_item(<<"publish_model">> = _Pubsub_Option, % Pubsub_Features, Xmlels) -> % case lists:member(<<"publish">>, Pubsub_Features) of % true -> % parse_xmlel_value({'list-single', 'atom', % _Default_Values = ['open', 'publishers', 'subscribers']}, % Xmlels); % false -> % {error, 'invalid-options'} % end; %% parse_pubsub_option_item(<<"purge_offline">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"purge-nodes">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"roster_groups_allowed">> = _Pubsub_Option, Pubsub_Features, [] = _Xmlels) -> case lists:member(<<"access-roster">>, Pubsub_Features) of true -> {ok, []}; false -> {error, 'invalid-options'} end; parse_pubsub_option_item(<<"roster_groups_allowed">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"access-roster">>, Pubsub_Features) of true -> parse_xmlel_value('list-multi', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"send_last_published_item">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"last-published">>, Pubsub_Features) of true -> parse_xmlel_value({'list-single', 'atom', _Default_Values = case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> ['never', 'on_sub', 'on_sub_and_presence']; false -> ['never', 'on_sub'] end}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(<<"type">> = _Pubsub_Option, Pubsub_Features, [] = _Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_item(<<"type">> = _Pubsub_Option, Pubsub_Features, Xmlels) -> case lists:member(<<"publish">>, Pubsub_Features) of true -> parse_xmlel_value({'text-single', 'atom'}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_item(_Pubsub_Option, _Pubsub_Features, _Xmlels) -> {error, 'invalid-options'}. %% %% -spec(parse_pubsub_option_subscription/5 :: ( Pubsub_Option :: binary(), Node_Type :: 'collection' | 'leaf', Entity_Type :: 'local' | 'remote', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Xmlels :: [Xmlel_Value::xmlel()] | [Xmlel::xmlel()]) -> % {ok, Digest :: boolean()} % | {ok, Digest_Frequency :: undefined | non_neg_integer()} {ok, Deliver :: boolean()} | {ok, Expire :: undefined | 'presence' | erlang:timestamp()} % | {ok, Include_Body :: boolean()} | {ok, Show_Values :: ['away' | 'chat' | 'dnd' | 'online' | 'xa']} % | {ok, Subscription_Type :: 'all' | 'items' | 'nodes'} % | {ok, Subscription_Depth :: 'all' | non_neg_integer()} %%% | {error, 'invalid-options'} % | {error, 'not-acceptable'} ). %% parse_pubsub_option_subscription(<<"digest">> = _Pubsub_Option, %% 'leaf' = _Node_Type, _Entity_Type, Pubsub_Features, Xmlels) -> %% case lists:member(<<"subscribe">>, Pubsub_Features) of %% true -> %% parse_xmlel_value('boolean', Xmlels); %% false -> %% {error, 'invalid-options'} %% end; %% %% parse_pubsub_option_subscription(<<"digest_frequency">> = _Pubsub_Option, %% 'leaf' = _Node_Type, _Entity_Type, Pubsub_Features, Xmlels) -> %% case lists:member(<<"subscribe">>, Pubsub_Features) of %% true -> %% parse_xmlel_value({'text-single', 'integer'}, Xmlels); %% false -> %% {error, 'invalid-options'} %% end; %% parse_pubsub_option_subscription(<<"deliver">> = _Pubsub_Option, Node_Type, _Entity_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"subscribe">>, Pubsub_Features) of true -> parse_xmlel_value('boolean', Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_subscription(<<"expire">> = _Pubsub_Option, Node_Type, 'local' = _Entity_Type, Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"presence-notifications">>, Pubsub_Features) orelse lists:member(<<"leased-subscriptions">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_subscription(<<"expire">> = _Pubsub_Option, Node_Type, 'local' = _Entity_Type, Pubsub_Features, [Xmlel_Value]) when Node_Type == 'collection' orelse Node_Type == 'leaf' andalso ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> {ok, undefined}; {?NS_XDATA, <<"presence">>} -> case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> {ok, 'presence'}; false -> {error, 'invalid-options'} end; {?NS_XDATA, CData} -> case lists:member(<<"leased-subscriptions">>, Pubsub_Features) of true -> case jlib:datetime_string_to_timestamp(CData) of undefined -> {error, 'not-acceptable'}; DateTime -> {ok, DateTime} end; false -> {error, 'invalid-options'} end; _ -> {error, 'invalid-options'} end; % parse_pubsub_option_subscription(<<"expire">> = _Pubsub_Option, Node_Type, 'remote' = _Entity_Type, Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"leased-subscriptions">>, Pubsub_Features) of true -> {ok, undefined}; false -> {error, 'invalid-options'} end; parse_pubsub_option_subscription(<<"expire">> = _Pubsub_Option, Node_Type, 'remote' = _Entity_Type, Pubsub_Features, [Xmlel_Value]) when Node_Type == 'collection' orelse Node_Type == 'leaf' andalso ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> {ok, undefined}; {?NS_XDATA, <<"presence">>} -> {error, 'invalid-options'}; {?NS_XDATA, CData} -> case lists:member(<<"leased-subscriptions">>, Pubsub_Features) of true -> case jlib:datetime_string_to_timestamp(CData) of undefined -> {error, 'not-acceptable'}; DateTime -> {ok, DateTime} end; false -> {error, 'invalid-options'} end; _ -> {error, 'invalid-options'} end; %% %parse_pubsub_option_subscription(<<"include_body">> = _Pubsub_Option, % 'leaf' = _Node_Type, _Entity_Type, Pubsub_Features, Xmlels) -> % case lists:member(<<"subscribe">>, Pubsub_Features) of % true -> % parse_xmlel_value('boolean', Xmlels); % false -> % {error, 'invalid-options'} % end; %% parse_pubsub_option_subscription(<<"show-values">> = _Pubsub_Option, Node_Type, 'local' = _Entity_Type, Pubsub_Features, [] = _Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> {ok, []}; false -> {error, 'invalid-options'} end; parse_pubsub_option_subscription(<<"show-values">> = _Pubsub_Option, Node_Type, 'local' = _Entity_Type, Pubsub_Features, Xmlels) when Node_Type == 'collection' orelse Node_Type == 'leaf' -> case lists:member(<<"presence-notifications">>, Pubsub_Features) of true -> parse_xmlel_value({'list-multi', 'atom', _Default_Values = ['away' ,'chat', 'dnd', 'online', 'xa']}, Xmlels); false -> {error, 'invalid-options'} end; %% parse_pubsub_option_subscription(<<"show-values">> = _Pubsub_Option, _Node_Type, 'remote' = _Entity_Type, _Pubsub_Features, _Xmlels) -> {error, 'invalid-options'}; %% %parse_pubsub_option_subscription(<<"subscription_type">> = _Pubsub_Option, % 'collection' = _Node_Type, _Entity_Type, _Pubsub_Features, Xmlels) -> % parse_xmlel_value({'list-single', 'atom', % _Default_Values = ['all', 'items', 'nodes']}, Xmlels); %% %parse_pubsub_option_subscription(<<"subscription_depth">> = _Pubsub_Option, % 'collection' = _Node_Type, _Entity_Type, _Pubsub_Features, Xmlels) -> % case Xmlels of % [] -> % {ok, 0}; % [Xmlel_Value] when ?Is_Xmlel_Value(Xmlel_Value) -> % case {Xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of % {?NS_XDATA, <<>>} -> % {ok, 0}; % {?NS_XDATA, <<"all">>} -> % {ok, 'all'}; % {?NS_XDATA, CData} -> % case catch list_to_integer(binary_to_list(CData)) of % Integer % when is_integer(Integer) andalso Integer > -1 -> % {ok, Integer}; % _Error -> % {error, 'not-acceptable'} % end; % _ -> % {error, 'not-acceptable'} % end; % _Xmlels -> % {error, 'not-acceptable'} % end; %% parse_pubsub_option_subscription(_Pubsub_Option, _Node_Type, _Entity_Type, _Pubsub_Features, _Xmlels) -> {error, 'invalid-options'}. -spec(parse_xmlel_value/2 :: ( DataType :: {'jid-multi', 'bare'} | {'jid-multi', 'full'} | {'list-multi', 'atom', Default_Values::[Default_Value::atom(),...]} | 'list-multi' | 'text-multi' | {'access_model', Pubsub_Features::exmpp_pubsub:pubsub_features()} | 'boolean' | 'text-single' | {'text-single', 'atom'} | {'text-single', 'integer'} | {'list-single', 'atom', Default_Values::[Default_Value::atom(),...]}, Xmlels :: [Xmlel_Value::xmlel()] | [Xmlel::xmlel()]) -> %% {ok, Values :: [] | [Value::binary()] | [Value::atom()] | [Value::xmpp_jid:raw_jid_entity_bare()] | [Value::xmpp_jid:raw_jid_entity()]} | {ok, Value :: atom() | binary() | boolean() | non_neg_integer() | undefined} %%% | {error, 'invalid-options'} | {error, 'jid-malformed'} | {error, 'not-acceptable'} | {error, 'not-acceptable', 'unsupported-access-model'} ). %% parse_xmlel_value({'jid-multi', 'bare'}, [] = _Xmlels) -> {ok, []}; %% parse_xmlel_value({'jid-multi', 'bare'}, Xmlels) -> parse_xmlel_value({'jid-multi', 'bare'}, Xmlels, []); %% parse_xmlel_value({'jid-multi', 'full'}, [] = _Xmlels) -> {ok, []}; %% parse_xmlel_value({'jid-multi', 'full'}, Xmlels) -> parse_xmlel_value({'jid-multi', 'full'}, Xmlels, []); %% %% parse_xmlel_value({'list-multi', 'atom', _Default_Values}, [] = _Xmlels) -> {error, 'not-acceptable'}; %% parse_xmlel_value({'list-multi', 'atom', Default_Values}, Xmlels) -> parse_xmlel_value({'list-multi', 'atom', Default_Values}, Xmlels, []); %% parse_xmlel_value('list-multi', Xmlels) -> parse_xmlel_value('list-multi', Xmlels, []); %% %% parse_xmlel_value('text-multi', [] = _Xmlels) -> {ok, []}; %% parse_xmlel_value('text-multi', Xmlels) -> parse_xmlel_value('text-multi', Xmlels, []); %% parse_xmlel_value({'access_model', Pubsub_Features}, [Xmlel_Value]) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<"authorize">>} -> case lists:member(<<"access-authorize">>, Pubsub_Features) of true -> {ok, 'authorize'}; false -> {error, 'not-acceptable', 'unsupported-access-model'} end; %% {?NS_XDATA, <<"open">>} -> case lists:member(<<"access-open">>, Pubsub_Features) of true -> {ok, 'open'}; false -> {error, 'not-acceptable', 'unsupported-access-model'} end; %% {?NS_XDATA, <<"presence">>} -> case lists:member(<<"access-presence">>, Pubsub_Features) of true -> {ok, 'presence'}; false -> {error, 'not-acceptable', 'unsupported-access-model'} end; %% {?NS_XDATA, <<"roster">>} -> case lists:member(<<"access-roster">>, Pubsub_Features) of true -> {ok, 'roster'}; false -> {error, 'not-acceptable', 'unsupported-access-model'} end; %% {?NS_XDATA, <<"whitelist">>} -> case lists:member(<<"access-whitelist">>, Pubsub_Features) of true -> {ok, 'whitelist'}; false -> {error, 'not-acceptable', 'unsupported-access-model'} end; %% _ -> {error, 'not-acceptable'} end; parse_xmlel_value({'access_model', _Pubsub_Features}, _Xmlels) -> {error, 'not-acceptable'}; %% %% parse_xmlel_value('boolean', [Xmlel_Value]) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, False} when False == <<"0">> orelse False == <<"false">> -> {ok, false}; {?NS_XDATA, True} when True == <<"1">> orelse True == <<"true">> -> {ok, true}; _ -> {error, 'not-acceptable'} end; parse_xmlel_value('boolean', _Xmlels) -> {error, 'not-acceptable'}; %% %% parse_xmlel_value('text-single', [] = _Xmlels) -> {ok, undefined}; parse_xmlel_value('text-single', [Xmlel_Value]) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> {ok, undefined}; {?NS_XDATA, CData} -> {ok, CData}; _ -> {error, 'not-acceptable'} end; parse_xmlel_value('text-single', _Xmlels) -> {error, 'not-acceptable'}; %% %% parse_xmlel_value({'text-single', 'atom'}, [] = _Xmlels) -> {ok, undefined}; parse_xmlel_value({'text-single', 'atom'}, [Xmlel_Value]) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> {ok, undefined}; {?NS_XDATA, CData} -> {ok, list_to_atom(binary_to_list(CData))}; _ -> {error, 'not-acceptable'} end; parse_xmlel_value({'text-single', 'atom'}, _Xmlels) -> {error, 'not-acceptable'}; %% %% parse_xmlel_value({'text-single', 'integer'}, [] = _Xmlels) -> {ok, undefined}; parse_xmlel_value({'text-single', 'integer'}, [Xmlel_Value]) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> {ok, undefined}; {?NS_XDATA, CData} -> case catch list_to_integer(binary_to_list(CData)) of Integer when is_integer(Integer) andalso Integer > -1 -> {ok, Integer}; _ -> {error, 'not-acceptable'} end; _ -> {error, 'not-acceptable'} end; parse_xmlel_value({'text-single', 'integer'}, _Xmlels) -> {error, 'not-acceptable'}; %% %% parse_xmlel_value({'list-single', 'atom', Default_Values}, [Xmlel_Value]) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {_, <<>>} -> {error, 'not-acceptable'}; {?NS_XDATA, CData} -> case lists:member(Value = list_to_atom(binary_to_list(CData)), Default_Values) of true -> {ok, Value}; false -> {error, 'not-acceptable'} end; _ -> {error, 'not-acceptable'} end; parse_xmlel_value({'list-single', 'atom', _Default_Values}, _Xmlels) -> {error, 'not-acceptable'}; %% parse_xmlel_value({_DataType, _Default_Values}, _Xmlels) -> {error, 'not-acceptable'}. %% %% -spec(parse_xmlel_value/3 :: ( DataType :: {'list-multi', 'atom', Default_Values::[Default_Value::atom(),...]} | 'list-multi' | 'text-multi' | {'jid-multi', 'full'} | {'jid-multi', 'bare'}, Xmlels :: [Xmlel_Value::xmlel()] | [Xmlel::xmlel()], Values :: [Value::binary()] | [Value::atom()] | [Value::xmpp_jid:raw_jid_entity_bare()] | [Value::xmpp_jid:raw_jid_entity_full()]) -> {ok, Values :: [Value::binary()] | [Value::atom()] | [Value::xmpp_jid:raw_jid_entity_bare()] | [Value::xmpp_jid:raw_jid_entity_full()]} %%% | {error, 'not-acceptable'} | {error, 'jid-malformed'} ). parse_xmlel_value(_DataType, _Xmlels = [], Values) -> {ok, lists:usort(Values)}; %% %% parse_xmlel_value({'list-multi', 'atom', Default_Values}, [Xmlel_Value | Xmlels], Values) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> parse_xmlel_value({'list-multi', 'atom', Default_Values}, Xmlels, Values); {?NS_XDATA, CData} -> case lists:member(Value = list_to_atom(binary_to_list(CData)), Default_Values) of true -> parse_xmlel_value({'list-multi', 'atom', Default_Values}, Xmlels, [Value | Values]); false -> {error, 'not-acceptable'} end; _ -> {error, 'not-acceptable'} end; %% %% parse_xmlel_value('list-multi', [Xmlel_Value | Xmlels], Values) when ?Is_Xmlel_Value(Xmlel_Value) -> parse_xmlel_value('list-multi', Xmlels, case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> Values; {?NS_XDATA, CData} -> [CData | Values]; _ -> {error, 'not-acceptable'} end); %% %% parse_xmlel_value('text-multi', [Xmlel_Value | Xmlels] , Values) when ?Is_Xmlel_Value(Xmlel_Value) -> parse_xmlel_value('text-multi', Xmlels, case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> Values; {?NS_XDATA, CData} -> [_Value = CData | Values]; _ -> {error, 'not-acceptable'} end); %% %% parse_xmlel_value({'jid-multi', 'full'}, [Xmlel_Value | Xmlels], Values) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> parse_xmlel_value({'jid-multi', 'full'}, Xmlels, Values); {?NS_XDATA, CData} -> case is_jid(CData) of #jid{} = Jid -> parse_xmlel_value({'jid-multi', 'full'}, Xmlels, [jlib:jid_to_string(Jid) | Values]); Error -> Error end; _ -> {error, 'not-acceptable'} end; %% parse_xmlel_value({'jid-multi', 'bare'}, [Xmlel_Value | Xmlels], Values) when ?Is_Xmlel_Value(Xmlel_Value) -> case {xmlns(Xmlel_Value), get_tag_cdata(Xmlel_Value)} of {?NS_XDATA, <<>>} -> parse_xmlel_value({'jid-multi', 'bare'}, Xmlels, Values); {?NS_XDATA, CData} -> case is_jid(CData) of #jid{} = Jid -> parse_xmlel_value({'jid-multi', 'bare'}, Xmlels, [jlib:jid_to_string(Jid#jid{resource = <<>>, lresource = <<>>}) | Values]); Error -> Error end; _ -> {error, 'not-acceptable'} end; %% parse_xmlel_value(_Data_Type, _Xmlels, _Values) -> {error, 'not-acceptable'}. %% %% -spec(xdata_x/6 :: ( Options_Type :: 'node_config' | 'subscribe_options', Form_Type :: 'form' | 'result', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Host :: xmpp_jid:raw_jid_component_bare(), Entity :: xmpp_jid:usr_bare(), Options :: pubsub_options:options_node() | pubsub_options:options_subscription()) -> Xmlel_X::xmlel() ). xdata_x('node_config', 'form', Pubsub_Features, Host, Entity, Node_Options) -> xmpp_xdata:xmlel_x(<<"form">>, _Xmlels_Field = [ xmpp_xdata:xmlel_field(<<"FORM_TYPE">>, <<"hidden">>, [?NS_PUBSUB_NODE_CONFIG]) |xdata_field(Pubsub_Features, Host, Entity, Node_Options, []) ]); xdata_x('subscribe_options', 'form', Pubsub_Features, Host, Entity, Subscription_Options) -> xmpp_xdata:xmlel_x(<<"form">>, _Xmlels_Field = [ xmpp_xdata:xmlel_field(<<"FORM_TYPE">>, <<"hidden">>, [?NS_PUBSUB_SUBSCRIBE_OPTIONS]) |xdata_field(Pubsub_Features, Host, Entity, Subscription_Options, []) ]); xdata_x('subscribe_options', 'result', Pubsub_Features, Host, Entity, Subscription_Options) -> xmpp_xdata:xmlel_x(<<"result">>, _Xmlels_Field = [ xmpp_xdata:xmlel_field(<<"FORM_TYPE">>, <<"hidden">>, [?NS_PUBSUB_SUBSCRIBE_OPTIONS]) |xdata_field(Pubsub_Features, Host, Entity, Subscription_Options, []) ]). %% %% -spec(xdata_x/7 :: ( Options_Type :: 'subscribe_options', Form_Type :: 'form', Pubsub_Features :: exmpp_pubsub:pubsub_features(), Host :: xmpp_jid:raw_jid_component_bare(), Entity :: xmpp_jid:usr_bare(), Subscription_Options :: [] | pubsub_options:options_subscription(), Default_Subscription_Options :: pubsub_options:options_subscription()) -> Xmlel_X::xmlel() ). %% xdata_x('subscribe_options', 'form', Pubsub_Features, Host, Entity, Subscription_Options, Default_Subscription_Options) -> xmpp_xdata:xmlel_x(<<"form">>, _Xmlels_Field = [ xmpp_xdata:xmlel_field(<<"FORM_TYPE">>, <<"hidden">>, [?NS_PUBSUB_SUBSCRIBE_OPTIONS]) |xdata_field(Pubsub_Features, Host, Entity, filter_subscription_options(Subscription_Options, Default_Subscription_Options, []), []) ]). %% -spec(filter_subscription_options/3 :: ( Options :: [] | pubsub_options:options_subscription(), Default_Subscription_Options :: pubsub_options:options_subscription(), Subscription_Options :: [] | pubsub_options:options_subscription()) -> Subscription_Options::pubsub_options:options_subscription() ). filter_subscription_options([] = _Options, Default_Subscription_Options, Subscription_Options) -> Default_Subscription_Options ++ Subscription_Options; %% filter_subscription_options([{Key, Value} | Options], Default_Subscription_Options, Subscription_Options) -> filter_subscription_options(Options, lists:keydelete(Key, 1, Default_Subscription_Options), [{Key, Value} | Subscription_Options]). -define(Label_Deliver, <<"Enable delivery ?">>). -define(Label_Digest, <<"Receive digest notifications ?">>). -define(Label_Digest_Frequency, <<"Receive digest notifications (approx. one per day)?">>). -define(Label_Expire, <<"Requested lease period">>). -define(Label_Include_Body, <<"Receive message body in addition to payload ?">>). -define(Label_Show_Values, <<"Select the presence types which are allowed to receive event notifications">>). %% %% pubsub#subscribe_options %% -spec(xdata_field/5 :: ( Pubsub_Features :: exmpp_pubsub:pubsub_features(), Host :: xmpp_jid:raw_jid_component_bare(), Entity :: xmpp_jid:usr_bare(), Options :: [] | pubsub_options:options_subscription(), Xmlels_Field :: [] | [Xmlel_Field::xmlel(),...]) -> Xmlels_Field::[Xmlel_Field::xmlel(),...] ). %% xdata_field(_Pubsub_Features, _Host, _Entity, [] = _Options, Xmlels_Field) -> lists:sort(Xmlels_Field); %% 'pubsub#deliver' xdata_field(Pubsub_Features, Host, Entity, [{'deliver', Deliver} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#deliver">>, <<"Enable delivery?">>, xdata_value('boolean', Deliver)) | Xmlels_Field]); %% 'pubsub#digest' xdata_field(Pubsub_Features, Host, Entity, [{'digest', Digest} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#digest">>, <<"Receive digest notifications (approx. one per day)?">>, xdata_value('boolean', Digest)) | Xmlels_Field]); %% 'pubsub#digest_frequency' xdata_field(Pubsub_Features, Host, Entity, [{'digest_frequency', Digest_Frequency} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#digest_frequency">>, <<"Receive digest notifications (approx. one per day)?">>, xdata_value('integer', Digest_Frequency)) | Xmlels_Field]); %% 'pubsub#expire' xdata_field(Pubsub_Features, Host, Entity, [{'expire', Expire} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#expire">>, <<"Requested lease period">>, case is_atom(Expire) of true -> xdata_value('atom', Expire); false -> xdata_value('date', Expire) end) | Xmlels_Field]); %% 'pubsub#include_body' xdata_field(Pubsub_Features, Host, Entity, [{'include_body', Include_Body} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#include_body">>, <<"Receive message body in addition to payload?">>, xdata_value('boolean', Include_Body)) | Xmlels_Field]); %% 'pubsub#show-values' xdata_field(Pubsub_Features, Host, Entity, [{'show-values', Show_Values} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_multi( <<"pubsub#show-values">>, <<"Select the presence types which are allowed to receive event notifications">>, lists:map(fun ('away') -> <<"away">>; ('chat') -> <<"chat">>; ('dnd') -> <<"dnd">>; ('online') -> <<"online">>; ('xa') -> <<"xa">> end, Show_Values), [{<<"away">>, <<"Away">>}, {<<"chat">>, <<"Want to Chat">>}, {<<"dnd">>, <<"Do Not Disturb">>}, {<<"online">>, <<"Available">>}, {<<"xa">>, <<"Extended Away">>}]) | Xmlels_Field]); %% 'pubsub#subscription_type' xdata_field(Pubsub_Features, Host, Entity, [{'subscription_type', Subscription_Type} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#subscription_type">>, <<"Subscription Type">>, case Subscription_Type of undefined -> <<"items">>; 'items' -> <<"items">>; 'nodes' -> <<"nodes">>; 'all' -> <<"all">> end, [{<<"items">>, <<"Receive notification of items only">>}, {<<"nodes">>, <<"Receive notification of new nodes only">>}, {<<"all">>, <<"Receive notification of items and nodes">>}]) | Xmlels_Field]); %% 'pubsub#subscription_depth' xdata_field(Pubsub_Features, Host, Entity, [{'subscription_depth', Subscription_Depth} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#subscription_depth">>, <<"How far to traverse the node graph for notifications">>, case Subscription_Depth of undefined -> <<"1">>; 'all' -> <<"all">>; _ -> xdata_value('integer', Subscription_Depth) end, [{<<"1">>, <<"Receive notification from direct child nodes only">>}, {<<"all">>, <<"Receive notification from all descendent nodes">>}]) | Xmlels_Field]); %% %% pubsub#node_config %% %% 'pubsub#access_model' xdata_field(Pubsub_Features, Host, Entity, [{'access_model', Access_Model} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#access_model">>, <<"Specify the subscriber model">>, case Access_Model of % undefined -> <<"open">>; 'authorize' -> <<"authorize">>; 'open' -> <<"open">>; 'presence' -> <<"presence">>; 'roster' -> <<"roster">>; 'whitelist' -> <<"whitelist">> end, xdata_access_model(Pubsub_Features, ['authorize', 'open', 'presence', 'roster', 'whitelist'])) | Xmlels_Field]); %% 'pubsub#body_xslt' xdata_field(Pubsub_Features, Host, Entity, [{'body_xslt', Xslt} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#body_xslt">>, <<"The URL of an XSL transformation which can be applied to " "payloads in order to generate an appropriate message body element">>, Xslt) | Xmlels_Field]); %% 'pubsub#children_association_policy' xdata_field(Pubsub_Features, Host, Entity, [{'children_association_policy', Children_Association_Policy} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#children_association_policy">>, <<"Who may associate leaf nodes with a collection">>, case Children_Association_Policy of undefined -> <<"owners">>; 'owners' -> <<"owners">>; 'all' -> <<"all">>; 'whitelist' -> <<"whitelist">> end, [{<<"all">>, <<"Anyone may associate leaf nodes with the collection">>}, {<<"owners">>, <<"Only collection node owners may associate leaf" " nodes with the collection">>}, {<<"whitelist">>, <<"Only those on a whitelist may associate leaf " "nodes with the collection">>}]) | Xmlels_Field]); %% 'pubsub#children_association_whitelist' xdata_field(Pubsub_Features, Host, Entity, [{'children_association_whitelist', Children_Association_Whitelist} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_jid_multi( <<"pubsub#children_association_whitelist">>, <<"The list of JIDs that may associate leaf nodes with a collection">>, Children_Association_Whitelist) | Xmlels_Field]); %% 'pubsub#children' xdata_field(Pubsub_Features, Host, Entity, [{'children', Children} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_multi( <<"pubsub#children">>, <<"The child nodes (leaf or collection) associated with a collection">>, Children) | Xmlels_Field]); %% 'pubsub#children_max' xdata_field(Pubsub_Features, Host, Entity, [{'children_max', Children_Max} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#children_max">>, <<"The maximum number of child nodes that can be associated with a collection">>, xdata_value('integer', Children_Max)) | Xmlels_Field]); %% 'pubsub#collection' xdata_field(Pubsub_Features, Host, Entity, [{'collection', Collection} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_multi( <<"pubsub#collection">>, <<"The collection(s) with which a node is affiliated">>, Collection) | Xmlels_Field]); %% 'pubsub#contact' xdata_field(Pubsub_Features, Host, Entity, [{'contact', Contacts} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_jid_multi( <<"pubsub#contact">>, <<"The JIDs of those to contact with questions">>, Contacts) | Xmlels_Field]); %% 'pubsub#dataform_xslt' xdata_field(Pubsub_Features, Host, Entity, [{'dataform_xslt', Dataform_Xslt} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#dataform_xslt">>, <<"Payload XSLT">>, xdata_value({'text-multi', 'atom'}, Dataform_Xslt)) | Xmlels_Field]); %% 'pubsub#deliver_notifications' xdata_field(Pubsub_Features, Host, Entity, [{'deliver_notifications', Deliver_Notifications} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#deliver_notifications">>, <<"Whether to deliver event notifications">>, xdata_value('boolean', Deliver_Notifications)) | Xmlels_Field]); %% 'pubsub#deliver_payloads' xdata_field(Pubsub_Features, Host, Entity, [{'deliver_payloads', Deliver_Payloads} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#deliver_payloads">>, <<"Whether to deliver payloads with event notifications">>, xdata_value('boolean', Deliver_Payloads)) | Xmlels_Field]); %% 'pubsub#description' xdata_field(Pubsub_Features, Host, Entity, [{'description', Description} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#description">>, <<"A description of the node">>, Description) | Xmlels_Field]); %% 'pubsub#item_expire' xdata_field(Pubsub_Features, Host, Entity, [{'item_expire', Item_Expire} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#item_expire">>, <<"Number of seconds after which to automatically purge items">>, xdata_value('integer', Item_Expire)) | Xmlels_Field]); %% 'pubsub#itemreply' xdata_field(Pubsub_Features, Host, Entity, [{'itemreply', ItemReply} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#itemreply">>, <<"Whether owners or publisher should receive replies to items">>, case ItemReply of undefined -> <<"publisher">>; 'owner' -> <<"owner">>; 'publisher' -> <<"publisher">> end, [{<<"owner">>, <<"Statically specify a replyto of the node owner(s)">>}, {<<"publisher">>, <<"Dynamically specify a replyto of the item publisher">>}]) | Xmlels_Field]); %% 'pubsub#language' xdata_field(Pubsub_Features, Host, Entity, [{'language', Language} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#language">>, <<"The default language of the node">>, case Language of undefined -> <<"en">>; _Language -> Language end, [{<<"en">>, <<"English">>} %{<<"es">>, <<"Español">>}, %{<<"fr">>, <<"Français">>}, %{<<"pl">>, <<"Polski">>}, %{<<"ru">>, <<"Русский">>} ]) | Xmlels_Field]); %% 'pubsub#max_items' xdata_field(Pubsub_Features, Host, Entity, [{'max_items', Max_Items} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#max_items">>, <<"The maximum number of items to persist">>, xdata_value('integer', Max_Items)) | Xmlels_Field]); %% 'pubsub#max_payload_size' xdata_field(Pubsub_Features, Host, Entity, [{'max_payload_size', Max_Payload_Size} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#max_payload_size">>, <<"The maximum payload size in bytes">>, xdata_value('integer', Max_Payload_Size)) | Xmlels_Field]); %% 'pubsub#node_type' xdata_field(Pubsub_Features, Host, Entity, [{'node_type', Node_Type} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [case lists:member(<<"collections">>, Pubsub_Features) of true -> xmpp_xdata:xmlel_field_list_single( <<"pubsub#node_type">>, <<"Whether the node is a leaf (default) or a collection">>, case Node_Type of undefined -> <<"leaf">>; 'leaf' -> <<"leaf">>; 'collection' -> <<"collection">> end, [{<<"leaf">>, <<"The node is a leaf node (default)">>}, {<<"collection">>, <<"The node is a collection node">>}]); false -> %% Collections not supported -> non-modifiable field % xmpp_xdata:xmlel_field_fixed( % <<"pubsub#node_type">>, % <<"The node is a leaf node (default)">>, % <<"leaf">>) xmpp_xdata:xmlel_field_list_single( <<"pubsub#node_type">>, <<"Whether the node is a leaf (default) or a collection">>, <<"leaf">>, [{<<"leaf">>, <<"The node is a leaf node (default)">>}]) end |Xmlels_Field]); %% 'pubsub#notification_type' xdata_field(Pubsub_Features, Host, Entity, [{'notification_type', Notification_Type} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#notification_type">>, <<"Specify the delivery style for event notifications">>, case Notification_Type of undefined -> <<"headline">>; 'headline' -> <<"headline">>; 'normal' -> <<"normal">>; 'chat' -> <<"chat">> end, [{<<"headline">>, <<"Messages of type headline">>}, {<<"normal">>, <<"Messages of type normal">>} %{<<"chat">>, <<"Messages of type chat">>} %{<<"presence">>, <<"Presence">>} %{<<"iq">>, <<"Iq">>} ]) | Xmlels_Field]); %% 'pubsub#notify_config' xdata_field(Pubsub_Features, Host, Entity, [{'notify_config', Notify_Config} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#notify_config">>, <<"Notify owners and subscribers when the node configuration changes">>, xdata_value('boolean', Notify_Config)) | Xmlels_Field]); %% 'pubsub#notify_delete' xdata_field(Pubsub_Features, Host, Entity, [{'notify_delete', Notify_Delete} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#notify_delete">>, <<"Notify owners and subscribers when the node is deleted">>, xdata_value('boolean', Notify_Delete)) | Xmlels_Field]); %% 'pubsub#notify_retract' xdata_field(Pubsub_Features, Host, Entity, [{'notify_retract', Notify_Retract} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#notify_retract">>, <<"Notify subscribers when items are removed from the node">>, xdata_value('boolean', Notify_Retract)) | Xmlels_Field]); %% 'pubsub#notify_sub' xdata_field(Pubsub_Features, Host, Entity, [{'notify_sub', Notify_Sub} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#notify_sub">>, <<"Notify owners about new subscribers and unsubscribes">>, xdata_value('boolean', Notify_Sub)) | Xmlels_Field]); %% 'pubsub#persist_items' xdata_field(Pubsub_Features, Host, Entity, [{'persist_items', Persist_Items} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#persist_items">>, <<"Persist items to storage">>, xdata_value('boolean', Persist_Items)) | Xmlels_Field]); %% 'pubsub#presence_based_delivery' xdata_field(Pubsub_Features, Host, Entity, [{'presence_based_delivery', Presence_Based_Delivery} | Options] , Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#presence_based_delivery">>, <<"Deliver event notifications only to available users">>, xdata_value('boolean', Presence_Based_Delivery)) | Xmlels_Field]); %% 'pubsub#publish_model' xdata_field(Pubsub_Features, Host, Entity, [{'publish_model', Publish_Model} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#publish_model">>, <<"Specify the publisher model">>, case Publish_Model of % undefined -> <<"open">>; 'open' -> <<"open">>; 'publishers' -> <<"publishers">>; 'subscribers' -> <<"subscribers">> end, [{<<"publishers">>, <<"Only publishers may publish">>}, {<<"subscribers">>, <<"Subscribers may publish">>}, {<<"open">>, <<"Anyone may publish">>}]) | Xmlels_Field]); %% 'pubsub#purge_offline' xdata_field(Pubsub_Features, Host, Entity, [{'purge_offline', Purge_Offline} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#purge_offline">>, <<"Purge all items when the relevant publisher goes offline ?">>, xdata_value('boolean', Purge_Offline)) | Xmlels_Field]); %% 'pubsub#roster_groups_allowed' xdata_field(Pubsub_Features, Host, Entity, [{'roster_groups_allowed', Rosters_Groups_Allowed} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_multi( <<"pubsub#roster_groups_allowed">>, <<"Roster group(s) allowed to subscribe and retrieve items">>, case lists:keyfind(Entity, 1, Rosters_Groups_Allowed) of false -> []; {_Entity, Roster_Groups} -> Roster_Groups end, xdata_roster(Host, Entity)) | Xmlels_Field]); %% 'pubsub#send_last_published_item' xdata_field(Pubsub_Features, Host, Entity, [{'send_last_published_item', Send_Last_Published_Item} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_list_single( <<"pubsub#send_last_published_item">>, <<"When to send the last published item">>, case Send_Last_Published_Item of undefined -> <<"on_sub_and_presence">>; 'never' -> <<"never">>; 'on_sub_and_presence' -> <<"on_sub_and_presence">>; 'on_sub' -> <<"on_sub">> end, [{<<"never">>, <<"Never">>}, {<<"on_sub">>, <<"When a new subscription is processed">>}, {<<"on_sub_and_presence">>, <<"When a new subscription is processed " "and whenever a subscriber comes online">>}]) | Xmlels_Field]); %% 'pubsub#subscribe' xdata_field(Pubsub_Features, Host, Entity, [{'subscribe', Subscribe} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#subscribe">>, <<"Whether to allow subscriptions">>, xdata_value('boolean', Subscribe)) | Xmlels_Field]); %% 'pubsub#tempsub' xdata_field(Pubsub_Features, Host, Entity, [{'tempsub', Tempsub} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_boolean( <<"pubsub#tempsub">>, <<"Make all subscriptions temporary, based on subscriber presence">>, xdata_value('boolean', Tempsub)) | Xmlels_Field]); %% 'pubsub#title' xdata_field(Pubsub_Features, Host, Entity, [{'title', Title} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#title">>, <<"A friendly name for the node">>, Title) | Xmlels_Field]); %% 'pubsub#type' xdata_field(Pubsub_Features, Host, Entity, [{'type', Type} | Options], Xmlels_Field) -> xdata_field(Pubsub_Features, Host, Entity, Options, [xmpp_xdata:xmlel_field_text_single( <<"pubsub#type">>, <<"Specify the type of payload data to be provided at this node">>, Type) | Xmlels_Field]). %% -spec(xdata_value/2 :: ( DataType :: 'atom' | 'boolean' | 'date' | 'integer' | {'text-multi', 'atom'}, Value :: undefined | atom() | boolean() | erlang:timestamp() | non_neg_integer() | [atom()]) -> Xdata_Value :: binary() | [binary(),...] ). xdata_value(_, undefined) -> undefined; %% xdata_value('atom', Value) -> list_to_binary(atom_to_list(Value)); %% xdata_value('boolean', false) -> <<"false">>; xdata_value('boolean', true) -> <<"true">>; %% xdata_value('date', TimeStamp) -> {DateTime, _} = jlib:timestamp_to_iso(calendar:now_to_datetime(TimeStamp), utc), list_to_binary(DateTime ++ "Z"); %% xdata_value('integer', Value) -> list_to_binary(integer_to_list(Value)); %% xdata_value({'text-multi', 'atom'}, Values) -> [list_to_binary(atom_to_list(Value)) || Value <- Values]. %% -spec(xdata_access_model/3 :: ( Access_Model :: pubsub_options:access_model(), Pubsub_Feature :: boolean(), Access_Models :: [{binary(), binary()}]) -> Access_Models :: [{binary(), binary()}] ). xdata_access_model(_Access_Model, false, Access_Models) -> Access_Models; %% xdata_access_model('authorize' = _Access_Model, true, Access_Models) -> [{<<"authorize">>, <<"Subscription requests must be approved and only " "subscribers may retrieve items">>} | Access_Models]; %% xdata_access_model('open' = _Access_Model, true, Access_Models) -> [{<<"open">>, <<"Anyone may subscribe and retrieve items">>} | Access_Models]; %% xdata_access_model('presence' = _Access_Model, true, Access_Models) -> [{<<"presence">>, <<"Anyone with a presence subscription of both or from may " "subscribe and retrieve items">>} | Access_Models]; %% xdata_access_model('roster' = _Access_Model, true, Access_Models) -> [{<<"roster">>, <<"Anyone in the specified roster group(s) may subscribe and " "retrieve items">>} | Access_Models]; %% xdata_access_model('whitelist' = _Access_Model, true, Access_Models) -> [{<<"whitelist">>, <<"Only those on a whitelist may subscribe and retrieve items">>} | Access_Models]. %% -spec(xdata_access_model/2 :: ( Pubsub_Features :: exmpp_pubsub:pubsub_features(), Default_Access_Model :: ['authorize'|'open'|'presence'|'roster'|'whitelist',...]) -> Access_Models :: [{binary(), binary()},...] ). xdata_access_model(Pubsub_Features, Default_Access_Models) -> lists:foldr(fun ('authorize', Access_Models) -> xdata_access_model('authorize', lists:member(<<"access-authorize">>, Pubsub_Features), Access_Models); %% ('open', Access_Models) -> xdata_access_model('open', lists:member(<<"access-open">>, Pubsub_Features), Access_Models); %% ('presence', Access_Models) -> xdata_access_model('presence', lists:member(<<"access-presence">>, Pubsub_Features), Access_Models); %% ('roster', Access_Models) -> xdata_access_model('roster', lists:member(<<"access-roster">>, Pubsub_Features), Access_Models); %% ('whitelist', Access_Models) -> xdata_access_model('whitelist', lists:member(<<"access-whitelist">>, Pubsub_Features), Access_Models) % end, [], Default_Access_Models). %% %% Local Entity -spec(xdata_roster/2 :: ( Host :: binary(), Entity :: xmpp_jid:usr_bare()) -> Roster_Groups :: [Roster_Group::binary()] ). xdata_roster(Host, {_, Host, _} = Entity) -> _Roster_Groups = lists:usort(lists:foldl(fun (#roster{groups = Groups}, Roster_Groups) -> lists:foldl(fun (Group, Roster_Groups_Bis) -> [Group | Roster_Groups_Bis] end, Roster_Groups, Groups) end, [], _Roster = get_entity_roster(Entity))); %% Remote Entity xdata_roster(_Host, _Entity) -> [].