mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-20 17:27:00 +01:00
Switch to stand-alone XMPP library
This commit is contained in:
parent
d00a634025
commit
9aff7e52a8
10
Makefile.in
10
Makefile.in
@ -108,14 +108,6 @@ edoc:
|
||||
$(ERL) -noinput +B -eval \
|
||||
'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.'
|
||||
|
||||
spec:
|
||||
$(ERL) -noinput +B -pa ebin -pa deps/*/ebin -eval \
|
||||
'case fxml_gen:compile("specs/xmpp_codec.spec", [{add_type_specs, xmpp_element}, {erl_dir, "src"}, {hrl_dir, "include"}]) of ok -> halt(0); _ -> halt(1) end.'
|
||||
|
||||
xdata:
|
||||
$(ERL) -noinput +B -pa ebin -pa deps/*/ebin -eval \
|
||||
'case xdata_codec:compile("specs", [{erl_dir, "src"}, {hrl_dir, "include"}]) of ok -> halt(0); _ -> halt(1) end.'
|
||||
|
||||
JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1))
|
||||
|
||||
VERSIONED_DEP=$(if $(DEP_$(1)_VERSION),$(DEP_$(1)_VERSION),$(1))
|
||||
@ -347,5 +339,5 @@ quicktest:
|
||||
$(REBAR) skip_deps=true ct suites=elixir
|
||||
|
||||
.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean rel \
|
||||
install uninstall uninstall-binary uninstall-all translations deps test spec \
|
||||
install uninstall uninstall-binary uninstall-all translations deps test \
|
||||
quicktest erlang_plt deps_plt ejabberd_plt
|
||||
|
@ -1,10 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: flex_offline.xdata
|
||||
%% Form type: http://jabber.org/protocol/offline
|
||||
%% Document: XEP-0013
|
||||
|
||||
|
||||
-type property() :: {'number_of_messages', non_neg_integer()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type form() :: [property() | xdata_field()].
|
@ -1,17 +0,0 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @copyright (C) 2016, Evgeny Khramtsov
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 10 Jul 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%-------------------------------------------------------------------
|
||||
-record(jid, {user = <<"">> :: binary(),
|
||||
server = <<"">> :: binary(),
|
||||
resource = <<"">> :: binary(),
|
||||
luser = <<"">> :: binary(),
|
||||
lserver = <<"">> :: binary(),
|
||||
lresource = <<"">> :: binary()}).
|
||||
|
||||
-type(jid() :: #jid{}).
|
||||
-type(ljid() :: {binary(), binary(), binary()}).
|
@ -1,13 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: mam_query.xdata
|
||||
%% Form type: urn:xmpp:mam:1
|
||||
%% Document: XEP-0313
|
||||
|
||||
|
||||
-type property() :: {'with', jid:jid()} |
|
||||
{'start', erlang:timestamp()} |
|
||||
{'end', erlang:timestamp()} |
|
||||
{'withtext', binary()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type form() :: [property() | xdata_field()].
|
@ -1,16 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: muc_register.xdata
|
||||
%% Form type: http://jabber.org/protocol/muc#register
|
||||
%% Document: XEP-0045
|
||||
|
||||
|
||||
-type property() :: {'allow', boolean()} |
|
||||
{'email', binary()} |
|
||||
{'faqentry', [binary()]} |
|
||||
{'first', binary()} |
|
||||
{'last', binary()} |
|
||||
{'roomnick', binary()} |
|
||||
{'url', binary()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type form() :: [property() | xdata_field()].
|
@ -1,16 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: muc_request.xdata
|
||||
%% Form type: http://jabber.org/protocol/muc#request
|
||||
%% Document: XEP-0045
|
||||
|
||||
|
||||
-type property() :: {'role', participant} |
|
||||
{'jid', jid:jid()} |
|
||||
{'roomnick', binary()} |
|
||||
{'request_allow', boolean()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type options(T) :: [{binary(), T}].
|
||||
-type property_with_options() ::
|
||||
{'role', participant, options(participant)}.
|
||||
-type form() :: [property() | property_with_options() | xdata_field()].
|
@ -1,55 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: muc_roomconfig.xdata
|
||||
%% Form type: http://jabber.org/protocol/muc#roomconfig
|
||||
%% Document: XEP-0045
|
||||
|
||||
-type 'allow_private_messages_from_visitors'() :: nobody | moderators | anyone.
|
||||
-type 'maxusers'() :: none | non_neg_integer().
|
||||
-type 'presencebroadcast'() :: moderator | participant | visitor.
|
||||
-type 'whois'() :: moderators | anyone.
|
||||
|
||||
-type property() :: {'maxhistoryfetch', binary()} |
|
||||
{'allowpm', binary()} |
|
||||
{'allow_private_messages', boolean()} |
|
||||
{'allow_private_messages_from_visitors', 'allow_private_messages_from_visitors'()} |
|
||||
{'allow_visitor_status', boolean()} |
|
||||
{'allow_visitor_nickchange', boolean()} |
|
||||
{'allow_voice_requests', boolean()} |
|
||||
{'allow_subscription', boolean()} |
|
||||
{'voice_request_min_interval', non_neg_integer()} |
|
||||
{'captcha_protected', boolean()} |
|
||||
{'captcha_whitelist', [jid:jid()]} |
|
||||
{'allow_query_users', boolean()} |
|
||||
{'allowinvites', boolean()} |
|
||||
{'changesubject', boolean()} |
|
||||
{'enablelogging', boolean()} |
|
||||
{'getmemberlist', [binary()]} |
|
||||
{'lang', binary()} |
|
||||
{'pubsub', binary()} |
|
||||
{'maxusers', 'maxusers'()} |
|
||||
{'membersonly', boolean()} |
|
||||
{'moderatedroom', boolean()} |
|
||||
{'members_by_default', boolean()} |
|
||||
{'passwordprotectedroom', boolean()} |
|
||||
{'persistentroom', boolean()} |
|
||||
{'presencebroadcast', ['presencebroadcast'()]} |
|
||||
{'publicroom', boolean()} |
|
||||
{'public_list', boolean()} |
|
||||
{'roomadmins', [jid:jid()]} |
|
||||
{'roomdesc', binary()} |
|
||||
{'roomname', binary()} |
|
||||
{'roomowners', [jid:jid()]} |
|
||||
{'roomsecret', binary()} |
|
||||
{'whois', 'whois'()} |
|
||||
{'mam', boolean()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type options(T) :: [{binary(), T}].
|
||||
-type property_with_options() ::
|
||||
{'allowpm', binary(), options(binary())} |
|
||||
{'allow_private_messages_from_visitors', 'allow_private_messages_from_visitors'(), options('allow_private_messages_from_visitors'())} |
|
||||
{'getmemberlist', [binary()], options(binary())} |
|
||||
{'maxusers', 'maxusers'(), options('maxusers'())} |
|
||||
{'presencebroadcast', ['presencebroadcast'()], options('presencebroadcast'())} |
|
||||
{'whois', 'whois'(), options('whois'())}.
|
||||
-type form() :: [property() | property_with_options() | xdata_field()].
|
@ -1,18 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: muc_roominfo.xdata
|
||||
%% Form type: http://jabber.org/protocol/muc#roominfo
|
||||
%% Document: XEP-0045
|
||||
|
||||
|
||||
-type property() :: {'maxhistoryfetch', non_neg_integer()} |
|
||||
{'contactjid', [jid:jid()]} |
|
||||
{'description', binary()} |
|
||||
{'lang', binary()} |
|
||||
{'ldapgroup', binary()} |
|
||||
{'logs', binary()} |
|
||||
{'occupants', non_neg_integer()} |
|
||||
{'subject', binary()} |
|
||||
{'subjectmod', boolean()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type form() :: [property() | xdata_field()].
|
182
include/ns.hrl
182
include/ns.hrl
@ -1,182 +0,0 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2016 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
%%% published by the Free Software Foundation; either version 2 of the
|
||||
%%% License, or (at your option) any later version.
|
||||
%%%
|
||||
%%% This program is distributed in the hope that it will be useful,
|
||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
%%% General Public License for more details.
|
||||
%%%
|
||||
%%% You should have received a copy of the GNU General Public License along
|
||||
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-define(NS_COMPONENT, <<"jabber:component:accept">>).
|
||||
-define(NS_SERVER, <<"jabber:server">>).
|
||||
-define(NS_SERVER_DIALBACK, <<"jabber:server:dialback">>).
|
||||
-define(NS_CLIENT, <<"jabber:client">>).
|
||||
-define(NS_DISCO_ITEMS,
|
||||
<<"http://jabber.org/protocol/disco#items">>).
|
||||
-define(NS_DISCO_INFO,
|
||||
<<"http://jabber.org/protocol/disco#info">>).
|
||||
-define(NS_VCARD, <<"vcard-temp">>).
|
||||
-define(NS_VCARD_UPDATE, <<"vcard-temp:x:update">>).
|
||||
-define(NS_AUTH, <<"jabber:iq:auth">>).
|
||||
-define(NS_AUTH_ERROR, <<"jabber:iq:auth:error">>).
|
||||
-define(NS_REGISTER, <<"jabber:iq:register">>).
|
||||
-define(NS_SEARCH, <<"jabber:iq:search">>).
|
||||
-define(NS_ROSTER, <<"jabber:iq:roster">>).
|
||||
-define(NS_ROSTER_VER,
|
||||
<<"urn:xmpp:features:rosterver">>).
|
||||
-define(NS_PRIVACY, <<"jabber:iq:privacy">>).
|
||||
-define(NS_BLOCKING, <<"urn:xmpp:blocking">>).
|
||||
-define(NS_PRIVATE, <<"jabber:iq:private">>).
|
||||
-define(NS_VERSION, <<"jabber:iq:version">>).
|
||||
-define(NS_TIME, <<"urn:xmpp:time">>).
|
||||
-define(NS_LAST, <<"jabber:iq:last">>).
|
||||
-define(NS_XDATA, <<"jabber:x:data">>).
|
||||
-define(NS_IQDATA, <<"jabber:iq:data">>).
|
||||
-define(NS_DELAY, <<"urn:xmpp:delay">>).
|
||||
-define(NS_HINTS, <<"urn:xmpp:hints">>).
|
||||
-define(NS_EXPIRE, <<"jabber:x:expire">>).
|
||||
-define(NS_EVENT, <<"jabber:x:event">>).
|
||||
-define(NS_CHATSTATES,
|
||||
<<"http://jabber.org/protocol/chatstates">>).
|
||||
-define(NS_XCONFERENCE, <<"jabber:x:conference">>).
|
||||
-define(NS_STATS,
|
||||
<<"http://jabber.org/protocol/stats">>).
|
||||
-define(NS_MUC, <<"http://jabber.org/protocol/muc">>).
|
||||
-define(NS_MUC_USER,
|
||||
<<"http://jabber.org/protocol/muc#user">>).
|
||||
-define(NS_MUC_ADMIN,
|
||||
<<"http://jabber.org/protocol/muc#admin">>).
|
||||
-define(NS_MUC_OWNER,
|
||||
<<"http://jabber.org/protocol/muc#owner">>).
|
||||
-define(NS_MUC_UNIQUE,
|
||||
<<"http://jabber.org/protocol/muc#unique">>).
|
||||
-define(NS_PUBSUB,
|
||||
<<"http://jabber.org/protocol/pubsub">>).
|
||||
-define(NS_PUBSUB_EVENT,
|
||||
<<"http://jabber.org/protocol/pubsub#event">>).
|
||||
-define(NS_PUBSUB_META_DATA,
|
||||
<<"http://jabber.org/protocol/pubsub#meta-data">>).
|
||||
-define(NS_PUBSUB_OWNER,
|
||||
<<"http://jabber.org/protocol/pubsub#owner">>).
|
||||
-define(NS_PUBSUB_NMI,
|
||||
<<"http://jabber.org/protocol/pubsub#node-meta-info">>).
|
||||
-define(NS_PUBSUB_ERRORS,
|
||||
<<"http://jabber.org/protocol/pubsub#errors">>).
|
||||
-define(NS_PUBSUB_NODE_CONFIG,
|
||||
<<"http://jabber.org/protocol/pubsub#node_config">>).
|
||||
-define(NS_PUBSUB_SUB_OPTIONS,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_options">>).
|
||||
-define(NS_PUBSUB_SUBSCRIBE_OPTIONS,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_options">>).
|
||||
-define(NS_PUBSUB_PUBLISH_OPTIONS,
|
||||
<<"http://jabber.org/protocol/pubsub#publish_options">>).
|
||||
-define(NS_PUBSUB_SUB_AUTH,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_authorization">>).
|
||||
-define(NS_PUBSUB_GET_PENDING,
|
||||
<<"http://jabber.org/protocol/pubsub#get-pending">>).
|
||||
-define(NS_COMMANDS,
|
||||
<<"http://jabber.org/protocol/commands">>).
|
||||
-define(NS_BYTESTREAMS,
|
||||
<<"http://jabber.org/protocol/bytestreams">>).
|
||||
-define(NS_ADMIN,
|
||||
<<"http://jabber.org/protocol/admin">>).
|
||||
-define(NS_ADMIN_ANNOUNCE,
|
||||
<<"http://jabber.org/protocol/admin#announce">>).
|
||||
-define(NS_ADMIN_ANNOUNCE_ALL,
|
||||
<<"http://jabber.org/protocol/admin#announce-all">>).
|
||||
-define(NS_ADMIN_SET_MOTD,
|
||||
<<"http://jabber.org/protocol/admin#set-motd">>).
|
||||
-define(NS_ADMIN_EDIT_MOTD,
|
||||
<<"http://jabber.org/protocol/admin#edit-motd">>).
|
||||
-define(NS_ADMIN_DELETE_MOTD,
|
||||
<<"http://jabber.org/protocol/admin#delete-motd">>).
|
||||
-define(NS_ADMIN_ANNOUNCE_ALLHOSTS,
|
||||
<<"http://jabber.org/protocol/admin#announce-allhosts">>).
|
||||
-define(NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS,
|
||||
<<"http://jabber.org/protocol/admin#announce-all-allhosts">>).
|
||||
-define(NS_ADMIN_SET_MOTD_ALLHOSTS,
|
||||
<<"http://jabber.org/protocol/admin#set-motd-allhosts">>).
|
||||
-define(NS_ADMIN_EDIT_MOTD_ALLHOSTS,
|
||||
<<"http://jabber.org/protocol/admin#edit-motd-allhosts">>).
|
||||
-define(NS_ADMIN_DELETE_MOTD_ALLHOSTS,
|
||||
<<"http://jabber.org/protocol/admin#delete-motd-allhosts">>).
|
||||
-define(NS_SERVERINFO,
|
||||
<<"http://jabber.org/network/serverinfo">>).
|
||||
-define(NS_RSM, <<"http://jabber.org/protocol/rsm">>).
|
||||
-define(NS_EJABBERD_CONFIG, <<"ejabberd:config">>).
|
||||
-define(NS_STREAM,
|
||||
<<"http://etherx.jabber.org/streams">>).
|
||||
-define(NS_STANZAS,
|
||||
<<"urn:ietf:params:xml:ns:xmpp-stanzas">>).
|
||||
-define(NS_STREAMS,
|
||||
<<"urn:ietf:params:xml:ns:xmpp-streams">>).
|
||||
-define(NS_TLS, <<"urn:ietf:params:xml:ns:xmpp-tls">>).
|
||||
-define(NS_SASL,
|
||||
<<"urn:ietf:params:xml:ns:xmpp-sasl">>).
|
||||
-define(NS_SESSION,
|
||||
<<"urn:ietf:params:xml:ns:xmpp-session">>).
|
||||
-define(NS_BIND,
|
||||
<<"urn:ietf:params:xml:ns:xmpp-bind">>).
|
||||
-define(NS_FEATURE_IQAUTH,
|
||||
<<"http://jabber.org/features/iq-auth">>).
|
||||
-define(NS_FEATURE_IQREGISTER,
|
||||
<<"http://jabber.org/features/iq-register">>).
|
||||
-define(NS_FEATURE_COMPRESS,
|
||||
<<"http://jabber.org/features/compress">>).
|
||||
-define(NS_FEATURE_MSGOFFLINE, <<"msgoffline">>).
|
||||
-define(NS_FLEX_OFFLINE, <<"http://jabber.org/protocol/offline">>).
|
||||
-define(NS_COMPRESS,
|
||||
<<"http://jabber.org/protocol/compress">>).
|
||||
-define(NS_CAPS, <<"http://jabber.org/protocol/caps">>).
|
||||
-define(NS_SHIM, <<"http://jabber.org/protocol/shim">>).
|
||||
-define(NS_ADDRESS,
|
||||
<<"http://jabber.org/protocol/address">>).
|
||||
-define(NS_OOB, <<"jabber:x:oob">>).
|
||||
-define(NS_CAPTCHA, <<"urn:xmpp:captcha">>).
|
||||
-define(NS_MEDIA, <<"urn:xmpp:media-element">>).
|
||||
-define(NS_BOB, <<"urn:xmpp:bob">>).
|
||||
-define(NS_MAM_TMP, <<"urn:xmpp:mam:tmp">>).
|
||||
-define(NS_MAM_0, <<"urn:xmpp:mam:0">>).
|
||||
-define(NS_MAM_1, <<"urn:xmpp:mam:1">>).
|
||||
-define(NS_SID_0, <<"urn:xmpp:sid:0">>).
|
||||
-define(NS_PING, <<"urn:xmpp:ping">>).
|
||||
-define(NS_CARBONS_2, <<"urn:xmpp:carbons:2">>).
|
||||
-define(NS_CARBONS_1, <<"urn:xmpp:carbons:1">>).
|
||||
-define(NS_FORWARD, <<"urn:xmpp:forward:0">>).
|
||||
-define(NS_CLIENT_STATE, <<"urn:xmpp:csi:0">>).
|
||||
-define(NS_STREAM_MGMT_2, <<"urn:xmpp:sm:2">>).
|
||||
-define(NS_STREAM_MGMT_3, <<"urn:xmpp:sm:3">>).
|
||||
-define(NS_HTTP_UPLOAD, <<"urn:xmpp:http:upload">>).
|
||||
-define(NS_HTTP_UPLOAD_OLD, <<"eu:siacs:conversations:http:upload">>).
|
||||
-define(NS_THUMBS_1, <<"urn:xmpp:thumbs:1">>).
|
||||
-define(NS_NICK, <<"http://jabber.org/protocol/nick">>).
|
||||
-define(NS_SIC_0, <<"urn:xmpp:sic:0">>).
|
||||
-define(NS_SIC_1, <<"urn:xmpp:sic:1">>).
|
||||
-define(NS_MIX_0, <<"urn:xmpp:mix:0">>).
|
||||
-define(NS_MIX_SERVICEINFO_0, <<"urn:xmpp:mix:0#serviceinfo">>).
|
||||
-define(NS_MIX_NODES_MESSAGES, <<"urn:xmpp:mix:nodes:messages">>).
|
||||
-define(NS_MIX_NODES_PRESENCE, <<"urn:xmpp:mix:nodes:presence">>).
|
||||
-define(NS_MIX_NODES_PARTICIPANTS, <<"urn:xmpp:mix:nodes:participants">>).
|
||||
-define(NS_MIX_NODES_SUBJECT, <<"urn:xmpp:mix:nodes:subject">>).
|
||||
-define(NS_MIX_NODES_CONFIG, <<"urn:xmpp:mix:nodes:config">>).
|
||||
-define(NS_PRIVILEGE, <<"urn:xmpp:privilege:1">>).
|
||||
-define(NS_DELEGATION, <<"urn:xmpp:delegation:1">>).
|
||||
-define(NS_MUCSUB, <<"urn:xmpp:mucsub:0">>).
|
||||
-define(NS_MUCSUB_NODES_PRESENCE, <<"urn:xmpp:mucsub:nodes:presence">>).
|
||||
-define(NS_MUCSUB_NODES_MESSAGES, <<"urn:xmpp:mucsub:nodes:messages">>).
|
||||
-define(NS_MUCSUB_NODES_PARTICIPANTS, <<"urn:xmpp:mucsub:nodes:participants">>).
|
||||
-define(NS_MUCSUB_NODES_AFFILIATIONS, <<"urn:xmpp:mucsub:nodes:affiliations">>).
|
||||
-define(NS_MUCSUB_NODES_SUBJECT, <<"urn:xmpp:mucsub:nodes:subject">>).
|
||||
-define(NS_MUCSUB_NODES_CONFIG, <<"urn:xmpp:mucsub:nodes:config">>).
|
||||
-define(NS_MUCSUB_NODES_SYSTEM, <<"urn:xmpp:mucsub:nodes:system">>).
|
@ -1,13 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_get_pending.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#subscribe_authorization
|
||||
%% Document: XEP-0060
|
||||
|
||||
|
||||
-type property() :: {'node', binary()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type options(T) :: [{binary(), T}].
|
||||
-type property_with_options() ::
|
||||
{'node', binary(), options(binary())}.
|
||||
-type form() :: [property() | property_with_options() | xdata_field()].
|
@ -1,60 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_node_config.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#node_config
|
||||
%% Document: XEP-0060
|
||||
|
||||
-type 'access_model'() :: authorize | open | presence | roster | whitelist.
|
||||
-type 'children_association_policy'() :: all | owners | whitelist.
|
||||
-type 'itemreply'() :: owner | publisher | none.
|
||||
-type 'node_type'() :: leaf | collection.
|
||||
-type 'notification_type'() :: normal | headline.
|
||||
-type 'publish_model'() :: publishers | subscribers | open.
|
||||
-type 'send_last_published_item'() :: never | on_sub | on_sub_and_presence.
|
||||
|
||||
-type property() :: {'access_model', 'access_model'()} |
|
||||
{'body_xslt', binary()} |
|
||||
{'children_association_policy', 'children_association_policy'()} |
|
||||
{'children_association_whitelist', [jid:jid()]} |
|
||||
{'children', [binary()]} |
|
||||
{'children_max', binary()} |
|
||||
{'collection', [binary()]} |
|
||||
{'contact', [jid:jid()]} |
|
||||
{'dataform_xslt', binary()} |
|
||||
{'deliver_notifications', boolean()} |
|
||||
{'deliver_payloads', boolean()} |
|
||||
{'description', binary()} |
|
||||
{'item_expire', binary()} |
|
||||
{'itemreply', 'itemreply'()} |
|
||||
{'language', binary()} |
|
||||
{'max_items', non_neg_integer()} |
|
||||
{'max_payload_size', non_neg_integer()} |
|
||||
{'node_type', 'node_type'()} |
|
||||
{'notification_type', 'notification_type'()} |
|
||||
{'notify_config', boolean()} |
|
||||
{'notify_delete', boolean()} |
|
||||
{'notify_retract', boolean()} |
|
||||
{'notify_sub', boolean()} |
|
||||
{'persist_items', boolean()} |
|
||||
{'presence_based_delivery', boolean()} |
|
||||
{'publish_model', 'publish_model'()} |
|
||||
{'purge_offline', boolean()} |
|
||||
{'roster_groups_allowed', [binary()]} |
|
||||
{'send_last_published_item', 'send_last_published_item'()} |
|
||||
{'tempsub', boolean()} |
|
||||
{'subscribe', boolean()} |
|
||||
{'title', binary()} |
|
||||
{'type', binary()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type options(T) :: [{binary(), T}].
|
||||
-type property_with_options() ::
|
||||
{'access_model', 'access_model'(), options('access_model'())} |
|
||||
{'children_association_policy', 'children_association_policy'(), options('children_association_policy'())} |
|
||||
{'itemreply', 'itemreply'(), options('itemreply'())} |
|
||||
{'language', binary(), options(binary())} |
|
||||
{'node_type', 'node_type'(), options('node_type'())} |
|
||||
{'notification_type', 'notification_type'(), options('notification_type'())} |
|
||||
{'publish_model', 'publish_model'(), options('publish_model'())} |
|
||||
{'roster_groups_allowed', [binary()], options(binary())} |
|
||||
{'send_last_published_item', 'send_last_published_item'(), options('send_last_published_item'())}.
|
||||
-type form() :: [property() | property_with_options() | xdata_field()].
|
@ -1,14 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_publish_options.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#publish-options
|
||||
%% Document: XEP-0060
|
||||
|
||||
-type 'access_model'() :: authorize | open | presence | roster | whitelist.
|
||||
|
||||
-type property() :: {'access_model', 'access_model'()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type options(T) :: [{binary(), T}].
|
||||
-type property_with_options() ::
|
||||
{'access_model', 'access_model'(), options('access_model'())}.
|
||||
-type form() :: [property() | property_with_options() | xdata_field()].
|
@ -1,13 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_subscribe_authorization.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#subscribe_authorization
|
||||
%% Document: XEP-0060
|
||||
|
||||
|
||||
-type property() :: {'allow', boolean()} |
|
||||
{'node', binary()} |
|
||||
{'subscriber_jid', jid:jid()} |
|
||||
{'subid', binary()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type form() :: [property() | xdata_field()].
|
@ -1,25 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_subscribe_options.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#subscribe_options
|
||||
%% Document: XEP-0060
|
||||
|
||||
-type 'show-values'() :: away | chat | dnd | online | xa.
|
||||
-type 'subscription_type'() :: items | nodes.
|
||||
-type 'subscription_depth'() :: 1 | all.
|
||||
|
||||
-type property() :: {'deliver', boolean()} |
|
||||
{'digest', boolean()} |
|
||||
{'digest_frequency', binary()} |
|
||||
{'expire', binary()} |
|
||||
{'include_body', boolean()} |
|
||||
{'show-values', ['show-values'()]} |
|
||||
{'subscription_type', 'subscription_type'()} |
|
||||
{'subscription_depth', 'subscription_depth'()}.
|
||||
-type result() :: [property()].
|
||||
|
||||
-type options(T) :: [{binary(), T}].
|
||||
-type property_with_options() ::
|
||||
{'show-values', ['show-values'()], options('show-values'())} |
|
||||
{'subscription_type', 'subscription_type'(), options('subscription_type'())} |
|
||||
{'subscription_depth', 'subscription_depth'(), options('subscription_depth'())}.
|
||||
-type form() :: [property() | property_with_options() | xdata_field()].
|
@ -1,25 +0,0 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @copyright (C) 2015, Evgeny Khramtsov
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 10 Dec 2015 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%-------------------------------------------------------------------
|
||||
-include("ns.hrl").
|
||||
-include("jid.hrl").
|
||||
-include("xmpp_codec.hrl").
|
||||
-include("fxml.hrl").
|
||||
|
||||
-type iq_type() :: get | set | result | error.
|
||||
-type message_type() :: chat | error | groupchat | headline | normal.
|
||||
-type presence_type() :: available | error | probe | subscribe |
|
||||
subscribed | unavailable | unsubscribe |
|
||||
unsubscribed.
|
||||
|
||||
-type stanza() :: iq() | presence() | message().
|
||||
|
||||
-define(is_stanza(Pkt),
|
||||
(is_record(Pkt, iq) or
|
||||
is_record(Pkt, message) or
|
||||
is_record(Pkt, presence))).
|
File diff suppressed because it is too large
Load Diff
12
rebar.config
12
rebar.config
@ -13,6 +13,7 @@
|
||||
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.7"}}},
|
||||
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.6"}}},
|
||||
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.16"}}},
|
||||
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.0.2"}}},
|
||||
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.7"}}},
|
||||
{esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.8"}}},
|
||||
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.6"}}},
|
||||
@ -55,6 +56,7 @@
|
||||
luerl,
|
||||
stun,
|
||||
fast_yaml,
|
||||
xmpp,
|
||||
p1_utils,
|
||||
p1_mysql,
|
||||
p1_pgsql,
|
||||
@ -65,7 +67,9 @@
|
||||
{erl_first_files, ["src/ejabberd_config.erl", "src/gen_mod.erl"]}.
|
||||
|
||||
{erl_opts, [nowarn_deprecated_function,
|
||||
{i, "include"}, {i, "deps/fast_xml/include"},
|
||||
{i, "include"},
|
||||
{i, "deps/fast_xml/include"},
|
||||
{i, "deps/xmpp/include"},
|
||||
{if_var_false, debug, no_debug_info},
|
||||
{if_var_true, debug, debug_info},
|
||||
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}},
|
||||
@ -113,8 +117,10 @@
|
||||
{if_var_false, elixir, "(\"Elixir.*\":_/_)"},
|
||||
{if_var_false, redis, "(\"eredis\":_/_)"}]}.
|
||||
|
||||
{eunit_compile_opts, [{i, "tools"}, {i, "include"},
|
||||
{i, "deps/fast_xml/include"}]}.
|
||||
{eunit_compile_opts, [{i, "tools"},
|
||||
{i, "include"},
|
||||
{i, "deps/fast_xml/include"},
|
||||
{i, "deps/xmpp/include"}]}.
|
||||
|
||||
{if_version_above, "17", {cover_enabled, true}}.
|
||||
{cover_export_enabled, true}.
|
||||
|
@ -1 +0,0 @@
|
||||
[{decode, [{<<"number_of_messages">>, {dec_int, [0, infinity]}}]}].
|
@ -1,12 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/offline</name>
|
||||
<doc>XEP-0013</doc>
|
||||
<desc>
|
||||
Service Discovery extension for number of messages
|
||||
in an offline message queue.
|
||||
</desc>
|
||||
<field
|
||||
var='number_of_messages'
|
||||
type='text-single'
|
||||
label='Number of Offline Messages'/>
|
||||
</form_type>
|
@ -1,9 +0,0 @@
|
||||
[{decode, [{<<"start">>, {xmpp_util, decode_timestamp, []}},
|
||||
{<<"end">>, {xmpp_util, decode_timestamp, []}}]},
|
||||
{specs, [{<<"start">>, "erlang:timestamp()"},
|
||||
{<<"end">>, "erlang:timestamp()"}]}].
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
%% End:
|
||||
%% vim: set filetype=erlang tabstop=8:
|
@ -1,23 +0,0 @@
|
||||
<form_type>
|
||||
<name>urn:xmpp:mam:1</name>
|
||||
<doc>XEP-0313</doc>
|
||||
<desc>Form to query message archives</desc>
|
||||
<field var='with'
|
||||
type='jid-single'
|
||||
label='User JID'/>
|
||||
<field var='start'
|
||||
type='text-single'
|
||||
label='Search from the date'/>
|
||||
<field var='end'
|
||||
type='text-single'
|
||||
label='Search until the date'/>
|
||||
<field var='withtext'
|
||||
type='text-single'
|
||||
label='Search the text'/>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1,2 +0,0 @@
|
||||
[{prefix, <<"muc#register_">>},
|
||||
{required, [<<"muc#register_roomnick">>]}].
|
@ -1,37 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/muc#register</name>
|
||||
<doc>XEP-0045</doc>
|
||||
<desc>
|
||||
Forms enabling user registration with a
|
||||
Multi-User Chat (MUC) room or admin approval
|
||||
of user registration requests.
|
||||
</desc>
|
||||
<field
|
||||
var='muc#register_allow'
|
||||
type='boolean'
|
||||
label='Allow this person to register with the room?'/>
|
||||
<field
|
||||
var='muc#register_email'
|
||||
type='text-single'
|
||||
label='Email Address'/>
|
||||
<field
|
||||
var='muc#register_faqentry'
|
||||
type='text-multi'
|
||||
label='FAQ Entry'/>
|
||||
<field
|
||||
var='muc#register_first'
|
||||
type='text-single'
|
||||
label='Given Name'/>
|
||||
<field
|
||||
var='muc#register_last'
|
||||
type='text-single'
|
||||
label='Family Name'/>
|
||||
<field
|
||||
var='muc#register_roomnick'
|
||||
type='text-single'
|
||||
label='Nickname'/>
|
||||
<field
|
||||
var='muc#register_url'
|
||||
type='text-single'
|
||||
label='A Web Page'/>
|
||||
</form_type>
|
@ -1,2 +0,0 @@
|
||||
[{prefix, <<"muc#">>},
|
||||
{required, [<<"muc#role">>]}].
|
@ -1,31 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/muc#request</name>
|
||||
<doc>XEP-0045</doc>
|
||||
<desc>
|
||||
Forms enabling voice requests in a
|
||||
Multi-User Chat (MUC) room or admin
|
||||
approval of such requests.
|
||||
</desc>
|
||||
<field var='muc#role'
|
||||
type='list-single'
|
||||
label='Requested role'>
|
||||
<option label='Participant'>
|
||||
<value>participant</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='muc#jid'
|
||||
type='jid-single'
|
||||
label='User JID'/>
|
||||
<field var='muc#roomnick'
|
||||
type='text-single'
|
||||
label='Nickname'/>
|
||||
<field var='muc#request_allow'
|
||||
type='boolean'
|
||||
label='Grant voice to this person?'/>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1,11 +0,0 @@
|
||||
[{prefix, <<"muc#roomconfig_">>},
|
||||
{prefix, <<"muc#">>},
|
||||
{decode, [{<<"muc#roomconfig_maxusers">>,
|
||||
{dec_enum_int, [[none], 0, infinity]}},
|
||||
{<<"voice_request_min_interval">>,
|
||||
{dec_int, [0, infinity]}}]}].
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
%% End:
|
||||
%% vim: set filetype=erlang tabstop=8:
|
@ -1,192 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/muc#roomconfig</name>
|
||||
<doc>XEP-0045</doc>
|
||||
<desc>
|
||||
Forms enabling creation and configuration of
|
||||
a Multi-User Chat (MUC) room.
|
||||
</desc>
|
||||
<field
|
||||
var='muc#maxhistoryfetch'
|
||||
type='text-single'
|
||||
label='Maximum Number of History Messages Returned by Room'/>
|
||||
<field
|
||||
var='muc#roomconfig_allowpm'
|
||||
type='list-single'
|
||||
label='Roles that May Send Private Messages'/>
|
||||
<field
|
||||
var='allow_private_messages'
|
||||
type='boolean'
|
||||
label='Allow users to send private messages'/>
|
||||
<field
|
||||
var='allow_private_messages_from_visitors'
|
||||
type='list-single'
|
||||
label='Allow visitors to send private messages to'>
|
||||
<option label='nobody'>
|
||||
<value>nobody</value>
|
||||
</option>
|
||||
<option label='moderators only'>
|
||||
<value>moderators</value>
|
||||
</option>
|
||||
<option label='anyone'>
|
||||
<value>anyone</value>
|
||||
</option>
|
||||
</field>
|
||||
<field
|
||||
var='allow_visitor_status'
|
||||
type='boolean'
|
||||
label='Allow visitors to send status text in presence updates'/>
|
||||
<field
|
||||
var='allow_visitor_nickchange'
|
||||
type='boolean'
|
||||
label='Allow visitors to change nickname'/>
|
||||
<field
|
||||
var='allow_voice_requests'
|
||||
type='boolean'
|
||||
label='Allow visitors to send voice requests'/>
|
||||
<field
|
||||
var='allow_subscription'
|
||||
type='boolean'
|
||||
label='Allow subscription'/>
|
||||
<field
|
||||
var='voice_request_min_interval'
|
||||
type='text-single'
|
||||
label='Minimum interval between voice requests (in seconds)'/>
|
||||
<field
|
||||
var='captcha_protected'
|
||||
type='boolean'
|
||||
label='Make room CAPTCHA protected'/>
|
||||
<field
|
||||
var='captcha_whitelist'
|
||||
type='jid-multi'
|
||||
label='Exclude Jabber IDs from CAPTCHA challenge'/>
|
||||
<field
|
||||
var='allow_query_users'
|
||||
type='boolean'
|
||||
label='Allow users to query other users'/>
|
||||
<field
|
||||
var='muc#roomconfig_allowinvites'
|
||||
type='boolean'
|
||||
label='Allow users to send invites'/>
|
||||
<field
|
||||
var='muc#roomconfig_changesubject'
|
||||
type='boolean'
|
||||
label='Allow users to change the subject'/>
|
||||
<field
|
||||
var='muc#roomconfig_enablelogging'
|
||||
type='boolean'
|
||||
label='Enable logging'/>
|
||||
<field
|
||||
var='muc#roomconfig_getmemberlist'
|
||||
type='list-multi'
|
||||
label='Roles and Affiliations that May Retrieve Member List'/>
|
||||
<field
|
||||
var='muc#roomconfig_lang'
|
||||
type='text-single'
|
||||
label='Natural Language for Room Discussions'/>
|
||||
<field
|
||||
var='muc#roomconfig_pubsub'
|
||||
type='text-single'
|
||||
label='XMPP URI of Associated Publish-Subscribe Node'/>
|
||||
<field
|
||||
var='muc#roomconfig_maxusers'
|
||||
type='list-single'
|
||||
label='Maximum Number of Occupants'>
|
||||
<option label='No limit'>
|
||||
<value>none</value>
|
||||
</option>
|
||||
<option><value>5</value></option>
|
||||
<option><value>10</value></option>
|
||||
<option><value>20</value></option>
|
||||
<option><value>30</value></option>
|
||||
<option><value>50</value></option>
|
||||
<option><value>100</value></option>
|
||||
<option><value>200</value></option>
|
||||
<option><value>500</value></option>
|
||||
<option><value>1000</value></option>
|
||||
<option><value>2000</value></option>
|
||||
<option><value>5000</value></option>
|
||||
</field>
|
||||
<field
|
||||
var='muc#roomconfig_membersonly'
|
||||
type='boolean'
|
||||
label='Make room members-only'/>
|
||||
<field
|
||||
var='muc#roomconfig_moderatedroom'
|
||||
type='boolean'
|
||||
label='Make room moderated'/>
|
||||
<field
|
||||
var='members_by_default'
|
||||
type='boolean'
|
||||
label='Default users as participants'/>
|
||||
<field
|
||||
var='muc#roomconfig_passwordprotectedroom'
|
||||
type='boolean'
|
||||
label='Make room password protected'/>
|
||||
<field
|
||||
var='muc#roomconfig_persistentroom'
|
||||
type='boolean'
|
||||
label='Make room persistent'/>
|
||||
<field
|
||||
var='muc#roomconfig_presencebroadcast'
|
||||
type='list-multi'
|
||||
label='Roles for which Presence is Broadcasted'>
|
||||
<option label='Moderator'>
|
||||
<value>moderator</value>
|
||||
</option>
|
||||
<option label='Participant'>
|
||||
<value>participant</value>
|
||||
</option>
|
||||
<option label='Visitor'>
|
||||
<value>visitor</value>
|
||||
</option>
|
||||
</field>
|
||||
<field
|
||||
var='muc#roomconfig_publicroom'
|
||||
type='boolean'
|
||||
label='Make room public searchable'/>
|
||||
<field
|
||||
var='public_list'
|
||||
type='boolean'
|
||||
label='Make participants list public'/>
|
||||
<field
|
||||
var='muc#roomconfig_roomadmins'
|
||||
type='jid-multi'
|
||||
label='Full List of Room Admins'/>
|
||||
<field
|
||||
var='muc#roomconfig_roomdesc'
|
||||
type='text-single'
|
||||
label='Room description'/>
|
||||
<field
|
||||
var='muc#roomconfig_roomname'
|
||||
type='text-single'
|
||||
label='Room title'/>
|
||||
<field
|
||||
var='muc#roomconfig_roomowners'
|
||||
type='jid-multi'
|
||||
label='Full List of Room Owners'/>
|
||||
<field
|
||||
var='muc#roomconfig_roomsecret'
|
||||
type='text-private'
|
||||
label='Password'/>
|
||||
<field
|
||||
var='muc#roomconfig_whois'
|
||||
type='list-single'
|
||||
label='Present real Jabber IDs to'>
|
||||
<option label='moderators only'>
|
||||
<value>moderators</value>
|
||||
</option>
|
||||
<option label='anyone'>
|
||||
<value>anyone</value>
|
||||
</option>
|
||||
</field>
|
||||
<field
|
||||
var='mam'
|
||||
type='boolean'
|
||||
label='Enable message archiving'/>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1,11 +0,0 @@
|
||||
[{prefix, <<"muc#roominfo_">>},
|
||||
{prefix, <<"muc#">>},
|
||||
{decode, [{<<"muc#maxhistoryfetch">>,
|
||||
{dec_int, [0, infinity]}},
|
||||
{<<"muc#roominfo_occupants">>,
|
||||
{dec_int, [0, infinity]}}]}].
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
%% End:
|
||||
%% vim: set filetype=erlang tabstop=8:
|
@ -1,55 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/muc#roominfo</name>
|
||||
<doc>XEP-0045</doc>
|
||||
<desc>
|
||||
Forms enabling the communication of extended service discovery
|
||||
information about a Multi-User Chat (MUC) room.
|
||||
</desc>
|
||||
<field
|
||||
var='muc#maxhistoryfetch'
|
||||
type='text-single'
|
||||
label='Maximum Number of History Messages Returned by Room'/>
|
||||
<field
|
||||
var='muc#roominfo_contactjid'
|
||||
type='jid-multi'
|
||||
label='Contact Addresses (normally, room owner or owners)'/>
|
||||
<field
|
||||
var='muc#roominfo_description'
|
||||
type='text-single'
|
||||
label='Room description'/>
|
||||
<field
|
||||
var='muc#roominfo_lang'
|
||||
type='text-single'
|
||||
label='Natural Language for Room Discussions'/>
|
||||
<field
|
||||
var='muc#roominfo_ldapgroup'
|
||||
type='text-single'
|
||||
label='An associated LDAP group that defines
|
||||
room membership; this should be an LDAP
|
||||
Distinguished Name according to an
|
||||
implementation-specific or
|
||||
deployment-specific definition of a
|
||||
group.'/>
|
||||
<field
|
||||
var='muc#roominfo_logs'
|
||||
type='text-single'
|
||||
label='URL for Archived Discussion Logs'/>
|
||||
<field
|
||||
var='muc#roominfo_occupants'
|
||||
type='text-single'
|
||||
label='Number of occupants'/>
|
||||
<field
|
||||
var='muc#roominfo_subject'
|
||||
type='text-single'
|
||||
label='Current Discussion Topic'/>
|
||||
<field
|
||||
var='muc#roominfo_subjectmod'
|
||||
type='boolean'
|
||||
label='The room subject can be modified by participants'/>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1,7 +0,0 @@
|
||||
[{prefix, <<"pubsub#">>},
|
||||
{required, [<<"pubsub#node">>]}].
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
%% End:
|
||||
%% vim: set filetype=erlang tabstop=8:
|
@ -1,15 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/pubsub#subscribe_authorization</name>
|
||||
<doc>XEP-0060</doc>
|
||||
<desc>Forms enabling authorization of subscriptions to pubsub nodes</desc>
|
||||
<field
|
||||
var='pubsub#node'
|
||||
type='list-single'
|
||||
label='The NodeID of the relevant node'/>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1,8 +0,0 @@
|
||||
[{prefix, <<"pubsub#">>},
|
||||
{decode, [{<<"pubsub#max_items">>, {dec_int, [0,infinity]}},
|
||||
{<<"pubsub#max_payload_size">>, {dec_int, [0,infinity]}}]}].
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
%% End:
|
||||
%% vim: set filetype=erlang tabstop=8:
|
@ -1,189 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/pubsub#node_config</name>
|
||||
<doc>XEP-0060</doc>
|
||||
<desc>Forms enabling configuration of pubsub nodes</desc>
|
||||
<field var='pubsub#access_model'
|
||||
type='list-single'
|
||||
label='Specify the access model'>
|
||||
<option label='Subscription requests must be approved and only subscribers may retrieve items'>
|
||||
<value>authorize</value>
|
||||
</option>
|
||||
<option label='Anyone may subscribe and retrieve items'>
|
||||
<value>open</value>
|
||||
</option>
|
||||
<option label='Anyone with a presence subscription of both or from may subscribe and retrieve items'>
|
||||
<value>presence</value>
|
||||
</option>
|
||||
<option label='Anyone in the specified roster group(s) may subscribe and retrieve items'>
|
||||
<value>roster</value>
|
||||
</option>
|
||||
<option label='Only those on a whitelist may subscribe and retrieve items'>
|
||||
<value>whitelist</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#body_xslt'
|
||||
type='text-single'
|
||||
label='The URL of an XSL transformation which can be
|
||||
applied to payloads in order to generate an
|
||||
appropriate message body element.'/>
|
||||
<field var='pubsub#children_association_policy'
|
||||
type='list-single'
|
||||
label='Who may associate leaf nodes with a collection'>
|
||||
<option label='Anyone may associate leaf nodes with the collection'>
|
||||
<value>all</value>
|
||||
</option>
|
||||
<option label='Only collection node owners may associate leaf nodes with the collection'>
|
||||
<value>owners</value>
|
||||
</option>
|
||||
<option label='Only those on a whitelist may associate leaf nodes with the collection'>
|
||||
<value>whitelist</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#children_association_whitelist'
|
||||
type='jid-multi'
|
||||
label='The list of JIDs that may associate leaf nodes with a collection'/>
|
||||
<field var='pubsub#children'
|
||||
type='text-multi'
|
||||
label='The child nodes (leaf or collection) associated with a collection'/>
|
||||
<field var='pubsub#children_max'
|
||||
type='text-single'
|
||||
label='The maximum number of child nodes that can be associated with a collection'/>
|
||||
<field var='pubsub#collection'
|
||||
type='text-multi'
|
||||
label='The collections with which a node is affiliated'/>
|
||||
<field var='pubsub#contact'
|
||||
type='jid-multi'
|
||||
label='The JIDs of those to contact with questions'/>
|
||||
<field var='pubsub#dataform_xslt'
|
||||
type='text-single'
|
||||
label='The URL of an XSL transformation which can be
|
||||
applied to the payload format in order to generate
|
||||
a valid Data Forms result that the client could
|
||||
display using a generic Data Forms rendering
|
||||
engine'/>
|
||||
<field var='pubsub#deliver_notifications' type='boolean'
|
||||
label='Deliver event notifications'>
|
||||
<value>true</value>
|
||||
</field>
|
||||
<field var='pubsub#deliver_payloads'
|
||||
type='boolean'
|
||||
label='Deliver payloads with event notifications'/>
|
||||
<field var='pubsub#description'
|
||||
type='text-single'
|
||||
label='A description of the node'/>
|
||||
<field var='pubsub#item_expire'
|
||||
type='text-single'
|
||||
label='Number of seconds after which to automatically purge items'/>
|
||||
<field var='pubsub#itemreply'
|
||||
type='list-single'
|
||||
label='Whether owners or publisher should receive replies to items'>
|
||||
<option label='Statically specify a replyto of the node owner(s)'>
|
||||
<value>owner</value>
|
||||
</option>
|
||||
<option label='Dynamically specify a replyto of the item publisher'>
|
||||
<value>publisher</value>
|
||||
</option>
|
||||
<option>
|
||||
<value>none</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#language'
|
||||
type='list-single'
|
||||
label='The default language of the node'/>
|
||||
<field var='pubsub#max_items'
|
||||
type='text-single'
|
||||
label='Max # of items to persist'>
|
||||
</field>
|
||||
<field var='pubsub#max_payload_size'
|
||||
type='text-single'
|
||||
label='Max payload size in bytes'/>
|
||||
<field var='pubsub#node_type'
|
||||
type='list-single'
|
||||
label='Whether the node is a leaf (default) or a collection'>
|
||||
<option label='The node is a leaf node (default)'>
|
||||
<value>leaf</value>
|
||||
</option>
|
||||
<option label='The node is a collection node'>
|
||||
<value>collection</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#notification_type' type='list-single'
|
||||
label='Specify the event message type'>
|
||||
<option label='Messages of type normal'>
|
||||
<value>normal</value>
|
||||
</option>
|
||||
<option label='Messages of type headline'>
|
||||
<value>headline</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#notify_config'
|
||||
type='boolean'
|
||||
label='Notify subscribers when the node configuration changes'/>
|
||||
<field var='pubsub#notify_delete'
|
||||
type='boolean'
|
||||
label='Notify subscribers when the node is deleted'/>
|
||||
<field var='pubsub#notify_retract'
|
||||
type='boolean'
|
||||
label='Notify subscribers when items are removed from the node'/>
|
||||
<field var='pubsub#notify_sub'
|
||||
type='boolean'
|
||||
label='Whether to notify owners about new subscribers and unsubscribes'/>
|
||||
<field var='pubsub#persist_items'
|
||||
type='boolean'
|
||||
label='Persist items to storage'/>
|
||||
<field var='pubsub#presence_based_delivery'
|
||||
type='boolean'
|
||||
label='Only deliver notifications to available users'/>
|
||||
<field var='pubsub#publish_model'
|
||||
type='list-single'
|
||||
label='Specify the publisher model'>
|
||||
<option label='Only publishers may publish'>
|
||||
<value>publishers</value>
|
||||
</option>
|
||||
<option label='Subscribers may publish'>
|
||||
<value>subscribers</value>
|
||||
</option>
|
||||
<option label='Anyone may publish'>
|
||||
<value>open</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#purge_offline'
|
||||
type='boolean'
|
||||
label='Purge all items when the relevant publisher goes offline'/>
|
||||
<field var='pubsub#roster_groups_allowed'
|
||||
type='list-multi'
|
||||
label='Roster groups allowed to subscribe'/>
|
||||
<field var='pubsub#send_last_published_item'
|
||||
type='list-single'
|
||||
label='When to send the last published item'>
|
||||
<option label='Never'>
|
||||
<value>never</value>
|
||||
</option>
|
||||
<option label='When a new subscription is processed'>
|
||||
<value>on_sub</value>
|
||||
</option>
|
||||
<option label='When a new subscription is processed and whenever a subscriber comes online'>
|
||||
<value>on_sub_and_presence</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#tempsub'
|
||||
type='boolean'
|
||||
label='Whether to make all subscriptions temporary, based on subscriber presence'/>
|
||||
<field var='pubsub#subscribe' type='boolean'
|
||||
label='Whether to allow subscriptions'>
|
||||
<value>1</value>
|
||||
</field>
|
||||
<field var='pubsub#title'
|
||||
type='text-single'
|
||||
label='A friendly name for the node'/>
|
||||
<field var='pubsub#type'
|
||||
type='text-single'
|
||||
label='The type of node data, usually specified by
|
||||
the namespace of the payload (if any)'/>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1,6 +0,0 @@
|
||||
[{prefix, <<"pubsub#">>}].
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
%% End:
|
||||
%% vim: set filetype=erlang tabstop=8:
|
@ -1,34 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/pubsub#publish-options</name>
|
||||
<doc>XEP-0060</doc>
|
||||
<desc>
|
||||
Forms enabling publication with options; each field must specify whether it
|
||||
defines METADATA to be attached to the item, a per-item OVERRIDE of the node
|
||||
configuration, or a PRECONDITION to be checked against the node configuration.
|
||||
</desc>
|
||||
<field var='pubsub#access_model'
|
||||
type='list-single'
|
||||
label='Specify the access model'>
|
||||
<option label='Access model of authorize'>
|
||||
<value>authorize</value>
|
||||
</option>
|
||||
<option label='Access model of open'>
|
||||
<value>open</value>
|
||||
</option>
|
||||
<option label='Access model of presence'>
|
||||
<value>presence</value>
|
||||
</option>
|
||||
<option label='Access model of roster'>
|
||||
<value>roster</value>
|
||||
</option>
|
||||
<option label='Access model of whitelist'>
|
||||
<value>whitelist</value>
|
||||
</option>
|
||||
</field>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1,7 +0,0 @@
|
||||
[{prefix, <<"pubsub#">>},
|
||||
{required, [<<"pubsub#node">>, <<"pubsub#subscriber_jid">>, <<"pubsub#allow">>]}].
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
%% End:
|
||||
%% vim: set filetype=erlang tabstop=8:
|
@ -1,27 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/pubsub#subscribe_authorization</name>
|
||||
<doc>XEP-0060</doc>
|
||||
<desc>Forms enabling authorization of subscriptions to pubsub nodes</desc>
|
||||
<field
|
||||
var='pubsub#allow'
|
||||
type='boolean'
|
||||
label='Allow this Jabber ID to subscribe to this pubsub node?'/>
|
||||
<field
|
||||
var='pubsub#node'
|
||||
type='text-single'
|
||||
label='Node ID'/>
|
||||
<field
|
||||
var='pubsub#subscriber_jid'
|
||||
type='jid-single'
|
||||
label='Subscriber Address'/>
|
||||
<field
|
||||
var='pubsub#subid'
|
||||
type='text-single'
|
||||
label='The subscription identifier associated with the subscription request'/>
|
||||
</form_type>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
End:
|
||||
-->
|
@ -1 +0,0 @@
|
||||
[{prefix, <<"pubsub#">>}].
|
@ -1,70 +0,0 @@
|
||||
<form_type>
|
||||
<name>http://jabber.org/protocol/pubsub#subscribe_options</name>
|
||||
<doc>XEP-0060</doc>
|
||||
<desc>Forms enabling configuration of subscription options for pubsub nodes</desc>
|
||||
<field
|
||||
var='pubsub#deliver'
|
||||
type='boolean'
|
||||
label='Whether an entity wants to receive
|
||||
or disable notifications'/>
|
||||
<field
|
||||
var='pubsub#digest'
|
||||
type='boolean'
|
||||
label='Whether an entity wants to receive digests
|
||||
(aggregations) of notifications or all
|
||||
notifications individually'/>
|
||||
<field var='pubsub#digest_frequency'
|
||||
type='text-single'
|
||||
label='The minimum number of milliseconds between
|
||||
sending any two notification digests'/>
|
||||
<field
|
||||
var='pubsub#expire'
|
||||
type='text-single'
|
||||
label='The DateTime at which a leased subscription
|
||||
will end or has ended'/>
|
||||
<field
|
||||
var='pubsub#include_body'
|
||||
type='boolean'
|
||||
label='Whether an entity wants to receive an XMPP
|
||||
message body in addition to the payload
|
||||
format'/>
|
||||
<field
|
||||
var='pubsub#show-values'
|
||||
type='list-multi'
|
||||
label='The presence states for which an entity
|
||||
wants to receive notifications'>
|
||||
<option label='XMPP Show Value of Away'>
|
||||
<value>away</value>
|
||||
</option>
|
||||
<option label='XMPP Show Value of Chat'>
|
||||
<value>chat</value>
|
||||
</option>
|
||||
<option label='XMPP Show Value of DND (Do Not Disturb)'>
|
||||
<value>dnd</value>
|
||||
</option>
|
||||
<option label='Mere Availability in XMPP (No Show Value)'>
|
||||
<value>online</value>
|
||||
</option>
|
||||
<option label='XMPP Show Value of XA (Extended Away)'>
|
||||
<value>xa</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#subscription_type'
|
||||
type='list-single'>
|
||||
<option label='Receive notification of new items only'>
|
||||
<value>items</value>
|
||||
</option>
|
||||
<option label='Receive notification of new nodes only'>
|
||||
<value>nodes</value>
|
||||
</option>
|
||||
</field>
|
||||
<field var='pubsub#subscription_depth'
|
||||
type='list-single'>
|
||||
<option label='Receive notification from direct child nodes only'>
|
||||
<value>1</value>
|
||||
</option>
|
||||
<option label='Receive notification from all descendent nodes'>
|
||||
<value>all</value>
|
||||
</option>
|
||||
</field>
|
||||
</form_type>
|
File diff suppressed because it is too large
Load Diff
@ -1,128 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: flex_offline.xdata
|
||||
%% Form type: http://jabber.org/protocol/offline
|
||||
%% Document: XEP-0013
|
||||
|
||||
-module(flex_offline).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("flex_offline.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
dec_int(Val, Min, Max) ->
|
||||
case list_to_integer(binary_to_list(Val)) of
|
||||
Int when Int =< Max, Min == infinity -> Int;
|
||||
Int when Int =< Max, Int >= Min -> Int
|
||||
end.
|
||||
|
||||
enc_int(Int) -> integer_to_binary(Int).
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, []);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/offline">>]} ->
|
||||
decode(Fs, Acc, []);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/offline">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{number_of_messages, Val} ->
|
||||
[encode_number_of_messages(Val, Translate)];
|
||||
{number_of_messages, _, _} ->
|
||||
erlang:error({badarg, Opt});
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/offline">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"number_of_messages">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_int(Value, 0, infinity) of
|
||||
Result ->
|
||||
decode(Fs, [{number_of_messages, Result} | Acc],
|
||||
lists:delete(<<"number_of_messages">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"number_of_messages">>,
|
||||
<<"http://jabber.org/protocol/offline">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"number_of_messages">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"number_of_messages">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"number_of_messages">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"number_of_messages">>,
|
||||
<<"http://jabber.org/protocol/offline">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/offline">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/offline">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_number_of_messages(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_int(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"number_of_messages">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Number of Offline Messages">>)}.
|
266
src/jid.erl
266
src/jid.erl
@ -1,266 +0,0 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @doc
|
||||
%%% JID processing library
|
||||
%%% @end
|
||||
%%% Created : 24 Nov 2015 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2016 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
%%% published by the Free Software Foundation; either version 2 of the
|
||||
%%% License, or (at your option) any later version.
|
||||
%%%
|
||||
%%% This program is distributed in the hope that it will be useful,
|
||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
%%% General Public License for more details.
|
||||
%%%
|
||||
%%% You should have received a copy of the GNU General Public License along
|
||||
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(jid).
|
||||
|
||||
%% API
|
||||
-export([start/0,
|
||||
make/1,
|
||||
make/2,
|
||||
make/3,
|
||||
split/1,
|
||||
from_string/1,
|
||||
to_string/1,
|
||||
is_nodename/1,
|
||||
nodeprep/1,
|
||||
nameprep/1,
|
||||
resourceprep/1,
|
||||
tolower/1,
|
||||
remove_resource/1,
|
||||
replace_resource/2]).
|
||||
|
||||
-include("jid.hrl").
|
||||
|
||||
-export_type([jid/0]).
|
||||
-export_type([ljid/0]).
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
-spec start() -> ok.
|
||||
|
||||
start() ->
|
||||
{ok, Owner} = ets_owner(),
|
||||
SplitPattern = binary:compile_pattern([<<"@">>, <<"/">>]),
|
||||
%% Table is public to allow ETS insert to fix / update the table even if table already exist
|
||||
%% with another owner.
|
||||
catch ets:new(jlib, [named_table, public, set, {keypos, 1}, {heir, Owner, undefined}]),
|
||||
ets:insert(jlib, {string_to_jid_pattern, SplitPattern}),
|
||||
ok.
|
||||
|
||||
ets_owner() ->
|
||||
case whereis(jlib_ets) of
|
||||
undefined ->
|
||||
Pid = spawn(fun() -> ets_keepalive() end),
|
||||
case catch register(jlib_ets, Pid) of
|
||||
true ->
|
||||
{ok, Pid};
|
||||
Error -> Error
|
||||
end;
|
||||
Pid ->
|
||||
{ok,Pid}
|
||||
end.
|
||||
|
||||
%% Process used to keep jlib ETS table alive in case the original owner dies.
|
||||
%% The table need to be public, otherwise subsequent inserts would fail.
|
||||
ets_keepalive() ->
|
||||
receive
|
||||
_ ->
|
||||
ets_keepalive()
|
||||
end.
|
||||
|
||||
-spec make(binary(), binary(), binary()) -> jid() | error.
|
||||
|
||||
make(User, Server, Resource) ->
|
||||
case nodeprep(User) of
|
||||
error -> error;
|
||||
LUser ->
|
||||
case nameprep(Server) of
|
||||
error -> error;
|
||||
LServer ->
|
||||
case resourceprep(Resource) of
|
||||
error -> error;
|
||||
LResource ->
|
||||
#jid{user = User, server = Server, resource = Resource,
|
||||
luser = LUser, lserver = LServer,
|
||||
lresource = LResource}
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
-spec make(binary(), binary()) -> jid() | error.
|
||||
make(User, Server) ->
|
||||
make(User, Server, <<"">>).
|
||||
|
||||
-spec make({binary(), binary(), binary()} | binary()) -> jid() | error.
|
||||
|
||||
make({User, Server, Resource}) ->
|
||||
make(User, Server, Resource);
|
||||
make(Server) ->
|
||||
make(<<"">>, Server, <<"">>).
|
||||
|
||||
%% This is the reverse of make_jid/1
|
||||
-spec split(jid()) -> {binary(), binary(), binary()} | error.
|
||||
|
||||
split(#jid{user = U, server = S, resource = R}) ->
|
||||
{U, S, R};
|
||||
split(_) ->
|
||||
error.
|
||||
|
||||
-spec from_string(binary() | string()) -> jid() | error.
|
||||
from_string(S) when is_list(S) ->
|
||||
%% We do not accept list because we want to enforce good practice of
|
||||
%% using binaries for string. However, we do not let it crash to avoid
|
||||
%% losing associated ets table.
|
||||
{error, need_jid_as_binary};
|
||||
from_string(<<>>) ->
|
||||
error;
|
||||
from_string(S) when is_binary(S) ->
|
||||
SplitPattern = ets:lookup_element(jlib, string_to_jid_pattern, 2),
|
||||
Size = size(S),
|
||||
End = Size-1,
|
||||
case binary:match(S, SplitPattern) of
|
||||
{0, _} ->
|
||||
error;
|
||||
{End, _} ->
|
||||
error;
|
||||
{Pos1, _} ->
|
||||
case binary:at(S, Pos1) of
|
||||
$/ ->
|
||||
make(<<>>,
|
||||
binary:part(S, 0, Pos1),
|
||||
binary:part(S, Pos1+1, Size-Pos1-1));
|
||||
_ ->
|
||||
Pos1N = Pos1+1,
|
||||
case binary:match(S, SplitPattern, [{scope, {Pos1+1, Size-Pos1-1}}]) of
|
||||
{End, _} ->
|
||||
error;
|
||||
{Pos1N, _} ->
|
||||
error;
|
||||
{Pos2, _} ->
|
||||
case binary:at(S, Pos2) of
|
||||
$/ ->
|
||||
make(binary:part(S, 0, Pos1),
|
||||
binary:part(S, Pos1+1, Pos2-Pos1-1),
|
||||
binary:part(S, Pos2+1, Size-Pos2-1));
|
||||
_ -> error
|
||||
end;
|
||||
_ ->
|
||||
make(binary:part(S, 0, Pos1),
|
||||
binary:part(S, Pos1+1, Size-Pos1-1),
|
||||
<<>>)
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
make(<<>>, S, <<>>)
|
||||
end.
|
||||
|
||||
-spec to_string(jid() | ljid()) -> binary().
|
||||
|
||||
to_string(#jid{user = User, server = Server,
|
||||
resource = Resource}) ->
|
||||
to_string({User, Server, Resource});
|
||||
to_string({N, S, R}) ->
|
||||
Node = iolist_to_binary(N),
|
||||
Server = iolist_to_binary(S),
|
||||
Resource = iolist_to_binary(R),
|
||||
S1 = case Node of
|
||||
<<"">> -> <<"">>;
|
||||
_ -> <<Node/binary, "@">>
|
||||
end,
|
||||
S2 = <<S1/binary, Server/binary>>,
|
||||
S3 = case Resource of
|
||||
<<"">> -> S2;
|
||||
_ -> <<S2/binary, "/", Resource/binary>>
|
||||
end,
|
||||
S3.
|
||||
|
||||
-spec is_nodename(binary()) -> boolean().
|
||||
|
||||
is_nodename(Node) ->
|
||||
N = nodeprep(Node),
|
||||
(N /= error) and (N /= <<>>).
|
||||
|
||||
-define(LOWER(Char),
|
||||
if Char >= $A, Char =< $Z -> Char + 32;
|
||||
true -> Char
|
||||
end).
|
||||
|
||||
-spec nodeprep(binary()) -> binary() | error.
|
||||
|
||||
nodeprep("") -> <<>>;
|
||||
nodeprep(S) when byte_size(S) < 1024 ->
|
||||
R = stringprep:nodeprep(S),
|
||||
if byte_size(R) < 1024 -> R;
|
||||
true -> error
|
||||
end;
|
||||
nodeprep(_) -> error.
|
||||
|
||||
-spec nameprep(binary()) -> binary() | error.
|
||||
|
||||
nameprep(S) when byte_size(S) < 1024 ->
|
||||
R = stringprep:nameprep(S),
|
||||
if byte_size(R) < 1024 -> R;
|
||||
true -> error
|
||||
end;
|
||||
nameprep(_) -> error.
|
||||
|
||||
-spec resourceprep(binary()) -> binary() | error.
|
||||
|
||||
resourceprep(S) when byte_size(S) < 1024 ->
|
||||
R = stringprep:resourceprep(S),
|
||||
if byte_size(R) < 1024 -> R;
|
||||
true -> error
|
||||
end;
|
||||
resourceprep(_) -> error.
|
||||
|
||||
-spec tolower(jid() | ljid()) -> error | ljid().
|
||||
|
||||
tolower(#jid{luser = U, lserver = S,
|
||||
lresource = R}) ->
|
||||
{U, S, R};
|
||||
tolower({U, S, R}) ->
|
||||
case nodeprep(U) of
|
||||
error -> error;
|
||||
LUser ->
|
||||
case nameprep(S) of
|
||||
error -> error;
|
||||
LServer ->
|
||||
case resourceprep(R) of
|
||||
error -> error;
|
||||
LResource -> {LUser, LServer, LResource}
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
-spec remove_resource(jid()) -> jid();
|
||||
(ljid()) -> ljid().
|
||||
|
||||
remove_resource(#jid{} = JID) ->
|
||||
JID#jid{resource = <<"">>, lresource = <<"">>};
|
||||
remove_resource({U, S, _R}) -> {U, S, <<"">>}.
|
||||
|
||||
-spec replace_resource(jid(), binary()) -> error | jid().
|
||||
|
||||
replace_resource(JID, Resource) ->
|
||||
case resourceprep(Resource) of
|
||||
error -> error;
|
||||
LResource ->
|
||||
JID#jid{resource = Resource, lresource = LResource}
|
||||
end.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
@ -1,220 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: mam_query.xdata
|
||||
%% Form type: urn:xmpp:mam:1
|
||||
%% Document: XEP-0313
|
||||
|
||||
-module(mam_query).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("mam_query.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
enc_jid(J) -> jid:to_string(J).
|
||||
|
||||
dec_jid(Val) ->
|
||||
case jid:from_string(Val) of
|
||||
error -> erlang:error(badarg);
|
||||
J -> J
|
||||
end.
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, []);
|
||||
#xdata_field{values = [<<"urn:xmpp:mam:1">>]} ->
|
||||
decode(Fs, Acc, []);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch, <<"urn:xmpp:mam:1">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{with, Val} -> [encode_with(Val, Translate)];
|
||||
{with, _, _} -> erlang:error({badarg, Opt});
|
||||
{start, Val} -> [encode_start(Val, Translate)];
|
||||
{start, _, _} -> erlang:error({badarg, Opt});
|
||||
{'end', Val} -> [encode_end(Val, Translate)];
|
||||
{'end', _, _} -> erlang:error({badarg, Opt});
|
||||
{withtext, Val} -> [encode_withtext(Val, Translate)];
|
||||
{withtext, _, _} -> erlang:error({badarg, Opt});
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden, values = [<<"urn:xmpp:mam:1">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"with">>, values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_jid(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{with, Result} | Acc],
|
||||
lists:delete(<<"with">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"with">>, <<"urn:xmpp:mam:1">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"with">>, values = []} = F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"with">>, values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"with">>} | _], _, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"with">>, <<"urn:xmpp:mam:1">>}});
|
||||
decode([#xdata_field{var = <<"start">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try xmpp_util:decode_timestamp(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{start, Result} | Acc],
|
||||
lists:delete(<<"start">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"start">>, <<"urn:xmpp:mam:1">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"start">>, values = []} = F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"start">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"start">>} | _], _, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"start">>, <<"urn:xmpp:mam:1">>}});
|
||||
decode([#xdata_field{var = <<"end">>, values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try xmpp_util:decode_timestamp(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{'end', Result} | Acc],
|
||||
lists:delete(<<"end">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"end">>, <<"urn:xmpp:mam:1">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"end">>, values = []} = F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"end">>, values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"end">>} | _], _, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"end">>, <<"urn:xmpp:mam:1">>}});
|
||||
decode([#xdata_field{var = <<"withtext">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{withtext, Result} | Acc],
|
||||
lists:delete(<<"withtext">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"withtext">>, <<"urn:xmpp:mam:1">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"withtext">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"withtext">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"withtext">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"withtext">>,
|
||||
<<"urn:xmpp:mam:1">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var, <<"urn:xmpp:mam:1">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var, <<"urn:xmpp:mam:1">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_with(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_jid(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"with">>, values = Values,
|
||||
required = false, type = 'jid-single', options = Opts,
|
||||
desc = <<>>, label = Translate(<<"User JID">>)}.
|
||||
|
||||
encode_start(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"start">>, values = Values,
|
||||
required = false, type = 'text-single', options = Opts,
|
||||
desc = <<>>,
|
||||
label = Translate(<<"Search from the date">>)}.
|
||||
|
||||
encode_end(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"end">>, values = Values,
|
||||
required = false, type = 'text-single', options = Opts,
|
||||
desc = <<>>,
|
||||
label = Translate(<<"Search until the date">>)}.
|
||||
|
||||
encode_withtext(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"withtext">>, values = Values,
|
||||
required = false, type = 'text-single', options = Opts,
|
||||
desc = <<>>, label = Translate(<<"Search the text">>)}.
|
@ -1,364 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: muc_register.xdata
|
||||
%% Form type: http://jabber.org/protocol/muc#register
|
||||
%% Document: XEP-0045
|
||||
|
||||
-module(muc_register).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("muc_register.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
dec_bool(<<"1">>) -> true;
|
||||
dec_bool(<<"0">>) -> false;
|
||||
dec_bool(<<"true">>) -> true;
|
||||
dec_bool(<<"false">>) -> false.
|
||||
|
||||
enc_bool(true) -> <<"1">>;
|
||||
enc_bool(false) -> <<"0">>.
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, [<<"muc#register_roomnick">>]);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/muc#register">>]} ->
|
||||
decode(Fs, Acc, [<<"muc#register_roomnick">>]);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{allow, Val} -> [encode_allow(Val, Translate)];
|
||||
{allow, _, _} -> erlang:error({badarg, Opt});
|
||||
{email, Val} -> [encode_email(Val, Translate)];
|
||||
{email, _, _} -> erlang:error({badarg, Opt});
|
||||
{faqentry, Val} -> [encode_faqentry(Val, Translate)];
|
||||
{faqentry, _, _} -> erlang:error({badarg, Opt});
|
||||
{first, Val} -> [encode_first(Val, Translate)];
|
||||
{first, _, _} -> erlang:error({badarg, Opt});
|
||||
{last, Val} -> [encode_last(Val, Translate)];
|
||||
{last, _, _} -> erlang:error({badarg, Opt});
|
||||
{roomnick, Val} -> [encode_roomnick(Val, Translate)];
|
||||
{roomnick, _, _} -> erlang:error({badarg, Opt});
|
||||
{url, Val} -> [encode_url(Val, Translate)];
|
||||
{url, _, _} -> erlang:error({badarg, Opt});
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/muc#register">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"muc#register_allow">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_bool(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{allow, Result} | Acc],
|
||||
lists:delete(<<"muc#register_allow">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#register_allow">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#register_allow">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#register_allow">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#register_allow">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#register_allow">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
decode([#xdata_field{var = <<"muc#register_email">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{email, Result} | Acc],
|
||||
lists:delete(<<"muc#register_email">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#register_email">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#register_email">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#register_email">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#register_email">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#register_email">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
decode([#xdata_field{var = <<"muc#register_faqentry">>,
|
||||
values = Values}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try [Value || Value <- Values] of
|
||||
Result ->
|
||||
decode(Fs, [{faqentry, Result} | Acc],
|
||||
lists:delete(<<"muc#register_faqentry">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#register_faqentry">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#register_first">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{first, Result} | Acc],
|
||||
lists:delete(<<"muc#register_first">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#register_first">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#register_first">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#register_first">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#register_first">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#register_first">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
decode([#xdata_field{var = <<"muc#register_last">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{last, Result} | Acc],
|
||||
lists:delete(<<"muc#register_last">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#register_last">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#register_last">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#register_last">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#register_last">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#register_last">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
decode([#xdata_field{var = <<"muc#register_roomnick">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{roomnick, Result} | Acc],
|
||||
lists:delete(<<"muc#register_roomnick">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#register_roomnick">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#register_roomnick">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#register_roomnick">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#register_roomnick">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#register_roomnick">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
decode([#xdata_field{var = <<"muc#register_url">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{url, Result} | Acc],
|
||||
lists:delete(<<"muc#register_url">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#register_url">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#register_url">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#register_url">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#register_url">>} | _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#register_url">>,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/muc#register">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_allow(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_bool(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#register_allow">>,
|
||||
values = Values, required = false, type = boolean,
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Allow this person to register with the "
|
||||
"room?">>)}.
|
||||
|
||||
encode_email(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#register_email">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Email Address">>)}.
|
||||
|
||||
encode_faqentry(Value, Translate) ->
|
||||
Values = case Value of
|
||||
[] -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#register_faqentry">>,
|
||||
values = Values, required = false, type = 'text-multi',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"FAQ Entry">>)}.
|
||||
|
||||
encode_first(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#register_first">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Given Name">>)}.
|
||||
|
||||
encode_last(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#register_last">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Family Name">>)}.
|
||||
|
||||
encode_roomnick(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#register_roomnick">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Nickname">>)}.
|
||||
|
||||
encode_url(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#register_url">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"A Web Page">>)}.
|
@ -1,269 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: muc_request.xdata
|
||||
%% Form type: http://jabber.org/protocol/muc#request
|
||||
%% Document: XEP-0045
|
||||
|
||||
-module(muc_request).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("muc_request.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
dec_enum(Val, Enums) ->
|
||||
AtomVal = erlang:binary_to_existing_atom(Val, utf8),
|
||||
case lists:member(AtomVal, Enums) of
|
||||
true -> AtomVal
|
||||
end.
|
||||
|
||||
enc_enum(Atom) -> erlang:atom_to_binary(Atom, utf8).
|
||||
|
||||
dec_bool(<<"1">>) -> true;
|
||||
dec_bool(<<"0">>) -> false;
|
||||
dec_bool(<<"true">>) -> true;
|
||||
dec_bool(<<"false">>) -> false.
|
||||
|
||||
enc_bool(true) -> <<"1">>;
|
||||
enc_bool(false) -> <<"0">>.
|
||||
|
||||
enc_jid(J) -> jid:to_string(J).
|
||||
|
||||
dec_jid(Val) ->
|
||||
case jid:from_string(Val) of
|
||||
error -> erlang:error(badarg);
|
||||
J -> J
|
||||
end.
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, [<<"muc#role">>]);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/muc#request">>]} ->
|
||||
decode(Fs, Acc, [<<"muc#role">>]);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/muc#request">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{role, Val} -> [encode_role(Val, default, Translate)];
|
||||
{role, Val, Opts} ->
|
||||
[encode_role(Val, Opts, Translate)];
|
||||
{jid, Val} -> [encode_jid(Val, Translate)];
|
||||
{jid, _, _} -> erlang:error({badarg, Opt});
|
||||
{roomnick, Val} -> [encode_roomnick(Val, Translate)];
|
||||
{roomnick, _, _} -> erlang:error({badarg, Opt});
|
||||
{request_allow, Val} ->
|
||||
[encode_request_allow(Val, Translate)];
|
||||
{request_allow, _, _} -> erlang:error({badarg, Opt});
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/muc#request">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"muc#role">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_enum(Value, [participant]) of
|
||||
Result ->
|
||||
decode(Fs, [{role, Result} | Acc],
|
||||
lists:delete(<<"muc#role">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#role">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#role">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#role">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#role">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#role">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}});
|
||||
decode([#xdata_field{var = <<"muc#jid">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_jid(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{jid, Result} | Acc],
|
||||
lists:delete(<<"muc#jid">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#jid">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#jid">>, values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#jid">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#jid">>} | _], _, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#jid">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}});
|
||||
decode([#xdata_field{var = <<"muc#roomnick">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{roomnick, Result} | Acc],
|
||||
lists:delete(<<"muc#roomnick">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roomnick">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#roomnick">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#roomnick">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#roomnick">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roomnick">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}});
|
||||
decode([#xdata_field{var = <<"muc#request_allow">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_bool(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{request_allow, Result} | Acc],
|
||||
lists:delete(<<"muc#request_allow">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#request_allow">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#request_allow">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#request_allow">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#request_allow">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#request_allow">>,
|
||||
<<"http://jabber.org/protocol/muc#request">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/muc#request">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/muc#request">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_role(Value, Options, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_enum(Value)]
|
||||
end,
|
||||
Opts = if Options == default ->
|
||||
[#xdata_option{label = Translate(<<"Participant">>),
|
||||
value = <<"participant">>}];
|
||||
true ->
|
||||
[#xdata_option{label = Translate(L),
|
||||
value = enc_enum(V)}
|
||||
|| {L, V} <- Options]
|
||||
end,
|
||||
#xdata_field{var = <<"muc#role">>, values = Values,
|
||||
required = false, type = 'list-single', options = Opts,
|
||||
desc = <<>>, label = Translate(<<"Requested role">>)}.
|
||||
|
||||
encode_jid(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_jid(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#jid">>, values = Values,
|
||||
required = false, type = 'jid-single', options = Opts,
|
||||
desc = <<>>, label = Translate(<<"User JID">>)}.
|
||||
|
||||
encode_roomnick(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roomnick">>, values = Values,
|
||||
required = false, type = 'text-single', options = Opts,
|
||||
desc = <<>>, label = Translate(<<"Nickname">>)}.
|
||||
|
||||
encode_request_allow(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_bool(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#request_allow">>,
|
||||
values = Values, required = false, type = boolean,
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Grant voice to this person?">>)}.
|
File diff suppressed because it is too large
Load Diff
@ -1,491 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: muc_roominfo.xdata
|
||||
%% Form type: http://jabber.org/protocol/muc#roominfo
|
||||
%% Document: XEP-0045
|
||||
|
||||
-module(muc_roominfo).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("muc_roominfo.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
dec_int(Val, Min, Max) ->
|
||||
case list_to_integer(binary_to_list(Val)) of
|
||||
Int when Int =< Max, Min == infinity -> Int;
|
||||
Int when Int =< Max, Int >= Min -> Int
|
||||
end.
|
||||
|
||||
enc_int(Int) -> integer_to_binary(Int).
|
||||
|
||||
dec_bool(<<"1">>) -> true;
|
||||
dec_bool(<<"0">>) -> false;
|
||||
dec_bool(<<"true">>) -> true;
|
||||
dec_bool(<<"false">>) -> false.
|
||||
|
||||
enc_bool(true) -> <<"1">>;
|
||||
enc_bool(false) -> <<"0">>.
|
||||
|
||||
enc_jid(J) -> jid:to_string(J).
|
||||
|
||||
dec_jid(Val) ->
|
||||
case jid:from_string(Val) of
|
||||
error -> erlang:error(badarg);
|
||||
J -> J
|
||||
end.
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, []);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/muc#roominfo">>]} ->
|
||||
decode(Fs, Acc, []);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{maxhistoryfetch, Val} ->
|
||||
[encode_maxhistoryfetch(Val, Translate)];
|
||||
{maxhistoryfetch, _, _} -> erlang:error({badarg, Opt});
|
||||
{contactjid, Val} ->
|
||||
[encode_contactjid(Val, Translate)];
|
||||
{contactjid, _, _} -> erlang:error({badarg, Opt});
|
||||
{description, Val} ->
|
||||
[encode_description(Val, Translate)];
|
||||
{description, _, _} -> erlang:error({badarg, Opt});
|
||||
{lang, Val} -> [encode_lang(Val, Translate)];
|
||||
{lang, _, _} -> erlang:error({badarg, Opt});
|
||||
{ldapgroup, Val} -> [encode_ldapgroup(Val, Translate)];
|
||||
{ldapgroup, _, _} -> erlang:error({badarg, Opt});
|
||||
{logs, Val} -> [encode_logs(Val, Translate)];
|
||||
{logs, _, _} -> erlang:error({badarg, Opt});
|
||||
{occupants, Val} -> [encode_occupants(Val, Translate)];
|
||||
{occupants, _, _} -> erlang:error({badarg, Opt});
|
||||
{subject, Val} -> [encode_subject(Val, Translate)];
|
||||
{subject, _, _} -> erlang:error({badarg, Opt});
|
||||
{subjectmod, Val} ->
|
||||
[encode_subjectmod(Val, Translate)];
|
||||
{subjectmod, _, _} -> erlang:error({badarg, Opt});
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/muc#roominfo">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"muc#maxhistoryfetch">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_int(Value, 0, infinity) of
|
||||
Result ->
|
||||
decode(Fs, [{maxhistoryfetch, Result} | Acc],
|
||||
lists:delete(<<"muc#maxhistoryfetch">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#maxhistoryfetch">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#maxhistoryfetch">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#maxhistoryfetch">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#maxhistoryfetch">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#maxhistoryfetch">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var =
|
||||
<<"muc#roominfo_contactjid">>,
|
||||
values = Values}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try [dec_jid(Value) || Value <- Values] of
|
||||
Result ->
|
||||
decode(Fs, [{contactjid, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_contactjid">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_contactjid">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var =
|
||||
<<"muc#roominfo_description">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{description, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_description">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_description">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var =
|
||||
<<"muc#roominfo_description">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var =
|
||||
<<"muc#roominfo_description">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var =
|
||||
<<"muc#roominfo_description">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roominfo_description">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var = <<"muc#roominfo_lang">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{lang, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_lang">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_lang">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#roominfo_lang">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#roominfo_lang">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#roominfo_lang">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roominfo_lang">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var = <<"muc#roominfo_ldapgroup">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{ldapgroup, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_ldapgroup">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_ldapgroup">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#roominfo_ldapgroup">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var =
|
||||
<<"muc#roominfo_ldapgroup">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#roominfo_ldapgroup">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roominfo_ldapgroup">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var = <<"muc#roominfo_logs">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{logs, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_logs">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_logs">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#roominfo_logs">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#roominfo_logs">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#roominfo_logs">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roominfo_logs">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var = <<"muc#roominfo_occupants">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_int(Value, 0, infinity) of
|
||||
Result ->
|
||||
decode(Fs, [{occupants, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_occupants">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_occupants">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#roominfo_occupants">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var =
|
||||
<<"muc#roominfo_occupants">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#roominfo_occupants">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roominfo_occupants">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var = <<"muc#roominfo_subject">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{subject, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_subject">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_subject">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"muc#roominfo_subject">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"muc#roominfo_subject">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"muc#roominfo_subject">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roominfo_subject">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var =
|
||||
<<"muc#roominfo_subjectmod">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_bool(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{subjectmod, Result} | Acc],
|
||||
lists:delete(<<"muc#roominfo_subjectmod">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"muc#roominfo_subjectmod">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}})
|
||||
end;
|
||||
decode([#xdata_field{var =
|
||||
<<"muc#roominfo_subjectmod">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var =
|
||||
<<"muc#roominfo_subjectmod">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var =
|
||||
<<"muc#roominfo_subjectmod">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"muc#roominfo_subjectmod">>,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/muc#roominfo">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_maxhistoryfetch(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_int(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#maxhistoryfetch">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Maximum Number of History Messages Returned "
|
||||
"by Room">>)}.
|
||||
|
||||
encode_contactjid(Value, Translate) ->
|
||||
Values = case Value of
|
||||
[] -> [];
|
||||
Value -> [enc_jid(V) || V <- Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_contactjid">>,
|
||||
values = Values, required = false, type = 'jid-multi',
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Contact Addresses (normally, room owner "
|
||||
"or owners)">>)}.
|
||||
|
||||
encode_description(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_description">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Room description">>)}.
|
||||
|
||||
encode_lang(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_lang">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Natural Language for Room Discussions">>)}.
|
||||
|
||||
encode_ldapgroup(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_ldapgroup">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"An associated LDAP group that defines "
|
||||
"room membership; this should be an LDAP "
|
||||
"Distinguished Name according to an implementa"
|
||||
"tion-specific or deployment-specific "
|
||||
"definition of a group.">>)}.
|
||||
|
||||
encode_logs(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_logs">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"URL for Archived Discussion Logs">>)}.
|
||||
|
||||
encode_occupants(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_int(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_occupants">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Number of occupants">>)}.
|
||||
|
||||
encode_subject(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_subject">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Current Discussion Topic">>)}.
|
||||
|
||||
encode_subjectmod(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_bool(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"muc#roominfo_subjectmod">>,
|
||||
values = Values, required = false, type = boolean,
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"The room subject can be modified by "
|
||||
"participants">>)}.
|
@ -1,130 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_get_pending.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#subscribe_authorization
|
||||
%% Document: XEP-0060
|
||||
|
||||
-module(pubsub_get_pending).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("pubsub_get_pending.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, [<<"pubsub#node">>]);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>]} ->
|
||||
decode(Fs, Acc, [<<"pubsub#node">>]);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{node, Val} -> [encode_node(Val, default, Translate)];
|
||||
{node, Val, Opts} ->
|
||||
[encode_node(Val, Opts, Translate)];
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"pubsub#node">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{node, Result} | Acc],
|
||||
lists:delete(<<"pubsub#node">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#node">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#node">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#node">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#node">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#node">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_node(Value, Options, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = if Options == default -> [];
|
||||
true ->
|
||||
[#xdata_option{label = Translate(L), value = V}
|
||||
|| {L, V} <- Options]
|
||||
end,
|
||||
#xdata_field{var = <<"pubsub#node">>, values = Values,
|
||||
required = false, type = 'list-single', options = Opts,
|
||||
desc = <<>>,
|
||||
label =
|
||||
Translate(<<"The NodeID of the relevant node">>)}.
|
File diff suppressed because it is too large
Load Diff
@ -1,157 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_publish_options.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#publish-options
|
||||
%% Document: XEP-0060
|
||||
|
||||
-module(pubsub_publish_options).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("pubsub_publish_options.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
dec_enum(Val, Enums) ->
|
||||
AtomVal = erlang:binary_to_existing_atom(Val, utf8),
|
||||
case lists:member(AtomVal, Enums) of
|
||||
true -> AtomVal
|
||||
end.
|
||||
|
||||
enc_enum(Atom) -> erlang:atom_to_binary(Atom, utf8).
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, []);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/pubsub#publish-opt"
|
||||
"ions">>]} ->
|
||||
decode(Fs, Acc, []);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/pubsub#publish-opt"
|
||||
"ions">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{access_model, Val} ->
|
||||
[encode_access_model(Val, default, Translate)];
|
||||
{access_model, Val, Opts} ->
|
||||
[encode_access_model(Val, Opts, Translate)];
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/pubsub#publish-opt"
|
||||
"ions">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"pubsub#access_model">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_enum(Value,
|
||||
[authorize, open, presence, roster, whitelist])
|
||||
of
|
||||
Result ->
|
||||
decode(Fs, [{access_model, Result} | Acc],
|
||||
lists:delete(<<"pubsub#access_model">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#access_model">>,
|
||||
<<"http://jabber.org/protocol/pubsub#publish-opt"
|
||||
"ions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#access_model">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#access_model">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#access_model">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#access_model">>,
|
||||
<<"http://jabber.org/protocol/pubsub#publish-opt"
|
||||
"ions">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#publish-opt"
|
||||
"ions">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#publish-opt"
|
||||
"ions">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_access_model(Value, Options, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_enum(Value)]
|
||||
end,
|
||||
Opts = if Options == default ->
|
||||
[#xdata_option{label =
|
||||
Translate(<<"Access model of authorize">>),
|
||||
value = <<"authorize">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"Access model of open">>),
|
||||
value = <<"open">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"Access model of presence">>),
|
||||
value = <<"presence">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"Access model of roster">>),
|
||||
value = <<"roster">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"Access model of whitelist">>),
|
||||
value = <<"whitelist">>}];
|
||||
true ->
|
||||
[#xdata_option{label = Translate(L),
|
||||
value = enc_enum(V)}
|
||||
|| {L, V} <- Options]
|
||||
end,
|
||||
#xdata_field{var = <<"pubsub#access_model">>,
|
||||
values = Values, required = false, type = 'list-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Specify the access model">>)}.
|
@ -1,279 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_subscribe_authorization.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#subscribe_authorization
|
||||
%% Document: XEP-0060
|
||||
|
||||
-module(pubsub_subscribe_authorization).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("pubsub_subscribe_authorization.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
dec_bool(<<"1">>) -> true;
|
||||
dec_bool(<<"0">>) -> false;
|
||||
dec_bool(<<"true">>) -> true;
|
||||
dec_bool(<<"false">>) -> false.
|
||||
|
||||
enc_bool(true) -> <<"1">>;
|
||||
enc_bool(false) -> <<"0">>.
|
||||
|
||||
enc_jid(J) -> jid:to_string(J).
|
||||
|
||||
dec_jid(Val) ->
|
||||
case jid:from_string(Val) of
|
||||
error -> erlang:error(badarg);
|
||||
J -> J
|
||||
end.
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false ->
|
||||
decode(Fs, Acc,
|
||||
[<<"pubsub#allow">>, <<"pubsub#node">>,
|
||||
<<"pubsub#subscriber_jid">>]);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>]} ->
|
||||
decode(Fs, Acc,
|
||||
[<<"pubsub#allow">>, <<"pubsub#node">>,
|
||||
<<"pubsub#subscriber_jid">>]);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{allow, Val} -> [encode_allow(Val, Translate)];
|
||||
{allow, _, _} -> erlang:error({badarg, Opt});
|
||||
{node, Val} -> [encode_node(Val, Translate)];
|
||||
{node, _, _} -> erlang:error({badarg, Opt});
|
||||
{subscriber_jid, Val} ->
|
||||
[encode_subscriber_jid(Val, Translate)];
|
||||
{subscriber_jid, _, _} -> erlang:error({badarg, Opt});
|
||||
{subid, Val} -> [encode_subid(Val, Translate)];
|
||||
{subid, _, _} -> erlang:error({badarg, Opt});
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"pubsub#allow">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_bool(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{allow, Result} | Acc],
|
||||
lists:delete(<<"pubsub#allow">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#allow">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#allow">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#allow">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#allow">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#allow">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
decode([#xdata_field{var = <<"pubsub#node">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{node, Result} | Acc],
|
||||
lists:delete(<<"pubsub#node">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#node">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#node">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#node">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#node">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#node">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
decode([#xdata_field{var = <<"pubsub#subscriber_jid">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_jid(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{subscriber_jid, Result} | Acc],
|
||||
lists:delete(<<"pubsub#subscriber_jid">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#subscriber_jid">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#subscriber_jid">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#subscriber_jid">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#subscriber_jid">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#subscriber_jid">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
decode([#xdata_field{var = <<"pubsub#subid">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{subid, Result} | Acc],
|
||||
lists:delete(<<"pubsub#subid">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#subid">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#subid">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#subid">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#subid">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#subid">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_a"
|
||||
"uthorization">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_allow(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_bool(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#allow">>, values = Values,
|
||||
required = false, type = boolean, options = Opts,
|
||||
desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Allow this Jabber ID to subscribe to "
|
||||
"this pubsub node?">>)}.
|
||||
|
||||
encode_node(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#node">>, values = Values,
|
||||
required = false, type = 'text-single', options = Opts,
|
||||
desc = <<>>, label = Translate(<<"Node ID">>)}.
|
||||
|
||||
encode_subscriber_jid(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_jid(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#subscriber_jid">>,
|
||||
values = Values, required = false, type = 'jid-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label = Translate(<<"Subscriber Address">>)}.
|
||||
|
||||
encode_subid(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#subid">>, values = Values,
|
||||
required = false, type = 'text-single', options = Opts,
|
||||
desc = <<>>,
|
||||
label =
|
||||
Translate(<<"The subscription identifier associated "
|
||||
"with the subscription request">>)}.
|
@ -1,508 +0,0 @@
|
||||
%% Created automatically by xdata generator (xdata_codec.erl)
|
||||
%% Source: pubsub_subscribe_options.xdata
|
||||
%% Form type: http://jabber.org/protocol/pubsub#subscribe_options
|
||||
%% Document: XEP-0060
|
||||
|
||||
-module(pubsub_subscribe_options).
|
||||
|
||||
-export([decode/1, decode/2, encode/1, encode/2,
|
||||
format_error/1]).
|
||||
|
||||
-include("xmpp_codec.hrl").
|
||||
|
||||
-include("pubsub_subscribe_options.hrl").
|
||||
|
||||
-export_type([property/0, result/0, form/0]).
|
||||
|
||||
dec_enum(Val, Enums) ->
|
||||
AtomVal = erlang:binary_to_existing_atom(Val, utf8),
|
||||
case lists:member(AtomVal, Enums) of
|
||||
true -> AtomVal
|
||||
end.
|
||||
|
||||
enc_enum(Atom) -> erlang:atom_to_binary(Atom, utf8).
|
||||
|
||||
dec_bool(<<"1">>) -> true;
|
||||
dec_bool(<<"0">>) -> false;
|
||||
dec_bool(<<"true">>) -> true;
|
||||
dec_bool(<<"false">>) -> false.
|
||||
|
||||
enc_bool(true) -> <<"1">>;
|
||||
enc_bool(false) -> <<"0">>.
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary,
|
||||
"' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '",
|
||||
Type/binary, "'">>.
|
||||
|
||||
decode(Fs) -> decode(Fs, []).
|
||||
|
||||
decode(Fs, Acc) ->
|
||||
case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var,
|
||||
Fs)
|
||||
of
|
||||
false -> decode(Fs, Acc, []);
|
||||
#xdata_field{values =
|
||||
[<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>]} ->
|
||||
decode(Fs, Acc, []);
|
||||
_ ->
|
||||
erlang:error({?MODULE,
|
||||
{form_type_mismatch,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end.
|
||||
|
||||
encode(Cfg) -> encode(Cfg, fun (Text) -> Text end).
|
||||
|
||||
encode(List, Translate) when is_list(List) ->
|
||||
Fs = [case Opt of
|
||||
{deliver, Val} -> [encode_deliver(Val, Translate)];
|
||||
{deliver, _, _} -> erlang:error({badarg, Opt});
|
||||
{digest, Val} -> [encode_digest(Val, Translate)];
|
||||
{digest, _, _} -> erlang:error({badarg, Opt});
|
||||
{digest_frequency, Val} ->
|
||||
[encode_digest_frequency(Val, Translate)];
|
||||
{digest_frequency, _, _} -> erlang:error({badarg, Opt});
|
||||
{expire, Val} -> [encode_expire(Val, Translate)];
|
||||
{expire, _, _} -> erlang:error({badarg, Opt});
|
||||
{include_body, Val} ->
|
||||
[encode_include_body(Val, Translate)];
|
||||
{include_body, _, _} -> erlang:error({badarg, Opt});
|
||||
{'show-values', Val} ->
|
||||
['encode_show-values'(Val, default, Translate)];
|
||||
{'show-values', Val, Opts} ->
|
||||
['encode_show-values'(Val, Opts, Translate)];
|
||||
{subscription_type, Val} ->
|
||||
[encode_subscription_type(Val, default, Translate)];
|
||||
{subscription_type, Val, Opts} ->
|
||||
[encode_subscription_type(Val, Opts, Translate)];
|
||||
{subscription_depth, Val} ->
|
||||
[encode_subscription_depth(Val, default, Translate)];
|
||||
{subscription_depth, Val, Opts} ->
|
||||
[encode_subscription_depth(Val, Opts, Translate)];
|
||||
#xdata_field{} -> [Opt];
|
||||
_ -> []
|
||||
end
|
||||
|| Opt <- List],
|
||||
FormType = #xdata_field{var = <<"FORM_TYPE">>,
|
||||
type = hidden,
|
||||
values =
|
||||
[<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>]},
|
||||
[FormType | lists:flatten(Fs)].
|
||||
|
||||
decode([#xdata_field{var = <<"pubsub#deliver">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_bool(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{deliver, Result} | Acc],
|
||||
lists:delete(<<"pubsub#deliver">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#deliver">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#deliver">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#deliver">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#deliver">>} | _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#deliver">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([#xdata_field{var = <<"pubsub#digest">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_bool(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{digest, Result} | Acc],
|
||||
lists:delete(<<"pubsub#digest">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#digest">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#digest">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#digest">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#digest">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#digest">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#digest_frequency">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{digest_frequency, Result} | Acc],
|
||||
lists:delete(<<"pubsub#digest_frequency">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#digest_frequency">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#digest_frequency">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var =
|
||||
<<"pubsub#digest_frequency">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#digest_frequency">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#digest_frequency">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([#xdata_field{var = <<"pubsub#expire">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try Value of
|
||||
Result ->
|
||||
decode(Fs, [{expire, Result} | Acc],
|
||||
lists:delete(<<"pubsub#expire">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#expire">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#expire">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#expire">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#expire">>} | _], _,
|
||||
_) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#expire">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([#xdata_field{var = <<"pubsub#include_body">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_bool(Value) of
|
||||
Result ->
|
||||
decode(Fs, [{include_body, Result} | Acc],
|
||||
lists:delete(<<"pubsub#include_body">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#include_body">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var = <<"pubsub#include_body">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var = <<"pubsub#include_body">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var = <<"pubsub#include_body">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#include_body">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([#xdata_field{var = <<"pubsub#show-values">>,
|
||||
values = Values}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try [dec_enum(Value, [away, chat, dnd, online, xa])
|
||||
|| Value <- Values]
|
||||
of
|
||||
Result ->
|
||||
decode(Fs, [{'show-values', Result} | Acc],
|
||||
lists:delete(<<"pubsub#show-values">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#show-values">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#subscription_type">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_enum(Value, [items, nodes]) of
|
||||
Result ->
|
||||
decode(Fs, [{subscription_type, Result} | Acc],
|
||||
lists:delete(<<"pubsub#subscription_type">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#subscription_type">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#subscription_type">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var =
|
||||
<<"pubsub#subscription_type">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#subscription_type">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#subscription_type">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#subscription_depth">>,
|
||||
values = [Value]}
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
try dec_enum(Value, ['1', all]) of
|
||||
Result ->
|
||||
decode(Fs, [{subscription_depth, Result} | Acc],
|
||||
lists:delete(<<"pubsub#subscription_depth">>, Required))
|
||||
catch
|
||||
_:_ ->
|
||||
erlang:error({?MODULE,
|
||||
{bad_var_value, <<"pubsub#subscription_depth">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}})
|
||||
end;
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#subscription_depth">>,
|
||||
values = []} =
|
||||
F
|
||||
| Fs],
|
||||
Acc, Required) ->
|
||||
decode([F#xdata_field{var =
|
||||
<<"pubsub#subscription_depth">>,
|
||||
values = [<<>>]}
|
||||
| Fs],
|
||||
Acc, Required);
|
||||
decode([#xdata_field{var =
|
||||
<<"pubsub#subscription_depth">>}
|
||||
| _],
|
||||
_, _) ->
|
||||
erlang:error({?MODULE,
|
||||
{too_many_values, <<"pubsub#subscription_depth">>,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([#xdata_field{var = Var} | Fs], Acc, Required) ->
|
||||
if Var /= <<"FORM_TYPE">> ->
|
||||
erlang:error({?MODULE,
|
||||
{unknown_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
true -> decode(Fs, Acc, Required)
|
||||
end;
|
||||
decode([], _, [Var | _]) ->
|
||||
erlang:error({?MODULE,
|
||||
{missing_required_var, Var,
|
||||
<<"http://jabber.org/protocol/pubsub#subscribe_o"
|
||||
"ptions">>}});
|
||||
decode([], Acc, []) -> Acc.
|
||||
|
||||
encode_deliver(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_bool(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#deliver">>,
|
||||
values = Values, required = false, type = boolean,
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Whether an entity wants to receive or "
|
||||
"disable notifications">>)}.
|
||||
|
||||
encode_digest(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_bool(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#digest">>, values = Values,
|
||||
required = false, type = boolean, options = Opts,
|
||||
desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Whether an entity wants to receive digests "
|
||||
"(aggregations) of notifications or all "
|
||||
"notifications individually">>)}.
|
||||
|
||||
encode_digest_frequency(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#digest_frequency">>,
|
||||
values = Values, required = false, type = 'text-single',
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"The minimum number of milliseconds between "
|
||||
"sending any two notification digests">>)}.
|
||||
|
||||
encode_expire(Value, Translate) ->
|
||||
Values = case Value of
|
||||
<<>> -> [];
|
||||
Value -> [Value]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#expire">>, values = Values,
|
||||
required = false, type = 'text-single', options = Opts,
|
||||
desc = <<>>,
|
||||
label =
|
||||
Translate(<<"The DateTime at which a leased subscription "
|
||||
"will end or has ended">>)}.
|
||||
|
||||
encode_include_body(Value, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_bool(Value)]
|
||||
end,
|
||||
Opts = [],
|
||||
#xdata_field{var = <<"pubsub#include_body">>,
|
||||
values = Values, required = false, type = boolean,
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"Whether an entity wants to receive an "
|
||||
"XMPP message body in addition to the "
|
||||
"payload format">>)}.
|
||||
|
||||
'encode_show-values'(Value, Options, Translate) ->
|
||||
Values = case Value of
|
||||
[] -> [];
|
||||
Value -> [enc_enum(V) || V <- Value]
|
||||
end,
|
||||
Opts = if Options == default ->
|
||||
[#xdata_option{label =
|
||||
Translate(<<"XMPP Show Value of Away">>),
|
||||
value = <<"away">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"XMPP Show Value of Chat">>),
|
||||
value = <<"chat">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"XMPP Show Value of DND (Do Not Disturb)">>),
|
||||
value = <<"dnd">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"Mere Availability in XMPP (No Show Value)">>),
|
||||
value = <<"online">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"XMPP Show Value of XA (Extended Away)">>),
|
||||
value = <<"xa">>}];
|
||||
true ->
|
||||
[#xdata_option{label = Translate(L),
|
||||
value = enc_enum(V)}
|
||||
|| {L, V} <- Options]
|
||||
end,
|
||||
#xdata_field{var = <<"pubsub#show-values">>,
|
||||
values = Values, required = false, type = 'list-multi',
|
||||
options = Opts, desc = <<>>,
|
||||
label =
|
||||
Translate(<<"The presence states for which an entity "
|
||||
"wants to receive notifications">>)}.
|
||||
|
||||
encode_subscription_type(Value, Options, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_enum(Value)]
|
||||
end,
|
||||
Opts = if Options == default ->
|
||||
[#xdata_option{label =
|
||||
Translate(<<"Receive notification of new items only">>),
|
||||
value = <<"items">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"Receive notification of new nodes only">>),
|
||||
value = <<"nodes">>}];
|
||||
true ->
|
||||
[#xdata_option{label = Translate(L),
|
||||
value = enc_enum(V)}
|
||||
|| {L, V} <- Options]
|
||||
end,
|
||||
#xdata_field{var = <<"pubsub#subscription_type">>,
|
||||
values = Values, required = false, type = 'list-single',
|
||||
options = Opts, desc = <<>>, label = <<>>}.
|
||||
|
||||
encode_subscription_depth(Value, Options, Translate) ->
|
||||
Values = case Value of
|
||||
undefined -> [];
|
||||
Value -> [enc_enum(Value)]
|
||||
end,
|
||||
Opts = if Options == default ->
|
||||
[#xdata_option{label =
|
||||
Translate(<<"Receive notification from direct child "
|
||||
"nodes only">>),
|
||||
value = <<"1">>},
|
||||
#xdata_option{label =
|
||||
Translate(<<"Receive notification from all descendent "
|
||||
"nodes">>),
|
||||
value = <<"all">>}];
|
||||
true ->
|
||||
[#xdata_option{label = Translate(L),
|
||||
value = enc_enum(V)}
|
||||
|| {L, V} <- Options]
|
||||
end,
|
||||
#xdata_field{var = <<"pubsub#subscription_depth">>,
|
||||
values = Values, required = false, type = 'list-single',
|
||||
options = Opts, desc = <<>>, label = <<>>}.
|
@ -1,648 +0,0 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @copyright (C) 2016, Evgeny Khramtsov
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 27 Sep 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(xdata_codec).
|
||||
|
||||
%% API
|
||||
-export([compile/1, compile/2]).
|
||||
-export([dec_int/1, dec_int/3, dec_enum/2, dec_bool/1, not_empty/1,
|
||||
dec_enum_int/2, dec_enum_int/4, enc_int/1, enc_enum/1,
|
||||
enc_bool/1, enc_enum_int/1, format_error/1, enc_jid/1, dec_jid/1]).
|
||||
-include("xmpp.hrl").
|
||||
|
||||
-record(state, {mod_name :: atom(),
|
||||
file_name :: string(),
|
||||
erl = "" :: string(),
|
||||
hrl = "" :: string(),
|
||||
dir = "" :: string(),
|
||||
ns = <<>> :: binary(),
|
||||
doc = <<>> :: binary(),
|
||||
erl_dir = "" :: string(),
|
||||
hrl_dir = "" :: string(),
|
||||
prefix = [] :: [binary()],
|
||||
dec_mfas = [] :: [{binary(), mfa()}],
|
||||
enc_mfas = [] :: [{binary(), mfa()}],
|
||||
specs = [] :: [{binary(), string()}],
|
||||
required = [] :: [{binary(), boolean()} | binary()],
|
||||
defaults = [] :: [{binary(), any()}]}).
|
||||
|
||||
-define(is_multi_type(T),
|
||||
((T == 'list-multi') or (T == 'jid-multi') or (T == 'text-multi'))).
|
||||
|
||||
-define(is_list_type(T),
|
||||
((T == 'list-single') or (T == 'list-multi'))).
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
compile(Path) ->
|
||||
compile(Path, []).
|
||||
|
||||
compile(Path, Opts) ->
|
||||
case filelib:is_dir(Path) of
|
||||
true ->
|
||||
filelib:fold_files(
|
||||
Path, ".*.xdata", false,
|
||||
fun(File, ok) ->
|
||||
compile_file(File, Opts);
|
||||
(_, Err) ->
|
||||
Err
|
||||
end, ok);
|
||||
false ->
|
||||
compile_file(Path, Opts)
|
||||
end.
|
||||
|
||||
compile_file(Path, Opts) ->
|
||||
try
|
||||
ok = application:ensure_started(fast_xml),
|
||||
DirName = filename:dirname(Path),
|
||||
FileName = filename:basename(Path),
|
||||
RootName = filename:rootname(FileName),
|
||||
ConfigPath = filename:join(DirName, RootName) ++ ".cfg",
|
||||
ModName = list_to_atom(RootName),
|
||||
{ok, Data} = file:read_file(Path),
|
||||
Config = case file:consult(ConfigPath) of
|
||||
{ok, Terms} -> lists:flatten(Terms);
|
||||
{error, enoent} -> []
|
||||
end,
|
||||
State = #state{mod_name = ModName,
|
||||
file_name = FileName,
|
||||
erl = filename:rootname(FileName) ++ ".erl",
|
||||
hrl = filename:rootname(FileName) ++ ".hrl",
|
||||
dir = DirName,
|
||||
prefix = proplists:get_all_values(prefix, Config),
|
||||
erl_dir = proplists:get_value(erl_dir, Opts, DirName),
|
||||
hrl_dir = proplists:get_value(hrl_dir, Opts, DirName),
|
||||
dec_mfas = proplists:get_value(decode, Config, []),
|
||||
enc_mfas = proplists:get_value(encode, Config, []),
|
||||
specs = proplists:get_value(specs, Config, []),
|
||||
required = proplists:get_value(required, Config, []),
|
||||
defaults = proplists:get_value(defaults, Config, [])},
|
||||
#xmlel{} = El = fxml_stream:parse_element(Data),
|
||||
ok = compile_element(normalize(El), State),
|
||||
io:format("Compiled ~s~n", [Path])
|
||||
catch _:{badmatch, Err} ->
|
||||
io:format(standard_error, "Failed to compile ~s: ~p~n",
|
||||
[Path, Err]),
|
||||
Err
|
||||
end.
|
||||
|
||||
emit(Format) ->
|
||||
emit(Format, []).
|
||||
|
||||
emit(Format, Args) ->
|
||||
put(outbuf, get(outbuf) ++ io_lib:format(Format, Args)).
|
||||
|
||||
dec_int(Val) ->
|
||||
dec_int(Val, infinity, infinity).
|
||||
|
||||
dec_int(Val, Min, Max) ->
|
||||
case list_to_integer(binary_to_list(Val)) of
|
||||
Int when Int =< Max, Min == infinity ->
|
||||
Int;
|
||||
Int when Int =< Max, Int >= Min ->
|
||||
Int
|
||||
end.
|
||||
|
||||
enc_int(Int) ->
|
||||
integer_to_binary(Int).
|
||||
|
||||
dec_enum(Val, Enums) ->
|
||||
AtomVal = erlang:binary_to_existing_atom(Val, utf8),
|
||||
case lists:member(AtomVal, Enums) of
|
||||
true ->
|
||||
AtomVal
|
||||
end.
|
||||
|
||||
enc_enum(Atom) ->
|
||||
erlang:atom_to_binary(Atom, utf8).
|
||||
|
||||
dec_enum_int(Val, Enums) ->
|
||||
try dec_int(Val)
|
||||
catch _:_ -> dec_enum(Val, Enums)
|
||||
end.
|
||||
|
||||
dec_enum_int(Val, Enums, Min, Max) ->
|
||||
try dec_int(Val, Min, Max)
|
||||
catch _:_ -> dec_enum(Val, Enums)
|
||||
end.
|
||||
|
||||
enc_enum_int(Int) when is_integer(Int) ->
|
||||
enc_int(Int);
|
||||
enc_enum_int(Atom) ->
|
||||
enc_enum(Atom).
|
||||
|
||||
dec_bool(<<"1">>) -> true;
|
||||
dec_bool(<<"0">>) -> false;
|
||||
dec_bool(<<"true">>) -> true;
|
||||
dec_bool(<<"false">>) -> false.
|
||||
|
||||
enc_bool(true) -> <<"1">>;
|
||||
enc_bool(false) -> <<"0">>.
|
||||
|
||||
enc_jid(J) -> jid:to_string(J).
|
||||
|
||||
dec_jid(Val) ->
|
||||
case jid:from_string(Val) of
|
||||
error -> erlang:error(badarg);
|
||||
J -> J
|
||||
end.
|
||||
|
||||
not_empty(<<_, _/binary>> = Val) ->
|
||||
Val.
|
||||
|
||||
format_error({form_type_mismatch, Type}) ->
|
||||
<<"FORM_TYPE doesn't match '", Type/binary, "'">>;
|
||||
format_error({bad_var_value, Var, Type}) ->
|
||||
<<"Bad value of field '", Var/binary, "' of type '", Type/binary, "'">>;
|
||||
format_error({missing_value, Var, Type}) ->
|
||||
<<"Missing value of field '", Var/binary, "' of type '", Type/binary, "'">>;
|
||||
format_error({too_many_values, Var, Type}) ->
|
||||
<<"Too many values for field '", Var/binary, "' of type '", Type/binary, "'">>;
|
||||
format_error({unknown_var, Var, Type}) ->
|
||||
<<"Unknown field '", Var/binary, "' of type '", Type/binary, "'">>;
|
||||
format_error({missing_required_var, Var, Type}) ->
|
||||
<<"Missing required field '", Var/binary, "' of type '", Type/binary, "'">>.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
compile_element(#xmlel{name = <<"form_type">>, children = Els} = Form,
|
||||
#state{erl = OutErl, erl_dir = ErlDir,
|
||||
hrl = OutHrl, hrl_dir = HrlDir} = State0) ->
|
||||
try
|
||||
Name = fxml:get_subtag_cdata(Form, <<"name">>),
|
||||
Doc = fxml:get_subtag_cdata(Form, <<"doc">>),
|
||||
X = #xmlel{name = <<"x">>,
|
||||
attrs = [{<<"type">>, <<"form">>},
|
||||
{<<"xmlns">>, <<"jabber:x:data">>}],
|
||||
children = Els},
|
||||
State = State0#state{ns = Name, doc = Doc},
|
||||
#xdata{fields = Fs} = xmpp_codec:decode(X),
|
||||
put(outbuf, []),
|
||||
mk_header(State),
|
||||
mk_aux_funs(),
|
||||
mk_top_decoder(Fs, State),
|
||||
mk_top_encoder(Fs, State),
|
||||
mk_decoder(Fs, State),
|
||||
mk_encoders(Fs, State),
|
||||
ErlData = get(outbuf),
|
||||
ok = file:write_file(filename:join(ErlDir, OutErl), ErlData),
|
||||
ok = erl_tidy:file(filename:join(ErlDir, OutErl), [{backups, false}]),
|
||||
put(outbuf, []),
|
||||
mk_type_definitions(Fs, State),
|
||||
HrlData = get(outbuf),
|
||||
ok = file:write_file(filename:join(HrlDir, OutHrl), HrlData)
|
||||
catch _:{badmatch, Err} ->
|
||||
Err
|
||||
end.
|
||||
|
||||
mk_aux_funs() ->
|
||||
case get_abstract_code_from_myself() of
|
||||
{ok, AbsCode} ->
|
||||
AST = lists:filter(
|
||||
fun(T) ->
|
||||
case catch erl_syntax_lib:analyze_function(T) of
|
||||
{format_error, 1} -> true;
|
||||
{dec_int, 3} -> true;
|
||||
{dec_int, 1} -> true;
|
||||
{dec_enum, 2} -> true;
|
||||
{dec_enum_int, 2} -> true;
|
||||
{dec_enum_int, 4} -> true;
|
||||
{enc_int, 1} -> true;
|
||||
{enc_enum, 1} -> true;
|
||||
{enc_enum_int, 1} -> true;
|
||||
{not_empty, 1} -> true;
|
||||
{dec_bool, 1} -> true;
|
||||
{enc_bool, 1} -> true;
|
||||
{enc_jid, 1} -> true;
|
||||
{dec_jid, 1} -> true;
|
||||
_ -> false
|
||||
end
|
||||
end, AbsCode),
|
||||
emit(erl_prettypr:format(erl_syntax:form_list(AST)) ++ io_lib:nl());
|
||||
error ->
|
||||
erlang:error({no_abstract_code_found, ?MODULE})
|
||||
end.
|
||||
|
||||
get_abstract_code_from_myself() ->
|
||||
{file, File} = code:is_loaded(?MODULE),
|
||||
case beam_lib:chunks(File, [abstract_code]) of
|
||||
{ok, {_, List}} ->
|
||||
case lists:keyfind(abstract_code, 1, List) of
|
||||
{abstract_code, {raw_abstract_v1, Abstr}} ->
|
||||
{ok, Abstr};
|
||||
_ ->
|
||||
error
|
||||
end;
|
||||
_ ->
|
||||
error
|
||||
end.
|
||||
|
||||
mk_comment_header(#state{file_name = Source, ns = NS, doc = Doc}) ->
|
||||
emit("%% Created automatically by xdata generator (xdata_codec.erl)~n"
|
||||
"%% Source: ~s~n"
|
||||
"%% Form type: ~s~n", [Source, NS]),
|
||||
if Doc /= <<>> -> emit("%% Document: ~s~n~n", [Doc]);
|
||||
true -> emit("~n")
|
||||
end.
|
||||
|
||||
mk_header(#state{mod_name = Mod, hrl = Include} = State) ->
|
||||
mk_comment_header(State),
|
||||
emit("~n-module(~s).~n", [Mod]),
|
||||
emit("-export([decode/1, decode/2, encode/1, encode/2, format_error/1]).~n"),
|
||||
emit("-include(\"xmpp_codec.hrl\").~n"),
|
||||
emit("-include(\"~s\").~n", [Include]),
|
||||
emit("-export_type([property/0, result/0, form/0]).~n").
|
||||
|
||||
mk_type_definitions(Fs, State) ->
|
||||
mk_comment_header(State),
|
||||
lists:foreach(
|
||||
fun(#xdata_field{var = Var} = F) ->
|
||||
Spec = get_typespec(F, State),
|
||||
case is_complex_type(Spec) of
|
||||
true ->
|
||||
emit("-type '~s'() :: ~s.~n",
|
||||
[var_to_rec_field(Var, State), Spec]);
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
end, Fs),
|
||||
emit("~n-type property() :: "),
|
||||
Fields = lists:map(
|
||||
fun(#xdata_field{var = Var} = F) ->
|
||||
RecField = var_to_rec_field(Var, State),
|
||||
[io_lib:format("{'~s', ~s}",
|
||||
[RecField, mk_typespec(F, State)])]
|
||||
end, Fs),
|
||||
emit(string:join(Fields, " |~n ") ++ ".~n"),
|
||||
emit("-type result() :: [property()].~n~n"),
|
||||
VarsWithSpec = lists:flatmap(
|
||||
fun(#xdata_field{type = T, var = Var} = F)
|
||||
when ?is_list_type(T) ->
|
||||
RecName = var_to_rec_field(Var, State),
|
||||
Spec0 = get_typespec(F, State),
|
||||
Spec = case is_complex_type(Spec0) of
|
||||
true ->
|
||||
io_lib:format("'~s'()", [RecName]);
|
||||
false ->
|
||||
Spec0
|
||||
end,
|
||||
[{RecName, mk_typespec(F, State), Spec}];
|
||||
(_) ->
|
||||
[]
|
||||
end, Fs),
|
||||
case VarsWithSpec of
|
||||
[] ->
|
||||
emit("-type form() :: [property() | xdata_field()].~n");
|
||||
_ ->
|
||||
emit("-type options(T) :: [{binary(), T}].~n"),
|
||||
emit("-type property_with_options() ::~n "),
|
||||
Options = [io_lib:format("{'~s', ~s, options(~s)}",
|
||||
[Var, Spec1, Spec2])
|
||||
|| {Var, Spec1, Spec2} <- VarsWithSpec],
|
||||
emit(string:join(Options, " |~n ") ++ ".~n"),
|
||||
emit("-type form() :: [property() | property_with_options() | xdata_field()].~n")
|
||||
end.
|
||||
|
||||
mk_top_decoder(Fs, State) ->
|
||||
Required = [Var || #xdata_field{var = Var} <- Fs, is_required(Var, State)],
|
||||
emit("decode(Fs) -> decode(Fs, []).~n"),
|
||||
emit("decode(Fs, Acc) ->"
|
||||
" case lists:keyfind(<<\"FORM_TYPE\">>, #xdata_field.var, Fs) of"
|
||||
" false ->"
|
||||
" decode(Fs, Acc, ~p);"
|
||||
" #xdata_field{values = [~p]} ->"
|
||||
" decode(Fs, Acc, ~p);"
|
||||
" _ ->"
|
||||
" erlang:error({?MODULE, {form_type_mismatch, ~p}})~n"
|
||||
" end.~n",
|
||||
[Required, State#state.ns, Required, State#state.ns]).
|
||||
|
||||
mk_top_encoder(Fs, State) ->
|
||||
Clauses = string:join(
|
||||
lists:map(
|
||||
fun(#xdata_field{var = Var, type = T}) when ?is_list_type(T) ->
|
||||
Field = var_to_rec_field(Var, State),
|
||||
io_lib:format(
|
||||
"{'~s', Val} -> ['encode_~s'(Val, default, Translate)];"
|
||||
"{'~s', Val, Opts} -> ['encode_~s'(Val, Opts, Translate)]",
|
||||
[Field, Field, Field, Field]);
|
||||
(#xdata_field{var = Var}) ->
|
||||
Field = var_to_rec_field(Var, State),
|
||||
io_lib:format(
|
||||
"{'~s', Val} -> ['encode_~s'(Val, Translate)];"
|
||||
"{'~s', _, _} -> erlang:error({badarg, Opt})",
|
||||
[Field, Field, Field])
|
||||
end, Fs) ++ ["#xdata_field{} -> [Opt]; _ -> []"],
|
||||
";"),
|
||||
emit("encode(Cfg) -> encode(Cfg, fun(Text) -> Text end).~n"),
|
||||
emit("encode(List, Translate) when is_list(List) ->"
|
||||
" Fs = [case Opt of ~s end || Opt <- List],"
|
||||
" FormType = #xdata_field{var = <<\"FORM_TYPE\">>, type = hidden,"
|
||||
" values = [~p]},"
|
||||
" [FormType|lists:flatten(Fs)].~n",
|
||||
[Clauses, State#state.ns]).
|
||||
|
||||
mk_decoder([#xdata_field{var = Var, type = Type} = F|Fs], State) ->
|
||||
ValVar = if ?is_multi_type(Type) -> "Values";
|
||||
true -> "[Value]"
|
||||
end,
|
||||
DecFun = if ?is_multi_type(Type) ->
|
||||
["[", mk_decoding_fun(F, State), " || Value <- Values]"];
|
||||
true ->
|
||||
mk_decoding_fun(F, State)
|
||||
end,
|
||||
emit("decode([#xdata_field{var = ~p, values = ~s}|Fs], Acc, Required) ->"
|
||||
" try ~s of"
|
||||
" Result -> decode(Fs, [{'~s', Result}|Acc],"
|
||||
" lists:delete(~p, Required))"
|
||||
" catch _:_ ->"
|
||||
" erlang:error({?MODULE, {bad_var_value, ~p, ~p}})"
|
||||
" end;",
|
||||
[Var, ValVar, DecFun, var_to_rec_field(Var, State),
|
||||
Var, Var, State#state.ns]),
|
||||
if not ?is_multi_type(Type) ->
|
||||
emit("decode([#xdata_field{var = ~p, values = []} = F|Fs],"
|
||||
" Acc, Required) ->"
|
||||
" decode([F#xdata_field{var = ~p, values = [<<>>]}|Fs],"
|
||||
" Acc, Required);",
|
||||
[Var, Var]),
|
||||
emit("decode([#xdata_field{var = ~p}|_], _, _) ->"
|
||||
" erlang:error({?MODULE, {too_many_values, ~p, ~p}});",
|
||||
[Var, Var, State#state.ns]);
|
||||
true ->
|
||||
ok
|
||||
end,
|
||||
mk_decoder(Fs, State);
|
||||
mk_decoder([], State) ->
|
||||
emit("decode([#xdata_field{var = Var}|Fs], Acc, Required) ->"
|
||||
" if Var /= <<\"FORM_TYPE\">> ->"
|
||||
" erlang:error({?MODULE, {unknown_var, Var, ~p}});"
|
||||
" true ->"
|
||||
" decode(Fs, Acc, Required)"
|
||||
" end;",
|
||||
[State#state.ns]),
|
||||
emit("decode([], _, [Var|_]) ->"
|
||||
" erlang:error({?MODULE, {missing_required_var, Var, ~p}});~n",
|
||||
[State#state.ns]),
|
||||
emit("decode([], Acc, []) -> Acc.~n").
|
||||
|
||||
mk_encoders(Fs, State) ->
|
||||
lists:foreach(
|
||||
fun(#xdata_field{var = Var, required = IsRequired, desc = Desc,
|
||||
label = Label, type = Type} = F) ->
|
||||
EncVals = mk_encoded_values(F, State),
|
||||
EncOpts = mk_encoded_options(F, State),
|
||||
FieldName = var_to_rec_field(Var, State),
|
||||
DescStr = if Desc == <<>> -> "<<>>";
|
||||
true -> io_lib:format("Translate(~p)", [Desc])
|
||||
end,
|
||||
LabelStr = if Label == <<>> -> "<<>>";
|
||||
true -> io_lib:format("Translate(~p)", [Label])
|
||||
end,
|
||||
if ?is_list_type(Type) ->
|
||||
emit("'encode_~s'(Value, Options, Translate) ->", [FieldName]);
|
||||
true ->
|
||||
emit("'encode_~s'(Value, Translate) ->", [FieldName])
|
||||
end,
|
||||
emit(" Values = ~s,"
|
||||
" Opts = ~s,"
|
||||
" #xdata_field{var = ~p,"
|
||||
" values = Values,"
|
||||
" required = ~p,"
|
||||
" type = ~p,"
|
||||
" options = Opts,"
|
||||
" desc = ~s,"
|
||||
" label = ~s}.~n",
|
||||
[EncVals, EncOpts, Var, IsRequired, Type, DescStr, LabelStr])
|
||||
end, Fs).
|
||||
|
||||
mk_encoded_values(#xdata_field{var = Var, type = Type,
|
||||
options = Options}, State) ->
|
||||
EncFun =
|
||||
case get_enc_fun(Var, Type, Options, State) of
|
||||
{M, Fun, Args} ->
|
||||
Mod = if M == undefined -> "";
|
||||
true -> io_lib:format("~s:", [M])
|
||||
end,
|
||||
FArgs = [io_lib:format(", ~p", [A]) || A <- Args],
|
||||
if ?is_multi_type(Type) ->
|
||||
"[" ++ io_lib:format("~s~s(V~s)", [Mod, Fun, FArgs]) ++
|
||||
" || V <- Value]";
|
||||
true ->
|
||||
"[" ++ io_lib:format("~s~s(Value~s)", [Mod, Fun, FArgs])
|
||||
++ "]"
|
||||
end;
|
||||
undefined ->
|
||||
"[Value]"
|
||||
end,
|
||||
Default = case get_dec_fun(Var, Type, Options, State) of
|
||||
_ when ?is_multi_type(Type) -> "[]";
|
||||
undefined -> "<<>>";
|
||||
_MFA -> "undefined"
|
||||
end,
|
||||
io_lib:format(
|
||||
"case Value of"
|
||||
" ~s -> [];~n"
|
||||
" Value -> ~s~n"
|
||||
"end",
|
||||
[Default, EncFun]).
|
||||
|
||||
mk_encoded_options(#xdata_field{var = Var, type = Type,
|
||||
options = Options}, State) ->
|
||||
EncFun = case get_enc_fun(Var, Type, Options, State) of
|
||||
{M, Fun, Args} ->
|
||||
Mod = if M == undefined -> "";
|
||||
true -> io_lib:format("~s:", [M])
|
||||
end,
|
||||
FArgs = [io_lib:format(", ~p", [A]) || A <- Args],
|
||||
io_lib:format("~s~s(V~s)", [Mod, Fun, FArgs]);
|
||||
undefined ->
|
||||
"V"
|
||||
end,
|
||||
EncOpts = string:join(
|
||||
[case L of
|
||||
<<>> ->
|
||||
io_lib:format("#xdata_option{value = ~p}", [V]);
|
||||
_ ->
|
||||
io_lib:format(
|
||||
"#xdata_option{label = Translate(~p), value = ~p}",
|
||||
[L, V])
|
||||
end || #xdata_option{label = L, value = V} <- Options],
|
||||
","),
|
||||
if ?is_list_type(Type) ->
|
||||
io_lib:format(
|
||||
"if Options == default ->"
|
||||
" [~s];"
|
||||
"true ->"
|
||||
" [#xdata_option{label = Translate(L), value = ~s}"
|
||||
" || {L, V} <- Options]"
|
||||
"end",
|
||||
[EncOpts, EncFun]);
|
||||
true ->
|
||||
"[]"
|
||||
end.
|
||||
|
||||
mk_decoding_fun(#xdata_field{var = Var, type = Type,
|
||||
options = Options}, State) ->
|
||||
case get_dec_fun(Var, Type, Options, State) of
|
||||
{M, Fun, Args} ->
|
||||
Mod = if M == undefined -> "";
|
||||
true -> io_lib:format("~s:", [M])
|
||||
end,
|
||||
FArgs = [io_lib:format(", ~p", [A]) || A <- Args],
|
||||
io_lib:format("~s~s(Value~s)", [Mod, Fun, FArgs]);
|
||||
undefined ->
|
||||
"Value"
|
||||
end.
|
||||
|
||||
var_to_rec_field(Var, #state{prefix = [Prefix|T]} = State) ->
|
||||
Size = size(Prefix),
|
||||
case Var of
|
||||
<<(Prefix):Size/binary, Rest/binary>> ->
|
||||
binary_to_atom(Rest, utf8);
|
||||
_ ->
|
||||
var_to_rec_field(Var, State#state{prefix = T})
|
||||
end;
|
||||
var_to_rec_field(Var, #state{prefix = []}) ->
|
||||
Var.
|
||||
|
||||
get_dec_fun(Var, Type, Options, State) ->
|
||||
case lists:keyfind(Var, 1, State#state.dec_mfas) of
|
||||
false when Type == 'list-multi'; Type == 'list-single' ->
|
||||
if Options /= [] ->
|
||||
Variants = [binary_to_atom(V, utf8)
|
||||
|| #xdata_option{value = V} <- Options],
|
||||
{undefined, dec_enum, [Variants]};
|
||||
true ->
|
||||
undefined
|
||||
end;
|
||||
false when Type == 'jid-multi'; Type == 'jid-single' ->
|
||||
{undefined, dec_jid, []};
|
||||
false when Type == boolean ->
|
||||
{undefined, dec_bool, []};
|
||||
false ->
|
||||
undefined;
|
||||
{Var, {M, F, A}} ->
|
||||
{M, F, A};
|
||||
{Var, {dec_bool, []}} ->
|
||||
{undefined, dec_bool, []};
|
||||
{Var, {not_empty, []}} ->
|
||||
{undefined, not_empty, []};
|
||||
{Var, {dec_enum, [Variants]}} ->
|
||||
{undefined, dec_enum, [Variants]};
|
||||
{Var, {dec_int, Args}} ->
|
||||
{undefined, dec_int, Args};
|
||||
{Var, {dec_enum_int, Args}} ->
|
||||
{undefined, dec_enum_int, Args};
|
||||
{Var, {dec_jid, []}} ->
|
||||
{undefined, dec_jid, []}
|
||||
end.
|
||||
|
||||
get_enc_fun(Var, Type, Options, State) ->
|
||||
case get_dec_fun(Var, Type, Options, State) of
|
||||
{undefined, dec_enum, _} ->
|
||||
{undefined, enc_enum, []};
|
||||
{undefined, dec_bool, _} ->
|
||||
{undefined, enc_bool, []};
|
||||
{undefined, dec_int, _} ->
|
||||
{undefined, enc_int, []};
|
||||
{undefined, dec_enum_int, _} ->
|
||||
{undefined, enc_enum_int, []};
|
||||
{undefined, dec_jid, _} ->
|
||||
{undefined, enc_jid, []};
|
||||
_ ->
|
||||
case lists:keyfind(Var, 1, State#state.enc_mfas) of
|
||||
false ->
|
||||
undefined;
|
||||
{Var, {M, F, A}} ->
|
||||
{M, F, A};
|
||||
{Var, {enc_bool, []}} ->
|
||||
{undefined, enc_bool, []};
|
||||
{Var, {dec_enum, _}} ->
|
||||
{undefined, enc_enum, []};
|
||||
{Var, {enc_int, _}} ->
|
||||
{undefined, enc_int, []};
|
||||
{Var, {dec_enum_int, _}} ->
|
||||
{undefined, enc_enum_int, []};
|
||||
{Var, {enc_jid, _}} ->
|
||||
{undefined, enc_jid, []}
|
||||
end
|
||||
end.
|
||||
|
||||
mk_typespec(#xdata_field{type = Type, var = Var} = Field, State) ->
|
||||
Spec0 = get_typespec(Field, State),
|
||||
Spec1 = case is_complex_type(Spec0) of
|
||||
true ->
|
||||
io_lib:format("'~s'()", [var_to_rec_field(Var, State)]);
|
||||
false ->
|
||||
Spec0
|
||||
end,
|
||||
if ?is_multi_type(Type) -> "[" ++ Spec1 ++ "]";
|
||||
true -> Spec1
|
||||
end.
|
||||
|
||||
get_typespec(#xdata_field{var = Var, type = Type, options = Options}, State) ->
|
||||
case lists:keyfind(Var, 1, State#state.specs) of
|
||||
false ->
|
||||
case get_dec_fun(Var, Type, Options, State) of
|
||||
{undefined, dec_enum, Args} ->
|
||||
enum_spec(Args);
|
||||
{undefined, dec_bool, _} ->
|
||||
"boolean()";
|
||||
{undefined, dec_jid, _} ->
|
||||
"jid:jid()";
|
||||
{undefined, dec_int, Args} ->
|
||||
int_spec(Args);
|
||||
{undefined, dec_enum_int, [Variants|T]} ->
|
||||
enum_spec([Variants]) ++ " | " ++ int_spec(T);
|
||||
_ ->
|
||||
"binary()"
|
||||
end;
|
||||
{Var, Spec} ->
|
||||
Spec
|
||||
end.
|
||||
|
||||
-spec is_complex_type(string()) -> boolean().
|
||||
is_complex_type(Spec) ->
|
||||
string:chr(Spec, $|) /= 0.
|
||||
|
||||
int_spec([]) ->
|
||||
"integer()";
|
||||
int_spec([From, To]) ->
|
||||
if From /= infinity, To /= infinity ->
|
||||
io_lib:format("~p..~p", [From, To]);
|
||||
From > 0 ->
|
||||
"pos_integer()";
|
||||
From == 0 ->
|
||||
"non_neg_integer()";
|
||||
true ->
|
||||
"integer()"
|
||||
end.
|
||||
|
||||
enum_spec([Variants]) ->
|
||||
string:join([atom_to_list(V) || V <- Variants], " | ").
|
||||
|
||||
is_required(Var, State) ->
|
||||
lists:member(Var, State#state.required) orelse
|
||||
proplists:get_bool(Var, State#state.required).
|
||||
|
||||
normalize(#xmlel{name = Name, attrs = Attrs, children = Els}) ->
|
||||
#xmlel{name = Name,
|
||||
attrs = [normalize(Attr) || Attr <- Attrs],
|
||||
children = [normalize(El) || El <- Els]};
|
||||
normalize({Key, Data}) ->
|
||||
{Key, normalize(Data)};
|
||||
normalize(Txt) when is_binary(Txt) ->
|
||||
case re:split(Txt, "[\\s\\r\\n\\t]+", [trim, {return, list}]) of
|
||||
[""|T] ->
|
||||
list_to_binary(string:join(T, " "));
|
||||
T ->
|
||||
list_to_binary(string:join(T, " "))
|
||||
end.
|
827
src/xmpp.erl
827
src/xmpp.erl
@ -1,827 +0,0 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @copyright (C) 2015, Evgeny Khramtsov
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 9 Dec 2015 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(xmpp).
|
||||
|
||||
%% API
|
||||
-export([make_iq_result/1, make_iq_result/2, make_error/2,
|
||||
decode/1, decode/3, encode/1, encode/2,
|
||||
get_type/1, get_to/1, get_from/1, get_id/1,
|
||||
get_lang/1, get_error/1, get_els/1, get_ns/1,
|
||||
set_type/2, set_to/2, set_from/2, set_id/2,
|
||||
set_lang/2, set_error/2, set_els/2, set_from_to/3,
|
||||
format_error/1, is_stanza/1, set_subtag/2, get_subtag/2,
|
||||
remove_subtag/2, has_subtag/2, decode_els/1, decode_els/3,
|
||||
pp/1, get_name/1, get_text/1, mk_text/1, mk_text/2,
|
||||
is_known_tag/1, is_known_tag/2, append_subtags/2]).
|
||||
|
||||
%% XMPP errors
|
||||
-export([err_bad_request/0, err_bad_request/2,
|
||||
err_conflict/0, err_conflict/2,
|
||||
err_feature_not_implemented/0, err_feature_not_implemented/2,
|
||||
err_forbidden/0, err_forbidden/2,
|
||||
err_gone/0, err_gone/2,
|
||||
err_internal_server_error/0, err_internal_server_error/2,
|
||||
err_item_not_found/0, err_item_not_found/2,
|
||||
err_jid_malformed/0, err_jid_malformed/2,
|
||||
err_not_acceptable/0, err_not_acceptable/2,
|
||||
err_not_allowed/0, err_not_allowed/2,
|
||||
err_not_authorized/0, err_not_authorized/2,
|
||||
err_payment_required/0, err_payment_required/2,
|
||||
err_policy_violation/0, err_policy_violation/2,
|
||||
err_recipient_unavailable/0, err_recipient_unavailable/2,
|
||||
err_redirect/0, err_redirect/2,
|
||||
err_registration_required/0, err_registration_required/2,
|
||||
err_remote_server_not_found/0, err_remote_server_not_found/2,
|
||||
err_remote_server_timeout/0, err_remote_server_timeout/2,
|
||||
err_resource_constraint/0, err_resource_constraint/2,
|
||||
err_service_unavailable/0, err_service_unavailable/2,
|
||||
err_subscription_required/0, err_subscription_required/2,
|
||||
err_undefined_condition/1, err_undefined_condition/3,
|
||||
err_unexpected_request/0, err_unexpected_request/2]).
|
||||
|
||||
%% XMPP stream errors
|
||||
-export([serr_bad_format/0, serr_bad_format/2,
|
||||
serr_bad_namespace_prefix/0, serr_bad_namespace_prefix/2,
|
||||
serr_conflict/0, serr_conflict/2,
|
||||
serr_connection_timeout/0, serr_connection_timeout/2,
|
||||
serr_host_gone/0, serr_host_gone/2,
|
||||
serr_host_unknown/0, serr_host_unknown/2,
|
||||
serr_improper_addressing/0, serr_improper_addressing/2,
|
||||
serr_internal_server_error/0, serr_internal_server_error/2,
|
||||
serr_invalid_from/0, serr_invalid_from/2,
|
||||
serr_invalid_id/0, serr_invalid_id/2,
|
||||
serr_invalid_namespace/0, serr_invalid_namespace/2,
|
||||
serr_invalid_xml/0, serr_invalid_xml/2,
|
||||
serr_not_authorized/0, serr_not_authorized/2,
|
||||
serr_not_well_formed/0, serr_not_well_formed/2,
|
||||
serr_policy_violation/0, serr_policy_violation/2,
|
||||
serr_remote_connection_failed/0, serr_remote_connection_failed/2,
|
||||
serr_reset/0, serr_reset/2,
|
||||
serr_resource_constraint/0, serr_resource_constraint/2,
|
||||
serr_restricted_xml/0, serr_restricted_xml/2,
|
||||
serr_see_other_host/0, serr_see_other_host/2,
|
||||
serr_system_shutdown/0, serr_system_shutdown/2,
|
||||
serr_undefined_condition/0, serr_undefined_condition/2,
|
||||
serr_unsupported_encoding/0, serr_unsupported_encoding/2,
|
||||
serr_unsupported_stanza_type/0, serr_unsupported_stanza_type/2,
|
||||
serr_unsupported_version/0, serr_unsupported_version/2]).
|
||||
|
||||
-include("xmpp.hrl").
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
-spec make_iq_result(iq()) -> iq().
|
||||
make_iq_result(IQ) ->
|
||||
make_iq_result(IQ, undefined).
|
||||
|
||||
-spec make_iq_result(iq(), xmpp_element() | xmlel() | undefined) -> iq().
|
||||
make_iq_result(#iq{type = Type, from = From, to = To} = IQ, El)
|
||||
when Type == get; Type == set ->
|
||||
SubEls = if El == undefined -> [];
|
||||
true -> [El]
|
||||
end,
|
||||
IQ#iq{type = result, to = From, from = To, sub_els = SubEls}.
|
||||
|
||||
-spec make_error(message(), stanza_error() | xmlel()) -> message();
|
||||
(presence(), stanza_error() | xmlel()) -> presence();
|
||||
(iq(), stanza_error() | xmlel()) -> iq();
|
||||
(xmlel(), stanza_error() | xmlel()) -> xmlel().
|
||||
make_error(#message{type = Type, from = From, to = To, sub_els = Els} = Msg,
|
||||
Err) when Type /= error ->
|
||||
Msg#message{type = error, from = To, to = From, sub_els = Els ++ [Err]};
|
||||
make_error(#presence{type = Type, from = From, to = To, sub_els = Els} = Pres,
|
||||
Err) when Type /= error ->
|
||||
Pres#presence{type = error, from = To, to = From, sub_els = Els ++ [Err]};
|
||||
make_error(#iq{type = Type, from = From, to = To, sub_els = Els} = IQ,
|
||||
Err) when Type /= result, Type /= error ->
|
||||
IQ#iq{type = error, from = To, to = From, sub_els = Els ++ [Err]};
|
||||
make_error(#xmlel{attrs = Attrs, children = Els} = El, Err) ->
|
||||
To = fxml:get_attr(<<"to">>, Attrs),
|
||||
From = fxml:get_attr(<<"from">>, Attrs),
|
||||
Attrs1 = case To of
|
||||
{value, T} ->
|
||||
lists:keystore(<<"from">>, 1, Attrs, {<<"from">>, T});
|
||||
_ ->
|
||||
Attrs
|
||||
end,
|
||||
Attrs2 = case From of
|
||||
{value, F} ->
|
||||
lists:keystore(<<"to">>, 1, Attrs1, {<<"to">>, F});
|
||||
_ ->
|
||||
Attrs
|
||||
end,
|
||||
Attrs3 = lists:keystore(<<"type">>, 1, Attrs2, {<<"type">>, <<"error">>}),
|
||||
El#xmlel{attrs = Attrs3, children = Els ++ [encode(Err, ?NS_CLIENT)]}.
|
||||
|
||||
-spec get_id(iq() | message() | presence() | xmlel()) -> binary().
|
||||
get_id(#iq{id = ID}) -> ID;
|
||||
get_id(#message{id = ID}) -> ID;
|
||||
get_id(#presence{id = ID}) -> ID;
|
||||
get_id(#xmlel{attrs = Attrs}) -> fxml:get_attr_s(<<"id">>, Attrs).
|
||||
|
||||
-spec get_type(iq()) -> iq_type();
|
||||
(message()) -> message_type();
|
||||
(presence()) -> presence_type();
|
||||
(xmlel()) -> binary().
|
||||
get_type(#iq{type = T}) -> T;
|
||||
get_type(#message{type = T}) -> T;
|
||||
get_type(#presence{type = T}) -> T;
|
||||
get_type(#xmlel{attrs = Attrs}) -> fxml:get_attr_s(<<"type">>, Attrs).
|
||||
|
||||
-spec get_lang(iq() | message() | presence() | xmlel()) -> binary().
|
||||
get_lang(#iq{lang = L}) -> L;
|
||||
get_lang(#message{lang = L}) -> L;
|
||||
get_lang(#presence{lang = L}) -> L;
|
||||
get_lang(#xmlel{attrs = Attrs}) -> fxml:get_attr_s(<<"xml:lang">>, Attrs).
|
||||
|
||||
-spec get_from(iq() | message() | presence()) -> undefined | jid:jid().
|
||||
get_from(#iq{from = J}) -> J;
|
||||
get_from(#message{from = J}) -> J;
|
||||
get_from(#presence{from = J}) -> J.
|
||||
|
||||
-spec get_to(iq() | message() | presence()) -> undefined | jid:jid().
|
||||
get_to(#iq{to = J}) -> J;
|
||||
get_to(#message{to = J}) -> J;
|
||||
get_to(#presence{to = J}) -> J.
|
||||
|
||||
-spec get_error(iq() | message() | presence()) -> undefined | stanza_error().
|
||||
get_error(Stanza) ->
|
||||
case get_subtag(Stanza, #stanza_error{}) of
|
||||
false -> undefined;
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
-spec get_els(iq() | message() | presence()) -> [xmpp_element() | xmlel()];
|
||||
(xmlel()) -> [xmlel()].
|
||||
get_els(#iq{sub_els = Els}) -> Els;
|
||||
get_els(#message{sub_els = Els}) -> Els;
|
||||
get_els(#presence{sub_els = Els}) -> Els;
|
||||
get_els(#xmlel{children = Els}) -> [El || El = #xmlel{} <- Els].
|
||||
|
||||
-spec set_id(iq(), binary()) -> iq();
|
||||
(message(), binary()) -> message();
|
||||
(presence(), binary()) -> presence().
|
||||
set_id(#iq{} = IQ, I) -> IQ#iq{id = I};
|
||||
set_id(#message{} = Msg, I) -> Msg#message{id = I};
|
||||
set_id(#presence{} = Pres, I) -> Pres#presence{id = I}.
|
||||
|
||||
-spec set_type(iq(), iq_type()) -> iq();
|
||||
(message(), message_type()) -> message();
|
||||
(presence(), presence_type()) -> presence().
|
||||
set_type(#iq{} = IQ, T) -> IQ#iq{type = T};
|
||||
set_type(#message{} = Msg, T) -> Msg#message{type = T};
|
||||
set_type(#presence{} = Pres, T) -> Pres#presence{type = T}.
|
||||
|
||||
-spec set_lang(iq(), binary()) -> iq();
|
||||
(message(), binary()) -> message();
|
||||
(presence(), binary()) -> presence().
|
||||
set_lang(#iq{} = IQ, L) -> IQ#iq{lang = L};
|
||||
set_lang(#message{} = Msg, L) -> Msg#message{lang = L};
|
||||
set_lang(#presence{} = Pres, L) -> Pres#presence{lang = L}.
|
||||
|
||||
-spec set_from(iq(), jid:jid()) -> iq();
|
||||
(message(), jid:jid()) -> message();
|
||||
(presence(), jid:jid()) -> presence().
|
||||
set_from(#iq{} = IQ, J) -> IQ#iq{from = J};
|
||||
set_from(#message{} = Msg, J) -> Msg#message{from = J};
|
||||
set_from(#presence{} = Pres, J) -> Pres#presence{from = J}.
|
||||
|
||||
-spec set_to(iq(), jid:jid()) -> iq();
|
||||
(message(), jid:jid()) -> message();
|
||||
(presence(), jid:jid()) -> presence().
|
||||
set_to(#iq{} = IQ, J) -> IQ#iq{to = J};
|
||||
set_to(#message{} = Msg, J) -> Msg#message{to = J};
|
||||
set_to(#presence{} = Pres, J) -> Pres#presence{to = J}.
|
||||
|
||||
-spec set_from_to(iq(), undefined | jid:jid(), undefined | jid:jid()) -> iq();
|
||||
(message(), undefined | jid:jid(), undefined | jid:jid()) -> message();
|
||||
(presence(), undefined | jid:jid(), undefined | jid:jid()) -> presence().
|
||||
set_from_to(#iq{} = IQ, F, T) -> IQ#iq{from = F, to = T};
|
||||
set_from_to(#message{} = Msg, F, T) -> Msg#message{from = F, to = T};
|
||||
set_from_to(#presence{} = Pres, F, T) -> Pres#presence{from = F, to = T}.
|
||||
|
||||
-spec set_error(iq(), stanza_error()) -> iq();
|
||||
(message(), stanza_error()) -> message();
|
||||
(presence(), stanza_error()) -> presence().
|
||||
set_error(Stanza, E) -> set_subtag(Stanza, E).
|
||||
|
||||
-spec set_els(iq(), [xmpp_element() | xmlel()]) -> iq();
|
||||
(message(), [xmpp_element() | xmlel()]) -> message();
|
||||
(presence(), [xmpp_element() | xmlel()]) -> presence().
|
||||
set_els(#iq{} = IQ, Els) -> IQ#iq{sub_els = Els};
|
||||
set_els(#message{} = Msg, Els) -> Msg#message{sub_els = Els};
|
||||
set_els(#presence{} = Pres, Els) -> Pres#presence{sub_els = Els}.
|
||||
|
||||
-spec get_ns(xmpp_element() | xmlel()) -> binary().
|
||||
get_ns(#xmlel{attrs = Attrs}) ->
|
||||
fxml:get_attr_s(<<"xmlns">>, Attrs);
|
||||
get_ns(Pkt) ->
|
||||
xmpp_codec:get_ns(Pkt).
|
||||
|
||||
-spec get_name(xmpp_element() | xmlel()) -> binary().
|
||||
get_name(#xmlel{name = Name}) ->
|
||||
Name;
|
||||
get_name(Pkt) ->
|
||||
xmpp_codec:get_name(Pkt).
|
||||
|
||||
-spec decode(xmlel() | xmpp_element()) -> {ok, xmpp_element()} | {error, any()}.
|
||||
decode(El) ->
|
||||
decode(El, ?NS_CLIENT, []).
|
||||
|
||||
-spec decode(xmlel() | xmpp_element(), binary(), [proplists:property()]) ->
|
||||
{ok, xmpp_element()} | {error, any()}.
|
||||
decode(#xmlel{} = El, TopXMLNS, Opts) ->
|
||||
xmpp_codec:decode(El, TopXMLNS, Opts);
|
||||
decode(Pkt, _, _) ->
|
||||
Pkt.
|
||||
|
||||
-spec decode_els(iq()) -> iq();
|
||||
(message()) -> message();
|
||||
(presence()) -> presence().
|
||||
decode_els(Stanza) ->
|
||||
decode_els(Stanza, ?NS_CLIENT, fun is_known_tag/1).
|
||||
|
||||
-type match_fun() :: fun((xmlel()) -> boolean()).
|
||||
-spec decode_els(iq(), binary(), match_fun()) -> iq();
|
||||
(message(), binary(), match_fun()) -> message();
|
||||
(presence(), binary(), match_fun()) -> presence().
|
||||
decode_els(Stanza, TopXMLNS, MatchFun) ->
|
||||
Els = lists:map(
|
||||
fun(#xmlel{} = El) ->
|
||||
case MatchFun(El) of
|
||||
true -> decode(El, TopXMLNS, []);
|
||||
false -> El
|
||||
end;
|
||||
(Pkt) ->
|
||||
Pkt
|
||||
end, get_els(Stanza)),
|
||||
set_els(Stanza, Els).
|
||||
|
||||
-spec encode(xmpp_element() | xmlel()) -> xmlel().
|
||||
encode(Pkt) ->
|
||||
encode(Pkt, <<>>).
|
||||
|
||||
-spec encode(xmpp_element() | xmlel(), binary()) -> xmlel().
|
||||
encode(Pkt, TopXMLNS) ->
|
||||
xmpp_codec:encode(Pkt, TopXMLNS).
|
||||
|
||||
-spec is_known_tag(xmlel()) -> boolean().
|
||||
is_known_tag(El) ->
|
||||
is_known_tag(El, ?NS_CLIENT).
|
||||
|
||||
-spec is_known_tag(xmlel(), binary()) -> boolean().
|
||||
is_known_tag(El, TopXMLNS) ->
|
||||
xmpp_codec:is_known_tag(El, TopXMLNS).
|
||||
|
||||
format_error(Reason) ->
|
||||
xmpp_codec:format_error(Reason).
|
||||
|
||||
-spec is_stanza(any()) -> boolean().
|
||||
is_stanza(#message{}) -> true;
|
||||
is_stanza(#iq{}) -> true;
|
||||
is_stanza(#presence{}) -> true;
|
||||
is_stanza(#xmlel{name = Name}) ->
|
||||
(Name == <<"iq">>) or (Name == <<"message">>) or (Name == <<"presence">>);
|
||||
is_stanza(_) -> false.
|
||||
|
||||
-spec set_subtag(iq(), xmpp_element()) -> iq();
|
||||
(message(), xmpp_element()) -> message();
|
||||
(presence(), xmpp_element()) -> presence().
|
||||
set_subtag(Stanza, Tag) ->
|
||||
TagName = xmpp_codec:get_name(Tag),
|
||||
XMLNS = xmpp_codec:get_ns(Tag),
|
||||
Els = get_els(Stanza),
|
||||
NewEls = set_subtag(Els, Tag, TagName, XMLNS),
|
||||
set_els(Stanza, NewEls).
|
||||
|
||||
set_subtag([El|Els], Tag, TagName, XMLNS) ->
|
||||
case match_tag(El, TagName, XMLNS) of
|
||||
true ->
|
||||
[Tag|Els];
|
||||
false ->
|
||||
[El|set_subtag(Els, Tag, TagName, XMLNS)]
|
||||
end;
|
||||
set_subtag([], Tag, _, _) ->
|
||||
[Tag].
|
||||
|
||||
-spec get_subtag(stanza(), xmpp_element()) -> xmpp_element() | false.
|
||||
get_subtag(Stanza, Tag) ->
|
||||
Els = get_els(Stanza),
|
||||
TagName = xmpp_codec:get_name(Tag),
|
||||
XMLNS = xmpp_codec:get_ns(Tag),
|
||||
get_subtag(Els, TagName, XMLNS).
|
||||
|
||||
get_subtag([El|Els], TagName, XMLNS) ->
|
||||
case match_tag(El, TagName, XMLNS) of
|
||||
true ->
|
||||
try
|
||||
decode(El)
|
||||
catch _:{xmpp_codec, _Why} ->
|
||||
get_subtag(Els, TagName, XMLNS)
|
||||
end;
|
||||
false ->
|
||||
get_subtag(Els, TagName, XMLNS)
|
||||
end;
|
||||
get_subtag([], _, _) ->
|
||||
false.
|
||||
|
||||
-spec remove_subtag(iq(), xmpp_element()) -> iq();
|
||||
(message(), xmpp_element()) -> message();
|
||||
(presence(), xmpp_element()) -> presence().
|
||||
remove_subtag(Stanza, Tag) ->
|
||||
Els = get_els(Stanza),
|
||||
TagName = xmpp_codec:get_name(Tag),
|
||||
XMLNS = xmpp_codec:get_ns(Tag),
|
||||
NewEls = remove_subtag(Els, TagName, XMLNS),
|
||||
set_els(Stanza, NewEls).
|
||||
|
||||
remove_subtag([El|Els], TagName, XMLNS) ->
|
||||
case match_tag(El, TagName, XMLNS) of
|
||||
true ->
|
||||
remove_subtag(Els, TagName, XMLNS);
|
||||
false ->
|
||||
[El|remove_subtag(Els, TagName, XMLNS)]
|
||||
end;
|
||||
remove_subtag([], _, _) ->
|
||||
[].
|
||||
|
||||
-spec has_subtag(stanza(), xmpp_element()) -> boolean().
|
||||
has_subtag(Stanza, Tag) ->
|
||||
Els = get_els(Stanza),
|
||||
TagName = xmpp_codec:get_name(Tag),
|
||||
XMLNS = xmpp_codec:get_ns(Tag),
|
||||
has_subtag(Els, TagName, XMLNS).
|
||||
|
||||
has_subtag([El|Els], TagName, XMLNS) ->
|
||||
case match_tag(El, TagName, XMLNS) of
|
||||
true ->
|
||||
true;
|
||||
false ->
|
||||
has_subtag(Els, TagName, XMLNS)
|
||||
end;
|
||||
has_subtag([], _, _) ->
|
||||
false.
|
||||
|
||||
-spec append_subtags(stanza(), [xmpp_element() | xmlel()]) -> stanza().
|
||||
append_subtags(Stanza, Tags) ->
|
||||
Els = get_els(Stanza),
|
||||
set_els(Stanza, Els ++ Tags).
|
||||
|
||||
-spec get_text([text()]) -> binary().
|
||||
get_text([]) -> <<"">>;
|
||||
get_text([#text{data = Data}|_]) -> Data.
|
||||
|
||||
-spec mk_text(binary()) -> [text()].
|
||||
mk_text(Text) ->
|
||||
mk_text(Text, <<"">>).
|
||||
|
||||
-spec mk_text(binary(), binary()) -> [text()].
|
||||
mk_text(<<"">>, _) ->
|
||||
[];
|
||||
mk_text(Text, Lang) ->
|
||||
[#text{lang = Lang,
|
||||
data = translate:translate(Lang, Text)}].
|
||||
|
||||
-spec pp(any()) -> iodata().
|
||||
pp(Term) ->
|
||||
xmpp_codec:pp(Term).
|
||||
|
||||
%%%===================================================================
|
||||
%%% Functions to construct general XMPP errors
|
||||
%%%===================================================================
|
||||
-spec err_bad_request() -> stanza_error().
|
||||
err_bad_request() ->
|
||||
err(modify, 'bad-request', 400).
|
||||
|
||||
-spec err_bad_request(binary(), binary()) -> stanza_error().
|
||||
err_bad_request(Text, Lang) ->
|
||||
err(modify, 'bad-request', 400, Text, Lang).
|
||||
|
||||
-spec err_conflict() -> stanza_error().
|
||||
err_conflict() ->
|
||||
err(cancel, 'conflict', 409).
|
||||
|
||||
-spec err_conflict(binary(), binary()) -> stanza_error().
|
||||
err_conflict(Text, Lang) ->
|
||||
err(cancel, 'conflict', 409, Text, Lang).
|
||||
|
||||
-spec err_feature_not_implemented() -> stanza_error().
|
||||
err_feature_not_implemented() ->
|
||||
err(cancel, 'feature-not-implemented', 501).
|
||||
|
||||
-spec err_feature_not_implemented(binary(), binary()) -> stanza_error().
|
||||
err_feature_not_implemented(Text, Lang) ->
|
||||
err(cancel, 'feature-not-implemented', 501, Text, Lang).
|
||||
|
||||
-spec err_forbidden() -> stanza_error().
|
||||
err_forbidden() ->
|
||||
err(auth, 'forbidden', 403).
|
||||
|
||||
-spec err_forbidden(binary(), binary()) -> stanza_error().
|
||||
err_forbidden(Text, Lang) ->
|
||||
err(auth, 'forbidden', 403, Text, Lang).
|
||||
|
||||
%% RFC 6120 says error type SHOULD be "cancel".
|
||||
%% RFC 3920 and XEP-0082 says it SHOULD be "modify".
|
||||
-spec err_gone() -> stanza_error().
|
||||
err_gone() ->
|
||||
err(modify, 'gone', 302).
|
||||
|
||||
-spec err_gone(binary(), binary()) -> stanza_error().
|
||||
err_gone(Text, Lang) ->
|
||||
err(modify, 'gone', 302, Text, Lang).
|
||||
|
||||
%% RFC 6120 sasy error type SHOULD be "cancel".
|
||||
%% RFC 3920 and XEP-0082 says it SHOULD be "wait".
|
||||
-spec err_internal_server_error() -> stanza_error().
|
||||
err_internal_server_error() ->
|
||||
err(wait, 'internal-server-error', 500).
|
||||
|
||||
-spec err_internal_server_error(binary(), binary()) -> stanza_error().
|
||||
err_internal_server_error(Text, Lang) ->
|
||||
err(wait, 'internal-server-error', 500, Text, Lang).
|
||||
|
||||
-spec err_item_not_found() -> stanza_error().
|
||||
err_item_not_found() ->
|
||||
err(cancel, 'item-not-found', 404).
|
||||
|
||||
-spec err_item_not_found(binary(), binary()) -> stanza_error().
|
||||
err_item_not_found(Text, Lang) ->
|
||||
err(cancel, 'item-not-found', 404, Text, Lang).
|
||||
|
||||
-spec err_jid_malformed() -> stanza_error().
|
||||
err_jid_malformed() ->
|
||||
err(modify, 'jid-malformed', 400).
|
||||
|
||||
-spec err_jid_malformed(binary(), binary()) -> stanza_error().
|
||||
err_jid_malformed(Text, Lang) ->
|
||||
err(modify, 'jid-malformed', 400, Text, Lang).
|
||||
|
||||
-spec err_not_acceptable() -> stanza_error().
|
||||
err_not_acceptable() ->
|
||||
err(modify, 'not-acceptable', 406).
|
||||
|
||||
-spec err_not_acceptable(binary(), binary()) -> stanza_error().
|
||||
err_not_acceptable(Text, Lang) ->
|
||||
err(modify, 'not-acceptable', 406, Text, Lang).
|
||||
|
||||
-spec err_not_allowed() -> stanza_error().
|
||||
err_not_allowed() ->
|
||||
err(cancel, 'not-allowed', 405).
|
||||
|
||||
-spec err_not_allowed(binary(), binary()) -> stanza_error().
|
||||
err_not_allowed(Text, Lang) ->
|
||||
err(cancel, 'not-allowed', 405, Text, Lang).
|
||||
|
||||
-spec err_not_authorized() -> stanza_error().
|
||||
err_not_authorized() ->
|
||||
err(auth, 'not-authorized', 401).
|
||||
|
||||
-spec err_not_authorized(binary(), binary()) -> stanza_error().
|
||||
err_not_authorized(Text, Lang) ->
|
||||
err(auth, 'not-authorized', 401, Text, Lang).
|
||||
|
||||
-spec err_payment_required() -> stanza_error().
|
||||
err_payment_required() ->
|
||||
err(auth, 'not-authorized', 402).
|
||||
|
||||
-spec err_payment_required(binary(), binary()) -> stanza_error().
|
||||
err_payment_required(Text, Lang) ->
|
||||
err(auth, 'not-authorized', 402, Text, Lang).
|
||||
|
||||
%% <policy-violation/> is defined in neither RFC 3920 nor XEP-0086.
|
||||
%% We choose '403' error code (as in <forbidden/>).
|
||||
-spec err_policy_violation() -> stanza_error().
|
||||
err_policy_violation() ->
|
||||
err(modify, 'policy-violation', 403).
|
||||
|
||||
-spec err_policy_violation(binary(), binary()) -> stanza_error().
|
||||
err_policy_violation(Text, Lang) ->
|
||||
err(modify, 'policy-violation', 403, Text, Lang).
|
||||
|
||||
-spec err_recipient_unavailable() -> stanza_error().
|
||||
err_recipient_unavailable() ->
|
||||
err(wait, 'recipient-unavailable', 404).
|
||||
|
||||
-spec err_recipient_unavailable(binary(), binary()) -> stanza_error().
|
||||
err_recipient_unavailable(Text, Lang) ->
|
||||
err(wait, 'recipient-unavailable', 404, Text, Lang).
|
||||
|
||||
-spec err_redirect() -> stanza_error().
|
||||
err_redirect() ->
|
||||
err(modify, 'redirect', 302).
|
||||
|
||||
-spec err_redirect(binary(), binary()) -> stanza_error().
|
||||
err_redirect(Text, Lang) ->
|
||||
err(modify, 'redirect', 302, Text, Lang).
|
||||
|
||||
-spec err_registration_required() -> stanza_error().
|
||||
err_registration_required() ->
|
||||
err(auth, 'registration-required', 407).
|
||||
|
||||
-spec err_registration_required(binary(), binary()) -> stanza_error().
|
||||
err_registration_required(Text, Lang) ->
|
||||
err(auth, 'registration-required', 407, Text, Lang).
|
||||
|
||||
-spec err_remote_server_not_found() -> stanza_error().
|
||||
err_remote_server_not_found() ->
|
||||
err(cancel, 'remote-server-not-found', 404).
|
||||
|
||||
-spec err_remote_server_not_found(binary(), binary()) -> stanza_error().
|
||||
err_remote_server_not_found(Text, Lang) ->
|
||||
err(cancel, 'remote-server-not-found', 404, Text, Lang).
|
||||
|
||||
-spec err_remote_server_timeout() -> stanza_error().
|
||||
err_remote_server_timeout() ->
|
||||
err(wait, 'remote-server-timeout', 504).
|
||||
|
||||
-spec err_remote_server_timeout(binary(), binary()) -> stanza_error().
|
||||
err_remote_server_timeout(Text, Lang) ->
|
||||
err(wait, 'remote-server-timeout', 504, Text, Lang).
|
||||
|
||||
-spec err_resource_constraint() -> stanza_error().
|
||||
err_resource_constraint() ->
|
||||
err(wait, 'resource-constraint', 500).
|
||||
|
||||
-spec err_resource_constraint(binary(), binary()) -> stanza_error().
|
||||
err_resource_constraint(Text, Lang) ->
|
||||
err(wait, 'resource-constraint', 500, Text, Lang).
|
||||
|
||||
-spec err_service_unavailable() -> stanza_error().
|
||||
err_service_unavailable() ->
|
||||
err(cancel, 'service-unavailable', 503).
|
||||
|
||||
-spec err_service_unavailable(binary(), binary()) -> stanza_error().
|
||||
err_service_unavailable(Text, Lang) ->
|
||||
err(cancel, 'service-unavailable', 503, Text, Lang).
|
||||
|
||||
-spec err_subscription_required() -> stanza_error().
|
||||
err_subscription_required() ->
|
||||
err(auth, 'subscription-required', 407).
|
||||
|
||||
-spec err_subscription_required(binary(), binary()) -> stanza_error().
|
||||
err_subscription_required(Text, Lang) ->
|
||||
err(auth, 'subscription-required', 407, Text, Lang).
|
||||
|
||||
%% No error type is defined for <undefined-confition/>.
|
||||
%% Let user provide the type.
|
||||
-spec err_undefined_condition('auth' | 'cancel' | 'continue' |
|
||||
'modify' | 'wait') -> stanza_error().
|
||||
err_undefined_condition(Type) ->
|
||||
err(Type, 'undefined-condition', 500).
|
||||
|
||||
-spec err_undefined_condition('auth' | 'cancel' | 'continue' | 'modify' | 'wait',
|
||||
binary(), binary()) -> stanza_error().
|
||||
err_undefined_condition(Type, Text, Lang) ->
|
||||
err(Type, 'undefined-condition', 500, Text, Lang).
|
||||
|
||||
%% RFC 6120 says error type SHOULD be "wait" or "modify".
|
||||
%% RFC 3920 and XEP-0082 says it SHOULD be "wait".
|
||||
-spec err_unexpected_request() -> stanza_error().
|
||||
err_unexpected_request() ->
|
||||
err(wait, 'unexpected-request', 400).
|
||||
|
||||
-spec err_unexpected_request(binary(), binary()) -> stanza_error().
|
||||
err_unexpected_request(Text, Lang) ->
|
||||
err(wait, 'unexpected-request', 400, Text, Lang).
|
||||
|
||||
%%%===================================================================
|
||||
%%% Functions to construct stream errors
|
||||
%%%===================================================================
|
||||
-spec serr_bad_format() -> stream_error().
|
||||
serr_bad_format() ->
|
||||
serr('bad-format').
|
||||
|
||||
-spec serr_bad_format(binary(), binary()) -> stream_error().
|
||||
serr_bad_format(Text, Lang) ->
|
||||
serr('bad-format', Text, Lang).
|
||||
|
||||
-spec serr_bad_namespace_prefix() -> stream_error().
|
||||
serr_bad_namespace_prefix() ->
|
||||
serr('bad-namespace-prefix').
|
||||
|
||||
-spec serr_bad_namespace_prefix(binary(), binary()) -> stream_error().
|
||||
serr_bad_namespace_prefix(Text, Lang) ->
|
||||
serr('bad-namespace-prefix', Text, Lang).
|
||||
|
||||
-spec serr_conflict() -> stream_error().
|
||||
serr_conflict() ->
|
||||
serr('conflict').
|
||||
|
||||
-spec serr_conflict(binary(), binary()) -> stream_error().
|
||||
serr_conflict(Text, Lang) ->
|
||||
serr('conflict', Text, Lang).
|
||||
|
||||
-spec serr_connection_timeout() -> stream_error().
|
||||
serr_connection_timeout() ->
|
||||
serr('connection-timeout').
|
||||
|
||||
-spec serr_connection_timeout(binary(), binary()) -> stream_error().
|
||||
serr_connection_timeout(Text, Lang) ->
|
||||
serr('connection-timeout', Text, Lang).
|
||||
|
||||
-spec serr_host_gone() -> stream_error().
|
||||
serr_host_gone() ->
|
||||
serr('host-gone').
|
||||
|
||||
-spec serr_host_gone(binary(), binary()) -> stream_error().
|
||||
serr_host_gone(Text, Lang) ->
|
||||
serr('host-gone', Text, Lang).
|
||||
|
||||
-spec serr_host_unknown() -> stream_error().
|
||||
serr_host_unknown() ->
|
||||
serr('host-unknown').
|
||||
|
||||
-spec serr_host_unknown(binary(), binary()) -> stream_error().
|
||||
serr_host_unknown(Text, Lang) ->
|
||||
serr('host-unknown', Text, Lang).
|
||||
|
||||
-spec serr_improper_addressing() -> stream_error().
|
||||
serr_improper_addressing() ->
|
||||
serr('improper-addressing').
|
||||
|
||||
-spec serr_improper_addressing(binary(), binary()) -> stream_error().
|
||||
serr_improper_addressing(Text, Lang) ->
|
||||
serr('improper-addressing', Text, Lang).
|
||||
|
||||
-spec serr_internal_server_error() -> stream_error().
|
||||
serr_internal_server_error() ->
|
||||
serr('internal-server-error').
|
||||
|
||||
-spec serr_internal_server_error(binary(), binary()) -> stream_error().
|
||||
serr_internal_server_error(Text, Lang) ->
|
||||
serr('internal-server-error', Text, Lang).
|
||||
|
||||
-spec serr_invalid_from() -> stream_error().
|
||||
serr_invalid_from() ->
|
||||
serr('invalid-from').
|
||||
|
||||
-spec serr_invalid_from(binary(), binary()) -> stream_error().
|
||||
serr_invalid_from(Text, Lang) ->
|
||||
serr('invalid-from', Text, Lang).
|
||||
|
||||
-spec serr_invalid_id() -> stream_error().
|
||||
serr_invalid_id() ->
|
||||
serr('invalid-id').
|
||||
|
||||
-spec serr_invalid_id(binary(), binary()) -> stream_error().
|
||||
serr_invalid_id(Text, Lang) ->
|
||||
serr('invalid-id', Text, Lang).
|
||||
|
||||
-spec serr_invalid_namespace() -> stream_error().
|
||||
serr_invalid_namespace() ->
|
||||
serr('invalid-namespace').
|
||||
|
||||
-spec serr_invalid_namespace(binary(), binary()) -> stream_error().
|
||||
serr_invalid_namespace(Text, Lang) ->
|
||||
serr('invalid-namespace', Text, Lang).
|
||||
|
||||
-spec serr_invalid_xml() -> stream_error().
|
||||
serr_invalid_xml() ->
|
||||
serr('invalid-xml').
|
||||
|
||||
-spec serr_invalid_xml(binary(), binary()) -> stream_error().
|
||||
serr_invalid_xml(Text, Lang) ->
|
||||
serr('invalid-xml', Text, Lang).
|
||||
|
||||
-spec serr_not_authorized() -> stream_error().
|
||||
serr_not_authorized() ->
|
||||
serr('not-authorized').
|
||||
|
||||
-spec serr_not_authorized(binary(), binary()) -> stream_error().
|
||||
serr_not_authorized(Text, Lang) ->
|
||||
serr('not-authorized', Text, Lang).
|
||||
|
||||
-spec serr_not_well_formed() -> stream_error().
|
||||
serr_not_well_formed() ->
|
||||
serr('not-well-formed').
|
||||
|
||||
-spec serr_not_well_formed(binary(), binary()) -> stream_error().
|
||||
serr_not_well_formed(Text, Lang) ->
|
||||
serr('not-well-formed', Text, Lang).
|
||||
|
||||
-spec serr_policy_violation() -> stream_error().
|
||||
serr_policy_violation() ->
|
||||
serr('policy-violation').
|
||||
|
||||
-spec serr_policy_violation(binary(), binary()) -> stream_error().
|
||||
serr_policy_violation(Text, Lang) ->
|
||||
serr('policy-violation', Text, Lang).
|
||||
|
||||
-spec serr_remote_connection_failed() -> stream_error().
|
||||
serr_remote_connection_failed() ->
|
||||
serr('remote-connection-failed').
|
||||
|
||||
-spec serr_remote_connection_failed(binary(), binary()) -> stream_error().
|
||||
serr_remote_connection_failed(Text, Lang) ->
|
||||
serr('remote-connection-failed', Text, Lang).
|
||||
|
||||
-spec serr_reset() -> stream_error().
|
||||
serr_reset() ->
|
||||
serr('reset').
|
||||
|
||||
-spec serr_reset(binary(), binary()) -> stream_error().
|
||||
serr_reset(Text, Lang) ->
|
||||
serr('reset', Text, Lang).
|
||||
|
||||
-spec serr_resource_constraint() -> stream_error().
|
||||
serr_resource_constraint() ->
|
||||
serr('resource-constraint').
|
||||
|
||||
-spec serr_resource_constraint(binary(), binary()) -> stream_error().
|
||||
serr_resource_constraint(Text, Lang) ->
|
||||
serr('resource-constraint', Text, Lang).
|
||||
|
||||
-spec serr_restricted_xml() -> stream_error().
|
||||
serr_restricted_xml() ->
|
||||
serr('restricted-xml').
|
||||
|
||||
-spec serr_restricted_xml(binary(), binary()) -> stream_error().
|
||||
serr_restricted_xml(Text, Lang) ->
|
||||
serr('restricted-xml', Text, Lang).
|
||||
|
||||
-spec serr_see_other_host() -> stream_error().
|
||||
serr_see_other_host() ->
|
||||
serr('see-other-host').
|
||||
|
||||
-spec serr_see_other_host(binary(), binary()) -> stream_error().
|
||||
serr_see_other_host(Text, Lang) ->
|
||||
serr('see-other-host', Text, Lang).
|
||||
|
||||
-spec serr_system_shutdown() -> stream_error().
|
||||
serr_system_shutdown() ->
|
||||
serr('system-shutdown').
|
||||
|
||||
-spec serr_system_shutdown(binary(), binary()) -> stream_error().
|
||||
serr_system_shutdown(Text, Lang) ->
|
||||
serr('system-shutdown', Text, Lang).
|
||||
|
||||
-spec serr_undefined_condition() -> stream_error().
|
||||
serr_undefined_condition() ->
|
||||
serr('undefined-condition').
|
||||
|
||||
-spec serr_undefined_condition(binary(), binary()) -> stream_error().
|
||||
serr_undefined_condition(Text, Lang) ->
|
||||
serr('undefined-condition', Text, Lang).
|
||||
|
||||
-spec serr_unsupported_encoding() -> stream_error().
|
||||
serr_unsupported_encoding() ->
|
||||
serr('unsupported-encoding').
|
||||
|
||||
-spec serr_unsupported_encoding(binary(), binary()) -> stream_error().
|
||||
serr_unsupported_encoding(Text, Lang) ->
|
||||
serr('unsupported-encoding', Text, Lang).
|
||||
|
||||
-spec serr_unsupported_stanza_type() -> stream_error().
|
||||
serr_unsupported_stanza_type() ->
|
||||
serr('unsupported-stanza-type').
|
||||
|
||||
-spec serr_unsupported_stanza_type(binary(), binary()) -> stream_error().
|
||||
serr_unsupported_stanza_type(Text, Lang) ->
|
||||
serr('unsupported-stanza-type', Text, Lang).
|
||||
|
||||
-spec serr_unsupported_version() -> stream_error().
|
||||
serr_unsupported_version() ->
|
||||
serr('unsupported-version').
|
||||
|
||||
-spec serr_unsupported_version(binary(), binary()) -> stream_error().
|
||||
serr_unsupported_version(Text, Lang) ->
|
||||
serr('unsupported-version', Text, Lang).
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
-spec err('auth' | 'cancel' | 'continue' | 'modify' | 'wait',
|
||||
atom() | gone() | redirect(), non_neg_integer()) -> stanza_error().
|
||||
err(Type, Reason, Code) ->
|
||||
#stanza_error{type = Type, reason = Reason, code = Code}.
|
||||
|
||||
-spec err('auth' | 'cancel' | 'continue' | 'modify' | 'wait',
|
||||
atom() | gone() | redirect(), non_neg_integer(),
|
||||
binary(), binary()) -> stanza_error().
|
||||
err(Type, Reason, Code, Text, Lang) ->
|
||||
#stanza_error{type = Type, reason = Reason, code = Code,
|
||||
text = #text{lang = Lang,
|
||||
data = translate:translate(Lang, Text)}}.
|
||||
|
||||
-spec serr(atom() | 'see-other-host'()) -> stream_error().
|
||||
serr(Reason) ->
|
||||
#stream_error{reason = Reason}.
|
||||
|
||||
-spec serr(atom() | 'see-other-host'(), binary(),
|
||||
binary()) -> stream_error().
|
||||
serr(Reason, Text, Lang) ->
|
||||
#stream_error{reason = Reason,
|
||||
text = #text{lang = Lang,
|
||||
data = translate:translate(Lang, Text)}}.
|
||||
|
||||
-spec match_tag(xmlel() | xmpp_element(), binary(), binary()) -> boolean().
|
||||
match_tag(El, TagName, XMLNS) ->
|
||||
get_name(El) == TagName andalso get_ns(El) == XMLNS.
|
34647
src/xmpp_codec.erl
34647
src/xmpp_codec.erl
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user