]> granicus.if.org Git - ejabberd/commitdiff
Initial version based on XML generator
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Mon, 18 Jul 2016 12:01:32 +0000 (15:01 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Mon, 18 Jul 2016 12:01:32 +0000 (15:01 +0300)
41 files changed:
Makefile.in
include/jid.hrl [new file with mode: 0644]
include/mod_privacy.hrl
include/xmpp.hrl [new file with mode: 0644]
include/xmpp_codec.hrl [moved from tools/xmpp_codec.hrl with 55% similarity]
src/cyrsasl.erl
src/cyrsasl_digest.erl
src/cyrsasl_oauth.erl
src/cyrsasl_plain.erl
src/cyrsasl_scram.erl
src/ejabberd_c2s.erl
src/ejabberd_frontend_socket.erl
src/ejabberd_local.erl
src/ejabberd_router.erl
src/ejabberd_sm.erl
src/ejabberd_socket.erl
src/ejabberd_system_monitor.erl
src/gen_iq_handler.erl
src/jid.erl
src/mod_caps.erl
src/mod_carboncopy.erl
src/mod_client_state.erl
src/mod_disco.erl
src/mod_echo.erl
src/mod_last.erl
src/mod_ping.erl
src/mod_privacy.erl
src/mod_privacy_mnesia.erl
src/mod_privacy_riak.erl
src/mod_privacy_sql.erl
src/mod_private.erl
src/mod_roster.erl
src/mod_time.erl
src/mod_vcard.erl
src/mod_vcard_xupdate.erl
src/mod_version.erl
src/translate.erl
src/xmpp.erl [new file with mode: 0644]
src/xmpp_codec.erl [moved from tools/xmpp_codec.erl with 68% similarity]
src/xmpp_util.erl [new file with mode: 0644]
tools/xmpp_codec.spec

index eb1474926fb9aef969a42a5bbf504195d5d902c4..07502f06e262badb69d6dcae6d80be6416935e96 100644 (file)
@@ -110,7 +110,7 @@ edoc:
 
 spec:
        $(ERL) -noinput +B -pa ebin -pa deps/*/ebin -eval \
-       'case fxml_gen:compile("tools/xmpp_codec.spec") of ok -> halt(0); _ -> halt(1) end.'
+       'case fxml_gen:compile("tools/xmpp_codec.spec", [{add_type_specs, xmpp_element}, {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))
 
diff --git a/include/jid.hrl b/include/jid.hrl
new file mode 100644 (file)
index 0000000..965985c
--- /dev/null
@@ -0,0 +1,17 @@
+%%%-------------------------------------------------------------------
+%%% @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()}).
index 8fe5abcca45d76697466e29892b158eb8424d20c..0d263d659b5e9c48c4bcc9d2e8386fdfb69ea8b5 100644 (file)
                   default = none        :: none | binary(),
                   lists = []            :: [{binary(), [listitem()]}]}).
 
--record(listitem, {type = none :: none | jid | group | subscription,
-                   value = none :: none | both | from | to | ljid() | binary(),
-                   action = allow :: allow | deny,
+-type privacy() :: #privacy{}.
+
+-record(listitem, {type = none :: listitem_type(),
+                   value = none :: listitem_value(),
+                   action = allow :: listitem_action(),
                    order = 0 :: integer(),
                    match_all = false :: boolean(),
                    match_iq = false :: boolean(),
@@ -33,6 +35,9 @@
                    match_presence_out = false :: boolean()}).
 
 -type listitem() :: #listitem{}.
+-type listitem_type() :: none | jid | group | subscription.
+-type listitem_value() :: none | both | from | to | ljid() | binary().
+-type listitem_action() :: allow | deny.
 
 -record(userlist, {name = none :: none | binary(),
                    list = [] :: [listitem()],
diff --git a/include/xmpp.hrl b/include/xmpp.hrl
new file mode 100644 (file)
index 0000000..e1bdaee
--- /dev/null
@@ -0,0 +1,29 @@
+%%%-------------------------------------------------------------------
+%%% @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").
+-ifdef(NO_EXT_LIB).
+-include("fxml.hrl").
+-else.
+-include_lib("fast_xml/include/fxml.hrl").
+-endif.
+
+-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))).
similarity index 55%
rename from tools/xmpp_codec.hrl
rename to include/xmpp_codec.hrl
index 6d4b750b6ad1506ca47cf21353dc6db930992360..64a185a30c2ceaeb3701a74be24c5924ec2833d2 100644 (file)
 %% Created automatically by XML generator (fxml_gen.erl)
 %% Source: xmpp_codec.spec
 
+-record(vcard_xupdate, {us :: {binary(), binary()},
+                       hash :: binary()}).
+-type vcard_xupdate() :: #vcard_xupdate{}.
+
 -record(chatstate, {type :: active | composing | gone | inactive | paused}).
+-type chatstate() :: #chatstate{}.
 
 -record(csi, {type :: active | inactive}).
+-type csi() :: #csi{}.
+
+-record(hint, {type :: 'no-copy' | 'no-store' | 'store' | 'no-permanent-store'}).
+-type hint() :: #hint{}.
 
 -record(feature_register, {}).
+-type feature_register() :: #feature_register{}.
 
 -record(sasl_success, {text :: any()}).
+-type sasl_success() :: #sasl_success{}.
 
 -record(mam_result, {xmlns :: binary(),
                      queryid :: binary(),
                      id :: binary(),
                      sub_els = [] :: [any()]}).
+-type mam_result() :: #mam_result{}.
 
 -record(rsm_first, {index :: non_neg_integer(),
                     data :: binary()}).
+-type rsm_first() :: #rsm_first{}.
 
 -record(text, {lang :: binary(),
                data :: binary()}).
+-type text() :: #text{}.
 
 -record(streamhost, {jid :: any(),
                      host :: binary(),
                      port = 1080 :: non_neg_integer()}).
+-type streamhost() :: #streamhost{}.
 
 -record(sm_resume, {h :: non_neg_integer(),
                     previd :: binary(),
                     xmlns :: binary()}).
+-type sm_resume() :: #sm_resume{}.
 
 -record(carbons_enable, {}).
+-type carbons_enable() :: #carbons_enable{}.
 
 -record(carbons_private, {}).
+-type carbons_private() :: #carbons_private{}.
 
 -record(pubsub_unsubscribe, {node :: binary(),
                              jid :: any(),
                              subid :: binary()}).
+-type pubsub_unsubscribe() :: #pubsub_unsubscribe{}.
 
 -record(mix_leave, {}).
+-type mix_leave() :: #mix_leave{}.
 
 -record(ping, {}).
+-type ping() :: #ping{}.
 
 -record(delay, {stamp :: any(),
-                from :: any()}).
+                from :: any(),
+                desc = <<>> :: binary()}).
+-type delay() :: #delay{}.
 
 -record(muc_history, {maxchars :: non_neg_integer(),
                       maxstanzas :: non_neg_integer(),
                       seconds :: non_neg_integer(),
                       since :: any()}).
+-type muc_history() :: #muc_history{}.
 
 -record(pubsub_affiliation, {node :: binary(),
                              type :: 'member' | 'none' | 'outcast' | 'owner' | 'publish-only' | 'publisher'}).
+-type pubsub_affiliation() :: #pubsub_affiliation{}.
 
 -record(muc_decline, {reason :: binary(),
                       from :: any(),
                       to :: any()}).
+-type muc_decline() :: #muc_decline{}.
 
 -record(sm_a, {h :: non_neg_integer(),
                xmlns :: binary()}).
+-type sm_a() :: #sm_a{}.
 
 -record(starttls_proceed, {}).
+-type starttls_proceed() :: #starttls_proceed{}.
 
 -record(sm_resumed, {h :: non_neg_integer(),
                      previd :: binary(),
                      xmlns :: binary()}).
+-type sm_resumed() :: #sm_resumed{}.
 
 -record(forwarded, {delay :: #delay{},
                     sub_els = [] :: [any()]}).
+-type forwarded() :: #forwarded{}.
 
 -record(sm_enable, {max :: non_neg_integer(),
                     resume = false :: any(),
                     xmlns :: binary()}).
+-type sm_enable() :: #sm_enable{}.
 
 -record(starttls_failure, {}).
+-type starttls_failure() :: #starttls_failure{}.
 
 -record(sasl_challenge, {text :: any()}).
+-type sasl_challenge() :: #sasl_challenge{}.
 
 -record(gone, {uri :: binary()}).
+-type gone() :: #gone{}.
 
 -record(private, {xml_els = [] :: [any()]}).
+-type private() :: #private{}.
 
 -record(p1_ack, {}).
+-type p1_ack() :: #p1_ack{}.
 
 -record(feature_sm, {xmlns :: binary()}).
+-type feature_sm() :: #feature_sm{}.
 
 -record(pubsub_item, {id :: binary(),
                       xml_els = [] :: [any()]}).
+-type pubsub_item() :: #pubsub_item{}.
 
 -record(pubsub_publish, {node :: binary(),
                          items = [] :: [#pubsub_item{}]}).
+-type pubsub_publish() :: #pubsub_publish{}.
 
 -record(roster_item, {jid :: any(),
-                      name :: binary(),
+                      name = <<>> :: binary(),
                       groups = [] :: [binary()],
                       subscription = none :: 'both' | 'from' | 'none' | 'remove' | 'to',
                       ask :: 'subscribe'}).
+-type roster_item() :: #roster_item{}.
 
--record(roster, {items = [] :: [#roster_item{}],
-                 ver :: binary()}).
+-record(roster_query, {items = [] :: [#roster_item{}],
+                       ver :: binary()}).
+-type roster_query() :: #roster_query{}.
 
 -record(pubsub_event_item, {id :: binary(),
                             node :: binary(),
                             publisher :: binary(),
                             xml_els = [] :: [any()]}).
+-type pubsub_event_item() :: #pubsub_event_item{}.
 
 -record(sm_r, {xmlns :: binary()}).
+-type sm_r() :: #sm_r{}.
 
 -record(muc_actor, {jid :: any(),
                     nick :: binary()}).
+-type muc_actor() :: #muc_actor{}.
 
 -record(stat, {name :: binary(),
                units :: binary(),
                value :: binary(),
                error = [] :: [{integer(),'undefined' | binary()}]}).
+-type stat() :: #stat{}.
 
 -record('see-other-host', {host :: binary()}).
+-type 'see-other-host'() :: #'see-other-host'{}.
 
 -record(compress, {methods = [] :: [binary()]}).
+-type compress() :: #compress{}.
 
 -record(starttls, {required = false :: boolean()}).
+-type starttls() :: #starttls{}.
 
 -record(last, {seconds :: non_neg_integer(),
-               text :: binary()}).
+               status = <<>> :: binary()}).
+-type last() :: #last{}.
 
 -record(redirect, {uri :: binary()}).
+-type redirect() :: #redirect{}.
 
 -record(sm_enabled, {id :: binary(),
                      location :: binary(),
                      max :: non_neg_integer(),
                      resume = false :: any(),
                      xmlns :: binary()}).
+-type sm_enabled() :: #sm_enabled{}.
 
 -record(pubsub_event_items, {node :: binary(),
                              retract = [] :: [binary()],
                              items = [] :: [#pubsub_event_item{}]}).
+-type pubsub_event_items() :: #pubsub_event_items{}.
 
 -record(pubsub_event, {items = [] :: [#pubsub_event_items{}]}).
+-type pubsub_event() :: #pubsub_event{}.
 
 -record(sasl_response, {text :: any()}).
+-type sasl_response() :: #sasl_response{}.
+
+-record(legacy_auth, {username :: 'none' | binary(),
+                      password :: 'none' | binary(),
+                      digest :: 'none' | binary(),
+                      resource :: 'none' | binary()}).
+-type legacy_auth() :: #legacy_auth{}.
 
 -record(pubsub_subscribe, {node :: binary(),
                            jid :: any()}).
+-type pubsub_subscribe() :: #pubsub_subscribe{}.
 
 -record(sasl_auth, {mechanism :: binary(),
                     text :: any()}).
+-type sasl_auth() :: #sasl_auth{}.
 
 -record(p1_push, {}).
+-type p1_push() :: #p1_push{}.
 
 -record(feature_csi, {xmlns :: binary()}).
+-type feature_csi() :: #feature_csi{}.
 
 -record(muc_user_destroy, {reason :: binary(),
                            jid :: any()}).
+-type muc_user_destroy() :: #muc_user_destroy{}.
 
 -record(disco_item, {jid :: any(),
                      name :: binary(),
                      node :: binary()}).
+-type disco_item() :: #disco_item{}.
 
 -record(disco_items, {node :: binary(),
                       items = [] :: [#disco_item{}]}).
+-type disco_items() :: #disco_items{}.
 
 -record(unblock, {items = [] :: [any()]}).
+-type unblock() :: #unblock{}.
 
 -record(block, {items = [] :: [any()]}).
-
--record(session, {}).
+-type block() :: #block{}.
 
 -record(compression, {methods = [] :: [binary()]}).
+-type compression() :: #compression{}.
 
 -record(muc_owner_destroy, {jid :: any(),
                             reason :: binary(),
                             password :: binary()}).
+-type muc_owner_destroy() :: #muc_owner_destroy{}.
 
 -record(pubsub_subscription, {jid :: any(),
                               node :: binary(),
                               subid :: binary(),
                               type :: 'none' | 'pending' | 'subscribed' | 'unconfigured'}).
+-type pubsub_subscription() :: #pubsub_subscription{}.
 
 -record(muc_item, {actor :: #muc_actor{},
                    continue :: binary(),
                    role :: 'moderator' | 'none' | 'participant' | 'visitor',
                    jid :: any(),
                    nick :: binary()}).
+-type muc_item() :: #muc_item{}.
 
 -record(muc_admin, {items = [] :: [#muc_item{}]}).
+-type muc_admin() :: #muc_admin{}.
 
 -record(shim, {headers = [] :: [{binary(),'undefined' | binary()}]}).
+-type shim() :: #shim{}.
 
 -record(mam_prefs, {xmlns :: binary(),
                     default :: 'always' | 'never' | 'roster',
                     always = [] :: [any()],
                     never = [] :: [any()]}).
+-type mam_prefs() :: #mam_prefs{}.
 
--record(caps, {hash :: binary(),
-               node :: binary(),
-               ver :: any()}).
+-record(caps, {node :: binary(),
+               version :: binary(),
+               hash :: binary(),
+               exts = [] :: any()}).
+-type caps() :: #caps{}.
 
 -record(muc, {history :: #muc_history{},
               password :: binary()}).
+-type muc() :: #muc{}.
 
 -record(stream_features, {sub_els = [] :: [any()]}).
+-type stream_features() :: #stream_features{}.
 
 -record(stats, {stat = [] :: [#stat{}]}).
+-type stats() :: #stats{}.
 
 -record(pubsub_items, {node :: binary(),
                        max_items :: non_neg_integer(),
                        subid :: binary(),
                        items = [] :: [#pubsub_item{}]}).
+-type pubsub_items() :: #pubsub_items{}.
 
 -record(carbons_sent, {forwarded :: #forwarded{}}).
+-type carbons_sent() :: #carbons_sent{}.
 
 -record(mam_archived, {by :: any(),
                        id :: binary()}).
+-type mam_archived() :: #mam_archived{}.
 
 -record(p1_rebind, {}).
+-type p1_rebind() :: #p1_rebind{}.
 
 -record(compress_failure, {reason :: 'processing-failed' | 'setup-failed' | 'unsupported-method'}).
+-type compress_failure() :: #compress_failure{}.
 
 -record(sasl_abort, {}).
+-type sasl_abort() :: #sasl_abort{}.
 
 -record(vcard_email, {home = false :: boolean(),
                       work = false :: boolean(),
                       pref = false :: boolean(),
                       x400 = false :: boolean(),
                       userid :: binary()}).
+-type vcard_email() :: #vcard_email{}.
 
 -record(carbons_received, {forwarded :: #forwarded{}}).
+-type carbons_received() :: #carbons_received{}.
 
 -record(pubsub_retract, {node :: binary(),
                          notify = false :: any(),
                          items = [] :: [#pubsub_item{}]}).
+-type pubsub_retract() :: #pubsub_retract{}.
 
 -record(mix_participant, {jid :: any(),
                           nick :: binary()}).
+-type mix_participant() :: #mix_participant{}.
 
 -record(vcard_geo, {lat :: binary(),
                     lon :: binary()}).
+-type vcard_geo() :: #vcard_geo{}.
 
 -record(compressed, {}).
+-type compressed() :: #compressed{}.
 
--record(sasl_failure, {reason :: 'aborted' | 'account-disabled' | 'credentials-expired' | 'encryption-required' | 'incorrect-encoding' | 'invalid-authzid' | 'invalid-mechanism' | 'malformed-request' | 'mechanism-too-weak' | 'not-authorized' | 'temporary-auth-failure',
+-record(sasl_failure, {reason :: 'aborted' | 'account-disabled' | 'bad-protocol' | 'credentials-expired' | 'encryption-required' | 'incorrect-encoding' | 'invalid-authzid' | 'invalid-mechanism' | 'malformed-request' | 'mechanism-too-weak' | 'not-authorized' | 'temporary-auth-failure',
                        text = [] :: [#text{}]}).
+-type sasl_failure() :: #sasl_failure{}.
 
 -record(block_list, {}).
+-type block_list() :: #block_list{}.
 
 -record(xdata_field, {label :: binary(),
                       type :: 'boolean' | 'fixed' | 'hidden' | 'jid-multi' | 'jid-single' | 'list-multi' | 'list-single' | 'text-multi' | 'text-private' | 'text-single',
                       desc :: binary(),
                       values = [] :: [binary()],
                       options = [] :: [binary()]}).
+-type xdata_field() :: #xdata_field{}.
 
 -record(version, {name :: binary(),
                   ver :: binary(),
                   os :: binary()}).
+-type version() :: #version{}.
 
 -record(muc_invite, {reason :: binary(),
                      from :: any(),
                      to :: any()}).
+-type muc_invite() :: #muc_invite{}.
 
 -record(bind, {jid :: any(),
                resource :: any()}).
+-type bind() :: #bind{}.
+
+-record(rosterver_feature, {}).
+-type rosterver_feature() :: #rosterver_feature{}.
 
 -record(muc_user, {decline :: #muc_decline{},
                    destroy :: #muc_user_destroy{},
                    items = [] :: [#muc_item{}],
                    status_codes = [] :: [pos_integer()],
                    password :: binary()}).
-
--record(vcard_xupdate, {photo :: binary()}).
+-type muc_user() :: #muc_user{}.
 
 -record(carbons_disable, {}).
+-type carbons_disable() :: #carbons_disable{}.
 
 -record(bytestreams, {hosts = [] :: [#streamhost{}],
                       used :: any(),
                       dstaddr :: binary(),
                       mode = tcp :: 'tcp' | 'udp',
                       sid :: binary()}).
+-type bytestreams() :: #bytestreams{}.
 
 -record(vcard_org, {name :: binary(),
                     units = [] :: [binary()]}).
+-type vcard_org() :: #vcard_org{}.
 
 -record(rsm_set, {'after' :: binary(),
                   before :: 'none' | binary(),
                   index :: non_neg_integer(),
                   last :: binary(),
                   max :: non_neg_integer()}).
+-type rsm_set() :: #rsm_set{}.
 
 -record(mam_fin, {id :: binary(),
                   rsm :: #rsm_set{},
                   stable :: any(),
                   complete :: any()}).
+-type mam_fin() :: #mam_fin{}.
 
 -record(vcard_tel, {home = false :: boolean(),
                     work = false :: boolean(),
                     pcs = false :: boolean(),
                     pref = false :: boolean(),
                     number :: binary()}).
+-type vcard_tel() :: #vcard_tel{}.
 
 -record(vcard_key, {type :: binary(),
                     cred :: binary()}).
+-type vcard_key() :: #vcard_key{}.
 
 -record(vcard_name, {family :: binary(),
                      given :: binary(),
                      middle :: binary(),
                      prefix :: binary(),
                      suffix :: binary()}).
+-type vcard_name() :: #vcard_name{}.
 
 -record(identity, {category :: binary(),
                    type :: binary(),
                    lang :: binary(),
                    name :: binary()}).
+-type identity() :: #identity{}.
 
 -record(bookmark_conference, {name :: binary(),
                               jid :: any(),
                               autojoin = false :: any(),
                               nick :: binary(),
                               password :: binary()}).
+-type bookmark_conference() :: #bookmark_conference{}.
+
+-record(xmpp_session, {optional = false :: boolean()}).
+-type xmpp_session() :: #xmpp_session{}.
 
 -record(bookmark_url, {name :: binary(),
                        url :: binary()}).
+-type bookmark_url() :: #bookmark_url{}.
 
 -record(bookmark_storage, {conference = [] :: [#bookmark_conference{}],
                            url = [] :: [#bookmark_url{}]}).
+-type bookmark_storage() :: #bookmark_storage{}.
 
 -record(vcard_sound, {phonetic :: binary(),
                       binval :: any(),
                       extval :: binary()}).
+-type vcard_sound() :: #vcard_sound{}.
 
 -record(vcard_photo, {type :: binary(),
                       binval :: any(),
                       extval :: binary()}).
+-type vcard_photo() :: #vcard_photo{}.
 
 -record(vcard_label, {home = false :: boolean(),
                       work = false :: boolean(),
                       intl = false :: boolean(),
                       pref = false :: boolean(),
                       line = [] :: [binary()]}).
+-type vcard_label() :: #vcard_label{}.
 
 -record(vcard_adr, {home = false :: boolean(),
                     work = false :: boolean(),
                     region :: binary(),
                     pcode :: binary(),
                     ctry :: binary()}).
+-type vcard_adr() :: #vcard_adr{}.
+
+-record(search_item, {jid :: any(),
+                      first :: binary(),
+                      last :: binary(),
+                      nick :: binary(),
+                      email :: binary()}).
+-type search_item() :: #search_item{}.
 
 -record(xdata, {type :: 'cancel' | 'form' | 'result' | 'submit',
                 instructions = [] :: [binary()],
                 reported :: [#xdata_field{}],
                 items = [] :: [[#xdata_field{}]],
                 fields = [] :: [#xdata_field{}]}).
+-type xdata() :: #xdata{}.
+
+-record(search, {instructions :: binary(),
+                 first :: binary(),
+                 last :: binary(),
+                 nick :: binary(),
+                 email :: binary(),
+                 items = [] :: [#search_item{}],
+                 xdata :: #xdata{}}).
+-type search() :: #search{}.
 
 -record(mam_query, {xmlns :: binary(),
                     id :: binary(),
                     with :: any(),
                     rsm :: #rsm_set{},
                     xdata :: #xdata{}}).
+-type mam_query() :: #mam_query{}.
 
 -record(muc_owner, {destroy :: #muc_owner_destroy{},
                     config :: #xdata{}}).
+-type muc_owner() :: #muc_owner{}.
 
 -record(pubsub_options, {node :: binary(),
                          jid :: any(),
                          subid :: binary(),
                          xdata :: #xdata{}}).
+-type pubsub_options() :: #pubsub_options{}.
 
 -record(pubsub, {subscriptions :: {'none' | binary(),[#pubsub_subscription{}]},
                  affiliations :: [#pubsub_affiliation{}],
                  options :: #pubsub_options{},
                  items :: #pubsub_items{},
                  retract :: #pubsub_retract{}}).
+-type pubsub() :: #pubsub{}.
 
 -record(register, {registered = false :: boolean(),
                    remove = false :: boolean(),
                    text :: 'none' | binary(),
                    key :: 'none' | binary(),
                    xdata :: #xdata{}}).
+-type register() :: #register{}.
 
 -record(disco_info, {node :: binary(),
                      identities = [] :: [#identity{}],
                      features = [] :: [binary()],
                      xdata = [] :: [#xdata{}]}).
+-type disco_info() :: #disco_info{}.
 
 -record(offline_item, {node :: binary(),
                        action :: 'remove' | 'view'}).
+-type offline_item() :: #offline_item{}.
 
 -record(offline, {items = [] :: [#offline_item{}],
                   purge = false :: boolean(),
                   fetch = false :: boolean()}).
+-type offline() :: #offline{}.
 
 -record(sasl_mechanisms, {list = [] :: [binary()]}).
+-type sasl_mechanisms() :: #sasl_mechanisms{}.
 
 -record(sm_failed, {reason :: atom() | #gone{} | #redirect{},
                     h :: non_neg_integer(),
                     xmlns :: binary()}).
+-type sm_failed() :: #sm_failed{}.
 
 -record(error, {type :: 'auth' | 'cancel' | 'continue' | 'modify' | 'wait',
+                code :: non_neg_integer(),
                 by :: binary(),
                 reason :: atom() | #gone{} | #redirect{},
                 text :: #text{}}).
+-type error() :: #error{}.
 
 -record(presence, {id :: binary(),
-                   type :: 'error' | 'probe' | 'subscribe' | 'subscribed' | 'unavailable' | 'unsubscribe' | 'unsubscribed',
+                   type = available :: 'available' | 'error' | 'probe' | 'subscribe' | 'subscribed' | 'unavailable' | 'unsubscribe' | 'unsubscribed',
                    lang :: binary(),
                    from :: any(),
                    to :: any(),
                    priority :: integer(),
                    error :: #error{},
                    sub_els = [] :: [any()]}).
+-type presence() :: #presence{}.
 
 -record(message, {id :: binary(),
                   type = normal :: 'chat' | 'error' | 'groupchat' | 'headline' | 'normal',
                   thread :: binary(),
                   error :: #error{},
                   sub_els = [] :: [any()]}).
+-type message() :: #message{}.
 
 -record(iq, {id :: binary(),
              type :: 'error' | 'get' | 'result' | 'set',
              to :: any(),
              error :: #error{},
              sub_els = [] :: [any()]}).
+-type iq() :: #iq{}.
 
 -record(mix_join, {jid :: any(),
                    subscribe = [] :: [binary()]}).
+-type mix_join() :: #mix_join{}.
 
 -record(privacy_item, {order :: non_neg_integer(),
                        action :: 'allow' | 'deny',
                        type :: 'group' | 'jid' | 'subscription',
                        value :: binary(),
-                       kinds = [] :: ['iq' | 'message' | 'presence-in' | 'presence-out']}).
+                       message = false :: boolean(),
+                       iq = false :: boolean(),
+                       presence_in = false :: boolean(),
+                       presence_out = false :: boolean()}).
+-type privacy_item() :: #privacy_item{}.
 
 -record(privacy_list, {name :: binary(),
                        items = [] :: [#privacy_item{}]}).
+-type privacy_list() :: #privacy_list{}.
 
--record(privacy, {lists = [] :: [#privacy_list{}],
-                  default :: 'none' | binary(),
-                  active :: 'none' | binary()}).
+-record(privacy_query, {lists = [] :: [#privacy_list{}],
+                        default :: 'none' | binary(),
+                        active :: 'none' | binary()}).
+-type privacy_query() :: #privacy_query{}.
 
 -record(stream_error, {reason :: atom() | #'see-other-host'{},
                        text :: #text{}}).
+-type stream_error() :: #stream_error{}.
 
 -record(vcard_logo, {type :: binary(),
                      binval :: any(),
                      extval :: binary()}).
-
--record(vcard, {version :: binary(),
-                fn :: binary(),
-                n :: #vcard_name{},
-                nickname :: binary(),
-                photo :: #vcard_photo{},
-                bday :: binary(),
-                adr = [] :: [#vcard_adr{}],
-                label = [] :: [#vcard_label{}],
-                tel = [] :: [#vcard_tel{}],
-                email = [] :: [#vcard_email{}],
-                jabberid :: binary(),
-                mailer :: binary(),
-                tz :: binary(),
-                geo :: #vcard_geo{},
-                title :: binary(),
-                role :: binary(),
-                logo :: #vcard_logo{},
-                org :: #vcard_org{},
-                categories = [] :: [binary()],
-                note :: binary(),
-                prodid :: binary(),
-                rev :: binary(),
-                sort_string :: binary(),
-                sound :: #vcard_sound{},
-                uid :: binary(),
-                url :: binary(),
-                class :: 'confidential' | 'private' | 'public',
-                key :: #vcard_key{},
-                desc :: binary()}).
+-type vcard_logo() :: #vcard_logo{}.
+
+-record(vcard_temp, {version :: binary(),
+                     fn :: binary(),
+                     n :: #vcard_name{},
+                     nickname :: binary(),
+                     photo :: #vcard_photo{},
+                     bday :: binary(),
+                     adr = [] :: [#vcard_adr{}],
+                     label = [] :: [#vcard_label{}],
+                     tel = [] :: [#vcard_tel{}],
+                     email = [] :: [#vcard_email{}],
+                     jabberid :: binary(),
+                     mailer :: binary(),
+                     tz :: binary(),
+                     geo :: #vcard_geo{},
+                     title :: binary(),
+                     role :: binary(),
+                     logo :: #vcard_logo{},
+                     org :: #vcard_org{},
+                     categories = [] :: [binary()],
+                     note :: binary(),
+                     prodid :: binary(),
+                     rev :: binary(),
+                     sort_string :: binary(),
+                     sound :: #vcard_sound{},
+                     uid :: binary(),
+                     url :: binary(),
+                     class :: 'confidential' | 'private' | 'public',
+                     key :: #vcard_key{},
+                     desc :: binary()}).
+-type vcard_temp() :: #vcard_temp{}.
 
 -record(time, {tzo :: any(),
                utc :: any()}).
-
-
+-type time() :: #time{}.
+
+-type xmpp_element() :: compression() |
+                        pubsub_subscription() |
+                        version() |
+                        pubsub_affiliation() |
+                        muc_admin() |
+                        mam_fin() |
+                        sm_a() |
+                        carbons_sent() |
+                        mam_archived() |
+                        p1_rebind() |
+                        sasl_abort() |
+                        carbons_received() |
+                        pubsub_retract() |
+                        mix_participant() |
+                        compressed() |
+                        block_list() |
+                        rsm_set() |
+                        'see-other-host'() |
+                        hint() |
+                        starttls_proceed() |
+                        sm_resumed() |
+                        forwarded() |
+                        privacy_list() |
+                        text() |
+                        vcard_org() |
+                        shim() |
+                        search_item() |
+                        offline_item() |
+                        feature_sm() |
+                        pubsub_item() |
+                        roster_item() |
+                        pubsub_event_item() |
+                        muc_item() |
+                        vcard_temp() |
+                        sasl_success() |
+                        pubsub_event_items() |
+                        disco_items() |
+                        pubsub_options() |
+                        compress() |
+                        bytestreams() |
+                        identity() |
+                        feature_csi() |
+                        muc_user_destroy() |
+                        privacy_query() |
+                        delay() |
+                        muc_history() |
+                        vcard_tel() |
+                        vcard_logo() |
+                        disco_info() |
+                        vcard_geo() |
+                        vcard_photo() |
+                        feature_register() |
+                        register() |
+                        muc_owner() |
+                        pubsub() |
+                        sm_r() |
+                        muc_actor() |
+                        error() |
+                        stream_error() |
+                        muc_user() |
+                        vcard_adr() |
+                        carbons_private() |
+                        mix_leave() |
+                        muc_invite() |
+                        rosterver_feature() |
+                        vcard_xupdate() |
+                        carbons_disable() |
+                        bookmark_conference() |
+                        offline() |
+                        time() |
+                        sasl_response() |
+                        pubsub_subscribe() |
+                        presence() |
+                        message() |
+                        sm_enable() |
+                        starttls_failure() |
+                        sasl_challenge() |
+                        gone() |
+                        private() |
+                        compress_failure() |
+                        sasl_failure() |
+                        bookmark_storage() |
+                        vcard_name() |
+                        sm_resume() |
+                        carbons_enable() |
+                        pubsub_unsubscribe() |
+                        muc_decline() |
+                        chatstate() |
+                        sasl_auth() |
+                        p1_push() |
+                        legacy_auth() |
+                        search() |
+                        pubsub_publish() |
+                        unblock() |
+                        p1_ack() |
+                        block() |
+                        mix_join() |
+                        xmpp_session() |
+                        xdata() |
+                        iq() |
+                        streamhost() |
+                        bind() |
+                        last() |
+                        redirect() |
+                        sm_enabled() |
+                        pubsub_event() |
+                        vcard_sound() |
+                        mam_result() |
+                        rsm_first() |
+                        stat() |
+                        xdata_field() |
+                        sm_failed() |
+                        ping() |
+                        disco_item() |
+                        privacy_item() |
+                        caps() |
+                        muc() |
+                        stream_features() |
+                        stats() |
+                        pubsub_items() |
+                        starttls() |
+                        mam_prefs() |
+                        sasl_mechanisms() |
+                        vcard_key() |
+                        csi() |
+                        roster_query() |
+                        muc_owner_destroy() |
+                        mam_query() |
+                        bookmark_url() |
+                        vcard_email() |
+                        vcard_label().
index a101e13803acfeb5908c20d98adae817b2d3114a..46b23384e17932f162cf7f3ecd4fbe7a31e08bb2 100644 (file)
@@ -73,8 +73,8 @@
 -callback mech_step(any(), binary()) -> {ok, props()} |
                                         {ok, props(), binary()} |
                                         {continue, binary(), any()} |
-                                        {error, binary()} |
-                                        {error, binary(), binary()}.
+                                        {error, atom()} |
+                                        {error, atom(), binary()}.
 
 start() ->
     ets:new(sasl_mechanism,
@@ -129,8 +129,8 @@ register_mechanism(Mechanism, Module, PasswordType) ->
 check_credentials(_State, Props) ->
     User = proplists:get_value(authzid, Props, <<>>),
     case jid:nodeprep(User) of
-      error -> {error, <<"not-authorized">>};
-      <<"">> -> {error, <<"not-authorized">>};
+      error -> {error, 'not-authorized'};
+      <<"">> -> {error, 'not-authorized'};
       _LUser -> ok
     end.
 
@@ -159,6 +159,8 @@ server_new(Service, ServerFQDN, UserRealm, _SecFlags,
                check_password = CheckPassword,
                check_password_digest = CheckPasswordDigest}.
 
+server_start(State, Mech, undefined) ->
+    server_start(State, Mech, <<"">>);
 server_start(State, Mech, ClientIn) ->
     case lists:member(Mech,
                      listmech(State#sasl_state.myname))
@@ -174,11 +176,13 @@ server_start(State, Mech, ClientIn) ->
                server_step(State#sasl_state{mech_mod = Module,
                                             mech_state = MechState},
                            ClientIn);
-           _ -> {error, <<"no-mechanism">>}
+           _ -> {error, 'no-mechanism'}
          end;
-      false -> {error, <<"no-mechanism">>}
+      false -> {error, 'no-mechanism'}
     end.
 
+server_step(State, undefined) ->
+    server_step(State, <<"">>);
 server_step(State, ClientIn) ->
     Module = State#sasl_state.mech_mod,
     MechState = State#sasl_state.mech_state,
index 0d408fc486eb91c6509c4866b26aef036137e960..150aa854cea12be8449a1f5d0b0f64aa18a25e9d 100644 (file)
@@ -80,7 +80,7 @@ mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
 mech_step(#state{step = 3, nonce = Nonce} = State,
          ClientIn) ->
     case parse(ClientIn) of
-      bad -> {error, <<"bad-protocol">>};
+      bad -> {error, 'bad-protocol'};
       KeyVals ->
          DigestURI = proplists:get_value(<<"digest-uri">>, KeyVals, <<>>),
          UserName = proplists:get_value(<<"username">>, KeyVals, <<>>),
@@ -92,11 +92,11 @@ mech_step(#state{step = 3, nonce = Nonce} = State,
                       "seems invalid: ~p (checking for Host "
                       "~p, FQDN ~p)",
                       [DigestURI, State#state.host, State#state.hostfqdn]),
-               {error, <<"not-authorized">>, UserName};
+               {error, 'not-authorized', UserName};
            true ->
                AuthzId = proplists:get_value(<<"authzid">>, KeyVals, <<>>),
                case (State#state.get_password)(UserName) of
-                 {false, _} -> {error, <<"not-authorized">>, UserName};
+                 {false, _} -> {error, 'not-authorized', UserName};
                  {Passwd, AuthModule} ->
                      case (State#state.check_password)(UserName, UserName, <<"">>,
                                    proplists:get_value(<<"response">>, KeyVals, <<>>),
@@ -116,8 +116,8 @@ mech_step(#state{step = 3, nonce = Nonce} = State,
                             State#state{step = 5, auth_module = AuthModule,
                                         username = UserName,
                                         authzid = AuthzId}};
-                       false -> {error, <<"not-authorized">>, UserName};
-                       {false, _} -> {error, <<"not-authorized">>, UserName}
+                       false -> {error, 'not-authorized', UserName};
+                       {false, _} -> {error, 'not-authorized', UserName}
                      end
                end
          end
@@ -134,7 +134,7 @@ mech_step(#state{step = 5, auth_module = AuthModule,
       {auth_module, AuthModule}]};
 mech_step(A, B) ->
     ?DEBUG("SASL DIGEST: A ~p B ~p", [A, B]),
-    {error, <<"bad-protocol">>}.
+    {error, 'bad-protocol'}.
 
 parse(S) -> parse1(binary_to_list(S), "", []).
 
index 16f1e3dfb775cbc45d016310175b2499aca2f073..09d143ef56892621b394f2485ea206d8e26f919b 100644 (file)
@@ -52,9 +52,9 @@ mech_step(State, ClientIn) ->
                      [{username, User}, {authzid, AuthzId},
                       {auth_module, ejabberd_oauth}]};
                 false ->
-                    {error, <<"not-authorized">>, User}
+                    {error, 'not-authorized', User}
             end;
-        _ -> {error, <<"bad-protocol">>}
+        _ -> {error, 'bad-protocol'}
     end.
 
 prepare(ClientIn) ->
index 82d68f87fcd6cc646902631c36dc38eefe83bde7..8e9b32b9931c7a0116e972b84c382d0c0d7a4eb5 100644 (file)
@@ -50,9 +50,9 @@ mech_step(State, ClientIn) ->
                {ok,
                 [{username, User}, {authzid, AuthzId},
                  {auth_module, AuthModule}]};
-           _ -> {error, <<"not-authorized">>, User}
+           _ -> {error, 'not-authorized', User}
          end;
-      _ -> {error, <<"bad-protocol">>}
+      _ -> {error, 'bad-protocol'}
     end.
 
 prepare(ClientIn) ->
index 18f52b48fe6b06d272c889bf730f062385fbbf1a..8643a89241acacf0954f491fce2954f93a7fcab5 100644 (file)
@@ -67,21 +67,21 @@ mech_step(#state{step = 2} = State, ClientIn) ->
     case re:split(ClientIn, <<",">>, [{return, binary}]) of
       [_CBind, _AuthorizationIdentity, _UserNameAttribute, _ClientNonceAttribute, ExtensionAttribute | _]
          when ExtensionAttribute /= [] ->
-         {error, <<"protocol-error-extension-not-supported">>};
+         {error, 'protocol-error-extension-not-supported'};
       [CBind, _AuthorizationIdentity, UserNameAttribute, ClientNonceAttribute | _]
          when (CBind == <<"y">>) or (CBind == <<"n">>) ->
          case parse_attribute(UserNameAttribute) of
            {error, Reason} -> {error, Reason};
            {_, EscapedUserName} ->
                case unescape_username(EscapedUserName) of
-                 error -> {error, <<"protocol-error-bad-username">>};
+                 error -> {error, 'protocol-error-bad-username'};
                  UserName ->
                      case parse_attribute(ClientNonceAttribute) of
                        {$r, ClientNonce} ->
                            {Ret, _AuthModule} = (State#state.get_password)(UserName),
                            case {Ret, jid:resourceprep(Ret)} of
-                             {false, _} -> {error, <<"not-authorized">>, UserName};
-                             {_, error} when is_binary(Ret) -> ?WARNING_MSG("invalid plain password", []), {error, <<"not-authorized">>, UserName};
+                             {false, _} -> {error, 'not-authorized', UserName};
+                             {_, error} when is_binary(Ret) -> ?WARNING_MSG("invalid plain password", []), {error, 'not-authorized', UserName};
                              {Ret, _} ->
                                  {StoredKey, ServerKey, Salt, IterationCount} =
                                      if is_tuple(Ret) -> Ret;
@@ -121,11 +121,11 @@ mech_step(#state{step = 2} = State, ClientIn) ->
                                               server_nonce = ServerNonce,
                                               username = UserName}}
                            end;
-                       _Else -> {error, <<"not-supported">>}
+                       _Else -> {error, 'not-supported'}
                      end
                end
          end;
-      _Else -> {error, <<"bad-protocol">>}
+      _Else -> {error, 'bad-protocol'}
     end;
 mech_step(#state{step = 4} = State, ClientIn) ->
     case str:tokens(ClientIn, <<",">>) of
@@ -163,18 +163,18 @@ mech_step(#state{step = 4} = State, ClientIn) ->
                                               {authzid, State#state.username}],
                                          <<"v=",
                                            (jlib:encode_base64(ServerSignature))/binary>>};
-                                    true -> {error, <<"bad-auth">>, State#state.username}
+                                    true -> {error, 'bad-auth', State#state.username}
                                  end;
-                           _Else -> {error, <<"bad-protocol">>}
+                           _Else -> {error, 'bad-protocol'}
                            end;
-                       {$r, _} -> {error, <<"bad-nonce">>};
-                       _Else -> {error, <<"bad-protocol">>}
+                       {$r, _} -> {error, 'bad-nonce'};
+                       _Else -> {error, 'bad-protocol'}
                    end;
-                 true -> {error, <<"bad-channel-binding">>}
+                 true -> {error, 'bad-channel-binding'}
                end;
-           _Else -> {error, <<"bad-protocol">>}
+           _Else -> {error, 'bad-protocol'}
          end;
-      _Else -> {error, <<"bad-protocol">>}
+      _Else -> {error, 'bad-protocol'}
     end.
 
 parse_attribute(Attribute) ->
@@ -187,11 +187,11 @@ parse_attribute(Attribute) ->
                 if SecondChar == $= ->
                        String = str:substr(Attribute, 3),
                        {lists:nth(1, AttributeS), String};
-                   true -> {error, <<"bad-format second char not equal sign">>}
+                   true -> {error, 'bad-format-second-char-not-equal-sign'}
                 end;
-            _Else -> {error, <<"bad-format first char not a letter">>}
+            _Else -> {error, 'bad-format-first-char-not-a-letter'}
           end;
-       true -> {error, <<"bad-format attribute too short">>}
+       true -> {error, 'bad-format-attribute-too-short'}
     end.
 
 unescape_username(<<"">>) -> <<"">>;
index 9ddb8511dc0c088096879c82a92599ec30ee1043..8d217a354149b4717d23662de8106db189e71b55 100644 (file)
@@ -67,7 +67,8 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
+%%-include("legacy.hrl").
 
 -include("mod_privacy.hrl").
 
                ask_offline = true,
                lang = <<"">>}).
 
+-type state_name() :: wait_for_stream | wait_for_auth |
+                     wait_for_feature_request | wait_for_bind |
+                     wait_for_sasl_response | wait_for_resume |
+                     session_established.
+-type state() :: #state{}.
+-type fsm_stop() :: {stop, normal, state()}.
+-type fsm_next() :: {next_state, state_name(), state(), non_neg_integer()}.
+-type fsm_transition() :: fsm_stop() | fsm_next().
+-export_type([state/0]).
+
 %-define(DBGFSM, true).
 
 -ifdef(DBGFSM).
 
 -define(STREAM_TRAILER, <<"</stream:stream>">>).
 
--define(INVALID_NS_ERR, ?SERR_INVALID_NAMESPACE).
-
--define(INVALID_XML_ERR, ?SERR_XML_NOT_WELL_FORMED).
-
--define(HOST_UNKNOWN_ERR, ?SERR_HOST_UNKNOWN).
-
--define(POLICY_VIOLATION_ERR(Lang, Text),
-       ?SERRT_POLICY_VIOLATION(Lang, Text)).
-
--define(INVALID_FROM, ?SERR_INVALID_FROM).
-
 %% XEP-0198:
 
--define(IS_STREAM_MGMT_TAG(Name),
-       (Name == <<"enable">>) or
-       (Name == <<"resume">>) or
-       (Name == <<"a">>) or
-       (Name == <<"r">>)).
-
--define(IS_SUPPORTED_MGMT_XMLNS(Xmlns),
-       (Xmlns == ?NS_STREAM_MGMT_2) or
-       (Xmlns == ?NS_STREAM_MGMT_3)).
-
--define(MGMT_FAILED(Condition, Attrs),
-       #xmlel{name = <<"failed">>,
-              attrs = Attrs,
-              children = [#xmlel{name = Condition,
-                                 attrs = [{<<"xmlns">>, ?NS_STANZAS}],
-                                 children = []}]}).
-
--define(MGMT_BAD_REQUEST(Xmlns),
-       ?MGMT_FAILED(<<"bad-request">>, [{<<"xmlns">>, Xmlns}])).
-
--define(MGMT_SERVICE_UNAVAILABLE(Xmlns),
-       ?MGMT_FAILED(<<"service-unavailable">>, [{<<"xmlns">>, Xmlns}])).
-
--define(MGMT_UNEXPECTED_REQUEST(Xmlns),
-       ?MGMT_FAILED(<<"unexpected-request">>, [{<<"xmlns">>, Xmlns}])).
-
--define(MGMT_UNSUPPORTED_VERSION(Xmlns),
-       ?MGMT_FAILED(<<"unsupported-version">>, [{<<"xmlns">>, Xmlns}])).
-
--define(MGMT_ITEM_NOT_FOUND(Xmlns),
-       ?MGMT_FAILED(<<"item-not-found">>, [{<<"xmlns">>, Xmlns}])).
-
--define(MGMT_ITEM_NOT_FOUND_H(Xmlns, NumStanzasIn),
-       ?MGMT_FAILED(<<"item-not-found">>,
-                    [{<<"xmlns">>, Xmlns},
-                     {<<"h">>, jlib:integer_to_binary(NumStanzasIn)}])).
+-define(IS_STREAM_MGMT_PACKET(Pkt),
+       is_record(Pkt, sm_enable) or
+       is_record(Pkt, sm_resume) or
+       is_record(Pkt, sm_a) or
+       is_record(Pkt, sm_r)).
 
 %%%----------------------------------------------------------------------
 %%% API
@@ -213,21 +182,25 @@ get_presence(FsmRef) ->
     (?GEN_FSM):sync_send_all_state_event(FsmRef,
                                         {get_presence}, 1000).
 
+-spec get_aux_field(any(), state()) -> {ok, any()} | error.
 get_aux_field(Key, #state{aux_fields = Opts}) ->
     case lists:keysearch(Key, 1, Opts) of
       {value, {_, Val}} -> {ok, Val};
       _ -> error
     end.
 
+-spec set_aux_field(any(), any(), state()) -> state().
 set_aux_field(Key, Val,
              #state{aux_fields = Opts} = State) ->
     Opts1 = lists:keydelete(Key, 1, Opts),
     State#state{aux_fields = [{Key, Val} | Opts1]}.
 
+-spec del_aux_field(any(), state()) -> state().
 del_aux_field(Key, #state{aux_fields = Opts} = State) ->
     Opts1 = lists:keydelete(Key, 1, Opts),
     State#state{aux_fields = Opts1}.
 
+-spec get_subscription(jid() | ljid(), state()) -> both | from | to | none.
 get_subscription(From = #jid{}, StateData) ->
     get_subscription(jid:tolower(From), StateData);
 get_subscription(LFrom, StateData) ->
@@ -244,14 +217,19 @@ get_subscription(LFrom, StateData) ->
        true -> none
     end.
 
+-spec send_filtered(pid(), binary(), jid(), jid(), stanza()) -> any().
 send_filtered(FsmRef, Feature, From, To, Packet) ->
     FsmRef ! {send_filtered, Feature, From, To, Packet}.
 
+-spec broadcast(pid(), any(), jid(), stanza()) -> any().
 broadcast(FsmRef, Type, From, Packet) ->
     FsmRef ! {broadcast, Type, From, Packet}.
 
+-spec stop(pid()) -> any().
 stop(FsmRef) -> (?GEN_FSM):send_event(FsmRef, stop).
 
+-spec close(pid()) -> any().
+%% What is the difference between stop and close???
 close(FsmRef) -> (?GEN_FSM):send_event(FsmRef, closed).
 
 %%%----------------------------------------------------------------------
@@ -336,6 +314,7 @@ init([{SockMod, Socket}, Opts]) ->
                       mgmt_resend = ResendOnTimeout},
     {ok, wait_for_stream, StateData, ?C2S_OPEN_TIMEOUT}.
 
+-spec get_subscribed(pid()) -> [ljid()].
 %% Return list of all available resources of contacts,
 get_subscribed(FsmRef) ->
     (?GEN_FSM):sync_send_all_state_event(FsmRef,
@@ -399,15 +378,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                                    Mechs =
                                        case TLSEnabled or not TLSRequired of
                                        true ->
-                                           Ms = lists:map(fun (S) ->
-                                                           #xmlel{name = <<"mechanism">>,
-                                                               attrs = [],
-                                                               children = [{xmlcdata, S}]}
-                                                   end,
-                                                   cyrsasl:listmech(Server)),
-                                           [#xmlel{name = <<"mechanisms">>,
-                                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                                   children = Ms}];
+                                           [#sasl_mechanisms{list = cyrsasl:listmech(Server)}];
                                        false ->
                                            []
                                    end,
@@ -417,11 +388,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                                    CompressFeature = case Zlib andalso
                                        ((SockMod == gen_tcp) orelse (SockMod == fast_tls)) of
                                        true ->
-                                           [#xmlel{name = <<"compression">>,
-                                                   attrs = [{<<"xmlns">>, ?NS_FEATURE_COMPRESS}],
-                                                   children = [#xmlel{name = <<"method">>,
-                                                           attrs = [],
-                                                           children = [{xmlcdata, <<"zlib">>}]}]}];
+                                           [#compression{methods = [<<"zlib">>]}];
                                        _ ->
                                            []
                                    end,
@@ -430,18 +397,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                                        (TLSEnabled == false) andalso
                                        (SockMod == gen_tcp) of
                                        true ->
-                                           case TLSRequired of
-                                               true ->
-                                                   [#xmlel{name = <<"starttls">>,
-                                                           attrs = [{<<"xmlns">>, ?NS_TLS}],
-                                                           children = [#xmlel{name = <<"required">>,
-                                                                   attrs = [],
-                                                                   children = []}]}];
-                                               _ ->
-                                                   [#xmlel{name = <<"starttls">>,
-                                                           attrs = [{<<"xmlns">>, ?NS_TLS}],
-                                                           children = []}]
-                                           end;
+                                           [#starttls{required = TLSRequired}];
                                        false ->
                                            []
                                    end,
@@ -449,9 +405,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                                    StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features,
                                            Server, StreamFeatures1, [Server]),
                                    send_element(StateData,
-                                       #xmlel{name = <<"stream:features">>,
-                                           attrs = [],
-                                           children = StreamFeatures}),
+                                                #stream_features{sub_els = StreamFeatures}),
                                    fsm_next_state(wait_for_feature_request,
                                        StateData#state{server = Server,
                                            sasl_state = SASLState,
@@ -466,12 +420,8 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                                            StreamManagementFeature =
                                                case stream_mgmt_enabled(StateData) of
                                                true ->
-                                                   [#xmlel{name = <<"sm">>,
-                                                           attrs = [{<<"xmlns">>, ?NS_STREAM_MGMT_2}],
-                                                           children = []},
-                                                       #xmlel{name = <<"sm">>,
-                                                           attrs = [{<<"xmlns">>, ?NS_STREAM_MGMT_3}],
-                                                           children = []}];
+                                                   [#feature_sm{xmlns = ?NS_STREAM_MGMT_2},
+                                                    #feature_sm{xmlns = ?NS_STREAM_MGMT_3}];
                                                false ->
                                                    []
                                            end,
@@ -483,21 +433,12 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                                                case Zlib andalso
                                                    ((SockMod == gen_tcp) orelse (SockMod == fast_tls)) of
                                                    true ->
-                                                       [#xmlel{name = <<"compression">>,
-                                                               attrs = [{<<"xmlns">>, ?NS_FEATURE_COMPRESS}],
-                                                               children = [#xmlel{name = <<"method">>,
-                                                                                  attrs = [],
-                                                                                  children = [{xmlcdata, <<"zlib">>}]}]}];
+                                                       [#compression{methods = [<<"zlib">>]}];
                                                    _ ->
                                                        []
                                                end,
-                                           StreamFeatures1 = [#xmlel{name = <<"bind">>,
-                                                       attrs = [{<<"xmlns">>, ?NS_BIND}],
-                                                       children = []},
-                                                   #xmlel{name = <<"session">>,
-                                                       attrs = [{<<"xmlns">>, ?NS_SESSION}],
-                                                       children =
-                                                           [#xmlel{name = <<"optional">>}]}]
+                                           StreamFeatures1 =
+                                               [#bind{}, #xmpp_session{optional = true}]
                                                ++
                                                RosterVersioningFeature ++
                                                StreamManagementFeature ++
@@ -507,16 +448,11 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                                            StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features,
                                                    Server, StreamFeatures1, [Server]),
                                            send_element(StateData,
-                                               #xmlel{name = <<"stream:features">>,
-                                                   attrs = [],
-                                                   children = StreamFeatures}),
+                                                        #stream_features{sub_els = StreamFeatures}),
                                            fsm_next_state(wait_for_bind,
                                                StateData#state{server = Server, lang = Lang});
                                        _ ->
-                                           send_element(StateData,
-                                               #xmlel{name = <<"stream:features">>,
-                                                   attrs = [],
-                                                   children = []}),
+                                           send_element(StateData, #stream_features{}),
                                            fsm_next_state(session_established,
                                                StateData#state{server = Server, lang = Lang})
                                    end
@@ -525,9 +461,10 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                            send_header(StateData, Server, <<"">>, DefaultLang),
                            if not StateData#state.tls_enabled and
                                        StateData#state.tls_required ->
-                                   send_element(StateData,
-                                       ?POLICY_VIOLATION_ERR(Lang,
-                                           <<"Use of STARTTLS required">>)),
+                                   send_element(
+                                     StateData,
+                                     xmpp:serr_policy_violation(
+                                       <<"Use of STARTTLS required">>, Lang)),
                                    {stop, normal, StateData};
                                true ->
                                    fsm_next_state(wait_for_auth,
@@ -541,183 +478,151 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
                    ?INFO_MSG("Connection attempt from blacklisted IP ~s: ~s",
                        [jlib:ip_to_list(IP), LogReason]),
                    send_header(StateData, Server, StreamVersion, DefaultLang),
-                   send_element(StateData, ?POLICY_VIOLATION_ERR(Lang, ReasonT)),
+                   send_element(StateData, xmpp:serr_policy_violation(ReasonT, Lang)),
                    {stop, normal, StateData};
                _ ->
                    send_header(StateData, ?MYNAME, StreamVersion, DefaultLang),
-                   send_element(StateData, ?HOST_UNKNOWN_ERR),
+                   send_element(StateData, xmpp:serr_host_unknown()),
                    {stop, normal, StateData}
            end;
        _ ->
            send_header(StateData, ?MYNAME, <<"">>, DefaultLang),
-           send_element(StateData, ?INVALID_NS_ERR),
+           send_element(StateData, xmpp:serr_invalid_namespace()),
            {stop, normal, StateData}
     end;
 wait_for_stream(timeout, StateData) ->
     {stop, normal, StateData};
 wait_for_stream({xmlstreamelement, _}, StateData) ->
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 wait_for_stream({xmlstreamend, _}, StateData) ->
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 wait_for_stream({xmlstreamerror, _}, StateData) ->
     send_header(StateData, ?MYNAME, <<"1.0">>, <<"">>),
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 wait_for_stream(closed, StateData) ->
     {stop, normal, StateData};
 wait_for_stream(stop, StateData) ->
     {stop, normal, StateData}.
 
-wait_for_auth({xmlstreamelement, #xmlel{name = Name} = El}, StateData)
-       when ?IS_STREAM_MGMT_TAG(Name) ->
-    fsm_next_state(wait_for_auth, dispatch_stream_mgmt(El, StateData));
-wait_for_auth({xmlstreamelement, El}, StateData) ->
-    case is_auth_packet(El) of
-       {auth, _ID, get, {U, _, _, _}} ->
-           #xmlel{name = Name, attrs = Attrs} = jlib:make_result_iq_reply(El),
-           case U of
-               <<"">> -> UCdata = [];
-               _ -> UCdata = [{xmlcdata, U}]
-           end,
-           Res = case
-               ejabberd_auth:plain_password_required(StateData#state.server)
-           of
-               false ->
-                   #xmlel{name = Name, attrs = Attrs,
-                       children =
-                       [#xmlel{name = <<"query">>,
-                               attrs = [{<<"xmlns">>, ?NS_AUTH}],
-                               children =
-                               [#xmlel{name = <<"username">>,
-                                       attrs = [],
-                                       children = UCdata},
-                                   #xmlel{name = <<"password">>,
-                                       attrs = [], children = []},
-                                   #xmlel{name = <<"digest">>,
-                                       attrs = [], children = []},
-                                   #xmlel{name = <<"resource">>,
-                                       attrs = [],
-                                       children = []}]}]};
-               true ->
-                   #xmlel{name = Name, attrs = Attrs,
-                       children =
-                       [#xmlel{name = <<"query">>,
-                               attrs = [{<<"xmlns">>, ?NS_AUTH}],
-                               children =
-                               [#xmlel{name = <<"username">>,
-                                       attrs = [],
-                                       children = UCdata},
-                                   #xmlel{name = <<"password">>,
-                                       attrs = [], children = []},
-                                   #xmlel{name = <<"resource">>,
-                                       attrs = [],
-                                       children = []}]}]}
-           end,
-           send_element(StateData, Res),
+wait_for_auth({xmlstreamelement, #xmlel{} = El}, StateData) ->
+    decode_element(El, wait_for_auth, StateData);
+wait_for_auth(Pkt, StateData) when ?IS_STREAM_MGMT_PACKET(Pkt) ->
+    fsm_next_state(wait_for_auth, dispatch_stream_mgmt(Pkt, StateData));
+wait_for_auth(#iq{type = get,
+                 sub_els = [#legacy_auth{username = U}]} = IQ, StateData) ->
+    Username = case U of
+                  undefined -> none;
+                  _ -> U
+              end,
+    Auth = #legacy_auth{username = Username, password = none, resource = none},
+    Res = case ejabberd_auth:plain_password_required(StateData#state.server) of
+             false ->
+                 xmpp:make_iq_result(IQ, Auth#legacy_auth{digest = none});
+             true ->
+                 xmpp:make_iq_result(IQ, Auth)
+         end,
+    send_element(StateData, Res),
+    fsm_next_state(wait_for_auth, StateData);
+wait_for_auth(#iq{type = set, sub_els = [#legacy_auth{resource = <<"">>}]} = IQ,
+             StateData) ->
+    Lang = StateData#state.lang,
+    Txt = <<"No resource provided">>,
+    Err = xmpp:make_error(IQ, xmpp:err_not_acceptable(Txt, Lang)),
+    send_element(StateData, Err),
+    fsm_next_state(wait_for_auth, StateData);
+wait_for_auth(#iq{type = set, sub_els = [#legacy_auth{username = U,
+                                                     password = P0,
+                                                     digest = D0,
+                                                     resource = R}]} = IQ,
+             StateData) when is_binary(U), is_binary(R) ->
+    JID = jid:make(U, StateData#state.server, R),
+    case (JID /= error) andalso
+       acl:access_matches(StateData#state.access,
+                          #{usr => jid:split(JID), ip => StateData#state.ip},
+                          StateData#state.server) == allow of
+       true ->
+           DGen = fun (PW) ->
+                          p1_sha:sha(<<(StateData#state.streamid)/binary, PW/binary>>)
+                  end,
+           P = if is_binary(P0) -> P0; true -> <<>> end,
+           D = if is_binary(D0) -> D0; true -> <<>> end,
+           case ejabberd_auth:check_password_with_authmodule(
+                  U, U, StateData#state.server, P, D, DGen) of
+               {true, AuthModule} ->
+                   ?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s",
+                             [StateData#state.socket,
+                              jid:to_string(JID), AuthModule,
+                              ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+                   ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                                      [true, U, StateData#state.server,
+                                       StateData#state.ip]),
+                   Conn = get_conn_type(StateData),
+                   Info = [{ip, StateData#state.ip}, {conn, Conn},
+                           {auth_module, AuthModule}],
+                   Res = xmpp:make_iq_result(IQ),
+                   send_element(StateData, Res),
+                   ejabberd_sm:open_session(StateData#state.sid, U,
+                                            StateData#state.server, R,
+                                            Info),
+                   change_shaper(StateData, JID),
+                   {Fs, Ts} = ejabberd_hooks:run_fold(
+                                roster_get_subscription_lists,
+                                StateData#state.server,
+                                {[], []},
+                                [U, StateData#state.server]),
+                   LJID = jid:tolower(jid:remove_resource(JID)),
+                   Fs1 = [LJID | Fs],
+                   Ts1 = [LJID | Ts],
+                   PrivList = ejabberd_hooks:run_fold(privacy_get_user_list,
+                                                      StateData#state.server,
+                                                      #userlist{},
+                                                      [U, StateData#state.server]),
+                   NewStateData = StateData#state{
+                                    user = U,
+                                    resource = R,
+                                    jid = JID,
+                                    conn = Conn,
+                                    auth_module = AuthModule,
+                                    pres_f = (?SETS):from_list(Fs1),
+                                    pres_t = (?SETS):from_list(Ts1),
+                                    privacy_list = PrivList},
+                   fsm_next_state(session_established, NewStateData);
+               _ ->
+                   ?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s",
+                             [StateData#state.socket,
+                              jid:to_string(JID),
+                              ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+                   ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                                      [false, U, StateData#state.server,
+                                       StateData#state.ip]),
+                   Lang = StateData#state.lang,
+                   Txt = <<"Legacy authentication failed">>,
+                   Err = xmpp:make_error(IQ, xmpp:err_not_authorized(Txt, Lang)),
+                   send_element(StateData, Err),
+                   fsm_next_state(wait_for_auth, StateData)
+           end;
+       false when JID == error ->
+           ?INFO_MSG("(~w) Forbidden legacy authentication "
+                     "for username '~s' with resource '~s'",
+                     [StateData#state.socket, U, R]),
+           Err = xmpp:make_error(IQ, xmpp:err_jid_malformed()),
+           send_element(StateData, Err),
            fsm_next_state(wait_for_auth, StateData);
-       {auth, _ID, set, {_U, _P, _D, <<"">>}} ->
+       false ->
+           ?INFO_MSG("(~w) Forbidden legacy authentication for ~s from ~s",
+                     [StateData#state.socket,
+                      jid:to_string(JID),
+                      ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                              [false, U, StateData#state.server,
+                               StateData#state.ip]),
            Lang = StateData#state.lang,
-           Txt = <<"No resource provided">>,
-           Err = jlib:make_error_reply(El, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)),
+           Txt = <<"Legacy authentication forbidden">>,
+           Err = xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)),
            send_element(StateData, Err),
-           fsm_next_state(wait_for_auth, StateData);
-       {auth, _ID, set, {U, P, D, R}} ->
-           JID = jid:make(U, StateData#state.server, R),
-           case JID /= error andalso
-               acl:access_matches(StateData#state.access,
-                                  #{usr => jid:split(JID), ip => StateData#state.ip},
-                                  StateData#state.server) == allow
-           of
-               true ->
-                   DGen = fun (PW) ->
-                           p1_sha:sha(<<(StateData#state.streamid)/binary, PW/binary>>)
-                   end,
-               case ejabberd_auth:check_password_with_authmodule(U, U,
-                           StateData#state.server,
-                           P, D, DGen)
-                   of
-                       {true, AuthModule} ->
-                           ?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s",
-                               [StateData#state.socket,
-                                   jid:to_string(JID), AuthModule,
-                                   ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-                           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                               [true, U, StateData#state.server,
-                                   StateData#state.ip]),
-                           Conn = get_conn_type(StateData),
-                           Info = [{ip, StateData#state.ip}, {conn, Conn},
-                                   {auth_module, AuthModule}],
-                           Res = jlib:make_result_iq_reply(
-                                   El#xmlel{children = []}),
-                           send_element(StateData, Res),
-                           ejabberd_sm:open_session(StateData#state.sid, U,
-                               StateData#state.server, R,
-                               Info),
-                           change_shaper(StateData, JID),
-                           {Fs, Ts} =
-                               ejabberd_hooks:run_fold(roster_get_subscription_lists,
-                                   StateData#state.server,
-                                   {[], []},
-                                   [U, StateData#state.server]),
-                           LJID = jid:tolower(jid:remove_resource(JID)),
-                           Fs1 = [LJID | Fs],
-                           Ts1 = [LJID | Ts],
-                           PrivList = ejabberd_hooks:run_fold(privacy_get_user_list,
-                                   StateData#state.server,
-                                   #userlist{},
-                                   [U, StateData#state.server]),
-                           NewStateData = StateData#state{user = U,
-                                   resource = R,
-                                   jid = JID,
-                                   conn = Conn,
-                                   auth_module = AuthModule,
-                                   pres_f = (?SETS):from_list(Fs1),
-                                   pres_t = (?SETS):from_list(Ts1),
-                                   privacy_list = PrivList},
-                           fsm_next_state(session_established, NewStateData);
-                       _ ->
-                           ?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s",
-                               [StateData#state.socket,
-                                   jid:to_string(JID),
-                                   ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-                           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                               [false, U, StateData#state.server,
-                                   StateData#state.ip]),
-                           Lang = StateData#state.lang,
-                           Txt = <<"Legacy authentication failed">>,
-                           Err = jlib:make_error_reply(
-                                   El, ?ERRT_NOT_AUTHORIZED(Lang, Txt)),
-                           send_element(StateData, Err),
-                           fsm_next_state(wait_for_auth, StateData)
-                   end;
-               _ ->
-                   if JID == error ->
-                           ?INFO_MSG("(~w) Forbidden legacy authentication "
-                               "for username '~s' with resource '~s'",
-                               [StateData#state.socket, U, R]),
-                           Err = jlib:make_error_reply(El, ?ERR_JID_MALFORMED),
-                           send_element(StateData, Err),
-                           fsm_next_state(wait_for_auth, StateData);
-                       true ->
-                           ?INFO_MSG("(~w) Forbidden legacy authentication "
-                               "for ~s from ~s",
-                               [StateData#state.socket,
-                                   jid:to_string(JID),
-                                   ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-                           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                               [false, U, StateData#state.server,
-                                   StateData#state.ip]),
-                           Lang = StateData#state.lang,
-                           Txt = <<"Legacy authentication forbidden">>,
-                           Err = jlib:make_error_reply(El, ?ERRT_NOT_ALLOWED(Lang, Txt)),
-                           send_element(StateData, Err),
-                           fsm_next_state(wait_for_auth, StateData)
-                   end
-           end;
-       _ ->
-           process_unauthenticated_stanza(StateData, El),
            fsm_next_state(wait_for_auth, StateData)
     end;
 wait_for_auth(timeout, StateData) ->
@@ -725,127 +630,97 @@ wait_for_auth(timeout, StateData) ->
 wait_for_auth({xmlstreamend, _Name}, StateData) ->
     {stop, normal, StateData};
 wait_for_auth({xmlstreamerror, _}, StateData) ->
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 wait_for_auth(closed, StateData) ->
     {stop, normal, StateData};
 wait_for_auth(stop, StateData) ->
-    {stop, normal, StateData}.
+    {stop, normal, StateData};
+wait_for_auth(Pkt, StateData) ->
+    process_unauthenticated_stanza(StateData, Pkt),
+    fsm_next_state(wait_for_auth, StateData).
 
-wait_for_feature_request({xmlstreamelement, #xmlel{name = Name} = El},
-                        StateData)
-    when ?IS_STREAM_MGMT_TAG(Name) ->
+wait_for_feature_request({xmlstreamelement, El}, StateData) ->
+    decode_element(El, wait_for_feature_request, StateData);
+wait_for_feature_request(Pkt, StateData) when ?IS_STREAM_MGMT_PACKET(Pkt) ->
     fsm_next_state(wait_for_feature_request,
-                  dispatch_stream_mgmt(El, StateData));
-wait_for_feature_request({xmlstreamelement, El},
-                        StateData) ->
-    #xmlel{name = Name, attrs = Attrs, children = Els} = El,
+                  dispatch_stream_mgmt(Pkt, StateData));
+wait_for_feature_request(#sasl_auth{mechanism = Mech,
+                                   text = ClientIn},
+                        #state{tls_enabled = TLSEnabled,
+                               tls_required = TLSRequired} = StateData)
+  when TLSEnabled or not TLSRequired ->
+    case cyrsasl:server_start(StateData#state.sasl_state, Mech, ClientIn) of
+       {ok, Props} ->
+           (StateData#state.sockmod):reset_stream(StateData#state.socket),
+           U = identity(Props),
+           AuthModule = proplists:get_value(auth_module, Props, undefined),
+           ?INFO_MSG("(~w) Accepted authentication for ~s by ~p from ~s",
+                     [StateData#state.socket, U, AuthModule,
+                      ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                              [true, U, StateData#state.server,
+                               StateData#state.ip]),
+           send_element(StateData, #sasl_success{}),
+           fsm_next_state(wait_for_stream,
+                          StateData#state{streamid = new_id(),
+                                          authenticated = true,
+                                          auth_module = AuthModule,
+                                          sasl_state = undefined,
+                                          user = U});
+       {continue, ServerOut, NewSASLState} ->
+           send_element(StateData, #sasl_challenge{text = ServerOut}),
+           fsm_next_state(wait_for_sasl_response,
+                          StateData#state{sasl_state = NewSASLState});
+       {error, Error, Username} ->
+           ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
+                     [StateData#state.socket,
+                      Username, StateData#state.server,
+                      ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                              [false, Username, StateData#state.server,
+                               StateData#state.ip]),
+           send_element(StateData, #sasl_failure{reason = Error}),
+           fsm_next_state(wait_for_feature_request, StateData);
+       {error, Error} ->
+           send_element(StateData, #sasl_failure{reason = Error}),
+           fsm_next_state(wait_for_feature_request, StateData)
+    end;
+wait_for_feature_request(#starttls{},
+                        #state{tls = true, tls_enabled = false} = StateData) ->
+    case (StateData#state.sockmod):get_sockmod(StateData#state.socket) of
+       gen_tcp ->
+           TLSOpts = case ejabberd_config:get_option(
+                            {domain_certfile, StateData#state.server},
+                            fun iolist_to_binary/1) of
+                         undefined ->
+                             StateData#state.tls_options;
+                         CertFile ->
+                             lists:keystore(certfile, 1,
+                                            StateData#state.tls_options,
+                                            {certfile, CertFile})
+                     end,
+           Socket = StateData#state.socket,
+           BProceed = fxml:element_to_binary(xmpp:encode(#starttls_proceed{})),
+           TLSSocket = (StateData#state.sockmod):starttls(Socket, TLSOpts, BProceed),
+           fsm_next_state(wait_for_stream,
+                          StateData#state{socket = TLSSocket,
+                                          streamid = new_id(),
+                                          tls_enabled = true});
+       _ ->
+           Lang = StateData#state.lang,
+           Txt = <<"Unsupported TLS transport">>,
+           send_element(StateData, xmpp:serr_policy_violation(Txt, Lang)),
+           {stop, normal, StateData}
+    end;
+wait_for_feature_request(#compress{} = Comp, StateData) ->
     Zlib = StateData#state.zlib,
-    TLS = StateData#state.tls,
-    TLSEnabled = StateData#state.tls_enabled,
-    TLSRequired = StateData#state.tls_required,
-    SockMod =
-       (StateData#state.sockmod):get_sockmod(StateData#state.socket),
-    case {fxml:get_attr_s(<<"xmlns">>, Attrs), Name} of
-      {?NS_SASL, <<"auth">>}
-         when TLSEnabled or not TLSRequired ->
-         Mech = fxml:get_attr_s(<<"mechanism">>, Attrs),
-         ClientIn = jlib:decode_base64(fxml:get_cdata(Els)),
-         case cyrsasl:server_start(StateData#state.sasl_state,
-                                   Mech, ClientIn)
-             of
-           {ok, Props} ->
-               (StateData#state.sockmod):reset_stream(StateData#state.socket),
-               U = identity(Props),
-               AuthModule = proplists:get_value(auth_module, Props, undefined),
-               ?INFO_MSG("(~w) Accepted authentication for ~s "
-                         "by ~p from ~s",
-                         [StateData#state.socket, U, AuthModule,
-                          ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-               ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                                  [true, U, StateData#state.server,
-                                   StateData#state.ip]),
-               send_element(StateData,
-                           #xmlel{name = <<"success">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children = []}),
-               fsm_next_state(wait_for_stream,
-                               StateData#state{streamid = new_id(),
-                                               authenticated = true,
-                                               auth_module = AuthModule,
-                                                sasl_state = undefined,
-                                               user = U});
-           {continue, ServerOut, NewSASLState} ->
-               send_element(StateData,
-                            #xmlel{name = <<"challenge">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children =
-                                       [{xmlcdata,
-                                         jlib:encode_base64(ServerOut)}]}),
-               fsm_next_state(wait_for_sasl_response,
-                              StateData#state{sasl_state = NewSASLState});
-           {error, Error, Username} ->
-               ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
-                       [StateData#state.socket,
-                           Username, StateData#state.server,
-                           ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-               ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                                  [false, Username, StateData#state.server,
-                                   StateData#state.ip]),
-               send_element(StateData,
-                            #xmlel{name = <<"failure">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children =
-                                       [#xmlel{name = Error, attrs = [],
-                                               children = []}]}),
-               fsm_next_state(wait_for_feature_request, StateData);
-           {error, Error} ->
-               send_element(StateData,
-                            #xmlel{name = <<"failure">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children =
-                                       [#xmlel{name = Error, attrs = [],
-                                               children = []}]}),
-               fsm_next_state(wait_for_feature_request, StateData)
-         end;
-      {?NS_TLS, <<"starttls">>}
-         when TLS == true, TLSEnabled == false,
-              SockMod == gen_tcp ->
-         TLSOpts = case
-                     ejabberd_config:get_option(
-                        {domain_certfile, StateData#state.server},
-                        fun iolist_to_binary/1)
-                       of
-                     undefined -> StateData#state.tls_options;
-                     CertFile ->
-                         [{certfile, CertFile} | lists:keydelete(certfile, 1,
-                                                                 StateData#state.tls_options)]
-                   end,
-         Socket = StateData#state.socket,
-         BProceed = fxml:element_to_binary(#xmlel{name = <<"proceed">>,
-                                                 attrs = [{<<"xmlns">>, ?NS_TLS}]}),
-         TLSSocket = (StateData#state.sockmod):starttls(Socket,
-                                                        TLSOpts,
-                                                        BProceed),
-         fsm_next_state(wait_for_stream,
-                        StateData#state{socket = TLSSocket,
-                                        streamid = new_id(),
-                                        tls_enabled = true});
-      {?NS_COMPRESS, <<"compress">>}
-         when Zlib == true,
-              (SockMod == gen_tcp) or (SockMod == fast_tls) ->
-         process_compression_request(El, wait_for_feature_request, StateData);
-      _ ->
-         if TLSRequired and not TLSEnabled ->
-                Lang = StateData#state.lang,
-                send_element(StateData,
-                             ?POLICY_VIOLATION_ERR(Lang,
-                                                   <<"Use of STARTTLS required">>)),
-                {stop, normal, StateData};
-            true ->
-                process_unauthenticated_stanza(StateData, El),
-                fsm_next_state(wait_for_feature_request, StateData)
-         end
+    SockMod = (StateData#state.sockmod):get_sockmod(StateData#state.socket),
+    if Zlib == true, (SockMod == gen_tcp) or (SockMod == fast_tls) ->
+           process_compression_request(Comp, wait_for_feature_request, StateData);
+       true ->
+           send_element(StateData, #compress_failure{reason = 'setup-failed'}),
+           fsm_next_state(wait_for_feature_request, StateData)
     end;
 wait_for_feature_request(timeout, StateData) ->
     {stop, normal, StateData};
@@ -854,106 +729,82 @@ wait_for_feature_request({xmlstreamend, _Name},
     {stop, normal, StateData};
 wait_for_feature_request({xmlstreamerror, _},
                         StateData) ->
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 wait_for_feature_request(closed, StateData) ->
     {stop, normal, StateData};
 wait_for_feature_request(stop, StateData) ->
-    {stop, normal, StateData}.
-
-wait_for_sasl_response({xmlstreamelement, #xmlel{name = Name} = El}, StateData)
-    when ?IS_STREAM_MGMT_TAG(Name) ->
-    fsm_next_state(wait_for_sasl_response, dispatch_stream_mgmt(El, StateData));
-wait_for_sasl_response({xmlstreamelement, El},
-                      StateData) ->
-    #xmlel{name = Name, attrs = Attrs, children = Els} = El,
-    case {fxml:get_attr_s(<<"xmlns">>, Attrs), Name} of
-      {?NS_SASL, <<"response">>} ->
-         ClientIn = jlib:decode_base64(fxml:get_cdata(Els)),
-         case cyrsasl:server_step(StateData#state.sasl_state,
-                                  ClientIn)
-             of
-           {ok, Props} ->
-               catch
-                 (StateData#state.sockmod):reset_stream(StateData#state.socket),
-               U = identity(Props),
-               AuthModule = proplists:get_value(auth_module, Props, <<>>),
-               ?INFO_MSG("(~w) Accepted authentication for ~s "
-                         "by ~p from ~s",
-                         [StateData#state.socket, U, AuthModule,
-                          ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-               ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                                  [true, U, StateData#state.server,
-                                   StateData#state.ip]),
-               send_element(StateData,
-                           #xmlel{name = <<"success">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children = []}),
-               fsm_next_state(wait_for_stream,
-                               StateData#state{streamid = new_id(),
-                                               authenticated = true,
-                                               auth_module = AuthModule,
-                                                sasl_state = undefined,
-                                               user = U});
-           {ok, Props, ServerOut} ->
-               (StateData#state.sockmod):reset_stream(StateData#state.socket),
-               U = identity(Props),
-               AuthModule = proplists:get_value(auth_module, Props, undefined),
-               ?INFO_MSG("(~w) Accepted authentication for ~s "
-                         "by ~p from ~s",
-                         [StateData#state.socket, U, AuthModule,
-                          ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-               ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                                  [true, U, StateData#state.server,
-                                   StateData#state.ip]),
-               send_element(StateData,
-                           #xmlel{name = <<"success">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children =
-                                       [{xmlcdata,
-                                       jlib:encode_base64(ServerOut)}]}),
-               fsm_next_state(wait_for_stream,
-                               StateData#state{streamid = new_id(),
-                                               authenticated = true,
-                                               auth_module = AuthModule,
-                                                sasl_state = undefined,
-                                               user = U});
-           {continue, ServerOut, NewSASLState} ->
-               send_element(StateData,
-                            #xmlel{name = <<"challenge">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children =
-                                       [{xmlcdata,
-                                         jlib:encode_base64(ServerOut)}]}),
-               fsm_next_state(wait_for_sasl_response,
-                              StateData#state{sasl_state = NewSASLState});
-           {error, Error, Username} ->
-               ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
-                          [StateData#state.socket,
-                           Username, StateData#state.server,
-                           ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
-               ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
-                                  [false, Username, StateData#state.server,
-                                   StateData#state.ip]),
-               send_element(StateData,
-                            #xmlel{name = <<"failure">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children =
-                                       [#xmlel{name = Error, attrs = [],
-                                               children = []}]}),
-               fsm_next_state(wait_for_feature_request, StateData);
-           {error, Error} ->
-               send_element(StateData,
-                            #xmlel{name = <<"failure">>,
-                                   attrs = [{<<"xmlns">>, ?NS_SASL}],
-                                   children =
-                                       [#xmlel{name = Error, attrs = [],
-                                               children = []}]}),
-               fsm_next_state(wait_for_feature_request, StateData)
-         end;
-      _ ->
-         process_unauthenticated_stanza(StateData, El),
-         fsm_next_state(wait_for_feature_request, StateData)
+    {stop, normal, StateData};
+wait_for_feature_request(_Pkt,
+                        #state{tls_required = TLSRequired,
+                               tls_enabled = TLSEnabled} = StateData)
+  when TLSRequired and not TLSEnabled ->
+    Lang = StateData#state.lang,
+    Txt = <<"Use of STARTTLS required">>,
+    send_element(StateData, xmpp:serr_policy_violation(Txt, Lang)),
+    {stop, normal, StateData};
+wait_for_feature_request(Pkt, StateData) ->
+    process_unauthenticated_stanza(StateData, Pkt),
+    fsm_next_state(wait_for_feature_request, StateData).
+
+wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
+    decode_element(El, wait_for_sasl_response, StateData);
+wait_for_sasl_response(Pkt, StateData) when ?IS_STREAM_MGMT_PACKET(Pkt) ->
+    fsm_next_state(wait_for_sasl_response,
+                  dispatch_stream_mgmt(Pkt, StateData));
+wait_for_sasl_response(#sasl_response{text = ClientIn}, StateData) ->
+    case cyrsasl:server_step(StateData#state.sasl_state, ClientIn) of
+       {ok, Props} ->
+           catch (StateData#state.sockmod):reset_stream(StateData#state.socket),
+           U = identity(Props),
+           AuthModule = proplists:get_value(auth_module, Props, <<>>),
+           ?INFO_MSG("(~w) Accepted authentication for ~s by ~p from ~s",
+                     [StateData#state.socket, U, AuthModule,
+                      ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                              [true, U, StateData#state.server,
+                               StateData#state.ip]),
+           send_element(StateData, #sasl_success{}),
+           fsm_next_state(wait_for_stream,
+                          StateData#state{streamid = new_id(),
+                                          authenticated = true,
+                                          auth_module = AuthModule,
+                                          sasl_state = undefined,
+                                          user = U});
+       {ok, Props, ServerOut} ->
+           (StateData#state.sockmod):reset_stream(StateData#state.socket),
+           U = identity(Props),
+           AuthModule = proplists:get_value(auth_module, Props, undefined),
+           ?INFO_MSG("(~w) Accepted authentication for ~s by ~p from ~s",
+                     [StateData#state.socket, U, AuthModule,
+                      ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                              [true, U, StateData#state.server,
+                               StateData#state.ip]),
+           send_element(StateData, #sasl_success{text = ServerOut}),
+           fsm_next_state(wait_for_stream,
+                          StateData#state{streamid = new_id(),
+                                          authenticated = true,
+                                          auth_module = AuthModule,
+                                          sasl_state = undefined,
+                                          user = U});
+       {continue, ServerOut, NewSASLState} ->
+           send_element(StateData, #sasl_challenge{text = ServerOut}),
+           fsm_next_state(wait_for_sasl_response,
+                          StateData#state{sasl_state = NewSASLState});
+       {error, Error, Username} ->
+           ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
+                     [StateData#state.socket,
+                      Username, StateData#state.server,
+                      ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
+           ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
+                              [false, Username, StateData#state.server,
+                               StateData#state.ip]),
+           send_element(StateData, #sasl_failure{reason = Error}),
+           fsm_next_state(wait_for_feature_request, StateData);
+       {error, Error} ->
+           send_element(StateData, #sasl_failure{reason = Error}),
+           fsm_next_state(wait_for_feature_request, StateData)
     end;
 wait_for_sasl_response(timeout, StateData) ->
     {stop, normal, StateData};
@@ -962,13 +813,18 @@ wait_for_sasl_response({xmlstreamend, _Name},
     {stop, normal, StateData};
 wait_for_sasl_response({xmlstreamerror, _},
                       StateData) ->
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 wait_for_sasl_response(closed, StateData) ->
     {stop, normal, StateData};
 wait_for_sasl_response(stop, StateData) ->
-    {stop, normal, StateData}.
+    {stop, normal, StateData};
+wait_for_sasl_response(Pkt, StateData) ->
+    process_unauthenticated_stanza(StateData, Pkt),
+    fsm_next_state(wait_for_feature_request, StateData).
 
+-spec resource_conflict_action(binary(), binary(), binary()) ->
+                                     {accept_resource, binary()} | closenew.
 resource_conflict_action(U, S, R) ->
     OptionRaw = case ejabberd_sm:is_existing_resource(U, S, R) of
                  true ->
@@ -998,108 +854,116 @@ resource_conflict_action(U, S, R) ->
          {accept_resource, Rnew}
     end.
 
-wait_for_bind({xmlstreamelement, #xmlel{name = Name, attrs = Attrs} = El},
-             StateData)
-    when ?IS_STREAM_MGMT_TAG(Name) ->
-    case Name of
-      <<"resume">> ->
-         case handle_resume(StateData, Attrs) of
-           {ok, ResumedState} ->
-               fsm_next_state(session_established, ResumedState);
-           error ->
-               fsm_next_state(wait_for_bind, StateData)
-         end;
-      _ ->
-         fsm_next_state(wait_for_bind, dispatch_stream_mgmt(El, StateData))
-    end;
-wait_for_bind({xmlstreamelement, El}, StateData) ->
-    case jlib:iq_query_info(El) of
-      #iq{type = set, lang = Lang, xmlns = ?NS_BIND, sub_el = SubEl} =
-         IQ ->
-         U = StateData#state.user,
-         R1 = fxml:get_path_s(SubEl,
-                             [{elem, <<"resource">>}, cdata]),
-         R = case jid:resourceprep(R1) of
-               error -> error;
-               <<"">> -> new_uniq_id();
-               Resource -> Resource
-             end,
-         case R of
-           error ->
-               Txt = <<"Malformed resource">>,
-               Err = jlib:make_error_reply(El, ?ERRT_BAD_REQUEST(Lang, Txt)),
-               send_element(StateData, Err),
-               fsm_next_state(wait_for_bind, StateData);
-           _ ->
-               case resource_conflict_action(U, StateData#state.server,
-                                             R)
-                   of
-                 closenew ->
-                     Err = jlib:make_error_reply(El,
-                                                 ?STANZA_ERROR(<<"409">>,
-                                                               <<"modify">>,
-                                                               <<"conflict">>)),
-                     send_element(StateData, Err),
-                     fsm_next_state(wait_for_bind, StateData);
-                 {accept_resource, R2} ->
-                        JID = jid:make(U, StateData#state.server, R2),
-                        StateData2 =
-                            StateData#state{resource = R2, jid = JID},
-                        case open_session(StateData2) of
-                            {ok, StateData3} ->
-                                Res =
-                                    IQ#iq{
-                                      type = result,
-                                      sub_el =
-                                      [#xmlel{name = <<"bind">>,
-                                              attrs = [{<<"xmlns">>, ?NS_BIND}],
-                                              children =
-                                              [#xmlel{name = <<"jid">>,
-                                                      attrs = [],
-                                                      children =
-                                                      [{xmlcdata,
-                                                        jid:to_string(JID)}]}]}]},
-                               try
-                                   send_element(StateData3, jlib:iq_to_xml(Res))
-                               catch exit:normal ->
-                                       close(self())
-                               end,
-                                fsm_next_state_pack(
-                                  session_established,
-                                  StateData3);
-                            {error, Error} ->
-                                Err = jlib:make_error_reply(El, Error),
-                                send_element(StateData, Err),
-                                fsm_next_state(wait_for_bind, StateData)
-                        end
-               end
-         end;
-       _ ->
-           #xmlel{name = Name, attrs = Attrs, children = _Els} = El,
-           Zlib = StateData#state.zlib,
-           SockMod =
-               (StateData#state.sockmod):get_sockmod(StateData#state.socket),
-           case {fxml:get_attr_s(<<"xmlns">>, Attrs), Name} of
-               {?NS_COMPRESS, <<"compress">>}
-               when Zlib == true,
-                    (SockMod == gen_tcp) or (SockMod == fast_tls) ->
-                   process_compression_request(El, wait_for_bind, StateData);
+-spec decode_subels(stanza()) -> stanza().
+decode_subels(#iq{sub_els = [El], type = T} = IQ) when T == set; T == get ->
+    NewEl = case xmpp:get_ns(El) of
+               ?NS_BIND when T == set -> xmpp:decode(El);
+               ?NS_AUTH -> xmpp:decode(El);
+               ?NS_PRIVACY -> xmpp:decode(El);
+               ?NS_BLOCKING -> xmpp:decode(El);
+               _ -> El
+           end,
+    IQ#iq{sub_els = [NewEl]};
+decode_subels(Pkt) ->
+    Pkt.
+
+-spec decode_element(xmlel(), state_name(), state()) -> fsm_next().
+decode_element(#xmlel{} = El, StateName, StateData) ->
+    try
+       Pkt0 = xmpp:decode(El, [ignore_els]),
+       Pkt = decode_subels(Pkt0),
+       ?MODULE:StateName(Pkt, StateData)
+    catch error:{xmpp_codec, Why} ->
+           Type = xmpp:get_type(El),
+           NS = xmpp:get_ns(El),
+           case xmpp:is_stanza(El) of
+               true when Type /= <<"result">>, Type /= <<"error">> ->
+                   Lang = xmpp:get_lang(El),
+                   Txt = xmpp:format_error(Why),
+                   Err = xmpp:make_error(El, xmpp:err_bad_request(Txt, Lang)),
+                   send_element(StateData, Err);
+               _ when NS == ?NS_STREAM_MGMT_2; NS == ?NS_STREAM_MGMT_3 ->
+                   Err = #sm_failed{reason = 'bad-request', xmlns = NS},
+                   send_element(StateData, Err);
                _ ->
+                   ok
+           end,
+           fsm_next_state(StateName, StateData)
+    end.
+
+wait_for_bind({xmlstreamelement, El}, StateData) ->
+    decode_element(El, wait_for_bind, StateData);
+wait_for_bind(#sm_resume{} = Pkt, StateData) ->
+    case handle_resume(StateData, Pkt) of
+       {ok, ResumedState} ->
+           fsm_next_state(session_established, ResumedState);
+       error ->
+           fsm_next_state(wait_for_bind, StateData)
+    end;
+wait_for_bind(Pkt, StateData) when ?IS_STREAM_MGMT_PACKET(Pkt) ->
+    fsm_next_state(wait_for_bind, dispatch_stream_mgmt(Pkt, StateData));
+wait_for_bind(#iq{type = set,
+                 sub_els = [#bind{resource = R}]} = IQ, StateData) ->
+    U = StateData#state.user,
+    case resource_conflict_action(U, StateData#state.server, R) of
+       closenew ->
+           Err = xmpp:make_error(IQ, xmpp:err_conflict()),
+           send_element(StateData, Err),
+           fsm_next_state(wait_for_bind, StateData);
+       {accept_resource, R2} ->
+           JID = jid:make(U, StateData#state.server, R2),
+           StateData2 = StateData#state{resource = R2, jid = JID},
+           case open_session(StateData2) of
+               {ok, StateData3} ->
+                   Res = xmpp:make_iq_result(IQ, #bind{jid = JID}),
+                   try
+                       send_element(StateData3, Res)
+                   catch
+                       exit:normal -> close(self())
+                   end,
+                   fsm_next_state_pack(session_established,StateData3);
+               {error, Error} ->
+                   Err = xmpp:make_error(IQ, Error),
+                   send_element(StateData, Err),
                    fsm_next_state(wait_for_bind, StateData)
            end
     end;
+wait_for_bind(#compress{} = Comp, StateData) ->
+    Zlib = StateData#state.zlib,
+    SockMod = (StateData#state.sockmod):get_sockmod(StateData#state.socket),
+    if Zlib == true, (SockMod == gen_tcp) or (SockMod == fast_tls) ->
+           process_compression_request(Comp, wait_for_bind, StateData);
+       true ->
+           send_element(StateData, #compress_failure{reason = 'setup-failed'}),
+           fsm_next_state(wait_for_bind, StateData)
+    end;
 wait_for_bind(timeout, StateData) ->
     {stop, normal, StateData};
 wait_for_bind({xmlstreamend, _Name}, StateData) ->
     {stop, normal, StateData};
 wait_for_bind({xmlstreamerror, _}, StateData) ->
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 wait_for_bind(closed, StateData) ->
     {stop, normal, StateData};
 wait_for_bind(stop, StateData) ->
-    {stop, normal, StateData}.
+    {stop, normal, StateData};
+wait_for_bind(Pkt, StateData) ->
+    case xmpp:is_stanza(Pkt) of
+       true ->
+           Type = xmpp:get_type(Pkt),
+           if Type /= error, Type /= result ->
+                   Err = xmpp:make_error(Pkt, xmpp:err_not_acceptable()),
+                   send_element(StateData, Err);
+              true ->
+                   ok
+           end;
+       false ->
+           ok
+    end,
+    fsm_next_state(wait_for_bind, StateData).
 
+-spec open_session(state()) -> {ok, state()} | {error, error()}.
 open_session(StateData) ->
     U = StateData#state.user,
     R = StateData#state.resource,
@@ -1145,33 +1009,18 @@ open_session(StateData) ->
             ?INFO_MSG("(~w) Forbidden session for ~s",
                       [StateData#state.socket, jid:to_string(JID)]),
            Txt = <<"Denied by ACL">>,
-            {error, ?ERRT_NOT_ALLOWED(Lang, Txt)}
+           {error, xmpp:err_not_allowed(Txt, Lang)}
     end.
 
-session_established({xmlstreamelement, #xmlel{name = Name} = El}, StateData)
-    when ?IS_STREAM_MGMT_TAG(Name) ->
-    fsm_next_state(session_established, dispatch_stream_mgmt(El, StateData));
-session_established({xmlstreamelement,
-                    #xmlel{name = <<"active">>,
-                           attrs = [{<<"xmlns">>, ?NS_CLIENT_STATE}]}},
-                   StateData) ->
+session_established({xmlstreamelement, El}, StateData) ->
+    decode_element(El, session_established, StateData);
+session_established(Pkt, StateData) when ?IS_STREAM_MGMT_PACKET(Pkt) ->
+    fsm_next_state(session_established, dispatch_stream_mgmt(Pkt, StateData));
+session_established(#csi{type = active}, StateData) ->
     NewStateData = csi_flush_queue(StateData),
     fsm_next_state(session_established, NewStateData#state{csi_state = active});
-session_established({xmlstreamelement,
-                    #xmlel{name = <<"inactive">>,
-                           attrs = [{<<"xmlns">>, ?NS_CLIENT_STATE}]}},
-                   StateData) ->
+session_established(#csi{type = inactive}, StateData) ->
     fsm_next_state(session_established, StateData#state{csi_state = inactive});
-session_established({xmlstreamelement, El},
-                   StateData) ->
-    FromJID = StateData#state.jid,
-    case check_from(El, FromJID) of
-       'invalid-from' ->
-           send_element(StateData, ?INVALID_FROM),
-           {stop, normal, StateData};
-       _NewEl ->
-           session_established2(El, StateData)
-    end;
 %% We hibernate the process to reduce memory consumption after a
 %% configurable activity timeout
 session_established(timeout, StateData) ->
@@ -1185,10 +1034,10 @@ session_established({xmlstreamerror,
                     <<"XML stanza is too big">> = E},
                    StateData) ->
     send_element(StateData,
-                ?POLICY_VIOLATION_ERR((StateData#state.lang), E)),
+                xmpp:serr_policy_violation(E, StateData#state.lang)),
     {stop, normal, StateData};
 session_established({xmlstreamerror, _}, StateData) ->
-    send_element(StateData, ?INVALID_XML_ERR),
+    send_element(StateData, xmpp:serr_not_well_formed()),
     {stop, normal, StateData};
 session_established(closed, #state{mgmt_state = active} = StateData) ->
     catch (StateData#state.sockmod):close(StateData#state.socket),
@@ -1196,92 +1045,82 @@ session_established(closed, #state{mgmt_state = active} = StateData) ->
 session_established(closed, StateData) ->
     {stop, normal, StateData};
 session_established(stop, StateData) ->
-    {stop, normal, StateData}.
+    {stop, normal, StateData};
+session_established(Pkt, StateData) ->
+    FromJID = StateData#state.jid,
+    case check_from(Pkt, FromJID) of
+       'invalid-from' ->
+           send_element(StateData, xmpp:serr_invalid_from()),
+           {stop, normal, StateData};
+       _ ->
+           NewStateData = update_num_stanzas_in(StateData, Pkt),
+           session_established2(Pkt, NewStateData)
+    end.
 
+-spec session_established2(xmpp_element(), state()) -> fsm_next().
 %% Process packets sent by user (coming from user on c2s XMPP connection)
-session_established2(El, StateData) ->
-    #xmlel{name = Name, attrs = Attrs} = El,
-    NewStateData = update_num_stanzas_in(StateData, El),
-    User = NewStateData#state.user,
-    Server = NewStateData#state.server,
-    FromJID = NewStateData#state.jid,
-    To = fxml:get_attr_s(<<"to">>, Attrs),
-    ToJID = case To of
-             <<"">> -> jid:make(User, Server, <<"">>);
-             _ -> jid:from_string(To)
-           end,
-    NewEl1 = jlib:remove_attr(<<"xmlns">>, El),
-    NewEl = case fxml:get_attr_s(<<"xml:lang">>, Attrs) of
-             <<"">> ->
-                 case NewStateData#state.lang of
-                   <<"">> -> NewEl1;
-                   Lang ->
-                       fxml:replace_tag_attr(<<"xml:lang">>, Lang, NewEl1)
-                 end;
-             _ -> NewEl1
+session_established2(Pkt, StateData) when ?is_stanza(Pkt) ->
+    User = StateData#state.user,
+    Server = StateData#state.server,
+    FromJID = StateData#state.jid,
+    ToJID = case xmpp:get_to(Pkt) of
+               undefined -> jid:make(User, Server, <<"">>);
+               J -> J
            end,
-    NewState = case ToJID of
-                error ->
-                    case fxml:get_attr_s(<<"type">>, Attrs) of
-                      <<"error">> -> NewStateData;
-                      <<"result">> -> NewStateData;
-                      _ ->
-                          Err = jlib:make_error_reply(NewEl,
-                                                      ?ERR_JID_MALFORMED),
-                          send_packet(NewStateData, Err)
-                    end;
-                _ ->
-                    case Name of
-                      <<"presence">> ->
-                          PresenceEl0 =
-                              ejabberd_hooks:run_fold(c2s_update_presence,
-                                                      Server, NewEl,
-                                                      [User, Server]),
-                          PresenceEl =
-                                ejabberd_hooks:run_fold(
-                                  user_send_packet, Server, PresenceEl0,
-                                  [NewStateData, FromJID, ToJID]),
-                          case ToJID of
-                            #jid{user = User, server = Server,
-                                 resource = <<"">>} ->
-                                ?DEBUG("presence_update(~p,~n\t~p,~n\t~p)",
-                                       [FromJID, PresenceEl, NewStateData]),
-                                presence_update(FromJID, PresenceEl,
-                                                NewStateData);
-                            _ ->
-                                presence_track(FromJID, ToJID, PresenceEl,
-                                               NewStateData)
-                          end;
-                      <<"iq">> ->
-                          case jlib:iq_query_info(NewEl) of
-                            #iq{xmlns = Xmlns} = IQ
-                                when Xmlns == (?NS_PRIVACY);
-                                     Xmlns == (?NS_BLOCKING) ->
-                                process_privacy_iq(FromJID, ToJID, IQ,
-                                                   NewStateData);
-                               #iq{xmlns = ?NS_SESSION} ->
-                                   Res = jlib:make_result_iq_reply(
-                                           NewEl#xmlel{children = []}),
-                                   send_stanza(NewStateData, Res);
-                            _ ->
-                                NewEl0 = ejabberd_hooks:run_fold(
-                                           user_send_packet, Server, NewEl,
-                                           [NewStateData, FromJID, ToJID]),
-                                check_privacy_route(FromJID, NewStateData,
-                                                    FromJID, ToJID, NewEl0)
-                          end;
-                      <<"message">> ->
-                          NewEl0 = ejabberd_hooks:run_fold(
-                                     user_send_packet, Server, NewEl,
-                                     [NewStateData, FromJID, ToJID]),
-                          check_privacy_route(FromJID, NewStateData, FromJID,
-                                              ToJID, NewEl0);
-                      _ -> NewStateData
-                    end
-              end,
+    Lang = case xmpp:get_lang(Pkt) of
+              undefined -> StateData#state.lang;
+              <<"">> -> StateData#state.lang;
+              L -> L
+          end,
+    NewPkt = xmpp:set_lang(Pkt, Lang),
+    NewState =
+       case NewPkt of
+           #presence{} ->
+               Presence0 = ejabberd_hooks:run_fold(
+                             c2s_update_presence, Server, NewPkt,
+                             [User, Server]),
+               Presence = ejabberd_hooks:run_fold(
+                            user_send_packet, Server, Presence0,
+                            [StateData, FromJID, ToJID]),
+               case ToJID of
+                   #jid{user = User, server = Server, resource = <<"">>} ->
+                       ?DEBUG("presence_update(~p,~n\t~p,~n\t~p)",
+                              [FromJID, Presence, StateData]),
+                       presence_update(FromJID, Presence,
+                                       StateData);
+                   _ ->
+                       presence_track(FromJID, ToJID, Presence,
+                                      StateData)
+               end;
+           #iq{type = T, sub_els = [El]} when T == set; T == get ->
+               NS = xmpp:get_ns(El),
+               if NS == ?NS_BLOCKING; NS == ?NS_PRIVACY ->
+                       IQ = xmpp:set_from_to(Pkt, FromJID, ToJID),
+                       process_privacy_iq(IQ, StateData);
+                  NS == ?NS_SESSION ->
+                       Res = xmpp:make_iq_result(Pkt),
+                       send_stanza(StateData, Res);
+                  true ->
+                       NewPkt0 = ejabberd_hooks:run_fold(
+                                   user_send_packet, Server, NewPkt,
+                                   [StateData, FromJID, ToJID]),
+                       check_privacy_route(FromJID, StateData, FromJID,
+                                           ToJID, NewPkt0)
+               end;
+           _ ->
+               NewPkt0 = ejabberd_hooks:run_fold(
+                           user_send_packet, Server, NewPkt,
+                           [StateData, FromJID, ToJID]),
+               check_privacy_route(FromJID, StateData, FromJID,
+                                   ToJID, NewPkt0)
+       end,
+    ejabberd_hooks:run(c2s_loop_debug,
+                      [{xmlstreamelement, Pkt}]),
+    fsm_next_state(session_established, NewState);
+session_established2(Pkt, StateData) ->
     ejabberd_hooks:run(c2s_loop_debug,
-                      [{xmlstreamelement, El}]),
-    fsm_next_state(session_established, NewState).
+                      [{xmlstreamelement, Pkt}]),
+    fsm_next_state(session_established, StateData).
 
 wait_for_resume({xmlstreamelement, _El} = Event, StateData) ->
     Result = session_established(Event, StateData),
@@ -1335,14 +1174,14 @@ handle_info({send_text, Text}, StateName, StateData) ->
     fsm_next_state(StateName, StateData);
 handle_info(replaced, StateName, StateData) ->
     Lang = StateData#state.lang,
-    Xmlelement = ?SERRT_CONFLICT(Lang, <<"Replaced by new connection">>),
-    handle_info({kick, replaced, Xmlelement}, StateName, StateData);
+    Pkt = xmpp:serr_conflict(<<"Replaced by new connection">>, Lang),
+    handle_info({kick, replaced, Pkt}, StateName, StateData);
 handle_info(kick, StateName, StateData) ->
     Lang = StateData#state.lang,
-    Xmlelement = ?SERRT_POLICY_VIOLATION(Lang, <<"has been kicked">>),
-    handle_info({kick, kicked_by_admin, Xmlelement}, StateName, StateData);
-handle_info({kick, Reason, Xmlelement}, _StateName, StateData) ->
-    send_element(StateData, Xmlelement),
+    Pkt = xmpp:serr_policy_violation(<<"has been kicked">>, Lang),
+    handle_info({kick, kicked_by_admin, Pkt}, StateName, StateData);
+handle_info({kick, Reason, Pkt}, _StateName, StateData) ->
+    send_element(StateData, Pkt),
     {stop, normal,
      StateData#state{authenticated = Reason}};
 handle_info({route, _From, _To, {broadcast, Data}},
@@ -1354,7 +1193,7 @@ handle_info({route, _From, _To, {broadcast, Data}},
                            roster_change(IJID, ISubscription, StateData));
         {exit, Reason} ->
             Lang = StateData#state.lang,
-            send_element(StateData, ?SERRT_CONFLICT(Lang, Reason)),
+            send_element(StateData, xmpp:serr_conflict(Reason, Lang)),
             {stop, normal, StateData};
         {privacy_list, PrivList, PrivListName} ->
             case ejabberd_hooks:run_fold(privacy_updated_list,
@@ -1365,24 +1204,15 @@ handle_info({route, _From, _To, {broadcast, Data}},
                 false ->
                     fsm_next_state(StateName, StateData);
                 NewPL ->
-                    PrivPushIQ = #iq{type = set,
-                                     id = <<"push",
-                                            (randoms:get_string())/binary>>,
-                                     sub_el =
-                                         [#xmlel{name = <<"query">>,
-                                                 attrs = [{<<"xmlns">>,
-                                                           ?NS_PRIVACY}],
-                                                 children =
-                                                     [#xmlel{name = <<"list">>,
-                                                             attrs = [{<<"name">>,
-                                                                       PrivListName}],
-                                                             children = []}]}]},
-                    PrivPushEl = jlib:replace_from_to(
-                                   jid:remove_resource(StateData#state.jid),
-                                   StateData#state.jid,
-                                   jlib:iq_to_xml(PrivPushIQ)),
-                    NewState = send_stanza(
-                                 StateData, PrivPushEl),
+                   PrivPushIQ =
+                       #iq{type = set,
+                           from = jid:remove_resource(StateData#state.jid),
+                           to = StateData#state.jid,
+                           id = <<"push", (randoms:get_string())/binary>>,
+                           sub_els = [#privacy_query{
+                                         lists = [#privacy_list{
+                                                     name = PrivListName}]}]},
+                    NewState = send_stanza(StateData, PrivPushIQ),
                     fsm_next_state(StateName,
                                    NewState#state{privacy_list = NewPL})
             end;
@@ -1393,265 +1223,147 @@ handle_info({route, _From, _To, {broadcast, Data}},
             fsm_next_state(StateName, StateData)
     end;
 %% Process Packets that are to be send to the user
-handle_info({route, From, To,
-             #xmlel{name = Name, attrs = Attrs, children = Els} = Packet},
-            StateName, StateData) ->
-    {Pass, NewAttrs, NewState} = case Name of
-                                  <<"presence">> ->
-                                      State =
-                                          ejabberd_hooks:run_fold(c2s_presence_in,
-                                                                  StateData#state.server,
-                                                                  StateData,
-                                                                  [{From, To,
-                                                                    Packet}]),
-                                      case fxml:get_attr_s(<<"type">>, Attrs) of
-                                        <<"probe">> ->
-                                            LFrom = jid:tolower(From),
-                                            LBFrom =
-                                                jid:remove_resource(LFrom),
-                                            NewStateData = case
-                                                             (?SETS):is_element(LFrom,
-                                                                                State#state.pres_a)
-                                                               orelse
-                                                               (?SETS):is_element(LBFrom,
-                                                                                  State#state.pres_a)
-                                                               of
-                                                             true -> State;
-                                                             false ->
-                                                                 case
-                                                                   (?SETS):is_element(LFrom,
-                                                                                      State#state.pres_f)
-                                                                     of
-                                                                   true ->
-                                                                       A =
-                                                                           (?SETS):add_element(LFrom,
-                                                                                               State#state.pres_a),
-                                                                       State#state{pres_a
-                                                                                       =
-                                                                                       A};
-                                                                   false ->
-                                                                       case
-                                                                         (?SETS):is_element(LBFrom,
-                                                                                            State#state.pres_f)
-                                                                           of
-                                                                         true ->
-                                                                             A =
-                                                                                 (?SETS):add_element(LBFrom,
-                                                                                                     State#state.pres_a),
-                                                                             State#state{pres_a
-                                                                                             =
-                                                                                             A};
-                                                                         false ->
-                                                                             State
-                                                                       end
-                                                                 end
-                                                           end,
-                                            process_presence_probe(From, To,
-                                                                   NewStateData),
-                                            {false, Attrs, NewStateData};
-                                        <<"error">> ->
-                                            NewA =
-                                                remove_element(jid:tolower(From),
-                                                               State#state.pres_a),
-                                            {true, Attrs,
-                                             State#state{pres_a = NewA}};
-                                        <<"subscribe">> ->
-                                            SRes = is_privacy_allow(State,
-                                                                    From, To,
-                                                                    Packet,
-                                                                    in),
-                                            {SRes, Attrs, State};
-                                        <<"subscribed">> ->
-                                            SRes = is_privacy_allow(State,
-                                                                    From, To,
-                                                                    Packet,
-                                                                    in),
-                                            {SRes, Attrs, State};
-                                        <<"unsubscribe">> ->
-                                            SRes = is_privacy_allow(State,
-                                                                    From, To,
-                                                                    Packet,
-                                                                    in),
-                                            {SRes, Attrs, State};
-                                        <<"unsubscribed">> ->
-                                            SRes = is_privacy_allow(State,
-                                                                    From, To,
-                                                                    Packet,
-                                                                    in),
-                                            {SRes, Attrs, State};
-                                        _ ->
-                                            case privacy_check_packet(State,
-                                                                      From, To,
-                                                                      Packet,
-                                                                      in)
-                                                of
-                                              allow ->
-                                                  LFrom =
-                                                      jid:tolower(From),
-                                                  LBFrom =
-                                                      jid:remove_resource(LFrom),
-                                                  case
-                                                    (?SETS):is_element(LFrom,
-                                                                       State#state.pres_a)
-                                                      orelse
-                                                      (?SETS):is_element(LBFrom,
-                                                                         State#state.pres_a)
-                                                      of
-                                                    true ->
-                                                        {true, Attrs, State};
-                                                    false ->
-                                                        case
-                                                          (?SETS):is_element(LFrom,
-                                                                             State#state.pres_f)
-                                                            of
-                                                          true ->
-                                                              A =
-                                                                  (?SETS):add_element(LFrom,
-                                                                                      State#state.pres_a),
-                                                              {true, Attrs,
-                                                               State#state{pres_a
-                                                                               =
-                                                                               A}};
-                                                          false ->
-                                                              case
-                                                                (?SETS):is_element(LBFrom,
-                                                                                   State#state.pres_f)
-                                                                  of
-                                                                true ->
-                                                                    A =
-                                                                        (?SETS):add_element(LBFrom,
-                                                                                            State#state.pres_a),
-                                                                    {true,
-                                                                     Attrs,
-                                                                     State#state{pres_a
-                                                                                     =
-                                                                                     A}};
-                                                                false ->
-                                                                    {true,
-                                                                     Attrs,
-                                                                     State}
-                                                              end
-                                                        end
-                                                  end;
-                                              deny -> {false, Attrs, State}
-                                            end
-                                      end;
-                                  <<"iq">> ->
-                                      IQ = jlib:iq_query_info(Packet),
-                                      case IQ of
-                                        #iq{xmlns = ?NS_LAST} ->
-                                            LFrom = jid:tolower(From),
-                                            LBFrom =
-                                                jid:remove_resource(LFrom),
-                                            HasFromSub =
-                                                ((?SETS):is_element(LFrom,
-                                                                    StateData#state.pres_f)
-                                                   orelse
-                                                   (?SETS):is_element(LBFrom,
-                                                                      StateData#state.pres_f))
-                                                  andalso
-                                                  is_privacy_allow(StateData,
-                                                                   To, From,
-                                                                   #xmlel{name
-                                                                              =
-                                                                              <<"presence">>,
-                                                                          attrs
-                                                                              =
-                                                                              [],
-                                                                          children
-                                                                              =
-                                                                              []},
-                                                                   out),
-                                            case HasFromSub of
-                                              true ->
-                                                  case
-                                                    privacy_check_packet(StateData,
-                                                                         From,
-                                                                         To,
-                                                                         Packet,
-                                                                         in)
-                                                      of
-                                                    allow ->
-                                                        {true, Attrs,
-                                                         StateData};
-                                                    deny ->
-                                                        Err =
-                                                            jlib:make_error_reply(Packet,
-                                                                                  ?ERR_SERVICE_UNAVAILABLE),
-                                                        ejabberd_router:route(To,
-                                                                              From,
-                                                                              Err),
-                                                        {false, Attrs,
-                                                         StateData}
-                                                  end;
-                                              _ ->
-                                                  Err =
-                                                      jlib:make_error_reply(Packet,
-                                                                            ?ERR_FORBIDDEN),
-                                                  ejabberd_router:route(To,
-                                                                        From,
-                                                                        Err),
-                                                  {false, Attrs, StateData}
-                                            end;
-                                        IQ
-                                            when is_record(IQ, iq) or
-                                                   (IQ == reply) ->
-                                            case
-                                              privacy_check_packet(StateData,
-                                                                   From, To,
-                                                                   Packet, in)
-                                                of
-                                              allow ->
-                                                  {true, Attrs, StateData};
-                                              deny when is_record(IQ, iq) ->
-                                                  Err =
-                                                      jlib:make_error_reply(Packet,
-                                                                            ?ERR_SERVICE_UNAVAILABLE),
-                                                  ejabberd_router:route(To,
-                                                                        From,
-                                                                        Err),
-                                                  {false, Attrs, StateData};
-                                              deny when IQ == reply ->
-                                                  {false, Attrs, StateData}
-                                            end;
-                                        IQ
-                                            when (IQ == invalid) or
-                                                   (IQ == not_iq) ->
-                                            {false, Attrs, StateData}
-                                      end;
-                                  <<"message">> ->
-                                      case privacy_check_packet(StateData,
-                                                                From, To,
-                                                                Packet, in)
-                                          of
-                                        allow ->
-                                            {true, Attrs, StateData};
-                                        deny ->
-                                               case fxml:get_attr_s(<<"type">>, Attrs) of
-                                                   <<"error">> -> ok;
-                                                   <<"groupchat">> -> ok;
-                                                   <<"headline">> -> ok;
-                                                   _ ->
-                                                       Err =
-                                                           jlib:make_error_reply(Packet,
-                                                                                 ?ERR_SERVICE_UNAVAILABLE),
-                                                       ejabberd_router:route(To, From,
-                                                                             Err)
-                                               end,
-                                               {false, Attrs, StateData}
-                                      end;
-                                  _ -> {true, Attrs, StateData}
-                                end,
+handle_info({route, From, To, Packet}, StateName, StateData) when ?is_stanza(Packet) ->
+    {Pass, NewState} =
+       case Packet of
+           #presence{type = T} ->
+               State = ejabberd_hooks:run_fold(c2s_presence_in,
+                                               StateData#state.server,
+                                               StateData,
+                                               [{From, To, Packet}]),
+               case T of
+                   probe ->
+                       LFrom = jid:tolower(From),
+                       LBFrom = jid:remove_resource(LFrom),
+                       NewStateData =
+                           case (?SETS):is_element(LFrom, State#state.pres_a)
+                               orelse (?SETS):is_element(LBFrom, State#state.pres_a) of
+                               true -> State;
+                               false ->
+                                   case (?SETS):is_element(LFrom, State#state.pres_f) of
+                                       true ->
+                                           A = (?SETS):add_element(LFrom, State#state.pres_a),
+                                           State#state{pres_a = A};
+                                       false ->
+                                           case (?SETS):is_element(LBFrom, State#state.pres_f) of
+                                               true ->
+                                                   A = (?SETS):add_element(LBFrom, State#state.pres_a),
+                                                   State#state{pres_a = A};
+                                               false ->
+                                                   State
+                                           end
+                                   end
+                           end,
+                       process_presence_probe(From, To, NewStateData),
+                       {false, NewStateData};
+                   error ->
+                       NewA = remove_element(jid:tolower(From), State#state.pres_a),
+                       {true, State#state{pres_a = NewA}};
+                   subscribe ->
+                       SRes = is_privacy_allow(State, From, To, Packet, in),
+                       {SRes, State};
+                   subscribed ->
+                       SRes = is_privacy_allow(State, From, To, Packet, in),
+                       {SRes, State};
+                   unsubscribe ->
+                       SRes = is_privacy_allow(State, From, To, Packet, in),
+                       {SRes, State};
+                   unsubscribed ->
+                       SRes = is_privacy_allow(State, From, To, Packet, in),
+                       {SRes, State};
+                   _ ->
+                       case privacy_check_packet(State, From, To, Packet, in) of
+                           allow ->
+                               LFrom = jid:tolower(From),
+                               LBFrom = jid:remove_resource(LFrom),
+                               case (?SETS):is_element(LFrom, State#state.pres_a)
+                                   orelse (?SETS):is_element(LBFrom, State#state.pres_a) of
+                                   true ->
+                                       {true, State};
+                                   false ->
+                                       case (?SETS):is_element(LFrom, State#state.pres_f) of
+                                           true ->
+                                               A = (?SETS):add_element(LFrom, State#state.pres_a),
+                                               {true, State#state{pres_a = A}};
+                                           false ->
+                                               case (?SETS):is_element(LBFrom,
+                                                                       State#state.pres_f) of
+                                                   true ->
+                                                       A = (?SETS):add_element(
+                                                             LBFrom,
+                                                             State#state.pres_a),
+                                                       {true, State#state{pres_a = A}};
+                                                   false ->
+                                                       {true, State}
+                                               end
+                                       end
+                               end;
+                           deny -> {false, State}
+                       end
+               end;
+           #iq{type = T} ->
+               case xmpp:has_subtag(Packet, #last{}) of
+                   true when T == get; T == set ->
+                       LFrom = jid:tolower(From),
+                       LBFrom = jid:remove_resource(LFrom),
+                       HasFromSub = ((?SETS):is_element(LFrom, StateData#state.pres_f)
+                                     orelse (?SETS):is_element(LBFrom, StateData#state.pres_f))
+                           andalso is_privacy_allow(StateData, To, From, #presence{}, out),
+                       case HasFromSub of
+                           true ->
+                               case privacy_check_packet(
+                                      StateData, From, To, Packet, in) of
+                                   allow ->
+                                       {true, StateData};
+                                   deny ->
+                                       Err = xmpp:make_error(
+                                               Packet,
+                                               xmpp:err_service_unavailable()),
+                                       ejabberd_router:route(To, From, Err),
+                                       {false, StateData}
+                               end;
+                           _ ->
+                               Err = xmpp:make_error(Packet, xmpp:err_forbidden()),
+                               ejabberd_router:route(To, From, Err),
+                               {false, StateData}
+                       end;
+                   _ ->
+                       case privacy_check_packet(StateData, From, To, Packet, in) of
+                           allow ->
+                               {true, StateData};
+                           deny when T == get; T == set ->
+                               Err = xmpp:make_error(
+                                       Packet, xmpp:err_service_unavailable()),
+                               ejabberd_router:route(To, From, Err),
+                               {false, StateData};
+                           deny ->
+                               {false, StateData}
+                       end
+               end;
+           #message{type = T} ->
+               case privacy_check_packet(StateData, From, To, Packet, in) of
+                   allow ->
+                       {true, StateData};
+                   deny ->
+                       case T of
+                           error -> ok;
+                           groupchat -> ok;
+                           headline -> ok;
+                           _ ->
+                               Err = xmpp:make_error(
+                                       Packet, xmpp:err_service_unavailable()),
+                               ejabberd_router:route(To, From, Err)
+                       end,
+                       {false, StateData}
+               end
+       end,
     if Pass ->
-           Attrs2 =
-               jlib:replace_from_to_attrs(jid:to_string(From),
-                   jid:to_string(To), NewAttrs),
-           FixedPacket0 = #xmlel{name = Name, attrs = Attrs2, children = Els},
+           FixedPacket0 = xmpp:set_from_to(Packet, From, To),
            FixedPacket = ejabberd_hooks:run_fold(
-                   user_receive_packet,
-                   NewState#state.server,
-                   FixedPacket0,
-                   [NewState, NewState#state.jid, From, To]),
+                           user_receive_packet,
+                           NewState#state.server,
+                           FixedPacket0,
+                           [NewState, NewState#state.jid, From, To]),
            SentStateData = send_packet(NewState, FixedPacket),
            ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]),
            fsm_next_state(StateName, SentStateData);
@@ -1672,10 +1384,10 @@ handle_info(system_shutdown, StateName, StateData) ->
     case StateName of
       wait_for_stream ->
          send_header(StateData, ?MYNAME, <<"1.0">>, <<"en">>),
-         send_element(StateData, ?SERR_SYSTEM_SHUTDOWN),
+         send_element(StateData, xmpp:serr_system_shutdown()),
          ok;
       _ ->
-         send_element(StateData, ?SERR_SYSTEM_SHUTDOWN),
+         send_element(StateData, xmpp:serr_system_shutdown()),
          ok
     end,
     {stop, normal, StateData};
@@ -1686,17 +1398,17 @@ handle_info({route_xmlstreamelement, El}, _StateName, StateData) ->
 handle_info({force_update_presence, LUser, LServer}, StateName,
            #state{jid = #jid{luser = LUser, lserver = LServer}} = StateData) ->
     NewStateData = case StateData#state.pres_last of
-                    #xmlel{name = <<"presence">>} ->
-                        PresenceEl =
-                            ejabberd_hooks:run_fold(c2s_update_presence,
-                                                    LServer,
-                                                    StateData#state.pres_last,
-                                                    [LUser, LServer]),
-                        StateData2 = StateData#state{pres_last = PresenceEl},
-                        presence_update(StateData2#state.jid, PresenceEl,
-                                        StateData2),
-                        StateData2;
-                    _ -> StateData
+                      #presence{} ->
+                          Presence =
+                              ejabberd_hooks:run_fold(c2s_update_presence,
+                                                      LServer,
+                                                      StateData#state.pres_last,
+                                                      [LUser, LServer]),
+                          StateData2 = StateData#state{pres_last = Presence},
+                          presence_update(StateData2#state.jid, Presence,
+                                          StateData2),
+                          StateData2;
+                      undefined -> StateData
                   end,
     fsm_next_state(StateName, NewStateData);
 handle_info({send_filtered, Feature, From, To, Packet}, StateName, StateData) ->
@@ -1709,7 +1421,7 @@ handle_info({send_filtered, Feature, From, To, Packet}, StateName, StateData) ->
                                  jid:to_string(To)]),
                          StateData;
                      true ->
-                         FinalPacket = jlib:replace_from_to(From, To, Packet),
+                         FinalPacket = xmpp:set_from_to(Packet, From, To),
                          case StateData#state.jid of
                            To ->
                                case privacy_check_packet(StateData, From, To,
@@ -1742,6 +1454,7 @@ handle_info(Info, StateName, StateData) ->
     ?ERROR_MSG("Unexpected info: ~p", [Info]),
     fsm_next_state(StateName, StateData).
 
+-spec print_state(state()) -> state().
 print_state(State = #state{pres_t = T, pres_f = F, pres_a = A}) ->
     State#state{pres_t = {pres_t, (?SETS):size(T)},
                pres_f = {pres_f, (?SETS):size(F)},
@@ -1761,18 +1474,16 @@ terminate(_Reason, StateName, StateData) ->
                                 [StateData#state.socket,
                                  jid:to_string(StateData#state.jid)]),
                       From = StateData#state.jid,
-                      Packet = #xmlel{name = <<"presence">>,
-                                      attrs = [{<<"type">>, <<"unavailable">>}],
-                                      children =
-                                          [#xmlel{name = <<"status">>, attrs = [],
-                                                  children =
-                                                      [{xmlcdata,
-                                                        <<"Replaced by new connection">>}]}]},
+                      Lang = StateData#state.lang,
+                      Status = <<"Replaced by new connection">>,
+                      Packet = #presence{
+                                  type = unavailable,
+                                  status = xmpp:mk_text(Status, Lang)},
                       ejabberd_sm:close_session_unset_presence(StateData#state.sid,
                                                                StateData#state.user,
                                                                StateData#state.server,
                                                                StateData#state.resource,
-                                                               <<"Replaced by new connection">>),
+                                                               Status),
                       presence_broadcast(StateData, From,
                                          StateData#state.pres_a, Packet);
                   _ ->
@@ -1788,9 +1499,7 @@ terminate(_Reason, StateName, StateData) ->
                                                       StateData#state.resource);
                         _ ->
                             From = StateData#state.jid,
-                            Packet = #xmlel{name = <<"presence">>,
-                                            attrs = [{<<"type">>, <<"unavailable">>}],
-                                            children = []},
+                            Packet = #presence{type = unavailable},
                             ejabberd_sm:close_session_unset_presence(StateData#state.sid,
                                                                      StateData#state.user,
                                                                      StateData#state.server,
@@ -1825,7 +1534,7 @@ terminate(_Reason, StateName, StateData) ->
 %%%----------------------------------------------------------------------
 %%% Internal functions
 %%%----------------------------------------------------------------------
-
+-spec change_shaper(state(), jid()) -> ok.
 change_shaper(StateData, JID) ->
     Shaper = acl:access_matches(StateData#state.shaper,
                                #{usr => jid:split(JID), ip => StateData#state.ip},
@@ -1833,6 +1542,7 @@ change_shaper(StateData, JID) ->
     (StateData#state.sockmod):change_shaper(StateData#state.socket,
                                            Shaper).
 
+-spec send_text(state(), iodata()) -> ok | {error, any()}.
 send_text(StateData, Text) when StateData#state.mgmt_state == pending ->
     ?DEBUG("Cannot send text while waiting for resumption: ~p", [Text]);
 send_text(StateData, Text) when StateData#state.xml_socket ->
@@ -1852,14 +1562,18 @@ send_text(StateData, Text) ->
     ?DEBUG("Send XML on stream = ~p", [Text]),
     (StateData#state.sockmod):send(StateData#state.socket, Text).
 
+-spec send_element(state(), xmlel() | xmpp_element()) -> ok | {error, any()}.
 send_element(StateData, El) when StateData#state.mgmt_state == pending ->
     ?DEBUG("Cannot send element while waiting for resumption: ~p", [El]);
-send_element(StateData, El) when StateData#state.xml_socket ->
+send_element(StateData, #xmlel{} = El) when StateData#state.xml_socket ->
     (StateData#state.sockmod):send_xml(StateData#state.socket,
                                       {xmlstreamelement, El});
-send_element(StateData, El) ->
-    send_text(StateData, fxml:element_to_binary(El)).
+send_element(StateData, #xmlel{} = El) ->
+    send_text(StateData, fxml:element_to_binary(El));
+send_element(StateData, Pkt) ->
+    send_element(StateData, xmpp:encode(Pkt)).
 
+-spec send_stanza(state(), xmpp_element()) -> state().
 send_stanza(StateData, Stanza) when StateData#state.csi_state == inactive ->
     csi_filter_stanza(StateData, Stanza);
 send_stanza(StateData, Stanza) when StateData#state.mgmt_state == pending ->
@@ -1871,8 +1585,9 @@ send_stanza(StateData, Stanza) ->
     send_element(StateData, Stanza),
     StateData.
 
+-spec send_packet(state(), xmpp_element()) -> state().
 send_packet(StateData, Packet) ->
-    case is_stanza(Packet) of
+    case xmpp:is_stanza(Packet) of
       true ->
          send_stanza(StateData, Packet);
       false ->
@@ -1880,6 +1595,7 @@ send_packet(StateData, Packet) ->
          StateData
     end.
 
+-spec send_header(state(), binary(), binary(), binary()) -> ok | {error, any()}.
 send_header(StateData, Server, Version, Lang)
     when StateData#state.xml_socket ->
     VersionAttr = case Version of
@@ -1914,6 +1630,7 @@ send_header(StateData, Server, Version, Lang) ->
                            LangStr]),
     send_text(StateData, iolist_to_binary(Header)).
 
+-spec send_trailer(state()) -> ok | {error, any()}.
 send_trailer(StateData)
     when StateData#state.mgmt_state == pending ->
     ?DEBUG("Cannot send stream trailer while waiting for resumption", []);
@@ -1924,64 +1641,24 @@ send_trailer(StateData)
 send_trailer(StateData) ->
     send_text(StateData, ?STREAM_TRAILER).
 
+-spec new_id() -> binary().
 new_id() -> randoms:get_string().
 
+-spec new_uniq_id() -> binary().
 new_uniq_id() ->
     iolist_to_binary([randoms:get_string(),
                      jlib:integer_to_binary(p1_time_compat:unique_integer([positive]))]).
 
-is_auth_packet(El) ->
-    case jlib:iq_query_info(El) of
-       #iq{id = ID, type = Type, xmlns = ?NS_AUTH, sub_el = SubEl} ->
-           #xmlel{children = Els} = SubEl,
-           {auth, ID, Type,
-               get_auth_tags(Els, <<"">>, <<"">>, <<"">>, <<"">>)};
-       _ -> false
-    end.
-
-is_stanza(#xmlel{name = Name, attrs = Attrs}) when Name == <<"message">>;
-                                                  Name == <<"presence">>;
-                                                  Name == <<"iq">> ->
-    case fxml:get_attr(<<"xmlns">>, Attrs) of
-      {value, NS} when NS /= <<"jabber:client">>,
-                      NS /= <<"jabber:server">> ->
-         false;
-      _ ->
-         true
-    end;
-is_stanza(_El) ->
-    false.
-
-get_auth_tags([#xmlel{name = Name, children = Els} | L],
-             U, P, D, R) ->
-    CData = fxml:get_cdata(Els),
-    case Name of
-      <<"username">> -> get_auth_tags(L, CData, P, D, R);
-      <<"password">> -> get_auth_tags(L, U, CData, D, R);
-      <<"digest">> -> get_auth_tags(L, U, P, CData, R);
-      <<"resource">> -> get_auth_tags(L, U, P, D, CData);
-      _ -> get_auth_tags(L, U, P, D, R)
-    end;
-get_auth_tags([_ | L], U, P, D, R) ->
-    get_auth_tags(L, U, P, D, R);
-get_auth_tags([], U, P, D, R) ->
-    {U, P, D, R}.
-
-%% Copied from ejabberd_socket.erl
--record(socket_state, {sockmod, socket, receiver}).
-
+-spec get_conn_type(state()) -> c2s | c2s_tls | c2s_compressed | websocket |
+                               c2s_compressed_tls | http_bind.
 get_conn_type(StateData) ->
-    case (StateData#state.sockmod):get_sockmod(StateData#state.socket) of
-    gen_tcp -> c2s;
-    fast_tls -> c2s_tls;
-    ezlib ->
-       case ezlib:get_sockmod((StateData#state.socket)#socket_state.socket) of
-           gen_tcp -> c2s_compressed;
-           fast_tls -> c2s_compressed_tls
-       end;
-    ejabberd_http_bind -> http_bind;
-    ejabberd_http_ws -> websocket;
-    _ -> unknown
+    case (StateData#state.sockmod):get_transport(StateData#state.socket) of
+       tcp -> c2s;
+       tls -> c2s_tls;
+       tcp_zlib -> c2s_compressed;
+       tls_zlib -> c2s_compressed_tls;
+       http_bind -> http_bind;
+       websocket -> websocket
     end.
 
 process_presence_probe(From, To, StateData) ->
@@ -1997,8 +1674,9 @@ process_presence_probe(From, To, StateData) ->
                     (?SETS):is_element(LBFrom, StateData#state.pres_f))),
            if Cond ->
                    %% To is the one sending the presence (the probe target)
-                   Packet = jlib:add_delay_info(StateData#state.pres_last, To,
-                                                StateData#state.pres_timestamp),
+                   Packet = xmpp_util:add_delay_info(
+                              StateData#state.pres_last, To,
+                              StateData#state.pres_timestamp),
                    case privacy_check_packet(StateData, To, From, Packet, out) of
                        deny ->
                            ok;
@@ -2020,13 +1698,10 @@ process_presence_probe(From, To, StateData) ->
 
 %% User updates his presence (non-directed presence packet)
 presence_update(From, Packet, StateData) ->
-    #xmlel{attrs = Attrs} = Packet,
-    case fxml:get_attr_s(<<"type">>, Attrs) of
-      <<"unavailable">> ->
-         Status = case fxml:get_subtag(Packet, <<"status">>) of
-                    false -> <<"">>;
-                    StatusTag -> fxml:get_tag_cdata(StatusTag)
-                  end,
+    #presence{type = Type} = Packet,
+    case Type of
+      unavailable ->
+         Status = xmpp:get_text(Packet#presence.status),
          Info = [{ip, StateData#state.ip},
                  {conn, StateData#state.conn},
                  {auth_module, StateData#state.auth_module}],
@@ -2038,12 +1713,12 @@ presence_update(From, Packet, StateData) ->
                             StateData#state.pres_a, Packet),
          StateData#state{pres_last = undefined,
                          pres_timestamp = undefined, pres_a = (?SETS):new()};
-      <<"error">> -> StateData;
-      <<"probe">> -> StateData;
-      <<"subscribe">> -> StateData;
-      <<"subscribed">> -> StateData;
-      <<"unsubscribe">> -> StateData;
-      <<"unsubscribed">> -> StateData;
+      error -> StateData;
+      probe -> StateData;
+      subscribe -> StateData;
+      subscribed -> StateData;
+      unsubscribe -> StateData;
+      unsubscribed -> StateData;
       _ ->
          OldPriority = case StateData#state.pres_last of
                          undefined -> 0;
@@ -2082,31 +1757,31 @@ presence_update(From, Packet, StateData) ->
 
 %% User sends a directed presence packet
 presence_track(From, To, Packet, StateData) ->
-    #xmlel{attrs = Attrs} = Packet,
+    #presence{type = Type} = Packet,
     LTo = jid:tolower(To),
     User = StateData#state.user,
     Server = StateData#state.server,
-    case fxml:get_attr_s(<<"type">>, Attrs) of
-      <<"unavailable">> ->
+    case Type of
+      unavailable ->
          A = remove_element(LTo, StateData#state.pres_a),
          check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet);
-      <<"subscribe">> ->
+      subscribe ->
          try_roster_subscribe(subscribe, User, Server, From, To, Packet, StateData);
-      <<"subscribed">> ->
+      subscribed ->
          ejabberd_hooks:run(roster_out_subscription, Server,
                             [User, Server, To, subscribed]),
          check_privacy_route(From, StateData,
                              jid:remove_resource(From), To, Packet);
-      <<"unsubscribe">> ->
+      unsubscribe ->
          try_roster_subscribe(unsubscribe, User, Server, From, To, Packet, StateData);
-      <<"unsubscribed">> ->
+      unsubscribed ->
          ejabberd_hooks:run(roster_out_subscription, Server,
                             [User, Server, To, unsubscribed]),
          check_privacy_route(From, StateData,
                              jid:remove_resource(From), To, Packet);
-      <<"error">> ->
+      error ->
          check_privacy_route(From, StateData, From, To, Packet);
-      <<"probe">> ->
+      probe ->
          check_privacy_route(From, StateData, From, To, Packet);
       _ ->
          A = (?SETS):add_element(LTo, StateData#state.pres_a),
@@ -2122,12 +1797,12 @@ check_privacy_route(From, StateData, FromRoute, To,
             Lang = StateData#state.lang,
             ErrText = <<"Your active privacy list has denied "
                        "the routing of this stanza.">>,
-            Err = jlib:make_error_reply(Packet,
-                                        ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
-            Err2 = jlib:replace_from_to(To, From, Err),
-            send_stanza(StateData, Err2);
+           Err = xmpp:make_error(
+                   xmpp:set_from_to(Packet, From, To),
+                   xmpp:err_not_acceptable(ErrText, Lang)),
+            send_stanza(StateData, Err);
         allow ->
-            ejabberd_router:route(FromRoute, To, Packet),
+           ejabberd_router:route(FromRoute, To, Packet),
             StateData
     end.
 
@@ -2182,7 +1857,7 @@ presence_broadcast_first(From, StateData, Packet) ->
           fun(JID, L) -> [JID | L] end,
           [],
           StateData#state.pres_t),
-    PacketProbe = #xmlel{name = <<"presence">>, attrs = [{<<"type">>,<<"probe">>}], children = []},
+    PacketProbe = #presence{type = probe},
     JIDs2Probe = format_and_check_privacy(From, StateData, PacketProbe, JIDsProbe, out),
     Server = StateData#state.server,
     send_multiple(From, Server, JIDs2Probe, PacketProbe),
@@ -2260,9 +1935,7 @@ roster_change(IJID, ISubscription, StateData) ->
                                 pres_t = TSet};
             Cond2 ->
                 ?DEBUG("C2: ~p~n", [LIJID]),
-                PU = #xmlel{name = <<"presence">>,
-                            attrs = [{<<"type">>, <<"unavailable">>}],
-                            children = []},
+                PU = #presence{type = unavailable},
                 case privacy_check_packet(StateData, From, To, PU, out)
                     of
                   deny -> ok;
@@ -2282,20 +1955,14 @@ update_priority(Priority, Packet, StateData) ->
                             StateData#state.user, StateData#state.server,
                             StateData#state.resource, Priority, Packet, Info).
 
-get_priority_from_presence(PresencePacket) ->
-    case fxml:get_subtag(PresencePacket, <<"priority">>) of
-      false -> 0;
-      SubEl ->
-         case catch
-                jlib:binary_to_integer(fxml:get_tag_cdata(SubEl))
-             of
-           P when is_integer(P) -> P;
-           _ -> 0
-         end
+get_priority_from_presence(#presence{priority = Prio}) ->
+    case Prio of
+       undefined -> 0;
+       _ -> Prio
     end.
 
-process_privacy_iq(From, To,
-                  #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ, StateData) ->
+process_privacy_iq(#iq{from = From, to = To,
+                      type = Type, lang = Lang} = IQ, StateData) ->
     Txt = <<"No module is handling this query">>,
     {Res, NewStateData} =
        case Type of
@@ -2303,16 +1970,15 @@ process_privacy_iq(From, To,
                R = ejabberd_hooks:run_fold(
                      privacy_iq_get,
                      StateData#state.server,
-                     {error, ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)},
-                     [From, To, IQ,
-                      StateData#state.privacy_list]),
+                     {error, xmpp:err_feature_not_implemented(Txt, Lang)},
+                     [IQ, StateData#state.privacy_list]),
                {R, StateData};
            set ->
                case ejabberd_hooks:run_fold(
                       privacy_iq_set,
                       StateData#state.server,
-                      {error, ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)},
-                      [From, To, IQ])
+                      {error, xmpp:err_feature_not_implemented(Txt, Lang)},
+                      [IQ])
                of
                    {result, R, NewPrivList} ->
                        {{result, R},
@@ -2323,11 +1989,11 @@ process_privacy_iq(From, To,
        end,
     IQRes = case Res of
              {result, Result} ->
-                 IQ#iq{type = result, sub_el = Result};
+                 xmpp:make_iq_result(IQ, Result);
              {error, Error} ->
-                 IQ#iq{type = error, sub_el = [SubEl, Error]}
+                 xmpp:make_error(IQ, Error)
            end,
-    ejabberd_router:route(To, From, jlib:iq_to_xml(IQRes)),
+    ejabberd_router:route(To, From, IQRes),
     NewStateData.
 
 resend_offline_messages(#state{ask_offline = true} = StateData) ->
@@ -2336,8 +2002,7 @@ resend_offline_messages(#state{ask_offline = true} = StateData) ->
                                 [StateData#state.user, StateData#state.server])
     of
       Rs -> %%when is_list(Rs) ->
-         lists:foreach(fun ({route, From, To,
-                             #xmlel{} = Packet}) ->
+         lists:foreach(fun ({route, From, To, Packet}) ->
                                Pass = case privacy_check_packet(StateData,
                                                                 From, To,
                                                                 Packet, in)
@@ -2367,50 +2032,35 @@ resend_subscription_requests(#state{user = User,
                PendingSubscriptions).
 
 get_showtag(undefined) -> <<"unavailable">>;
-get_showtag(Presence) ->
-    case fxml:get_path_s(Presence, [{elem, <<"show">>}, cdata]) of
-       <<"">> -> <<"available">>;
-       ShowTag -> ShowTag
-    end.
+get_showtag(#presence{show = undefined}) -> <<"available">>;
+get_showtag(#presence{show = Show}) -> atom_to_binary(Show, utf8).
 
-get_statustag(undefined) -> <<"">>;
-get_statustag(Presence) ->
-    fxml:get_path_s(Presence, [{elem, <<"status">>}, cdata]).
-
-process_unauthenticated_stanza(StateData, El) ->
-    NewEl = case fxml:get_tag_attr_s(<<"xml:lang">>, El) of
-             <<"">> ->
-                 case StateData#state.lang of
-                   <<"">> -> El;
-                   Lang -> fxml:replace_tag_attr(<<"xml:lang">>, Lang, El)
-                 end;
-             _ -> El
-           end,
-    case jlib:iq_query_info(NewEl) of
-      #iq{lang = L} = IQ ->
-         Res = ejabberd_hooks:run_fold(c2s_unauthenticated_iq,
-                                       StateData#state.server, empty,
-                                       [StateData#state.server, IQ,
-                                        StateData#state.ip]),
-         case Res of
-           empty ->
-               Txt = <<"Authentication required">>,
-               ResIQ = IQ#iq{type = error,
-                             sub_el = [?ERRT_SERVICE_UNAVAILABLE(L, Txt)]},
-               Res1 = jlib:replace_from_to(jid:make(<<"">>,
-                                                         StateData#state.server,
-                                                         <<"">>),
-                                           jid:make(<<"">>, <<"">>,
-                                                         <<"">>),
-                                           jlib:iq_to_xml(ResIQ)),
-               send_element(StateData,
-                            jlib:remove_attr(<<"to">>, Res1));
-           _ -> send_element(StateData, Res)
-         end;
-      _ ->
-         % Drop any stanza, which isn't IQ stanza
-         ok
-    end.
+get_statustag(#presence{status = [#text{data = Status}|_]}) -> Status;
+get_statustag(_) -> <<"">>.
+
+process_unauthenticated_stanza(StateData, #iq{type = T, lang = L} = IQ)
+  when T == set; T == get ->
+    Lang = if L == undefined; L == <<"">> -> StateData#state.lang;
+             true -> L
+          end,
+    NewIQ = IQ#iq{lang = Lang},
+    Res = ejabberd_hooks:run_fold(c2s_unauthenticated_iq,
+                                 StateData#state.server, empty,
+                                 [StateData#state.server, NewIQ,
+                                  StateData#state.ip]),
+    case Res of
+       empty ->
+           Txt = <<"Authentication required">>,
+           Err0 = xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang)),
+           Err1 = Err0#iq{from = jid:make(<<>>, StateData#state.server, <<>>),
+                          to = undefined},
+           send_element(StateData, Err1);
+       _ ->
+           send_element(StateData, Res)
+    end;
+process_unauthenticated_stanza(_StateData, _) ->
+    %% Drop any stanza, which isn't IQ stanza
+    ok.
 
 peerip(SockMod, Socket) ->
     IP = case SockMod of
@@ -2424,9 +2074,11 @@ peerip(SockMod, Socket) ->
 
 %% fsm_next_state_pack: Pack the StateData structure to improve
 %% sharing.
+-spec fsm_next_state_pack(state_name(), state()) -> fsm_transition().
 fsm_next_state_pack(StateName, StateData) ->
     fsm_next_state_gc(StateName, pack(StateData)).
 
+-spec fsm_next_state_gc(state_name(), state()) -> fsm_transition().
 %% fsm_next_state_gc: Garbage collect the process heap to make use of
 %% the newly packed StateData structure.
 fsm_next_state_gc(StateName, PackedStateData) ->
@@ -2435,12 +2087,13 @@ fsm_next_state_gc(StateName, PackedStateData) ->
 
 %% fsm_next_state: Generate the next_state FSM tuple with different
 %% timeout, depending on the future state
+-spec fsm_next_state(state_name(), state()) -> fsm_transition().
 fsm_next_state(session_established, #state{mgmt_max_queue = exceeded} =
               StateData) ->
     ?WARNING_MSG("ACK queue too long, terminating session for ~s",
                 [jid:to_string(StateData#state.jid)]),
-    Err = ?SERRT_POLICY_VIOLATION(StateData#state.lang,
-                                 <<"Too many unacked stanzas">>),
+    Err = xmpp:serr_policy_violation(<<"Too many unacked stanzas">>,
+                                    StateData#state.lang),
     send_element(StateData, Err),
     {stop, normal, StateData#state{mgmt_resend = false}};
 fsm_next_state(session_established, #state{mgmt_state = pending} = StateData) ->
@@ -2483,25 +2136,25 @@ is_ip_blacklisted({IP, _Port}, Lang) ->
 
 %% Check from attributes
 %% returns invalid-from|NewElement
-check_from(El, FromJID) ->
-    case fxml:get_tag_attr(<<"from">>, El) of
+check_from(Pkt, FromJID) ->
+    case xmpp:is_stanza(Pkt) of
        false ->
-           El;
-       {value, SJID} ->
-           JID = jid:from_string(SJID),
+           Pkt;
+       true ->
+           JID = xmpp:get_from(Pkt),
            case JID of
-               error ->
-                   'invalid-from';
+               undefined ->
+                   Pkt;
                #jid{} ->
                    if
                        (JID#jid.luser == FromJID#jid.luser) and
-                               (JID#jid.lserver == FromJID#jid.lserver) and
-                               (JID#jid.lresource == FromJID#jid.lresource) ->
-                           El;
+                       (JID#jid.lserver == FromJID#jid.lserver) and
+                       (JID#jid.lresource == FromJID#jid.lresource) ->
+                           Pkt;
                        (JID#jid.luser == FromJID#jid.luser) and
-                               (JID#jid.lserver == FromJID#jid.lserver) and
-                               (JID#jid.lresource == <<"">>) ->
-                           El;
+                       (JID#jid.lserver == FromJID#jid.lserver) and
+                       (JID#jid.lresource == <<"">>) ->
+                           Pkt;
                        true ->
                            'invalid-from'
                    end
@@ -2527,39 +2180,22 @@ bounce_messages() ->
       after 0 -> ok
     end.
 
-process_compression_request(El, StateName, StateData) ->
-    case fxml:get_subtag(El, <<"method">>) of
+process_compression_request(#compress{methods = []}, StateName, StateData) ->
+    send_element(StateData, #compress_failure{reason = 'setup-failed'}),
+    fsm_next_state(StateName, StateData);
+process_compression_request(#compress{methods = Ms}, StateName, StateData) ->
+    case lists:member(<<"zlib">>, Ms) of
+       true ->
+           Socket = StateData#state.socket,
+           BCompressed = fxml:element_to_binary(xmpp:encode(#compressed{})),
+           ZlibSocket = (StateData#state.sockmod):compress(Socket, BCompressed),
+           fsm_next_state(wait_for_stream,
+                          StateData#state{socket = ZlibSocket,
+                                          streamid = new_id()});
        false ->
            send_element(StateData,
-                        #xmlel{name = <<"failure">>,
-                               attrs = [{<<"xmlns">>, ?NS_COMPRESS}],
-                               children =
-                               [#xmlel{name = <<"setup-failed">>,
-                                       attrs = [], children = []}]}),
-           fsm_next_state(StateName, StateData);
-       Method ->
-           case fxml:get_tag_cdata(Method) of
-               <<"zlib">> ->
-                   Socket = StateData#state.socket,
-                   BCompressed = fxml:element_to_binary(
-                                   #xmlel{name = <<"compressed">>,
-                                          attrs = [{<<"xmlns">>,
-                                                    ?NS_COMPRESS}]}),
-                   ZlibSocket = (StateData#state.sockmod):compress(
-                                  Socket, BCompressed),
-                   fsm_next_state(wait_for_stream,
-                                  StateData#state{socket = ZlibSocket,
-                                                  streamid = new_id()});
-               _ ->
-                   send_element(StateData,
-                                #xmlel{name = <<"failure">>,
-                                       attrs = [{<<"xmlns">>, ?NS_COMPRESS}],
-                                       children =
-                                       [#xmlel{name = <<"unsupported-method">>,
-                                               attrs = [],
-                                               children = []}]}),
-                   fsm_next_state(StateName, StateData)
-           end
+                        #compress_failure{reason = 'unsupported-method'}),
+           fsm_next_state(StateName, StateData)
     end.
 
 %%%----------------------------------------------------------------------
@@ -2568,42 +2204,20 @@ process_compression_request(El, StateName, StateData) ->
 
 route_blocking(What, StateData) ->
     SubEl = case What of
-             {block, JIDs} ->
-                 #xmlel{name = <<"block">>,
-                        attrs = [{<<"xmlns">>, ?NS_BLOCKING}],
-                        children =
-                            lists:map(fun (JID) ->
-                                              #xmlel{name = <<"item">>,
-                                                     attrs =
-                                                         [{<<"jid">>,
-                                                           jid:to_string(JID)}],
-                                                     children = []}
-                                      end,
-                                      JIDs)};
-             {unblock, JIDs} ->
-                 #xmlel{name = <<"unblock">>,
-                        attrs = [{<<"xmlns">>, ?NS_BLOCKING}],
-                        children =
-                            lists:map(fun (JID) ->
-                                              #xmlel{name = <<"item">>,
-                                                     attrs =
-                                                         [{<<"jid">>,
-                                                           jid:to_string(JID)}],
-                                                     children = []}
-                                      end,
-                                      JIDs)};
-             unblock_all ->
-                 #xmlel{name = <<"unblock">>,
-                        attrs = [{<<"xmlns">>, ?NS_BLOCKING}], children = []}
+               {block, JIDs} ->
+                   #block{items = JIDs};
+               {unblock, JIDs} ->
+                   #unblock{items = JIDs};
+               unblock_all ->
+                   #unblock{}
            end,
-    PrivPushIQ = #iq{type = set, id = <<"push">>, sub_el = [SubEl]},
-    PrivPushEl =
-       jlib:replace_from_to(jid:remove_resource(StateData#state.jid),
-                            StateData#state.jid, jlib:iq_to_xml(PrivPushIQ)),
+    PrivPushIQ = #iq{type = set, id = <<"push">>, sub_els = [SubEl],
+                    from = jid:remove_resource(StateData#state.jid),
+                    to = StateData#state.jid},
     %% No need to replace active privacy list here,
     %% blocking pushes are always accompanied by
     %% Privacy List pushes
-    send_stanza(StateData, PrivPushEl).
+    send_stanza(StateData, PrivPushIQ).
 
 %%%----------------------------------------------------------------------
 %%% XEP-0198
@@ -2627,164 +2241,131 @@ negotiate_stream_mgmt(_El, #state{resource = <<"">>} = StateData) ->
     %% Binding unless it is resuming a previous session".  However, it also
     %% says: "Stream management errors SHOULD be considered recoverable", so we
     %% won't bail out.
-    send_element(StateData, ?MGMT_UNEXPECTED_REQUEST(?NS_STREAM_MGMT_3)),
+    send_element(StateData, #sm_failed{reason = 'unexpected-request',
+                                      xmlns = ?NS_STREAM_MGMT_3}),
     StateData;
-negotiate_stream_mgmt(#xmlel{name = Name, attrs = Attrs}, StateData) ->
-    case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-      Xmlns when ?IS_SUPPORTED_MGMT_XMLNS(Xmlns) ->
-         case stream_mgmt_enabled(StateData) of
-           true ->
-               case Name of
-                 <<"enable">> ->
-                     handle_enable(StateData#state{mgmt_xmlns = Xmlns}, Attrs);
-                 _ ->
-                     Res = if Name == <<"a">>;
-                              Name == <<"r">>;
-                              Name == <<"resume">> ->
-                                  ?MGMT_UNEXPECTED_REQUEST(Xmlns);
-                              true ->
-                                  ?MGMT_BAD_REQUEST(Xmlns)
-                           end,
-                     send_element(StateData, Res),
-                     StateData
-               end;
-           false ->
-             send_element(StateData, ?MGMT_SERVICE_UNAVAILABLE(Xmlns)),
-             StateData
-         end;
-      _ ->
-         send_element(StateData, ?MGMT_UNSUPPORTED_VERSION(?NS_STREAM_MGMT_3)),
-         StateData
+negotiate_stream_mgmt(Pkt, StateData) ->
+    Xmlns = xmpp:get_ns(Pkt),
+    case stream_mgmt_enabled(StateData) of
+       true ->
+           case Pkt of
+               #sm_enable{} ->
+                   handle_enable(StateData#state{mgmt_xmlns = Xmlns}, Pkt);
+               _ ->
+                   Res = if is_record(Pkt, sm_a);
+                            is_record(Pkt, sm_r);
+                            is_record(Pkt, sm_resume) ->
+                                 #sm_failed{reason = 'unexpected-request',
+                                            xmlns = Xmlns};
+                            true ->
+                                 #sm_failed{reason = 'bad-request',
+                                            xmlns = Xmlns}
+                         end,
+                   send_element(StateData, Res),
+                   StateData
+           end;
+       false ->
+           send_element(StateData,
+                        #sm_failed{reason = 'service-unavailable',
+                                   xmlns = Xmlns}),
+           StateData
     end.
 
-perform_stream_mgmt(#xmlel{name = Name, attrs = Attrs}, StateData) ->
-    case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-      Xmlns when Xmlns == StateData#state.mgmt_xmlns ->
-         case Name of
-           <<"r">> ->
-               handle_r(StateData);
-           <<"a">> ->
-               handle_a(StateData, Attrs);
-           _ ->
-               Res = if Name == <<"enable">>;
-                        Name == <<"resume">> ->
-                            ?MGMT_UNEXPECTED_REQUEST(Xmlns);
-                        true ->
-                            ?MGMT_BAD_REQUEST(Xmlns)
-                     end,
-               send_element(StateData, Res),
-               StateData
-         end;
-      _ ->
-         send_element(StateData,
-                      ?MGMT_UNSUPPORTED_VERSION(StateData#state.mgmt_xmlns)),
-         StateData
+perform_stream_mgmt(Pkt, StateData) ->
+    case xmpp:get_ns(Pkt) of
+       Xmlns when Xmlns == StateData#state.mgmt_xmlns ->
+           case Pkt of
+               #sm_r{} ->
+                   handle_r(StateData);
+               #sm_a{} ->
+                   handle_a(StateData, Pkt);
+               _ ->
+                   Res = if is_record(Pkt, sm_enable);
+                            is_record(Pkt, sm_resume) ->
+                                 #sm_failed{reason = 'unexpected-request',
+                                            xmlns = Xmlns};
+                            true ->
+                                 #sm_failed{reason = 'bad-request',
+                                            xmlns = Xmlns}
+                         end,
+                   send_element(StateData, Res),
+                   StateData
+           end;
+       _ ->
+           send_element(StateData,
+                        #sm_failed{reason = 'unsupported-version',
+                                   xmlns = StateData#state.mgmt_xmlns})
     end.
 
 handle_enable(#state{mgmt_timeout = DefaultTimeout,
-                    mgmt_max_timeout = MaxTimeout} = StateData, Attrs) ->
-    Timeout = case fxml:get_attr_s(<<"resume">>, Attrs) of
-               ResumeAttr when ResumeAttr == <<"true">>;
-                               ResumeAttr == <<"1">> ->
-                   MaxAttr = fxml:get_attr_s(<<"max">>, Attrs),
-                   case catch jlib:binary_to_integer(MaxAttr) of
-                     Max when is_integer(Max), Max > 0, Max =< MaxTimeout ->
-                         Max;
-                     _ ->
-                         DefaultTimeout
-                   end;
-               _ ->
-                   0
+                    mgmt_max_timeout = MaxTimeout} = StateData,
+             #sm_enable{resume = Resume, max = Max}) ->
+    Timeout = if Resume == false ->
+                     0;
+                Max /= undefined, Max > 0, Max =< MaxTimeout ->
+                     Max;
+                true ->
+                     DefaultTimeout
              end,
-    ResAttrs = [{<<"xmlns">>, StateData#state.mgmt_xmlns}] ++
-       if Timeout > 0 ->
-              ?INFO_MSG("Stream management with resumption enabled for ~s",
-                        [jid:to_string(StateData#state.jid)]),
-              [{<<"id">>, make_resume_id(StateData)},
-               {<<"resume">>, <<"true">>},
-               {<<"max">>, jlib:integer_to_binary(Timeout)}];
-          true ->
-              ?INFO_MSG("Stream management without resumption enabled for ~s",
-                        [jid:to_string(StateData#state.jid)]),
-              []
-       end,
-    Res = #xmlel{name = <<"enabled">>,
-                attrs = ResAttrs,
-                children = []},
+    Res = if Timeout > 0 ->
+                 ?INFO_MSG("Stream management with resumption enabled for ~s",
+                           [jid:to_string(StateData#state.jid)]),
+                 #sm_enabled{xmlns = StateData#state.mgmt_xmlns,
+                             id = make_resume_id(StateData),
+                             resume = true,
+                             max = Timeout};
+            true ->
+                 ?INFO_MSG("Stream management without resumption enabled for ~s",
+                           [jid:to_string(StateData#state.jid)]),
+                 #sm_enabled{xmlns = StateData#state.mgmt_xmlns}
+         end,
     send_element(StateData, Res),
     StateData#state{mgmt_state = active,
                    mgmt_queue = queue:new(),
                    mgmt_timeout = Timeout * 1000}.
 
 handle_r(StateData) ->
-    H = jlib:integer_to_binary(StateData#state.mgmt_stanzas_in),
-    Res = #xmlel{name = <<"a">>,
-                attrs = [{<<"xmlns">>, StateData#state.mgmt_xmlns},
-                         {<<"h">>, H}],
-                children = []},
+    Res = #sm_a{xmlns = StateData#state.mgmt_xmlns,
+               h = StateData#state.mgmt_stanzas_in},
     send_element(StateData, Res),
     StateData.
 
-handle_a(StateData, Attrs) ->
-    case catch jlib:binary_to_integer(fxml:get_attr_s(<<"h">>, Attrs)) of
-      H when is_integer(H), H >= 0 ->
-         check_h_attribute(StateData, H);
-      _ ->
-         ?DEBUG("Ignoring invalid ACK element from ~s",
-                [jid:to_string(StateData#state.jid)]),
-         StateData
-    end.
+handle_a(StateData, #sm_a{h = H}) ->
+    check_h_attribute(StateData, H).
 
-handle_resume(StateData, Attrs) ->
-    R = case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-         Xmlns when ?IS_SUPPORTED_MGMT_XMLNS(Xmlns) ->
-             case stream_mgmt_enabled(StateData) of
-               true ->
-                   case {fxml:get_attr(<<"previd">>, Attrs),
-                         catch jlib:binary_to_integer(fxml:get_attr_s(<<"h">>, Attrs))}
-                       of
-                     {{value, PrevID}, H} when is_integer(H), H >= 0 ->
-                         case inherit_session_state(StateData, PrevID) of
-                           {ok, InheritedState} ->
-                               {ok, InheritedState, H};
-                           {error, Err, InH} ->
-                               {error, ?MGMT_ITEM_NOT_FOUND_H(Xmlns, InH), Err};
-                           {error, Err} ->
-                               {error, ?MGMT_ITEM_NOT_FOUND(Xmlns), Err}
-                         end;
-                     _ ->
-                         {error, ?MGMT_BAD_REQUEST(Xmlns),
-                          <<"Invalid request">>}
-                   end;
-               false ->
-                   {error, ?MGMT_SERVICE_UNAVAILABLE(Xmlns),
-                    <<"XEP-0198 disabled">>}
-             end;
-         _ ->
-             {error, ?MGMT_UNSUPPORTED_VERSION(?NS_STREAM_MGMT_3),
-              <<"Invalid XMLNS">>}
+handle_resume(StateData, #sm_resume{h = H, previd = PrevID, xmlns = Xmlns}) ->
+    R = case stream_mgmt_enabled(StateData) of
+           true ->
+               case inherit_session_state(StateData, PrevID) of
+                   {ok, InheritedState} ->
+                       {ok, InheritedState, H};
+                   {error, Err, InH} ->
+                       {error, #sm_failed{reason = 'item-not-found',
+                                          h = InH, xmlns = Xmlns}, Err};
+                   {error, Err} ->
+                       {error, #sm_failed{reason = 'item-not-found',
+                                          xmlns = Xmlns}, Err}
+               end;
+           false ->
+               {error, #sm_failed{reason = 'service-unavailable',
+                                  xmlns = Xmlns},
+                <<"XEP-0198 disabled">>}
        end,
     case R of
       {ok, ResumedState, NumHandled} ->
          NewState = check_h_attribute(ResumedState, NumHandled),
          AttrXmlns = NewState#state.mgmt_xmlns,
          AttrId = make_resume_id(NewState),
-         AttrH = jlib:integer_to_binary(NewState#state.mgmt_stanzas_in),
-         send_element(NewState,
-                      #xmlel{name = <<"resumed">>,
-                             attrs = [{<<"xmlns">>, AttrXmlns},
-                                      {<<"h">>, AttrH},
-                                      {<<"previd">>, AttrId}],
-                             children = []}),
+         AttrH = NewState#state.mgmt_stanzas_in,
+         send_element(NewState, #sm_resumed{xmlns = AttrXmlns,
+                                            h = AttrH,
+                                            previd = AttrId}),
          SendFun = fun(_F, _T, El, Time) ->
                            NewEl = add_resent_delay_info(NewState, El, Time),
                            send_element(NewState, NewEl)
                    end,
          handle_unacked_stanzas(NewState, SendFun),
-         send_element(NewState,
-                      #xmlel{name = <<"r">>,
-                             attrs = [{<<"xmlns">>, AttrXmlns}],
-                             children = []}),
+         send_element(NewState, #sm_r{xmlns = AttrXmlns}),
          FlushedState = csi_flush_queue(NewState),
          NewStateData = FlushedState#state{csi_state = active},
          ?INFO_MSG("Resumed session for ~s",
@@ -2810,7 +2391,7 @@ check_h_attribute(#state{mgmt_stanzas_out = NumStanzasOut} = StateData, H) ->
 update_num_stanzas_in(#state{mgmt_state = MgmtState} = StateData, El)
     when MgmtState == active;
         MgmtState == pending ->
-    NewNum = case {is_stanza(El), StateData#state.mgmt_stanzas_in} of
+    NewNum = case {xmpp:is_stanza(El), StateData#state.mgmt_stanzas_in} of
               {true, 4294967295} ->
                   0;
               {true, Num} ->
@@ -2823,9 +2404,7 @@ update_num_stanzas_in(StateData, _El) ->
     StateData.
 
 send_stanza_and_ack_req(StateData, Stanza) ->
-    AckReq = #xmlel{name = <<"r">>,
-                   attrs = [{<<"xmlns">>, StateData#state.mgmt_xmlns}],
-                   children = []},
+    AckReq = #sm_r{xmlns = StateData#state.mgmt_xmlns},
     case send_element(StateData, Stanza) == ok andalso
         send_element(StateData, AckReq) == ok of
       true ->
@@ -2876,12 +2455,10 @@ handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData, F)
          ?DEBUG("~B stanza(s) were not acknowledged by ~s",
                 [N, jid:to_string(StateData#state.jid)]),
          lists:foreach(
-           fun({_, Time, #xmlel{attrs = Attrs} = El}) ->
-                   From_s = fxml:get_attr_s(<<"from">>, Attrs),
-                   From = jid:from_string(From_s),
-                   To_s = fxml:get_attr_s(<<"to">>, Attrs),
-                   To = jid:from_string(To_s),
-                   F(From, To, El, Time)
+           fun({_, Time, Pkt}) ->
+                   From = xmpp:get_from(Pkt),
+                   To = xmpp:get_to(Pkt),
+                   F(From, To, Pkt, Time)
            end, queue:to_list(Queue))
     end;
 handle_unacked_stanzas(_StateData, _F) ->
@@ -2917,20 +2494,18 @@ handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData)
                false ->
                    fun(From, To, El, _Time) ->
                            Txt = <<"User session terminated">>,
-                           Err =
-                               jlib:make_error_reply(
-                                 El,
-                                 ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)),
+                           Err = xmpp:make_error(
+                                   El, xmpp:err_service_unavailable(Txt, Lang)),
                            ejabberd_router:route(To, From, Err)
                    end
              end,
-    F = fun(From, _To, #xmlel{name = <<"presence">>}, _Time) ->
+    F = fun(From, _To, #presence{}, _Time) ->
                ?DEBUG("Dropping presence stanza from ~s",
                       [jid:to_string(From)]);
-          (From, To, #xmlel{name = <<"iq">>} = El, _Time) ->
+          (From, To, #iq{} = El, _Time) ->
                Txt = <<"User session terminated">>,
-               Err = jlib:make_error_reply(
-                       El, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)),
+               Err = xmpp:make_error(
+                       El, xmpp:err_service_unavailable(Txt, Lang)),
                ejabberd_router:route(To, From, Err);
           (From, To, El, Time) ->
                %% We'll drop the stanza if it was <forwarded/> by some
@@ -2943,7 +2518,7 @@ handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData)
                case is_encapsulated_forward(El) of
                  true ->
                      ?DEBUG("Dropping forwarded message stanza from ~s",
-                            [fxml:get_attr_s(<<"from">>, El#xmlel.attrs)]);
+                            [jid:to_string(From)]);
                  false ->
                      case ejabberd_hooks:run_fold(message_is_archived,
                                                   StateData#state.server,
@@ -2961,29 +2536,10 @@ handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData)
 handle_unacked_stanzas(_StateData) ->
     ok.
 
-is_encapsulated_forward(#xmlel{name = <<"message">>} = El) ->
-    SubTag = case {fxml:get_subtag(El, <<"sent">>),
-                  fxml:get_subtag(El, <<"received">>),
-                  fxml:get_subtag(El, <<"result">>)} of
-              {false, false, false} ->
-                  false;
-              {Tag, false, false} ->
-                  Tag;
-              {false, Tag, false} ->
-                  Tag;
-              {_, _, Tag} ->
-                  Tag
-           end,
-    if SubTag == false ->
-          false;
-       true ->
-          case fxml:get_subtag(SubTag, <<"forwarded">>) of
-            false ->
-                false;
-            _ ->
-                true
-          end
-    end;
+is_encapsulated_forward(#message{} = Msg) ->
+    xmpp:has_subtag(Msg, #forwarded{}) orelse
+       xmpp:has_subtag(Msg, #carbons_sent{}) orelse
+       xmpp:has_subtag(Msg, #carbons_received{});
 is_encapsulated_forward(_El) ->
     false.
 
@@ -3054,10 +2610,10 @@ make_resume_id(StateData) ->
     {Time, _} = StateData#state.sid,
     jlib:term_to_base64({StateData#state.resource, Time}).
 
-add_resent_delay_info(_State, #xmlel{name = <<"iq">>} = El, _Time) ->
+add_resent_delay_info(_State, #iq{} = El, _Time) ->
     El;
 add_resent_delay_info(#state{server = From}, El, Time) ->
-    jlib:add_delay_info(El, From, Time, <<"Resent">>).
+    xmpp_util:add_delay_info(El, From, Time, <<"Resent">>).
 
 %%%----------------------------------------------------------------------
 %%% XEP-0352
index b8e706f239da236b0f21b4a8ef6f20943270d13e..ab5b6a70163e65710704ee8f7023a0df20b5bf26 100644 (file)
@@ -42,6 +42,7 @@
         change_shaper/2,
         monitor/1,
         get_sockmod/1,
+        get_transport/1,
         get_peer_certificate/1,
         get_verify_result/1,
         close/1,
@@ -118,6 +119,9 @@ monitor(FsmRef) -> erlang:monitor(process, FsmRef).
 get_sockmod(FsmRef) ->
     gen_server:call(FsmRef, get_sockmod).
 
+get_transport(FsmRef) ->
+    gen_server:call(FsmRef, get_transport).
+
 get_peer_certificate(FsmRef) ->
     gen_server:call(FsmRef, get_peer_certificate).
 
@@ -186,6 +190,19 @@ handle_call({change_shaper, Shaper}, _From, State) ->
 handle_call(get_sockmod, _From, State) ->
     Reply = State#state.sockmod,
     {reply, Reply, State, ?HIBERNATE_TIMEOUT};
+handle_call(get_transport, _From, State) ->
+    Reply = case State#state.sockmod of
+               gen_tcp -> tcp;
+               fast_tls -> tls;
+               ezlib ->
+                   case ezlib:get_sockmod(State#state.socket) of
+                       tcp -> tcp_zlib;
+                       tls -> tls_zlib
+                   end;
+               ejabberd_http_bind -> http_bind;
+               ejabberd_http_ws -> websocket
+           end,
+    {reply, Reply, State, ?HIBERNATE_TIMEOUT};
 handle_call(get_peer_certificate, _From, State) ->
     Reply = fast_tls:get_peer_certificate(State#state.socket),
     {reply, Reply, State, ?HIBERNATE_TIMEOUT};
index 2ba94369363f211485a9be8b2cbf2d9ca6092732..dca456427a2bd3e99e37b6da530a41e1c140b861 100644 (file)
@@ -46,7 +46,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -record(state, {}).
 
@@ -60,6 +60,8 @@
 %% This value is used in SIP and Megaco for a transaction lifetime.
 -define(IQ_TIMEOUT, 32000).
 
+-type ping_timeout() :: non_neg_integer() | undefined.
+
 %%====================================================================
 %% API
 %%====================================================================
@@ -71,37 +73,38 @@ start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [],
                          []).
 
-process_iq(From, To, Packet) ->
-    IQ = jlib:iq_query_info(Packet),
-    case IQ of
-      #iq{xmlns = XMLNS, lang = Lang} ->
-         Host = To#jid.lserver,
-         case ets:lookup(?IQTABLE, {XMLNS, Host}) of
-           [{_, Module, Function}] ->
-               ResIQ = Module:Function(From, To, IQ),
-               if ResIQ /= ignore ->
-                      ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ));
-                  true -> ok
-               end;
-           [{_, Module, Function, Opts}] ->
-               gen_iq_handler:handle(Host, Module, Function, Opts,
-                                     From, To, IQ);
-           [] ->
-               Txt = <<"No module is handling this query">>,
-               Err = jlib:make_error_reply(
-                       Packet,
-                       ?ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Txt)),
-               ejabberd_router:route(To, From, Err)
-         end;
-      reply ->
-         IQReply = jlib:iq_query_or_response_info(Packet),
-         process_iq_reply(From, To, IQReply);
-      _ ->
-         Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST),
-         ejabberd_router:route(To, From, Err),
-         ok
+-spec process_iq(jid(), jid(), iq()) -> any().
+process_iq(From, To, #iq{type = T, lang = Lang, sub_els = [El]} = Packet)
+  when T == get; T == set ->
+    XMLNS = xmpp:get_ns(El),
+    Host = To#jid.lserver,
+    case ets:lookup(?IQTABLE, {XMLNS, Host}) of
+       [{_, Module, Function}] ->
+           gen_iq_handler:handle(Host, Module, Function, no_queue,
+                                 From, To, Packet);
+       [{_, Module, Function, Opts}] ->
+           gen_iq_handler:handle(Host, Module, Function, Opts,
+                                 From, To, Packet);
+       [] ->
+           Txt = <<"No module is handling this query">>,
+           Err = xmpp:make_error(
+                   Packet,
+                   xmpp:err_service_unavailable(Txt, Lang)),
+           ejabberd_router:route(To, From, Err)
+    end;
+process_iq(From, To, #iq{type = T} = Packet) when T == get; T == set ->
+    Err = xmpp:make_error(Packet, xmpp:err_bad_request()),
+    ejabberd_router:route(To, From, Err);
+process_iq(From, To, #iq{type = T} = Packet) when T == result; T == error ->
+    try
+       NewPacket = xmpp:decode_els(Packet),
+       process_iq_reply(From, To, NewPacket)
+    catch _:{xmpp_codec, Why} ->
+           ?DEBUG("failed to decode iq-result ~p: ~s",
+                  [Packet, xmpp:format_error(Why)])
     end.
 
+-spec process_iq_reply(jid(), jid(), iq()) -> any().
 process_iq_reply(From, To, #iq{id = ID} = IQ) ->
     case get_iq_callback(ID) of
       {ok, undefined, Function} -> Function(IQ), ok;
@@ -110,6 +113,7 @@ process_iq_reply(From, To, #iq{id = ID} = IQ) ->
       _ -> nothing
     end.
 
+-spec route(jid(), jid(), stanza()) -> any().
 route(From, To, Packet) ->
     case catch do_route(From, To, Packet) of
       {'EXIT', Reason} ->
@@ -118,26 +122,32 @@ route(From, To, Packet) ->
       _ -> ok
     end.
 
+-spec route_iq(jid(), jid(), iq(), function()) -> any().
 route_iq(From, To, IQ, F) ->
     route_iq(From, To, IQ, F, undefined).
 
+-spec route_iq(jid(), jid(), iq(), function(), ping_timeout()) -> any().
 route_iq(From, To, #iq{type = Type} = IQ, F, Timeout)
     when is_function(F) ->
     Packet = if Type == set; Type == get ->
                     ID = randoms:get_string(),
                     Host = From#jid.lserver,
                     register_iq_response_handler(Host, ID, undefined, F, Timeout),
-                    jlib:iq_to_xml(IQ#iq{id = ID});
+                    IQ#iq{id = ID};
                true ->
-                    jlib:iq_to_xml(IQ)
+                    IQ
             end,
     ejabberd_router:route(From, To, Packet).
 
+-spec register_iq_response_handler(binary(), binary(), module(),
+                                  atom() | function()) -> any().
 register_iq_response_handler(Host, ID, Module,
                             Function) ->
     register_iq_response_handler(Host, ID, Module, Function,
                                 undefined).
 
+-spec register_iq_response_handler(binary(), binary(), module(),
+                                  atom() | function(), ping_timeout()) -> any().
 register_iq_response_handler(_Host, ID, Module,
                             Function, Timeout0) ->
     Timeout = case Timeout0 of
@@ -150,28 +160,35 @@ register_iq_response_handler(_Host, ID, Module,
                                    function = Function,
                                    timer = TRef}).
 
+-spec register_iq_handler(binary(), binary(), module(), function()) -> any().
 register_iq_handler(Host, XMLNS, Module, Fun) ->
     ejabberd_local !
       {register_iq_handler, Host, XMLNS, Module, Fun}.
 
+-spec register_iq_handler(binary(), binary(), module(), function(),
+                         gen_iq_handler:opts()) -> any().
 register_iq_handler(Host, XMLNS, Module, Fun, Opts) ->
     ejabberd_local !
       {register_iq_handler, Host, XMLNS, Module, Fun, Opts}.
 
+-spec unregister_iq_response_handler(binary(), binary()) -> ok.
 unregister_iq_response_handler(_Host, ID) ->
     catch get_iq_callback(ID), ok.
 
+-spec unregister_iq_handler(binary(), binary()) -> any().
 unregister_iq_handler(Host, XMLNS) ->
     ejabberd_local ! {unregister_iq_handler, Host, XMLNS}.
 
+-spec refresh_iq_handlers() -> any().
 refresh_iq_handlers() ->
     ejabberd_local ! refresh_iq_handlers.
 
+-spec bounce_resource_packet(jid(), jid(), stanza()) -> stop.
 bounce_resource_packet(From, To, Packet) ->
-    Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet),
+    Lang = xmpp:get_lang(Packet),
     Txt = <<"No available resource found">>,
-    Err = jlib:make_error_reply(Packet,
-                               ?ERRT_ITEM_NOT_FOUND(Lang, Txt)),
+    Err = xmpp:make_error(Packet,
+                         xmpp:err_item_not_found(Txt, Lang)),
     ejabberd_router:route(To, From, Err),
     stop.
 
@@ -261,50 +278,45 @@ code_change(_OldVsn, State, _Extra) ->
 %%--------------------------------------------------------------------
 %%% Internal functions
 %%--------------------------------------------------------------------
+-spec do_route(jid(), jid(), stanza()) -> any().
 do_route(From, To, Packet) ->
     ?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket "
           "~P~n",
           [From, To, Packet, 8]),
     if To#jid.luser /= <<"">> ->
-          ejabberd_sm:route(From, To, Packet);
+           ejabberd_sm:route(From, To, Packet);
        To#jid.lresource == <<"">> ->
-          #xmlel{name = Name} = Packet,
-          case Name of
-            <<"iq">> -> process_iq(From, To, Packet);
-            <<"message">> ->
-                #xmlel{attrs = Attrs} = Packet,
-                case fxml:get_attr_s(<<"type">>, Attrs) of
-                  <<"headline">> -> ok;
-                  <<"error">> -> ok;
-                  _ ->
-                      Err = jlib:make_error_reply(Packet,
-                                                  ?ERR_SERVICE_UNAVAILABLE),
-                      ejabberd_router:route(To, From, Err)
-                end;
-            <<"presence">> -> ok;
-            _ -> ok
-          end;
+           case Packet of
+               #iq{} ->
+                   process_iq(From, To, Packet);
+               #message{type = T} when T /= headline, T /= error ->
+                   Err = xmpp:make_error(Packet, xmpp:err_service_unavailable()),
+                   ejabberd_router:route(To, From, Err);
+               _ -> ok
+           end;
        true ->
-          #xmlel{attrs = Attrs} = Packet,
-          case fxml:get_attr_s(<<"type">>, Attrs) of
-            <<"error">> -> ok;
-            <<"result">> -> ok;
-            _ ->
-                ejabberd_hooks:run(local_send_to_resource_hook,
-                                   To#jid.lserver, [From, To, Packet])
-          end
+           case xmpp:get_type(Packet) of
+               error -> ok;
+               result -> ok;
+               _ ->
+                   ejabberd_hooks:run(local_send_to_resource_hook,
+                                      To#jid.lserver, [From, To, Packet])
+           end
     end.
 
+-spec update_table() -> ok.
 update_table() ->
     case catch mnesia:table_info(iq_response, attributes) of
        [id, module, function] ->
-           mnesia:delete_table(iq_response);
+           mnesia:delete_table(iq_response),
+           ok;
        [id, module, function, timer] ->
            ok;
        {'EXIT', _} ->
            ok
     end.
 
+-spec get_iq_callback(binary()) -> {ok, module(), atom() | function()} | error.
 get_iq_callback(ID) ->
     case mnesia:dirty_read(iq_response, ID) of
        [#iq_response{module = Module, timer = TRef,
@@ -316,9 +328,11 @@ get_iq_callback(ID) ->
            error
     end.
 
+-spec process_iq_timeout(binary()) -> any().
 process_iq_timeout(ID) ->
     spawn(fun process_iq_timeout/0) ! ID.
 
+-spec process_iq_timeout() -> any().
 process_iq_timeout() ->
     receive
        ID ->
@@ -332,6 +346,7 @@ process_iq_timeout() ->
            ok
     end.
 
+-spec cancel_timer(reference()) -> ok.
 cancel_timer(TRef) ->
     case erlang:cancel_timer(TRef) of
       false ->
index e29d6acfb1ed8328c399f7d28f47c3c513120f8f..5924d92c06f714f468eefe7d824c5e5284624410 100644 (file)
@@ -39,6 +39,7 @@
         register_route/3,
         register_routes/1,
         host_of_route/1,
+        process_iq/3,
         unregister_route/1,
         unregister_routes/1,
         dirty_get_all_routes/0,
@@ -53,7 +54,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -type local_hint() :: undefined | integer() | {apply, atom(), atom()}.
 
@@ -71,7 +72,7 @@
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
--spec route(jid(), jid(), xmlel()) -> ok.
+-spec route(jid(), jid(), xmlel() | xmpp_element()) -> ok.
 
 route(From, To, Packet) ->
     case catch do_route(From, To, Packet) of
@@ -236,6 +237,28 @@ host_of_route(Domain) ->
            end
     end.
 
+-spec process_iq(jid(), jid(), iq() | xmlel()) -> any().
+process_iq(From, To, #iq{} = IQ) ->
+    if To#jid.luser == <<"">> ->
+           ejabberd_local:process_iq(From, To, IQ);
+       true ->
+           ejabberd_sm:process_iq(From, To, IQ)
+    end;
+process_iq(From, To, El) ->
+    try xmpp:decode(El, [ignore_els]) of
+       IQ -> process_iq(From, To, IQ)
+    catch _:{xmpp_codec, Why} ->
+           Type = xmpp:get_type(El),
+           if Type == <<"get">>; Type == <<"set">> ->
+                   Txt = xmpp:format_error(Why),
+                   Lang = xmpp:get_lang(El),
+                   Err = xmpp:make_error(El, xmpp:err_bad_request(Txt, Lang)),
+                   ejabberd_router:route(To, From, Err);
+              true ->
+                   ok
+           end
+    end.
+
 %%====================================================================
 %% gen_server callbacks
 %%====================================================================
@@ -347,6 +370,7 @@ code_change(_OldVsn, State, _Extra) ->
 %%--------------------------------------------------------------------
 %%% Internal functions
 %%--------------------------------------------------------------------
+-spec do_route(jid(), jid(), xmlel() | xmpp_element()) -> any().
 do_route(OrigFrom, OrigTo, OrigPacket) ->
     ?DEBUG("route~n\tfrom ~p~n\tto ~p~n\tpacket "
           "~p~n",
@@ -359,67 +383,66 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
          case mnesia:dirty_read(route, LDstDomain) of
            [] -> ejabberd_s2s:route(From, To, Packet);
            [R] ->
-               Pid = R#route.pid,
-               if node(Pid) == node() ->
-                      case R#route.local_hint of
-                        {apply, Module, Function} ->
-                            Module:Function(From, To, Packet);
-                        _ -> Pid ! {route, From, To, Packet}
-                      end;
-                  is_pid(Pid) -> Pid ! {route, From, To, Packet};
-                  true -> drop
-               end;
+               do_route(From, To, Packet, R);
            Rs ->
-               Value = case
-                         ejabberd_config:get_option({domain_balancing,
-                                                     LDstDomain}, fun(D) when is_atom(D) -> D end)
-                           of
-                         undefined -> p1_time_compat:monotonic_time();
-                         random -> p1_time_compat:monotonic_time();
-                         source -> jid:tolower(From);
-                         destination -> jid:tolower(To);
-                         bare_source ->
-                             jid:remove_resource(jid:tolower(From));
-                         bare_destination ->
-                             jid:remove_resource(jid:tolower(To))
-                       end,
+               Value = get_domain_balancing(From, To, LDstDomain),
                case get_component_number(LDstDomain) of
                  undefined ->
                      case [R || R <- Rs, node(R#route.pid) == node()] of
                        [] ->
                            R = lists:nth(erlang:phash(Value, length(Rs)), Rs),
-                           Pid = R#route.pid,
-                           if is_pid(Pid) -> Pid ! {route, From, To, Packet};
-                              true -> drop
-                           end;
+                           do_route(From, To, Packet, R);
                        LRs ->
-                           R = lists:nth(erlang:phash(Value, length(LRs)),
-                                         LRs),
-                           Pid = R#route.pid,
-                           case R#route.local_hint of
-                             {apply, Module, Function} ->
-                                 Module:Function(From, To, Packet);
-                             _ -> Pid ! {route, From, To, Packet}
-                           end
+                           R = lists:nth(erlang:phash(Value, length(LRs)), LRs),
+                           do_route(From, To, Packet, R)
                      end;
                  _ ->
                      SRs = lists:ukeysort(#route.local_hint, Rs),
                      R = lists:nth(erlang:phash(Value, length(SRs)), SRs),
-                     Pid = R#route.pid,
-                     if is_pid(Pid) -> Pid ! {route, From, To, Packet};
-                        true -> drop
-                     end
+                     do_route(From, To, Packet, R)
                end
          end;
       drop -> ok
     end.
 
+-spec do_route(jid(), jid(), xmlel() | xmpp_element(), #route{}) -> any().
+do_route(From, To, Packet,
+        #route{local_hint = {apply, Module, Function}, pid = Pid})
+  when is_pid(Pid) andalso node(Pid) == node() ->
+    try
+       Module:Function(From, To, xmpp:decode(Packet, [ignore_els]))
+    catch error:{xmpp_codec, Why} ->
+           ?ERROR_MSG("failed to decode xml element ~p when "
+                      "routing from ~s to ~s: ~s",
+                      [Packet, jid:to_string(From), jid:to_string(To),
+                       xmpp:format_error(Why)]),
+           drop
+    end;
+do_route(From, To, Packet, #route{pid = Pid}) when is_pid(Pid) ->
+    Pid ! {route, From, To, xmpp:encode(Packet)};
+do_route(_From, _To, _Packet, _Route) ->
+    drop.
+
+-spec get_component_number(binary()) -> pos_integer() | undefined.
 get_component_number(LDomain) ->
     ejabberd_config:get_option(
       {domain_balancing_component_number, LDomain},
       fun(N) when is_integer(N), N > 1 -> N end,
       undefined).
 
+-spec get_domain_balancing(jid(), jid(), binary()) -> any().
+get_domain_balancing(From, To, LDomain) ->
+    case ejabberd_config:get_option(
+          {domain_balancing, LDomain}, fun(D) when is_atom(D) -> D end) of
+       undefined -> p1_time_compat:monotonic_time();
+       random -> p1_time_compat:monotonic_time();
+       source -> jid:tolower(From);
+       destination -> jid:tolower(To);
+       bare_source -> jid:remove_resource(jid:tolower(From));
+       bare_destination -> jid:remove_resource(jid:tolower(To))
+    end.
+
+-spec update_tables() -> ok.
 update_tables() ->
     try
        mnesia:transform_table(route, ignore, record_info(fields, route))
index 8d94bc6aa23345bfb2ceca171cfc7dff258a6ff4..ec9ef43c6e5446f8dff772ae555ccf897837ea14 100644 (file)
@@ -78,7 +78,8 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+%%-include("jlib.hrl").
+-include("xmpp.hrl").
 
 -include("ejabberd_commands.hrl").
 -include("mod_privacy.hrl").
 %% default value for the maximum number of user connections
 -define(MAX_USER_SESSIONS, infinity).
 
+-type broadcast() :: {broadcast, broadcast_data()}.
+
+-type broadcast_data() ::
+        {rebind, pid(), binary()} | %% ejabberd_c2s
+        {item, ljid(), mod_roster:subscription()} | %% mod_roster/mod_shared_roster
+        {exit, binary()} | %% mod_roster/mod_shared_roster
+        {privacy_list, mod_privacy:userlist(), binary()} | %% mod_privacy
+        {blocking, unblock_all | {block | unblock, [ljid()]}}. %% mod_blocking
+
 %%====================================================================
 %% API
 %%====================================================================
@@ -111,7 +121,7 @@ start() ->
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
--spec route(jid(), jid(), xmlel() | broadcast()) -> ok.
+-spec route(jid(), jid(), stanza() | broadcast()) -> ok.
 
 route(From, To, Packet) ->
     case catch do_route(From, To, Packet) of
@@ -162,10 +172,10 @@ check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) ->
 -spec bounce_offline_message(jid(), jid(), xmlel()) -> stop.
 
 bounce_offline_message(From, To, Packet) ->
-    Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet),
+    Lang = xmpp:get_lang(Packet),
     Txt = <<"User session not found">>,
-    Err = jlib:make_error_reply(
-           Packet, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)),
+    Err = xmpp:make_error(
+           Packet, xmpp:err_service_unavailable(Txt, Lang)),
     ejabberd_router:route(To, From, Err),
     stop.
 
@@ -432,7 +442,7 @@ online(Sessions) ->
                 end, Sessions).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+-spec do_route(jid(), jid(), stanza() | broadcast()) -> any().
 do_route(From, To, {broadcast, _} = Packet) ->
     case To#jid.lresource of
         <<"">> ->
@@ -455,25 +465,20 @@ do_route(From, To, {broadcast, _} = Packet) ->
                     Pid ! {route, From, To, Packet}
             end
     end;
-do_route(From, To, #xmlel{} = Packet) ->
+do_route(From, To, Packet) ->
     ?DEBUG("session manager~n\tfrom ~p~n\tto ~p~n\tpacket "
           "~P~n",
           [From, To, Packet, 8]),
     #jid{user = User, server = Server,
         luser = LUser, lserver = LServer, lresource = LResource} = To,
-    #xmlel{name = Name, attrs = Attrs} = Packet,
-    Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs),
+    Lang = xmpp:get_lang(Packet),
     case LResource of
       <<"">> ->
-         case Name of
-           <<"presence">> ->
-               {Pass, _Subsc} = case fxml:get_attr_s(<<"type">>, Attrs)
-                                    of
-                                  <<"subscribe">> ->
-                                      Reason = fxml:get_path_s(Packet,
-                                                              [{elem,
-                                                                <<"status">>},
-                                                               cdata]),
+         case Packet of
+           #presence{type = T, status = Status} ->
+               {Pass, _Subsc} = case T of
+                                  subscribe ->
+                                      Reason = xmpp:get_text(Status),
                                       {is_privacy_allow(From, To, Packet)
                                          andalso
                                          ejabberd_hooks:run_fold(roster_in_subscription,
@@ -484,7 +489,7 @@ do_route(From, To, #xmlel{} = Packet) ->
                                                                   subscribe,
                                                                   Reason]),
                                        true};
-                                  <<"subscribed">> ->
+                                  subscribed ->
                                       {is_privacy_allow(From, To, Packet)
                                          andalso
                                          ejabberd_hooks:run_fold(roster_in_subscription,
@@ -495,7 +500,7 @@ do_route(From, To, #xmlel{} = Packet) ->
                                                                   subscribed,
                                                                   <<"">>]),
                                        true};
-                                  <<"unsubscribe">> ->
+                                  unsubscribe ->
                                       {is_privacy_allow(From, To, Packet)
                                          andalso
                                          ejabberd_hooks:run_fold(roster_in_subscription,
@@ -506,7 +511,7 @@ do_route(From, To, #xmlel{} = Packet) ->
                                                                   unsubscribe,
                                                                   <<"">>]),
                                        true};
-                                  <<"unsubscribed">> ->
+                                  unsubscribed ->
                                       {is_privacy_allow(From, To, Packet)
                                          andalso
                                          ejabberd_hooks:run_fold(roster_in_subscription,
@@ -530,53 +535,36 @@ do_route(From, To, #xmlel{} = Packet) ->
                                     PResources);
                   true -> ok
                end;
-           <<"message">> ->
-               case fxml:get_attr_s(<<"type">>, Attrs) of
-                 <<"chat">> -> route_message(From, To, Packet, chat);
-                 <<"headline">> -> route_message(From, To, Packet, headline);
-                 <<"error">> -> ok;
-                 <<"groupchat">> ->
-                     ErrTxt = <<"User session not found">>,
-                     Err = jlib:make_error_reply(
-                             Packet, ?ERRT_SERVICE_UNAVAILABLE(Lang, ErrTxt)),
-                     ejabberd_router:route(To, From, Err);
-                 _ ->
-                     route_message(From, To, Packet, normal)
-               end;
-           <<"iq">> -> process_iq(From, To, Packet);
-           _ -> ok
+             #message{type = T} when T == chat; T == headline; T == normal ->
+                 route_message(From, To, Packet, T);
+             #message{type = groupchat} ->
+                 ErrTxt = <<"User session not found">>,
+                 Err = xmpp:make_error(
+                         Packet, xmpp:err_service_unavailable(ErrTxt, Lang)),
+                 ejabberd_router:route(To, From, Err);
+             #iq{} -> process_iq(From, To, Packet);
+             _ -> ok
          end;
       _ ->
        Mod = get_sm_backend(LServer),
        case online(Mod:get_sessions(LUser, LServer, LResource)) of
            [] ->
-               case Name of
-                 <<"message">> ->
-                     case fxml:get_attr_s(<<"type">>, Attrs) of
-                       <<"chat">> -> route_message(From, To, Packet, chat);
-                       <<"headline">> -> ok;
-                       <<"error">> -> ok;
-                       <<"groupchat">> ->
-                           ErrTxt = <<"User session not found">>,
-                           Err = jlib:make_error_reply(
-                                   Packet,
-                                   ?ERRT_SERVICE_UNAVAILABLE(Lang, ErrTxt)),
-                           ejabberd_router:route(To, From, Err);
-                       _ ->
-                           route_message(From, To, Packet, normal)
-                     end;
-                 <<"iq">> ->
-                     case fxml:get_attr_s(<<"type">>, Attrs) of
-                       <<"error">> -> ok;
-                       <<"result">> -> ok;
-                       _ ->
-                           ErrTxt = <<"User session not found">>,
-                           Err = jlib:make_error_reply(
-                                   Packet,
-                                   ?ERRT_SERVICE_UNAVAILABLE(Lang, ErrTxt)),
-                           ejabberd_router:route(To, From, Err)
-                     end;
-                 _ -> ?DEBUG("packet dropped~n", [])
+               case Packet of
+                   #message{type = T} when T == chat; T == normal ->
+                       route_message(From, To, Packet, T);
+                   #message{type = groupchat} ->
+                       ErrTxt = <<"User session not found">>,
+                       Err = xmpp:make_error(
+                               Packet,
+                               xmpp:err_service_unavailable(ErrTxt, Lang)),
+                       ejabberd_router:route(To, From, Err);
+                   #iq{type = T} when T == get; T == set ->
+                       ErrTxt = <<"User session not found">>,
+                       Err = xmpp:make_error(
+                               Packet,
+                               xmpp:err_service_unavailable(ErrTxt, Lang)),
+                       ejabberd_router:route(To, From, Err);
+                   _ -> ?DEBUG("packet dropped~n", [])
                end;
            Ss ->
                Session = lists:max(Ss),
@@ -590,6 +578,7 @@ do_route(From, To, #xmlel{} = Packet) ->
 %% and is processed if there is no active list set
 %% for the target session/resource to which a stanza is addressed,
 %% or if there are no current sessions for the user.
+-spec is_privacy_allow(jid(), jid(), stanza()) -> boolean().
 is_privacy_allow(From, To, Packet) ->
     User = To#jid.user,
     Server = To#jid.server,
@@ -600,6 +589,7 @@ is_privacy_allow(From, To, Packet) ->
 
 %% Check if privacy rules allow this delivery
 %% Function copied from ejabberd_c2s.erl
+-spec is_privacy_allow(jid(), jid(), stanza(), #userlist{}) -> boolean().
 is_privacy_allow(From, To, Packet, PrivacyList) ->
     User = To#jid.user,
     Server = To#jid.server,
@@ -609,6 +599,7 @@ is_privacy_allow(From, To, Packet, PrivacyList) ->
                              [User, Server, PrivacyList, {From, To, Packet},
                               in]).
 
+-spec route_message(jid(), jid(), message(), message_type()) -> any().
 route_message(From, To, Packet, Type) ->
     LUser = To#jid.luser,
     LServer = To#jid.lserver,
@@ -644,18 +635,19 @@ route_message(From, To, Packet, Type) ->
                      ejabberd_hooks:run(offline_message_hook, LServer,
                                         [From, To, Packet]);
                  false ->
-                     Err = jlib:make_error_reply(Packet,
-                                                 ?ERR_SERVICE_UNAVAILABLE),
+                     Err = xmpp:make_error(Packet,
+                                           xmpp:err_service_unavailable()),
                      ejabberd_router:route(To, From, Err)
                end
          end
     end.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+-spec clean_session_list([#session{}]) -> [#session{}].
 clean_session_list(Ss) ->
     clean_session_list(lists:keysort(#session.usr, Ss), []).
 
+-spec clean_session_list([#session{}], [#session{}]) -> [#session{}].
 clean_session_list([], Res) -> Res;
 clean_session_list([S], Res) -> [S | Res];
 clean_session_list([S1, S2 | Rest], Res) ->
@@ -670,6 +662,7 @@ clean_session_list([S1, S2 | Rest], Res) ->
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 %% On new session, check if some existing connections need to be replace
+-spec check_for_sessions_to_replace(binary(), binary(), binary()) -> ok | replaced.
 check_for_sessions_to_replace(User, Server, Resource) ->
     LUser = jid:nodeprep(User),
     LServer = jid:nameprep(Server),
@@ -677,6 +670,7 @@ check_for_sessions_to_replace(User, Server, Resource) ->
     check_existing_resources(LUser, LServer, LResource),
     check_max_sessions(LUser, LServer).
 
+-spec check_existing_resources(binary(), binary(), binary()) -> ok.
 check_existing_resources(LUser, LServer, LResource) ->
     SIDs = get_resource_sessions(LUser, LServer, LResource),
     if SIDs == [] -> ok;
@@ -698,6 +692,7 @@ check_existing_resources(LUser, LServer, LResource) ->
 is_existing_resource(LUser, LServer, LResource) ->
     [] /= get_resource_sessions(LUser, LServer, LResource).
 
+-spec get_resource_sessions(binary(), binary(), binary()) -> [sid()].
 get_resource_sessions(User, Server, Resource) ->
     LUser = jid:nodeprep(User),
     LServer = jid:nameprep(Server),
@@ -705,6 +700,7 @@ get_resource_sessions(User, Server, Resource) ->
     Mod = get_sm_backend(LServer),
     [S#session.sid || S <- online(Mod:get_sessions(LUser, LServer, LResource))].
 
+-spec check_max_sessions(binary(), binary()) -> ok | replaced.
 check_max_sessions(LUser, LServer) ->
     Mod = get_sm_backend(LServer),
     SIDs = [S#session.sid || S <- online(Mod:get_sessions(LUser, LServer))],
@@ -717,6 +713,7 @@ check_max_sessions(LUser, LServer) ->
 %% This option defines the max number of time a given users are allowed to
 %% log in
 %% Defaults to infinity
+-spec get_max_user_sessions(binary(), binary()) -> infinity | non_neg_integer().
 get_max_user_sessions(LUser, Host) ->
     case acl:match_rule(Host, max_user_sessions,
                        jid:make(LUser, Host, <<"">>))
@@ -728,34 +725,31 @@ get_max_user_sessions(LUser, Host) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-process_iq(From, To, Packet) ->
-    IQ = jlib:iq_query_info(Packet),
-    case IQ of
-      #iq{xmlns = XMLNS, lang = Lang} ->
-         Host = To#jid.lserver,
-         case ets:lookup(sm_iqtable, {XMLNS, Host}) of
-           [{_, Module, Function}] ->
-               ResIQ = Module:Function(From, To, IQ),
-               if ResIQ /= ignore ->
-                      ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ));
-                  true -> ok
-               end;
-           [{_, Module, Function, Opts}] ->
-               gen_iq_handler:handle(Host, Module, Function, Opts,
-                                     From, To, IQ);
-           [] ->
-               Txt = <<"No module is handling this query">>,
-               Err = jlib:make_error_reply(
-                       Packet,
-                       ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)),
-               ejabberd_router:route(To, From, Err)
-         end;
-      reply -> ok;
-      _ ->
-         Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST),
-         ejabberd_router:route(To, From, Err),
-         ok
-    end.
+-spec process_iq(jid(), jid(), iq()) -> any().
+process_iq(From, To, #iq{type = T, lang = Lang, sub_els = [El]} = Packet)
+  when T == get; T == set ->
+    XMLNS = xmpp:get_ns(El),
+    Host = To#jid.lserver,
+    case ets:lookup(sm_iqtable, {XMLNS, Host}) of
+       [{_, Module, Function}] ->
+           gen_iq_handler:handle(Host, Module, Function, no_queue,
+                                 From, To, Packet);
+       [{_, Module, Function, Opts}] ->
+           gen_iq_handler:handle(Host, Module, Function, Opts,
+                                 From, To, Packet);
+       [] ->
+           Txt = <<"No module is handling this query">>,
+           Err = xmpp:make_error(
+                   Packet,
+                   xmpp:err_service_unavailable(Txt, Lang)),
+           ejabberd_router:route(To, From, Err)
+    end;
+process_iq(From, To, #iq{type = T} = Packet) when T == get; T == set ->
+    Err = xmpp:make_error(Packet, xmpp:err_bad_request()),
+    ejabberd_router:route(To, From, Err),
+    ok;
+process_iq(_From, _To, #iq{}) ->
+    ok.
 
 -spec force_update_presence({binary(), binary()}) -> any().
 
index 887b4a0f33d13e39b95862eb83b2ec4fc8a3c2cb..aa916867a06b1d72c498f6e0ee9b73343b4f3907 100644 (file)
@@ -41,6 +41,7 @@
         change_shaper/2,
         monitor/1,
         get_sockmod/1,
+        get_transport/1,
         get_peer_certificate/1,
         get_verify_result/1,
         close/1,
@@ -215,6 +216,20 @@ monitor(SocketData)
 get_sockmod(SocketData) ->
     SocketData#socket_state.sockmod.
 
+get_transport(#socket_state{sockmod = SockMod,
+                           socket = Socket}) ->
+    case SockMod of
+       gen_tcp -> tcp;
+       fast_tls -> tls;
+       ezlib ->
+           case ezlib:get_sockmod(Socket) of
+               tcp -> tcp_zlib;
+               tls -> tls_zlib
+           end;
+       ejabberd_http_bind -> http_bind;
+       ejabberd_http_ws -> websocket
+    end.
+
 get_peer_certificate(SocketData) ->
     fast_tls:get_peer_certificate(SocketData#socket_state.socket).
 
index 3f6c0566771e6889d4ede50e8414ee0ee3f2a53c..ae7cb2d88562ab6077dd8ffc4fc5c6d8c46b8e3b 100644 (file)
@@ -41,7 +41,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -record(state, {}).
 
@@ -64,18 +64,16 @@ start_link() ->
 process_command(From, To, Packet) ->
     case To of
       #jid{luser = <<"">>, lresource = <<"watchdog">>} ->
-         #xmlel{name = Name} = Packet,
-         case Name of
-           <<"message">> ->
+         case Packet of
+           #message{body = Body} ->
                LFrom =
                    jid:tolower(jid:remove_resource(From)),
                case lists:member(LFrom, get_admin_jids()) of
                  true ->
-                     Body = fxml:get_path_s(Packet,
-                                           [{elem, <<"body">>}, cdata]),
+                     BodyText = xmpp:get_text(Body),
                      spawn(fun () ->
                                    process_flag(priority, high),
-                                   process_command1(From, To, Body)
+                                   process_command1(From, To, BodyText)
                            end),
                      stop;
                  false -> ok
@@ -186,24 +184,20 @@ process_large_heap(Pid, Info) ->
                            "much memory:~n~p~n~s",
                            [node(), Pid, Info, DetailedInfo])),
     From = jid:make(<<"">>, Host, <<"watchdog">>),
-    Hint = [#xmlel{name = <<"no-permanent-store">>,
-                  attrs = [{<<"xmlns">>, ?NS_HINTS}]}],
-    lists:foreach(fun (JID) ->
-                          send_message(From, jid:make(JID), Body, Hint)
-                  end, JIDs).
+    Hint = [#hint{type = 'no-permanent-store'}],
+    lists:foreach(
+      fun(JID) ->
+             send_message(From, jid:make(JID), Body, Hint)
+      end, JIDs).
 
 send_message(From, To, Body) ->
     send_message(From, To, Body, []).
 
 send_message(From, To, Body, ExtraEls) ->
     ejabberd_router:route(From, To,
-                         #xmlel{name = <<"message">>,
-                                attrs = [{<<"type">>, <<"chat">>}],
-                                children =
-                                    [#xmlel{name = <<"body">>, attrs = [],
-                                            children =
-                                                [{xmlcdata, Body}]}
-                                     | ExtraEls]}).
+                         #message{type = chat,
+                                  body = xmpp:mk_text(Body),
+                                  sub_els = ExtraEls}).
 
 get_admin_jids() ->
     ejabberd_config:get_option(
index c2b4252c94e0b69adfb13c13d90fb28b779be0b1..f78ba7e40a3994daca558398879be16a025f923c 100644 (file)
@@ -40,7 +40,7 @@
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -record(state, {host, module, function}).
 
@@ -59,6 +59,8 @@ start_link(Host, Module, Function) ->
     gen_server:start_link(?MODULE, [Host, Module, Function],
                          []).
 
+-spec add_iq_handler(module(), binary(), binary(), module(), atom(), type()) -> any().
+
 add_iq_handler(Component, Host, NS, Module, Function,
               Type) ->
     case Type of
@@ -124,14 +126,49 @@ handle(Host, Module, Function, Opts, From, To, IQ) ->
 
 -spec process_iq(binary(), atom(), atom(), jid(), jid(), iq()) -> any().
 
-process_iq(_Host, Module, Function, From, To, IQ) ->
-    case catch Module:Function(From, To, IQ) of
-      {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
-      ResIQ ->
-         if ResIQ /= ignore ->
-                ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ));
-            true -> ok
-         end
+process_iq(_Host, Module, Function, From, To, IQ0) ->
+    IQ = xmpp:set_from_to(IQ0, From, To),
+    try
+       ResIQ = case erlang:function_exported(Module, Function, 1) of
+                   true ->
+                       process_iq(Module, Function, IQ);
+                   false ->
+                       process_iq(Module, Function, From, To,
+                                  jlib:iq_query_info(xmpp:encode(IQ)))
+               end,
+       if ResIQ /= ignore ->
+               ejabberd_router:route(To, From, ResIQ);
+          true ->
+               ok
+       end
+    catch E:R ->
+           ?ERROR_MSG("failed to process iq:~n~s~nReason = ~p",
+                      [xmpp_codec:pp(IQ), {E, {R, erlang:get_stacktrace()}}]),
+           Txt = <<"Module failed to handle the query">>,
+           Err = xmpp:err_internal_server_error(Txt, IQ#iq.lang),
+           ejabberd_router:route(To, From, xmpp:make_error(IQ, Err))
+    end.
+
+-spec process_iq(module(), atom(), iq()) -> ignore | iq().
+process_iq(Module, Function, #iq{lang = Lang, sub_els = [El]} = IQ) ->
+    try
+       %% TODO: move this 'conditional' decoding somewhere
+       %% IQ handler should know *nothing* about vCards.
+       Pkt = case xmpp:get_ns(El) of
+                 ?NS_VCARD -> El;
+                 _ -> xmpp:decode(El)
+             end,
+       Module:Function(IQ#iq{sub_els = [Pkt]})
+    catch error:{xmpp_codec, Why} ->
+           Txt = xmpp:format_error(Why),
+           xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang))
+    end.
+
+-spec process_iq(module(), atom(), jid(), jid(), term()) -> iq().
+process_iq(Module, Function, From, To, IQ) ->
+    case Module:Function(From, To, IQ) of
+       ignore -> ignore;
+       ResIQ -> xmpp:decode(jlib:iq_to_xml(ResIQ), [ignore_els])
     end.
 
 -spec check_type(type()) -> type().
index 0c3ac77c0d08d62d929a512bc7e8a1af66efe198..d81cbcefddb11117910ae52e37d4e8c11a1f823c 100644 (file)
@@ -28,6 +28,7 @@
 %% API
 -export([start/0,
         make/1,
+        make/2,
         make/3,
         split/1,
         from_string/1,
@@ -40,7 +41,7 @@
         remove_resource/1,
         replace_resource/2]).
 
--include("jlib.hrl").
+-include("jid.hrl").
 
 -export_type([jid/0]).
 
@@ -74,10 +75,16 @@ make(User, Server, Resource) ->
          end
     end.
 
--spec make({binary(), binary(), binary()}) -> jid() | error.
+-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(User, Server, Resource);
+make(Server) ->
+    make(<<"">>, Server, <<"">>).
 
 %% This is the reverse of make_jid/1
 -spec split(jid()) -> {binary(), binary(), binary()} | error.
@@ -93,6 +100,8 @@ from_string(S) when is_list(S) ->
     %% 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),
index 3ed3149bb62222e25b8837105a8b6f6783f0ed03..7c7ebf7b36137ea58c1a419a509e138f8dba9d7d 100644 (file)
@@ -35,6 +35,8 @@
 
 -behaviour(gen_mod).
 
+-compile(export_all).
+
 -export([read_caps/1, caps_stream_features/2,
         disco_features/5, disco_identity/5, disco_info/5,
         get_features/2, export/1, import_info/0, import/5,
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -define(PROCNAME, ejabberd_mod_caps).
 
 -define(BAD_HASH_LIFETIME, 600).
 
--record(caps,
-{
-    node    = <<"">> :: binary(),
-    version = <<"">> :: binary(),
-    hash    = <<"">> :: binary(),
-    exts    = []     :: [binary()]
-}).
-
--type caps() :: #caps{}.
-
--export_type([caps/0]).
-
 -record(caps_features,
 {
     node_pair = {<<"">>, <<"">>} :: {binary(), binary()},
@@ -103,6 +93,7 @@ stop(Host) ->
     supervisor:terminate_child(ejabberd_sup, Proc),
     supervisor:delete_child(ejabberd_sup, Proc).
 
+-spec get_features(binary(), nothing | caps()) -> [binary()].
 get_features(_Host, nothing) -> [];
 get_features(Host, #caps{node = Node, version = Version,
                   exts = Exts}) ->
@@ -119,65 +110,37 @@ get_features(Host, #caps{node = Node, version = Version,
                end,
                [], SubNodes).
 
--spec read_caps([xmlel()]) -> nothing | caps().
-
-read_caps(Els) -> read_caps(Els, nothing).
-
-read_caps([#xmlel{name = <<"c">>, attrs = Attrs}
-          | Tail],
-         Result) ->
-    case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-      ?NS_CAPS ->
-         Node = fxml:get_attr_s(<<"node">>, Attrs),
-         Version = fxml:get_attr_s(<<"ver">>, Attrs),
-         Hash = fxml:get_attr_s(<<"hash">>, Attrs),
-         Exts = str:tokens(fxml:get_attr_s(<<"ext">>, Attrs),
-                           <<" ">>),
-         read_caps(Tail,
-                   #caps{node = Node, hash = Hash, version = Version,
-                         exts = Exts});
-      _ -> read_caps(Tail, Result)
-    end;
-read_caps([#xmlel{name = <<"x">>, attrs = Attrs}
-          | Tail],
-         Result) ->
-    case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-      ?NS_MUC_USER -> nothing;
-      _ -> read_caps(Tail, Result)
-    end;
-read_caps([_ | Tail], Result) ->
-    read_caps(Tail, Result);
-read_caps([], Result) -> Result.
+-spec read_caps(#presence{}) -> nothing | caps().
+read_caps(Presence) ->
+    case xmpp:get_subtag(Presence, #caps{}) of
+       false -> nothing;
+       Caps -> Caps
+    end.
 
-user_send_packet(#xmlel{name = <<"presence">>, attrs = Attrs,
-                       children = Els} = Pkt,
+-spec user_send_packet(stanza(), ejabberd_c2s:state(), jid(), jid()) -> stanza().
+user_send_packet(#presence{type = available} = Pkt,
                 _C2SState,
                 #jid{luser = User, lserver = Server} = From,
                 #jid{luser = User, lserver = Server,
                      lresource = <<"">>}) ->
-    Type = fxml:get_attr_s(<<"type">>, Attrs),
-    if Type == <<"">>; Type == <<"available">> ->
-          case read_caps(Els) of
-            nothing -> ok;
-            #caps{version = Version, exts = Exts} = Caps ->
-                feature_request(Server, From, Caps, [Version | Exts])
-          end;
-       true -> ok
+    case read_caps(Pkt) of
+       nothing -> ok;
+       #caps{version = Version, exts = Exts} = Caps ->
+           feature_request(Server, From, Caps, [Version | Exts])
     end,
     Pkt;
 user_send_packet(Pkt, _C2SState, _From, _To) ->
     Pkt.
 
-user_receive_packet(#xmlel{name = <<"presence">>, attrs = Attrs,
-                          children = Els} = Pkt,
+-spec user_receive_packet(stanza(), ejabberd_c2s:state(),
+                         jid(), jid(), jid()) -> stanza().
+user_receive_packet(#presence{type = available} = Pkt,
                    _C2SState,
                    #jid{lserver = Server},
                    From, _To) ->
-    Type = fxml:get_attr_s(<<"type">>, Attrs),
     IsRemote = not lists:member(From#jid.lserver, ?MYHOSTS),
-    if IsRemote and
-        ((Type == <<"">>) or (Type == <<"available">>)) ->
-          case read_caps(Els) of
+    if IsRemote ->
+          case read_caps(Pkt) of
             nothing -> ok;
             #caps{version = Version, exts = Exts} = Caps ->
                 feature_request(Server, From, Caps, [Version | Exts])
@@ -188,58 +151,62 @@ user_receive_packet(#xmlel{name = <<"presence">>, attrs = Attrs,
 user_receive_packet(Pkt, _C2SState, _JID, _From, _To) ->
     Pkt.
 
--spec caps_stream_features([xmlel()], binary()) -> [xmlel()].
+-spec caps_stream_features([xmpp_element()], binary()) -> [xmpp_element()].
 
 caps_stream_features(Acc, MyHost) ->
     case make_my_disco_hash(MyHost) of
       <<"">> -> Acc;
       Hash ->
-         [#xmlel{name = <<"c">>,
-                 attrs =
-                     [{<<"xmlns">>, ?NS_CAPS}, {<<"hash">>, <<"sha-1">>},
-                      {<<"node">>, ?EJABBERD_URI}, {<<"ver">>, Hash}],
-                 children = []}
-          | Acc]
+         [#caps{hash = <<"sha-1">>, node = ?EJABBERD_URI, version = Hash}|Acc]
     end.
 
+-spec disco_features({error, error()} | {result, [binary()]} | empty,
+                    jid(), jid(),
+                    undefined | binary(), undefined | binary()) ->
+                           {error, error()} | {result, [binary()]}.
 disco_features(Acc, From, To, Node, Lang) ->
     case is_valid_node(Node) of
         true ->
             ejabberd_hooks:run_fold(disco_local_features,
                                     To#jid.lserver, empty,
-                                    [From, To, <<"">>, Lang]);
+                                    [From, To, undefined, Lang]);
         false ->
             Acc
     end.
 
+-spec disco_identity([identity()], jid(), jid(),
+                    undefined | binary(), undefined | binary()) ->
+                           [identity()].
 disco_identity(Acc, From, To, Node, Lang) ->
     case is_valid_node(Node) of
         true ->
             ejabberd_hooks:run_fold(disco_local_identity,
                                     To#jid.lserver, [],
-                                    [From, To, <<"">>, Lang]);
+                                    [From, To, undefined, Lang]);
         false ->
             Acc
     end.
 
+-spec disco_info([xdata()], binary(), module(),
+                undefined | binary(), undefined | binary()) -> [xdata()].
 disco_info(Acc, Host, Module, Node, Lang) ->
     case is_valid_node(Node) of
         true ->
             ejabberd_hooks:run_fold(disco_info, Host, [],
-                                    [Host, Module, <<"">>, Lang]);
+                                    [Host, Module, undefined, Lang]);
         false ->
             Acc
     end.
 
+-spec c2s_presence_in(ejabberd_c2s:state(), {jid(), jid(), presence()}) ->
+                            ejabberd_c2s:state().
 c2s_presence_in(C2SState,
-               {From, To, {_, _, Attrs, Els}}) ->
-    Type = fxml:get_attr_s(<<"type">>, Attrs),
+               {From, To, #presence{type = Type} = Presence}) ->
     Subscription = ejabberd_c2s:get_subscription(From,
                                                 C2SState),
-    Insert = ((Type == <<"">>) or (Type == <<"available">>))
+    Insert = (Type == available)
               and ((Subscription == both) or (Subscription == to)),
-    Delete = (Type == <<"unavailable">>) or
-              (Type == <<"error">>),
+    Delete = (Type == unavailable) or (Type == error),
     if Insert or Delete ->
           LFrom = jid:tolower(From),
           Rs = case ejabberd_c2s:get_aux_field(caps_resources,
@@ -248,7 +215,7 @@ c2s_presence_in(C2SState,
                  {ok, Rs1} -> Rs1;
                  error -> gb_trees:empty()
                end,
-          Caps = read_caps(Els),
+          Caps = read_caps(Presence),
           NewRs = case Caps of
                     nothing when Insert == true -> Rs;
                     _ when Insert == true ->
@@ -272,6 +239,9 @@ c2s_presence_in(C2SState,
        true -> C2SState
     end.
 
+-spec c2s_filter_packet(boolean(), binary(), ejabberd_c2s:state(),
+                       {pep_message, binary()}, jid(), stanza()) ->
+                              boolean().
 c2s_filter_packet(InAcc, Host, C2SState, {pep_message, Feature}, To, _Packet) ->
     case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of
       {ok, Rs} ->
@@ -287,6 +257,9 @@ c2s_filter_packet(InAcc, Host, C2SState, {pep_message, Feature}, To, _Packet) ->
     end;
 c2s_filter_packet(Acc, _, _, _, _, _) -> Acc.
 
+-spec c2s_broadcast_recipients([ljid()], binary(), ejabberd_c2s:state(),
+                              {pep_message, binary()}, jid(), stanza()) ->
+                                     [ljid()].
 c2s_broadcast_recipients(InAcc, Host, C2SState,
                         {pep_message, Feature}, _From, _Packet) ->
     case ejabberd_c2s:get_aux_field(caps_resources,
@@ -377,6 +350,7 @@ terminate(_Reason, State) ->
 
 code_change(_OldVsn, State, _Extra) -> {ok, State}.
 
+-spec feature_request(binary(), jid(), caps(), [binary()]) -> any().
 feature_request(Host, From, Caps,
                [SubNode | Tail] = SubNodes) ->
     Node = Caps#caps.node,
@@ -392,15 +366,9 @@ feature_request(Host, From, Caps,
                          _ -> true
                        end,
          if NeedRequest ->
-                IQ = #iq{type = get, xmlns = ?NS_DISCO_INFO,
-                         sub_el =
-                             [#xmlel{name = <<"query">>,
-                                     attrs =
-                                         [{<<"xmlns">>, ?NS_DISCO_INFO},
-                                          {<<"node">>,
-                                           <<Node/binary, "#",
-                                             SubNode/binary>>}],
-                                     children = []}]},
+                IQ = #iq{type = get,
+                         sub_els = [#disco_info{node = <<Node/binary, "#",
+                                                         SubNode/binary>>}]},
                 cache_tab:insert(caps_features, NodePair, now_ts(),
                                  caps_write_fun(Host, NodePair, now_ts())),
                 F = fun (IQReply) ->
@@ -415,39 +383,41 @@ feature_request(Host, From, Caps,
     end;
 feature_request(_Host, _From, _Caps, []) -> ok.
 
-feature_response(#iq{type = result,
-                    sub_el = [#xmlel{children = Els}]},
+-spec feature_response(iq(), binary(), jid(), caps(), [binary()]) -> any().
+feature_response(#iq{type = result, sub_els = [El]},
                 Host, From, Caps, [SubNode | SubNodes]) ->
     NodePair = {Caps#caps.node, SubNode},
-    case check_hash(Caps, Els) of
-      true ->
-         Features = lists:flatmap(fun (#xmlel{name =
-                                                  <<"feature">>,
-                                              attrs = FAttrs}) ->
-                                          [fxml:get_attr_s(<<"var">>, FAttrs)];
-                                      (_) -> []
-                                  end,
-                                  Els),
-         cache_tab:insert(caps_features, NodePair,
-                          Features,
-                          caps_write_fun(Host, NodePair, Features));
-      false -> ok
+    try
+       DiscoInfo = xmpp:decode(El),
+       case check_hash(Caps, DiscoInfo) of
+           true ->
+               Features = DiscoInfo#disco_info.features,
+               cache_tab:insert(caps_features, NodePair,
+                                Features,
+                                caps_write_fun(Host, NodePair, Features));
+           false -> ok
+       end
+    catch _:{xmpp_codec, _Why} ->
+           ok
     end,
     feature_request(Host, From, Caps, SubNodes);
 feature_response(_IQResult, Host, From, Caps,
                 [_SubNode | SubNodes]) ->
     feature_request(Host, From, Caps, SubNodes).
 
+-spec caps_read_fun(binary(), binary()) -> function().
 caps_read_fun(Host, Node) ->
     LServer = jid:nameprep(Host),
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     fun() -> Mod:caps_read(LServer, Node) end.
 
+-spec caps_write_fun(binary(), binary(), [binary()]) -> function().
 caps_write_fun(Host, Node, Features) ->
     LServer = jid:nameprep(Host),
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     fun() -> Mod:caps_write(LServer, Node, Features) end.
 
+-spec make_my_disco_hash(binary()) -> binary().
 make_my_disco_hash(Host) ->
     JID = jid:make(<<"">>, Host, <<"">>),
     case {ejabberd_hooks:run_fold(disco_local_features,
@@ -458,119 +428,70 @@ make_my_disco_hash(Host) ->
                                  [Host, undefined, <<"">>, <<"">>])}
        of
       {{result, Features}, Identities, Info} ->
-         Feats = lists:map(fun ({{Feat, _Host}}) ->
-                                   #xmlel{name = <<"feature">>,
-                                          attrs = [{<<"var">>, Feat}],
-                                          children = []};
-                               (Feat) ->
-                                   #xmlel{name = <<"feature">>,
-                                          attrs = [{<<"var">>, Feat}],
-                                          children = []}
+         Feats = lists:map(fun ({{Feat, _Host}}) -> Feat;
+                               (Feat) -> Feat
                            end,
                            Features),
-         make_disco_hash(Identities ++ Info ++ Feats, sha1);
+         DiscoInfo = #disco_info{identities = Identities,
+                                 features = Feats,
+                                 xdata = Info},
+         make_disco_hash(DiscoInfo, sha);
       _Err -> <<"">>
     end.
 
-make_disco_hash(DiscoEls, Algo) ->
-    Concat = list_to_binary([concat_identities(DiscoEls),
-                             concat_features(DiscoEls), concat_info(DiscoEls)]),
+-spec make_disco_hash(disco_info(), crypto:digest_type()) -> binary().
+
+make_disco_hash(DiscoInfo, Algo) ->
+    Concat = list_to_binary([concat_identities(DiscoInfo),
+                             concat_features(DiscoInfo), concat_info(DiscoInfo)]),
     jlib:encode_base64(case Algo of
                            md5 -> erlang:md5(Concat);
-                           sha1 -> p1_sha:sha1(Concat);
+                           sha -> p1_sha:sha1(Concat);
                            sha224 -> p1_sha:sha224(Concat);
                            sha256 -> p1_sha:sha256(Concat);
                            sha384 -> p1_sha:sha384(Concat);
                            sha512 -> p1_sha:sha512(Concat)
                        end).
 
-check_hash(Caps, Els) ->
+-spec check_hash(caps(), disco_info()) -> boolean().
+check_hash(Caps, DiscoInfo) ->
     case Caps#caps.hash of
       <<"md5">> ->
-         Caps#caps.version == make_disco_hash(Els, md5);
+         Caps#caps.version == make_disco_hash(DiscoInfo, md5);
       <<"sha-1">> ->
-         Caps#caps.version == make_disco_hash(Els, sha1);
+         Caps#caps.version == make_disco_hash(DiscoInfo, sha);
       <<"sha-224">> ->
-         Caps#caps.version == make_disco_hash(Els, sha224);
+         Caps#caps.version == make_disco_hash(DiscoInfo, sha224);
       <<"sha-256">> ->
-         Caps#caps.version == make_disco_hash(Els, sha256);
+         Caps#caps.version == make_disco_hash(DiscoInfo, sha256);
       <<"sha-384">> ->
-         Caps#caps.version == make_disco_hash(Els, sha384);
+         Caps#caps.version == make_disco_hash(DiscoInfo, sha384);
       <<"sha-512">> ->
-         Caps#caps.version == make_disco_hash(Els, sha512);
+         Caps#caps.version == make_disco_hash(DiscoInfo, sha512);
       _ -> true
     end.
 
-concat_features(Els) ->
-    lists:usort(lists:flatmap(fun (#xmlel{name =
-                                             <<"feature">>,
-                                         attrs = Attrs}) ->
-                                     [[fxml:get_attr_s(<<"var">>, Attrs), $<]];
-                                 (_) -> []
-                             end,
-                             Els)).
-
-concat_identities(Els) ->
-    lists:sort(lists:flatmap(fun (#xmlel{name =
-                                            <<"identity">>,
-                                        attrs = Attrs}) ->
-                                    [[fxml:get_attr_s(<<"category">>, Attrs),
-                                      $/, fxml:get_attr_s(<<"type">>, Attrs),
-                                      $/,
-                                      fxml:get_attr_s(<<"xml:lang">>, Attrs),
-                                      $/, fxml:get_attr_s(<<"name">>, Attrs),
-                                      $<]];
-                                (_) -> []
-                            end,
-                            Els)).
-
-concat_info(Els) ->
-    lists:sort(lists:flatmap(fun (#xmlel{name = <<"x">>,
-                                        attrs = Attrs, children = Fields}) ->
-                                    case {fxml:get_attr_s(<<"xmlns">>, Attrs),
-                                          fxml:get_attr_s(<<"type">>, Attrs)}
-                                        of
-                                      {?NS_XDATA, <<"result">>} ->
-                                          [concat_xdata_fields(Fields)];
-                                      _ -> []
-                                    end;
-                                (_) -> []
-                            end,
-                            Els)).
+concat_features(#disco_info{features = Features}) ->
+    lists:usort([[Feat, $<] || Feat <- Features]).
+
+concat_identities(#disco_info{identities = Identities}) ->
+    lists:sort(
+      [[Cat, $/, T, $/, Lang, $/, Name, $<] ||
+         #identity{category = Cat, type = T,
+                   lang = Lang, name = Name} <- Identities]).
+
+concat_info(#disco_info{xdata = Xs}) ->
+    lists:sort(
+      [concat_xdata_fields(Fs) || #xdata{type = result, fields = Fs} <- Xs]).
 
 concat_xdata_fields(Fields) ->
-    [Form, Res] = lists:foldl(fun (#xmlel{name =
-                                             <<"field">>,
-                                         attrs = Attrs, children = Els} =
-                                      El,
-                                  [FormType, VarFields] = Acc) ->
-                                     case fxml:get_attr_s(<<"var">>, Attrs) of
-                                       <<"">> -> Acc;
-                                       <<"FORM_TYPE">> ->
-                                           [fxml:get_subtag_cdata(El,
-                                                                 <<"value">>),
-                                            VarFields];
-                                       Var ->
-                                           [FormType,
-                                            [[[Var, $<],
-                                              lists:sort(lists:flatmap(fun
-                                                                         (#xmlel{name
-                                                                                     =
-                                                                                     <<"value">>,
-                                                                                 children
-                                                                                     =
-                                                                                     VEls}) ->
-                                                                             [[fxml:get_cdata(VEls),
-                                                                               $<]];
-                                                                         (_) ->
-                                                                             []
-                                                                       end,
-                                                                       Els))]
-                                             | VarFields]]
-                                     end;
-                                 (_, Acc) -> Acc
-                             end,
-                             [<<"">>, []], Fields),
+    Form = case lists:keysearch(<<"FORM_TYPE">>, #xdata_field.var, Fields) of
+              #xdata_field{values = Values} -> Values;
+              false -> []
+          end,
+    Res = [[Var, $<, lists:sort([[Val, $<] || Val <- Values])]
+          || #xdata_field{var = Var, values = Values} <- Fields,
+             is_binary(Var), Var /= <<"FORM_TYPE">>],
     [Form, $<, lists:sort(Res)].
 
 gb_trees_fold(F, Acc, Tree) ->
@@ -588,6 +509,9 @@ gb_trees_fold_iter(F, Acc, Iter) ->
 now_ts() ->
     p1_time_compat:system_time(seconds).
 
+-spec is_valid_node(undefined | binary()) -> boolean().
+is_valid_node(undefined) ->
+    false;
 is_valid_node(Node) ->
     case str:tokens(Node, <<"#">>) of
         [?EJABBERD_URI|_] ->
index de8d8e1a71f588fb0022da9336ac01b473a991e8..b70ccbc2acdf15036c5734f4a77234019328d5d3 100644 (file)
          stop/1]).
 
 -export([user_send_packet/4, user_receive_packet/5,
-        iq_handler2/3, iq_handler1/3, remove_connection/4,
+        iq_handler/1, remove_connection/4,
         is_carbon_copy/1, mod_opt_type/1, depends/2]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 -define(PROCNAME, ?MODULE).
 
+-type direction() :: sent | received.
+
 -callback init(binary(), gen_mod:opts()) -> any().
 -callback enable(binary(), binary(), binary(), binary()) -> ok | {error, any()}.
 -callback disable(binary(), binary(), binary()) -> ok | {error, any()}.
 -callback list(binary(), binary()) -> [{binary(), binary()}].
 
+-spec is_carbon_copy(stanza()) -> boolean().
 is_carbon_copy(Packet) ->
-    is_carbon_copy(Packet, <<"sent">>) orelse
-       is_carbon_copy(Packet, <<"received">>).
-
-is_carbon_copy(Packet, Direction) ->
-    case fxml:get_subtag(Packet, Direction) of
-       #xmlel{name = Direction, attrs = Attrs} ->
-           case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-               ?NS_CARBONS_2 -> true;
-               ?NS_CARBONS_1 -> true;
-               _ -> false
-           end;
-       _ -> false
-    end.
+    xmpp:has_subtag(Packet, #carbons_sent{}) orelse
+       xmpp:has_subtag(Packet, #carbons_received{}).
 
 start(Host, Opts) ->
     IQDisc = gen_mod:get_opt(iqdisc, Opts,fun gen_iq_handler:check_type/1, one_queue),
-    mod_disco:register_feature(Host, ?NS_CARBONS_1),
     mod_disco:register_feature(Host, ?NS_CARBONS_2),
     Mod = gen_mod:db_mod(Host, ?MODULE),
     Mod:init(Host, Opts),
@@ -74,54 +65,53 @@ start(Host, Opts) ->
     %% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
     ejabberd_hooks:add(user_send_packet,Host, ?MODULE, user_send_packet, 89),
     ejabberd_hooks:add(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
-    gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2, ?MODULE, iq_handler2, IQDisc),
-    gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_1, ?MODULE, iq_handler1, IQDisc).
+    gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2, ?MODULE, iq_handler, IQDisc).
 
 stop(Host) ->
-    gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_1),
     gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2),
     mod_disco:unregister_feature(Host, ?NS_CARBONS_2),
-    mod_disco:unregister_feature(Host, ?NS_CARBONS_1),
     %% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
     ejabberd_hooks:delete(user_send_packet,Host, ?MODULE, user_send_packet, 89),
     ejabberd_hooks:delete(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
     ejabberd_hooks:delete(unset_presence_hook,Host, ?MODULE, remove_connection, 10).
 
-iq_handler2(From, To, IQ) ->
-       iq_handler(From, To, IQ, ?NS_CARBONS_2).
-iq_handler1(From, To, IQ) ->
-       iq_handler(From, To, IQ, ?NS_CARBONS_1).
-
-iq_handler(From, _To,
-          #iq{type=set, lang = Lang,
-              sub_el = #xmlel{name = Operation} = SubEl} = IQ, CC)->
-    ?DEBUG("carbons IQ received: ~p", [IQ]),
+-spec iq_handler(iq()) -> iq().
+iq_handler(#iq{type = set, lang = Lang, from = From,
+              sub_els = [El]} = IQ) when is_record(El, carbons_enable);
+                                         is_record(El, carbons_disable) ->
     {U, S, R} = jid:tolower(From),
-    Result = case Operation of
-        <<"enable">>->
-           ?INFO_MSG("carbons enabled for user ~s@~s/~s", [U,S,R]),
-            enable(S,U,R,CC);
-        <<"disable">>->
-           ?INFO_MSG("carbons disabled for user ~s@~s/~s", [U,S,R]),
-            disable(S, U, R)
-    end,
+    Result = case El of
+                #carbons_enable{} ->
+                    ?INFO_MSG("carbons enabled for user ~s@~s/~s", [U,S,R]),
+                    enable(S, U, R, ?NS_CARBONS_2);
+                #carbons_disable{} ->
+                    ?INFO_MSG("carbons disabled for user ~s@~s/~s", [U,S,R]),
+                    disable(S, U, R)
+            end,
     case Result of
-        ok ->
+       ok ->
            ?DEBUG("carbons IQ result: ok", []),
-            IQ#iq{type=result, sub_el=[]};
+           xmpp:make_iq_result(IQ);
        {error,_Error} ->
            ?ERROR_MSG("Error enabling / disabling carbons: ~p", [Result]),
            Txt = <<"Database failure">>,
-            IQ#iq{type=error,sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]}
+           xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang))
     end;
-
-iq_handler(_From, _To, #iq{lang = Lang, sub_el = SubEl} = IQ, _CC)->
+iq_handler(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Only <enable/> or <disable/> tags are allowed">>,
+    xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
+iq_handler(#iq{type = get, lang = Lang} = IQ)->
     Txt = <<"Value 'get' of 'type' attribute is not allowed">>,
-    IQ#iq{type=error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}.
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)).
 
+-spec user_send_packet(stanza(), ejabberd_c2s:state(), jid(), jid()) ->
+                             stanza() | {stop, stanza()}.
 user_send_packet(Packet, _C2SState, From, To) ->
     check_and_forward(From, To, Packet, sent).
 
+-spec user_receive_packet(stanza(), ejabberd_c2s:state(),
+                         jid(), jid(), jid()) ->
+                                stanza() | {stop, stanza()}.
 user_receive_packet(Packet, _C2SState, JID, _From, To) ->
     check_and_forward(JID, To, Packet, received).
 
@@ -129,10 +119,12 @@ user_receive_packet(Packet, _C2SState, JID, _From, To) ->
 %    - registered to the user_send_packet hook, to be called only once even for multicast
 %    - do not support "private" message mode, and do not modify the original packet in any way
 %    - we also replicate "read" notifications
+-spec check_and_forward(jid(), jid(), stanza(), direction()) ->
+                              stanza() | {stop, stanza()}.
 check_and_forward(JID, To, Packet, Direction)->
     case is_chat_message(Packet) andalso
-            fxml:get_subtag(Packet, <<"private">>) == false andalso
-                fxml:get_subtag(Packet, <<"no-copy">>) == false of
+       xmpp:has_subtag(Packet, #carbons_private{}) == false andalso
+       xmpp:has_subtag(Packet, #hint{type = 'no-copy'}) == false of
        true ->
            case is_carbon_copy(Packet) of
                false ->
@@ -147,6 +139,7 @@ check_and_forward(JID, To, Packet, Direction)->
            Packet
     end.
 
+-spec remove_connection(binary(), binary(), binary(), binary()) -> ok.
 remove_connection(User, Server, Resource, _Status)->
     disable(Server, User, Resource),
     ok.
@@ -154,6 +147,7 @@ remove_connection(User, Server, Resource, _Status)->
 
 %%% Internal
 %% Direction = received | sent <received xmlns='urn:xmpp:carbons:1'/>
+-spec send_copies(jid(), jid(), message(), direction()) -> ok.
 send_copies(JID, To, Packet, Direction)->
     {U, S, R} = jid:tolower(JID),
     PrioRes = ejabberd_sm:get_user_present_resources(U, S),
@@ -191,88 +185,54 @@ send_copies(JID, To, Packet, Direction)->
            %TargetJIDs = lists:delete(JID, [ jid:make({U, S, CCRes}) || CCRes <- list(U, S) ]),
     end,
 
-    lists:map(fun({Dest,Version}) ->
+    lists:map(fun({Dest, _Version}) ->
                    {_, _, Resource} = jid:tolower(Dest),
                    ?DEBUG("Sending:  ~p =/= ~p", [R, Resource]),
                    Sender = jid:make({U, S, <<>>}),
                    %{xmlelement, N, A, C} = Packet,
-                   New = build_forward_packet(JID, Packet, Sender, Dest, Direction, Version),
+                   New = build_forward_packet(JID, Packet, Sender, Dest, Direction),
                    ejabberd_router:route(Sender, Dest, New)
              end, TargetJIDs),
     ok.
 
-build_forward_packet(JID, Packet, Sender, Dest, Direction, ?NS_CARBONS_2) ->
-    #xmlel{name = <<"message">>,
-          attrs = [{<<"xmlns">>, <<"jabber:client">>},
-                   {<<"type">>, message_type(Packet)},
-                   {<<"from">>, jid:to_string(Sender)},
-                   {<<"to">>, jid:to_string(Dest)}],
-          children = [
-               #xmlel{name = list_to_binary(atom_to_list(Direction)),
-                      attrs = [{<<"xmlns">>, ?NS_CARBONS_2}],
-                      children = [
-                       #xmlel{name = <<"forwarded">>,
-                              attrs = [{<<"xmlns">>, ?NS_FORWARD}],
-                              children = [
-                               complete_packet(JID, Packet, Direction)]}
-               ]}
-          ]};
-build_forward_packet(JID, Packet, Sender, Dest, Direction, ?NS_CARBONS_1) ->
-    #xmlel{name = <<"message">>,
-          attrs = [{<<"xmlns">>, <<"jabber:client">>},
-                   {<<"type">>, message_type(Packet)},
-                   {<<"from">>, jid:to_string(Sender)},
-                   {<<"to">>, jid:to_string(Dest)}],
-          children = [
-               #xmlel{name = list_to_binary(atom_to_list(Direction)),
-                       attrs = [{<<"xmlns">>, ?NS_CARBONS_1}]},
-               #xmlel{name = <<"forwarded">>,
-                      attrs = [{<<"xmlns">>, ?NS_FORWARD}],
-                      children = [complete_packet(JID, Packet, Direction)]}
-               ]}.
-
+-spec build_forward_packet(jid(), message(), jid(), jid(), direction()) -> message().
+build_forward_packet(JID, #message{type = T} = Msg, Sender, Dest, Direction) ->
+    Forwarded = #forwarded{sub_els = complete_packet(JID, Msg, Direction)},
+    Carbon = case Direction of
+                sent -> #carbons_sent{forwarded = Forwarded};
+                received -> #carbons_received{forwarded = Forwarded}
+            end,
+    #message{from = Sender, to = Dest, type = T, sub_els = [Carbon]}.
 
+-spec enable(binary(), binary(), binary(), binary()) -> ok | {error, any()}.
 enable(Host, U, R, CC)->
     ?DEBUG("enabling for ~p", [U]),
     Mod = gen_mod:db_mod(Host, ?MODULE),
     Mod:enable(U, Host, R, CC).
 
+-spec disable(binary(), binary(), binary()) -> ok | {error, any()}.
 disable(Host, U, R)->
     ?DEBUG("disabling for ~p", [U]),
     Mod = gen_mod:db_mod(Host, ?MODULE),
     Mod:disable(U, Host, R).
 
-complete_packet(From, #xmlel{name = <<"message">>, attrs = OrigAttrs} = Packet, sent) ->
+-spec complete_packet(jid(), message(), direction()) -> message().
+complete_packet(From, #message{from = undefined} = Msg, sent) ->
     %% if this is a packet sent by user on this host, then Packet doesn't
     %% include the 'from' attribute. We must add it.
-    Attrs = lists:keystore(<<"xmlns">>, 1, OrigAttrs, {<<"xmlns">>, <<"jabber:client">>}),
-    case proplists:get_value(<<"from">>, Attrs) of
-       undefined ->
-               Packet#xmlel{attrs = [{<<"from">>, jid:to_string(From)}|Attrs]};
-       _ ->
-               Packet#xmlel{attrs = Attrs}
-    end;
-complete_packet(_From, #xmlel{name = <<"message">>, attrs=OrigAttrs} = Packet, received) ->
-    Attrs = lists:keystore(<<"xmlns">>, 1, OrigAttrs, {<<"xmlns">>, <<"jabber:client">>}),
-    Packet#xmlel{attrs = Attrs}.
-
-message_type(#xmlel{attrs = Attrs}) ->
-    case fxml:get_attr(<<"type">>, Attrs) of
-       {value, Type} -> Type;
-       false -> <<"normal">>
-    end.
-
-is_chat_message(#xmlel{name = <<"message">>} = Packet) ->
-    case message_type(Packet) of
-       <<"chat">> -> true;
-       <<"normal">> -> has_non_empty_body(Packet);
-       _ -> false
-    end;
-is_chat_message(_Packet) -> false.
-
-has_non_empty_body(Packet) ->
-    fxml:get_subtag_cdata(Packet, <<"body">>) =/= <<"">>.
-
+    Msg#message{from = From};
+complete_packet(_From, Msg, _Direction) ->
+    Msg.
+
+-spec is_chat_message(stanza()) -> boolean().
+is_chat_message(#message{type = chat}) ->
+    true;
+is_chat_message(#message{type = normal, body = Body}) ->
+    xmpp:get_text(Body) /= <<"">>;
+is_chat_message(_) ->
+    false.
+
+-spec list(binary(), binary()) -> [{binary(), binary()}].
 %% list {resource, cc_version} with carbons enabled for given user and host
 list(User, Server) ->
     Mod = gen_mod:db_mod(Server, ?MODULE),
index 036175cced9997492ea0b389153f1c997500d2af..a6a6ddc20f67e0f595f2590a1376c25e22fcbcf3 100644 (file)
@@ -39,7 +39,7 @@
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -define(CSI_QUEUE_MAX, 100).
 
@@ -151,66 +151,62 @@ depends(_Host, _Opts) ->
 %% ejabberd_hooks callbacks.
 %%--------------------------------------------------------------------
 
--spec filter_presence({term(), [xmlel()]}, binary(), xmlel())
-      -> {term(), [xmlel()]} | {stop, {term(), [xmlel()]}}.
+-spec filter_presence({term(), [stanza()]}, binary(), stanza())
+      -> {term(), [stanza()]} | {stop, {term(), [stanza()]}}.
 
 filter_presence({C2SState, _OutStanzas} = Acc, Host,
-               #xmlel{name = <<"presence">>, attrs = Attrs} = Stanza) ->
-    case fxml:get_attr(<<"type">>, Attrs) of
-      {value, Type} when Type /= <<"unavailable">> ->
-         Acc;
-      _ ->
-         ?DEBUG("Got availability presence stanza", []),
-         queue_add(presence, Stanza, Host, C2SState)
+               #presence{type = Type} = Stanza) ->
+    if Type == available, Type == unavailable ->
+           ?DEBUG("Got availability presence stanza", []),
+           queue_add(presence, Stanza, Host, C2SState);
+       true ->
+           Acc
     end;
 filter_presence(Acc, _Host, _Stanza) -> Acc.
 
--spec filter_chat_states({term(), [xmlel()]}, binary(), xmlel())
-      -> {term(), [xmlel()]} | {stop, {term(), [xmlel()]}}.
+-spec filter_chat_states({term(), [stanza()]}, binary(), stanza())
+      -> {term(), [stanza()]} | {stop, {term(), [stanza()]}}.
 
 filter_chat_states({C2SState, _OutStanzas} = Acc, Host,
-                  #xmlel{name = <<"message">>} = Stanza) ->
-    case jlib:is_standalone_chat_state(Stanza) of
-      true ->
-         From = fxml:get_tag_attr_s(<<"from">>, Stanza),
-         To = fxml:get_tag_attr_s(<<"to">>, Stanza),
-         case {jid:from_string(From), jid:from_string(To)} of
-           {#jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}} ->
-               %% Don't queue (carbon copies of) chat states from other
-               %% resources, as they might be used to sync the state of
-               %% conversations across clients.
-               Acc;
-           _ ->
-               ?DEBUG("Got standalone chat state notification", []),
-               queue_add(chatstate, Stanza, Host, C2SState)
-         end;
-      false ->
-         Acc
+                  #message{from = From, to = To} = Stanza) ->
+    case xmpp_util:is_standalone_chat_state(Stanza) of
+       true ->
+           case {From, To} of
+               {#jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}} ->
+                   %% Don't queue (carbon copies of) chat states from other
+                   %% resources, as they might be used to sync the state of
+                   %% conversations across clients.
+                   Acc;
+               _ ->
+                   ?DEBUG("Got standalone chat state notification", []),
+                   queue_add(chatstate, Stanza, Host, C2SState)
+           end;
+       false ->
+           Acc
     end;
 filter_chat_states(Acc, _Host, _Stanza) -> Acc.
 
--spec filter_pep({term(), [xmlel()]}, binary(), xmlel())
-      -> {term(), [xmlel()]} | {stop, {term(), [xmlel()]}}.
+-spec filter_pep({term(), [stanza()]}, binary(), stanza())
+      -> {term(), [stanza()]} | {stop, {term(), [stanza()]}}.
 
-filter_pep({C2SState, _OutStanzas} = Acc, Host,
-          #xmlel{name = <<"message">>} = Stanza) ->
+filter_pep({C2SState, _OutStanzas} = Acc, Host, #message{} = Stanza) ->
     case get_pep_node(Stanza) of
-      {value, Node} ->
-         ?DEBUG("Got PEP notification", []),
-         queue_add({pep, Node}, Stanza, Host, C2SState);
-      false ->
-         Acc
+       undefined ->
+           Acc;
+       Node ->
+           ?DEBUG("Got PEP notification", []),
+           queue_add({pep, Node}, Stanza, Host, C2SState)
     end;
 filter_pep(Acc, _Host, _Stanza) -> Acc.
 
--spec filter_other({term(), [xmlel()]}, binary(), xmlel())
-      -> {stop, {term(), [xmlel()]}}.
+-spec filter_other({term(), [stanza()]}, binary(), stanza())
+      -> {stop, {term(), [stanza()]}}.
 
 filter_other({C2SState, _OutStanzas}, Host, Stanza) ->
     ?DEBUG("Won't add stanza to CSI queue", []),
     queue_take(Stanza, Host, C2SState).
 
--spec flush_queue({term(), [xmlel()]}, binary()) -> {term(), [xmlel()]}.
+-spec flush_queue({term(), [stanza()]}, binary()) -> {term(), [stanza()]}.
 
 flush_queue({C2SState, _OutStanzas}, Host) ->
     ?DEBUG("Going to flush CSI queue", []),
@@ -218,20 +214,17 @@ flush_queue({C2SState, _OutStanzas}, Host) ->
     NewState = set_queue([], C2SState),
     {NewState, get_stanzas(Queue, Host)}.
 
--spec add_stream_feature([xmlel()], binary) -> [xmlel()].
+-spec add_stream_feature([stanza()], binary) -> [stanza()].
 
 add_stream_feature(Features, _Host) ->
-    Feature = #xmlel{name = <<"csi">>,
-                    attrs = [{<<"xmlns">>, ?NS_CLIENT_STATE}],
-                    children = []},
-    [Feature | Features].
+    [#feature_csi{xmlns = <<"urn:xmpp:csi:0">>} | Features].
 
 %%--------------------------------------------------------------------
 %% Internal functions.
 %%--------------------------------------------------------------------
 
--spec queue_add(csi_type(), xmlel(), binary(), term())
-      -> {stop, {term(), [xmlel()]}}.
+-spec queue_add(csi_type(), stanza(), binary(), term())
+      -> {stop, {term(), [stanza()]}}.
 
 queue_add(Type, Stanza, Host, C2SState) ->
     case get_queue(C2SState) of
@@ -241,19 +234,19 @@ queue_add(Type, Stanza, Host, C2SState) ->
          {stop, {NewState, get_stanzas(Queue, Host) ++ [Stanza]}};
       Queue ->
          ?DEBUG("Adding stanza to CSI queue", []),
-         From = fxml:get_tag_attr_s(<<"from">>, Stanza),
-         Key = {jid:tolower(jid:from_string(From)), Type},
+         From = xmpp:get_from(Stanza),
+         Key = {jid:tolower(From), Type},
          Entry = {Key, p1_time_compat:timestamp(), Stanza},
          NewQueue = lists:keystore(Key, 1, Queue, Entry),
          NewState = set_queue(NewQueue, C2SState),
          {stop, {NewState, []}}
     end.
 
--spec queue_take(xmlel(), binary(), term()) -> {stop, {term(), [xmlel()]}}.
+-spec queue_take(stanza(), binary(), term()) -> {stop, {term(), [stanza()]}}.
 
 queue_take(Stanza, Host, C2SState) ->
-    From = fxml:get_tag_attr_s(<<"from">>, Stanza),
-    {LUser, LServer, _LResource} = jid:tolower(jid:from_string(From)),
+    From = xmpp:get_from(Stanza),
+    {LUser, LServer, _LResource} = jid:tolower(From),
     {Selected, Rest} = lists:partition(
                         fun({{{U, S, _R}, _Type}, _Time, _Stanza}) ->
                                 U == LUser andalso S == LServer
@@ -276,32 +269,23 @@ get_queue(C2SState) ->
              []
     end.
 
--spec get_stanzas(csi_queue(), binary()) -> [xmlel()].
+-spec get_stanzas(csi_queue(), binary()) -> [stanza()].
 
 get_stanzas(Queue, Host) ->
     lists:map(fun({_Key, Time, Stanza}) ->
-                     jlib:add_delay_info(Stanza, Host, Time,
-                                         <<"Client Inactive">>)
+                     xmpp_util:add_delay_info(Stanza, Host, Time,
+                                              <<"Client Inactive">>)
              end, Queue).
 
--spec get_pep_node(xmlel()) -> {value, binary()} | false.
-
-get_pep_node(#xmlel{name = <<"message">>} = Stanza) ->
-    From = fxml:get_tag_attr_s(<<"from">>, Stanza),
-    case jid:from_string(From) of
-      #jid{luser = <<>>} -> % It's not PEP.
-         false;
-      _ ->
-         case fxml:get_subtag_with_xmlns(Stanza, <<"event">>,
-                                         ?NS_PUBSUB_EVENT) of
-           #xmlel{children = Els} ->
-               case fxml:remove_cdata(Els) of
-                 [#xmlel{name = <<"items">>, attrs = ItemsAttrs}] ->
-                     fxml:get_attr(<<"node">>, ItemsAttrs);
-                 _ ->
-                     false
-               end;
-           false ->
-               false
-         end
+-spec get_pep_node(message()) -> binary() | undefined.
+
+get_pep_node(#message{from = #jid{luser = <<>>}}) ->
+    %% It's not PEP.
+    undefined;
+get_pep_node(#message{} = Msg) ->
+    case xmpp:get_subtag(Msg, #pubsub_event{}) of
+       #pubsub_event{items = [#pubsub_event_item{node = Node}]} ->
+           Node;
+       _ ->
+           undefined
     end.
index 2e7b80c188cda4755e37b1b2617dba76a5236d94..03fdab209a0c440e52e03a92530b0448a52cf39d 100644 (file)
 
 -behaviour(gen_mod).
 
--export([start/2, stop/1, process_local_iq_items/3,
-        process_local_iq_info/3, get_local_identity/5,
+-export([start/2, stop/1, process_local_iq_items/1,
+        process_local_iq_info/1, get_local_identity/5,
         get_local_features/5, get_local_services/5,
-        process_sm_iq_items/3, process_sm_iq_info/3,
+        process_sm_iq_items/1, process_sm_iq_info/1,
         get_sm_identity/5, get_sm_features/5, get_sm_items/5,
         get_info/5, register_feature/2, unregister_feature/2,
         register_extra_domain/2, unregister_extra_domain/2,
@@ -44,8 +44,8 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
-
+-include("xmpp.hrl").
+-include_lib("stdlib/include/ms_transform.hrl").
 -include("mod_roster.hrl").
 
 start(Host, Opts) ->
@@ -126,158 +126,133 @@ stop(Host) ->
                           {{'_', Host}}),
     ok.
 
+-spec register_feature(binary(), binary()) -> true.
 register_feature(Host, Feature) ->
     catch ets:new(disco_features,
                  [named_table, ordered_set, public]),
     ets:insert(disco_features, {{Feature, Host}}).
 
+-spec unregister_feature(binary(), binary()) -> true.
 unregister_feature(Host, Feature) ->
     catch ets:new(disco_features,
                  [named_table, ordered_set, public]),
     ets:delete(disco_features, {Feature, Host}).
 
+-spec register_extra_domain(binary(), binary()) -> true.
 register_extra_domain(Host, Domain) ->
     catch ets:new(disco_extra_domains,
                  [named_table, ordered_set, public]),
     ets:insert(disco_extra_domains, {{Domain, Host}}).
 
+-spec unregister_extra_domain(binary(), binary()) -> true.
 unregister_extra_domain(Host, Domain) ->
     catch ets:new(disco_extra_domains,
                  [named_table, ordered_set, public]),
     ets:delete(disco_extra_domains, {Domain, Host}).
 
-process_local_iq_items(From, To,
-                      #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         Node = fxml:get_tag_attr_s(<<"node">>, SubEl),
-         Host = To#jid.lserver,
-         case ejabberd_hooks:run_fold(disco_local_items, Host,
-                                      empty, [From, To, Node, Lang])
-             of
-           {result, Items} ->
-               ANode = case Node of
-                         <<"">> -> [];
-                         _ -> [{<<"node">>, Node}]
-                       end,
-               IQ#iq{type = result,
-                     sub_el =
-                         [#xmlel{name = <<"query">>,
-                                 attrs =
-                                     [{<<"xmlns">>, ?NS_DISCO_ITEMS} | ANode],
-                                 children = Items}]};
-           {error, Error} ->
-               IQ#iq{type = error, sub_el = [SubEl, Error]}
-         end
+-spec process_local_iq_items(iq()) -> iq().
+process_local_iq_items(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_local_iq_items(#iq{type = get, lang = Lang,
+                          from = From, to = To,
+                          sub_els = [#disco_items{node = Node}]} = IQ) ->
+    Host = To#jid.lserver,
+    case ejabberd_hooks:run_fold(disco_local_items, Host,
+                                empty, [From, To, Node, Lang]) of
+       {result, Items} ->
+           xmpp:make_iq_result(IQ, #disco_items{node = Node, items = Items});
+       {error, Error} ->
+           xmpp:make_error(IQ, Error)
     end.
 
-process_local_iq_info(From, To,
-                     #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         Host = To#jid.lserver,
-         Node = fxml:get_tag_attr_s(<<"node">>, SubEl),
-         Identity = ejabberd_hooks:run_fold(disco_local_identity,
-                                            Host, [], [From, To, Node, Lang]),
-         Info = ejabberd_hooks:run_fold(disco_info, Host, [],
-                                        [Host, ?MODULE, Node, Lang]),
-         case ejabberd_hooks:run_fold(disco_local_features, Host,
-                                      empty, [From, To, Node, Lang])
-             of
-           {result, Features} ->
-               ANode = case Node of
-                         <<"">> -> [];
-                         _ -> [{<<"node">>, Node}]
-                       end,
-               IQ#iq{type = result,
-                     sub_el =
-                         [#xmlel{name = <<"query">>,
-                                 attrs =
-                                     [{<<"xmlns">>, ?NS_DISCO_INFO} | ANode],
-                                 children =
-                                     Identity ++
-                                       Info ++ features_to_xml(Features)}]};
-           {error, Error} ->
-               IQ#iq{type = error, sub_el = [SubEl, Error]}
-         end
+-spec process_local_iq_info(iq()) -> iq().
+process_local_iq_info(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_local_iq_info(#iq{type = get, lang = Lang,
+                         from = From, to = To,
+                         sub_els = [#disco_info{node = Node}]} = IQ) ->
+    Host = To#jid.lserver,
+    Identity = ejabberd_hooks:run_fold(disco_local_identity,
+                                      Host, [], [From, To, Node, Lang]),
+    Info = ejabberd_hooks:run_fold(disco_info, Host, [],
+                                  [Host, ?MODULE, Node, Lang]),
+    case ejabberd_hooks:run_fold(disco_local_features, Host,
+                                empty, [From, To, Node, Lang]) of
+       {result, Features} ->
+           xmpp:make_iq_result(IQ, #disco_info{node = Node,
+                                               identities = Identity,
+                                               xdata = Info,
+                                               features = Features});
+       {error, Error} ->
+           xmpp:make_error(IQ, Error)
     end.
 
-get_local_identity(Acc, _From, _To, <<>>, _Lang) ->
-    Acc ++
-      [#xmlel{name = <<"identity">>,
-             attrs =
-                 [{<<"category">>, <<"server">>}, {<<"type">>, <<"im">>},
-                  {<<"name">>, <<"ejabberd">>}],
-             children = []}];
+-spec get_local_identity([identity()], jid(), jid(),
+                        undefined | binary(), undefined | binary()) ->
+                               [identity()].
+get_local_identity(Acc, _From, _To, undefined, _Lang) ->
+    Acc ++ [#identity{category = <<"server">>,
+                     type = <<"im">>,
+                     name = <<"ejabberd">>}];
 get_local_identity(Acc, _From, _To, _Node, _Lang) ->
     Acc.
 
+-spec get_local_features({error, error()} | {result, [binary()]} | empty,
+                        jid(), jid(),
+                        undefined | binary(), undefined | binary()) ->
+                               {error, error()} | {result, [binary()]}.
 get_local_features({error, _Error} = Acc, _From, _To,
                   _Node, _Lang) ->
     Acc;
-get_local_features(Acc, _From, To, <<>>, _Lang) ->
+get_local_features(Acc, _From, To, undefined, _Lang) ->
     Feats = case Acc of
-             {result, Features} -> Features;
-             empty -> []
+               {result, Features} -> Features;
+               empty -> []
            end,
     Host = To#jid.lserver,
     {result,
      ets:select(disco_features,
-               [{{{'_', Host}}, [], ['$_']}])
-       ++ Feats};
+               ets:fun2ms(fun({{F, H}}) when H == Host -> F end))
+     ++ Feats};
 get_local_features(Acc, _From, _To, _Node, Lang) ->
     case Acc of
       {result, _Features} -> Acc;
       empty ->
            Txt = <<"No features available">>,
-           {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)}
+           {error, xmpp:err_item_not_found(Txt, Lang)}
     end.
 
-features_to_xml(FeatureList) ->
-    [#xmlel{name = <<"feature">>,
-           attrs = [{<<"var">>, Feat}], children = []}
-     || Feat
-           <- lists:usort(lists:map(fun ({{Feature, _Host}}) ->
-                                            Feature;
-                                        (Feature) when is_binary(Feature) ->
-                                            Feature
-                                    end,
-                                    FeatureList))].
-
-domain_to_xml({Domain}) ->
-    #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Domain}],
-          children = []};
-domain_to_xml(Domain) ->
-    #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Domain}],
-          children = []}.
-
+-spec get_local_services({error, error()} | {result, [disco_item()]} | empty,
+                        jid(), jid(),
+                        undefined | binary(), undefined | binary()) ->
+                               {error, error()} | {result, [disco_item()]}.
 get_local_services({error, _Error} = Acc, _From, _To,
                   _Node, _Lang) ->
     Acc;
-get_local_services(Acc, _From, To, <<>>, _Lang) ->
+get_local_services(Acc, _From, To, undefined, _Lang) ->
     Items = case Acc of
              {result, Its} -> Its;
              empty -> []
            end,
     Host = To#jid.lserver,
     {result,
-     lists:usort(lists:map(fun domain_to_xml/1,
-                          get_vh_services(Host) ++
-                            ets:select(disco_extra_domains,
-                                       [{{{'$1', Host}}, [], ['$1']}])))
-       ++ Items};
+     lists:usort(
+       lists:map(
+        fun(Domain) -> #disco_item{jid = jid:make(Domain)} end,
+        get_vh_services(Host) ++
+            ets:select(disco_extra_domains,
+                       ets:fun2ms(
+                         fun({{D, H}}) when H == Host -> D end))))
+     ++ Items};
 get_local_services({result, _} = Acc, _From, _To, _Node,
                   _Lang) ->
     Acc;
 get_local_services(empty, _From, _To, _Node, Lang) ->
-    {error, ?ERRT_ITEM_NOT_FOUND(Lang, <<"No services available">>)}.
+    {error, xmpp:err_item_not_found(<<"No services available">>, Lang)}.
 
+-spec get_vh_services(binary()) -> [binary()].
 get_vh_services(Host) ->
     Hosts = lists:sort(fun (H1, H2) ->
                               byte_size(H1) >= byte_size(H2)
@@ -300,47 +275,38 @@ get_vh_services(Host) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-process_sm_iq_items(From, To,
-                   #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         case is_presence_subscribed(From, To) of
-           true ->
-               Host = To#jid.lserver,
-               Node = fxml:get_tag_attr_s(<<"node">>, SubEl),
-               case ejabberd_hooks:run_fold(disco_sm_items, Host,
-                                            empty, [From, To, Node, Lang])
-                   of
-                 {result, Items} ->
-                     ANode = case Node of
-                               <<"">> -> [];
-                               _ -> [{<<"node">>, Node}]
-                             end,
-                     IQ#iq{type = result,
-                           sub_el =
-                               [#xmlel{name = <<"query">>,
-                                       attrs =
-                                           [{<<"xmlns">>, ?NS_DISCO_ITEMS}
-                                            | ANode],
-                                       children = Items}]};
-                 {error, Error} ->
-                     IQ#iq{type = error, sub_el = [SubEl, Error]}
-               end;
-           false ->
-               Txt = <<"Not subscribed">>,
-               IQ#iq{type = error,
-                     sub_el = [SubEl, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)]}
-         end
+-spec process_sm_iq_items(iq()) -> iq().
+process_sm_iq_items(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_sm_iq_items(#iq{type = get, lang = Lang,
+                       from = From, to = To,
+                       sub_els = [#disco_items{node = Node}]} = IQ) ->
+    case is_presence_subscribed(From, To) of
+       true ->
+           Host = To#jid.lserver,
+           case ejabberd_hooks:run_fold(disco_sm_items, Host,
+                                        empty, [From, To, Node, Lang]) of
+               {result, Items} ->
+                   xmpp:make_iq_result(
+                     IQ, #disco_items{node = Node, items = Items});
+               {error, Error} ->
+                   xmpp:make_error(IQ, Error)
+           end;
+       false ->
+           Txt = <<"Not subscribed">>,
+           xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang))
     end.
 
+-spec get_sm_items({error, error()} | {result, [disco_item()]} | empty,
+                  jid(), jid(),
+                  undefined | binary(), undefined | binary()) ->
+                         {error, error()} | {result, [disco_item()]}.
 get_sm_items({error, _Error} = Acc, _From, _To, _Node,
             _Lang) ->
     Acc;
 get_sm_items(Acc, From,
-            #jid{user = User, server = Server} = To, <<>>, _Lang) ->
+            #jid{user = User, server = Server} = To, undefined, _Lang) ->
     Items = case Acc of
              {result, Its} -> Its;
              empty -> []
@@ -357,12 +323,13 @@ get_sm_items(empty, From, To, _Node, Lang) ->
     #jid{luser = LFrom, lserver = LSFrom} = From,
     #jid{luser = LTo, lserver = LSTo} = To,
     case {LFrom, LSFrom} of
-      {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND};
+      {LTo, LSTo} -> {error, xmpp:err_item_not_found()};
       _ ->
            Txt = <<"Query to another users is forbidden">>,
-           {error, ?ERRT_NOT_ALLOWED(Lang, Txt)}
+           {error, xmpp:err_not_allowed(Txt, Lang)}
     end.
 
+-spec is_presence_subscribed(jid(), jid()) -> boolean().
 is_presence_subscribed(#jid{luser = User, lserver = Server},
                       #jid{luser = User, lserver = Server}) -> true;
 is_presence_subscribed(#jid{luser = FromUser, lserver = FromServer},
@@ -377,86 +344,70 @@ is_presence_subscribed(#jid{luser = FromUser, lserver = FromServer},
              ejabberd_hooks:run_fold(roster_get, ToServer, [],
                                      [{ToUser, ToServer}])).
 
-process_sm_iq_info(From, To,
-                  #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         case is_presence_subscribed(From, To) of
-           true ->
-               Host = To#jid.lserver,
-               Node = fxml:get_tag_attr_s(<<"node">>, SubEl),
-               Identity = ejabberd_hooks:run_fold(disco_sm_identity,
-                                                  Host, [],
-                                                  [From, To, Node, Lang]),
-               Info = ejabberd_hooks:run_fold(disco_info, Host, [],
+-spec process_sm_iq_info(iq()) -> iq().
+process_sm_iq_info(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_sm_iq_info(#iq{type = get, lang = Lang,
+                      from = From, to = To,
+                      sub_els = [#disco_info{node = Node}]} = IQ) ->
+    case is_presence_subscribed(From, To) of
+       true ->
+           Host = To#jid.lserver,
+           Identity = ejabberd_hooks:run_fold(disco_sm_identity,
+                                              Host, [],
                                               [From, To, Node, Lang]),
-               case ejabberd_hooks:run_fold(disco_sm_features, Host,
-                                            empty, [From, To, Node, Lang])
-                   of
-                 {result, Features} ->
-                     ANode = case Node of
-                               <<"">> -> [];
-                               _ -> [{<<"node">>, Node}]
-                             end,
-                     IQ#iq{type = result,
-                           sub_el =
-                               [#xmlel{name = <<"query">>,
-                                       attrs =
-                                           [{<<"xmlns">>, ?NS_DISCO_INFO}
-                                            | ANode],
-                                       children =
-                                           Identity ++ Info ++
-                                             features_to_xml(Features)}]};
-                 {error, Error} ->
-                     IQ#iq{type = error, sub_el = [SubEl, Error]}
-               end;
-           false ->
-               Txt = <<"Not subscribed">>,
-               IQ#iq{type = error,
-                     sub_el = [SubEl, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)]}
-         end
+           Info = ejabberd_hooks:run_fold(disco_info, Host, [],
+                                          [From, To, Node, Lang]),
+           case ejabberd_hooks:run_fold(disco_sm_features, Host,
+                                        empty, [From, To, Node, Lang]) of
+               {result, Features} ->
+                   xmpp:make_iq_result(IQ, #disco_info{node = Node,
+                                                       identities = Identity,
+                                                       xdata = Info,
+                                                       features = Features});
+               {error, Error} ->
+                   xmpp:make_error(IQ, Error)
+           end;
+       false ->
+           Txt = <<"Not subscribed">>,
+           xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang))
     end.
 
+-spec get_sm_identity([identity()], jid(), jid(),
+                     undefined | binary(), undefined | binary()) ->
+                            [identity()].
 get_sm_identity(Acc, _From,
                #jid{luser = LUser, lserver = LServer}, _Node, _Lang) ->
     Acc ++
       case ejabberd_auth:is_user_exists(LUser, LServer) of
        true ->
-           [#xmlel{name = <<"identity">>,
-                   attrs =
-                       [{<<"category">>, <<"account">>},
-                        {<<"type">>, <<"registered">>}],
-                   children = []}];
+           [#identity{category = <<"account">>, type = <<"registered">>}];
        _ -> []
       end.
 
+-spec get_sm_features({error, error()} | {result, [binary()]} | empty,
+                     jid(), jid(),
+                     undefined | binary(), undefined | binary()) ->
+                            {error, error()} | {result, [binary()]}.
 get_sm_features(empty, From, To, _Node, Lang) ->
     #jid{luser = LFrom, lserver = LSFrom} = From,
     #jid{luser = LTo, lserver = LSTo} = To,
     case {LFrom, LSFrom} of
-      {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND};
+      {LTo, LSTo} -> {error, xmpp:err_item_not_found()};
       _ ->
            Txt = <<"Query to another users is forbidden">>,
-           {error, ?ERRT_NOT_ALLOWED(Lang, Txt)}
+           {error, xmpp:err_not_allowed(Txt, Lang)}
     end;
 get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc.
 
+-spec get_user_resources(binary(), binary()) -> [disco_item()].
 get_user_resources(User, Server) ->
     Rs = ejabberd_sm:get_user_resources(User, Server),
-    lists:map(fun (R) ->
-                     #xmlel{name = <<"item">>,
-                            attrs =
-                                [{<<"jid">>,
-                                  <<User/binary, "@", Server/binary, "/",
-                                    R/binary>>},
-                                 {<<"name">>, User}],
-                            children = []}
-             end,
-             lists:sort(Rs)).
+    [#disco_item{jid = jid:make(User, Server, Resource), name = User}
+     || Resource <- lists:sort(Rs)].
 
+-spec transform_module_options(gen_mod:opts()) -> gen_mod:opts().
 transform_module_options(Opts) ->
     lists:map(
       fun({server_info, Infos}) ->
@@ -477,27 +428,23 @@ transform_module_options(Opts) ->
 
 %%% Support for: XEP-0157 Contact Addresses for XMPP Services
 
-get_info(_A, Host, Mod, Node, _Lang) when Node == <<>> ->
+-spec get_info([xdata()], binary(), module(),
+              undefined | binary(), undefined | binary()) ->
+                     [xdata()].
+get_info(_A, Host, Mod, Node, _Lang) when Node == undefined ->
     Module = case Mod of
               undefined -> ?MODULE;
               _ -> Mod
             end,
-    Serverinfo_fields = get_fields_xml(Host, Module),
-    [#xmlel{name = <<"x">>,
-           attrs =
-               [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}],
-           children =
-               [#xmlel{name = <<"field">>,
-                       attrs =
-                           [{<<"var">>, <<"FORM_TYPE">>},
-                            {<<"type">>, <<"hidden">>}],
-                       children =
-                           [#xmlel{name = <<"value">>, attrs = [],
-                                   children = [{xmlcdata, ?NS_SERVERINFO}]}]}]
-                 ++ Serverinfo_fields}];
+    [#xdata{type = result,
+           fields = [#xdata_field{type = hidden,
+                                  var = <<"FORM_TYPE">>,
+                                  values = [?NS_SERVERINFO]}
+                     | get_fields(Host, Module)]}];
 get_info(Acc, _, _, _Node, _) -> Acc.
 
-get_fields_xml(Host, Module) ->
+-spec get_fields(binary(), module()) -> [xdata_field()].
+get_fields(Host, Module) ->
     Fields = gen_mod:get_module_opt(
                Host, ?MODULE, server_info,
                fun(L) ->
@@ -509,31 +456,17 @@ get_fields_xml(Host, Module) ->
                                  {Mods, Name, URLs}
                          end, L)
                end, []),
-    Fields_good = lists:filter(fun ({Modules, _, _}) ->
-                                      case Modules of
-                                        all -> true;
-                                        Modules ->
-                                            lists:member(Module, Modules)
-                                      end
-                              end,
-                              Fields),
-    fields_to_xml(Fields_good).
-
-fields_to_xml(Fields) ->
-    [field_to_xml(Field) || Field <- Fields].
-
-field_to_xml({_, Var, Values}) ->
-    Values_xml = values_to_xml(Values),
-    #xmlel{name = <<"field">>, attrs = [{<<"var">>, Var}],
-          children = Values_xml}.
-
-values_to_xml(Values) ->
-    lists:map(fun (Value) ->
-                     #xmlel{name = <<"value">>, attrs = [],
-                            children = [{xmlcdata, Value}]}
-             end,
-             Values).
-
+    Fields1 = lists:filter(fun ({Modules, _, _}) ->
+                                  case Modules of
+                                      all -> true;
+                                      Modules ->
+                                          lists:member(Module, Modules)
+                                  end
+                          end,
+                          Fields),
+    [#xdata_field{var = Var, values = Values} || {_, Var, Values} <- Fields1].
+
+-spec depends(binary(), gen_mod:opts()) -> [].
 depends(_Host, _Opts) ->
     [].
 
index ee904d798f18cf72ae2121f98686cc3fc00c67a1..fe4b8d90d0ddbafa4cb16d8d1ba644fb94687447 100644 (file)
@@ -42,7 +42,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -record(state, {host = <<"">> :: binary()}).
 
@@ -118,10 +118,10 @@ handle_cast(_Msg, State) -> {noreply, State}.
 handle_info({route, From, To, Packet}, State) ->
     Packet2 = case From#jid.user of
                <<"">> ->
-                   Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet),
+                   Lang = xmpp:get_lang(Packet),
                    Txt = <<"User part of JID in 'from' is empty">>,
-                   jlib:make_error_reply(
-                     Packet, ?ERRT_BAD_REQUEST(Lang, Txt));
+                   xmpp:make_error(
+                     Packet, xmpp:err_bad_request(Txt, Lang));
                _ -> Packet
              end,
     do_client_version(disabled, To, From),
@@ -168,37 +168,27 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
 %% using exactly the same JID. We add a (mostly) random resource to
 %% try to guarantee that the received response matches the request sent.
 %% Finally, the received response is printed in the ejabberd log file.
+
+%% THIS IS **NOT** HOW TO WRITE ejabberd CODE. THIS CODE IS RETARDED.
+
 do_client_version(disabled, _From, _To) -> ok;
 do_client_version(enabled, From, To) ->
-    ToS = jid:to_string(To),
-    Random_resource =
-       iolist_to_binary(integer_to_list(random:uniform(100000))),
+    Random_resource = randoms:get_string(),
     From2 = From#jid{resource = Random_resource,
                     lresource = Random_resource},
-    Packet = #xmlel{name = <<"iq">>,
-                   attrs = [{<<"to">>, ToS}, {<<"type">>, <<"get">>}],
-                   children =
-                       [#xmlel{name = <<"query">>,
-                               attrs = [{<<"xmlns">>, ?NS_VERSION}],
-                               children = []}]},
+    ID = randoms:get_string(),
+    Packet = #iq{from = From, to = To, type = get,
+                id = randoms:get_string(),
+                sub_els = [#version{}]},
     ejabberd_router:route(From2, To, Packet),
-    Els = receive
-           {route, To, From2, IQ} ->
-               #xmlel{name = <<"query">>, children = List} =
-                   fxml:get_subtag(IQ, <<"query">>),
-               List
-           after 5000 -> % Timeout in miliseconds: 5 seconds
-                     []
-         end,
-    Values = [{Name, Value}
-             || #xmlel{name = Name, attrs = [],
-                       children = [{xmlcdata, Value}]}
-                    <- Els],
-    Values_string1 = [io_lib:format("~n~s: ~p", [N, V])
-                     || {N, V} <- Values],
-    Values_string2 = iolist_to_binary(Values_string1),
-    ?INFO_MSG("Information of the client: ~s~s",
-             [ToS, Values_string2]).
+    receive
+       {route, To, From2,
+        #iq{id = ID, type = result, sub_els = [#version{} = V]}} ->
+           ?INFO_MSG("Version of the client ~s:~n~s",
+                     [jid:to_string(To), xmpp:pp(V)])
+    after 5000 -> % Timeout in miliseconds: 5 seconds
+           []
+    end.
 
 depends(_Host, _Opts) ->
     [].
index ce91488411dc37ffab1b766537c6b8f66bcb080c..b267aa89b191490c984b04fc282ed31027f6b24d 100644 (file)
@@ -33,8 +33,8 @@
 
 -behaviour(gen_mod).
 
--export([start/2, stop/1, process_local_iq/3, export/1,
-        process_sm_iq/3, on_presence_update/4, import/1,
+-export([start/2, stop/1, process_local_iq/1, export/1,
+        process_sm_iq/1, on_presence_update/4, import/1,
         import/3, store_last_info/4, get_last_info/2,
         remove_user/2, transform_options/1, mod_opt_type/1,
         opt_type/1, register_user/2, depends/2]).
@@ -42,7 +42,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -include("mod_privacy.hrl").
 -include("mod_last.hrl").
@@ -87,25 +87,14 @@ stop(Host) ->
 %%% Uptime of ejabberd node
 %%%
 
-process_local_iq(_From, _To,
-                #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         Sec = get_node_uptime(),
-         IQ#iq{type = result,
-               sub_el =
-                   [#xmlel{name = <<"query">>,
-                           attrs =
-                               [{<<"xmlns">>, ?NS_LAST},
-                                {<<"seconds">>,
-                                 iolist_to_binary(integer_to_list(Sec))}],
-                           children = []}]}
-    end.
+-spec process_local_iq(iq()) -> iq().
+process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_local_iq(#iq{type = get} = IQ) ->
+    xmpp:make_iq_result(IQ, #last{seconds = get_node_uptime()}).
 
-%% @spec () -> integer()
+-spec get_node_uptime() -> non_neg_integer().
 %% @doc Get the uptime of the ejabberd node, expressed in seconds.
 %% When ejabberd is starting, ejabberd_config:start/0 stores the datetime.
 get_node_uptime() ->
@@ -118,6 +107,7 @@ get_node_uptime() ->
             p1_time_compat:system_time(seconds) - Now
     end.
 
+-spec now_to_seconds(erlang:timestamp()) -> non_neg_integer().
 now_to_seconds({MegaSecs, Secs, _MicroSecs}) ->
     MegaSecs * 1000000 + Secs.
 
@@ -125,83 +115,63 @@ now_to_seconds({MegaSecs, Secs, _MicroSecs}) ->
 %%% Serve queries about user last online
 %%%
 
-process_sm_iq(From, To,
-             #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         User = To#jid.luser,
-         Server = To#jid.lserver,
-         {Subscription, _Groups} =
-             ejabberd_hooks:run_fold(roster_get_jid_info, Server,
-                                     {none, []}, [User, Server, From]),
-         if (Subscription == both) or (Subscription == from) or
-              (From#jid.luser == To#jid.luser) and
-                (From#jid.lserver == To#jid.lserver) ->
-                UserListRecord =
-                    ejabberd_hooks:run_fold(privacy_get_user_list, Server,
-                                            #userlist{}, [User, Server]),
-                case ejabberd_hooks:run_fold(privacy_check_packet,
-                                             Server, allow,
-                                             [User, Server, UserListRecord,
-                                              {To, From,
-                                               #xmlel{name = <<"presence">>,
-                                                      attrs = [],
-                                                      children = []}},
-                                              out])
-                    of
-                  allow -> get_last_iq(IQ, SubEl, User, Server);
-                  deny ->
-                      IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}
-                end;
-            true ->
-                Txt = <<"Not subscribed">>,
-                IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}
-         end
+-spec process_sm_iq(iq()) -> iq().
+process_sm_iq(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_sm_iq(#iq{from = From, to = To, lang = Lang} = IQ) ->
+    User = To#jid.luser,
+    Server = To#jid.lserver,
+    {Subscription, _Groups} =
+       ejabberd_hooks:run_fold(roster_get_jid_info, Server,
+                               {none, []}, [User, Server, From]),
+    if (Subscription == both) or (Subscription == from) or
+       (From#jid.luser == To#jid.luser) and
+       (From#jid.lserver == To#jid.lserver) ->
+           UserListRecord =
+               ejabberd_hooks:run_fold(privacy_get_user_list, Server,
+                                       #userlist{}, [User, Server]),
+           case ejabberd_hooks:run_fold(privacy_check_packet,
+                                        Server, allow,
+                                        [User, Server, UserListRecord,
+                                         {To, From, #presence{}}, out]) of
+               allow -> get_last_iq(IQ, User, Server);
+               deny -> xmpp:make_error(IQ, xmpp:err_forbidden())
+           end;
+       true ->
+           Txt = <<"Not subscribed">>,
+           xmpp:make_error(IQ, xmpp:err_not_subscribed(Txt, Lang))
     end.
 
 %% @spec (LUser::string(), LServer::string()) ->
 %%      {ok, TimeStamp::integer(), Status::string()} | not_found | {error, Reason}
+-spec get_last(binary(), binary()) -> {ok, non_neg_integer(), binary()} |
+                                     not_found | {error, any()}.
 get_last(LUser, LServer) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:get_last(LUser, LServer).
 
-get_last_iq(#iq{lang = Lang} = IQ, SubEl, LUser, LServer) ->
+-spec get_last_iq(iq(), binary(), binary()) -> iq().
+get_last_iq(#iq{lang = Lang} = IQ, LUser, LServer) ->
     case ejabberd_sm:get_user_resources(LUser, LServer) of
       [] ->
          case get_last(LUser, LServer) of
            {error, _Reason} ->
                Txt = <<"Database failure">>,
-               IQ#iq{type = error,
-                     sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]};
+               xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang));
            not_found ->
                Txt = <<"No info about last activity found">>,
-               IQ#iq{type = error,
-                     sub_el = [SubEl, ?ERRT_SERVICE_UNAVAILABLE(Lang, Txt)]};
+               xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang));
            {ok, TimeStamp, Status} ->
                TimeStamp2 = p1_time_compat:system_time(seconds),
                Sec = TimeStamp2 - TimeStamp,
-               IQ#iq{type = result,
-                     sub_el =
-                         [#xmlel{name = <<"query">>,
-                                 attrs =
-                                     [{<<"xmlns">>, ?NS_LAST},
-                                      {<<"seconds">>,
-                                       iolist_to_binary(integer_to_list(Sec))}],
-                                 children = [{xmlcdata, Status}]}]}
+               xmpp:make_iq_result(IQ, #last{seconds = Sec, status = Status})
          end;
       _ ->
-         IQ#iq{type = result,
-               sub_el =
-                   [#xmlel{name = <<"query">>,
-                           attrs =
-                               [{<<"xmlns">>, ?NS_LAST},
-                                {<<"seconds">>, <<"0">>}],
-                           children = []}]}
+         xmpp:make_iq_result(IQ, #last{seconds = 0})
     end.
 
+-spec register_user(binary(), binary()) -> {atomic, any()}.
 register_user(User, Server) ->
     on_presence_update(
        User,
@@ -209,18 +179,21 @@ register_user(User, Server) ->
        <<"RegisterResource">>,
        <<"Registered but didn't login">>).
 
+-spec on_presence_update(binary(), binary(), binary(), binary()) -> {atomic, any()}.
 on_presence_update(User, Server, _Resource, Status) ->
     TimeStamp = p1_time_compat:system_time(seconds),
     store_last_info(User, Server, TimeStamp, Status).
 
+-spec store_last_info(binary(), binary(), non_neg_integer(), binary()) ->
+                            {atomic, any()}.
 store_last_info(User, Server, TimeStamp, Status) ->
     LUser = jid:nodeprep(User),
     LServer = jid:nameprep(Server),
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:store_last_info(LUser, LServer, TimeStamp, Status).
 
-%% @spec (LUser::string(), LServer::string()) ->
-%%      {ok, TimeStamp::integer(), Status::string()} | not_found
+-spec get_last_info(binary(), binary()) -> {ok, non_neg_integer(), binary()} |
+                                          not_found.
 get_last_info(LUser, LServer) ->
     case get_last(LUser, LServer) of
       {error, _Reason} -> not_found;
index d1b3f9322fec10a5d75c02bddc7b4475cc117c67..b09ca9ab2f075188a94d26928e828e14ac823687 100644 (file)
@@ -36,7 +36,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -define(SUPERVISOR, ejabberd_sup).
 
@@ -54,7 +54,7 @@
 -export([init/1, terminate/2, handle_call/3,
         handle_cast/2, handle_info/2, code_change/3]).
 
--export([iq_ping/3, user_online/3, user_offline/3,
+-export([iq_ping/1, user_online/3, user_offline/3,
         user_send/4, mod_opt_type/1, depends/2]).
 
 -record(state,
@@ -73,10 +73,12 @@ start_link(Host, Opts) ->
     gen_server:start_link({local, Proc}, ?MODULE,
                          [Host, Opts], []).
 
+-spec start_ping(binary(), jid()) -> ok.
 start_ping(Host, JID) ->
     Proc = gen_mod:get_module_proc(Host, ?MODULE),
     gen_server:cast(Proc, {start_ping, JID}).
 
+-spec stop_ping(binary(), jid()) -> ok.
 stop_ping(Host, JID) ->
     Proc = gen_mod:get_module_proc(Host, ?MODULE),
     gen_server:cast(Proc, {stop_ping, JID}).
@@ -181,10 +183,7 @@ handle_cast({iq_pong, JID, timeout}, State) ->
 handle_cast(_Msg, State) -> {noreply, State}.
 
 handle_info({timeout, _TRef, {ping, JID}}, State) ->
-    IQ = #iq{type = get,
-            sub_el =
-                [#xmlel{name = <<"ping">>,
-                        attrs = [{<<"xmlns">>, ?NS_PING}], children = []}]},
+    IQ = #iq{type = get, sub_els = [#ping{}]},
     Pid = self(),
     F = fun (Response) ->
                gen_server:cast(Pid, {iq_pong, JID, Response})
@@ -201,23 +200,22 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
 %%====================================================================
 %% Hook callbacks
 %%====================================================================
-iq_ping(_From, _To,
-       #iq{type = Type, sub_el = SubEl, lang = Lang} = IQ) ->
-    case {Type, SubEl} of
-      {get, #xmlel{name = <<"ping">>}} ->
-         IQ#iq{type = result, sub_el = []};
-      _ ->
-         Txt = <<"Ping query is incorrect">>,
-         IQ#iq{type = error,
-               sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}
-    end.
-
+-spec iq_ping(iq()) -> iq().
+iq_ping(#iq{type = get, sub_els = [#ping{}]} = IQ) ->
+    xmpp:make_iq_result(IQ);
+iq_ping(#iq{lang = Lang} = IQ) ->
+    Txt = <<"Ping query is incorrect">>,
+    xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang)).
+
+-spec user_online(ejabberd_sm:sid(), jid(), any()) -> ok.
 user_online(_SID, JID, _Info) ->
     start_ping(JID#jid.lserver, JID).
 
+-spec user_offline(ejabberd_sm:sid(), jid(), any()) -> ok.
 user_offline(_SID, JID, _Info) ->
     stop_ping(JID#jid.lserver, JID).
 
+-spec user_send(stanza(), ejabberd_c2s:state(), jid(), jid()) -> stanza().
 user_send(Packet, _C2SState, JID, _From) ->
     start_ping(JID#jid.lserver, JID),
     Packet.
@@ -225,6 +223,7 @@ user_send(Packet, _C2SState, JID, _From) ->
 %%====================================================================
 %% Internal functions
 %%====================================================================
+-spec add_timer(jid(), non_neg_integer(), map()) -> map().
 add_timer(JID, Interval, Timers) ->
     LJID = jid:tolower(JID),
     NewTimers = case maps:find(LJID, Timers) of
@@ -237,6 +236,7 @@ add_timer(JID, Interval, Timers) ->
                              {ping, JID}),
     maps:put(LJID, TRef, NewTimers).
 
+-spec del_timer(jid(), map()) -> map().
 del_timer(JID, Timers) ->
     LJID = jid:tolower(JID),
     case maps:find(LJID, Timers) of
@@ -246,6 +246,7 @@ del_timer(JID, Timers) ->
       _ -> Timers
     end.
 
+-spec cancel_timer(reference()) -> ok.
 cancel_timer(TRef) ->
     case erlang:cancel_timer(TRef) of
       false ->
index 18ff78371a73146d32d62cfa0f1a7c0edec32c52..e88c1fb5b08bbf5bf6f4c20077eafac94a0e45a1 100644 (file)
@@ -31,8 +31,8 @@
 
 -behaviour(gen_mod).
 
--export([start/2, stop/1, process_iq/3, export/1, import/1,
-        process_iq_set/4, process_iq_get/5, get_user_list/3,
+-export([start/2, stop/1, process_iq/1, export/1, import/1,
+        process_iq_set/2, process_iq_get/3, get_user_list/3,
         check_packet/6, remove_user/2,
         is_list_needdb/1, updated_list/3,
          item_to_xml/1, get_user_lists/2, import/3,
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -include("mod_privacy.hrl").
 
 -callback init(binary(), gen_mod:opts()) -> any().
 -callback import(binary(), #privacy{}) -> ok | pass.
--callback process_lists_get(binary(), binary()) -> {none | binary(), [xmlel()]} | error.
+-callback process_lists_get(binary(), binary()) -> {none | binary(), [binary()]} | error.
 -callback process_list_get(binary(), binary(), binary()) -> [listitem()] | error | not_found.
--callback process_default_set(binary(), binary(), {value, binary()} | false) -> {atomic, any()}.
+-callback process_default_set(binary(), binary(), binary() | none) -> {atomic, any()}.
 -callback process_active_set(binary(), binary(), binary()) -> [listitem()] | error.
 -callback remove_privacy_list(binary(), binary(), binary()) -> {atomic, any()}.
 -callback set_privacy_list(#privacy{}) -> any().
@@ -96,335 +96,276 @@ stop(Host) ->
     gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
                                     ?NS_PRIVACY).
 
-process_iq(_From, _To, IQ) ->
-    SubEl = IQ#iq.sub_el,
-    IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}.
+-spec process_iq(iq()) -> iq().
+process_iq(IQ) ->
+    xmpp:make_error(IQ, xmpp:err_not_allowed()).
 
-process_iq_get(_, From, _To, #iq{lang = Lang, sub_el = SubEl},
+-spec process_iq_get({error, error()} | iq(),
+                    iq(), userlist()) -> {error, error()} | {result, privacy_query()}.
+process_iq_get(_, #iq{from = From, lang = Lang,
+                     sub_els = [#privacy_query{lists = Lists}]},
               #userlist{name = Active}) ->
     #jid{luser = LUser, lserver = LServer} = From,
-    #xmlel{children = Els} = SubEl,
-    case fxml:remove_cdata(Els) of
-      [] -> process_lists_get(LUser, LServer, Active, Lang);
-      [#xmlel{name = Name, attrs = Attrs}] ->
-         case Name of
-           <<"list">> ->
-               ListName = fxml:get_attr(<<"name">>, Attrs),
-               process_list_get(LUser, LServer, ListName, Lang);
-           _ ->
-                 Txt = <<"Unsupported tag name">>,
-                 {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
-         end;
-      _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Too many elements">>)}
+    case Lists of
+       [] ->
+           process_lists_get(LUser, LServer, Active, Lang);
+       [#privacy_list{name = ListName}] ->
+           process_list_get(LUser, LServer, ListName, Lang);
+       _ ->
+           Txt = <<"Too many <list/> elements">>,
+           {error, xmpp:err_bad_request(Txt, Lang)}
     end.
 
+-spec process_lists_get(binary(), binary(), binary(), undefined | binary()) ->
+                              {error, error()} | {result, privacy_query()}.
 process_lists_get(LUser, LServer, Active, Lang) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     case Mod:process_lists_get(LUser, LServer) of
-      error -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)};
-      {_Default, []} ->
-         {result,
-          [#xmlel{name = <<"query">>,
-                  attrs = [{<<"xmlns">>, ?NS_PRIVACY}], children = []}]};
-      {Default, LItems} ->
-         DItems = case Default of
-                    none -> LItems;
-                    _ ->
-                        [#xmlel{name = <<"default">>,
-                                attrs = [{<<"name">>, Default}], children = []}
-                         | LItems]
-                  end,
-         ADItems = case Active of
-                     none -> DItems;
-                     _ ->
-                         [#xmlel{name = <<"active">>,
-                                 attrs = [{<<"name">>, Active}], children = []}
-                          | DItems]
-                   end,
-         {result,
-          [#xmlel{name = <<"query">>,
-                  attrs = [{<<"xmlns">>, ?NS_PRIVACY}],
-                  children = ADItems}]}
+       error ->
+           Txt = <<"Database failure">>,
+           {error, xmpp:err_internal_server_error(Txt, Lang)};
+       {_Default, []} ->
+           {result, #privacy_query{}};
+       {Default, ListNames} ->
+           {result,
+            #privacy_query{active = Active,
+                           default = Default,
+                           lists = [#privacy_list{name = ListName}
+                                    || ListName <- ListNames]}}
     end.
 
-process_list_get(LUser, LServer, {value, Name}, Lang) ->
+-spec process_list_get(binary(), binary(), binary(), undefined | binary()) ->
+                             {error, error()} | {result, privacy_query()}.
+process_list_get(LUser, LServer, Name, Lang) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     case Mod:process_list_get(LUser, LServer, Name) of
-      error -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)};
-      not_found -> {error, ?ERR_ITEM_NOT_FOUND};
-      Items ->
-         LItems = lists:map(fun item_to_xml/1, Items),
-         {result,
-          [#xmlel{name = <<"query">>,
-                  attrs = [{<<"xmlns">>, ?NS_PRIVACY}],
-                  children =
-                      [#xmlel{name = <<"list">>, attrs = [{<<"name">>, Name}],
-                              children = LItems}]}]}
-    end;
-process_list_get(_LUser, _LServer, false, _Lang) ->
-    {error, ?ERR_BAD_REQUEST}.
-
-item_to_xml(Item) ->
-    Attrs1 = [{<<"action">>,
-              action_to_list(Item#listitem.action)},
-             {<<"order">>, order_to_list(Item#listitem.order)}],
-    Attrs2 = case Item#listitem.type of
-              none -> Attrs1;
-              Type ->
-                  [{<<"type">>, type_to_list(Item#listitem.type)},
-                   {<<"value">>, value_to_list(Type, Item#listitem.value)}
-                   | Attrs1]
-            end,
-    SubEls = case Item#listitem.match_all of
-              true -> [];
-              false ->
-                  SE1 = case Item#listitem.match_iq of
-                          true ->
-                              [#xmlel{name = <<"iq">>, attrs = [],
-                                      children = []}];
-                          false -> []
-                        end,
-                  SE2 = case Item#listitem.match_message of
-                          true ->
-                              [#xmlel{name = <<"message">>, attrs = [],
-                                      children = []}
-                               | SE1];
-                          false -> SE1
-                        end,
-                  SE3 = case Item#listitem.match_presence_in of
-                          true ->
-                              [#xmlel{name = <<"presence-in">>, attrs = [],
-                                      children = []}
-                               | SE2];
-                          false -> SE2
-                        end,
-                  SE4 = case Item#listitem.match_presence_out of
-                          true ->
-                              [#xmlel{name = <<"presence-out">>, attrs = [],
-                                      children = []}
-                               | SE3];
-                          false -> SE3
-                        end,
-                  SE4
-            end,
-    #xmlel{name = <<"item">>, attrs = Attrs2,
-          children = SubEls}.
-
-action_to_list(Action) ->
-    case Action of
-      allow -> <<"allow">>;
-      deny -> <<"deny">>
+       error ->
+           Txt = <<"Database failure">>,
+           {error, xmpp:err_internal_server_error(Txt, Lang)};
+       not_found ->
+           Txt = <<"No privacy list with this name found">>,
+           {error, xmpp:err_item_not_found(Txt, Lang)};
+       Items ->
+           LItems = lists:map(fun encode_list_item/1, Items),
+           {result,
+            #privacy_query{
+               lists = [#privacy_list{name = Name, items = LItems}]}}
     end.
 
-order_to_list(Order) ->
-    iolist_to_binary(integer_to_list(Order)).
-
-type_to_list(Type) ->
-    case Type of
-      jid -> <<"jid">>;
-      group -> <<"group">>;
-      subscription -> <<"subscription">>
+-spec item_to_xml(listitem()) -> xmlel().
+item_to_xml(ListItem) ->
+    xmpp:encode(encode_list_item(ListItem)).
+
+-spec encode_list_item(listitem()) -> privacy_item().
+encode_list_item(#listitem{action = Action,
+                          order = Order,
+                          type = Type,
+                          match_all = MatchAll,
+                          match_iq = MatchIQ,
+                          match_message = MatchMessage,
+                          match_presence_in = MatchPresenceIn,
+                          match_presence_out = MatchPresenceOut,
+                          value = Value}) ->
+    Item = #privacy_item{action = Action,
+                        order = Order,
+                        type = case Type of
+                                   none -> undefined;
+                                   Type -> Type
+                               end,
+                        value = encode_value(Type, Value)},
+    case MatchAll of
+       true ->
+           Item;
+       false ->
+           Item#privacy_item{message = MatchMessage,
+                             iq = MatchIQ,
+                             presence_in = MatchPresenceIn,
+                             presence_out = MatchPresenceOut}
     end.
 
-value_to_list(Type, Val) ->
+-spec encode_value(listitem_type(), listitem_value()) -> undefined | binary().
+encode_value(Type, Val) ->
     case Type of
-      jid -> jid:to_string(Val);
-      group -> Val;
-      subscription ->
-         case Val of
-           both -> <<"both">>;
-           to -> <<"to">>;
-           from -> <<"from">>;
-           none -> <<"none">>
-         end
+       jid -> jid:to_string(Val);
+       group -> Val;
+       subscription ->
+           case Val of
+               both -> <<"both">>;
+               to -> <<"to">>;
+               from -> <<"from">>;
+               none -> <<"none">>
+           end;
+       none -> undefined
     end.
 
-list_to_action(S) ->
-    case S of
-      <<"allow">> -> allow;
-      <<"deny">> -> deny
+-spec decode_value(jid | subscription | group | undefined, binary()) ->
+                         listitem_value().
+decode_value(Type, Value) ->
+    case Type of
+       jid -> jid:from_string(Value);
+       subscription ->
+           case Value of
+               <<"from">> -> from;
+               <<"to">> -> to;
+               <<"both">> -> both;
+               <<"none">> -> none
+           end;
+       group -> Value;
+       undefined -> none
     end.
 
-process_iq_set(_, From, _To, #iq{lang = Lang, sub_el = SubEl}) ->
+-spec process_iq_set({error, error()} |
+                    {result, privacy_query() | undefined, userlist()},
+                    iq()) -> {error, error()} |
+                             {result, undefined, userlist()}.
+process_iq_set(_, #iq{from = From, lang = Lang,
+                     sub_els = [#privacy_query{default = Default,
+                                               active = Active,
+                                               lists = Lists}]}) ->
     #jid{luser = LUser, lserver = LServer} = From,
-    #xmlel{children = Els} = SubEl,
-    case fxml:remove_cdata(Els) of
-      [#xmlel{name = Name, attrs = Attrs,
-             children = SubEls}] ->
-         ListName = fxml:get_attr(<<"name">>, Attrs),
-         case Name of
-           <<"list">> ->
-               process_list_set(LUser, LServer, ListName,
-                                fxml:remove_cdata(SubEls), Lang);
-           <<"active">> ->
-               process_active_set(LUser, LServer, ListName);
-           <<"default">> ->
-               process_default_set(LUser, LServer, ListName, Lang);
-           _ ->
-               Txt = <<"Unsupported tag name">>,
-               {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
-         end;
-      _ -> {error, ?ERR_BAD_REQUEST}
+    case Lists of
+       [#privacy_list{items = Items, name = ListName}]
+         when Default == undefined, Active == undefined ->
+           process_lists_set(LUser, LServer, ListName, Items, Lang);
+       [] when Default == undefined, Active /= undefined ->
+           process_active_set(LUser, LServer, Active, Lang);
+       [] when Active == undefined, Default /= undefined ->
+           process_default_set(LUser, LServer, Default, Lang);
+       _ ->
+           Txt = <<"There should be exactly one element in this query: "
+                   "<list/>, <active/> or <default/>">>,
+           {error, xmpp:err_bad_request(Txt, Lang)}
     end.
 
+-spec process_default_set(binary(), binary(), none | binary(),
+                         undefined | binary()) -> {error, error()} |
+                                                  {result, undefined}.                  
 process_default_set(LUser, LServer, Value, Lang) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     case Mod:process_default_set(LUser, LServer, Value) of
-      {atomic, error} ->
-           {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)};
-      {atomic, not_found} -> {error, ?ERR_ITEM_NOT_FOUND};
-      {atomic, ok} -> {result, []};
-      _ -> {error, ?ERR_INTERNAL_SERVER_ERROR}
+       {atomic, error} ->
+           Txt = <<"Database failure">>,
+           {error, xmpp:err_internal_server_error(Txt, Lang)};
+       {atomic, not_found} ->
+           Txt = <<"No privacy list with this name found">>,
+           {error, xmpp:err_item_not_found(Txt, Lang)};
+       {atomic, ok} ->
+           {result, undefined};
+       Err ->
+           ?ERROR_MSG("failed to set default list '~s' for user ~s@~s: ~p",
+                      [Value, LUser, LServer, Err]),
+           {error, xmpp:err_internal_server_error()}
     end.
 
-process_active_set(LUser, LServer, {value, Name}) ->
+-spec process_active_set(binary(), binary(), none | binary(),
+                        undefined | binary()) ->
+                               {error, error()} |
+                               {result, undefined, userlist()}.
+process_active_set(_LUser, _LServer, none, _Lang) ->
+    {result, undefined, #userlist{}};
+process_active_set(LUser, LServer, Name, Lang) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     case Mod:process_active_set(LUser, LServer, Name) of
-      error -> {error, ?ERR_ITEM_NOT_FOUND};
-      Items ->
-         NeedDb = is_list_needdb(Items),
-         {result, [],
-          #userlist{name = Name, list = Items, needdb = NeedDb}}
-    end;
-process_active_set(_LUser, _LServer, false) ->
-    {result, [], #userlist{}}.
+       error ->
+           Txt = <<"No privacy list with this name found">>,
+           {error, xmpp:err_item_not_found(Txt, Lang)};
+       Items ->
+           NeedDb = is_list_needdb(Items),
+           {result, undefined,
+            #userlist{name = Name, list = Items, needdb = NeedDb}}
+    end.
 
+-spec set_privacy_list(privacy()) -> any().
 set_privacy_list(#privacy{us = {_, LServer}} = Privacy) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:set_privacy_list(Privacy).
 
-process_list_set(LUser, LServer, {value, Name}, Els, Lang) ->
-    case parse_items(Els) of
-      false -> {error, ?ERR_BAD_REQUEST};
-      remove ->
-         Mod = gen_mod:db_mod(LServer, ?MODULE),
-         case Mod:remove_privacy_list(LUser, LServer, Name) of
-           {atomic, conflict} ->
-                 Txt = <<"Cannot remove default list">>,
-                 {error, ?ERRT_CONFLICT(Lang, Txt)};
-           {atomic, ok} ->
-               ejabberd_sm:route(jid:make(LUser, LServer,
-                                                <<"">>),
-                                  jid:make(LUser, LServer, <<"">>),
-                                  {broadcast, {privacy_list,
-                                               #userlist{name = Name,
-                                                         list = []},
-                                               Name}}),
-               {result, []};
-           _ -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)}
-         end;
-      List ->
-         Mod = gen_mod:db_mod(LServer, ?MODULE),
-         case Mod:set_privacy_list(LUser, LServer, Name, List) of
-           {atomic, ok} ->
-               NeedDb = is_list_needdb(List),
-               ejabberd_sm:route(jid:make(LUser, LServer,
-                                                <<"">>),
-                                  jid:make(LUser, LServer, <<"">>),
-                                  {broadcast, {privacy_list,
-                                               #userlist{name = Name,
-                                                         list = List,
-                                                         needdb = NeedDb},
-                                               Name}}),
-               {result, []};
-           _ -> {error, ?ERRT_INTERNAL_SERVER_ERROR(Lang, <<"Database failure">>)}
-         end
+-spec process_lists_set(binary(), binary(), binary(), [privacy_item()],
+                       undefined | binary()) -> {error, error()} |
+                                                {result, undefined}.
+process_lists_set(LUser, LServer, Name, [], Lang) ->
+    Mod = gen_mod:db_mod(LServer, ?MODULE),
+    case Mod:remove_privacy_list(LUser, LServer, Name) of
+       {atomic, conflict} ->
+           Txt = <<"Cannot remove default list">>,
+           {error, xmpp:err_conflict(Txt, Lang)};
+       {atomic, ok} ->
+           ejabberd_sm:route(jid:make(LUser, LServer,
+                                      <<"">>),
+                             jid:make(LUser, LServer, <<"">>),
+                             {broadcast, {privacy_list,
+                                          #userlist{name = Name,
+                                                    list = []},
+                                          Name}}),
+           {result, undefined};
+       Err ->
+           ?ERROR_MSG("failed to remove privacy list '~s' for user ~s@~s: ~p",
+                      [Name, LUser, LServer, Err]),
+           Txt = <<"Database failure">>,
+           {error, xmpp:err_internal_server_error(Txt, Lang)}
     end;
-process_list_set(_LUser, _LServer, false, _Els, _Lang) ->
-    {error, ?ERR_BAD_REQUEST}.
-
-parse_items([]) -> remove;
-parse_items(Els) -> parse_items(Els, []).
-
-parse_items([], Res) ->
-    lists:keysort(#listitem.order, Res);
-parse_items([#xmlel{name = <<"item">>, attrs = Attrs,
-                   children = SubEls}
-            | Els],
-           Res) ->
-    Type = fxml:get_attr(<<"type">>, Attrs),
-    Value = fxml:get_attr(<<"value">>, Attrs),
-    SAction = fxml:get_attr(<<"action">>, Attrs),
-    SOrder = fxml:get_attr(<<"order">>, Attrs),
-    Action = case catch list_to_action(element(2, SAction))
-                of
-              {'EXIT', _} -> false;
-              Val -> Val
-            end,
-    Order = case catch jlib:binary_to_integer(element(2,
-                                                       SOrder))
-               of
-             {'EXIT', _} -> false;
-             IntVal ->
-                 if IntVal >= 0 -> IntVal;
-                    true -> false
-                 end
+process_lists_set(LUser, LServer, Name, Items, Lang) ->
+    case catch lists:map(fun decode_item/1, Items) of
+       {error, Why} ->
+           Txt = xmpp:format_error(Why),
+           {error, xmpp:err_bad_request(Txt, Lang)};
+       List ->
+           Mod = gen_mod:db_mod(LServer, ?MODULE),
+           case Mod:set_privacy_list(LUser, LServer, Name, List) of
+               {atomic, ok} ->
+                   NeedDb = is_list_needdb(List),
+                   ejabberd_sm:route(jid:make(LUser, LServer,
+                                              <<"">>),
+                                     jid:make(LUser, LServer, <<"">>),
+                                     {broadcast, {privacy_list,
+                                                  #userlist{name = Name,
+                                                            list = List,
+                                                            needdb = NeedDb},
+                                                  Name}}),
+                   {result, undefined};
+               Err ->
+                   ?ERROR_MSG("failed to set privacy list '~s' "
+                              "for user ~s@~s: ~p",
+                              [Name, LUser, LServer, Err]),
+                   Txt = <<"Database failure">>,
+                   {error, xmpp:err_internal_server_error(Txt, Lang)}
+           end
+    end.
+
+-spec decode_item(privacy_item()) -> listitem().
+decode_item(#privacy_item{order = Order,
+                         action = Action,
+                         type = T,
+                         value = V,
+                         message = MatchMessage,
+                         iq = MatchIQ,
+                         presence_in = MatchPresenceIn,
+                         presence_out = MatchPresenceOut}) ->
+    Value = try decode_value(T, V)
+           catch _:_ ->
+                   throw({error, {bad_attr_value, <<"value">>,
+                                  <<"item">>, ?NS_PRIVACY}})
            end,
-    if (Action /= false) and (Order /= false) ->
-          I1 = #listitem{action = Action, order = Order},
-          I2 = case {Type, Value} of
-                 {{value, T}, {value, V}} ->
-                     case T of
-                       <<"jid">> ->
-                           case jid:from_string(V) of
-                             error -> false;
-                             JID ->
-                                 I1#listitem{type = jid,
-                                             value = jid:tolower(JID)}
-                           end;
-                       <<"group">> -> I1#listitem{type = group, value = V};
-                       <<"subscription">> ->
-                           case V of
-                             <<"none">> ->
-                                 I1#listitem{type = subscription,
-                                             value = none};
-                             <<"both">> ->
-                                 I1#listitem{type = subscription,
-                                             value = both};
-                             <<"from">> ->
-                                 I1#listitem{type = subscription,
-                                             value = from};
-                             <<"to">> ->
-                                 I1#listitem{type = subscription, value = to};
-                             _ -> false
-                           end
-                     end;
-                 {{value, _}, false} -> false;
-                 _ -> I1
-               end,
-          case I2 of
-            false -> false;
-            _ ->
-                case parse_matches(I2, fxml:remove_cdata(SubEls)) of
-                  false -> false;
-                  I3 -> parse_items(Els, [I3 | Res])
-                end
-          end;
-       true -> false
-    end;
-parse_items(_, _Res) -> false.
-
-parse_matches(Item, []) ->
-    Item#listitem{match_all = true};
-parse_matches(Item, Els) -> parse_matches1(Item, Els).
-
-parse_matches1(Item, []) -> Item;
-parse_matches1(Item,
-              [#xmlel{name = <<"message">>} | Els]) ->
-    parse_matches1(Item#listitem{match_message = true},
-                  Els);
-parse_matches1(Item, [#xmlel{name = <<"iq">>} | Els]) ->
-    parse_matches1(Item#listitem{match_iq = true}, Els);
-parse_matches1(Item,
-              [#xmlel{name = <<"presence-in">>} | Els]) ->
-    parse_matches1(Item#listitem{match_presence_in = true},
-                  Els);
-parse_matches1(Item,
-              [#xmlel{name = <<"presence-out">>} | Els]) ->
-    parse_matches1(Item#listitem{match_presence_out = true},
-                  Els);
-parse_matches1(_Item, [#xmlel{} | _Els]) -> false.
+    Type = case T of
+              undefined -> none;
+              _ -> T
+          end,
+    ListItem = #listitem{order = Order,
+                        action = Action,
+                        type = Type,
+                        value = Value},
+    if MatchMessage and MatchIQ and MatchPresenceIn and MatchPresenceOut ->
+           ListItem#listitem{match_all = true};
+       not (MatchMessage or MatchIQ or MatchPresenceIn or MatchPresenceOut) ->
+           ListItem#listitem{match_all = true};
+       true ->
+           ListItem#listitem{match_iq = MatchIQ,
+                             match_message = MatchMessage,
+                             match_presence_in = MatchPresenceIn,
+                             match_presence_out = MatchPresenceOut}
+    end.
 
+-spec is_list_needdb([listitem()]) -> boolean().
 is_list_needdb(Items) ->
     lists:any(fun (X) ->
                      case X#listitem.type of
@@ -435,6 +376,7 @@ is_list_needdb(Items) ->
              end,
              Items).
 
+-spec get_user_list(userlist(), binary(), binary()) -> userlist().
 get_user_list(_Acc, User, Server) ->
     LUser = jid:nodeprep(User),
     LServer = jid:nameprep(Server),
@@ -444,6 +386,7 @@ get_user_list(_Acc, User, Server) ->
     #userlist{name = Default, list = Items,
              needdb = NeedDb}.
 
+-spec get_user_lists(binary(), binary()) -> {ok, privacy()} | error.
 get_user_lists(User, Server) ->
     LUser = jid:nodeprep(User),
     LServer = jid:nameprep(Server),
@@ -453,6 +396,8 @@ get_user_lists(User, Server) ->
 %% From is the sender, To is the destination.
 %% If Dir = out, User@Server is the sender account (From).
 %% If Dir = in, User@Server is the destination account (To).
+-spec check_packet(allow | deny, binary(), binary(), userlist(),
+                  {jid(), jid(), stanza()}, in | out) -> allow | deny.
 check_packet(_, _User, _Server, _UserList,
             {#jid{luser = <<"">>, lserver = Server} = _From,
              #jid{lserver = Server} = _To, _},
@@ -470,22 +415,16 @@ check_packet(_, _User, _Server, _UserList,
     allow;
 check_packet(_, User, Server,
             #userlist{list = List, needdb = NeedDb},
-            {From, To, #xmlel{name = PName, attrs = Attrs}}, Dir) ->
+            {From, To, Packet}, Dir) ->
     case List of
       [] -> allow;
       _ ->
-         PType = case PName of
-                   <<"message">> -> message;
-                   <<"iq">> -> iq;
-                   <<"presence">> ->
-                       case fxml:get_attr_s(<<"type">>, Attrs) of
-                         %% notification
-                         <<"">> -> presence;
-                         <<"unavailable">> -> presence;
-                         %% subscribe, subscribed, unsubscribe,
-                         %% unsubscribed, error, probe, or other
-                         _ -> other
-                       end
+         PType = case Packet of
+                   #message{} -> message;
+                   #iq{} -> iq;
+                   #presence{type = available} -> presence;
+                   #presence{type = unavailable} -> presence;
+                   _ -> other
                  end,
          PType2 = case {PType, Dir} of
                     {message, in} -> message;
@@ -511,6 +450,10 @@ check_packet(_, User, Server,
                           Groups)
     end.
 
+-spec check_packet_aux([listitem()],
+                      message | iq | presence_in | presence_out | other,
+                      ljid(), none | both | from | to, [binary()]) ->
+                             allow | deny.
 %% Ptype = mesage | iq | presence_in | presence_out | other
 check_packet_aux([], _PType, _JID, _Subscription,
                 _Groups) ->
@@ -536,6 +479,9 @@ check_packet_aux([Item | List], PType, JID,
          check_packet_aux(List, PType, JID, Subscription, Groups)
     end.
 
+-spec is_ptype_match(listitem(),
+                    message | iq | presence_in | presence_out | other) ->
+                           boolean().
 is_ptype_match(Item, PType) ->
     case Item#listitem.match_all of
       true -> true;
@@ -549,6 +495,8 @@ is_ptype_match(Item, PType) ->
          end
     end.
 
+-spec is_type_match(jid | subscription | group, listitem_value(),
+                   ljid(), none | both | from | to, [binary()]) -> boolean().
 is_type_match(Type, Value, JID, Subscription, Groups) ->
     case Type of
       jid ->
@@ -575,6 +523,7 @@ remove_user(User, Server) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:remove_user(LUser, LServer).
 
+-spec updated_list(userlist(), userlist(), userlist()) -> userlist().
 updated_list(_, #userlist{name = OldName} = Old,
             #userlist{name = NewName} = New) ->
     if OldName == NewName -> New;
index 4026b7f64460c1c3f26ddd9b8080aa10a8bf02e9..1a9172b5a9871798c3db445e88207e96357f7f6b 100644 (file)
@@ -35,11 +35,7 @@ process_lists_get(LUser, LServer) ->
        {'EXIT', _Reason} -> error;
        [] -> {none, []};
        [#privacy{default = Default, lists = Lists}] ->
-           LItems = lists:map(fun ({N, _}) ->
-                                      #xmlel{name = <<"list">>,
-                                             attrs = [{<<"name">>, N}],
-                                             children = []}
-                              end, Lists),
+           LItems = lists:map(fun ({N, _}) -> N end, Lists),
            {Default, LItems}
     end.
 
@@ -54,7 +50,15 @@ process_list_get(LUser, LServer, Name) ->
            end
     end.
 
-process_default_set(LUser, LServer, {value, Name}) ->
+process_default_set(LUser, LServer, none) ->
+    F = fun () ->
+               case mnesia:read({privacy, {LUser, LServer}}) of
+                   [] -> ok;
+                   [R] -> mnesia:write(R#privacy{default = none})
+               end
+       end,
+    mnesia:transaction(F);
+process_default_set(LUser, LServer, Name) ->
     F = fun () ->
                case mnesia:read({privacy, {LUser, LServer}}) of
                    [] -> not_found;
@@ -68,14 +72,6 @@ process_default_set(LUser, LServer, {value, Name}) ->
                        end
                end
        end,
-    mnesia:transaction(F);
-process_default_set(LUser, LServer, false) ->
-    F = fun () ->
-               case mnesia:read({privacy, {LUser, LServer}}) of
-                   [] -> ok;
-                   [R] -> mnesia:write(R#privacy{default = none})
-               end
-       end,
     mnesia:transaction(F).
 
 process_active_set(LUser, LServer, Name) ->
index 0c43e74f9d7b9e1f61b6896aa292e5730838a1a9..40e92005cec0acfbe678241da00ac4bad6286333 100644 (file)
@@ -31,12 +31,7 @@ init(_Host, _Opts) ->
 process_lists_get(LUser, LServer) ->
     case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of
         {ok, #privacy{default = Default, lists = Lists}} ->
-            LItems = lists:map(fun ({N, _}) ->
-                                       #xmlel{name = <<"list">>,
-                                              attrs = [{<<"name">>, N}],
-                                              children = []}
-                               end,
-                               Lists),
+            LItems = lists:map(fun ({N, _}) -> N end, Lists),
             {Default, LItems};
         {error, notfound} ->
             {none, []};
@@ -57,7 +52,15 @@ process_list_get(LUser, LServer, Name) ->
             error
     end.
 
-process_default_set(LUser, LServer, {value, Name}) ->
+process_default_set(LUser, LServer, none) ->
+    {atomic,
+     case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of
+         {ok, R} ->
+             ejabberd_riak:put(R#privacy{default = none}, privacy_schema());
+         {error, _} ->
+             ok
+     end};
+process_default_set(LUser, LServer, Name) ->
     {atomic,
      case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of
          {ok, #privacy{lists = Lists} = P} ->
@@ -71,14 +74,6 @@ process_default_set(LUser, LServer, {value, Name}) ->
              end;
          {error, _} ->
              not_found
-     end};
-process_default_set(LUser, LServer, false) ->
-    {atomic,
-     case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of
-         {ok, R} ->
-             ejabberd_riak:put(R#privacy{default = none}, privacy_schema());
-         {error, _} ->
-             ok
      end}.
 
 process_active_set(LUser, LServer, Name) ->
index 6da917e9dd5f45e20765c3659e74e2dc4c8c443d..66926f23680fa43e7e27ecf0a7de08b4ebb039b5 100644 (file)
@@ -47,12 +47,7 @@ process_lists_get(LUser, LServer) ->
              end,
     case catch sql_get_privacy_list_names(LUser, LServer) of
       {selected, Names} ->
-         LItems = lists:map(fun ({N}) ->
-                                    #xmlel{name = <<"list">>,
-                                           attrs = [{<<"name">>, N}],
-                                           children = []}
-                            end,
-                            Names),
+         LItems = lists:map(fun ({N}) -> N end, Names),
          {Default, LItems};
       _ -> error
     end.
@@ -69,7 +64,15 @@ process_list_get(LUser, LServer, Name) ->
       _ -> error
     end.
 
-process_default_set(LUser, LServer, {value, Name}) ->
+process_default_set(LUser, LServer, none) ->
+    case catch sql_unset_default_privacy_list(LUser,
+                                             LServer)
+       of
+      {'EXIT', _Reason} -> {atomic, error};
+      {error, _Reason} -> {atomic, error};
+      _ -> {atomic, ok}
+    end;
+process_default_set(LUser, LServer, Name) ->
     F = fun () ->
                case sql_get_privacy_list_names_t(LUser) of
                  {selected, []} -> not_found;
@@ -80,15 +83,7 @@ process_default_set(LUser, LServer, {value, Name}) ->
                      end
                end
        end,
-    sql_queries:sql_transaction(LServer, F);
-process_default_set(LUser, LServer, false) ->
-    case catch sql_unset_default_privacy_list(LUser,
-                                             LServer)
-       of
-      {'EXIT', _Reason} -> {atomic, error};
-      {error, _Reason} -> {atomic, error};
-      _ -> {atomic, ok}
-    end.
+    sql_queries:sql_transaction(LServer, F).
 
 process_active_set(LUser, LServer, Name) ->
     case catch sql_get_privacy_list_id(LUser, LServer, Name) of
index f0e4632f6af540789bebe19167edc90f8ba80ca2..28d49bb3f94733fdbcfd7680cff84292dbd05080 100644 (file)
 
 -behaviour(gen_mod).
 
--export([start/2, stop/1, process_sm_iq/3, import/3,
+-export([start/2, stop/1, process_sm_iq/1, import/3,
         remove_user/2, get_data/2, export/1, import/1,
         mod_opt_type/1, set_data/3, depends/2]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 -include("mod_private.hrl").
 
 -callback init(binary(), gen_mod:opts()) -> any().
 -callback set_data(binary(), binary(), [{binary(), xmlel()}]) -> {atomic, any()}.
 -callback get_data(binary(), binary(), binary()) -> {ok, xmlel()} | error.
 -callback get_all_data(binary(), binary()) -> [xmlel()].
-    
--define(Xmlel_Query(Attrs, Children),
-       #xmlel{name = <<"query">>, attrs = Attrs,
-              children = Children}).
+-callback remove_user(binary(), binary()) -> {atomic, any()}.
 
 start(Host, Opts) ->
     IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
@@ -67,90 +64,55 @@ stop(Host) ->
     gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
                                     ?NS_PRIVATE).
 
-process_sm_iq(#jid{luser = LUser, lserver = LServer},
-             #jid{luser = LUser, lserver = LServer}, #iq{lang = Lang} = IQ)
-    when IQ#iq.type == set ->
-    case IQ#iq.sub_el of
-      #xmlel{name = <<"query">>, children = Xmlels} ->
-         case filter_xmlels(Xmlels) of
-           [] ->
-               Txt = <<"No private data found in this query">>,
-               IQ#iq{type = error,
-                     sub_el = [IQ#iq.sub_el, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)]};
-           Data ->
-               set_data(LUser, LServer, Data),
-               IQ#iq{type = result, sub_el = []}
-         end;
-      _ ->
-         Txt = <<"No query found">>,
-         IQ#iq{type = error,
-               sub_el = [IQ#iq.sub_el, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)]}
+-spec process_sm_iq(iq()) -> iq().
+process_sm_iq(#iq{type = Type, lang = Lang,
+                 from = #jid{luser = LUser, lserver = LServer},
+                 to = #jid{luser = LUser, lserver = LServer},
+                 sub_els = [#private{xml_els = Els0}]} = IQ) ->
+    case filter_xmlels(Els0) of
+       [] ->
+           Txt = <<"No private data found in this query">>,
+           xmpp:make_error(IQ, xmpp:err_bad_format(Txt, Lang));
+       Data when Type == set ->
+           set_data(LUser, LServer, Data),
+           xmpp:make_iq_result(IQ);
+       Data when Type == get ->
+           StorageEls = get_data(LUser, LServer, Data),
+           xmpp:make_iq_result(IQ, #private{xml_els = StorageEls})
     end;
-%%
-process_sm_iq(#jid{luser = LUser, lserver = LServer},
-             #jid{luser = LUser, lserver = LServer}, #iq{lang = Lang} = IQ)
-    when IQ#iq.type == get ->
-    case IQ#iq.sub_el of
-      #xmlel{name = <<"query">>, attrs = Attrs,
-            children = Xmlels} ->
-         case filter_xmlels(Xmlels) of
-           [] ->
-               Txt = <<"No private data found in this query">>,
-               IQ#iq{type = error,
-                     sub_el = [IQ#iq.sub_el, ?ERRT_BAD_FORMAT(Lang, Txt)]};
-           Data ->
-               case catch get_data(LUser, LServer, Data) of
-                 {'EXIT', _Reason} ->
-                     Txt = <<"Database failure">>,
-                     IQ#iq{type = error,
-                           sub_el =
-                               [IQ#iq.sub_el, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]};
-                 Storage_Xmlels ->
-                     IQ#iq{type = result,
-                           sub_el = [?Xmlel_Query(Attrs, Storage_Xmlels)]}
-               end
-         end;
-      _ ->
-         Txt = <<"No query found">>,
-         IQ#iq{type = error,
-               sub_el = [IQ#iq.sub_el, ?ERRT_BAD_FORMAT(Lang, Txt)]}
-    end;
-%%
-process_sm_iq(_From, _To, #iq{lang = Lang} = IQ) ->
+process_sm_iq(#iq{lang = Lang} = IQ) ->
     Txt = <<"Query to another users is forbidden">>,
-    IQ#iq{type = error,
-         sub_el = [IQ#iq.sub_el, ?ERRT_FORBIDDEN(Lang, Txt)]}.
-
-filter_xmlels(Xmlels) -> filter_xmlels(Xmlels, []).
-
-filter_xmlels([], Data) -> lists:reverse(Data);
-filter_xmlels([#xmlel{attrs = Attrs} = Xmlel | Xmlels],
-             Data) ->
-    case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-      <<"">> -> [];
-      XmlNS -> filter_xmlels(Xmlels, [{XmlNS, Xmlel} | Data])
-    end;
-filter_xmlels([_ | Xmlels], Data) ->
-    filter_xmlels(Xmlels, Data).
-
+    xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang)).
+
+-spec filter_xmlels([xmlel()]) -> [{binary(), xmlel()}].
+filter_xmlels(Els) ->
+    lists:flatmap(
+      fun(#xmlel{} = El) ->
+             case fxml:get_tag_attr_s(<<"xmlns">>, El) of
+                 <<"">> -> [];
+                 NS -> [{NS, El}]
+             end
+      end, Els).
+
+-spec set_data(binary(), binary(), [{binary(), xmlel()}]) -> {atomic, any()}.
 set_data(LUser, LServer, Data) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:set_data(LUser, LServer, Data).
 
+-spec get_data(binary(), binary(), [{binary(), xmlel()}]) -> [xmlel()].
 get_data(LUser, LServer, Data) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
-    get_data(LUser, LServer, Data, Mod, []).
-
-get_data(_LUser, _LServer, [], _Mod, Storage_Xmlels) ->
-    lists:reverse(Storage_Xmlels);
-get_data(LUser, LServer, [{XmlNS, Xmlel} | Data], Mod, Storage_Xmlels) ->
-    case Mod:get_data(LUser, LServer, XmlNS) of
-       {ok, Storage_Xmlel} ->
-           get_data(LUser, LServer, Data, Mod, [Storage_Xmlel | Storage_Xmlels]);
-       error ->
-           get_data(LUser, LServer, Data, Mod, [Xmlel | Storage_Xmlels])
-    end.
-
+    lists:map(
+      fun({NS, El}) ->
+             case Mod:get_data(LUser, LServer, NS) of
+                 {ok, StorageEl} ->
+                     StorageEl;
+                 error ->
+                     El
+             end
+      end, Data).
+
+-spec get_data(binary(), binary()) -> [xmlel()].
 get_data(LUser, LServer) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:get_all_data(LUser, LServer).
index a75041bc7335789cb8cc53f3e3b0af662024b3e5..58dc51983d173ef60c5341316a8c7ac05992cf02 100644 (file)
 
 -behaviour(gen_mod).
 
--export([start/2, stop/1, process_iq/3, export/1,
-        import/1, process_local_iq/3, get_user_roster/2,
+-export([start/2, stop/1, process_iq/1, export/1,
+        import/1, process_local_iq/1, get_user_roster/2,
         import/3, get_subscription_lists/3, get_roster/2,
         get_in_pending_subscriptions/3, in_subscription/6,
         out_subscription/4, set_items/3, remove_user/2,
-        get_jid_info/4, item_to_xml/1, webadmin_page/3,
+        get_jid_info/4, encode_item/1, webadmin_page/3,
         webadmin_user/4, get_versioning_feature/2,
         roster_versioning_enabled/1, roster_version/2,
         mod_opt_type/1, set_roster/1, depends/2]).
@@ -54,7 +54,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -include("mod_roster.hrl").
 
@@ -139,24 +139,23 @@ stop(Host) ->
 depends(_Host, _Opts) ->
     [].
 
-process_iq(From, To, IQ) when ((From#jid.luser == <<"">>) andalso (From#jid.resource == <<"">>)) ->
-    process_iq_manager(From, To, IQ);
+process_iq(#iq{from = #jid{luser = <<"">>},
+              to = #jid{resource = <<"">>}} = IQ) ->
+    process_iq_manager(IQ);
 
-process_iq(From, To, IQ) ->
-    #iq{sub_el = SubEl, lang = Lang} = IQ,
+process_iq(#iq{from = From, lang = Lang} = IQ) ->
     #jid{lserver = LServer} = From,
     case lists:member(LServer, ?MYHOSTS) of
-      true -> process_local_iq(From, To, IQ);
+      true -> process_local_iq(IQ);
       _ ->
          Txt = <<"The query is only allowed from local users">>,
-         IQ#iq{type = error,
-               sub_el = [SubEl, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)]}
+         xmpp:make_error(IQ, xmpp:err_item_not_found(Txt, Lang))
     end.
 
-process_local_iq(From, To, #iq{type = Type} = IQ) ->
+process_local_iq(#iq{type = Type} = IQ) ->
     case Type of
-      set -> try_process_iq_set(From, To, IQ);
-      get -> process_iq_get(From, To, IQ)
+      set -> try_process_iq_set(IQ);
+      get -> process_iq_get(IQ)
     end.
 
 roster_hash(Items) ->
@@ -179,10 +178,7 @@ roster_version_on_db(Host) ->
 get_versioning_feature(Acc, Host) ->
     case roster_versioning_enabled(Host) of
       true ->
-         Feature = #xmlel{name = <<"ver">>,
-                          attrs = [{<<"xmlns">>, ?NS_ROSTER_VER}],
-                          children = []},
-         [Feature | Acc];
+         [#rosterver_feature{}|Acc];
       false -> []
     end.
 
@@ -221,82 +217,61 @@ write_roster_version(LUser, LServer, InTransaction) ->
 %%     - roster versioning is not used by the client OR
 %%     - roster versioning is used by server and client, BUT the server isn't storing versions on db OR
 %%     - the roster version from client don't match current version.
-process_iq_get(From, To, #iq{sub_el = SubEl} = IQ) ->
+process_iq_get(#iq{from = From, to = To, lang = Lang,
+                  sub_els = [#roster_query{ver = RequestedVersion}]} = IQ) ->
     LUser = From#jid.luser,
     LServer = From#jid.lserver,
     US = {LUser, LServer},
-    try {ItemsToSend, VersionToSend} = case
-                                        {fxml:get_tag_attr(<<"ver">>, SubEl),
-                                         roster_versioning_enabled(LServer),
-                                         roster_version_on_db(LServer)}
-                                          of
-                                        {{value, RequestedVersion}, true,
-                                         true} ->
-                                            case read_roster_version(LUser,
-                                                                     LServer)
-                                                of
-                                              error ->
-                                                  RosterVersion =
-                                                      write_roster_version(LUser,
-                                                                           LServer),
-                                                  {lists:map(fun item_to_xml/1,
-                                                             ejabberd_hooks:run_fold(roster_get,
-                                                                                     To#jid.lserver,
-                                                                                     [],
-                                                                                     [US])),
-                                                   RosterVersion};
-                                              RequestedVersion ->
-                                                  {false, false};
-                                              NewVersion ->
-                                                  {lists:map(fun item_to_xml/1,
-                                                             ejabberd_hooks:run_fold(roster_get,
-                                                                                     To#jid.lserver,
-                                                                                     [],
-                                                                                     [US])),
-                                                   NewVersion}
-                                            end;
-                                        {{value, RequestedVersion}, true,
-                                         false} ->
-                                            RosterItems =
-                                                ejabberd_hooks:run_fold(roster_get,
-                                                                        To#jid.lserver,
-                                                                        [],
-                                                                        [US]),
-                                            case roster_hash(RosterItems) of
-                                              RequestedVersion ->
-                                                  {false, false};
-                                              New ->
-                                                  {lists:map(fun item_to_xml/1,
-                                                             RosterItems),
-                                                   New}
-                                            end;
-                                        _ ->
-                                            {lists:map(fun item_to_xml/1,
-                                                       ejabberd_hooks:run_fold(roster_get,
-                                                                               To#jid.lserver,
-                                                                               [],
-                                                                               [US])),
-                                             false}
-                                      end,
-       IQ#iq{type = result,
-             sub_el =
-                 case {ItemsToSend, VersionToSend} of
-                   {false, false} -> [];
-                   {Items, false} ->
-                       [#xmlel{name = <<"query">>,
-                               attrs = [{<<"xmlns">>, ?NS_ROSTER}],
-                               children = Items}];
-                   {Items, Version} ->
-                       [#xmlel{name = <<"query">>,
-                               attrs =
-                                   [{<<"xmlns">>, ?NS_ROSTER},
-                                    {<<"ver">>, Version}],
-                               children = Items}]
-                 end}
-    catch
-      _:_ ->
-         IQ#iq{type = error,
-               sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
+    try {ItemsToSend, VersionToSend} =
+            case {roster_versioning_enabled(LServer),
+                  roster_version_on_db(LServer)} of
+                {true, true} when RequestedVersion /= undefined ->
+                    case read_roster_version(LUser, LServer) of
+                        error ->
+                            RosterVersion = write_roster_version(LUser, LServer),
+                            {lists:map(fun encode_item/1,
+                                       ejabberd_hooks:run_fold(
+                                         roster_get, To#jid.lserver, [], [US])),
+                             RosterVersion};
+                        RequestedVersion ->
+                            {false, false};
+                        NewVersion ->
+                            {lists:map(fun encode_item/1,
+                                       ejabberd_hooks:run_fold(
+                                         roster_get, To#jid.lserver, [], [US])),
+                             NewVersion}
+                    end;
+                {true, false} when RequestedVersion /= undefined ->
+                    RosterItems = ejabberd_hooks:run_fold(
+                                    roster_get, To#jid.lserver, [], [US]),
+                    case roster_hash(RosterItems) of
+                        RequestedVersion ->
+                            {false, false};
+                        New ->
+                            {lists:map(fun encode_item/1, RosterItems), New}
+                    end;
+                _ ->
+                    {lists:map(fun encode_item/1,
+                               ejabberd_hooks:run_fold(
+                                 roster_get, To#jid.lserver, [], [US])),
+                     false}
+            end,
+        xmpp:make_iq_result(
+          IQ,
+          case {ItemsToSend, VersionToSend} of
+              {false, false} ->
+                  undefined;
+              {Items, false} ->
+                  #roster_query{items = Items};
+              {Items, Version} ->
+                  #roster_query{items = Items,
+                                ver = Version}
+          end)
+    catch E:R ->
+           ?ERROR_MSG("failed to process roster get for ~s: ~p",
+                      [jid:to_string(From), {E, {R, erlang:get_stacktrace()}}]),
+           Txt = <<"Roster module has failed">>,
+           xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang))
     end.
 
 get_user_roster(Acc, {LUser, LServer}) ->
@@ -320,143 +295,82 @@ set_roster(#roster{us = {LUser, LServer}, jid = LJID} = Item) ->
              roster_subscribe_t(LUser, LServer, LJID, Item)
       end).
 
-item_to_xml(Item) ->
-    Attrs1 = [{<<"jid">>,
-              jid:to_string(Item#roster.jid)}],
-    Attrs2 = case Item#roster.name of
-              <<"">> -> Attrs1;
-              Name -> [{<<"name">>, Name} | Attrs1]
-            end,
-    Attrs3 = case Item#roster.subscription of
-              none -> [{<<"subscription">>, <<"none">>} | Attrs2];
-              from -> [{<<"subscription">>, <<"from">>} | Attrs2];
-              to -> [{<<"subscription">>, <<"to">>} | Attrs2];
-              both -> [{<<"subscription">>, <<"both">>} | Attrs2];
-              remove -> [{<<"subscription">>, <<"remove">>} | Attrs2]
-            end,
-    Attrs4 = case ask_to_pending(Item#roster.ask) of
-              out -> [{<<"ask">>, <<"subscribe">>} | Attrs3];
-              both -> [{<<"ask">>, <<"subscribe">>} | Attrs3];
-              _ -> Attrs3
-            end,
-    SubEls1 = lists:map(fun (G) ->
-                               #xmlel{name = <<"group">>, attrs = [],
-                                      children = [{xmlcdata, G}]}
-                       end,
-                       Item#roster.groups),
-    SubEls = SubEls1 ++ Item#roster.xs,
-    #xmlel{name = <<"item">>, attrs = Attrs4,
-          children = SubEls}.
+encode_item(Item) ->
+    #roster_item{jid = jid:make(Item#roster.jid),
+                name = Item#roster.name,
+                subscription = Item#roster.subscription,
+                ask = case ask_to_pending(Item#roster.ask) of
+                          out -> subscribe;
+                          both -> subscribe;
+                          _ -> undefined
+                      end,
+                groups = Item#roster.groups}.
+
+decode_item(#roster_item{} = Item, R, Managed) ->
+    R#roster{jid = jid:tolower(Item#roster_item.jid),
+            name = Item#roster_item.name,
+            subscription = case Item#roster_item.subscription of
+                               remove -> remove;
+                               Sub when Managed -> Sub;
+                               _ -> undefined
+                           end,
+            groups = Item#roster_item.groups}.
 
 get_roster_by_jid_t(LUser, LServer, LJID) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:get_roster_by_jid(LUser, LServer, LJID).
 
-try_process_iq_set(From, To, #iq{sub_el = SubEl, lang = Lang} = IQ) ->
+try_process_iq_set(#iq{from = From, lang = Lang} = IQ) ->
     #jid{server = Server} = From,
     Access = gen_mod:get_module_opt(Server, ?MODULE, access, fun(A) -> A end, all),
     case acl:match_rule(Server, Access, From) of
        deny ->
            Txt = <<"Denied by ACL">>,
-           IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
+           xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
        allow ->
-           process_iq_set(From, To, IQ)
+           process_iq_set(IQ)
     end.
 
-process_iq_set(From, To, #iq{sub_el = SubEl, id = Id} = IQ) ->
-    #xmlel{children = Els} = SubEl,
+process_iq_set(#iq{from = From, to = To, id = Id,
+                  sub_els = [#roster_query{items = Items}]} = IQ) ->
     Managed = is_managed_from_id(Id),
-    lists:foreach(fun (El) -> process_item_set(From, To, El, Managed)
+    lists:foreach(fun (Item) -> process_item_set(From, To, Item, Managed)
                  end,
-                 Els),
-    IQ#iq{type = result, sub_el = []}.
-
-process_item_set(From, To,
-                #xmlel{attrs = Attrs, children = Els}, Managed) ->
-    JID1 = jid:from_string(fxml:get_attr_s(<<"jid">>,
-                                            Attrs)),
-    #jid{user = User, luser = LUser, lserver = LServer} =
-       From,
-    case JID1 of
-      error -> ok;
-      _ ->
-         LJID = jid:tolower(JID1),
-         F = fun () ->
-                     Item = get_roster_by_jid_t(LUser, LServer, LJID),
-                     Item1 = process_item_attrs_managed(Item, Attrs, Managed),
-                     Item2 = process_item_els(Item1, Els),
-                     Item3 = ejabberd_hooks:run_fold(roster_process_item,
-                                                     LServer, Item2,
-                                                     [LServer]),
-                     case Item3#roster.subscription of
-                       remove -> del_roster_t(LUser, LServer, LJID);
-                       _ -> update_roster_t(LUser, LServer, LJID, Item3)
-                     end,
-                      send_itemset_to_managers(From, Item3, Managed),
-                     case roster_version_on_db(LServer) of
-                       true -> write_roster_version_t(LUser, LServer);
-                       false -> ok
-                     end,
-                     {Item, Item3}
-             end,
-         case transaction(LServer, F) of
-           {atomic, {OldItem, Item}} ->
-               push_item(User, LServer, To, Item),
-               case Item#roster.subscription of
-                 remove ->
-                     send_unsubscribing_presence(From, OldItem), ok;
-                 _ -> ok
-               end;
-           E ->
-               ?DEBUG("ROSTER: roster item set error: ~p~n", [E]), ok
-         end
-    end;
-process_item_set(_From, _To, _, _Managed) -> ok.
+                 Items),
+    xmpp:make_iq_result(IQ).
 
-process_item_attrs(Item, [{Attr, Val} | Attrs]) ->
-    case Attr of
-      <<"jid">> ->
-         case jid:from_string(Val) of
-           error -> process_item_attrs(Item, Attrs);
-           JID1 ->
-               JID = {JID1#jid.luser, JID1#jid.lserver,
-                      JID1#jid.lresource},
-               process_item_attrs(Item#roster{jid = JID}, Attrs)
-         end;
-      <<"name">> ->
-         process_item_attrs(Item#roster{name = Val}, Attrs);
-      <<"subscription">> ->
-         case Val of
-           <<"remove">> ->
-               process_item_attrs(Item#roster{subscription = remove},
-                                  Attrs);
-           _ -> process_item_attrs(Item, Attrs)
-         end;
-      <<"ask">> -> process_item_attrs(Item, Attrs);
-      _ -> process_item_attrs(Item, Attrs)
-    end;
-process_item_attrs(Item, []) -> Item.
-
-process_item_els(Item,
-                [#xmlel{name = Name, attrs = Attrs, children = SEls}
-                 | Els]) ->
-    case Name of
-      <<"group">> ->
-         Groups = [fxml:get_cdata(SEls) | Item#roster.groups],
-         process_item_els(Item#roster{groups = Groups}, Els);
-      _ ->
-         case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-           <<"">> -> process_item_els(Item, Els);
-           _ ->
-               XEls = [#xmlel{name = Name, attrs = Attrs,
-                              children = SEls}
-                       | Item#roster.xs],
-               process_item_els(Item#roster{xs = XEls}, Els)
-         end
+process_item_set(From, To, #roster_item{jid = JID1} = QueryItem, Managed) ->
+    #jid{user = User, luser = LUser, lserver = LServer} = From,
+    LJID = jid:tolower(JID1),
+    F = fun () ->
+               Item = get_roster_by_jid_t(LUser, LServer, LJID),
+               Item2 = decode_item(QueryItem, Item, Managed),
+               Item3 = ejabberd_hooks:run_fold(roster_process_item,
+                                               LServer, Item2,
+                                               [LServer]),
+               case Item3#roster.subscription of
+                   remove -> del_roster_t(LUser, LServer, LJID);
+                   _ -> update_roster_t(LUser, LServer, LJID, Item3)
+               end,
+               send_itemset_to_managers(From, Item3, Managed),
+               case roster_version_on_db(LServer) of
+                   true -> write_roster_version_t(LUser, LServer);
+                   false -> ok
+               end,
+               {Item, Item3}
+       end,
+    case transaction(LServer, F) of
+       {atomic, {OldItem, Item}} ->
+           push_item(User, LServer, To, Item),
+           case Item#roster.subscription of
+               remove ->
+                   send_unsubscribing_presence(From, OldItem), ok;
+               _ -> ok
+           end;
+       E ->
+           ?DEBUG("ROSTER: roster item set error: ~p~n", [E]), ok
     end;
-process_item_els(Item, [{xmlcdata, _} | Els]) ->
-    process_item_els(Item, Els);
-process_item_els(Item, []) -> Item.
+process_item_set(_From, _To, _, _Managed) -> ok.
 
 push_item(User, Server, From, Item) ->
     ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>),
@@ -480,21 +394,19 @@ push_item(User, Server, Resource, From, Item) ->
 
 push_item(User, Server, Resource, From, Item,
          RosterVersion) ->
-    ExtraAttrs = case RosterVersion of
-                  not_found -> [];
-                  _ -> [{<<"ver">>, RosterVersion}]
-                end,
-    ResIQ = #iq{type = set, xmlns = ?NS_ROSTER,
+    Ver = case RosterVersion of
+             not_found -> undefined;
+             _ -> RosterVersion
+         end,
+    ResIQ = #iq{type = set,
 %% @doc Roster push, calculate and include the version attribute.
 %% TODO: don't push to those who didn't load roster
                id = <<"push", (randoms:get_string())/binary>>,
-               sub_el =
-                   [#xmlel{name = <<"query">>,
-                           attrs = [{<<"xmlns">>, ?NS_ROSTER} | ExtraAttrs],
-                           children = [item_to_xml(Item)]}]},
+               sub_els = [#roster_query{ver = Ver,
+                                        items = [encode_item(Item)]}]},
     ejabberd_router:route(From,
                          jid:make(User, Server, Resource),
-                         jlib:iq_to_xml(ResIQ)).
+                         ResIQ).
 
 push_item_version(Server, User, From, Item,
                  RosterVersion) ->
@@ -598,16 +510,8 @@ process_subscription(Direction, User, Server, JID1,
          case AutoReply of
            none -> ok;
            _ ->
-               T = case AutoReply of
-                     subscribed -> <<"subscribed">>;
-                     unsubscribed -> <<"unsubscribed">>
-                   end,
-               ejabberd_router:route(jid:make(User, Server,
-                                                   <<"">>),
-                                     JID1,
-                                     #xmlel{name = <<"presence">>,
-                                            attrs = [{<<"type">>, T}],
-                                            children = []})
+               ejabberd_router:route(jid:make(User, Server, <<"">>),
+                                     JID1, #presence{type = AutoReply})
          end,
          case Push of
            {push, Item} ->
@@ -769,24 +673,19 @@ send_unsubscribing_presence(From, Item) ->
               _ -> false
             end,
     if IsTo ->
-          send_presence_type(jid:remove_resource(From),
-                             jid:make(Item#roster.jid),
-                             <<"unsubscribe">>);
+           ejabberd_router:route(jid:remove_resource(From),
+                                 jid:make(Item#roster.jid),
+                                 #presence{type = unsubscribe});
        true -> ok
     end,
     if IsFrom ->
-          send_presence_type(jid:remove_resource(From),
-                             jid:make(Item#roster.jid),
-                             <<"unsubscribed">>);
+           ejabberd_router:route(jid:remove_resource(From),
+                                 jid:make(Item#roster.jid),
+                                 #presence{type = unsubscribed});
        true -> ok
     end,
     ok.
 
-send_presence_type(From, To, Type) ->
-    ejabberd_router:route(From, To,
-                         #xmlel{name = <<"presence">>,
-                                attrs = [{<<"type">>, Type}], children = []}).
-
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 set_items(User, Server, SubEl) ->
@@ -809,65 +708,20 @@ del_roster_t(LUser, LServer, LJID) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:del_roster(LUser, LServer, LJID).
 
-process_item_set_t(LUser, LServer,
-                  #xmlel{attrs = Attrs, children = Els}) ->
-    JID1 = jid:from_string(fxml:get_attr_s(<<"jid">>,
-                                            Attrs)),
-    case JID1 of
-      error -> ok;
-      _ ->
-         JID = {JID1#jid.user, JID1#jid.server,
-                JID1#jid.resource},
-         LJID = {JID1#jid.luser, JID1#jid.lserver,
-                 JID1#jid.lresource},
-         Item = #roster{usj = {LUser, LServer, LJID},
-                        us = {LUser, LServer}, jid = JID},
-         Item1 = process_item_attrs_ws(Item, Attrs),
-         Item2 = process_item_els(Item1, Els),
-         case Item2#roster.subscription of
-           remove -> del_roster_t(LUser, LServer, LJID);
-           _ -> update_roster_t(LUser, LServer, LJID, Item2)
-         end
+process_item_set_t(LUser, LServer, #roster_item{jid = JID1} = QueryItem) ->
+    JID = {JID1#jid.user, JID1#jid.server,
+          JID1#jid.resource},
+    LJID = {JID1#jid.luser, JID1#jid.lserver,
+           JID1#jid.lresource},
+    Item = #roster{usj = {LUser, LServer, LJID},
+                  us = {LUser, LServer}, jid = JID},
+    Item2 = decode_item(QueryItem, Item, _Managed = true),
+    case Item2#roster.subscription of
+       remove -> del_roster_t(LUser, LServer, LJID);
+       _ -> update_roster_t(LUser, LServer, LJID, Item2)
     end;
 process_item_set_t(_LUser, _LServer, _) -> ok.
 
-process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
-    case Attr of
-      <<"jid">> ->
-         case jid:from_string(Val) of
-           error -> process_item_attrs_ws(Item, Attrs);
-           JID1 ->
-               JID = {JID1#jid.luser, JID1#jid.lserver,
-                      JID1#jid.lresource},
-               process_item_attrs_ws(Item#roster{jid = JID}, Attrs)
-         end;
-      <<"name">> ->
-         process_item_attrs_ws(Item#roster{name = Val}, Attrs);
-      <<"subscription">> ->
-         case Val of
-           <<"remove">> ->
-               process_item_attrs_ws(Item#roster{subscription =
-                                                     remove},
-                                     Attrs);
-           <<"none">> ->
-               process_item_attrs_ws(Item#roster{subscription = none},
-                                     Attrs);
-           <<"both">> ->
-               process_item_attrs_ws(Item#roster{subscription = both},
-                                     Attrs);
-           <<"from">> ->
-               process_item_attrs_ws(Item#roster{subscription = from},
-                                     Attrs);
-           <<"to">> ->
-               process_item_attrs_ws(Item#roster{subscription = to},
-                                     Attrs);
-           _ -> process_item_attrs_ws(Item, Attrs)
-         end;
-      <<"ask">> -> process_item_attrs_ws(Item, Attrs);
-      _ -> process_item_attrs_ws(Item, Attrs)
-    end;
-process_item_attrs_ws(Item, []) -> Item.
-
 get_in_pending_subscriptions(Ls, User, Server) ->
     LServer = jid:nameprep(Server),
     Mod = gen_mod:db_mod(LServer, ?MODULE),
@@ -876,31 +730,18 @@ get_in_pending_subscriptions(Ls, User, Server) ->
 get_in_pending_subscriptions(Ls, User, Server, Mod) ->
     JID = jid:make(User, Server, <<"">>),
     Result = Mod:get_only_items(JID#jid.luser, JID#jid.lserver),
-    Ls ++ lists:map(fun (R) ->
-                            Message = R#roster.askmessage,
-                            Status = if is_binary(Message) -> (Message);
-                                        true -> <<"">>
-                                     end,
-                            #xmlel{name = <<"presence">>,
-                                   attrs =
-                                       [{<<"from">>,
-                                         jid:to_string(R#roster.jid)},
-                                        {<<"to">>, jid:to_string(JID)},
-                                        {<<"type">>, <<"subscribe">>}],
-                                   children =
-                                       [#xmlel{name = <<"status">>,
-                                               attrs = [],
-                                               children =
-                                                   [{xmlcdata, Status}]}]}
-                    end,
-                    lists:filter(fun (R) ->
-                                         case R#roster.ask of
-                                             in -> true;
-                                             both -> true;
-                                             _ -> false
-                                         end
-                                 end,
-                                 Result)).
+    Ls ++ lists:flatmap(
+           fun(#roster{ask = Ask} = R) when Ask == in; Ask == both ->
+                   Message = R#roster.askmessage,
+                   Status = if is_binary(Message) -> (Message);
+                               true -> <<"">>
+                            end,
+                   [#presence{from = R#roster.jid, to = JID,
+                              type = subscribe,
+                              status = xmpp:mk_text(Status)}];
+              (_) ->
+                   []
+           end, Result).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -1070,10 +911,7 @@ user_roster_parse_query(User, Server, Items, Query) ->
 user_roster_subscribe_jid(User, Server, JID) ->
     out_subscription(User, Server, JID, subscribe),
     UJID = jid:make(User, Server, <<"">>),
-    ejabberd_router:route(UJID, JID,
-                         #xmlel{name = <<"presence">>,
-                                attrs = [{<<"type">>, <<"subscribe">>}],
-                                children = []}).
+    ejabberd_router:route(UJID, JID, #presence{type = subscribe}).
 
 user_roster_item_parse_query(User, Server, Items,
                             Query) ->
@@ -1089,12 +927,7 @@ user_roster_item_parse_query(User, Server, Items,
                                                 subscribed),
                                UJID = jid:make(User, Server, <<"">>),
                                ejabberd_router:route(UJID, JID1,
-                                                     #xmlel{name =
-                                                                <<"presence">>,
-                                                            attrs =
-                                                                [{<<"type">>,
-                                                                  <<"subscribed">>}],
-                                                            children = []}),
+                                                     #presence{type = subscribed}),
                                throw(submitted);
                            false ->
                                case lists:keysearch(<<"remove",
@@ -1102,29 +935,17 @@ user_roster_item_parse_query(User, Server, Items,
                                                     1, Query)
                                    of
                                  {value, _} ->
-                                     UJID = jid:make(User, Server,
-                                                          <<"">>),
-                                     process_iq_set(UJID, UJID,
-                                                #iq{type = set,
-                                                    sub_el =
-                                                        #xmlel{name =
-                                                                   <<"query">>,
-                                                               attrs =
-                                                                   [{<<"xmlns">>,
-                                                                     ?NS_ROSTER}],
-                                                               children =
-                                                                   [#xmlel{name
-                                                                               =
-                                                                               <<"item">>,
-                                                                           attrs
-                                                                               =
-                                                                               [{<<"jid">>,
-                                                                                 jid:to_string(JID)},
-                                                                                {<<"subscription">>,
-                                                                                 <<"remove">>}],
-                                                                           children
-                                                                               =
-                                                                               []}]}}),
+                                     UJID = jid:make(User, Server),
+                                     RosterItem = #roster_item{
+                                                     jid = jid:make(JID),
+                                                     subscription = remove},
+                                     process_iq_set(
+                                       #iq{type = set,
+                                           from = UJID,
+                                           to = UJID,
+                                           id = randoms:get_string(),
+                                           sub_els = [#roster_query{
+                                                         items = [RosterItem]}]}),
                                      throw(submitted);
                                  false -> ok
                                end
@@ -1144,24 +965,24 @@ webadmin_user(Acc, _User, _Server, Lang) ->
 
 %% Implement XEP-0321 Remote Roster Management
 
-process_iq_manager(From, To, IQ) ->
+process_iq_manager(#iq{from = From, to = To, lang = Lang} = IQ) ->
     %% Check what access is allowed for From to To
     MatchDomain = From#jid.lserver,
     case is_domain_managed(MatchDomain, To#jid.lserver) of
        true ->
-           process_iq_manager2(MatchDomain, To, IQ);
+           process_iq_manager2(MatchDomain, IQ);
        false ->
-           #iq{sub_el = SubEl, lang = Lang} = IQ,
            Txt = <<"Roster management is not allowed from this domain">>,
-           IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}
+           xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang))
     end.
 
-process_iq_manager2(MatchDomain, To, IQ) ->
+process_iq_manager2(MatchDomain, #iq{to = To} = IQ) ->
     %% If IQ is SET, filter the input IQ
     IQFiltered = maybe_filter_request(MatchDomain, IQ),
     %% Call the standard function with reversed JIDs
     IdInitial = IQFiltered#iq.id,
-    ResIQ = process_iq(To, To, IQFiltered#iq{id = <<"roster-remotely-managed">>}),
+    ResIQ = process_iq(IQFiltered#iq{from = To, to = To,
+                                    id = <<"roster-remotely-managed">>}),
     %% Filter the output IQ
     filter_stanza(MatchDomain, ResIQ#iq{id = IdInitial}).
 
@@ -1176,37 +997,13 @@ maybe_filter_request(MatchDomain, IQ) when IQ#iq.type == set ->
 maybe_filter_request(_MatchDomain, IQ) ->
     IQ.
 
-filter_stanza(_MatchDomain, #iq{sub_el = []} = IQ) ->
-    IQ;
-filter_stanza(MatchDomain, #iq{sub_el = [SubEl | _]} = IQ) ->
-    #iq{sub_el = SubElFiltered} = IQRes =
-       filter_stanza(MatchDomain, IQ#iq{sub_el = SubEl}),
-    IQRes#iq{sub_el = [SubElFiltered]};
-filter_stanza(MatchDomain, #iq{sub_el = SubEl} = IQ) ->
-    #xmlel{name = Type, attrs = Attrs, children = Items} = SubEl,
+filter_stanza(MatchDomain,
+             #iq{sub_els = [#roster_query{items = Items} = R]} = IQ) ->
     ItemsFiltered = lists:filter(
-                     fun(Item) ->
-                             is_item_of_domain(MatchDomain, Item) end, Items),
-    SubElFiltered = #xmlel{name=Type, attrs = Attrs, children = ItemsFiltered},
-    IQ#iq{sub_el = SubElFiltered}.
-
-is_item_of_domain(MatchDomain, #xmlel{} = El) ->
-    lists:any(fun(Attr) -> is_jid_of_domain(MatchDomain, Attr) end, El#xmlel.attrs);
-is_item_of_domain(_MatchDomain, {xmlcdata, _}) ->
-    false.
-
-is_jid_of_domain(MatchDomain, {<<"jid">>, JIDString}) ->
-    case jid:from_string(JIDString) of
-       JID when JID#jid.lserver == MatchDomain -> true;
-       _ -> false
-    end;
-is_jid_of_domain(_, _) ->
-    false.
-
-process_item_attrs_managed(Item, Attrs, true) ->
-    process_item_attrs_ws(Item, Attrs);
-process_item_attrs_managed(Item, _Attrs, false) ->
-    process_item_attrs(Item, _Attrs).
+                     fun(#roster_item{jid = #jid{lserver = S}}) ->
+                             S == MatchDomain
+                     end, Items),
+    IQ#iq{sub_els = [R#roster_query{items = ItemsFiltered}]}.
 
 send_itemset_to_managers(_From, _Item, true) ->
     ok;
index 90296f3d809f9de3f81fbb9c5485cb0f6882b617..0aeb6831cfdb7e275b1414b256f37dfebe0bd85d 100644 (file)
 
 -behaviour(gen_mod).
 
--export([start/2, stop/1, process_local_iq/3,
+-export([start/2, stop/1, process_local_iq/1,
         mod_opt_type/1, depends/2]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 start(Host, Opts) ->
     IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
@@ -50,41 +50,18 @@ stop(Host) ->
     gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
                                     ?NS_TIME).
 
-process_local_iq(_From, _To,
-                #iq{type = Type, sub_el = SubEl, lang = Lang} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         Now_universal = calendar:universal_time(),
-         Now_local = calendar:universal_time_to_local_time(Now_universal),
-         {UTC, UTC_diff} = jlib:timestamp_to_iso(Now_universal,
-                                                 utc),
-         Seconds_diff =
-             calendar:datetime_to_gregorian_seconds(Now_local) -
-               calendar:datetime_to_gregorian_seconds(Now_universal),
-         {Hd, Md, _} =
-             calendar:seconds_to_time(abs(Seconds_diff)),
-         {_, TZO_diff} = jlib:timestamp_to_iso({{0, 1, 1},
-                                                {0, 0, 0}},
-                                               {sign(Seconds_diff), {Hd, Md}}),
-         IQ#iq{type = result,
-               sub_el =
-                   [#xmlel{name = <<"time">>,
-                           attrs = [{<<"xmlns">>, ?NS_TIME}],
-                           children =
-                               [#xmlel{name = <<"tzo">>, attrs = [],
-                                       children = [{xmlcdata, TZO_diff}]},
-                                #xmlel{name = <<"utc">>, attrs = [],
-                                       children =
-                                           [{xmlcdata,
-                                              <<UTC/binary,
-                                                UTC_diff/binary>>}]}]}]}
-    end.
-
-sign(N) when N < 0 -> <<"-">>;
-sign(_) -> <<"+">>.
+process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_local_iq(#iq{type = get} = IQ) ->
+    Now = p1_time_compat:timestamp(),
+    Now_universal = calendar:now_to_universal_time(Now),
+    Now_local = calendar:universal_time_to_local_time(Now_universal),
+    Seconds_diff =
+       calendar:datetime_to_gregorian_seconds(Now_local) -
+       calendar:datetime_to_gregorian_seconds(Now_universal),
+    {Hd, Md, _} = calendar:seconds_to_time(abs(Seconds_diff)),
+    xmpp:make_iq_result(IQ, #time{tzo = {Hd, Md}, utc = Now}).
 
 depends(_Host, _Opts) ->
     [].
index aca9d7462ba79e40672424b2b748ed1e9d3142db..de9fce00d1b0d39c72cbf753698c6bbdb625abe3 100644 (file)
 -behaviour(gen_mod).
 
 -export([start/2, init/3, stop/1, get_sm_features/5,
-        process_local_iq/3, process_sm_iq/3, string2lower/1,
+        process_local_iq/1, process_sm_iq/1, string2lower/1,
         remove_user/2, export/1, import/1, import/3, depends/2,
+        process_search/1, process_vcard/1,
+        disco_items/5, disco_features/5, disco_identity/5,
         mod_opt_type/1, set_vcard/3, make_vcard_search/4]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 -include("mod_vcard.hrl").
 
 -define(JUD_MATCHES, 30).
@@ -68,11 +70,30 @@ start(Host, Opts) ->
                                  ?NS_VCARD, ?MODULE, process_sm_iq, IQDisc),
     ejabberd_hooks:add(disco_sm_features, Host, ?MODULE,
                       get_sm_features, 50),
-    MyHost = gen_mod:get_opt_host(Host, Opts,
-                                 <<"vjud.@HOST@">>),
+    MyHost = gen_mod:get_opt_host(Host, Opts, <<"vjud.@HOST@">>),
     Search = gen_mod:get_opt(search, Opts,
                              fun(B) when is_boolean(B) -> B end,
                              false),
+    if Search ->
+           ejabberd_hooks:add(
+             disco_local_items, MyHost, ?MODULE, disco_items, 100),
+           ejabberd_hooks:add(
+             disco_local_features, MyHost, ?MODULE, disco_features, 100),
+           ejabberd_hooks:add(
+             disco_local_identity, MyHost, ?MODULE, disco_identity, 100),
+           gen_iq_handler:add_iq_handler(
+             ejabberd_local, MyHost, ?NS_SEARCH, ?MODULE, process_search, IQDisc),
+           gen_iq_handler:add_iq_handler(
+             ejabberd_local, MyHost, ?NS_VCARD, ?MODULE, process_vcard, IQDisc),
+           gen_iq_handler:add_iq_handler(
+             ejabberd_local, MyHost, ?NS_DISCO_ITEMS, mod_disco,
+             process_local_iq_items, IQDisc),
+           gen_iq_handler:add_iq_handler(
+             ejabberd_local, MyHost, ?NS_DISCO_INFO, mod_disco,
+             process_local_iq_info, IQDisc);
+       true ->
+           ok
+    end,
     register(gen_mod:get_module_proc(Host, ?PROCNAME),
             spawn(?MODULE, init, [MyHost, Host, Search])).
 
@@ -87,12 +108,20 @@ init(Host, ServerHost, Search) ->
 loop(Host, ServerHost) ->
     receive
       {route, From, To, Packet} ->
-         case catch do_route(ServerHost, From, To, Packet) of
+         case catch do_route(From, To, Packet) of
            {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
            _ -> ok
          end,
          loop(Host, ServerHost);
-      stop -> ejabberd_router:unregister_route(Host), ok;
+      stop ->
+           ejabberd_router:unregister_route(Host),
+           ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, disco_items, 50),
+           ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50),
+           ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, disco_identity, 50),
+           gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_SEARCH),
+           gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
+           gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
+           gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO);
       _ -> loop(Host, ServerHost)
     end.
 
@@ -109,12 +138,23 @@ stop(Host) ->
     Proc ! stop,
     {wait, Proc}.
 
+do_route(From, To, #xmlel{name = <<"iq">>} = El) ->
+    ejabberd_router:process_iq(From, To, El);
+do_route(From, To, #iq{} = IQ) ->
+    ejabberd_router:process_iq(From, To, IQ);
+do_route(_, _, _) ->
+    ok.
+
+-spec get_sm_features({error, error()} | empty | {result, [binary()]},
+                     jid(), jid(),
+                     undefined | binary(), undefined | binary()) ->
+                            {error, error()} | empty | {result, [binary()]}.
 get_sm_features({error, _Error} = Acc, _From, _To,
                _Node, _Lang) ->
     Acc;
 get_sm_features(Acc, _From, _To, Node, _Lang) ->
     case Node of
-      <<"">> ->
+      undefined ->
          case Acc of
            {result, Features} ->
                {result, [?NS_DISCO_INFO, ?NS_VCARD | Features]};
@@ -123,67 +163,113 @@ get_sm_features(Acc, _From, _To, Node, _Lang) ->
       _ -> Acc
     end.
 
-process_local_iq(_From, _To,
-                #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         IQ#iq{type = result,
-               sub_el =
-                   [#xmlel{name = <<"vCard">>,
-                           attrs = [{<<"xmlns">>, ?NS_VCARD}],
-                           children =
-                               [#xmlel{name = <<"FN">>, attrs = [],
-                                       children =
-                                           [{xmlcdata, <<"ejabberd">>}]},
-                                #xmlel{name = <<"URL">>, attrs = [],
-                                       children = [{xmlcdata, ?EJABBERD_URI}]},
-                                #xmlel{name = <<"DESC">>, attrs = [],
-                                       children =
-                                           [{xmlcdata,
-                                             <<(translate:translate(Lang,
-                                                                    <<"Erlang Jabber Server">>))/binary,
-                                               "\nCopyright (c) 2002-2016 ProcessOne">>}]},
-                                #xmlel{name = <<"BDAY">>, attrs = [],
-                                       children =
-                                           [{xmlcdata, <<"2002-11-16">>}]}]}]}
-    end.
-
-process_sm_iq(From, To,
-             #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-      set ->
-         #jid{user = User, lserver = LServer} = From,
-         case lists:member(LServer, ?MYHOSTS) of
-           true ->
-               set_vcard(User, LServer, SubEl),
-               IQ#iq{type = result, sub_el = []};
-           false ->
-               Txt = <<"The query is only allowed from local users">>,
-               IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]}
-         end;
-      get ->
-         #jid{luser = LUser, lserver = LServer} = To,
-         case get_vcard(LUser, LServer) of
-           error ->
-               Txt = <<"Database failure">>,
-               IQ#iq{type = error,
-                     sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]};
-           [] ->
-               IQ#iq{type = result,
-                     sub_el = [#xmlel{name = <<"vCard">>,
-                               attrs = [{<<"xmlns">>, ?NS_VCARD}],
-                               children = []}]};
-           Els -> IQ#iq{type = result, sub_el = Els}
-         end
+-spec process_local_iq(iq()) -> iq().
+process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_local_iq(#iq{type = get, lang = Lang} = IQ) ->
+    Desc = translate:translate(Lang, <<"Erlang Jabber Server">>),
+    Copyright = <<"Copyright (c) 2002-2016 ProcessOne">>,
+    xmpp:make_iq_result(
+      IQ, #vcard_temp{fn = <<"ejabberd">>,
+                     url = ?EJABBERD_URI,
+                     desc = <<Desc/binary, $\n, Copyright/binary>>,
+                     bday = <<"2002-11-16">>}).
+
+-spec process_sm_iq(iq()) -> iq().
+process_sm_iq(#iq{type = set, lang = Lang, from = From,
+                 sub_els = [SubEl]} = IQ) ->
+    #jid{user = User, lserver = LServer} = From,
+    case lists:member(LServer, ?MYHOSTS) of
+       true ->
+           set_vcard(User, LServer, SubEl),
+           xmpp:make_iq_result(IQ);
+       false ->
+           Txt = <<"The query is only allowed from local users">>,
+           xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang))
+    end;
+process_sm_iq(#iq{type = get, from = From, to = To, lang = Lang} = IQ) ->
+    #jid{luser = LUser, lserver = LServer} = To,
+    case get_vcard(LUser, LServer) of
+       error ->
+           Txt = <<"Database failure">>,
+           xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang));
+       [] ->
+           xmpp:make_iq_result(IQ, #vcard_temp{});
+       Els ->
+           IQ#iq{type = result, to = From, from = To, sub_els = Els}
     end.
 
+-spec process_vcard(iq()) -> iq().
+process_vcard(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_vcard(#iq{type = get, lang = Lang} = IQ) ->
+    Desc = translate:translate(Lang, <<"ejabberd vCard module">>),
+    Copyright = <<"Copyright (c) 2003-2016 ProcessOne">>,
+    xmpp:make_iq_result(
+      IQ, #vcard_temp{fn = <<"ejabberd/mod_vcard">>,
+                     url = ?EJABBERD_URI,
+                     desc = <<Desc/binary, $\n, Copyright/binary>>}).
+
+-spec process_search(iq()) -> iq().
+process_search(#iq{type = get, to = To, lang = Lang} = IQ) ->
+    xmpp:make_iq_result(IQ, mk_search_form(To, Lang));
+process_search(#iq{type = set, to = To, lang = Lang,
+                  sub_els = [#search{xdata = #xdata{type = submit,
+                                                    fields = Fs}}]} = IQ) ->
+    ServerHost = ejabberd_router:host_of_route(To#jid.lserver),
+    ResultXData = search_result(Lang, To, ServerHost, Fs),
+    xmpp:make_iq_result(IQ, #search{xdata = ResultXData});
+process_search(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Incorrect data form">>,
+    xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang)).
+
+-spec disco_items({error, error()} | {result, [disco_item()]} | empty,
+                 jid(), jid(),
+                 undefined | binary(), undefined | binary()) ->
+                        {error, error()} | {result, [disco_item()]}.
+disco_items(empty, _From, _To, undefined, _Lang) ->
+    {result, []};
+disco_items(empty, _From, _To, _Node, Lang) ->
+    {error, xmpp:err_item_not_found(<<"No services available">>, Lang)};
+disco_items(Acc, _From, _To, _Node, _Lang) ->
+    Acc.
+
+-spec disco_features({error, error()} | {result, [binary()]} | empty,
+                    jid(), jid(),
+                    undefined | binary(), undefined | binary()) ->
+                           {error, error()} | {result, [binary()]}.
+disco_features({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
+    Acc;
+disco_features(Acc, _From, _To, undefined, _Lang) ->
+    Features = case Acc of
+                  {result, Fs} -> Fs;
+                  empty -> []
+              end,
+    {result, [?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
+             ?NS_VCARD, ?NS_SEARCH | Features]};
+disco_features(empty, _From, _To, _Node, Lang) ->
+    Txt = <<"No features available">>,
+    {error, xmpp:err_item_not_found(Txt, Lang)};
+disco_features(Acc, _From, _To, _Node, _Lang) ->
+    Acc.
+
+-spec disco_identity([identity()], jid(), jid(), undefined | binary(),
+                    undefined | binary()) -> [identity()].
+disco_identity(Acc, _From, _To, undefined, Lang) ->
+    [#identity{category = <<"directory">>,
+              type = <<"user">>,
+              name = translate:translate(Lang, <<"vCard User Search">>)}|Acc];
+disco_identity(Acc, _From, _To, _Node, _Lang) ->
+    Acc.
+
+-spec get_vcard(binary(), binary()) -> [xmlel()] | error.
 get_vcard(LUser, LServer) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     Mod:get_vcard(LUser, LServer).
 
+-spec make_vcard_search(binary(), binary(), binary(), xmlel()) -> #vcard_search{}.
 make_vcard_search(User, LUser, LServer, VCARD) ->
     FN = fxml:get_path_s(VCARD, [{elem, <<"FN">>}, cdata]),
     Family = fxml:get_path_s(VCARD,
@@ -250,6 +336,7 @@ make_vcard_search(User, LUser, LServer, VCARD) ->
                  orgunit = OrgUnit,
                  lorgunit = LOrgUnit}.
 
+-spec set_vcard(binary(), binary(), xmlel()) -> any().
 set_vcard(User, LServer, VCARD) ->
     case jid:nodeprep(User) of
        error ->
@@ -262,307 +349,108 @@ set_vcard(User, LServer, VCARD) ->
                               [LUser, LServer, VCARD])
     end.
 
+-spec string2lower(binary()) -> binary().
 string2lower(String) ->
     case stringprep:tolower(String) of
       Lower when is_binary(Lower) -> Lower;
       error -> str:to_lower(String)
     end.
 
--define(TLFIELD(Type, Label, Var),
-       #xmlel{name = <<"field">>,
-              attrs =
-                  [{<<"type">>, Type},
-                   {<<"label">>, translate:translate(Lang, Label)},
-                   {<<"var">>, Var}],
-              children = []}).
-
--define(FORM(JID),
-       [#xmlel{name = <<"instructions">>, attrs = [],
-               children =
-                   [{xmlcdata,
-                     translate:translate(Lang,
-                                         <<"You need an x:data capable client to "
-                                           "search">>)}]},
-        #xmlel{name = <<"x">>,
-               attrs =
-                   [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}],
-               children =
-                   [#xmlel{name = <<"title">>, attrs = [],
-                           children =
-                               [{xmlcdata,
-                                 <<(translate:translate(Lang,
-                                                        <<"Search users in ">>))/binary,
-                                   (jid:to_string(JID))/binary>>}]},
-                    #xmlel{name = <<"instructions">>, attrs = [],
-                           children =
-                               [{xmlcdata,
-                                 translate:translate(Lang,
-                                                     <<"Fill in the form to search for any matching "
-                                                       "Jabber User (Add * to the end of field "
-                                                       "to match substring)">>)}]},
-                    ?TLFIELD(<<"text-single">>, <<"User">>, <<"user">>),
-                    ?TLFIELD(<<"text-single">>, <<"Full Name">>, <<"fn">>),
-                    ?TLFIELD(<<"text-single">>, <<"Name">>, <<"first">>),
-                    ?TLFIELD(<<"text-single">>, <<"Middle Name">>,
-                             <<"middle">>),
-                    ?TLFIELD(<<"text-single">>, <<"Family Name">>,
-                             <<"last">>),
-                    ?TLFIELD(<<"text-single">>, <<"Nickname">>, <<"nick">>),
-                    ?TLFIELD(<<"text-single">>, <<"Birthday">>, <<"bday">>),
-                    ?TLFIELD(<<"text-single">>, <<"Country">>, <<"ctry">>),
-                    ?TLFIELD(<<"text-single">>, <<"City">>, <<"locality">>),
-                    ?TLFIELD(<<"text-single">>, <<"Email">>, <<"email">>),
-                    ?TLFIELD(<<"text-single">>, <<"Organization Name">>,
-                             <<"orgname">>),
-                    ?TLFIELD(<<"text-single">>, <<"Organization Unit">>,
-                             <<"orgunit">>)]}]).
-
-do_route(ServerHost, From, To, Packet) ->
-    #jid{user = User, resource = Resource} = To,
-    if (User /= <<"">>) or (Resource /= <<"">>) ->
-          Err = jlib:make_error_reply(Packet,
-                                      ?ERR_SERVICE_UNAVAILABLE),
-          ejabberd_router:route(To, From, Err);
-       true ->
-          IQ = jlib:iq_query_info(Packet),
-          case IQ of
-            #iq{type = Type, xmlns = ?NS_SEARCH, lang = Lang,
-                sub_el = SubEl} ->
-                case Type of
-                  set ->
-                      XDataEl = find_xdata_el(SubEl),
-                      case XDataEl of
-                        false ->
-                            Txt = <<"Data form not found">>,
-                            Err = jlib:make_error_reply(
-                                    Packet, ?ERRT_BAD_REQUEST(Lang, Txt)),
-                            ejabberd_router:route(To, From, Err);
-                        _ ->
-                            XData = jlib:parse_xdata_submit(XDataEl),
-                            case XData of
-                              invalid ->
-                                  Txt = <<"Incorrect data form">>,
-                                  Err = jlib:make_error_reply(
-                                          Packet, ?ERRT_BAD_REQUEST(Lang, Txt)),
-                                  ejabberd_router:route(To, From, Err);
-                              _ ->
-                                  ResIQ = IQ#iq{type = result,
-                                                sub_el =
-                                                    [#xmlel{name = <<"query">>,
-                                                            attrs =
-                                                                [{<<"xmlns">>,
-                                                                  ?NS_SEARCH}],
-                                                            children =
-                                                                [#xmlel{name =
-                                                                            <<"x">>,
-                                                                        attrs =
-                                                                            [{<<"xmlns">>,
-                                                                              ?NS_XDATA},
-                                                                             {<<"type">>,
-                                                                              <<"result">>}],
-                                                                        children
-                                                                            =
-                                                                            search_result(Lang,
-                                                                                          To,
-                                                                                          ServerHost,
-                                                                                          XData)}]}]},
-                                  ejabberd_router:route(To, From,
-                                                        jlib:iq_to_xml(ResIQ))
-                            end
-                      end;
-                  get ->
-                      ResIQ = IQ#iq{type = result,
-                                    sub_el =
-                                        [#xmlel{name = <<"query">>,
-                                                attrs =
-                                                    [{<<"xmlns">>,
-                                                      ?NS_SEARCH}],
-                                                children = ?FORM(To)}]},
-                      ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ))
-                end;
-            #iq{type = Type, xmlns = ?NS_DISCO_INFO, lang = Lang} ->
-                case Type of
-                  set ->
-                      Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-                      Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, Txt)),
-                      ejabberd_router:route(To, From, Err);
-                  get ->
-                      Info = ejabberd_hooks:run_fold(disco_info, ServerHost,
-                                                     [],
-                                                     [ServerHost, ?MODULE,
-                                                      <<"">>, <<"">>]),
-                      ResIQ = IQ#iq{type = result,
-                                    sub_el =
-                                        [#xmlel{name = <<"query">>,
-                                                attrs =
-                                                    [{<<"xmlns">>,
-                                                      ?NS_DISCO_INFO}],
-                                                children =
-                                                    [#xmlel{name =
-                                                                <<"identity">>,
-                                                            attrs =
-                                                                [{<<"category">>,
-                                                                  <<"directory">>},
-                                                                 {<<"type">>,
-                                                                  <<"user">>},
-                                                                 {<<"name">>,
-                                                                  translate:translate(Lang,
-                                                                                      <<"vCard User Search">>)}],
-                                                            children = []},
-                                                     #xmlel{name =
-                                                                <<"feature">>,
-                                                            attrs =
-                                                                [{<<"var">>,
-                                                                  ?NS_DISCO_INFO}],
-                                                            children = []},
-                                                     #xmlel{name =
-                                                                <<"feature">>,
-                                                            attrs =
-                                                                [{<<"var">>,
-                                                                  ?NS_SEARCH}],
-                                                            children = []},
-                                                     #xmlel{name =
-                                                                <<"feature">>,
-                                                            attrs =
-                                                                [{<<"var">>,
-                                                                  ?NS_VCARD}],
-                                                            children = []}]
-                                                      ++ Info}]},
-                      ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ))
-                end;
-            #iq{type = Type, lang = Lang, xmlns = ?NS_DISCO_ITEMS} ->
-                case Type of
-                  set ->
-                      Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-                      Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, Txt)),
-                      ejabberd_router:route(To, From, Err);
-                  get ->
-                      ResIQ = IQ#iq{type = result,
-                                    sub_el =
-                                        [#xmlel{name = <<"query">>,
-                                                attrs =
-                                                    [{<<"xmlns">>,
-                                                      ?NS_DISCO_ITEMS}],
-                                                children = []}]},
-                      ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ))
-                end;
-            #iq{type = get, xmlns = ?NS_VCARD, lang = Lang} ->
-                ResIQ = IQ#iq{type = result,
-                              sub_el =
-                                  [#xmlel{name = <<"vCard">>,
-                                          attrs = [{<<"xmlns">>, ?NS_VCARD}],
-                                          children = iq_get_vcard(Lang)}]},
-                ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ));
-            _ ->
-                Err = jlib:make_error_reply(Packet,
-                                            ?ERR_SERVICE_UNAVAILABLE),
-                ejabberd_router:route(To, From, Err)
-          end
-    end.
-
-iq_get_vcard(Lang) ->
-    [#xmlel{name = <<"FN">>, attrs = [],
-           children = [{xmlcdata, <<"ejabberd/mod_vcard">>}]},
-     #xmlel{name = <<"URL">>, attrs = [],
-           children = [{xmlcdata, ?EJABBERD_URI}]},
-     #xmlel{name = <<"DESC">>, attrs = [],
-           children =
-               [{xmlcdata,
-                 <<(translate:translate(Lang,
-                                        <<"ejabberd vCard module">>))/binary,
-                   "\nCopyright (c) 2003-2016 ProcessOne">>}]}].
-
-find_xdata_el(#xmlel{children = SubEls}) ->
-    find_xdata_el1(SubEls).
-
-find_xdata_el1([]) -> false;
-find_xdata_el1([#xmlel{name = Name, attrs = Attrs,
-                      children = SubEls}
-               | Els]) ->
-    case fxml:get_attr_s(<<"xmlns">>, Attrs) of
-      ?NS_XDATA ->
-         #xmlel{name = Name, attrs = Attrs, children = SubEls};
-      _ -> find_xdata_el1(Els)
-    end;
-find_xdata_el1([_ | Els]) -> find_xdata_el1(Els).
-
--define(LFIELD(Label, Var),
-       #xmlel{name = <<"field">>,
-              attrs =
-                  [{<<"label">>, translate:translate(Lang, Label)},
-                   {<<"var">>, Var}],
-              children = []}).
-
-search_result(Lang, JID, ServerHost, Data) ->
-    [#xmlel{name = <<"title">>, attrs = [],
-           children =
-               [{xmlcdata,
-                 <<(translate:translate(Lang,
-                                        <<"Search Results for ">>))/binary,
-                   (jid:to_string(JID))/binary>>}]},
-     #xmlel{name = <<"reported">>, attrs = [],
-           children =
-               [?TLFIELD(<<"text-single">>, <<"Jabber ID">>,
-                         <<"jid">>),
-                ?TLFIELD(<<"text-single">>, <<"Full Name">>, <<"fn">>),
-                ?TLFIELD(<<"text-single">>, <<"Name">>, <<"first">>),
-                ?TLFIELD(<<"text-single">>, <<"Middle Name">>,
-                         <<"middle">>),
-                ?TLFIELD(<<"text-single">>, <<"Family Name">>,
-                         <<"last">>),
-                ?TLFIELD(<<"text-single">>, <<"Nickname">>, <<"nick">>),
-                ?TLFIELD(<<"text-single">>, <<"Birthday">>, <<"bday">>),
-                ?TLFIELD(<<"text-single">>, <<"Country">>, <<"ctry">>),
-                ?TLFIELD(<<"text-single">>, <<"City">>, <<"locality">>),
-                ?TLFIELD(<<"text-single">>, <<"Email">>, <<"email">>),
-                ?TLFIELD(<<"text-single">>, <<"Organization Name">>,
-                         <<"orgname">>),
-                ?TLFIELD(<<"text-single">>, <<"Organization Unit">>,
-                         <<"orgunit">>)]}]
-      ++
-      lists:map(fun (R) -> record_to_item(ServerHost, R) end,
-               search(ServerHost, Data)).
-
--define(FIELD(Var, Val),
-       #xmlel{name = <<"field">>, attrs = [{<<"var">>, Var}],
-              children =
-                  [#xmlel{name = <<"value">>, attrs = [],
-                          children = [{xmlcdata, Val}]}]}).
-
+-spec mk_tfield(binary(), binary(), undefined | binary()) -> xdata_field().
+mk_tfield(Label, Var, Lang) ->
+    #xdata_field{type = 'text-single',
+                label = translate:translate(Lang, Label),
+                var = Var}.
+
+-spec mk_field(binary(), binary()) -> xdata_field().
+mk_field(Var, Val) ->
+    #xdata_field{var = Var, values = [Val]}.
+
+-spec mk_search_form(jid(), undefined | binary()) -> search().
+mk_search_form(JID, Lang) ->
+    Title = <<(translate:translate(Lang, <<"Search users in ">>))/binary,
+             (jid:to_string(JID))/binary>>,
+    Fs = [mk_tfield(<<"User">>, <<"user">>, Lang),
+         mk_tfield(<<"Full Name">>, <<"fn">>, Lang),
+         mk_tfield(<<"Name">>, <<"first">>, Lang),
+         mk_tfield(<<"Middle Name">>, <<"middle">>, Lang),
+         mk_tfield(<<"Family Name">>, <<"last">>, Lang),
+         mk_tfield(<<"Nickname">>, <<"nick">>, Lang),
+         mk_tfield(<<"Birthday">>, <<"bday">>, Lang),
+         mk_tfield(<<"Country">>, <<"ctry">>, Lang),
+         mk_tfield(<<"City">>, <<"locality">>, Lang),
+         mk_tfield(<<"Email">>, <<"email">>, Lang),
+         mk_tfield(<<"Organization Name">>, <<"orgname">>, Lang),
+         mk_tfield(<<"Organization Unit">>, <<"orgunit">>, Lang)],
+    X = #xdata{type = form,
+              title = Title,
+              instructions =
+                  [translate:translate(
+                     Lang,
+                     <<"Fill in the form to search for any matching "
+                       "Jabber User (Add * to the end of field "
+                       "to match substring)">>)],
+              fields = Fs},
+    #search{instructions =
+               translate:translate(
+                 Lang, <<"You need an x:data capable client to search">>),
+           xdata = X}.
+
+-spec search_result(undefined | binary(), jid(), binary(), [xdata_field()]) -> xdata().
+search_result(Lang, JID, ServerHost, XFields) ->
+    #xdata{type = result,
+          title = <<(translate:translate(Lang,
+                                         <<"Search Results for ">>))/binary,
+                    (jid:to_string(JID))/binary>>,
+          reported = [mk_tfield(<<"Jabber ID">>, <<"jid">>, Lang),
+                      mk_tfield(<<"Full Name">>, <<"fn">>, Lang),
+                      mk_tfield(<<"Name">>, <<"first">>, Lang),
+                      mk_tfield(<<"Middle Name">>, <<"middle">>, Lang),
+                      mk_tfield(<<"Family Name">>, <<"last">>, Lang),
+                      mk_tfield(<<"Nickname">>, <<"nick">>, Lang),
+                      mk_tfield(<<"Birthday">>, <<"bday">>, Lang),
+                      mk_tfield(<<"Country">>, <<"ctry">>, Lang),
+                      mk_tfield(<<"City">>, <<"locality">>, Lang),
+                      mk_tfield(<<"Email">>, <<"email">>, Lang),
+                      mk_tfield(<<"Organization Name">>, <<"orgname">>, Lang),
+                      mk_tfield(<<"Organization Unit">>, <<"orgunit">>, Lang)],
+          items = lists:map(fun (R) -> record_to_item(ServerHost, R) end,
+                            search(ServerHost, XFields))}.
+
+-spec record_to_item(binary(), [binary()] | #vcard_search{}) -> [xdata_field()].
 record_to_item(LServer,
               [Username, FN, Family, Given, Middle, Nickname, BDay,
                CTRY, Locality, EMail, OrgName, OrgUnit]) ->
-    #xmlel{name = <<"item">>, attrs = [],
-          children =
-              [?FIELD(<<"jid">>,
-                      <<Username/binary, "@", LServer/binary>>),
-               ?FIELD(<<"fn">>, FN), ?FIELD(<<"last">>, Family),
-               ?FIELD(<<"first">>, Given),
-               ?FIELD(<<"middle">>, Middle),
-               ?FIELD(<<"nick">>, Nickname), ?FIELD(<<"bday">>, BDay),
-               ?FIELD(<<"ctry">>, CTRY),
-               ?FIELD(<<"locality">>, Locality),
-               ?FIELD(<<"email">>, EMail),
-               ?FIELD(<<"orgname">>, OrgName),
-               ?FIELD(<<"orgunit">>, OrgUnit)]};
+    [mk_field(<<"jid">>, <<Username/binary, "@", LServer/binary>>),
+     mk_field(<<"fn">>, FN),
+     mk_field(<<"last">>, Family),
+     mk_field(<<"first">>, Given),
+     mk_field(<<"middle">>, Middle),
+     mk_field(<<"nick">>, Nickname),
+     mk_field(<<"bday">>, BDay),
+     mk_field(<<"ctry">>, CTRY),
+     mk_field(<<"locality">>, Locality),
+     mk_field(<<"email">>, EMail),
+     mk_field(<<"orgname">>, OrgName),
+     mk_field(<<"orgunit">>, OrgUnit)];
 record_to_item(_LServer, #vcard_search{} = R) ->
     {User, Server} = R#vcard_search.user,
-    #xmlel{name = <<"item">>, attrs = [],
-          children =
-              [?FIELD(<<"jid">>, <<User/binary, "@", Server/binary>>),
-               ?FIELD(<<"fn">>, (R#vcard_search.fn)),
-               ?FIELD(<<"last">>, (R#vcard_search.family)),
-               ?FIELD(<<"first">>, (R#vcard_search.given)),
-               ?FIELD(<<"middle">>, (R#vcard_search.middle)),
-               ?FIELD(<<"nick">>, (R#vcard_search.nickname)),
-               ?FIELD(<<"bday">>, (R#vcard_search.bday)),
-               ?FIELD(<<"ctry">>, (R#vcard_search.ctry)),
-               ?FIELD(<<"locality">>, (R#vcard_search.locality)),
-               ?FIELD(<<"email">>, (R#vcard_search.email)),
-               ?FIELD(<<"orgname">>, (R#vcard_search.orgname)),
-               ?FIELD(<<"orgunit">>, (R#vcard_search.orgunit))]}.
-
-search(LServer, Data) ->
+    [mk_field(<<"jid">>, <<User/binary, "@", Server/binary>>),
+     mk_field(<<"fn">>, (R#vcard_search.fn)),
+     mk_field(<<"last">>, (R#vcard_search.family)),
+     mk_field(<<"first">>, (R#vcard_search.given)),
+     mk_field(<<"middle">>, (R#vcard_search.middle)),
+     mk_field(<<"nick">>, (R#vcard_search.nickname)),
+     mk_field(<<"bday">>, (R#vcard_search.bday)),
+     mk_field(<<"ctry">>, (R#vcard_search.ctry)),
+     mk_field(<<"locality">>, (R#vcard_search.locality)),
+     mk_field(<<"email">>, (R#vcard_search.email)),
+     mk_field(<<"orgname">>, (R#vcard_search.orgname)),
+     mk_field(<<"orgunit">>, (R#vcard_search.orgunit))].
+
+-spec search(binary(), [xdata_field()]) -> [binary()].
+search(LServer, XFields) ->
+    Data = [{Var, Vals} || #xdata_field{var = Var, values = Vals} <- XFields],
     Mod = gen_mod:db_mod(LServer, ?MODULE),
     AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE, allow_return_all,
                                             fun(B) when is_boolean(B) -> B end,
index f2101df912e2508dedad1966bc7b6e327cbbca6f..27ea8461aa0687fe86e9f4acd32407f28f353405 100644 (file)
@@ -17,8 +17,7 @@
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
--include("mod_vcard_xupdate.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -callback init(binary(), gen_mod:opts()) -> any().
 -callback import(binary(), #vcard_xupdate{}) -> ok | pass.
@@ -53,12 +52,8 @@ depends(_Host, _Opts) ->
 %% Hooks
 %%====================================================================
 
-update_presence(#xmlel{name = <<"presence">>, attrs = Attrs} = Packet,
-  User, Host) ->
-    case fxml:get_attr_s(<<"type">>, Attrs) of
-      <<>> -> presence_with_xupdate(Packet, User, Host);
-      _ -> Packet
-    end;
+update_presence(#presence{type = undefined} = Packet, User, Host) ->
+    presence_with_xupdate(Packet, User, Host);
 update_presence(Packet, _User, _Host) -> Packet.
 
 vcard_set(LUser, LServer, VCARD) ->
@@ -93,36 +88,10 @@ remove_xupdate(LUser, LServer) ->
 %%% Presence stanza rebuilding
 %%%----------------------------------------------------------------------
 
-presence_with_xupdate(#xmlel{name = <<"presence">>,
-                            attrs = Attrs, children = Els},
-                     User, Host) ->
-    XPhotoEl = build_xphotoel(User, Host),
-    Els2 = presence_with_xupdate2(Els, [], XPhotoEl),
-    #xmlel{name = <<"presence">>, attrs = Attrs,
-          children = Els2}.
-
-presence_with_xupdate2([], Els2, XPhotoEl) ->
-    lists:reverse([XPhotoEl | Els2]);
-%% This clause assumes that the x element contains only the XMLNS attribute:
-presence_with_xupdate2([#xmlel{name = <<"x">>,
-                              attrs = [{<<"xmlns">>, ?NS_VCARD_UPDATE}]}
-                       | Els],
-                      Els2, XPhotoEl) ->
-    presence_with_xupdate2(Els, Els2, XPhotoEl);
-presence_with_xupdate2([El | Els], Els2, XPhotoEl) ->
-    presence_with_xupdate2(Els, [El | Els2], XPhotoEl).
-
-build_xphotoel(User, Host) ->
+presence_with_xupdate(Presence, User, Host) ->
     Hash = get_xupdate(User, Host),
-    PhotoSubEls = case Hash of
-                   Hash when is_binary(Hash) -> [{xmlcdata, Hash}];
-                   _ -> []
-                 end,
-    PhotoEl = [#xmlel{name = <<"photo">>, attrs = [],
-                     children = PhotoSubEls}],
-    #xmlel{name = <<"x">>,
-          attrs = [{<<"xmlns">>, ?NS_VCARD_UPDATE}],
-          children = PhotoEl}.
+    Presence1 = xmpp:remove_subtag(Presence, #vcard_xupdate{}),
+    xmpp:set_subtag(Presence1, #vcard_xupdate{hash = Hash}).
 
 export(LServer) ->
     Mod = gen_mod:db_mod(LServer, ?MODULE),
index 8a035763f4f193fb9732cc027e49a542c0ec3e87..80b22554d7d16112bead2beb7167837fad92cc4a 100644 (file)
 
 -behaviour(gen_mod).
 
--export([start/2, stop/1, process_local_iq/3,
+-export([start/2, stop/1, process_local_iq/1,
         mod_opt_type/1, depends/2]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 start(Host, Opts) ->
     IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
@@ -50,35 +50,20 @@ stop(Host) ->
     gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
                                     ?NS_VERSION).
 
-process_local_iq(_From, To,
-                #iq{id = _ID, type = Type, xmlns = _XMLNS,
-                    sub_el = SubEl, lang = Lang} =
-                    IQ) ->
-    case Type of
-      set ->
-         Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, Txt)]};
-      get ->
-         Host = To#jid.lserver,
-         OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os,
-                                           fun(B) when is_boolean(B) -> B end,
-                                          true)
-                  of
-                true -> [get_os()];
-                false -> []
-              end,
-         IQ#iq{type = result,
-               sub_el =
-                   [#xmlel{name = <<"query">>,
-                           attrs = [{<<"xmlns">>, ?NS_VERSION}],
-                           children =
-                               [#xmlel{name = <<"name">>, attrs = [],
-                                       children =
-                                           [{xmlcdata, <<"ejabberd">>}]},
-                                #xmlel{name = <<"version">>, attrs = [],
-                                       children = [{xmlcdata, ?VERSION}]}]
-                                 ++ OS}]}
-    end.
+process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_local_iq(#iq{type = get, to = To} = IQ) ->
+    Host = To#jid.lserver,
+    OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os,
+                                    fun(B) when is_boolean(B) -> B end,
+                                    true) of
+            true -> get_os();
+            false -> undefined
+        end,
+    xmpp:make_iq_result(IQ, #version{name = <<"ejabberd">>,
+                                    ver = ?VERSION,
+                                    os = OS}).
 
 get_os() ->
     {Osfamily, Osname} = os:type(),
@@ -89,9 +74,7 @@ get_os() ->
                                                     [Major, Minor, Release]));
                  VersionString -> VersionString
                end,
-    OS = <<OSType/binary, " ", OSVersion/binary>>,
-    #xmlel{name = <<"os">>, attrs = [],
-          children = [{xmlcdata, OS}]}.
+    <<OSType/binary, " ", OSVersion/binary>>.
 
 depends(_Host, _Opts) ->
     [].
index e9f61ab8c0375c64a6aba1c4358fcf64b007787c..c8a924585ed6fc0b37e3cd8d2224fd73b4a94519 100644 (file)
@@ -126,8 +126,10 @@ load_file_loop(Fd, Line, File, Lang) ->
             ok
     end.
 
--spec translate(binary(), binary()) -> binary().
+-spec translate(binary() | undefined, binary()) -> binary().
 
+translate(undefined, Msg) ->
+    translate(?MYLANG, Msg);
 translate(Lang, Msg) ->
     LLang = ascii_tolower(Lang),
     case ets:lookup(translations, {LLang, Msg}) of
diff --git a/src/xmpp.erl b/src/xmpp.erl
new file mode 100644 (file)
index 0000000..ca6ed5e
--- /dev/null
@@ -0,0 +1,712 @@
+%%%-------------------------------------------------------------------
+%%% @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/2, decode_tags_by_ns/2, encode/1,
+        get_type/1, get_to/1, get_from/1, get_id/1,
+        get_lang/1, get_error/1, get_els/1, get_ns/1,
+        set_type/2, set_to/2, set_from/2, set_id/2,
+        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, pp/1,
+        get_name/1, get_text/1, mk_text/1, mk_text/2]).
+
+%% XMPP errors
+-export([err_bad_request/0, err_bad_request/2,
+        err_bad_format/0, err_bad_format/2,
+        err_not_allowed/0, err_not_allowed/2,
+        err_conflict/0, err_conflict/2,
+        err_forbidden/0, err_forbidden/2,
+        err_not_acceptable/0, err_not_acceptable/2,
+        err_internal_server_error/0, err_internal_server_error/2,
+        err_service_unavailable/0, err_service_unavailable/2,
+        err_item_not_found/0, err_item_not_found/2,
+        err_jid_malformed/0, err_jid_malformed/2,
+        err_not_authorized/0, err_not_authorized/2,
+        err_feature_not_implemented/0, err_feature_not_implemented/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]).
+
+-ifndef(NS_CLIENT).
+-define(NS_CLIENT, <<"jabber:client">>).
+-endif.
+
+-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(), error()) -> message();
+               (presence(), error()) -> presence();
+               (iq(), error()) -> iq();
+               (xmlel(), error()) -> 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)]}.
+
+-spec get_id(iq() | message() | presence() | xmlel()) -> undefined | binary().
+get_id(#iq{id = ID}) -> ID;
+get_id(#message{id = ID}) -> ID;
+get_id(#presence{id = ID}) -> ID;
+get_id(#xmlel{attrs = Attrs}) ->
+    case fxml:get_attr(<<"id">>, Attrs) of
+       {value, ID} -> ID;
+       false -> undefined
+    end.
+
+-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()) -> undefined | binary().
+get_lang(#iq{lang = L}) -> L;
+get_lang(#message{lang = L}) -> L;
+get_lang(#presence{lang = L}) -> L;
+get_lang(#xmlel{attrs = Attrs}) ->
+    case fxml:get_attr(<<"xml:lang">>, Attrs) of
+       {value, L} -> L;
+       false -> undefined
+    end.
+
+-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 | error().
+get_error(#iq{error = E}) -> E;
+get_error(#message{error = E}) -> E;
+get_error(#presence{error = E}) -> E.
+
+-spec get_els(iq() | message() | presence()) -> [xmpp_element() | xmlel()].
+get_els(#iq{sub_els = Els}) -> Els;
+get_els(#message{sub_els = Els}) -> Els;
+get_els(#presence{sub_els = Els}) -> 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(), jid:jid(), jid:jid()) -> iq();
+                (message(), jid:jid(), jid:jid()) -> message();
+                (presence(), jid:jid(), 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(), error()) -> iq();
+              (message(), error()) -> message();
+              (presence(), error()) -> presence().
+set_error(#iq{} = IQ, E) -> IQ#iq{error = E};
+set_error(#message{} = Msg, E) -> Msg#message{error = E};
+set_error(#presence{} = Pres, E) -> Pres#presence{error = 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, []).
+
+-spec decode(xmlel() | xmpp_element(), [proplists:property()]) ->
+                   {ok, xmpp_element()} | {error, any()}.
+decode(#xmlel{} = El, Opts) ->
+    xmpp_codec:decode(add_ns(El), Opts);
+decode(Pkt, _Opts) ->
+    Pkt.
+
+-spec decode_els(iq()) -> iq();
+               (message()) -> message();
+               (presence()) -> presence().
+decode_els(Stanza) ->
+    Els = lists:map(
+           fun(#xmlel{} = El) ->
+                   case xmpp_codec:is_known_tag(El) of
+                       true -> decode(El);
+                       false -> El
+                   end;
+              (Pkt) ->
+                   Pkt
+           end, get_els(Stanza)),
+    set_els(Stanza, Els).
+
+-spec encode(xmpp_element() | xmlel()) -> xmlel().
+encode(Pkt) ->
+    xmpp_codec:encode(Pkt).
+
+-spec decode_tags_by_ns([xmpp_element() | xmlel()], [binary()]) -> [xmpp_element()].
+decode_tags_by_ns(Els, NSList) ->
+    [xmpp_codec:decode(El) || El <- Els, lists:member(get_ns(El), NSList)].
+
+format_error(Reason) ->
+    xmpp_codec:format_error(Reason).
+
+-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 {get_name(El), get_ns(El)} of
+       {TagName, XMLNS} ->
+           [Tag|Els];
+       _ ->
+           [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 {get_name(El), get_ns(El)} of
+       {TagName, XMLNS} ->
+           try
+               decode(El)
+           catch _:{xmpp_codec, _Why} ->
+                   get_subtag(Els, TagName, XMLNS)
+           end;
+       _ ->
+           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 {get_name(El), get_ns(El)} of
+       {TagName, XMLNS} ->
+           remove_subtag(Els, TagName, XMLNS);
+       _ ->
+           [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 {get_name(El), get_ns(El)} of
+       {TagName, XMLNS} ->
+           true;
+       _ ->
+           has_subtag(Els, TagName, XMLNS)
+    end;
+has_subtag([], _, _) ->
+    false.
+
+-spec get_text([text()]) -> binary().
+get_text([]) -> <<"">>;
+get_text([#text{data = undefined}|_]) -> <<"">>;
+get_text([#text{data = Data}|_]) -> Data.
+
+-spec mk_text(binary()) -> [text()].
+mk_text(Text) ->
+    mk_text(Text, undefined).
+
+-spec mk_text(binary(), binary() | undefined) -> [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() -> error().
+err_bad_request() ->
+    err(modify, 'bad-request', 400).
+
+-spec err_bad_request(binary(), binary() | undefined) -> error().
+err_bad_request(Text, Lang) ->
+    err(modify, 'bad-request', 400, Text, Lang).
+
+-spec err_bad_format() -> error().
+err_bad_format() ->
+    err(modify, 'bad-format', 406).
+
+-spec err_bad_format(binary(), binary() | undefined) -> error().
+err_bad_format(Text, Lang) ->
+    err(modify, 'bad-format', 406, Text, Lang).
+
+-spec err_conflict() -> error().
+err_conflict() ->
+    err(cancel, 'conflict', 409).
+
+-spec err_conflict(binary(), binary() | undefined) -> error().
+err_conflict(Text, Lang) ->
+    err(cancel, 'conflict', 409, Text, Lang).
+
+-spec err_not_allowed() -> error().
+err_not_allowed() ->
+    err(cancel, 'not-allowed', 405).
+
+-spec err_not_allowed(binary(), binary() | undefined) -> error().
+err_not_allowed(Text, Lang) ->
+    err(cancel, 'not-allowed', 405, Text, Lang).
+
+-spec err_feature_not_implemented() -> error().
+err_feature_not_implemented() ->
+    err(cancel, 'feature-not-implemented', 501).
+
+-spec err_feature_not_implemented(binary(), binary() | undefined) -> error().
+err_feature_not_implemented(Text, Lang) ->
+    err(cancel, 'feature-not-implemented', 501, Text, Lang).
+
+-spec err_item_not_found() -> error().
+err_item_not_found() ->
+    err(cancel, 'item-not-found', 404).
+
+-spec err_item_not_found(binary(), binary() | undefined) -> error().
+err_item_not_found(Text, Lang) ->
+    err(cancel, 'item-not-found', 404, Text, Lang).
+
+-spec err_forbidden() -> error().
+err_forbidden() ->
+    err(auth, 'forbidden', 403).
+
+-spec err_forbidden(binary(), binary() | undefined) -> error().
+err_forbidden(Text, Lang) ->
+    err(auth, 'forbidden', 403, Text, Lang).
+
+-spec err_not_acceptable() -> error().
+err_not_acceptable() ->
+    err(modify, 'not-acceptable', 406).
+
+-spec err_not_acceptable(binary(), binary() | undefined) -> error().
+err_not_acceptable(Text, Lang) ->
+    err(modify, 'not-acceptable', 406, Text, Lang).
+
+-spec err_internal_server_error() -> error().
+err_internal_server_error() ->
+    err(wait, 'internal-server-error', 500).
+
+-spec err_internal_server_error(binary(), binary() | undefined) -> error().
+err_internal_server_error(Text, Lang) ->
+    err(wait, 'internal-server-error', 500, Text, Lang).
+
+-spec err_service_unavailable() -> error().
+err_service_unavailable() ->
+    err(cancel, 'service-unavailable', 503).
+
+-spec err_service_unavailable(binary(), binary() | undefined) -> error().
+err_service_unavailable(Text, Lang) ->
+    err(cancel, 'service-unavailable', 503, Text, Lang).
+
+-spec err_jid_malformed() -> error().
+err_jid_malformed() ->
+    err(modify, 'jid-malformed', 400).
+
+-spec err_jid_malformed(binary(), binary() | undefined) -> error().
+err_jid_malformed(Text, Lang) ->
+    err(modify, 'jid-malformed', 400, Text, Lang).
+
+-spec err_not_authorized() -> error().
+err_not_authorized() ->
+    err(auth, 'not-authorized', 401).
+
+-spec err_not_authorized(binary(), binary() | undefined) -> error().
+err_not_authorized(Text, Lang) ->
+    err(auth, 'not-authorized', 401, 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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() | undefined) -> 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()) -> error().
+err(Type, Reason, Code) ->
+    #error{type = Type, reason = Reason, code = Code}.
+
+-spec err('auth' | 'cancel' | 'continue' | 'modify' | 'wait',
+         atom() | gone() | redirect(), non_neg_integer(),
+         binary(), binary() | undefined) -> error().
+err(Type, Reason, Code, Text, Lang) ->
+    #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() | undefined) -> stream_error().
+serr(Reason, Text, Lang) ->
+    #stream_error{reason = Reason,
+                 text = #text{lang = Lang,
+                              data = translate:translate(Lang, Text)}}.
+
+-spec add_ns(xmlel()) -> xmlel().
+add_ns(#xmlel{name = Name} = El) when Name == <<"message">>;
+                                     Name == <<"presence">>;
+                                     Name == <<"iq">> ->
+    Attrs = lists:keystore(<<"xmlns">>, 1, El#xmlel.attrs,
+                          {<<"xmlns">>, ?NS_CLIENT}),
+    El#xmlel{attrs = Attrs};
+add_ns(El) ->
+    El.
similarity index 68%
rename from tools/xmpp_codec.erl
rename to src/xmpp_codec.erl
index ef1421962483259d35e05127f47b92bc84b75cf4..568c5fbc741236a3a59b6b1febfbc0cebe8e677b 100644 (file)
@@ -8,13 +8,44 @@
           {enc_int, 1}, {get_attr, 2}, {enc_enum, 1}]}).
 
 -export([pp/1, format_error/1, decode/1, decode/2,
-        is_known_tag/1, encode/1, get_ns/1]).
+        is_known_tag/1, encode/1, get_name/1, get_ns/1]).
 
 decode(_el) -> decode(_el, []).
 
 decode({xmlel, _name, _attrs, _} = _el, Opts) ->
     IgnoreEls = proplists:get_bool(ignore_els, Opts),
     case {_name, get_attr(<<"xmlns">>, _attrs)} of
+      {<<"query">>, <<"jabber:iq:search">>} ->
+         decode_search(<<"jabber:iq:search">>, IgnoreEls, _el);
+      {<<"item">>, <<"jabber:iq:search">>} ->
+         decode_search_item(<<"jabber:iq:search">>, IgnoreEls,
+                            _el);
+      {<<"email">>, <<"jabber:iq:search">>} ->
+         decode_search_email(<<"jabber:iq:search">>, IgnoreEls,
+                             _el);
+      {<<"nick">>, <<"jabber:iq:search">>} ->
+         decode_search_nick(<<"jabber:iq:search">>, IgnoreEls,
+                            _el);
+      {<<"last">>, <<"jabber:iq:search">>} ->
+         decode_search_last(<<"jabber:iq:search">>, IgnoreEls,
+                            _el);
+      {<<"first">>, <<"jabber:iq:search">>} ->
+         decode_search_first(<<"jabber:iq:search">>, IgnoreEls,
+                             _el);
+      {<<"instructions">>, <<"jabber:iq:search">>} ->
+         decode_search_instructions(<<"jabber:iq:search">>,
+                                    IgnoreEls, _el);
+      {<<"no-permanent-store">>, <<"urn:xmpp:hints">>} ->
+         decode_hint_no_permanent_store(<<"urn:xmpp:hints">>,
+                                        IgnoreEls, _el);
+      {<<"store">>, <<"urn:xmpp:hints">>} ->
+         decode_hint_store(<<"urn:xmpp:hints">>, IgnoreEls, _el);
+      {<<"no-store">>, <<"urn:xmpp:hints">>} ->
+         decode_hint_no_store(<<"urn:xmpp:hints">>, IgnoreEls,
+                              _el);
+      {<<"no-copy">>, <<"urn:xmpp:hints">>} ->
+         decode_hint_no_copy(<<"urn:xmpp:hints">>, IgnoreEls,
+                             _el);
       {<<"participant">>, <<"urn:xmpp:mix:0">>} ->
          decode_mix_participant(<<"urn:xmpp:mix:0">>, IgnoreEls,
                                 _el);
@@ -382,7 +413,7 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
          decode_vcard_xupdate_photo(<<"vcard-temp:x:update">>,
                                     IgnoreEls, _el);
       {<<"vCard">>, <<"vcard-temp">>} ->
-         decode_vcard(<<"vcard-temp">>, IgnoreEls, _el);
+         decode_vcard_temp(<<"vcard-temp">>, IgnoreEls, _el);
       {<<"CLASS">>, <<"vcard-temp">>} ->
          decode_vcard_CLASS(<<"vcard-temp">>, IgnoreEls, _el);
       {<<"CATEGORIES">>, <<"vcard-temp">>} ->
@@ -658,6 +689,10 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
        <<"urn:ietf:params:xml:ns:xmpp-session">>} ->
          decode_session(<<"urn:ietf:params:xml:ns:xmpp-session">>,
                         IgnoreEls, _el);
+      {<<"optional">>,
+       <<"urn:ietf:params:xml:ns:xmpp-session">>} ->
+         decode_session_optional(<<"urn:ietf:params:xml:ns:xmpp-session">>,
+                                 IgnoreEls, _el);
       {<<"query">>, <<"jabber:iq:register">>} ->
          decode_register(<<"jabber:iq:register">>, IgnoreEls,
                          _el);
@@ -806,6 +841,10 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
        <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
          decode_sasl_failure_temporary_auth_failure(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
                                                     IgnoreEls, _el);
+      {<<"bad-protocol">>,
+       <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
+         decode_sasl_failure_bad_protocol(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                          IgnoreEls, _el);
       {<<"not-authorized">>,
        <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
          decode_sasl_failure_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
@@ -867,6 +906,21 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
       {<<"auth">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
          decode_sasl_auth(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
                           IgnoreEls, _el);
+      {<<"query">>, <<"jabber:iq:auth">>} ->
+         decode_legacy_auth(<<"jabber:iq:auth">>, IgnoreEls,
+                            _el);
+      {<<"resource">>, <<"jabber:iq:auth">>} ->
+         decode_legacy_auth_resource(<<"jabber:iq:auth">>,
+                                     IgnoreEls, _el);
+      {<<"digest">>, <<"jabber:iq:auth">>} ->
+         decode_legacy_auth_digest(<<"jabber:iq:auth">>,
+                                   IgnoreEls, _el);
+      {<<"password">>, <<"jabber:iq:auth">>} ->
+         decode_legacy_auth_password(<<"jabber:iq:auth">>,
+                                     IgnoreEls, _el);
+      {<<"username">>, <<"jabber:iq:auth">>} ->
+         decode_legacy_auth_username(<<"jabber:iq:auth">>,
+                                     IgnoreEls, _el);
       {<<"bind">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} ->
          decode_bind(<<"urn:ietf:params:xml:ns:xmpp-bind">>,
                      IgnoreEls, _el);
@@ -1077,8 +1131,12 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
       {<<"message">>, <<"jabber:iq:privacy">>} ->
          decode_privacy_message(<<"jabber:iq:privacy">>,
                                 IgnoreEls, _el);
+      {<<"ver">>, <<"urn:xmpp:features:rosterver">>} ->
+         decode_rosterver_feature(<<"urn:xmpp:features:rosterver">>,
+                                  IgnoreEls, _el);
       {<<"query">>, <<"jabber:iq:roster">>} ->
-         decode_roster(<<"jabber:iq:roster">>, IgnoreEls, _el);
+         decode_roster_query(<<"jabber:iq:roster">>, IgnoreEls,
+                             _el);
       {<<"item">>, <<"jabber:iq:roster">>} ->
          decode_roster_item(<<"jabber:iq:roster">>, IgnoreEls,
                             _el);
@@ -1104,6 +1162,18 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
 
 is_known_tag({xmlel, _name, _attrs, _} = _el) ->
     case {_name, get_attr(<<"xmlns">>, _attrs)} of
+      {<<"query">>, <<"jabber:iq:search">>} -> true;
+      {<<"item">>, <<"jabber:iq:search">>} -> true;
+      {<<"email">>, <<"jabber:iq:search">>} -> true;
+      {<<"nick">>, <<"jabber:iq:search">>} -> true;
+      {<<"last">>, <<"jabber:iq:search">>} -> true;
+      {<<"first">>, <<"jabber:iq:search">>} -> true;
+      {<<"instructions">>, <<"jabber:iq:search">>} -> true;
+      {<<"no-permanent-store">>, <<"urn:xmpp:hints">>} ->
+         true;
+      {<<"store">>, <<"urn:xmpp:hints">>} -> true;
+      {<<"no-store">>, <<"urn:xmpp:hints">>} -> true;
+      {<<"no-copy">>, <<"urn:xmpp:hints">>} -> true;
       {<<"participant">>, <<"urn:xmpp:mix:0">>} -> true;
       {<<"leave">>, <<"urn:xmpp:mix:0">>} -> true;
       {<<"join">>, <<"urn:xmpp:mix:0">>} -> true;
@@ -1491,6 +1561,9 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) ->
       {<<"session">>,
        <<"urn:ietf:params:xml:ns:xmpp-session">>} ->
          true;
+      {<<"optional">>,
+       <<"urn:ietf:params:xml:ns:xmpp-session">>} ->
+         true;
       {<<"query">>, <<"jabber:iq:register">>} -> true;
       {<<"key">>, <<"jabber:iq:register">>} -> true;
       {<<"text">>, <<"jabber:iq:register">>} -> true;
@@ -1574,6 +1647,9 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) ->
       {<<"temporary-auth-failure">>,
        <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
          true;
+      {<<"bad-protocol">>,
+       <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
+         true;
       {<<"not-authorized">>,
        <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
          true;
@@ -1619,6 +1695,11 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) ->
          true;
       {<<"auth">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} ->
          true;
+      {<<"query">>, <<"jabber:iq:auth">>} -> true;
+      {<<"resource">>, <<"jabber:iq:auth">>} -> true;
+      {<<"digest">>, <<"jabber:iq:auth">>} -> true;
+      {<<"password">>, <<"jabber:iq:auth">>} -> true;
+      {<<"username">>, <<"jabber:iq:auth">>} -> true;
       {<<"bind">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} ->
          true;
       {<<"resource">>,
@@ -1745,6 +1826,7 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) ->
       {<<"presence-in">>, <<"jabber:iq:privacy">>} -> true;
       {<<"iq">>, <<"jabber:iq:privacy">>} -> true;
       {<<"message">>, <<"jabber:iq:privacy">>} -> true;
+      {<<"ver">>, <<"urn:xmpp:features:rosterver">>} -> true;
       {<<"query">>, <<"jabber:iq:roster">>} -> true;
       {<<"item">>, <<"jabber:iq:roster">>} -> true;
       {<<"group">>, <<"jabber:iq:roster">>} -> true;
@@ -1766,16 +1848,20 @@ encode({version, _, _, _} = Query) ->
 encode({roster_item, _, _, _, _, _} = Item) ->
     encode_roster_item(Item,
                       [{<<"xmlns">>, <<"jabber:iq:roster">>}]);
-encode({roster, _, _} = Query) ->
-    encode_roster(Query,
-                 [{<<"xmlns">>, <<"jabber:iq:roster">>}]);
-encode({privacy_item, _, _, _, _, _} = Item) ->
+encode({roster_query, _, _} = Query) ->
+    encode_roster_query(Query,
+                       [{<<"xmlns">>, <<"jabber:iq:roster">>}]);
+encode({rosterver_feature} = Ver) ->
+    encode_rosterver_feature(Ver,
+                            [{<<"xmlns">>,
+                              <<"urn:xmpp:features:rosterver">>}]);
+encode({privacy_item, _, _, _, _, _, _, _, _} = Item) ->
     encode_privacy_item(Item,
                        [{<<"xmlns">>, <<"jabber:iq:privacy">>}]);
 encode({privacy_list, _, _} = List) ->
     encode_privacy_list(List,
                        [{<<"xmlns">>, <<"jabber:iq:privacy">>}]);
-encode({privacy, _, _, _} = Query) ->
+encode({privacy_query, _, _, _} = Query) ->
     encode_privacy(Query,
                   [{<<"xmlns">>, <<"jabber:iq:privacy">>}]);
 encode({block, _} = Block) ->
@@ -1842,13 +1928,16 @@ encode({redirect, _} = Redirect) ->
     encode_error_redirect(Redirect,
                          [{<<"xmlns">>,
                            <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]);
-encode({error, _, _, _, _} = Error) ->
+encode({error, _, _, _, _, _} = Error) ->
     encode_error(Error,
                 [{<<"xmlns">>, <<"jabber:client">>}]);
 encode({bind, _, _} = Bind) ->
     encode_bind(Bind,
                [{<<"xmlns">>,
                  <<"urn:ietf:params:xml:ns:xmpp-bind">>}]);
+encode({legacy_auth, _, _, _, _} = Query) ->
+    encode_legacy_auth(Query,
+                      [{<<"xmlns">>, <<"jabber:iq:auth">>}]);
 encode({sasl_auth, _, _} = Auth) ->
     encode_sasl_auth(Auth,
                     [{<<"xmlns">>,
@@ -1915,7 +2004,7 @@ encode({p1_rebind} = Rebind) ->
                     [{<<"xmlns">>, <<"p1:rebind">>}]);
 encode({p1_ack} = Ack) ->
     encode_p1_ack(Ack, [{<<"xmlns">>, <<"p1:ack">>}]);
-encode({caps, _, _, _} = C) ->
+encode({caps, _, _, _, _} = C) ->
     encode_caps(C,
                [{<<"xmlns">>, <<"http://jabber.org/protocol/caps">>}]);
 encode({feature_register} = Register) ->
@@ -1927,7 +2016,7 @@ encode({register, _, _, _, _, _, _, _, _, _, _, _, _, _,
           Query) ->
     encode_register(Query,
                    [{<<"xmlns">>, <<"jabber:iq:register">>}]);
-encode({session} = Session) ->
+encode({xmpp_session, _} = Session) ->
     encode_session(Session,
                   [{<<"xmlns">>,
                     <<"urn:ietf:params:xml:ns:xmpp-session">>}]);
@@ -1981,11 +2070,12 @@ encode({vcard_sound, _, _, _} = Sound) ->
 encode({vcard_key, _, _} = Key) ->
     encode_vcard_KEY(Key,
                     [{<<"xmlns">>, <<"vcard-temp">>}]);
-encode({vcard, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-       _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} =
+encode({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, _,
+       _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} =
           Vcard) ->
-    encode_vcard(Vcard, [{<<"xmlns">>, <<"vcard-temp">>}]);
-encode({vcard_xupdate, _} = X) ->
+    encode_vcard_temp(Vcard,
+                     [{<<"xmlns">>, <<"vcard-temp">>}]);
+encode({vcard_xupdate, undefined, _} = X) ->
     encode_vcard_xupdate(X,
                         [{<<"xmlns">>, <<"vcard-temp:x:update">>}]);
 encode({xdata_field, _, _, _, _, _, _, _} = Field) ->
@@ -2069,7 +2159,7 @@ encode({chatstate, paused} = Paused) ->
     encode_chatstate_paused(Paused,
                            [{<<"xmlns">>,
                              <<"http://jabber.org/protocol/chatstates">>}]);
-encode({delay, _, _} = Delay) ->
+encode({delay, _, _, _} = Delay) ->
     encode_delay(Delay,
                 [{<<"xmlns">>, <<"urn:xmpp:delay">>}]);
 encode({streamhost, _, _, _} = Streamhost) ->
@@ -2192,17 +2282,202 @@ encode({mix_leave} = Leave) ->
                     [{<<"xmlns">>, <<"urn:xmpp:mix:0">>}]);
 encode({mix_participant, _, _} = Participant) ->
     encode_mix_participant(Participant,
-                          [{<<"xmlns">>, <<"urn:xmpp:mix:0">>}]).
+                          [{<<"xmlns">>, <<"urn:xmpp:mix:0">>}]);
+encode({hint, 'no-copy'} = No_copy) ->
+    encode_hint_no_copy(No_copy,
+                       [{<<"xmlns">>, <<"urn:xmpp:hints">>}]);
+encode({hint, 'no-store'} = No_store) ->
+    encode_hint_no_store(No_store,
+                        [{<<"xmlns">>, <<"urn:xmpp:hints">>}]);
+encode({hint, store} = Store) ->
+    encode_hint_store(Store,
+                     [{<<"xmlns">>, <<"urn:xmpp:hints">>}]);
+encode({hint, 'no-permanent-store'} =
+          No_permanent_store) ->
+    encode_hint_no_permanent_store(No_permanent_store,
+                                  [{<<"xmlns">>, <<"urn:xmpp:hints">>}]);
+encode({search_item, _, _, _, _, _} = Item) ->
+    encode_search_item(Item,
+                      [{<<"xmlns">>, <<"jabber:iq:search">>}]);
+encode({search, _, _, _, _, _, _, _} = Query) ->
+    encode_search(Query,
+                 [{<<"xmlns">>, <<"jabber:iq:search">>}]).
+
+get_name({last, _, _}) -> <<"query">>;
+get_name({version, _, _, _}) -> <<"query">>;
+get_name({roster_item, _, _, _, _, _}) -> <<"item">>;
+get_name({roster_query, _, _}) -> <<"query">>;
+get_name({rosterver_feature}) -> <<"ver">>;
+get_name({privacy_item, _, _, _, _, _, _, _, _}) ->
+    <<"item">>;
+get_name({privacy_list, _, _}) -> <<"list">>;
+get_name({privacy_query, _, _, _}) -> <<"query">>;
+get_name({block, _}) -> <<"block">>;
+get_name({unblock, _}) -> <<"unblock">>;
+get_name({block_list}) -> <<"blocklist">>;
+get_name({identity, _, _, _, _}) -> <<"identity">>;
+get_name({disco_info, _, _, _, _}) -> <<"query">>;
+get_name({disco_item, _, _, _}) -> <<"item">>;
+get_name({disco_items, _, _}) -> <<"query">>;
+get_name({private, _}) -> <<"query">>;
+get_name({bookmark_conference, _, _, _, _, _}) ->
+    <<"conference">>;
+get_name({bookmark_url, _, _}) -> <<"url">>;
+get_name({bookmark_storage, _, _}) -> <<"storage">>;
+get_name({stat, _, _, _, _}) -> <<"stat">>;
+get_name({stats, _}) -> <<"query">>;
+get_name({iq, _, _, _, _, _, _, _}) -> <<"iq">>;
+get_name({message, _, _, _, _, _, _, _, _, _, _}) ->
+    <<"message">>;
+get_name({presence, _, _, _, _, _, _, _, _, _, _}) ->
+    <<"presence">>;
+get_name({gone, _}) -> <<"gone">>;
+get_name({redirect, _}) -> <<"redirect">>;
+get_name({error, _, _, _, _, _}) -> <<"error">>;
+get_name({bind, _, _}) -> <<"bind">>;
+get_name({legacy_auth, _, _, _, _}) -> <<"query">>;
+get_name({sasl_auth, _, _}) -> <<"auth">>;
+get_name({sasl_abort}) -> <<"abort">>;
+get_name({sasl_challenge, _}) -> <<"challenge">>;
+get_name({sasl_response, _}) -> <<"response">>;
+get_name({sasl_success, _}) -> <<"success">>;
+get_name({sasl_failure, _, _}) -> <<"failure">>;
+get_name({sasl_mechanisms, _}) -> <<"mechanisms">>;
+get_name({starttls, _}) -> <<"starttls">>;
+get_name({starttls_proceed}) -> <<"proceed">>;
+get_name({starttls_failure}) -> <<"failure">>;
+get_name({compress_failure, _}) -> <<"failure">>;
+get_name({compress, _}) -> <<"compress">>;
+get_name({compressed}) -> <<"compressed">>;
+get_name({compression, _}) -> <<"compression">>;
+get_name({stream_features, _}) -> <<"stream:features">>;
+get_name({p1_push}) -> <<"push">>;
+get_name({p1_rebind}) -> <<"rebind">>;
+get_name({p1_ack}) -> <<"ack">>;
+get_name({caps, _, _, _, _}) -> <<"c">>;
+get_name({feature_register}) -> <<"register">>;
+get_name({register, _, _, _, _, _, _, _, _, _, _, _, _,
+         _, _, _, _, _, _, _, _, _}) ->
+    <<"query">>;
+get_name({xmpp_session, _}) -> <<"session">>;
+get_name({ping}) -> <<"ping">>;
+get_name({time, _, _}) -> <<"time">>;
+get_name({text, _, _}) -> <<"text">>;
+get_name({'see-other-host', _}) -> <<"see-other-host">>;
+get_name({stream_error, _, _}) -> <<"stream:error">>;
+get_name({vcard_name, _, _, _, _, _}) -> <<"N">>;
+get_name({vcard_adr, _, _, _, _, _, _, _, _, _, _, _, _,
+         _, _}) ->
+    <<"ADR">>;
+get_name({vcard_label, _, _, _, _, _, _, _, _}) ->
+    <<"LABEL">>;
+get_name({vcard_tel, _, _, _, _, _, _, _, _, _, _, _, _,
+         _, _}) ->
+    <<"TEL">>;
+get_name({vcard_email, _, _, _, _, _, _}) ->
+    <<"EMAIL">>;
+get_name({vcard_geo, _, _}) -> <<"GEO">>;
+get_name({vcard_logo, _, _, _}) -> <<"LOGO">>;
+get_name({vcard_photo, _, _, _}) -> <<"PHOTO">>;
+get_name({vcard_org, _, _}) -> <<"ORG">>;
+get_name({vcard_sound, _, _, _}) -> <<"SOUND">>;
+get_name({vcard_key, _, _}) -> <<"KEY">>;
+get_name({vcard_temp, _, _, _, _, _, _, _, _, _, _, _,
+         _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+         _}) ->
+    <<"vCard">>;
+get_name({vcard_xupdate, undefined, _}) -> <<"x">>;
+get_name({xdata_field, _, _, _, _, _, _, _}) ->
+    <<"field">>;
+get_name({xdata, _, _, _, _, _, _}) -> <<"x">>;
+get_name({pubsub_subscription, _, _, _, _}) ->
+    <<"subscription">>;
+get_name({pubsub_affiliation, _, _}) ->
+    <<"affiliation">>;
+get_name({pubsub_item, _, _}) -> <<"item">>;
+get_name({pubsub_items, _, _, _, _}) -> <<"items">>;
+get_name({pubsub_event_item, _, _, _, _}) -> <<"item">>;
+get_name({pubsub_event_items, _, _, _}) -> <<"items">>;
+get_name({pubsub_event, _}) -> <<"event">>;
+get_name({pubsub_subscribe, _, _}) -> <<"subscribe">>;
+get_name({pubsub_unsubscribe, _, _, _}) ->
+    <<"unsubscribe">>;
+get_name({pubsub_publish, _, _}) -> <<"publish">>;
+get_name({pubsub_options, _, _, _, _}) -> <<"options">>;
+get_name({pubsub_retract, _, _, _}) -> <<"retract">>;
+get_name({pubsub, _, _, _, _, _, _, _, _}) ->
+    <<"pubsub">>;
+get_name({shim, _}) -> <<"headers">>;
+get_name({chatstate, active}) -> <<"active">>;
+get_name({chatstate, composing}) -> <<"composing">>;
+get_name({chatstate, gone}) -> <<"gone">>;
+get_name({chatstate, inactive}) -> <<"inactive">>;
+get_name({chatstate, paused}) -> <<"paused">>;
+get_name({delay, _, _, _}) -> <<"delay">>;
+get_name({streamhost, _, _, _}) -> <<"streamhost">>;
+get_name({bytestreams, _, _, _, _, _, _}) ->
+    <<"query">>;
+get_name({muc_history, _, _, _, _}) -> <<"history">>;
+get_name({muc_decline, _, _, _}) -> <<"decline">>;
+get_name({muc_user_destroy, _, _}) -> <<"destroy">>;
+get_name({muc_invite, _, _, _}) -> <<"invite">>;
+get_name({muc_user, _, _, _, _, _, _}) -> <<"x">>;
+get_name({muc_owner_destroy, _, _, _}) -> <<"destroy">>;
+get_name({muc_owner, _, _}) -> <<"query">>;
+get_name({muc_item, _, _, _, _, _, _, _}) -> <<"item">>;
+get_name({muc_actor, _, _}) -> <<"actor">>;
+get_name({muc_admin, _}) -> <<"query">>;
+get_name({muc, _, _}) -> <<"x">>;
+get_name({rsm_first, _, _}) -> <<"first">>;
+get_name({rsm_set, _, _, _, _, _, _, _}) -> <<"set">>;
+get_name({mam_query, _, _, _, _, _, _, _}) ->
+    <<"query">>;
+get_name({mam_archived, _, _}) -> <<"archived">>;
+get_name({mam_result, _, _, _, _}) -> <<"result">>;
+get_name({mam_prefs, _, _, _, _}) -> <<"prefs">>;
+get_name({mam_fin, _, _, _, _}) -> <<"fin">>;
+get_name({forwarded, _, _}) -> <<"forwarded">>;
+get_name({carbons_disable}) -> <<"disable">>;
+get_name({carbons_enable}) -> <<"enable">>;
+get_name({carbons_private}) -> <<"private">>;
+get_name({carbons_received, _}) -> <<"received">>;
+get_name({carbons_sent, _}) -> <<"sent">>;
+get_name({feature_csi, _}) -> <<"csi">>;
+get_name({csi, active}) -> <<"active">>;
+get_name({csi, inactive}) -> <<"inactive">>;
+get_name({feature_sm, _}) -> <<"sm">>;
+get_name({sm_enable, _, _, _}) -> <<"enable">>;
+get_name({sm_enabled, _, _, _, _, _}) -> <<"enabled">>;
+get_name({sm_resume, _, _, _}) -> <<"resume">>;
+get_name({sm_resumed, _, _, _}) -> <<"resumed">>;
+get_name({sm_r, _}) -> <<"r">>;
+get_name({sm_a, _, _}) -> <<"a">>;
+get_name({sm_failed, _, _, _}) -> <<"failed">>;
+get_name({offline_item, _, _}) -> <<"item">>;
+get_name({offline, _, _, _}) -> <<"offline">>;
+get_name({mix_join, _, _}) -> <<"join">>;
+get_name({mix_leave}) -> <<"leave">>;
+get_name({mix_participant, _, _}) -> <<"participant">>;
+get_name({hint, 'no-copy'}) -> <<"no-copy">>;
+get_name({hint, 'no-store'}) -> <<"no-store">>;
+get_name({hint, store}) -> <<"store">>;
+get_name({hint, 'no-permanent-store'}) ->
+    <<"no-permanent-store">>;
+get_name({search_item, _, _, _, _, _}) -> <<"item">>;
+get_name({search, _, _, _, _, _, _, _}) -> <<"query">>.
 
 get_ns({last, _, _}) -> <<"jabber:iq:last">>;
 get_ns({version, _, _, _}) -> <<"jabber:iq:version">>;
 get_ns({roster_item, _, _, _, _, _}) ->
     <<"jabber:iq:roster">>;
-get_ns({roster, _, _}) -> <<"jabber:iq:roster">>;
-get_ns({privacy_item, _, _, _, _, _}) ->
+get_ns({roster_query, _, _}) -> <<"jabber:iq:roster">>;
+get_ns({rosterver_feature}) ->
+    <<"urn:xmpp:features:rosterver">>;
+get_ns({privacy_item, _, _, _, _, _, _, _, _}) ->
     <<"jabber:iq:privacy">>;
 get_ns({privacy_list, _, _}) -> <<"jabber:iq:privacy">>;
-get_ns({privacy, _, _, _}) -> <<"jabber:iq:privacy">>;
+get_ns({privacy_query, _, _, _}) ->
+    <<"jabber:iq:privacy">>;
 get_ns({block, _}) -> <<"urn:xmpp:blocking">>;
 get_ns({unblock, _}) -> <<"urn:xmpp:blocking">>;
 get_ns({block_list}) -> <<"urn:xmpp:blocking">>;
@@ -2234,9 +2509,11 @@ get_ns({gone, _}) ->
     <<"urn:ietf:params:xml:ns:xmpp-stanzas">>;
 get_ns({redirect, _}) ->
     <<"urn:ietf:params:xml:ns:xmpp-stanzas">>;
-get_ns({error, _, _, _, _}) -> <<"jabber:client">>;
+get_ns({error, _, _, _, _, _}) -> <<"jabber:client">>;
 get_ns({bind, _, _}) ->
     <<"urn:ietf:params:xml:ns:xmpp-bind">>;
+get_ns({legacy_auth, _, _, _, _}) ->
+    <<"jabber:iq:auth">>;
 get_ns({sasl_auth, _, _}) ->
     <<"urn:ietf:params:xml:ns:xmpp-sasl">>;
 get_ns({sasl_abort}) ->
@@ -2270,14 +2547,14 @@ get_ns({stream_features, _}) ->
 get_ns({p1_push}) -> <<"p1:push">>;
 get_ns({p1_rebind}) -> <<"p1:rebind">>;
 get_ns({p1_ack}) -> <<"p1:ack">>;
-get_ns({caps, _, _, _}) ->
+get_ns({caps, _, _, _, _}) ->
     <<"http://jabber.org/protocol/caps">>;
 get_ns({feature_register}) ->
     <<"http://jabber.org/features/iq-register">>;
 get_ns({register, _, _, _, _, _, _, _, _, _, _, _, _, _,
        _, _, _, _, _, _, _, _}) ->
     <<"jabber:iq:register">>;
-get_ns({session}) ->
+get_ns({xmpp_session, _}) ->
     <<"urn:ietf:params:xml:ns:xmpp-session">>;
 get_ns({ping}) -> <<"urn:xmpp:ping">>;
 get_ns({time, _, _}) -> <<"urn:xmpp:time">>;
@@ -2302,10 +2579,11 @@ get_ns({vcard_photo, _, _, _}) -> <<"vcard-temp">>;
 get_ns({vcard_org, _, _}) -> <<"vcard-temp">>;
 get_ns({vcard_sound, _, _, _}) -> <<"vcard-temp">>;
 get_ns({vcard_key, _, _}) -> <<"vcard-temp">>;
-get_ns({vcard, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-       _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) ->
+get_ns({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, _,
+       _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) ->
     <<"vcard-temp">>;
-get_ns({vcard_xupdate, _}) -> <<"vcard-temp:x:update">>;
+get_ns({vcard_xupdate, undefined, _}) ->
+    <<"vcard-temp:x:update">>;
 get_ns({xdata_field, _, _, _, _, _, _, _}) ->
     <<"jabber:x:data">>;
 get_ns({xdata, _, _, _, _, _, _}) ->
@@ -2348,7 +2626,7 @@ get_ns({chatstate, inactive}) ->
     <<"http://jabber.org/protocol/chatstates">>;
 get_ns({chatstate, paused}) ->
     <<"http://jabber.org/protocol/chatstates">>;
-get_ns({delay, _, _}) -> <<"urn:xmpp:delay">>;
+get_ns({delay, _, _, _}) -> <<"urn:xmpp:delay">>;
 get_ns({streamhost, _, _, _}) ->
     <<"http://jabber.org/protocol/bytestreams">>;
 get_ns({bytestreams, _, _, _, _, _, _}) ->
@@ -2375,7 +2653,10 @@ get_ns({rsm_first, _, _}) ->
     <<"http://jabber.org/protocol/rsm">>;
 get_ns({rsm_set, _, _, _, _, _, _, _}) ->
     <<"http://jabber.org/protocol/rsm">>;
+get_ns({mam_query, Xmlns, _, _, _, _, _, _}) -> Xmlns;
 get_ns({mam_archived, _, _}) -> <<"urn:xmpp:mam:tmp">>;
+get_ns({mam_result, Xmlns, _, _, _}) -> Xmlns;
+get_ns({mam_prefs, Xmlns, _, _, _}) -> Xmlns;
 get_ns({mam_fin, _, _, _, _}) -> <<"urn:xmpp:mam:0">>;
 get_ns({forwarded, _, _}) -> <<"urn:xmpp:forward:0">>;
 get_ns({carbons_disable}) -> <<"urn:xmpp:carbons:2">>;
@@ -2384,9 +2665,17 @@ get_ns({carbons_private}) -> <<"urn:xmpp:carbons:2">>;
 get_ns({carbons_received, _}) ->
     <<"urn:xmpp:carbons:2">>;
 get_ns({carbons_sent, _}) -> <<"urn:xmpp:carbons:2">>;
-get_ns({feature_csi, _}) -> <<"urn:xmpp:csi:0">>;
+get_ns({feature_csi, Xmlns}) -> Xmlns;
 get_ns({csi, active}) -> <<"urn:xmpp:csi:0">>;
 get_ns({csi, inactive}) -> <<"urn:xmpp:csi:0">>;
+get_ns({feature_sm, Xmlns}) -> Xmlns;
+get_ns({sm_enable, _, _, Xmlns}) -> Xmlns;
+get_ns({sm_enabled, _, _, _, _, Xmlns}) -> Xmlns;
+get_ns({sm_resume, _, _, Xmlns}) -> Xmlns;
+get_ns({sm_resumed, _, _, Xmlns}) -> Xmlns;
+get_ns({sm_r, Xmlns}) -> Xmlns;
+get_ns({sm_a, _, Xmlns}) -> Xmlns;
+get_ns({sm_failed, _, _, Xmlns}) -> Xmlns;
 get_ns({offline_item, _, _}) ->
     <<"http://jabber.org/protocol/offline">>;
 get_ns({offline, _, _, _}) ->
@@ -2394,7 +2683,15 @@ get_ns({offline, _, _, _}) ->
 get_ns({mix_join, _, _}) -> <<"urn:xmpp:mix:0">>;
 get_ns({mix_leave}) -> <<"urn:xmpp:mix:0">>;
 get_ns({mix_participant, _, _}) -> <<"urn:xmpp:mix:0">>;
-get_ns(_) -> <<>>.
+get_ns({hint, 'no-copy'}) -> <<"urn:xmpp:hints">>;
+get_ns({hint, 'no-store'}) -> <<"urn:xmpp:hints">>;
+get_ns({hint, store}) -> <<"urn:xmpp:hints">>;
+get_ns({hint, 'no-permanent-store'}) ->
+    <<"urn:xmpp:hints">>;
+get_ns({search_item, _, _, _, _, _}) ->
+    <<"jabber:iq:search">>;
+get_ns({search, _, _, _, _, _, _, _}) ->
+    <<"jabber:iq:search">>.
 
 dec_int(Val) -> dec_int(Val, infinity, infinity).
 
@@ -2443,15 +2740,17 @@ get_attr(Attr, Attrs) ->
 
 pp(Term) -> io_lib_pretty:print(Term, fun pp/2).
 
-pp(last, 2) -> [seconds, text];
+pp(last, 2) -> [seconds, status];
 pp(version, 3) -> [name, ver, os];
 pp(roster_item, 5) ->
     [jid, name, groups, subscription, ask];
-pp(roster, 2) -> [items, ver];
-pp(privacy_item, 5) ->
-    [order, action, type, value, kinds];
+pp(roster_query, 2) -> [items, ver];
+pp(rosterver_feature, 0) -> [];
+pp(privacy_item, 8) ->
+    [order, action, type, value, message, iq, presence_in,
+     presence_out];
 pp(privacy_list, 2) -> [name, items];
-pp(privacy, 3) -> [lists, default, active];
+pp(privacy_query, 3) -> [lists, default, active];
 pp(block, 1) -> [items];
 pp(unblock, 1) -> [items];
 pp(block_list, 0) -> [];
@@ -2476,8 +2775,10 @@ pp(presence, 10) ->
      error, sub_els];
 pp(gone, 1) -> [uri];
 pp(redirect, 1) -> [uri];
-pp(error, 4) -> [type, by, reason, text];
+pp(error, 5) -> [type, code, by, reason, text];
 pp(bind, 2) -> [jid, resource];
+pp(legacy_auth, 4) ->
+    [username, password, digest, resource];
 pp(sasl_auth, 2) -> [mechanism, text];
 pp(sasl_abort, 0) -> [];
 pp(sasl_challenge, 1) -> [text];
@@ -2496,13 +2797,13 @@ pp(stream_features, 1) -> [sub_els];
 pp(p1_push, 0) -> [];
 pp(p1_rebind, 0) -> [];
 pp(p1_ack, 0) -> [];
-pp(caps, 3) -> [hash, node, ver];
+pp(caps, 4) -> [node, version, hash, exts];
 pp(feature_register, 0) -> [];
 pp(register, 21) ->
     [registered, remove, instructions, username, nick,
      password, name, first, last, email, address, city,
      state, zip, phone, url, date, misc, text, key, xdata];
-pp(session, 0) -> [];
+pp(xmpp_session, 1) -> [optional];
 pp(ping, 0) -> [];
 pp(time, 2) -> [tzo, utc];
 pp(text, 2) -> [lang, data];
@@ -2526,12 +2827,12 @@ pp(vcard_photo, 3) -> [type, binval, extval];
 pp(vcard_org, 2) -> [name, units];
 pp(vcard_sound, 3) -> [phonetic, binval, extval];
 pp(vcard_key, 2) -> [type, cred];
-pp(vcard, 29) ->
+pp(vcard_temp, 29) ->
     [version, fn, n, nickname, photo, bday, adr, label, tel,
      email, jabberid, mailer, tz, geo, title, role, logo,
      org, categories, note, prodid, rev, sort_string, sound,
      uid, url, class, key, desc];
-pp(vcard_xupdate, 1) -> [photo];
+pp(vcard_xupdate, 2) -> [us, hash];
 pp(xdata_field, 7) ->
     [label, type, var, required, desc, values, options];
 pp(xdata, 6) ->
@@ -2554,7 +2855,7 @@ pp(pubsub, 8) ->
      unsubscribe, options, items, retract];
 pp(shim, 1) -> [headers];
 pp(chatstate, 1) -> [type];
-pp(delay, 2) -> [stamp, from];
+pp(delay, 3) -> [stamp, from, desc];
 pp(streamhost, 3) -> [jid, host, port];
 pp(bytestreams, 6) ->
     [hosts, used, activate, dstaddr, mode, sid];
@@ -2603,8 +2904,16 @@ pp(offline, 3) -> [items, purge, fetch];
 pp(mix_join, 2) -> [jid, subscribe];
 pp(mix_leave, 0) -> [];
 pp(mix_participant, 2) -> [jid, nick];
+pp(hint, 1) -> [type];
+pp(search_item, 5) -> [jid, first, last, nick, email];
+pp(search, 7) ->
+    [instructions, first, last, nick, email, items, xdata];
 pp(_, _) -> no.
 
+join([], _Sep) -> <<>>;
+join([H | T], Sep) ->
+    <<H/binary, << <<Sep, X/binary>>  || X <- T >>/binary>>.
+
 enc_bool(false) -> <<"false">>;
 enc_bool(true) -> <<"true">>.
 
@@ -2645,6 +2954,530 @@ dec_tzo(Val) ->
     M = jlib:binary_to_integer(M1),
     if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end.
 
+decode_search(__TopXMLNS, __IgnoreEls,
+             {xmlel, <<"query">>, _attrs, _els}) ->
+    {Xdata, Items, Instructions, Last, First, Nick, Email} =
+       decode_search_els(__TopXMLNS, __IgnoreEls, _els,
+                         undefined, [], undefined, undefined, undefined,
+                         undefined, undefined),
+    {search, Instructions, First, Last, Nick, Email, Items,
+     Xdata}.
+
+decode_search_els(__TopXMLNS, __IgnoreEls, [], Xdata,
+                 Items, Instructions, Last, First, Nick, Email) ->
+    {Xdata, lists:reverse(Items), Instructions, Last, First,
+     Nick, Email};
+decode_search_els(__TopXMLNS, __IgnoreEls,
+                 [{xmlel, <<"instructions">>, _attrs, _} = _el | _els],
+                 Xdata, Items, Instructions, Last, First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items,
+                           decode_search_instructions(__TopXMLNS, __IgnoreEls,
+                                                      _el),
+                           Last, First, Nick, Email);
+      <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items,
+                           decode_search_instructions(<<"jabber:iq:search">>,
+                                                      __IgnoreEls, _el),
+                           Last, First, Nick, Email);
+      _ ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick, Email)
+    end;
+decode_search_els(__TopXMLNS, __IgnoreEls,
+                 [{xmlel, <<"first">>, _attrs, _} = _el | _els], Xdata,
+                 Items, Instructions, Last, First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last,
+                           decode_search_first(__TopXMLNS, __IgnoreEls, _el),
+                           Nick, Email);
+      <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last,
+                           decode_search_first(<<"jabber:iq:search">>,
+                                               __IgnoreEls, _el),
+                           Nick, Email);
+      _ ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick, Email)
+    end;
+decode_search_els(__TopXMLNS, __IgnoreEls,
+                 [{xmlel, <<"last">>, _attrs, _} = _el | _els], Xdata,
+                 Items, Instructions, Last, First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions,
+                           decode_search_last(__TopXMLNS, __IgnoreEls, _el),
+                           First, Nick, Email);
+      <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions,
+                           decode_search_last(<<"jabber:iq:search">>,
+                                              __IgnoreEls, _el),
+                           First, Nick, Email);
+      _ ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick, Email)
+    end;
+decode_search_els(__TopXMLNS, __IgnoreEls,
+                 [{xmlel, <<"nick">>, _attrs, _} = _el | _els], Xdata,
+                 Items, Instructions, Last, First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First,
+                           decode_search_nick(__TopXMLNS, __IgnoreEls, _el),
+                           Email);
+      <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First,
+                           decode_search_nick(<<"jabber:iq:search">>,
+                                              __IgnoreEls, _el),
+                           Email);
+      _ ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick, Email)
+    end;
+decode_search_els(__TopXMLNS, __IgnoreEls,
+                 [{xmlel, <<"email">>, _attrs, _} = _el | _els], Xdata,
+                 Items, Instructions, Last, First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick,
+                           decode_search_email(__TopXMLNS, __IgnoreEls, _el));
+      <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick,
+                           decode_search_email(<<"jabber:iq:search">>,
+                                               __IgnoreEls, _el));
+      _ ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick, Email)
+    end;
+decode_search_els(__TopXMLNS, __IgnoreEls,
+                 [{xmlel, <<"item">>, _attrs, _} = _el | _els], Xdata,
+                 Items, Instructions, Last, First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           [decode_search_item(__TopXMLNS, __IgnoreEls, _el)
+                            | Items],
+                           Instructions, Last, First, Nick, Email);
+      <<"jabber:iq:search">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           [decode_search_item(<<"jabber:iq:search">>,
+                                               __IgnoreEls, _el)
+                            | Items],
+                           Instructions, Last, First, Nick, Email);
+      _ ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick, Email)
+    end;
+decode_search_els(__TopXMLNS, __IgnoreEls,
+                 [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata,
+                 Items, Instructions, Last, First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"jabber:x:data">> ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els,
+                           decode_xdata(<<"jabber:x:data">>, __IgnoreEls, _el),
+                           Items, Instructions, Last, First, Nick, Email);
+      _ ->
+         decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                           Items, Instructions, Last, First, Nick, Email)
+    end;
+decode_search_els(__TopXMLNS, __IgnoreEls, [_ | _els],
+                 Xdata, Items, Instructions, Last, First, Nick, Email) ->
+    decode_search_els(__TopXMLNS, __IgnoreEls, _els, Xdata,
+                     Items, Instructions, Last, First, Nick, Email).
+
+encode_search({search, Instructions, First, Last, Nick,
+              Email, Items, Xdata},
+             _xmlns_attrs) ->
+    _els = lists:reverse('encode_search_$xdata'(Xdata,
+                                               'encode_search_$items'(Items,
+                                                                      'encode_search_$instructions'(Instructions,
+                                                                                                    'encode_search_$last'(Last,
+                                                                                                                          'encode_search_$first'(First,
+                                                                                                                                                 'encode_search_$nick'(Nick,
+                                                                                                                                                                       'encode_search_$email'(Email,
+                                                                                                                                                                                              [])))))))),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"query">>, _attrs, _els}.
+
+'encode_search_$xdata'(undefined, _acc) -> _acc;
+'encode_search_$xdata'(Xdata, _acc) ->
+    [encode_xdata(Xdata,
+                 [{<<"xmlns">>, <<"jabber:x:data">>}])
+     | _acc].
+
+'encode_search_$items'([], _acc) -> _acc;
+'encode_search_$items'([Items | _els], _acc) ->
+    'encode_search_$items'(_els,
+                          [encode_search_item(Items, []) | _acc]).
+
+'encode_search_$instructions'(undefined, _acc) -> _acc;
+'encode_search_$instructions'(Instructions, _acc) ->
+    [encode_search_instructions(Instructions, []) | _acc].
+
+'encode_search_$last'(undefined, _acc) -> _acc;
+'encode_search_$last'(Last, _acc) ->
+    [encode_search_last(Last, []) | _acc].
+
+'encode_search_$first'(undefined, _acc) -> _acc;
+'encode_search_$first'(First, _acc) ->
+    [encode_search_first(First, []) | _acc].
+
+'encode_search_$nick'(undefined, _acc) -> _acc;
+'encode_search_$nick'(Nick, _acc) ->
+    [encode_search_nick(Nick, []) | _acc].
+
+'encode_search_$email'(undefined, _acc) -> _acc;
+'encode_search_$email'(Email, _acc) ->
+    [encode_search_email(Email, []) | _acc].
+
+decode_search_item(__TopXMLNS, __IgnoreEls,
+                  {xmlel, <<"item">>, _attrs, _els}) ->
+    {Last, First, Nick, Email} =
+       decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                              undefined, undefined, undefined, undefined),
+    Jid = decode_search_item_attrs(__TopXMLNS, _attrs,
+                                  undefined),
+    {search_item, Jid, First, Last, Nick, Email}.
+
+decode_search_item_els(__TopXMLNS, __IgnoreEls, [],
+                      Last, First, Nick, Email) ->
+    {Last, First, Nick, Email};
+decode_search_item_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"first">>, _attrs, _} = _el | _els], Last,
+                      First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last,
+                                decode_search_first(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                                Nick, Email);
+      <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last,
+                                decode_search_first(<<"jabber:iq:search">>,
+                                                    __IgnoreEls, _el),
+                                Nick, Email);
+      _ ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First, Nick, Email)
+    end;
+decode_search_item_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"last">>, _attrs, _} = _el | _els], Last,
+                      First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_search_last(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                                First, Nick, Email);
+      <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_search_last(<<"jabber:iq:search">>,
+                                                   __IgnoreEls, _el),
+                                First, Nick, Email);
+      _ ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First, Nick, Email)
+    end;
+decode_search_item_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"nick">>, _attrs, _} = _el | _els], Last,
+                      First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First,
+                                decode_search_nick(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                                Email);
+      <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First,
+                                decode_search_nick(<<"jabber:iq:search">>,
+                                                   __IgnoreEls, _el),
+                                Email);
+      _ ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First, Nick, Email)
+    end;
+decode_search_item_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"email">>, _attrs, _} = _el | _els], Last,
+                      First, Nick, Email) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First, Nick,
+                                decode_search_email(__TopXMLNS, __IgnoreEls,
+                                                    _el));
+      <<"jabber:iq:search">> ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First, Nick,
+                                decode_search_email(<<"jabber:iq:search">>,
+                                                    __IgnoreEls, _el));
+      _ ->
+         decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Last, First, Nick, Email)
+    end;
+decode_search_item_els(__TopXMLNS, __IgnoreEls,
+                      [_ | _els], Last, First, Nick, Email) ->
+    decode_search_item_els(__TopXMLNS, __IgnoreEls, _els,
+                          Last, First, Nick, Email).
+
+decode_search_item_attrs(__TopXMLNS,
+                        [{<<"jid">>, _val} | _attrs], _Jid) ->
+    decode_search_item_attrs(__TopXMLNS, _attrs, _val);
+decode_search_item_attrs(__TopXMLNS, [_ | _attrs],
+                        Jid) ->
+    decode_search_item_attrs(__TopXMLNS, _attrs, Jid);
+decode_search_item_attrs(__TopXMLNS, [], Jid) ->
+    decode_search_item_attr_jid(__TopXMLNS, Jid).
+
+encode_search_item({search_item, Jid, First, Last, Nick,
+                   Email},
+                  _xmlns_attrs) ->
+    _els = lists:reverse('encode_search_item_$last'(Last,
+                                                   'encode_search_item_$first'(First,
+                                                                               'encode_search_item_$nick'(Nick,
+                                                                                                          'encode_search_item_$email'(Email,
+                                                                                                                                      []))))),
+    _attrs = encode_search_item_attr_jid(Jid, _xmlns_attrs),
+    {xmlel, <<"item">>, _attrs, _els}.
+
+'encode_search_item_$last'(undefined, _acc) -> _acc;
+'encode_search_item_$last'(Last, _acc) ->
+    [encode_search_last(Last, []) | _acc].
+
+'encode_search_item_$first'(undefined, _acc) -> _acc;
+'encode_search_item_$first'(First, _acc) ->
+    [encode_search_first(First, []) | _acc].
+
+'encode_search_item_$nick'(undefined, _acc) -> _acc;
+'encode_search_item_$nick'(Nick, _acc) ->
+    [encode_search_nick(Nick, []) | _acc].
+
+'encode_search_item_$email'(undefined, _acc) -> _acc;
+'encode_search_item_$email'(Email, _acc) ->
+    [encode_search_email(Email, []) | _acc].
+
+decode_search_item_attr_jid(__TopXMLNS, undefined) ->
+    erlang:error({xmpp_codec,
+                 {missing_attr, <<"jid">>, <<"item">>, __TopXMLNS}});
+decode_search_item_attr_jid(__TopXMLNS, _val) ->
+    case catch dec_jid(_val) of
+      {'EXIT', _} ->
+         erlang:error({xmpp_codec,
+                       {bad_attr_value, <<"jid">>, <<"item">>, __TopXMLNS}});
+      _res -> _res
+    end.
+
+encode_search_item_attr_jid(_val, _acc) ->
+    [{<<"jid">>, enc_jid(_val)} | _acc].
+
+decode_search_email(__TopXMLNS, __IgnoreEls,
+                   {xmlel, <<"email">>, _attrs, _els}) ->
+    Cdata = decode_search_email_els(__TopXMLNS, __IgnoreEls,
+                                   _els, <<>>),
+    Cdata.
+
+decode_search_email_els(__TopXMLNS, __IgnoreEls, [],
+                       Cdata) ->
+    decode_search_email_cdata(__TopXMLNS, Cdata);
+decode_search_email_els(__TopXMLNS, __IgnoreEls,
+                       [{xmlcdata, _data} | _els], Cdata) ->
+    decode_search_email_els(__TopXMLNS, __IgnoreEls, _els,
+                           <<Cdata/binary, _data/binary>>);
+decode_search_email_els(__TopXMLNS, __IgnoreEls,
+                       [_ | _els], Cdata) ->
+    decode_search_email_els(__TopXMLNS, __IgnoreEls, _els,
+                           Cdata).
+
+encode_search_email(Cdata, _xmlns_attrs) ->
+    _els = encode_search_email_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"email">>, _attrs, _els}.
+
+decode_search_email_cdata(__TopXMLNS, <<>>) -> <<>>;
+decode_search_email_cdata(__TopXMLNS, _val) -> _val.
+
+encode_search_email_cdata(<<>>, _acc) -> _acc;
+encode_search_email_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_search_nick(__TopXMLNS, __IgnoreEls,
+                  {xmlel, <<"nick">>, _attrs, _els}) ->
+    Cdata = decode_search_nick_els(__TopXMLNS, __IgnoreEls,
+                                  _els, <<>>),
+    Cdata.
+
+decode_search_nick_els(__TopXMLNS, __IgnoreEls, [],
+                      Cdata) ->
+    decode_search_nick_cdata(__TopXMLNS, Cdata);
+decode_search_nick_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlcdata, _data} | _els], Cdata) ->
+    decode_search_nick_els(__TopXMLNS, __IgnoreEls, _els,
+                          <<Cdata/binary, _data/binary>>);
+decode_search_nick_els(__TopXMLNS, __IgnoreEls,
+                      [_ | _els], Cdata) ->
+    decode_search_nick_els(__TopXMLNS, __IgnoreEls, _els,
+                          Cdata).
+
+encode_search_nick(Cdata, _xmlns_attrs) ->
+    _els = encode_search_nick_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"nick">>, _attrs, _els}.
+
+decode_search_nick_cdata(__TopXMLNS, <<>>) -> <<>>;
+decode_search_nick_cdata(__TopXMLNS, _val) -> _val.
+
+encode_search_nick_cdata(<<>>, _acc) -> _acc;
+encode_search_nick_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_search_last(__TopXMLNS, __IgnoreEls,
+                  {xmlel, <<"last">>, _attrs, _els}) ->
+    Cdata = decode_search_last_els(__TopXMLNS, __IgnoreEls,
+                                  _els, <<>>),
+    Cdata.
+
+decode_search_last_els(__TopXMLNS, __IgnoreEls, [],
+                      Cdata) ->
+    decode_search_last_cdata(__TopXMLNS, Cdata);
+decode_search_last_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlcdata, _data} | _els], Cdata) ->
+    decode_search_last_els(__TopXMLNS, __IgnoreEls, _els,
+                          <<Cdata/binary, _data/binary>>);
+decode_search_last_els(__TopXMLNS, __IgnoreEls,
+                      [_ | _els], Cdata) ->
+    decode_search_last_els(__TopXMLNS, __IgnoreEls, _els,
+                          Cdata).
+
+encode_search_last(Cdata, _xmlns_attrs) ->
+    _els = encode_search_last_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"last">>, _attrs, _els}.
+
+decode_search_last_cdata(__TopXMLNS, <<>>) -> <<>>;
+decode_search_last_cdata(__TopXMLNS, _val) -> _val.
+
+encode_search_last_cdata(<<>>, _acc) -> _acc;
+encode_search_last_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_search_first(__TopXMLNS, __IgnoreEls,
+                   {xmlel, <<"first">>, _attrs, _els}) ->
+    Cdata = decode_search_first_els(__TopXMLNS, __IgnoreEls,
+                                   _els, <<>>),
+    Cdata.
+
+decode_search_first_els(__TopXMLNS, __IgnoreEls, [],
+                       Cdata) ->
+    decode_search_first_cdata(__TopXMLNS, Cdata);
+decode_search_first_els(__TopXMLNS, __IgnoreEls,
+                       [{xmlcdata, _data} | _els], Cdata) ->
+    decode_search_first_els(__TopXMLNS, __IgnoreEls, _els,
+                           <<Cdata/binary, _data/binary>>);
+decode_search_first_els(__TopXMLNS, __IgnoreEls,
+                       [_ | _els], Cdata) ->
+    decode_search_first_els(__TopXMLNS, __IgnoreEls, _els,
+                           Cdata).
+
+encode_search_first(Cdata, _xmlns_attrs) ->
+    _els = encode_search_first_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"first">>, _attrs, _els}.
+
+decode_search_first_cdata(__TopXMLNS, <<>>) -> <<>>;
+decode_search_first_cdata(__TopXMLNS, _val) -> _val.
+
+encode_search_first_cdata(<<>>, _acc) -> _acc;
+encode_search_first_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_search_instructions(__TopXMLNS, __IgnoreEls,
+                          {xmlel, <<"instructions">>, _attrs, _els}) ->
+    Cdata = decode_search_instructions_els(__TopXMLNS,
+                                          __IgnoreEls, _els, <<>>),
+    Cdata.
+
+decode_search_instructions_els(__TopXMLNS, __IgnoreEls,
+                              [], Cdata) ->
+    decode_search_instructions_cdata(__TopXMLNS, Cdata);
+decode_search_instructions_els(__TopXMLNS, __IgnoreEls,
+                              [{xmlcdata, _data} | _els], Cdata) ->
+    decode_search_instructions_els(__TopXMLNS, __IgnoreEls,
+                                  _els, <<Cdata/binary, _data/binary>>);
+decode_search_instructions_els(__TopXMLNS, __IgnoreEls,
+                              [_ | _els], Cdata) ->
+    decode_search_instructions_els(__TopXMLNS, __IgnoreEls,
+                                  _els, Cdata).
+
+encode_search_instructions(Cdata, _xmlns_attrs) ->
+    _els = encode_search_instructions_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"instructions">>, _attrs, _els}.
+
+decode_search_instructions_cdata(__TopXMLNS, <<>>) ->
+    undefined;
+decode_search_instructions_cdata(__TopXMLNS, _val) ->
+    _val.
+
+encode_search_instructions_cdata(undefined, _acc) ->
+    _acc;
+encode_search_instructions_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_hint_no_permanent_store(__TopXMLNS, __IgnoreEls,
+                              {xmlel, <<"no-permanent-store">>, _attrs,
+                               _els}) ->
+    {hint, 'no-permanent-store'}.
+
+encode_hint_no_permanent_store({hint,
+                               'no-permanent-store'},
+                              _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"no-permanent-store">>, _attrs, _els}.
+
+decode_hint_store(__TopXMLNS, __IgnoreEls,
+                 {xmlel, <<"store">>, _attrs, _els}) ->
+    {hint, store}.
+
+encode_hint_store({hint, store}, _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"store">>, _attrs, _els}.
+
+decode_hint_no_store(__TopXMLNS, __IgnoreEls,
+                    {xmlel, <<"no-store">>, _attrs, _els}) ->
+    {hint, 'no-store'}.
+
+encode_hint_no_store({hint, 'no-store'},
+                    _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"no-store">>, _attrs, _els}.
+
+decode_hint_no_copy(__TopXMLNS, __IgnoreEls,
+                   {xmlel, <<"no-copy">>, _attrs, _els}) ->
+    {hint, 'no-copy'}.
+
+encode_hint_no_copy({hint, 'no-copy'}, _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"no-copy">>, _attrs, _els}.
+
 decode_mix_participant(__TopXMLNS, __IgnoreEls,
                       {xmlel, <<"participant">>, _attrs, _els}) ->
     {Jid, Nick} = decode_mix_participant_attrs(__TopXMLNS,
@@ -2727,15 +3560,20 @@ decode_mix_join_els(__TopXMLNS, __IgnoreEls, [],
 decode_mix_join_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"subscribe">>, _attrs, _} = _el | _els],
                    Subscribe) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els,
-                              [decode_mix_subscribe(__TopXMLNS, __IgnoreEls,
-                                                    _el)
-                               | Subscribe]);
-       true ->
-          decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els,
-                              Subscribe)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mix:0">> ->
+         decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els,
+                             [decode_mix_subscribe(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                              | Subscribe]);
+      <<"urn:xmpp:mix:0">> ->
+         decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els,
+                             [decode_mix_subscribe(<<"urn:xmpp:mix:0">>,
+                                                   __IgnoreEls, _el)
+                              | Subscribe]);
+      _ ->
+         decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els,
+                             Subscribe)
     end;
 decode_mix_join_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                    Subscribe) ->
@@ -2822,41 +3660,62 @@ decode_offline_els(__TopXMLNS, __IgnoreEls, [], Items,
 decode_offline_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"purge">>, _attrs, _} = _el | _els], Items,
                   Purge, Fetch) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                             decode_offline_purge(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                             Fetch);
-       true ->
-          decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                             Purge, Fetch)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/offline">> ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                            decode_offline_purge(__TopXMLNS, __IgnoreEls, _el),
+                            Fetch);
+      <<"http://jabber.org/protocol/offline">> ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                            decode_offline_purge(<<"http://jabber.org/protocol/offline">>,
+                                                 __IgnoreEls, _el),
+                            Fetch);
+      _ ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                            Purge, Fetch)
     end;
 decode_offline_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"fetch">>, _attrs, _} = _el | _els], Items,
                   Purge, Fetch) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                             Purge,
-                             decode_offline_fetch(__TopXMLNS, __IgnoreEls,
-                                                  _el));
-       true ->
-          decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                             Purge, Fetch)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/offline">> ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                            Purge,
+                            decode_offline_fetch(__TopXMLNS, __IgnoreEls,
+                                                 _el));
+      <<"http://jabber.org/protocol/offline">> ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                            Purge,
+                            decode_offline_fetch(<<"http://jabber.org/protocol/offline">>,
+                                                 __IgnoreEls, _el));
+      _ ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                            Purge, Fetch)
     end;
 decode_offline_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items,
                   Purge, Fetch) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_offline_els(__TopXMLNS, __IgnoreEls, _els,
-                             [decode_offline_item(__TopXMLNS, __IgnoreEls, _el)
-                              | Items],
-                             Purge, Fetch);
-       true ->
-          decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                             Purge, Fetch)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/offline">> ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els,
+                            [decode_offline_item(__TopXMLNS, __IgnoreEls, _el)
+                             | Items],
+                            Purge, Fetch);
+      <<"http://jabber.org/protocol/offline">> ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els,
+                            [decode_offline_item(<<"http://jabber.org/protocol/offline">>,
+                                                 __IgnoreEls, _el)
+                             | Items],
+                            Purge, Fetch);
+      _ ->
+         decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                            Purge, Fetch)
     end;
 decode_offline_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                   Items, Purge, Fetch) ->
@@ -2973,312 +3832,290 @@ decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [],
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"bad-request">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_bad_request(_xmlns, __IgnoreEls,
-                                                        _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_bad_request(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                       __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"conflict">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_conflict(_xmlns, __IgnoreEls,
-                                                     _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_conflict(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                    __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"feature-not-implemented">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_feature_not_implemented(_xmlns,
-                                                                    __IgnoreEls,
-                                                                    _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_feature_not_implemented(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                                   __IgnoreEls,
+                                                                   _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"forbidden">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_forbidden(_xmlns, __IgnoreEls,
-                                                      _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_forbidden(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                     __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"gone">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_gone(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_gone(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"internal-server-error">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_internal_server_error(_xmlns,
-                                                                  __IgnoreEls,
-                                                                  _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_internal_server_error(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                                 __IgnoreEls,
+                                                                 _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"item-not-found">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_item_not_found(_xmlns, __IgnoreEls,
-                                                           _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_item_not_found(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                          __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"jid-malformed">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_jid_malformed(_xmlns, __IgnoreEls,
-                                                          _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_jid_malformed(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                         __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"not-acceptable">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_not_acceptable(_xmlns, __IgnoreEls,
-                                                           _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_not_acceptable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                          __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"not-allowed">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_not_allowed(_xmlns, __IgnoreEls,
-                                                        _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_not_allowed(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                       __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_not_authorized(_xmlns, __IgnoreEls,
-                                                           _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                          __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"policy-violation">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_policy_violation(_xmlns,
-                                                             __IgnoreEls,
-                                                             _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_policy_violation(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                            __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"recipient-unavailable">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_recipient_unavailable(_xmlns,
-                                                                  __IgnoreEls,
-                                                                  _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_recipient_unavailable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                                 __IgnoreEls,
+                                                                 _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"redirect">>, _attrs, _} = _el | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_redirect(_xmlns, __IgnoreEls,
-                                                     _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_redirect(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                    __IgnoreEls, _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"registration-required">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_registration_required(_xmlns,
-                                                                  __IgnoreEls,
-                                                                  _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_registration_required(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                                 __IgnoreEls,
+                                                                 _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"remote-server-not-found">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_remote_server_not_found(_xmlns,
-                                                                    __IgnoreEls,
-                                                                    _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_remote_server_not_found(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                                   __IgnoreEls,
+                                                                   _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"remote-server-timeout">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_remote_server_timeout(_xmlns,
-                                                                  __IgnoreEls,
-                                                                  _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_remote_server_timeout(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                                 __IgnoreEls,
+                                                                 _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"resource-constraint">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_resource_constraint(_xmlns,
-                                                                __IgnoreEls,
-                                                                _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_resource_constraint(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                               __IgnoreEls,
+                                                               _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"service-unavailable">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_service_unavailable(_xmlns,
-                                                                __IgnoreEls,
-                                                                _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_service_unavailable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                               __IgnoreEls,
+                                                               _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"subscription-required">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_subscription_required(_xmlns,
-                                                                  __IgnoreEls,
-                                                                  _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_subscription_required(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                                 __IgnoreEls,
+                                                                 _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"undefined-condition">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_undefined_condition(_xmlns,
-                                                                __IgnoreEls,
-                                                                _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_undefined_condition(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                               __IgnoreEls,
+                                                               _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
     end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"unexpected-request">>, _attrs, _} = _el
                      | _els],
                     Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_error_unexpected_request(_xmlns,
-                                                               __IgnoreEls,
-                                                               _el));
-       true ->
-          decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
-                               Reason)
-    end;
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_error_unexpected_request(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                              __IgnoreEls,
+                                                              _el));
+      _ ->
+         decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
+                              Reason)
+    end;
 decode_sm_failed_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Reason) ->
     decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els,
@@ -3963,15 +4800,15 @@ decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, [],
 decode_carbons_sent_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"forwarded">>, _attrs, _} = _el | _els],
                        Forwarded) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"urn:xmpp:forward:0">> ->
-          decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els,
-                                  {value,
-                                   decode_forwarded(_xmlns, __IgnoreEls,
-                                                    _el)});
-       true ->
-          decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Forwarded)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:xmpp:forward:0">> ->
+         decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els,
+                                 {value,
+                                  decode_forwarded(<<"urn:xmpp:forward:0">>,
+                                                   __IgnoreEls, _el)});
+      _ ->
+         decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Forwarded)
     end;
 decode_carbons_sent_els(__TopXMLNS, __IgnoreEls,
                        [_ | _els], Forwarded) ->
@@ -4008,16 +4845,16 @@ decode_carbons_received_els(__TopXMLNS, __IgnoreEls, [],
 decode_carbons_received_els(__TopXMLNS, __IgnoreEls,
                            [{xmlel, <<"forwarded">>, _attrs, _} = _el | _els],
                            Forwarded) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"urn:xmpp:forward:0">> ->
-          decode_carbons_received_els(__TopXMLNS, __IgnoreEls,
-                                      _els,
-                                      {value,
-                                       decode_forwarded(_xmlns, __IgnoreEls,
-                                                        _el)});
-       true ->
-          decode_carbons_received_els(__TopXMLNS, __IgnoreEls,
-                                      _els, Forwarded)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:xmpp:forward:0">> ->
+         decode_carbons_received_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     {value,
+                                      decode_forwarded(<<"urn:xmpp:forward:0">>,
+                                                       __IgnoreEls, _el)});
+      _ ->
+         decode_carbons_received_els(__TopXMLNS, __IgnoreEls,
+                                     _els, Forwarded)
     end;
 decode_carbons_received_els(__TopXMLNS, __IgnoreEls,
                            [_ | _els], Forwarded) ->
@@ -4078,13 +4915,15 @@ decode_forwarded_els(__TopXMLNS, __IgnoreEls, [], Delay,
 decode_forwarded_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"delay">>, _attrs, _} = _el | _els], Delay,
                     __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"urn:xmpp:delay">> ->
-          decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_delay(_xmlns, __IgnoreEls, _el), __Els);
-       true ->
-          decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els,
-                               Delay, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:xmpp:delay">> ->
+         decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_delay(<<"urn:xmpp:delay">>, __IgnoreEls,
+                                           _el),
+                              __Els);
+      _ ->
+         decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els,
+                              Delay, __Els)
     end;
 decode_forwarded_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, _, _, _} = _el | _els], Delay, __Els) ->
@@ -4132,12 +4971,13 @@ decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [], Rsm) ->
     Rsm;
 decode_mam_fin_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"set">>, _attrs, _} = _el | _els], Rsm) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"http://jabber.org/protocol/rsm">> ->
-          decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els,
-                             decode_rsm_set(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_rsm_set(<<"http://jabber.org/protocol/rsm">>,
+                                           __IgnoreEls, _el));
+      _ ->
+         decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm)
     end;
 decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                   Rsm) ->
@@ -4234,27 +5074,36 @@ decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, [], Never,
 decode_mam_prefs_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"always">>, _attrs, _} = _el | _els], Never,
                     Always) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
-                               Never,
-                               decode_mam_always(__TopXMLNS, __IgnoreEls,
-                                                 _el));
-       true ->
-          decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
-                               Never, Always)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
+                              Never,
+                              decode_mam_always(__TopXMLNS, __IgnoreEls, _el));
+      <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
+                              Never,
+                              decode_mam_always(<<"urn:xmpp:mam:tmp">>,
+                                                __IgnoreEls, _el));
+      _ ->
+         decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
+                              Never, Always)
     end;
 decode_mam_prefs_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"never">>, _attrs, _} = _el | _els], Never,
                     Always) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_mam_never(__TopXMLNS, __IgnoreEls, _el),
-                               Always);
-       true ->
-          decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
-                               Never, Always)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_mam_never(__TopXMLNS, __IgnoreEls, _el),
+                              Always);
+      <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_mam_never(<<"urn:xmpp:mam:tmp">>,
+                                               __IgnoreEls, _el),
+                              Always);
+      _ ->
+         decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els,
+                              Never, Always)
     end;
 decode_mam_prefs_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Never, Always) ->
@@ -4290,15 +5139,11 @@ encode_mam_prefs({mam_prefs, Xmlns, Default, Always,
 
 'encode_mam_prefs_$never'([], _acc) -> _acc;
 'encode_mam_prefs_$never'(Never, _acc) ->
-    [encode_mam_never(Never,
-                     [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}])
-     | _acc].
+    [encode_mam_never(Never, []) | _acc].
 
 'encode_mam_prefs_$always'([], _acc) -> _acc;
 'encode_mam_prefs_$always'(Always, _acc) ->
-    [encode_mam_always(Always,
-                      [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}])
-     | _acc].
+    [encode_mam_always(Always, []) | _acc].
 
 decode_mam_prefs_attr_default(__TopXMLNS, undefined) ->
     undefined;
@@ -4334,18 +5179,26 @@ decode_mam_always_els(__TopXMLNS, __IgnoreEls, [],
     lists:reverse(Jids);
 decode_mam_always_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"jid">>, _attrs, _} = _el | _els], Jids) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els,
-                                case decode_mam_jid(__TopXMLNS, __IgnoreEls,
-                                                    _el)
-                                    of
-                                  [] -> Jids;
-                                  _new_el -> [_new_el | Jids]
-                                end);
-       true ->
-          decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els,
-                                Jids)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els,
+                               case decode_mam_jid(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                                   of
+                                 [] -> Jids;
+                                 _new_el -> [_new_el | Jids]
+                               end);
+      <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els,
+                               case decode_mam_jid(<<"urn:xmpp:mam:tmp">>,
+                                                   __IgnoreEls, _el)
+                                   of
+                                 [] -> Jids;
+                                 _new_el -> [_new_el | Jids]
+                               end);
+      _ ->
+         decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els,
+                               Jids)
     end;
 decode_mam_always_els(__TopXMLNS, __IgnoreEls,
                      [_ | _els], Jids) ->
@@ -4374,18 +5227,25 @@ decode_mam_never_els(__TopXMLNS, __IgnoreEls, [],
     lists:reverse(Jids);
 decode_mam_never_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"jid">>, _attrs, _} = _el | _els], Jids) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els,
-                               case decode_mam_jid(__TopXMLNS, __IgnoreEls,
-                                                   _el)
-                                   of
-                                 [] -> Jids;
-                                 _new_el -> [_new_el | Jids]
-                               end);
-       true ->
-          decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els,
-                               Jids)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els,
+                              case decode_mam_jid(__TopXMLNS, __IgnoreEls, _el)
+                                  of
+                                [] -> Jids;
+                                _new_el -> [_new_el | Jids]
+                              end);
+      <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els,
+                              case decode_mam_jid(<<"urn:xmpp:mam:tmp">>,
+                                                  __IgnoreEls, _el)
+                                  of
+                                [] -> Jids;
+                                _new_el -> [_new_el | Jids]
+                              end);
+      _ ->
+         decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els,
+                              Jids)
     end;
 decode_mam_never_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Jids) ->
@@ -4596,65 +5456,85 @@ decode_mam_query_els(__TopXMLNS, __IgnoreEls, [], Xdata,
 decode_mam_query_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"start">>, _attrs, _} = _el | _els], Xdata,
                     End, Start, With, Rsm) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End,
-                               decode_mam_start(__TopXMLNS, __IgnoreEls, _el),
-                               With, Rsm);
-       true ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End, Start, With, Rsm)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End,
+                              decode_mam_start(__TopXMLNS, __IgnoreEls, _el),
+                              With, Rsm);
+      <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End,
+                              decode_mam_start(<<"urn:xmpp:mam:tmp">>,
+                                               __IgnoreEls, _el),
+                              With, Rsm);
+      _ ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start, With, Rsm)
     end;
 decode_mam_query_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"end">>, _attrs, _} = _el | _els], Xdata,
                     End, Start, With, Rsm) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata,
-                               decode_mam_end(__TopXMLNS, __IgnoreEls, _el),
-                               Start, With, Rsm);
-       true ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End, Start, With, Rsm)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata,
+                              decode_mam_end(__TopXMLNS, __IgnoreEls, _el),
+                              Start, With, Rsm);
+      <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata,
+                              decode_mam_end(<<"urn:xmpp:mam:tmp">>,
+                                             __IgnoreEls, _el),
+                              Start, With, Rsm);
+      _ ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start, With, Rsm)
     end;
 decode_mam_query_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"with">>, _attrs, _} = _el | _els], Xdata,
                     End, Start, With, Rsm) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End, Start,
-                               decode_mam_with(__TopXMLNS, __IgnoreEls, _el),
-                               Rsm);
-       true ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End, Start, With, Rsm)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start,
+                              decode_mam_with(__TopXMLNS, __IgnoreEls, _el),
+                              Rsm);
+      <<"urn:xmpp:mam:tmp">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start,
+                              decode_mam_with(<<"urn:xmpp:mam:tmp">>,
+                                              __IgnoreEls, _el),
+                              Rsm);
+      _ ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start, With, Rsm)
     end;
 decode_mam_query_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"set">>, _attrs, _} = _el | _els], Xdata,
                     End, Start, With, Rsm) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"http://jabber.org/protocol/rsm">> ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End, Start, With,
-                               decode_rsm_set(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End, Start, With, Rsm)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start, With,
+                              decode_rsm_set(<<"http://jabber.org/protocol/rsm">>,
+                                             __IgnoreEls, _el));
+      _ ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start, With, Rsm)
     end;
 decode_mam_query_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata, End,
                     Start, With, Rsm) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"jabber:x:data">> ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_xdata(_xmlns, __IgnoreEls, _el), End,
-                               Start, With, Rsm);
-       true ->
-          decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
-                               Xdata, End, Start, With, Rsm)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"jabber:x:data">> ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_xdata(<<"jabber:x:data">>, __IgnoreEls,
+                                           _el),
+                              End, Start, With, Rsm);
+      _ ->
+         decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els,
+                              Xdata, End, Start, With, Rsm)
     end;
 decode_mam_query_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Xdata, End, Start, With, Rsm) ->
@@ -4696,21 +5576,15 @@ encode_mam_query({mam_query, Xmlns, Id, Start, End,
 
 'encode_mam_query_$end'(undefined, _acc) -> _acc;
 'encode_mam_query_$end'(End, _acc) ->
-    [encode_mam_end(End,
-                   [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}])
-     | _acc].
+    [encode_mam_end(End, []) | _acc].
 
 'encode_mam_query_$start'(undefined, _acc) -> _acc;
 'encode_mam_query_$start'(Start, _acc) ->
-    [encode_mam_start(Start,
-                     [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}])
-     | _acc].
+    [encode_mam_start(Start, []) | _acc].
 
 'encode_mam_query_$with'(undefined, _acc) -> _acc;
 'encode_mam_query_$with'(With, _acc) ->
-    [encode_mam_with(With,
-                    [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}])
-     | _acc].
+    [encode_mam_with(With, []) | _acc].
 
 'encode_mam_query_$rsm'(undefined, _acc) -> _acc;
 'encode_mam_query_$rsm'(Rsm, _acc) ->
@@ -4860,90 +5734,143 @@ decode_rsm_set_els(__TopXMLNS, __IgnoreEls, [], After,
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"after">>, _attrs, _} = _el | _els], After,
                   Last, First, Count, Before, Max, Index) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els,
-                             decode_rsm_after(__TopXMLNS, __IgnoreEls, _el),
-                             Last, First, Count, Before, Max, Index);
-       true ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max, Index)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_rsm_after(__TopXMLNS, __IgnoreEls, _el),
+                            Last, First, Count, Before, Max, Index);
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_rsm_after(<<"http://jabber.org/protocol/rsm">>,
+                                             __IgnoreEls, _el),
+                            Last, First, Count, Before, Max, Index);
+      _ ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max, Index)
     end;
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"before">>, _attrs, _} = _el | _els], After,
                   Last, First, Count, Before, Max, Index) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count,
-                             decode_rsm_before(__TopXMLNS, __IgnoreEls, _el),
-                             Max, Index);
-       true ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max, Index)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count,
+                            decode_rsm_before(__TopXMLNS, __IgnoreEls, _el),
+                            Max, Index);
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count,
+                            decode_rsm_before(<<"http://jabber.org/protocol/rsm">>,
+                                              __IgnoreEls, _el),
+                            Max, Index);
+      _ ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max, Index)
     end;
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"count">>, _attrs, _} = _el | _els], After,
                   Last, First, Count, Before, Max, Index) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First,
-                             decode_rsm_count(__TopXMLNS, __IgnoreEls, _el),
-                             Before, Max, Index);
-       true ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max, Index)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First,
+                            decode_rsm_count(__TopXMLNS, __IgnoreEls, _el),
+                            Before, Max, Index);
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First,
+                            decode_rsm_count(<<"http://jabber.org/protocol/rsm">>,
+                                             __IgnoreEls, _el),
+                            Before, Max, Index);
+      _ ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max, Index)
     end;
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"first">>, _attrs, _} = _el | _els], After,
                   Last, First, Count, Before, Max, Index) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last,
-                             decode_rsm_first(__TopXMLNS, __IgnoreEls, _el),
-                             Count, Before, Max, Index);
-       true ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max, Index)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last,
+                            decode_rsm_first(__TopXMLNS, __IgnoreEls, _el),
+                            Count, Before, Max, Index);
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last,
+                            decode_rsm_first(<<"http://jabber.org/protocol/rsm">>,
+                                             __IgnoreEls, _el),
+                            Count, Before, Max, Index);
+      _ ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max, Index)
     end;
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"index">>, _attrs, _} = _el | _els], After,
                   Last, First, Count, Before, Max, Index) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max,
-                             decode_rsm_index(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max, Index)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max,
+                            decode_rsm_index(__TopXMLNS, __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max,
+                            decode_rsm_index(<<"http://jabber.org/protocol/rsm">>,
+                                             __IgnoreEls, _el));
+      _ ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max, Index)
     end;
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"last">>, _attrs, _} = _el | _els], After,
                   Last, First, Count, Before, Max, Index) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             decode_rsm_last(__TopXMLNS, __IgnoreEls, _el),
-                             First, Count, Before, Max, Index);
-       true ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max, Index)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            decode_rsm_last(__TopXMLNS, __IgnoreEls, _el),
+                            First, Count, Before, Max, Index);
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            decode_rsm_last(<<"http://jabber.org/protocol/rsm">>,
+                                            __IgnoreEls, _el),
+                            First, Count, Before, Max, Index);
+      _ ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max, Index)
     end;
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"max">>, _attrs, _} = _el | _els], After,
                   Last, First, Count, Before, Max, Index) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before,
-                             decode_rsm_max(__TopXMLNS, __IgnoreEls, _el),
-                             Index);
-       true ->
-          decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
-                             Last, First, Count, Before, Max, Index)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before,
+                            decode_rsm_max(__TopXMLNS, __IgnoreEls, _el),
+                            Index);
+      <<"http://jabber.org/protocol/rsm">> ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before,
+                            decode_rsm_max(<<"http://jabber.org/protocol/rsm">>,
+                                           __IgnoreEls, _el),
+                            Index);
+      _ ->
+         decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After,
+                            Last, First, Count, Before, Max, Index)
     end;
 decode_rsm_set_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                   After, Last, First, Count, Before, Max, Index) ->
@@ -5261,12 +6188,18 @@ decode_muc_els(__TopXMLNS, __IgnoreEls, [], History) ->
 decode_muc_els(__TopXMLNS, __IgnoreEls,
               [{xmlel, <<"history">>, _attrs, _} = _el | _els],
               History) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_els(__TopXMLNS, __IgnoreEls, _els,
-                         decode_muc_history(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_muc_els(__TopXMLNS, __IgnoreEls, _els, History)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc">> ->
+         decode_muc_els(__TopXMLNS, __IgnoreEls, _els,
+                        decode_muc_history(__TopXMLNS, __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/muc">> ->
+         decode_muc_els(__TopXMLNS, __IgnoreEls, _els,
+                        decode_muc_history(<<"http://jabber.org/protocol/muc">>,
+                                           __IgnoreEls, _el));
+      _ ->
+         decode_muc_els(__TopXMLNS, __IgnoreEls, _els, History)
     end;
 decode_muc_els(__TopXMLNS, __IgnoreEls, [_ | _els],
               History) ->
@@ -5310,15 +6243,22 @@ decode_muc_admin_els(__TopXMLNS, __IgnoreEls, [],
     lists:reverse(Items);
 decode_muc_admin_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els,
-                               [decode_muc_admin_item(__TopXMLNS, __IgnoreEls,
-                                                      _el)
-                                | Items]);
-       true ->
-          decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els,
-                               Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els,
+                              [decode_muc_admin_item(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                               | Items]);
+      <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els,
+                              [decode_muc_admin_item(<<"http://jabber.org/protocol/muc#admin">>,
+                                                     __IgnoreEls, _el)
+                               | Items]);
+      _ ->
+         decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els,
+                              Items)
     end;
 decode_muc_admin_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Items) ->
@@ -5480,43 +6420,64 @@ decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, [],
 decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls,
                          [{xmlel, <<"actor">>, _attrs, _} = _el | _els], Actor,
                          Continue, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                    decode_muc_admin_actor(__TopXMLNS,
-                                                           __IgnoreEls, _el),
-                                    Continue, Reason);
-       true ->
-          decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Actor, Continue, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   decode_muc_admin_actor(__TopXMLNS,
+                                                          __IgnoreEls, _el),
+                                   Continue, Reason);
+      <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   decode_muc_admin_actor(<<"http://jabber.org/protocol/muc#admin">>,
+                                                          __IgnoreEls, _el),
+                                   Continue, Reason);
+      _ ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Actor, Continue, Reason)
     end;
 decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls,
                          [{xmlel, <<"continue">>, _attrs, _} = _el | _els],
                          Actor, Continue, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Actor,
-                                    decode_muc_admin_continue(__TopXMLNS,
-                                                              __IgnoreEls,
-                                                              _el),
-                                    Reason);
-       true ->
-          decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Actor, Continue, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Actor,
+                                   decode_muc_admin_continue(__TopXMLNS,
+                                                             __IgnoreEls, _el),
+                                   Reason);
+      <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Actor,
+                                   decode_muc_admin_continue(<<"http://jabber.org/protocol/muc#admin">>,
+                                                             __IgnoreEls, _el),
+                                   Reason);
+      _ ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Actor, Continue, Reason)
     end;
 decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls,
                          [{xmlel, <<"reason">>, _attrs, _} = _el | _els],
                          Actor, Continue, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Actor, Continue,
-                                    decode_muc_admin_reason(__TopXMLNS,
-                                                            __IgnoreEls, _el));
-       true ->
-          decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Actor, Continue, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Actor, Continue,
+                                   decode_muc_admin_reason(__TopXMLNS,
+                                                           __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/muc#admin">> ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Actor, Continue,
+                                   decode_muc_admin_reason(<<"http://jabber.org/protocol/muc#admin">>,
+                                                           __IgnoreEls, _el));
+      _ ->
+         decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Actor, Continue, Reason)
     end;
 decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls,
                          [_ | _els], Actor, Continue, Reason) ->
@@ -5661,27 +6622,35 @@ decode_muc_owner_els(__TopXMLNS, __IgnoreEls, [],
 decode_muc_owner_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"destroy">>, _attrs, _} = _el | _els],
                     Config, Destroy) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
-                               Config,
-                               decode_muc_owner_destroy(__TopXMLNS,
-                                                        __IgnoreEls, _el));
-       true ->
-          decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
-                               Config, Destroy)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#owner">> ->
+         decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
+                              Config,
+                              decode_muc_owner_destroy(__TopXMLNS, __IgnoreEls,
+                                                       _el));
+      <<"http://jabber.org/protocol/muc#owner">> ->
+         decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
+                              Config,
+                              decode_muc_owner_destroy(<<"http://jabber.org/protocol/muc#owner">>,
+                                                       __IgnoreEls, _el));
+      _ ->
+         decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
+                              Config, Destroy)
     end;
 decode_muc_owner_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"x">>, _attrs, _} = _el | _els], Config,
                     Destroy) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"jabber:x:data">> ->
-          decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_xdata(_xmlns, __IgnoreEls, _el),
-                               Destroy);
-       true ->
-          decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
-                               Config, Destroy)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"jabber:x:data">> ->
+         decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_xdata(<<"jabber:x:data">>, __IgnoreEls,
+                                           _el),
+                              Destroy);
+      _ ->
+         decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els,
+                              Config, Destroy)
     end;
 decode_muc_owner_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Config, Destroy) ->
@@ -5721,31 +6690,48 @@ decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
 decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
                             [{xmlel, <<"password">>, _attrs, _} = _el | _els],
                             Password, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
-                                       _els,
-                                       decode_muc_owner_password(__TopXMLNS,
-                                                                 __IgnoreEls,
-                                                                 _el),
-                                       Reason);
-       true ->
-          decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
-                                       _els, Password, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#owner">> ->
+         decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
+                                      _els,
+                                      decode_muc_owner_password(__TopXMLNS,
+                                                                __IgnoreEls,
+                                                                _el),
+                                      Reason);
+      <<"http://jabber.org/protocol/muc#owner">> ->
+         decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
+                                      _els,
+                                      decode_muc_owner_password(<<"http://jabber.org/protocol/muc#owner">>,
+                                                                __IgnoreEls,
+                                                                _el),
+                                      Reason);
+      _ ->
+         decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Password, Reason)
     end;
 decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
                             [{xmlel, <<"reason">>, _attrs, _} = _el | _els],
                             Password, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
-                                       _els, Password,
-                                       decode_muc_owner_reason(__TopXMLNS,
-                                                               __IgnoreEls,
-                                                               _el));
-       true ->
-          decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
-                                       _els, Password, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#owner">> ->
+         decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Password,
+                                      decode_muc_owner_reason(__TopXMLNS,
+                                                              __IgnoreEls,
+                                                              _el));
+      <<"http://jabber.org/protocol/muc#owner">> ->
+         decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Password,
+                                      decode_muc_owner_reason(<<"http://jabber.org/protocol/muc#owner">>,
+                                                              __IgnoreEls,
+                                                              _el));
+      _ ->
+         decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Password, Reason)
     end;
 decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls,
                             [_ | _els], Password, Reason) ->
@@ -5881,76 +6867,121 @@ decode_muc_user_els(__TopXMLNS, __IgnoreEls, [],
 decode_muc_user_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"decline">>, _attrs, _} = _el | _els],
                    Status_codes, Items, Invites, Decline, Destroy) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items, Invites,
-                              decode_muc_user_decline(__TopXMLNS, __IgnoreEls,
-                                                      _el),
-                              Destroy);
-       true ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items, Invites, Decline, Destroy)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites,
+                             decode_muc_user_decline(__TopXMLNS, __IgnoreEls,
+                                                     _el),
+                             Destroy);
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites,
+                             decode_muc_user_decline(<<"http://jabber.org/protocol/muc#user">>,
+                                                     __IgnoreEls, _el),
+                             Destroy);
+      _ ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites, Decline, Destroy)
     end;
 decode_muc_user_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"destroy">>, _attrs, _} = _el | _els],
                    Status_codes, Items, Invites, Decline, Destroy) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items, Invites, Decline,
-                              decode_muc_user_destroy(__TopXMLNS, __IgnoreEls,
-                                                      _el));
-       true ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items, Invites, Decline, Destroy)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites, Decline,
+                             decode_muc_user_destroy(__TopXMLNS, __IgnoreEls,
+                                                     _el));
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites, Decline,
+                             decode_muc_user_destroy(<<"http://jabber.org/protocol/muc#user">>,
+                                                     __IgnoreEls, _el));
+      _ ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites, Decline, Destroy)
     end;
 decode_muc_user_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"invite">>, _attrs, _} = _el | _els],
                    Status_codes, Items, Invites, Decline, Destroy) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items,
-                              [decode_muc_user_invite(__TopXMLNS, __IgnoreEls,
-                                                      _el)
-                               | Invites],
-                              Decline, Destroy);
-       true ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items, Invites, Decline, Destroy)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items,
+                             [decode_muc_user_invite(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                              | Invites],
+                             Decline, Destroy);
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items,
+                             [decode_muc_user_invite(<<"http://jabber.org/protocol/muc#user">>,
+                                                     __IgnoreEls, _el)
+                              | Invites],
+                             Decline, Destroy);
+      _ ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites, Decline, Destroy)
     end;
 decode_muc_user_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"item">>, _attrs, _} = _el | _els],
                    Status_codes, Items, Invites, Decline, Destroy) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes,
-                              [decode_muc_user_item(__TopXMLNS, __IgnoreEls,
-                                                    _el)
-                               | Items],
-                              Invites, Decline, Destroy);
-       true ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items, Invites, Decline, Destroy)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes,
+                             [decode_muc_user_item(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                              | Items],
+                             Invites, Decline, Destroy);
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes,
+                             [decode_muc_user_item(<<"http://jabber.org/protocol/muc#user">>,
+                                                   __IgnoreEls, _el)
+                              | Items],
+                             Invites, Decline, Destroy);
+      _ ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites, Decline, Destroy)
     end;
 decode_muc_user_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"status">>, _attrs, _} = _el | _els],
                    Status_codes, Items, Invites, Decline, Destroy) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              case decode_muc_user_status(__TopXMLNS,
-                                                          __IgnoreEls, _el)
-                                  of
-                                undefined -> Status_codes;
-                                _new_el -> [_new_el | Status_codes]
-                              end,
-                              Items, Invites, Decline, Destroy);
-       true ->
-          decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
-                              Status_codes, Items, Invites, Decline, Destroy)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             case decode_muc_user_status(__TopXMLNS,
+                                                         __IgnoreEls, _el)
+                                 of
+                               undefined -> Status_codes;
+                               _new_el -> [_new_el | Status_codes]
+                             end,
+                             Items, Invites, Decline, Destroy);
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             case
+                               decode_muc_user_status(<<"http://jabber.org/protocol/muc#user">>,
+                                                      __IgnoreEls, _el)
+                                 of
+                               undefined -> Status_codes;
+                               _new_el -> [_new_el | Status_codes]
+                             end,
+                             Items, Invites, Decline, Destroy);
+      _ ->
+         decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els,
+                             Status_codes, Items, Invites, Decline, Destroy)
     end;
 decode_muc_user_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                    Status_codes, Items, Invites, Decline, Destroy) ->
@@ -6030,42 +7061,64 @@ decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, [],
 decode_muc_user_item_els(__TopXMLNS, __IgnoreEls,
                         [{xmlel, <<"actor">>, _attrs, _} = _el | _els], Actor,
                         Continue, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                   decode_muc_user_actor(__TopXMLNS,
-                                                         __IgnoreEls, _el),
-                                   Continue, Reason);
-       true ->
-          decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                   Actor, Continue, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  decode_muc_user_actor(__TopXMLNS,
+                                                        __IgnoreEls, _el),
+                                  Continue, Reason);
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  decode_muc_user_actor(<<"http://jabber.org/protocol/muc#user">>,
+                                                        __IgnoreEls, _el),
+                                  Continue, Reason);
+      _ ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Actor, Continue, Reason)
     end;
 decode_muc_user_item_els(__TopXMLNS, __IgnoreEls,
                         [{xmlel, <<"continue">>, _attrs, _} = _el | _els],
                         Actor, Continue, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                   Actor,
-                                   decode_muc_user_continue(__TopXMLNS,
-                                                            __IgnoreEls, _el),
-                                   Reason);
-       true ->
-          decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                   Actor, Continue, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Actor,
+                                  decode_muc_user_continue(__TopXMLNS,
+                                                           __IgnoreEls, _el),
+                                  Reason);
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Actor,
+                                  decode_muc_user_continue(<<"http://jabber.org/protocol/muc#user">>,
+                                                           __IgnoreEls, _el),
+                                  Reason);
+      _ ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Actor, Continue, Reason)
     end;
 decode_muc_user_item_els(__TopXMLNS, __IgnoreEls,
                         [{xmlel, <<"reason">>, _attrs, _} = _el | _els], Actor,
                         Continue, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                   Actor, Continue,
-                                   decode_muc_user_reason(__TopXMLNS,
-                                                          __IgnoreEls, _el));
-       true ->
-          decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                   Actor, Continue, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Actor, Continue,
+                                  decode_muc_user_reason(__TopXMLNS,
+                                                         __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Actor, Continue,
+                                  decode_muc_user_reason(<<"http://jabber.org/protocol/muc#user">>,
+                                                         __IgnoreEls, _el));
+      _ ->
+         decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Actor, Continue, Reason)
     end;
 decode_muc_user_item_els(__TopXMLNS, __IgnoreEls,
                         [_ | _els], Actor, Continue, Reason) ->
@@ -6337,15 +7390,22 @@ decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, [],
 decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls,
                           [{xmlel, <<"reason">>, _attrs, _} = _el | _els],
                           Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls,
-                                     _els,
-                                     decode_muc_user_reason(__TopXMLNS,
-                                                            __IgnoreEls, _el));
-       true ->
-          decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls,
-                                     _els, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls,
+                                    _els,
+                                    decode_muc_user_reason(__TopXMLNS,
+                                                           __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls,
+                                    _els,
+                                    decode_muc_user_reason(<<"http://jabber.org/protocol/muc#user">>,
+                                                           __IgnoreEls, _el));
+      _ ->
+         decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls,
+                                    _els, Reason)
     end;
 decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls,
                           [_ | _els], Reason) ->
@@ -6429,16 +7489,22 @@ decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, [],
 decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls,
                            [{xmlel, <<"reason">>, _attrs, _} = _el | _els],
                            Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls,
-                                      _els,
-                                      decode_muc_user_reason(__TopXMLNS,
-                                                             __IgnoreEls,
-                                                             _el));
-       true ->
-          decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls,
-                                      _els, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_muc_user_reason(__TopXMLNS,
+                                                            __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_muc_user_reason(<<"http://jabber.org/protocol/muc#user">>,
+                                                            __IgnoreEls, _el));
+      _ ->
+         decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls,
+                                     _els, Reason)
     end;
 decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls,
                            [_ | _els], Reason) ->
@@ -6499,16 +7565,22 @@ decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, [],
 decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls,
                            [{xmlel, <<"reason">>, _attrs, _} = _el | _els],
                            Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls,
-                                      _els,
-                                      decode_muc_user_reason(__TopXMLNS,
-                                                             __IgnoreEls,
-                                                             _el));
-       true ->
-          decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls,
-                                      _els, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_muc_user_reason(__TopXMLNS,
+                                                            __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/muc#user">> ->
+         decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_muc_user_reason(<<"http://jabber.org/protocol/muc#user">>,
+                                                            __IgnoreEls, _el));
+      _ ->
+         decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls,
+                                     _els, Reason)
     end;
 decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls,
                            [_ | _els], Reason) ->
@@ -6744,47 +7816,71 @@ decode_bytestreams_els(__TopXMLNS, __IgnoreEls, [],
 decode_bytestreams_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"streamhost">>, _attrs, _} = _el | _els],
                       Hosts, Used, Activate) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
-                                 [decode_bytestreams_streamhost(__TopXMLNS,
-                                                                __IgnoreEls,
-                                                                _el)
-                                  | Hosts],
-                                 Used, Activate);
-       true ->
-          decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Hosts, Used, Activate)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/bytestreams">> ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                [decode_bytestreams_streamhost(__TopXMLNS,
+                                                               __IgnoreEls,
+                                                               _el)
+                                 | Hosts],
+                                Used, Activate);
+      <<"http://jabber.org/protocol/bytestreams">> ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                [decode_bytestreams_streamhost(<<"http://jabber.org/protocol/bytestreams">>,
+                                                               __IgnoreEls,
+                                                               _el)
+                                 | Hosts],
+                                Used, Activate);
+      _ ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                Hosts, Used, Activate)
     end;
 decode_bytestreams_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"streamhost-used">>, _attrs, _} = _el
                        | _els],
                       Hosts, Used, Activate) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Hosts,
-                                 decode_bytestreams_streamhost_used(__TopXMLNS,
-                                                                    __IgnoreEls,
-                                                                    _el),
-                                 Activate);
-       true ->
-          decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Hosts, Used, Activate)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/bytestreams">> ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                Hosts,
+                                decode_bytestreams_streamhost_used(__TopXMLNS,
+                                                                   __IgnoreEls,
+                                                                   _el),
+                                Activate);
+      <<"http://jabber.org/protocol/bytestreams">> ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                Hosts,
+                                decode_bytestreams_streamhost_used(<<"http://jabber.org/protocol/bytestreams">>,
+                                                                   __IgnoreEls,
+                                                                   _el),
+                                Activate);
+      _ ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                Hosts, Used, Activate)
     end;
 decode_bytestreams_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"activate">>, _attrs, _} = _el | _els],
                       Hosts, Used, Activate) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Hosts, Used,
-                                 decode_bytestreams_activate(__TopXMLNS,
-                                                             __IgnoreEls,
-                                                             _el));
-       true ->
-          decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Hosts, Used, Activate)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/bytestreams">> ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                Hosts, Used,
+                                decode_bytestreams_activate(__TopXMLNS,
+                                                            __IgnoreEls, _el));
+      <<"http://jabber.org/protocol/bytestreams">> ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                Hosts, Used,
+                                decode_bytestreams_activate(<<"http://jabber.org/protocol/bytestreams">>,
+                                                            __IgnoreEls, _el));
+      _ ->
+         decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els,
+                                Hosts, Used, Activate)
     end;
 decode_bytestreams_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Hosts, Used, Activate) ->
@@ -7055,9 +8151,21 @@ encode_bytestreams_streamhost_attr_port(_val, _acc) ->
 
 decode_delay(__TopXMLNS, __IgnoreEls,
             {xmlel, <<"delay">>, _attrs, _els}) ->
+    Desc = decode_delay_els(__TopXMLNS, __IgnoreEls, _els,
+                           <<>>),
     {Stamp, From} = decode_delay_attrs(__TopXMLNS, _attrs,
                                       undefined, undefined),
-    {delay, Stamp, From}.
+    {delay, Stamp, From, Desc}.
+
+decode_delay_els(__TopXMLNS, __IgnoreEls, [], Desc) ->
+    decode_delay_cdata(__TopXMLNS, Desc);
+decode_delay_els(__TopXMLNS, __IgnoreEls,
+                [{xmlcdata, _data} | _els], Desc) ->
+    decode_delay_els(__TopXMLNS, __IgnoreEls, _els,
+                    <<Desc/binary, _data/binary>>);
+decode_delay_els(__TopXMLNS, __IgnoreEls, [_ | _els],
+                Desc) ->
+    decode_delay_els(__TopXMLNS, __IgnoreEls, _els, Desc).
 
 decode_delay_attrs(__TopXMLNS,
                   [{<<"stamp">>, _val} | _attrs], _Stamp, From) ->
@@ -7072,8 +8180,9 @@ decode_delay_attrs(__TopXMLNS, [], Stamp, From) ->
     {decode_delay_attr_stamp(__TopXMLNS, Stamp),
      decode_delay_attr_from(__TopXMLNS, From)}.
 
-encode_delay({delay, Stamp, From}, _xmlns_attrs) ->
-    _els = [],
+encode_delay({delay, Stamp, From, Desc},
+            _xmlns_attrs) ->
+    _els = encode_delay_cdata(Desc, []),
     _attrs = encode_delay_attr_from(From,
                                    encode_delay_attr_stamp(Stamp,
                                                            _xmlns_attrs)),
@@ -7108,6 +8217,13 @@ encode_delay_attr_from(undefined, _acc) -> _acc;
 encode_delay_attr_from(_val, _acc) ->
     [{<<"from">>, enc_jid(_val)} | _acc].
 
+decode_delay_cdata(__TopXMLNS, <<>>) -> <<>>;
+decode_delay_cdata(__TopXMLNS, _val) -> _val.
+
+encode_delay_cdata(<<>>, _acc) -> _acc;
+encode_delay_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
 decode_chatstate_paused(__TopXMLNS, __IgnoreEls,
                        {xmlel, <<"paused">>, _attrs, _els}) ->
     {chatstate, paused}.
@@ -7170,15 +8286,22 @@ decode_shim_headers_els(__TopXMLNS, __IgnoreEls, [],
 decode_shim_headers_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"header">>, _attrs, _} = _el | _els],
                        Headers) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els,
-                                  [decode_shim_header(__TopXMLNS, __IgnoreEls,
-                                                      _el)
-                                   | Headers]);
-       true ->
-          decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Headers)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/shim">> ->
+         decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_shim_header(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                                  | Headers]);
+      <<"http://jabber.org/protocol/shim">> ->
+         decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_shim_header(<<"http://jabber.org/protocol/shim">>,
+                                                     __IgnoreEls, _el)
+                                  | Headers]);
+      _ ->
+         decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Headers)
     end;
 decode_shim_headers_els(__TopXMLNS, __IgnoreEls,
                        [_ | _els], Headers) ->
@@ -7267,130 +8390,194 @@ decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"subscriptions">>, _attrs, _} = _el | _els],
                  Items, Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations,
-                            decode_pubsub_subscriptions(__TopXMLNS,
-                                                        __IgnoreEls, _el),
-                            Retract, Unsubscribe, Subscribe, Publish);
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations,
+                           decode_pubsub_subscriptions(__TopXMLNS, __IgnoreEls,
+                                                       _el),
+                           Retract, Unsubscribe, Subscribe, Publish);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations,
+                           decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub">>,
+                                                       __IgnoreEls, _el),
+                           Retract, Unsubscribe, Subscribe, Publish);
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"affiliations">>, _attrs, _} = _el | _els],
                  Items, Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options,
-                            decode_pubsub_affiliations(__TopXMLNS, __IgnoreEls,
-                                                       _el),
-                            Subscriptions, Retract, Unsubscribe, Subscribe,
-                            Publish);
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options,
+                           decode_pubsub_affiliations(__TopXMLNS, __IgnoreEls,
+                                                      _el),
+                           Subscriptions, Retract, Unsubscribe, Subscribe,
+                           Publish);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options,
+                           decode_pubsub_affiliations(<<"http://jabber.org/protocol/pubsub">>,
+                                                      __IgnoreEls, _el),
+                           Subscriptions, Retract, Unsubscribe, Subscribe,
+                           Publish);
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"subscribe">>, _attrs, _} = _el | _els],
                  Items, Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe,
-                            decode_pubsub_subscribe(__TopXMLNS, __IgnoreEls,
-                                                    _el),
-                            Publish);
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe,
+                           decode_pubsub_subscribe(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                           Publish);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe,
+                           decode_pubsub_subscribe(<<"http://jabber.org/protocol/pubsub">>,
+                                                   __IgnoreEls, _el),
+                           Publish);
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"unsubscribe">>, _attrs, _} = _el | _els],
                  Items, Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            decode_pubsub_unsubscribe(__TopXMLNS, __IgnoreEls,
-                                                      _el),
-                            Subscribe, Publish);
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           decode_pubsub_unsubscribe(__TopXMLNS, __IgnoreEls,
+                                                     _el),
+                           Subscribe, Publish);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           decode_pubsub_unsubscribe(<<"http://jabber.org/protocol/pubsub">>,
+                                                     __IgnoreEls, _el),
+                           Subscribe, Publish);
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"options">>, _attrs, _} = _el | _els], Items,
                  Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            decode_pubsub_options(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                            Affiliations, Subscriptions, Retract, Unsubscribe,
-                            Subscribe, Publish);
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           decode_pubsub_options(__TopXMLNS, __IgnoreEls, _el),
+                           Affiliations, Subscriptions, Retract, Unsubscribe,
+                           Subscribe, Publish);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           decode_pubsub_options(<<"http://jabber.org/protocol/pubsub">>,
+                                                 __IgnoreEls, _el),
+                           Affiliations, Subscriptions, Retract, Unsubscribe,
+                           Subscribe, Publish);
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"items">>, _attrs, _} = _el | _els], Items,
                  Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els,
-                            decode_pubsub_items(__TopXMLNS, __IgnoreEls, _el),
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish);
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els,
+                           decode_pubsub_items(__TopXMLNS, __IgnoreEls, _el),
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els,
+                           decode_pubsub_items(<<"http://jabber.org/protocol/pubsub">>,
+                                               __IgnoreEls, _el),
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish);
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"retract">>, _attrs, _} = _el | _els], Items,
                  Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions,
-                            decode_pubsub_retract(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                            Unsubscribe, Subscribe, Publish);
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions,
+                           decode_pubsub_retract(__TopXMLNS, __IgnoreEls, _el),
+                           Unsubscribe, Subscribe, Publish);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions,
+                           decode_pubsub_retract(<<"http://jabber.org/protocol/pubsub">>,
+                                                 __IgnoreEls, _el),
+                           Unsubscribe, Subscribe, Publish);
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls,
                  [{xmlel, <<"publish">>, _attrs, _} = _el | _els], Items,
                  Options, Affiliations, Subscriptions, Retract,
                  Unsubscribe, Subscribe, Publish) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe,
-                            decode_pubsub_publish(__TopXMLNS, __IgnoreEls,
-                                                  _el));
-       true ->
-          decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
-                            Options, Affiliations, Subscriptions, Retract,
-                            Unsubscribe, Subscribe, Publish)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe,
+                           decode_pubsub_publish(__TopXMLNS, __IgnoreEls,
+                                                 _el));
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe,
+                           decode_pubsub_publish(<<"http://jabber.org/protocol/pubsub">>,
+                                                 __IgnoreEls, _el));
+      _ ->
+         decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items,
+                           Options, Affiliations, Subscriptions, Retract,
+                           Unsubscribe, Subscribe, Publish)
     end;
 decode_pubsub_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                  Items, Options, Affiliations, Subscriptions, Retract,
@@ -7461,15 +8648,22 @@ decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, [],
 decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls,
                          [{xmlel, <<"item">>, _attrs, _} = _el | _els],
                          Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els,
-                                    [decode_pubsub_item(__TopXMLNS,
-                                                        __IgnoreEls, _el)
-                                     | Items]);
-       true ->
-          decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els,
+                                   [decode_pubsub_item(__TopXMLNS, __IgnoreEls,
+                                                       _el)
+                                    | Items]);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els,
+                                   [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>,
+                                                       __IgnoreEls, _el)
+                                    | Items]);
+      _ ->
+         decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Items)
     end;
 decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls,
                          [_ | _els], Items) ->
@@ -7549,13 +8743,14 @@ decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, [],
     Xdata;
 decode_pubsub_options_els(__TopXMLNS, __IgnoreEls,
                          [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"jabber:x:data">> ->
-          decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els,
-                                    decode_xdata(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Xdata)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"jabber:x:data">> ->
+         decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els,
+                                   decode_xdata(<<"jabber:x:data">>,
+                                                __IgnoreEls, _el));
+      _ ->
+         decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Xdata)
     end;
 decode_pubsub_options_els(__TopXMLNS, __IgnoreEls,
                          [_ | _els], Xdata) ->
@@ -7654,15 +8849,22 @@ decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, [],
 decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls,
                          [{xmlel, <<"item">>, _attrs, _} = _el | _els],
                          Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els,
-                                    [decode_pubsub_item(__TopXMLNS,
-                                                        __IgnoreEls, _el)
-                                     | Items]);
-       true ->
-          decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els,
+                                   [decode_pubsub_item(__TopXMLNS, __IgnoreEls,
+                                                       _el)
+                                    | Items]);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els,
+                                   [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>,
+                                                       __IgnoreEls, _el)
+                                    | Items]);
+      _ ->
+         decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Items)
     end;
 decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls,
                          [_ | _els], Items) ->
@@ -7857,17 +9059,26 @@ decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls,
                               [{xmlel, <<"affiliation">>, _attrs, _} = _el
                                | _els],
                               Affiliations) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls,
-                                         _els,
-                                         [decode_pubsub_affiliation(__TopXMLNS,
-                                                                    __IgnoreEls,
-                                                                    _el)
-                                          | Affiliations]);
-       true ->
-          decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls,
-                                         _els, Affiliations)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls,
+                                        _els,
+                                        [decode_pubsub_affiliation(__TopXMLNS,
+                                                                   __IgnoreEls,
+                                                                   _el)
+                                         | Affiliations]);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls,
+                                        _els,
+                                        [decode_pubsub_affiliation(<<"http://jabber.org/protocol/pubsub">>,
+                                                                   __IgnoreEls,
+                                                                   _el)
+                                         | Affiliations]);
+      _ ->
+         decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls,
+                                        _els, Affiliations)
     end;
 decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls,
                               [_ | _els], Affiliations) ->
@@ -7908,17 +9119,26 @@ decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls,
                                [{xmlel, <<"subscription">>, _attrs, _} = _el
                                 | _els],
                                Subscriptions) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls,
-                                          _els,
-                                          [decode_pubsub_subscription(__TopXMLNS,
-                                                                      __IgnoreEls,
-                                                                      _el)
-                                           | Subscriptions]);
-       true ->
-          decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls,
-                                          _els, Subscriptions)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls,
+                                         _els,
+                                         [decode_pubsub_subscription(__TopXMLNS,
+                                                                     __IgnoreEls,
+                                                                     _el)
+                                          | Subscriptions]);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls,
+                                         _els,
+                                         [decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub">>,
+                                                                     __IgnoreEls,
+                                                                     _el)
+                                          | Subscriptions]);
+      _ ->
+         decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls,
+                                         _els, Subscriptions)
     end;
 decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls,
                                [_ | _els], Subscriptions) ->
@@ -7981,15 +9201,22 @@ decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, [],
 decode_pubsub_event_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"items">>, _attrs, _} = _el | _els],
                        Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els,
-                                  [decode_pubsub_event_items(__TopXMLNS,
-                                                             __IgnoreEls, _el)
-                                   | Items]);
-       true ->
-          decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub#event">> ->
+         decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_pubsub_event_items(__TopXMLNS,
+                                                            __IgnoreEls, _el)
+                                  | Items]);
+      <<"http://jabber.org/protocol/pubsub#event">> ->
+         decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_pubsub_event_items(<<"http://jabber.org/protocol/pubsub#event">>,
+                                                            __IgnoreEls, _el)
+                                  | Items]);
+      _ ->
+         decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Items)
     end;
 decode_pubsub_event_els(__TopXMLNS, __IgnoreEls,
                        [_ | _els], Items) ->
@@ -8023,34 +9250,53 @@ decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
 decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
                              [{xmlel, <<"retract">>, _attrs, _} = _el | _els],
                              Items, Retract) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
-                                        _els, Items,
-                                        [decode_pubsub_event_retract(__TopXMLNS,
-                                                                     __IgnoreEls,
-                                                                     _el)
-                                         | Retract]);
-       true ->
-          decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
-                                        _els, Items, Retract)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub#event">> ->
+         decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
+                                       _els, Items,
+                                       [decode_pubsub_event_retract(__TopXMLNS,
+                                                                    __IgnoreEls,
+                                                                    _el)
+                                        | Retract]);
+      <<"http://jabber.org/protocol/pubsub#event">> ->
+         decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
+                                       _els, Items,
+                                       [decode_pubsub_event_retract(<<"http://jabber.org/protocol/pubsub#event">>,
+                                                                    __IgnoreEls,
+                                                                    _el)
+                                        | Retract]);
+      _ ->
+         decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
+                                       _els, Items, Retract)
     end;
 decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
                              [{xmlel, <<"item">>, _attrs, _} = _el | _els],
                              Items, Retract) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
-                                        _els,
-                                        [decode_pubsub_event_item(__TopXMLNS,
-                                                                  __IgnoreEls,
-                                                                  _el)
-                                         | Items],
-                                        Retract);
-       true ->
-          decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
-                                        _els, Items, Retract)
-    end;
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub#event">> ->
+         decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
+                                       _els,
+                                       [decode_pubsub_event_item(__TopXMLNS,
+                                                                 __IgnoreEls,
+                                                                 _el)
+                                        | Items],
+                                       Retract);
+      <<"http://jabber.org/protocol/pubsub#event">> ->
+         decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
+                                       _els,
+                                       [decode_pubsub_event_item(<<"http://jabber.org/protocol/pubsub#event">>,
+                                                                 __IgnoreEls,
+                                                                 _el)
+                                        | Items],
+                                       Retract);
+      _ ->
+         decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
+                                       _els, Items, Retract)
+    end;
 decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
                              [_ | _els], Items, Retract) ->
     decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls,
@@ -8243,15 +9489,22 @@ decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, [],
     lists:reverse(Items);
 decode_pubsub_items_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els,
-                                  [decode_pubsub_item(__TopXMLNS, __IgnoreEls,
-                                                      _el)
-                                   | Items]);
-       true ->
-          decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_pubsub_item(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                                  | Items]);
+      <<"http://jabber.org/protocol/pubsub">> ->
+         decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>,
+                                                     __IgnoreEls, _el)
+                                  | Items]);
+      _ ->
+         decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Items)
     end;
 decode_pubsub_items_els(__TopXMLNS, __IgnoreEls,
                        [_ | _els], Items) ->
@@ -8580,71 +9833,104 @@ decode_xdata_els(__TopXMLNS, __IgnoreEls, [], Fields,
 decode_xdata_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"instructions">>, _attrs, _} = _el | _els],
                 Fields, Items, Instructions, Reported, Title) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items,
-                           case decode_xdata_instructions(__TopXMLNS,
-                                                          __IgnoreEls, _el)
-                               of
-                             undefined -> Instructions;
-                             _new_el -> [_new_el | Instructions]
-                           end,
-                           Reported, Title);
-       true ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items, Instructions, Reported, Title)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items,
+                          case decode_xdata_instructions(__TopXMLNS,
+                                                         __IgnoreEls, _el)
+                              of
+                            undefined -> Instructions;
+                            _new_el -> [_new_el | Instructions]
+                          end,
+                          Reported, Title);
+      <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items,
+                          case decode_xdata_instructions(<<"jabber:x:data">>,
+                                                         __IgnoreEls, _el)
+                              of
+                            undefined -> Instructions;
+                            _new_el -> [_new_el | Instructions]
+                          end,
+                          Reported, Title);
+      _ ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions, Reported, Title)
     end;
 decode_xdata_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"title">>, _attrs, _} = _el | _els], Fields,
                 Items, Instructions, Reported, Title) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items, Instructions, Reported,
-                           decode_xdata_title(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items, Instructions, Reported, Title)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions, Reported,
+                          decode_xdata_title(__TopXMLNS, __IgnoreEls, _el));
+      <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions, Reported,
+                          decode_xdata_title(<<"jabber:x:data">>, __IgnoreEls,
+                                             _el));
+      _ ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions, Reported, Title)
     end;
 decode_xdata_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"reported">>, _attrs, _} = _el | _els],
                 Fields, Items, Instructions, Reported, Title) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items, Instructions,
-                           decode_xdata_reported(__TopXMLNS, __IgnoreEls, _el),
-                           Title);
-       true ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items, Instructions, Reported, Title)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions,
+                          decode_xdata_reported(__TopXMLNS, __IgnoreEls, _el),
+                          Title);
+      <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions,
+                          decode_xdata_reported(<<"jabber:x:data">>,
+                                                __IgnoreEls, _el),
+                          Title);
+      _ ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions, Reported, Title)
     end;
 decode_xdata_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"item">>, _attrs, _} = _el | _els], Fields,
                 Items, Instructions, Reported, Title) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           [decode_xdata_item(__TopXMLNS, __IgnoreEls, _el)
-                            | Items],
-                           Instructions, Reported, Title);
-       true ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items, Instructions, Reported, Title)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          [decode_xdata_item(__TopXMLNS, __IgnoreEls, _el)
+                           | Items],
+                          Instructions, Reported, Title);
+      <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          [decode_xdata_item(<<"jabber:x:data">>, __IgnoreEls,
+                                             _el)
+                           | Items],
+                          Instructions, Reported, Title);
+      _ ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions, Reported, Title)
     end;
 decode_xdata_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"field">>, _attrs, _} = _el | _els], Fields,
                 Items, Instructions, Reported, Title) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els,
-                           [decode_xdata_field(__TopXMLNS, __IgnoreEls, _el)
-                            | Fields],
-                           Items, Instructions, Reported, Title);
-       true ->
-          decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
-                           Items, Instructions, Reported, Title)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els,
+                          [decode_xdata_field(__TopXMLNS, __IgnoreEls, _el)
+                           | Fields],
+                          Items, Instructions, Reported, Title);
+      <<"jabber:x:data">> ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els,
+                          [decode_xdata_field(<<"jabber:x:data">>, __IgnoreEls,
+                                              _el)
+                           | Fields],
+                          Items, Instructions, Reported, Title);
+      _ ->
+         decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields,
+                          Items, Instructions, Reported, Title)
     end;
 decode_xdata_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                 Fields, Items, Instructions, Reported, Title) ->
@@ -8724,15 +10010,20 @@ decode_xdata_item_els(__TopXMLNS, __IgnoreEls, [],
 decode_xdata_item_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"field">>, _attrs, _} = _el | _els],
                      Fields) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                [decode_xdata_field(__TopXMLNS, __IgnoreEls,
-                                                    _el)
-                                 | Fields]);
-       true ->
-          decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                Fields)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els,
+                               [decode_xdata_field(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                                | Fields]);
+      <<"jabber:x:data">> ->
+         decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els,
+                               [decode_xdata_field(<<"jabber:x:data">>,
+                                                   __IgnoreEls, _el)
+                                | Fields]);
+      _ ->
+         decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els,
+                               Fields)
     end;
 decode_xdata_item_els(__TopXMLNS, __IgnoreEls,
                      [_ | _els], Fields) ->
@@ -8762,15 +10053,20 @@ decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, [],
 decode_xdata_reported_els(__TopXMLNS, __IgnoreEls,
                          [{xmlel, <<"field">>, _attrs, _} = _el | _els],
                          Fields) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els,
-                                    [decode_xdata_field(__TopXMLNS,
-                                                        __IgnoreEls, _el)
-                                     | Fields]);
-       true ->
-          decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els,
-                                    Fields)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els,
+                                   [decode_xdata_field(__TopXMLNS, __IgnoreEls,
+                                                       _el)
+                                    | Fields]);
+      <<"jabber:x:data">> ->
+         decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els,
+                                   [decode_xdata_field(<<"jabber:x:data">>,
+                                                       __IgnoreEls, _el)
+                                    | Fields]);
+      _ ->
+         decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els,
+                                   Fields)
     end;
 decode_xdata_reported_els(__TopXMLNS, __IgnoreEls,
                          [_ | _els], Fields) ->
@@ -8871,67 +10167,97 @@ decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [],
 decode_xdata_field_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"required">>, _attrs, _} = _el | _els],
                       Options, Values, Desc, Required) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Options, Values, Desc,
-                                 decode_xdata_field_required(__TopXMLNS,
-                                                             __IgnoreEls,
-                                                             _el));
-       true ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Options, Values, Desc, Required)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values, Desc,
+                                decode_xdata_field_required(__TopXMLNS,
+                                                            __IgnoreEls, _el));
+      <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values, Desc,
+                                decode_xdata_field_required(<<"jabber:x:data">>,
+                                                            __IgnoreEls, _el));
+      _ ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values, Desc, Required)
     end;
 decode_xdata_field_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"desc">>, _attrs, _} = _el | _els], Options,
                       Values, Desc, Required) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Options, Values,
-                                 decode_xdata_field_desc(__TopXMLNS,
-                                                         __IgnoreEls, _el),
-                                 Required);
-       true ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Options, Values, Desc, Required)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values,
+                                decode_xdata_field_desc(__TopXMLNS,
+                                                        __IgnoreEls, _el),
+                                Required);
+      <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values,
+                                decode_xdata_field_desc(<<"jabber:x:data">>,
+                                                        __IgnoreEls, _el),
+                                Required);
+      _ ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values, Desc, Required)
     end;
 decode_xdata_field_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"value">>, _attrs, _} = _el | _els], Options,
                       Values, Desc, Required) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Options,
-                                 case decode_xdata_field_value(__TopXMLNS,
-                                                               __IgnoreEls,
-                                                               _el)
-                                     of
-                                   undefined -> Values;
-                                   _new_el -> [_new_el | Values]
-                                 end,
-                                 Desc, Required);
-       true ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Options, Values, Desc, Required)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options,
+                                case decode_xdata_field_value(__TopXMLNS,
+                                                              __IgnoreEls, _el)
+                                    of
+                                  undefined -> Values;
+                                  _new_el -> [_new_el | Values]
+                                end,
+                                Desc, Required);
+      <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options,
+                                case
+                                  decode_xdata_field_value(<<"jabber:x:data">>,
+                                                           __IgnoreEls, _el)
+                                    of
+                                  undefined -> Values;
+                                  _new_el -> [_new_el | Values]
+                                end,
+                                Desc, Required);
+      _ ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values, Desc, Required)
     end;
 decode_xdata_field_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"option">>, _attrs, _} = _el | _els],
                       Options, Values, Desc, Required) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 case decode_xdata_field_option(__TopXMLNS,
-                                                                __IgnoreEls,
-                                                                _el)
-                                     of
-                                   undefined -> Options;
-                                   _new_el -> [_new_el | Options]
-                                 end,
-                                 Values, Desc, Required);
-       true ->
-          decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Options, Values, Desc, Required)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                case decode_xdata_field_option(__TopXMLNS,
+                                                               __IgnoreEls,
+                                                               _el)
+                                    of
+                                  undefined -> Options;
+                                  _new_el -> [_new_el | Options]
+                                end,
+                                Values, Desc, Required);
+      <<"jabber:x:data">> ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                case
+                                  decode_xdata_field_option(<<"jabber:x:data">>,
+                                                            __IgnoreEls, _el)
+                                    of
+                                  undefined -> Options;
+                                  _new_el -> [_new_el | Options]
+                                end,
+                                Values, Desc, Required);
+      _ ->
+         decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els,
+                                Options, Values, Desc, Required)
     end;
 decode_xdata_field_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Options, Values, Desc, Required) ->
@@ -9045,17 +10371,24 @@ decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
 decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
                              [{xmlel, <<"value">>, _attrs, _} = _el | _els],
                              Value) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
-                                        _els,
-                                        {value,
-                                         decode_xdata_field_value(__TopXMLNS,
-                                                                  __IgnoreEls,
-                                                                  _el)});
-       true ->
-          decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
-                                        _els, Value)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:x:data">> ->
+         decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
+                                       _els,
+                                       {value,
+                                        decode_xdata_field_value(__TopXMLNS,
+                                                                 __IgnoreEls,
+                                                                 _el)});
+      <<"jabber:x:data">> ->
+         decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
+                                       _els,
+                                       {value,
+                                        decode_xdata_field_value(<<"jabber:x:data">>,
+                                                                 __IgnoreEls,
+                                                                 _el)});
+      _ ->
+         decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
+                                       _els, Value)
     end;
 decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls,
                              [_ | _els], Value) ->
@@ -9146,41 +10479,46 @@ encode_xdata_field_required(true, _xmlns_attrs) ->
 
 decode_vcard_xupdate(__TopXMLNS, __IgnoreEls,
                     {xmlel, <<"x">>, _attrs, _els}) ->
-    Photo = decode_vcard_xupdate_els(__TopXMLNS,
-                                    __IgnoreEls, _els, undefined),
-    {vcard_xupdate, Photo}.
+    Hash = decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls,
+                                   _els, undefined),
+    {vcard_xupdate, undefined, Hash}.
 
 decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, [],
-                        Photo) ->
-    Photo;
+                        Hash) ->
+    Hash;
 decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls,
                         [{xmlel, <<"photo">>, _attrs, _} = _el | _els],
-                        Photo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els,
-                                   decode_vcard_xupdate_photo(__TopXMLNS,
-                                                              __IgnoreEls,
-                                                              _el));
-       true ->
-          decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els,
-                                   Photo)
+                        Hash) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp:x:update">> ->
+         decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els,
+                                  decode_vcard_xupdate_photo(__TopXMLNS,
+                                                             __IgnoreEls,
+                                                             _el));
+      <<"vcard-temp:x:update">> ->
+         decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els,
+                                  decode_vcard_xupdate_photo(<<"vcard-temp:x:update">>,
+                                                             __IgnoreEls,
+                                                             _el));
+      _ ->
+         decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els,
+                                  Hash)
     end;
 decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls,
-                        [_ | _els], Photo) ->
+                        [_ | _els], Hash) ->
     decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els,
-                            Photo).
+                            Hash).
 
-encode_vcard_xupdate({vcard_xupdate, Photo},
+encode_vcard_xupdate({vcard_xupdate, undefined, Hash},
                     _xmlns_attrs) ->
-    _els =
-       lists:reverse('encode_vcard_xupdate_$photo'(Photo, [])),
+    _els = lists:reverse('encode_vcard_xupdate_$hash'(Hash,
+                                                     [])),
     _attrs = _xmlns_attrs,
     {xmlel, <<"x">>, _attrs, _els}.
 
-'encode_vcard_xupdate_$photo'(undefined, _acc) -> _acc;
-'encode_vcard_xupdate_$photo'(Photo, _acc) ->
-    [encode_vcard_xupdate_photo(Photo, []) | _acc].
+'encode_vcard_xupdate_$hash'(undefined, _acc) -> _acc;
+'encode_vcard_xupdate_$hash'(Hash, _acc) ->
+    [encode_vcard_xupdate_photo(Hash, []) | _acc].
 
 decode_vcard_xupdate_photo(__TopXMLNS, __IgnoreEls,
                           {xmlel, <<"photo">>, _attrs, _els}) ->
@@ -9215,833 +10553,1153 @@ encode_vcard_xupdate_photo_cdata(undefined, _acc) ->
 encode_vcard_xupdate_photo_cdata(_val, _acc) ->
     [{xmlcdata, _val} | _acc].
 
-decode_vcard(__TopXMLNS, __IgnoreEls,
-            {xmlel, <<"vCard">>, _attrs, _els}) ->
+decode_vcard_temp(__TopXMLNS, __IgnoreEls,
+                 {xmlel, <<"vCard">>, _attrs, _els}) ->
     {Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
      Jabberid, Sound, Note, Role, Title, Nickname, Rev,
      Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
      Fn, Version, N, Photo, Logo, Geo} =
-       decode_vcard_els(__TopXMLNS, __IgnoreEls, _els,
-                        undefined, [], undefined, [], undefined, undefined,
-                        undefined, undefined, undefined, undefined, undefined,
-                        undefined, undefined, undefined, undefined, undefined,
-                        undefined, undefined, undefined, undefined, [], [], [],
-                        undefined, undefined, undefined, undefined, undefined,
-                        undefined),
-    {vcard, Version, Fn, N, Nickname, Photo, Bday, Adr,
+       decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                             undefined, [], undefined, [], undefined,
+                             undefined, undefined, undefined, undefined,
+                             undefined, undefined, undefined, undefined,
+                             undefined, undefined, undefined, undefined,
+                             undefined, undefined, undefined, [], [], [],
+                             undefined, undefined, undefined, undefined,
+                             undefined, undefined),
+    {vcard_temp, Version, Fn, N, Nickname, Photo, Bday, Adr,
      Label, Tel, Email, Jabberid, Mailer, Tz, Geo, Title,
      Role, Logo, Org, Categories, Note, Prodid, Rev,
      Sort_string, Sound, Uid, Url, Class, Key, Desc}.
 
-decode_vcard_els(__TopXMLNS, __IgnoreEls, [], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, [],
+                     Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
+                     Jabberid, Sound, Note, Role, Title, Nickname, Rev,
+                     Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
+                     Fn, Version, N, Photo, Logo, Geo) ->
     {Mailer, lists:reverse(Adr), Class, Categories, Desc,
      Uid, Prodid, Jabberid, Sound, Note, Role, Title,
      Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url,
      lists:reverse(Email), lists:reverse(Tel),
      lists:reverse(Label), Fn, Version, N, Photo, Logo, Geo};
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"N">>, _attrs, _} = _el | _els], Mailer, Adr,
-                Class, Categories, Desc, Uid, Prodid, Jabberid, Sound,
-                Note, Role, Title, Nickname, Rev, Sort_string, Org,
-                Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
-                Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version,
-                           decode_vcard_N(__TopXMLNS, __IgnoreEls, _el), Photo,
-                           Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"ADR">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           [decode_vcard_ADR(__TopXMLNS, __IgnoreEls, _el)
-                            | Adr],
-                           Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"LABEL">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           [decode_vcard_LABEL(__TopXMLNS, __IgnoreEls, _el)
-                            | Label],
-                           Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"TEL">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email,
-                           [decode_vcard_TEL(__TopXMLNS, __IgnoreEls, _el)
-                            | Tel],
-                           Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"EMAIL">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url,
-                           [decode_vcard_EMAIL(__TopXMLNS, __IgnoreEls, _el)
-                            | Email],
-                           Tel, Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"GEO">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo,
-                           decode_vcard_GEO(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"LOGO">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo,
-                           decode_vcard_LOGO(__TopXMLNS, __IgnoreEls, _el),
-                           Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"PHOTO">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N,
-                           decode_vcard_PHOTO(__TopXMLNS, __IgnoreEls, _el),
-                           Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"ORG">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string,
-                           decode_vcard_ORG(__TopXMLNS, __IgnoreEls, _el),
-                           Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                           N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"SOUND">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           decode_vcard_SOUND(__TopXMLNS, __IgnoreEls, _el),
-                           Note, Role, Title, Nickname, Rev, Sort_string, Org,
-                           Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                           N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"KEY">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday,
-                           decode_vcard_KEY(__TopXMLNS, __IgnoreEls, _el), Tz,
-                           Url, Email, Tel, Label, Fn, Version, N, Photo, Logo,
-                           Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"VERSION">>, _attrs, _} = _el | _els],
-                Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
-                Jabberid, Sound, Note, Role, Title, Nickname, Rev,
-                Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
-                Fn, Version, N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn,
-                           decode_vcard_VERSION(__TopXMLNS, __IgnoreEls, _el),
-                           N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"FN">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label,
-                           decode_vcard_FN(__TopXMLNS, __IgnoreEls, _el),
-                           Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"NICKNAME">>, _attrs, _} = _el | _els],
-                Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
-                Jabberid, Sound, Note, Role, Title, Nickname, Rev,
-                Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
-                Fn, Version, N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title,
-                           decode_vcard_NICKNAME(__TopXMLNS, __IgnoreEls, _el),
-                           Rev, Sort_string, Org, Bday, Key, Tz, Url, Email,
-                           Tel, Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"BDAY">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org,
-                           decode_vcard_BDAY(__TopXMLNS, __IgnoreEls, _el),
-                           Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
-                           Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"JABBERID">>, _attrs, _} = _el | _els],
-                Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
-                Jabberid, Sound, Note, Role, Title, Nickname, Rev,
-                Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
-                Fn, Version, N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid,
-                           decode_vcard_JABBERID(__TopXMLNS, __IgnoreEls, _el),
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"MAILER">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els,
-                           decode_vcard_MAILER(__TopXMLNS, __IgnoreEls, _el),
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"TZ">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key,
-                           decode_vcard_TZ(__TopXMLNS, __IgnoreEls, _el), Url,
-                           Email, Tel, Label, Fn, Version, N, Photo, Logo,
-                           Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"TITLE">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role,
-                           decode_vcard_TITLE(__TopXMLNS, __IgnoreEls, _el),
-                           Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url,
-                           Email, Tel, Label, Fn, Version, N, Photo, Logo,
-                           Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"ROLE">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note,
-                           decode_vcard_ROLE(__TopXMLNS, __IgnoreEls, _el),
-                           Title, Nickname, Rev, Sort_string, Org, Bday, Key,
-                           Tz, Url, Email, Tel, Label, Fn, Version, N, Photo,
-                           Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"NOTE">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound,
-                           decode_vcard_NOTE(__TopXMLNS, __IgnoreEls, _el),
-                           Role, Title, Nickname, Rev, Sort_string, Org, Bday,
-                           Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
-                           Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"PRODID">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid,
-                           decode_vcard_PRODID(__TopXMLNS, __IgnoreEls, _el),
-                           Jabberid, Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"REV">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname,
-                           decode_vcard_REV(__TopXMLNS, __IgnoreEls, _el),
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"SORT-STRING">>, _attrs, _} = _el | _els],
-                Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
-                Jabberid, Sound, Note, Role, Title, Nickname, Rev,
-                Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
-                Fn, Version, N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           decode_vcard_SORT_STRING(__TopXMLNS, __IgnoreEls,
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"N">>, _attrs, _} = _el | _els], Mailer, Adr,
+                     Class, Categories, Desc, Uid, Prodid, Jabberid, Sound,
+                     Note, Role, Title, Nickname, Rev, Sort_string, Org,
+                     Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
+                     Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version,
+                               decode_vcard_N(__TopXMLNS, __IgnoreEls, _el),
+                               Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version,
+                               decode_vcard_N(<<"vcard-temp">>, __IgnoreEls,
+                                              _el),
+                               Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"ADR">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer,
+                               [decode_vcard_ADR(__TopXMLNS, __IgnoreEls, _el)
+                                | Adr],
+                               Class, Categories, Desc, Uid, Prodid, Jabberid,
+                               Sound, Note, Role, Title, Nickname, Rev,
+                               Sort_string, Org, Bday, Key, Tz, Url, Email,
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer,
+                               [decode_vcard_ADR(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el)
+                                | Adr],
+                               Class, Categories, Desc, Uid, Prodid, Jabberid,
+                               Sound, Note, Role, Title, Nickname, Rev,
+                               Sort_string, Org, Bday, Key, Tz, Url, Email,
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"LABEL">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel,
+                               [decode_vcard_LABEL(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                                | Label],
+                               Fn, Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel,
+                               [decode_vcard_LABEL(<<"vcard-temp">>,
+                                                   __IgnoreEls, _el)
+                                | Label],
+                               Fn, Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"TEL">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email,
+                               [decode_vcard_TEL(__TopXMLNS, __IgnoreEls, _el)
+                                | Tel],
+                               Label, Fn, Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email,
+                               [decode_vcard_TEL(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el)
+                                | Tel],
+                               Label, Fn, Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"EMAIL">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url,
+                               [decode_vcard_EMAIL(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                                | Email],
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url,
+                               [decode_vcard_EMAIL(<<"vcard-temp">>,
+                                                   __IgnoreEls, _el)
+                                | Email],
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"GEO">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo,
+                               decode_vcard_GEO(__TopXMLNS, __IgnoreEls, _el));
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo,
+                               decode_vcard_GEO(<<"vcard-temp">>, __IgnoreEls,
+                                                _el));
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"LOGO">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               decode_vcard_LOGO(__TopXMLNS, __IgnoreEls, _el),
+                               Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               decode_vcard_LOGO(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                               Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"PHOTO">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N,
+                               decode_vcard_PHOTO(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                               Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N,
+                               decode_vcard_PHOTO(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                               Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"ORG">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string,
+                               decode_vcard_ORG(__TopXMLNS, __IgnoreEls, _el),
+                               Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string,
+                               decode_vcard_ORG(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                               Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"SOUND">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid,
+                               decode_vcard_SOUND(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                               Note, Role, Title, Nickname, Rev, Sort_string,
+                               Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid,
+                               decode_vcard_SOUND(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                               Note, Role, Title, Nickname, Rev, Sort_string,
+                               Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"KEY">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday,
+                               decode_vcard_KEY(__TopXMLNS, __IgnoreEls, _el),
+                               Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday,
+                               decode_vcard_KEY(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                               Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"VERSION">>, _attrs, _} = _el | _els],
+                     Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
+                     Jabberid, Sound, Note, Role, Title, Nickname, Rev,
+                     Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
+                     Fn, Version, N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn,
+                               decode_vcard_VERSION(__TopXMLNS, __IgnoreEls,
                                                     _el),
-                           Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn,
-                           Version, N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"UID">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc,
-                           decode_vcard_UID(__TopXMLNS, __IgnoreEls, _el),
-                           Prodid, Jabberid, Sound, Note, Role, Title,
-                           Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url,
-                           Email, Tel, Label, Fn, Version, N, Photo, Logo,
-                           Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"URL">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz,
-                           decode_vcard_URL(__TopXMLNS, __IgnoreEls, _el),
-                           Email, Tel, Label, Fn, Version, N, Photo, Logo,
-                           Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"DESC">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories,
-                           decode_vcard_DESC(__TopXMLNS, __IgnoreEls, _el),
-                           Uid, Prodid, Jabberid, Sound, Note, Role, Title,
-                           Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url,
-                           Email, Tel, Label, Fn, Version, N, Photo, Logo,
-                           Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"CATEGORIES">>, _attrs, _} = _el | _els],
-                Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
-                Jabberid, Sound, Note, Role, Title, Nickname, Rev,
-                Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
-                Fn, Version, N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class,
-                           decode_vcard_CATEGORIES(__TopXMLNS, __IgnoreEls,
+                               N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn,
+                               decode_vcard_VERSION(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el),
+                               N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"FN">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label,
+                               decode_vcard_FN(__TopXMLNS, __IgnoreEls, _el),
+                               Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label,
+                               decode_vcard_FN(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                               Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"NICKNAME">>, _attrs, _} = _el | _els],
+                     Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
+                     Jabberid, Sound, Note, Role, Title, Nickname, Rev,
+                     Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
+                     Fn, Version, N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               decode_vcard_NICKNAME(__TopXMLNS, __IgnoreEls,
+                                                     _el),
+                               Rev, Sort_string, Org, Bday, Key, Tz, Url,
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               decode_vcard_NICKNAME(<<"vcard-temp">>,
+                                                     __IgnoreEls, _el),
+                               Rev, Sort_string, Org, Bday, Key, Tz, Url,
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"BDAY">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org,
+                               decode_vcard_BDAY(__TopXMLNS, __IgnoreEls, _el),
+                               Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org,
+                               decode_vcard_BDAY(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                               Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"JABBERID">>, _attrs, _} = _el | _els],
+                     Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
+                     Jabberid, Sound, Note, Role, Title, Nickname, Rev,
+                     Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
+                     Fn, Version, N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid,
+                               decode_vcard_JABBERID(__TopXMLNS, __IgnoreEls,
+                                                     _el),
+                               Sound, Note, Role, Title, Nickname, Rev,
+                               Sort_string, Org, Bday, Key, Tz, Url, Email,
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid,
+                               decode_vcard_JABBERID(<<"vcard-temp">>,
+                                                     __IgnoreEls, _el),
+                               Sound, Note, Role, Title, Nickname, Rev,
+                               Sort_string, Org, Bday, Key, Tz, Url, Email,
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"MAILER">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               decode_vcard_MAILER(__TopXMLNS, __IgnoreEls,
                                                    _el),
-                           Desc, Uid, Prodid, Jabberid, Sound, Note, Role,
-                           Title, Nickname, Rev, Sort_string, Org, Bday, Key,
-                           Tz, Url, Email, Tel, Label, Fn, Version, N, Photo,
-                           Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls,
-                [{xmlel, <<"CLASS">>, _attrs, _} = _el | _els], Mailer,
-                Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                N, Photo, Logo, Geo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr,
-                           decode_vcard_CLASS(__TopXMLNS, __IgnoreEls, _el),
-                           Categories, Desc, Uid, Prodid, Jabberid, Sound,
-                           Note, Role, Title, Nickname, Rev, Sort_string, Org,
-                           Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                           N, Photo, Logo, Geo);
-       true ->
-          decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                           Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                           Sound, Note, Role, Title, Nickname, Rev,
-                           Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
-                           Label, Fn, Version, N, Photo, Logo, Geo)
-    end;
-decode_vcard_els(__TopXMLNS, __IgnoreEls, [_ | _els],
-                Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
-                Jabberid, Sound, Note, Role, Title, Nickname, Rev,
-                Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
-                Fn, Version, N, Photo, Logo, Geo) ->
-    decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer,
-                    Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
-                    Sound, Note, Role, Title, Nickname, Rev, Sort_string,
-                    Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
-                    N, Photo, Logo, Geo).
-
-encode_vcard({vcard, Version, Fn, N, Nickname, Photo,
-             Bday, Adr, Label, Tel, Email, Jabberid, Mailer, Tz, Geo,
-             Title, Role, Logo, Org, Categories, Note, Prodid, Rev,
-             Sort_string, Sound, Uid, Url, Class, Key, Desc},
-            _xmlns_attrs) ->
-    _els = lists:reverse('encode_vcard_$mailer'(Mailer,
-                                               'encode_vcard_$adr'(Adr,
-                                                                   'encode_vcard_$class'(Class,
-                                                                                         'encode_vcard_$categories'(Categories,
-                                                                                                                    'encode_vcard_$desc'(Desc,
-                                                                                                                                         'encode_vcard_$uid'(Uid,
-                                                                                                                                                             'encode_vcard_$prodid'(Prodid,
-                                                                                                                                                                                    'encode_vcard_$jabberid'(Jabberid,
-                                                                                                                                                                                                             'encode_vcard_$sound'(Sound,
-                                                                                                                                                                                                                                   'encode_vcard_$note'(Note,
-                                                                                                                                                                                                                                                        'encode_vcard_$role'(Role,
-                                                                                                                                                                                                                                                                             'encode_vcard_$title'(Title,
-                                                                                                                                                                                                                                                                                                   'encode_vcard_$nickname'(Nickname,
-                                                                                                                                                                                                                                                                                                                            'encode_vcard_$rev'(Rev,
-                                                                                                                                                                                                                                                                                                                                                'encode_vcard_$sort_string'(Sort_string,
-                                                                                                                                                                                                                                                                                                                                                                            'encode_vcard_$org'(Org,
-                                                                                                                                                                                                                                                                                                                                                                                                'encode_vcard_$bday'(Bday,
-                                                                                                                                                                                                                                                                                                                                                                                                                     'encode_vcard_$key'(Key,
-                                                                                                                                                                                                                                                                                                                                                                                                                                         'encode_vcard_$tz'(Tz,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                            'encode_vcard_$url'(Url,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                'encode_vcard_$email'(Email,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      'encode_vcard_$tel'(Tel,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          'encode_vcard_$label'(Label,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                'encode_vcard_$fn'(Fn,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   'encode_vcard_$version'(Version,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           'encode_vcard_$n'(N,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             'encode_vcard_$photo'(Photo,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   'encode_vcard_$logo'(Logo,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        'encode_vcard_$geo'(Geo,
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            [])))))))))))))))))))))))))))))),
+                               Adr, Class, Categories, Desc, Uid, Prodid,
+                               Jabberid, Sound, Note, Role, Title, Nickname,
+                               Rev, Sort_string, Org, Bday, Key, Tz, Url,
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               decode_vcard_MAILER(<<"vcard-temp">>,
+                                                   __IgnoreEls, _el),
+                               Adr, Class, Categories, Desc, Uid, Prodid,
+                               Jabberid, Sound, Note, Role, Title, Nickname,
+                               Rev, Sort_string, Org, Bday, Key, Tz, Url,
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"TZ">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key,
+                               decode_vcard_TZ(__TopXMLNS, __IgnoreEls, _el),
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key,
+                               decode_vcard_TZ(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"TITLE">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role,
+                               decode_vcard_TITLE(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role,
+                               decode_vcard_TITLE(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"ROLE">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note,
+                               decode_vcard_ROLE(__TopXMLNS, __IgnoreEls, _el),
+                               Title, Nickname, Rev, Sort_string, Org, Bday,
+                               Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note,
+                               decode_vcard_ROLE(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                               Title, Nickname, Rev, Sort_string, Org, Bday,
+                               Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"NOTE">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound,
+                               decode_vcard_NOTE(__TopXMLNS, __IgnoreEls, _el),
+                               Role, Title, Nickname, Rev, Sort_string, Org,
+                               Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound,
+                               decode_vcard_NOTE(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                               Role, Title, Nickname, Rev, Sort_string, Org,
+                               Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"PRODID">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               decode_vcard_PRODID(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                               Jabberid, Sound, Note, Role, Title, Nickname,
+                               Rev, Sort_string, Org, Bday, Key, Tz, Url,
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               decode_vcard_PRODID(<<"vcard-temp">>,
+                                                   __IgnoreEls, _el),
+                               Jabberid, Sound, Note, Role, Title, Nickname,
+                               Rev, Sort_string, Org, Bday, Key, Tz, Url,
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"REV">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname,
+                               decode_vcard_REV(__TopXMLNS, __IgnoreEls, _el),
+                               Sort_string, Org, Bday, Key, Tz, Url, Email,
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname,
+                               decode_vcard_REV(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                               Sort_string, Org, Bday, Key, Tz, Url, Email,
+                               Tel, Label, Fn, Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"SORT-STRING">>, _attrs, _} = _el | _els],
+                     Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
+                     Jabberid, Sound, Note, Role, Title, Nickname, Rev,
+                     Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
+                     Fn, Version, N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev,
+                               decode_vcard_SORT_STRING(__TopXMLNS,
+                                                        __IgnoreEls, _el),
+                               Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev,
+                               decode_vcard_SORT_STRING(<<"vcard-temp">>,
+                                                        __IgnoreEls, _el),
+                               Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"UID">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc,
+                               decode_vcard_UID(__TopXMLNS, __IgnoreEls, _el),
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc,
+                               decode_vcard_UID(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"URL">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               decode_vcard_URL(__TopXMLNS, __IgnoreEls, _el),
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               decode_vcard_URL(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                               Email, Tel, Label, Fn, Version, N, Photo, Logo,
+                               Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"DESC">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories,
+                               decode_vcard_DESC(__TopXMLNS, __IgnoreEls, _el),
+                               Uid, Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories,
+                               decode_vcard_DESC(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                               Uid, Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"CATEGORIES">>, _attrs, _} = _el | _els],
+                     Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
+                     Jabberid, Sound, Note, Role, Title, Nickname, Rev,
+                     Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label,
+                     Fn, Version, N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class,
+                               decode_vcard_CATEGORIES(__TopXMLNS, __IgnoreEls,
+                                                       _el),
+                               Desc, Uid, Prodid, Jabberid, Sound, Note, Role,
+                               Title, Nickname, Rev, Sort_string, Org, Bday,
+                               Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class,
+                               decode_vcard_CATEGORIES(<<"vcard-temp">>,
+                                                       __IgnoreEls, _el),
+                               Desc, Uid, Prodid, Jabberid, Sound, Note, Role,
+                               Title, Nickname, Rev, Sort_string, Org, Bday,
+                               Key, Tz, Url, Email, Tel, Label, Fn, Version, N,
+                               Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [{xmlel, <<"CLASS">>, _attrs, _} = _el | _els], Mailer,
+                     Adr, Class, Categories, Desc, Uid, Prodid, Jabberid,
+                     Sound, Note, Role, Title, Nickname, Rev, Sort_string,
+                     Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version,
+                     N, Photo, Logo, Geo) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr,
+                               decode_vcard_CLASS(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                               Categories, Desc, Uid, Prodid, Jabberid, Sound,
+                               Note, Role, Title, Nickname, Rev, Sort_string,
+                               Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      <<"vcard-temp">> ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr,
+                               decode_vcard_CLASS(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                               Categories, Desc, Uid, Prodid, Jabberid, Sound,
+                               Note, Role, Title, Nickname, Rev, Sort_string,
+                               Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn,
+                               Version, N, Photo, Logo, Geo);
+      _ ->
+         decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                               Mailer, Adr, Class, Categories, Desc, Uid,
+                               Prodid, Jabberid, Sound, Note, Role, Title,
+                               Nickname, Rev, Sort_string, Org, Bday, Key, Tz,
+                               Url, Email, Tel, Label, Fn, Version, N, Photo,
+                               Logo, Geo)
+    end;
+decode_vcard_temp_els(__TopXMLNS, __IgnoreEls,
+                     [_ | _els], Mailer, Adr, Class, Categories, Desc, Uid,
+                     Prodid, Jabberid, Sound, Note, Role, Title, Nickname,
+                     Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
+                     Label, Fn, Version, N, Photo, Logo, Geo) ->
+    decode_vcard_temp_els(__TopXMLNS, __IgnoreEls, _els,
+                         Mailer, Adr, Class, Categories, Desc, Uid, Prodid,
+                         Jabberid, Sound, Note, Role, Title, Nickname, Rev,
+                         Sort_string, Org, Bday, Key, Tz, Url, Email, Tel,
+                         Label, Fn, Version, N, Photo, Logo, Geo).
+
+encode_vcard_temp({vcard_temp, Version, Fn, N, Nickname,
+                  Photo, Bday, Adr, Label, Tel, Email, Jabberid, Mailer,
+                  Tz, Geo, Title, Role, Logo, Org, Categories, Note,
+                  Prodid, Rev, Sort_string, Sound, Uid, Url, Class, Key,
+                  Desc},
+                 _xmlns_attrs) ->
+    _els = lists:reverse('encode_vcard_temp_$mailer'(Mailer,
+                                                    'encode_vcard_temp_$adr'(Adr,
+                                                                             'encode_vcard_temp_$class'(Class,
+                                                                                                        'encode_vcard_temp_$categories'(Categories,
+                                                                                                                                        'encode_vcard_temp_$desc'(Desc,
+                                                                                                                                                                  'encode_vcard_temp_$uid'(Uid,
+                                                                                                                                                                                           'encode_vcard_temp_$prodid'(Prodid,
+                                                                                                                                                                                                                       'encode_vcard_temp_$jabberid'(Jabberid,
+                                                                                                                                                                                                                                                     'encode_vcard_temp_$sound'(Sound,
+                                                                                                                                                                                                                                                                                'encode_vcard_temp_$note'(Note,
+                                                                                                                                                                                                                                                                                                          'encode_vcard_temp_$role'(Role,
+                                                                                                                                                                                                                                                                                                                                    'encode_vcard_temp_$title'(Title,
+                                                                                                                                                                                                                                                                                                                                                               'encode_vcard_temp_$nickname'(Nickname,
+                                                                                                                                                                                                                                                                                                                                                                                             'encode_vcard_temp_$rev'(Rev,
+                                                                                                                                                                                                                                                                                                                                                                                                                      'encode_vcard_temp_$sort_string'(Sort_string,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                       'encode_vcard_temp_$org'(Org,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                'encode_vcard_temp_$bday'(Bday,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          'encode_vcard_temp_$key'(Key,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   'encode_vcard_temp_$tz'(Tz,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           'encode_vcard_temp_$url'(Url,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    'encode_vcard_temp_$email'(Email,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               'encode_vcard_temp_$tel'(Tel,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        'encode_vcard_temp_$label'(Label,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   'encode_vcard_temp_$fn'(Fn,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           'encode_vcard_temp_$version'(Version,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        'encode_vcard_temp_$n'(N,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               'encode_vcard_temp_$photo'(Photo,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          'encode_vcard_temp_$logo'(Logo,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    'encode_vcard_temp_$geo'(Geo,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             [])))))))))))))))))))))))))))))),
     _attrs = _xmlns_attrs,
     {xmlel, <<"vCard">>, _attrs, _els}.
 
-'encode_vcard_$mailer'(undefined, _acc) -> _acc;
-'encode_vcard_$mailer'(Mailer, _acc) ->
+'encode_vcard_temp_$mailer'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$mailer'(Mailer, _acc) ->
     [encode_vcard_MAILER(Mailer, []) | _acc].
 
-'encode_vcard_$adr'([], _acc) -> _acc;
-'encode_vcard_$adr'([Adr | _els], _acc) ->
-    'encode_vcard_$adr'(_els,
-                       [encode_vcard_ADR(Adr, []) | _acc]).
+'encode_vcard_temp_$adr'([], _acc) -> _acc;
+'encode_vcard_temp_$adr'([Adr | _els], _acc) ->
+    'encode_vcard_temp_$adr'(_els,
+                            [encode_vcard_ADR(Adr, []) | _acc]).
 
-'encode_vcard_$class'(undefined, _acc) -> _acc;
-'encode_vcard_$class'(Class, _acc) ->
+'encode_vcard_temp_$class'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$class'(Class, _acc) ->
     [encode_vcard_CLASS(Class, []) | _acc].
 
-'encode_vcard_$categories'([], _acc) -> _acc;
-'encode_vcard_$categories'(Categories, _acc) ->
+'encode_vcard_temp_$categories'([], _acc) -> _acc;
+'encode_vcard_temp_$categories'(Categories, _acc) ->
     [encode_vcard_CATEGORIES(Categories, []) | _acc].
 
-'encode_vcard_$desc'(undefined, _acc) -> _acc;
-'encode_vcard_$desc'(Desc, _acc) ->
+'encode_vcard_temp_$desc'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$desc'(Desc, _acc) ->
     [encode_vcard_DESC(Desc, []) | _acc].
 
-'encode_vcard_$uid'(undefined, _acc) -> _acc;
-'encode_vcard_$uid'(Uid, _acc) ->
+'encode_vcard_temp_$uid'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$uid'(Uid, _acc) ->
     [encode_vcard_UID(Uid, []) | _acc].
 
-'encode_vcard_$prodid'(undefined, _acc) -> _acc;
-'encode_vcard_$prodid'(Prodid, _acc) ->
+'encode_vcard_temp_$prodid'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$prodid'(Prodid, _acc) ->
     [encode_vcard_PRODID(Prodid, []) | _acc].
 
-'encode_vcard_$jabberid'(undefined, _acc) -> _acc;
-'encode_vcard_$jabberid'(Jabberid, _acc) ->
+'encode_vcard_temp_$jabberid'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$jabberid'(Jabberid, _acc) ->
     [encode_vcard_JABBERID(Jabberid, []) | _acc].
 
-'encode_vcard_$sound'(undefined, _acc) -> _acc;
-'encode_vcard_$sound'(Sound, _acc) ->
+'encode_vcard_temp_$sound'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$sound'(Sound, _acc) ->
     [encode_vcard_SOUND(Sound, []) | _acc].
 
-'encode_vcard_$note'(undefined, _acc) -> _acc;
-'encode_vcard_$note'(Note, _acc) ->
+'encode_vcard_temp_$note'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$note'(Note, _acc) ->
     [encode_vcard_NOTE(Note, []) | _acc].
 
-'encode_vcard_$role'(undefined, _acc) -> _acc;
-'encode_vcard_$role'(Role, _acc) ->
+'encode_vcard_temp_$role'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$role'(Role, _acc) ->
     [encode_vcard_ROLE(Role, []) | _acc].
 
-'encode_vcard_$title'(undefined, _acc) -> _acc;
-'encode_vcard_$title'(Title, _acc) ->
+'encode_vcard_temp_$title'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$title'(Title, _acc) ->
     [encode_vcard_TITLE(Title, []) | _acc].
 
-'encode_vcard_$nickname'(undefined, _acc) -> _acc;
-'encode_vcard_$nickname'(Nickname, _acc) ->
+'encode_vcard_temp_$nickname'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$nickname'(Nickname, _acc) ->
     [encode_vcard_NICKNAME(Nickname, []) | _acc].
 
-'encode_vcard_$rev'(undefined, _acc) -> _acc;
-'encode_vcard_$rev'(Rev, _acc) ->
+'encode_vcard_temp_$rev'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$rev'(Rev, _acc) ->
     [encode_vcard_REV(Rev, []) | _acc].
 
-'encode_vcard_$sort_string'(undefined, _acc) -> _acc;
-'encode_vcard_$sort_string'(Sort_string, _acc) ->
+'encode_vcard_temp_$sort_string'(undefined, _acc) ->
+    _acc;
+'encode_vcard_temp_$sort_string'(Sort_string, _acc) ->
     [encode_vcard_SORT_STRING(Sort_string, []) | _acc].
 
-'encode_vcard_$org'(undefined, _acc) -> _acc;
-'encode_vcard_$org'(Org, _acc) ->
+'encode_vcard_temp_$org'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$org'(Org, _acc) ->
     [encode_vcard_ORG(Org, []) | _acc].
 
-'encode_vcard_$bday'(undefined, _acc) -> _acc;
-'encode_vcard_$bday'(Bday, _acc) ->
+'encode_vcard_temp_$bday'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$bday'(Bday, _acc) ->
     [encode_vcard_BDAY(Bday, []) | _acc].
 
-'encode_vcard_$key'(undefined, _acc) -> _acc;
-'encode_vcard_$key'(Key, _acc) ->
+'encode_vcard_temp_$key'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$key'(Key, _acc) ->
     [encode_vcard_KEY(Key, []) | _acc].
 
-'encode_vcard_$tz'(undefined, _acc) -> _acc;
-'encode_vcard_$tz'(Tz, _acc) ->
+'encode_vcard_temp_$tz'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$tz'(Tz, _acc) ->
     [encode_vcard_TZ(Tz, []) | _acc].
 
-'encode_vcard_$url'(undefined, _acc) -> _acc;
-'encode_vcard_$url'(Url, _acc) ->
+'encode_vcard_temp_$url'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$url'(Url, _acc) ->
     [encode_vcard_URL(Url, []) | _acc].
 
-'encode_vcard_$email'([], _acc) -> _acc;
-'encode_vcard_$email'([Email | _els], _acc) ->
-    'encode_vcard_$email'(_els,
-                         [encode_vcard_EMAIL(Email, []) | _acc]).
+'encode_vcard_temp_$email'([], _acc) -> _acc;
+'encode_vcard_temp_$email'([Email | _els], _acc) ->
+    'encode_vcard_temp_$email'(_els,
+                              [encode_vcard_EMAIL(Email, []) | _acc]).
 
-'encode_vcard_$tel'([], _acc) -> _acc;
-'encode_vcard_$tel'([Tel | _els], _acc) ->
-    'encode_vcard_$tel'(_els,
-                       [encode_vcard_TEL(Tel, []) | _acc]).
+'encode_vcard_temp_$tel'([], _acc) -> _acc;
+'encode_vcard_temp_$tel'([Tel | _els], _acc) ->
+    'encode_vcard_temp_$tel'(_els,
+                            [encode_vcard_TEL(Tel, []) | _acc]).
 
-'encode_vcard_$label'([], _acc) -> _acc;
-'encode_vcard_$label'([Label | _els], _acc) ->
-    'encode_vcard_$label'(_els,
-                         [encode_vcard_LABEL(Label, []) | _acc]).
+'encode_vcard_temp_$label'([], _acc) -> _acc;
+'encode_vcard_temp_$label'([Label | _els], _acc) ->
+    'encode_vcard_temp_$label'(_els,
+                              [encode_vcard_LABEL(Label, []) | _acc]).
 
-'encode_vcard_$fn'(undefined, _acc) -> _acc;
-'encode_vcard_$fn'(Fn, _acc) ->
+'encode_vcard_temp_$fn'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$fn'(Fn, _acc) ->
     [encode_vcard_FN(Fn, []) | _acc].
 
-'encode_vcard_$version'(undefined, _acc) -> _acc;
-'encode_vcard_$version'(Version, _acc) ->
+'encode_vcard_temp_$version'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$version'(Version, _acc) ->
     [encode_vcard_VERSION(Version, []) | _acc].
 
-'encode_vcard_$n'(undefined, _acc) -> _acc;
-'encode_vcard_$n'(N, _acc) ->
+'encode_vcard_temp_$n'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$n'(N, _acc) ->
     [encode_vcard_N(N, []) | _acc].
 
-'encode_vcard_$photo'(undefined, _acc) -> _acc;
-'encode_vcard_$photo'(Photo, _acc) ->
+'encode_vcard_temp_$photo'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$photo'(Photo, _acc) ->
     [encode_vcard_PHOTO(Photo, []) | _acc].
 
-'encode_vcard_$logo'(undefined, _acc) -> _acc;
-'encode_vcard_$logo'(Logo, _acc) ->
+'encode_vcard_temp_$logo'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$logo'(Logo, _acc) ->
     [encode_vcard_LOGO(Logo, []) | _acc].
 
-'encode_vcard_$geo'(undefined, _acc) -> _acc;
-'encode_vcard_$geo'(Geo, _acc) ->
+'encode_vcard_temp_$geo'(undefined, _acc) -> _acc;
+'encode_vcard_temp_$geo'(Geo, _acc) ->
     [encode_vcard_GEO(Geo, []) | _acc].
 
 decode_vcard_CLASS(__TopXMLNS, __IgnoreEls,
@@ -10056,38 +11714,50 @@ decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, [],
 decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"PUBLIC">>, _attrs, _} = _el | _els],
                       Class) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
-                                 decode_vcard_PUBLIC(__TopXMLNS, __IgnoreEls,
-                                                     _el));
-       true ->
-          decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Class)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_PUBLIC(__TopXMLNS, __IgnoreEls,
+                                                    _el));
+      <<"vcard-temp">> ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_PUBLIC(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el));
+      _ ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                Class)
     end;
 decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"PRIVATE">>, _attrs, _} = _el | _els],
                       Class) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
-                                 decode_vcard_PRIVATE(__TopXMLNS, __IgnoreEls,
-                                                      _el));
-       true ->
-          decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Class)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_PRIVATE(__TopXMLNS, __IgnoreEls,
+                                                     _el));
+      <<"vcard-temp">> ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_PRIVATE(<<"vcard-temp">>,
+                                                     __IgnoreEls, _el));
+      _ ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                Class)
     end;
 decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"CONFIDENTIAL">>, _attrs, _} = _el | _els],
                       Class) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
-                                 decode_vcard_CONFIDENTIAL(__TopXMLNS,
-                                                           __IgnoreEls, _el));
-       true ->
-          decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Class)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_CONFIDENTIAL(__TopXMLNS,
+                                                          __IgnoreEls, _el));
+      <<"vcard-temp">> ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_CONFIDENTIAL(<<"vcard-temp">>,
+                                                          __IgnoreEls, _el));
+      _ ->
+         decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els,
+                                Class)
     end;
 decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Class) ->
@@ -10121,20 +11791,30 @@ decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, [],
 decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls,
                            [{xmlel, <<"KEYWORD">>, _attrs, _} = _el | _els],
                            Keywords) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls,
-                                      _els,
-                                      case decode_vcard_KEYWORD(__TopXMLNS,
-                                                                __IgnoreEls,
-                                                                _el)
-                                          of
-                                        undefined -> Keywords;
-                                        _new_el -> [_new_el | Keywords]
-                                      end);
-       true ->
-          decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls,
-                                      _els, Keywords)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     case decode_vcard_KEYWORD(__TopXMLNS,
+                                                               __IgnoreEls,
+                                                               _el)
+                                         of
+                                       undefined -> Keywords;
+                                       _new_el -> [_new_el | Keywords]
+                                     end);
+      <<"vcard-temp">> ->
+         decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     case
+                                       decode_vcard_KEYWORD(<<"vcard-temp">>,
+                                                            __IgnoreEls, _el)
+                                         of
+                                       undefined -> Keywords;
+                                       _new_el -> [_new_el | Keywords]
+                                     end);
+      _ ->
+         decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls,
+                                     _els, Keywords)
     end;
 decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls,
                            [_ | _els], Keywords) ->
@@ -10168,27 +11848,36 @@ decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, [], Cred,
 decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"TYPE">>, _attrs, _} = _el | _els], Cred,
                     Type) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
-                               Cred,
-                               decode_vcard_TYPE(__TopXMLNS, __IgnoreEls,
-                                                 _el));
-       true ->
-          decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
-                               Cred, Type)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
+                              Cred,
+                              decode_vcard_TYPE(__TopXMLNS, __IgnoreEls, _el));
+      <<"vcard-temp">> ->
+         decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
+                              Cred,
+                              decode_vcard_TYPE(<<"vcard-temp">>, __IgnoreEls,
+                                                _el));
+      _ ->
+         decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
+                              Cred, Type)
     end;
 decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"CRED">>, _attrs, _} = _el | _els], Cred,
                     Type) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_vcard_CRED(__TopXMLNS, __IgnoreEls, _el),
-                               Type);
-       true ->
-          decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
-                               Cred, Type)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_CRED(__TopXMLNS, __IgnoreEls, _el),
+                              Type);
+      <<"vcard-temp">> ->
+         decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_CRED(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Type);
+      _ ->
+         decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els,
+                              Cred, Type)
     end;
 decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Cred, Type) ->
@@ -10224,42 +11913,58 @@ decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, [],
 decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"BINVAL">>, _attrs, _} = _el | _els],
                       Phonetic, Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Phonetic, Extval,
-                                 decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls,
-                                                     _el));
-       true ->
-          decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Phonetic, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                Phonetic, Extval,
+                                decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls,
+                                                    _el));
+      <<"vcard-temp">> ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                Phonetic, Extval,
+                                decode_vcard_BINVAL(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el));
+      _ ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                Phonetic, Extval, Binval)
     end;
 decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"EXTVAL">>, _attrs, _} = _el | _els],
                       Phonetic, Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Phonetic,
-                                 decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls,
-                                                     _el),
-                                 Binval);
-       true ->
-          decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Phonetic, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                Phonetic,
+                                decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                                Binval);
+      <<"vcard-temp">> ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                Phonetic,
+                                decode_vcard_EXTVAL(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el),
+                                Binval);
+      _ ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                Phonetic, Extval, Binval)
     end;
 decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"PHONETIC">>, _attrs, _} = _el | _els],
                       Phonetic, Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
-                                 decode_vcard_PHONETIC(__TopXMLNS, __IgnoreEls,
-                                                       _el),
-                                 Extval, Binval);
-       true ->
-          decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Phonetic, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_PHONETIC(__TopXMLNS, __IgnoreEls,
+                                                      _el),
+                                Extval, Binval);
+      <<"vcard-temp">> ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_PHONETIC(<<"vcard-temp">>,
+                                                      __IgnoreEls, _el),
+                                Extval, Binval);
+      _ ->
+         decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els,
+                                Phonetic, Extval, Binval)
     end;
 decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Phonetic, Extval, Binval) ->
@@ -10301,32 +12006,46 @@ decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, [], Units,
 decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"ORGNAME">>, _attrs, _} = _el | _els], Units,
                     Name) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
-                               Units,
-                               decode_vcard_ORGNAME(__TopXMLNS, __IgnoreEls,
-                                                    _el));
-       true ->
-          decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
-                               Units, Name)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
+                              Units,
+                              decode_vcard_ORGNAME(__TopXMLNS, __IgnoreEls,
+                                                   _el));
+      <<"vcard-temp">> ->
+         decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
+                              Units,
+                              decode_vcard_ORGNAME(<<"vcard-temp">>,
+                                                   __IgnoreEls, _el));
+      _ ->
+         decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
+                              Units, Name)
     end;
 decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"ORGUNIT">>, _attrs, _} = _el | _els], Units,
                     Name) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
-                               case decode_vcard_ORGUNIT(__TopXMLNS,
-                                                         __IgnoreEls, _el)
-                                   of
-                                 undefined -> Units;
-                                 _new_el -> [_new_el | Units]
-                               end,
-                               Name);
-       true ->
-          decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
-                               Units, Name)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
+                              case decode_vcard_ORGUNIT(__TopXMLNS,
+                                                        __IgnoreEls, _el)
+                                  of
+                                undefined -> Units;
+                                _new_el -> [_new_el | Units]
+                              end,
+                              Name);
+      <<"vcard-temp">> ->
+         decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
+                              case decode_vcard_ORGUNIT(<<"vcard-temp">>,
+                                                        __IgnoreEls, _el)
+                                  of
+                                undefined -> Units;
+                                _new_el -> [_new_el | Units]
+                              end,
+                              Name);
+      _ ->
+         decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els,
+                              Units, Name)
     end;
 decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Units, Name) ->
@@ -10363,42 +12082,58 @@ decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, [],
 decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"TYPE">>, _attrs, _} = _el | _els], Type,
                       Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
-                                 decode_vcard_TYPE(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Extval, Binval);
-       true ->
-          decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Type, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_TYPE(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Extval, Binval);
+      <<"vcard-temp">> ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_TYPE(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Extval, Binval);
+      _ ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                Type, Extval, Binval)
     end;
 decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"BINVAL">>, _attrs, _} = _el | _els], Type,
                       Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Type, Extval,
-                                 decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls,
-                                                     _el));
-       true ->
-          decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Type, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                Type, Extval,
+                                decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls,
+                                                    _el));
+      <<"vcard-temp">> ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                Type, Extval,
+                                decode_vcard_BINVAL(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el));
+      _ ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                Type, Extval, Binval)
     end;
 decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"EXTVAL">>, _attrs, _} = _el | _els], Type,
                       Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Type,
-                                 decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls,
-                                                     _el),
-                                 Binval);
-       true ->
-          decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Type, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                Type,
+                                decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                                Binval);
+      <<"vcard-temp">> ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                Type,
+                                decode_vcard_EXTVAL(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el),
+                                Binval);
+      _ ->
+         decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els,
+                                Type, Extval, Binval)
     end;
 decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Type, Extval, Binval) ->
@@ -10439,42 +12174,57 @@ decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, [], Type,
 decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"TYPE">>, _attrs, _} = _el | _els], Type,
                      Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
-                                decode_vcard_TYPE(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                                Extval, Binval);
-       true ->
-          decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
-                                Type, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               decode_vcard_TYPE(__TopXMLNS, __IgnoreEls, _el),
+                               Extval, Binval);
+      <<"vcard-temp">> ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               decode_vcard_TYPE(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                               Extval, Binval);
+      _ ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               Type, Extval, Binval)
     end;
 decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"BINVAL">>, _attrs, _} = _el | _els], Type,
                      Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
-                                Type, Extval,
-                                decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls,
-                                                    _el));
-       true ->
-          decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
-                                Type, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               Type, Extval,
+                               decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls,
+                                                   _el));
+      <<"vcard-temp">> ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               Type, Extval,
+                               decode_vcard_BINVAL(<<"vcard-temp">>,
+                                                   __IgnoreEls, _el));
+      _ ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               Type, Extval, Binval)
     end;
 decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"EXTVAL">>, _attrs, _} = _el | _els], Type,
                      Extval, Binval) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
-                                Type,
-                                decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls,
-                                                    _el),
-                                Binval);
-       true ->
-          decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
-                                Type, Extval, Binval)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               Type,
+                               decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                               Binval);
+      <<"vcard-temp">> ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               Type,
+                               decode_vcard_EXTVAL(<<"vcard-temp">>,
+                                                   __IgnoreEls, _el),
+                               Binval);
+      _ ->
+         decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els,
+                               Type, Extval, Binval)
     end;
 decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls,
                      [_ | _els], Type, Extval, Binval) ->
@@ -10551,25 +12301,34 @@ decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, [], Lat,
 decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"LAT">>, _attrs, _} = _el | _els], Lat,
                     Lon) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_vcard_LAT(__TopXMLNS, __IgnoreEls, _el),
-                               Lon);
-       true ->
-          decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat,
-                               Lon)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_LAT(__TopXMLNS, __IgnoreEls, _el),
+                              Lon);
+      <<"vcard-temp">> ->
+         decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_LAT(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                              Lon);
+      _ ->
+         decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat,
+                              Lon)
     end;
 decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"LON">>, _attrs, _} = _el | _els], Lat,
                     Lon) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat,
-                               decode_vcard_LON(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat,
-                               Lon)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat,
+                              decode_vcard_LON(__TopXMLNS, __IgnoreEls, _el));
+      <<"vcard-temp">> ->
+         decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat,
+                              decode_vcard_LON(<<"vcard-temp">>, __IgnoreEls,
+                                               _el));
+      _ ->
+         decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat,
+                              Lon)
     end;
 decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Lat, Lon) ->
@@ -10604,84 +12363,118 @@ decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [],
 decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], X400,
                       Userid, Internet, Home, Pref, Work) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet,
-                                 decode_vcard_HOME(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Pref, Work);
-       true ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home, Pref, Work)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet,
+                                decode_vcard_HOME(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Pref, Work);
+      <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet,
+                                decode_vcard_HOME(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Pref, Work);
+      _ ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref, Work)
     end;
 decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], X400,
                       Userid, Internet, Home, Pref, Work) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home, Pref,
-                                 decode_vcard_WORK(__TopXMLNS, __IgnoreEls,
-                                                   _el));
-       true ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home, Pref, Work)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref,
+                                decode_vcard_WORK(__TopXMLNS, __IgnoreEls,
+                                                  _el));
+      <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref,
+                                decode_vcard_WORK(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el));
+      _ ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref, Work)
     end;
 decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"INTERNET">>, _attrs, _} = _el | _els], X400,
                       Userid, Internet, Home, Pref, Work) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid,
-                                 decode_vcard_INTERNET(__TopXMLNS, __IgnoreEls,
-                                                       _el),
-                                 Home, Pref, Work);
-       true ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home, Pref, Work)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid,
+                                decode_vcard_INTERNET(__TopXMLNS, __IgnoreEls,
+                                                      _el),
+                                Home, Pref, Work);
+      <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid,
+                                decode_vcard_INTERNET(<<"vcard-temp">>,
+                                                      __IgnoreEls, _el),
+                                Home, Pref, Work);
+      _ ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref, Work)
     end;
 decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], X400,
                       Userid, Internet, Home, Pref, Work) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home,
-                                 decode_vcard_PREF(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Work);
-       true ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home, Pref, Work)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home,
+                                decode_vcard_PREF(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Work);
+      <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home,
+                                decode_vcard_PREF(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Work);
+      _ ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref, Work)
     end;
 decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"X400">>, _attrs, _} = _el | _els], X400,
                       Userid, Internet, Home, Pref, Work) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 decode_vcard_X400(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Userid, Internet, Home, Pref, Work);
-       true ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home, Pref, Work)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_X400(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Userid, Internet, Home, Pref, Work);
+      <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_vcard_X400(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Userid, Internet, Home, Pref, Work);
+      _ ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref, Work)
     end;
 decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"USERID">>, _attrs, _} = _el | _els], X400,
                       Userid, Internet, Home, Pref, Work) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400,
-                                 decode_vcard_USERID(__TopXMLNS, __IgnoreEls,
-                                                     _el),
-                                 Internet, Home, Pref, Work);
-       true ->
-          decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 X400, Userid, Internet, Home, Pref, Work)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400,
+                                decode_vcard_USERID(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                                Internet, Home, Pref, Work);
+      <<"vcard-temp">> ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400,
+                                decode_vcard_USERID(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el),
+                                Internet, Home, Pref, Work);
+      _ ->
+         decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els,
+                                X400, Userid, Internet, Home, Pref, Work)
     end;
 decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], X400, Userid, Internet, Home, Pref, Work) ->
@@ -10745,224 +12538,313 @@ decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice,
-                               decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el),
-                               Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice,
+                              decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el),
+                              Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice,
+                              decode_vcard_HOME(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax,
-                               decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el),
-                               Cell, Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax,
+                              decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el),
+                              Cell, Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax,
+                              decode_vcard_WORK(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Cell, Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"VOICE">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs,
-                               decode_vcard_VOICE(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                               Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn,
-                               Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs,
+                              decode_vcard_VOICE(__TopXMLNS, __IgnoreEls, _el),
+                              Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn,
+                              Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs,
+                              decode_vcard_VOICE(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                              Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn,
+                              Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"FAX">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               decode_vcard_FAX(__TopXMLNS, __IgnoreEls, _el),
-                               Work, Cell, Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              decode_vcard_FAX(__TopXMLNS, __IgnoreEls, _el),
+                              Work, Cell, Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              decode_vcard_FAX(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                              Work, Cell, Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"PAGER">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number,
-                               decode_vcard_PAGER(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                               Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
-                               Cell, Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number,
+                              decode_vcard_PAGER(__TopXMLNS, __IgnoreEls, _el),
+                              Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
+                              Cell, Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number,
+                              decode_vcard_PAGER(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                              Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
+                              Cell, Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"MSG">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref,
-                               decode_vcard_MSG(__TopXMLNS, __IgnoreEls, _el),
-                               Fax, Work, Cell, Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref,
+                              decode_vcard_MSG(__TopXMLNS, __IgnoreEls, _el),
+                              Fax, Work, Cell, Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref,
+                              decode_vcard_MSG(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                              Fax, Work, Cell, Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"CELL">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work,
-                               decode_vcard_CELL(__TopXMLNS, __IgnoreEls, _el),
-                               Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work,
+                              decode_vcard_CELL(__TopXMLNS, __IgnoreEls, _el),
+                              Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work,
+                              decode_vcard_CELL(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"VIDEO">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn,
-                               decode_vcard_VIDEO(__TopXMLNS, __IgnoreEls,
-                                                  _el));
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn,
+                              decode_vcard_VIDEO(__TopXMLNS, __IgnoreEls,
+                                                 _el));
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn,
+                              decode_vcard_VIDEO(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el));
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"BBS">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs,
-                               decode_vcard_BBS(__TopXMLNS, __IgnoreEls, _el),
-                               Voice, Home, Pref, Msg, Fax, Work, Cell, Modem,
-                               Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs,
+                              decode_vcard_BBS(__TopXMLNS, __IgnoreEls, _el),
+                              Voice, Home, Pref, Msg, Fax, Work, Cell, Modem,
+                              Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs,
+                              decode_vcard_BBS(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                              Voice, Home, Pref, Msg, Fax, Work, Cell, Modem,
+                              Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"MODEM">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell,
-                               decode_vcard_MODEM(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                               Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell,
+                              decode_vcard_MODEM(__TopXMLNS, __IgnoreEls, _el),
+                              Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell,
+                              decode_vcard_MODEM(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                              Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"ISDN">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem,
-                               decode_vcard_ISDN(__TopXMLNS, __IgnoreEls, _el),
-                               Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem,
+                              decode_vcard_ISDN(__TopXMLNS, __IgnoreEls, _el),
+                              Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem,
+                              decode_vcard_ISDN(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"PCS">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager,
-                               decode_vcard_PCS(__TopXMLNS, __IgnoreEls, _el),
-                               Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell,
-                               Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager,
+                              decode_vcard_PCS(__TopXMLNS, __IgnoreEls, _el),
+                              Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell,
+                              Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager,
+                              decode_vcard_PCS(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                              Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell,
+                              Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home,
-                               decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el),
-                               Msg, Fax, Work, Cell, Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home,
+                              decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el),
+                              Msg, Fax, Work, Cell, Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home,
+                              decode_vcard_PREF(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Msg, Fax, Work, Cell, Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"NUMBER">>, _attrs, _} = _el | _els], Number,
                     Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work,
                     Cell, Modem, Isdn, Video) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_vcard_NUMBER(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                               Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax,
-                               Work, Cell, Modem, Isdn, Video);
-       true ->
-          decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
-                               Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
-                               Fax, Work, Cell, Modem, Isdn, Video)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_NUMBER(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                              Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax,
+                              Work, Cell, Modem, Isdn, Video);
+      <<"vcard-temp">> ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_NUMBER(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                              Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax,
+                              Work, Cell, Modem, Isdn, Video);
+      _ ->
+         decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els,
+                              Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg,
+                              Fax, Work, Cell, Modem, Isdn, Video)
     end;
 decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref,
@@ -11065,124 +12947,174 @@ decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [],
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line,
-                                 decode_vcard_HOME(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Pref, Work, Intl, Parcel, Postal, Dom);
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line,
+                                decode_vcard_HOME(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Pref, Work, Intl, Parcel, Postal, Dom);
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line,
+                                decode_vcard_HOME(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Pref, Work, Intl, Parcel, Postal, Dom);
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref,
-                                 decode_vcard_WORK(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Intl, Parcel, Postal, Dom);
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref,
+                                decode_vcard_WORK(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Intl, Parcel, Postal, Dom);
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref,
+                                decode_vcard_WORK(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Intl, Parcel, Postal, Dom);
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"POSTAL">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel,
-                                 decode_vcard_POSTAL(__TopXMLNS, __IgnoreEls,
-                                                     _el),
-                                 Dom);
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel,
+                                decode_vcard_POSTAL(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                                Dom);
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel,
+                                decode_vcard_POSTAL(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el),
+                                Dom);
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"PARCEL">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl,
-                                 decode_vcard_PARCEL(__TopXMLNS, __IgnoreEls,
-                                                     _el),
-                                 Postal, Dom);
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl,
+                                decode_vcard_PARCEL(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                                Postal, Dom);
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl,
+                                decode_vcard_PARCEL(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el),
+                                Postal, Dom);
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"DOM">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 decode_vcard_DOM(__TopXMLNS, __IgnoreEls,
-                                                  _el));
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                decode_vcard_DOM(__TopXMLNS, __IgnoreEls,
+                                                 _el));
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                decode_vcard_DOM(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el));
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"INTL">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work,
-                                 decode_vcard_INTL(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Parcel, Postal, Dom);
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work,
+                                decode_vcard_INTL(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Parcel, Postal, Dom);
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work,
+                                decode_vcard_INTL(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Parcel, Postal, Dom);
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home,
-                                 decode_vcard_PREF(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                                 Work, Intl, Parcel, Postal, Dom);
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home,
+                                decode_vcard_PREF(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                                Work, Intl, Parcel, Postal, Dom);
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home,
+                                decode_vcard_PREF(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                                Work, Intl, Parcel, Postal, Dom);
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"LINE">>, _attrs, _} = _el | _els], Line,
                       Home, Pref, Work, Intl, Parcel, Postal, Dom) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 case decode_vcard_LINE(__TopXMLNS,
-                                                        __IgnoreEls, _el)
-                                     of
-                                   undefined -> Line;
-                                   _new_el -> [_new_el | Line]
-                                 end,
-                                 Home, Pref, Work, Intl, Parcel, Postal, Dom);
-       true ->
-          decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Line, Home, Pref, Work, Intl, Parcel, Postal,
-                                 Dom)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                case decode_vcard_LINE(__TopXMLNS, __IgnoreEls,
+                                                       _el)
+                                    of
+                                  undefined -> Line;
+                                  _new_el -> [_new_el | Line]
+                                end,
+                                Home, Pref, Work, Intl, Parcel, Postal, Dom);
+      <<"vcard-temp">> ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                case decode_vcard_LINE(<<"vcard-temp">>,
+                                                       __IgnoreEls, _el)
+                                    of
+                                  undefined -> Line;
+                                  _new_el -> [_new_el | Line]
+                                end,
+                                Home, Pref, Work, Intl, Parcel, Postal, Dom);
+      _ ->
+         decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els,
+                                Line, Home, Pref, Work, Intl, Parcel, Postal,
+                                Dom)
     end;
 decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Line, Home, Pref, Work, Intl, Parcel,
@@ -11258,245 +13190,337 @@ decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode,
-                               decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el),
-                               Pref, Pobox, Ctry, Locality, Work, Intl, Parcel,
-                               Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode,
+                              decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el),
+                              Pref, Pobox, Ctry, Locality, Work, Intl, Parcel,
+                              Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode,
+                              decode_vcard_HOME(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Pref, Pobox, Ctry, Locality, Work, Intl, Parcel,
+                              Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality,
-                               decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el),
-                               Intl, Parcel, Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality,
+                              decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el),
+                              Intl, Parcel, Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality,
+                              decode_vcard_WORK(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Intl, Parcel, Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"POSTAL">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel,
-                               decode_vcard_POSTAL(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                               Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel,
+                              decode_vcard_POSTAL(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                              Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel,
+                              decode_vcard_POSTAL(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                              Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"PARCEL">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl,
-                               decode_vcard_PARCEL(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                               Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl,
+                              decode_vcard_PARCEL(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                              Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl,
+                              decode_vcard_PARCEL(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                              Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"DOM">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal,
-                               decode_vcard_DOM(__TopXMLNS, __IgnoreEls, _el),
-                               Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal,
+                              decode_vcard_DOM(__TopXMLNS, __IgnoreEls, _el),
+                              Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal,
+                              decode_vcard_DOM(<<"vcard-temp">>, __IgnoreEls,
+                                               _el),
+                              Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"INTL">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work,
-                               decode_vcard_INTL(__TopXMLNS, __IgnoreEls, _el),
-                               Parcel, Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work,
+                              decode_vcard_INTL(__TopXMLNS, __IgnoreEls, _el),
+                              Parcel, Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work,
+                              decode_vcard_INTL(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Parcel, Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home,
-                               decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el),
-                               Pobox, Ctry, Locality, Work, Intl, Parcel,
-                               Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home,
+                              decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el),
+                              Pobox, Ctry, Locality, Work, Intl, Parcel,
+                              Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home,
+                              decode_vcard_PREF(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Pobox, Ctry, Locality, Work, Intl, Parcel,
+                              Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"POBOX">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref,
-                               decode_vcard_POBOX(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                               Ctry, Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref,
+                              decode_vcard_POBOX(__TopXMLNS, __IgnoreEls, _el),
+                              Ctry, Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref,
+                              decode_vcard_POBOX(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                              Ctry, Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"EXTADD">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street,
-                               decode_vcard_EXTADD(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                               Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
-                               Intl, Parcel, Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street,
+                              decode_vcard_EXTADD(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                              Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
+                              Intl, Parcel, Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street,
+                              decode_vcard_EXTADD(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                              Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
+                              Intl, Parcel, Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"STREET">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               decode_vcard_STREET(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                               Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_STREET(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                              Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality,
+                              Work, Intl, Parcel, Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              decode_vcard_STREET(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el),
+                              Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality,
+                              Work, Intl, Parcel, Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"LOCALITY">>, _attrs, _} = _el | _els],
                     Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
                     Locality, Work, Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               decode_vcard_LOCALITY(__TopXMLNS, __IgnoreEls,
-                                                     _el),
-                               Work, Intl, Parcel, Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              decode_vcard_LOCALITY(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                              Work, Intl, Parcel, Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              decode_vcard_LOCALITY(<<"vcard-temp">>,
+                                                    __IgnoreEls, _el),
+                              Work, Intl, Parcel, Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"REGION">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               decode_vcard_REGION(__TopXMLNS, __IgnoreEls,
-                                                   _el));
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              decode_vcard_REGION(__TopXMLNS, __IgnoreEls,
+                                                  _el));
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              decode_vcard_REGION(<<"vcard-temp">>,
+                                                  __IgnoreEls, _el));
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"PCODE">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd,
-                               decode_vcard_PCODE(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                               Home, Pref, Pobox, Ctry, Locality, Work, Intl,
-                               Parcel, Postal, Dom, Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd,
+                              decode_vcard_PCODE(__TopXMLNS, __IgnoreEls, _el),
+                              Home, Pref, Pobox, Ctry, Locality, Work, Intl,
+                              Parcel, Postal, Dom, Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd,
+                              decode_vcard_PCODE(<<"vcard-temp">>, __IgnoreEls,
+                                                 _el),
+                              Home, Pref, Pobox, Ctry, Locality, Work, Intl,
+                              Parcel, Postal, Dom, Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [{xmlel, <<"CTRY">>, _attrs, _} = _el | _els], Street,
                     Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work,
                     Intl, Parcel, Postal, Dom, Region) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox,
-                               decode_vcard_CTRY(__TopXMLNS, __IgnoreEls, _el),
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region);
-       true ->
-          decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
-                               Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
-                               Locality, Work, Intl, Parcel, Postal, Dom,
-                               Region)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox,
+                              decode_vcard_CTRY(__TopXMLNS, __IgnoreEls, _el),
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region);
+      <<"vcard-temp">> ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox,
+                              decode_vcard_CTRY(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region);
+      _ ->
+         decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els,
+                              Street, Extadd, Pcode, Home, Pref, Pobox, Ctry,
+                              Locality, Work, Intl, Parcel, Postal, Dom,
+                              Region)
     end;
 decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls,
                     [_ | _els], Street, Extadd, Pcode, Home, Pref, Pobox,
@@ -11598,65 +13622,93 @@ decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [], Middle,
 decode_vcard_N_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"FAMILY">>, _attrs, _} = _el | _els], Middle,
                   Suffix, Prefix, Family, Given) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix, Prefix,
-                             decode_vcard_FAMILY(__TopXMLNS, __IgnoreEls, _el),
-                             Given);
-       true ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix, Prefix, Family, Given)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix,
+                            decode_vcard_FAMILY(__TopXMLNS, __IgnoreEls, _el),
+                            Given);
+      <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix,
+                            decode_vcard_FAMILY(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                            Given);
+      _ ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix, Family, Given)
     end;
 decode_vcard_N_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"GIVEN">>, _attrs, _} = _el | _els], Middle,
                   Suffix, Prefix, Family, Given) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix, Prefix, Family,
-                             decode_vcard_GIVEN(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix, Prefix, Family, Given)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix, Family,
+                            decode_vcard_GIVEN(__TopXMLNS, __IgnoreEls, _el));
+      <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix, Family,
+                            decode_vcard_GIVEN(<<"vcard-temp">>, __IgnoreEls,
+                                               _el));
+      _ ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix, Family, Given)
     end;
 decode_vcard_N_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"MIDDLE">>, _attrs, _} = _el | _els], Middle,
                   Suffix, Prefix, Family, Given) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             decode_vcard_MIDDLE(__TopXMLNS, __IgnoreEls, _el),
-                             Suffix, Prefix, Family, Given);
-       true ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix, Prefix, Family, Given)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_vcard_MIDDLE(__TopXMLNS, __IgnoreEls, _el),
+                            Suffix, Prefix, Family, Given);
+      <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_vcard_MIDDLE(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                            Suffix, Prefix, Family, Given);
+      _ ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix, Family, Given)
     end;
 decode_vcard_N_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"PREFIX">>, _attrs, _} = _el | _els], Middle,
                   Suffix, Prefix, Family, Given) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix,
-                             decode_vcard_PREFIX(__TopXMLNS, __IgnoreEls, _el),
-                             Family, Given);
-       true ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix, Prefix, Family, Given)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix,
+                            decode_vcard_PREFIX(__TopXMLNS, __IgnoreEls, _el),
+                            Family, Given);
+      <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix,
+                            decode_vcard_PREFIX(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                            Family, Given);
+      _ ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix, Family, Given)
     end;
 decode_vcard_N_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"SUFFIX">>, _attrs, _} = _el | _els], Middle,
                   Suffix, Prefix, Family, Given) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle,
-                             decode_vcard_SUFFIX(__TopXMLNS, __IgnoreEls, _el),
-                             Prefix, Family, Given);
-       true ->
-          decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
-                             Middle, Suffix, Prefix, Family, Given)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle,
+                            decode_vcard_SUFFIX(__TopXMLNS, __IgnoreEls, _el),
+                            Prefix, Family, Given);
+      <<"vcard-temp">> ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle,
+                            decode_vcard_SUFFIX(<<"vcard-temp">>, __IgnoreEls,
+                                                _el),
+                            Prefix, Family, Given);
+      _ ->
+         decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els,
+                            Middle, Suffix, Prefix, Family, Given)
     end;
 decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                   Middle, Suffix, Prefix, Family, Given) ->
@@ -13128,405 +15180,379 @@ decode_stream_error_els(__TopXMLNS, __IgnoreEls, [],
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"text">>, _attrs, _} = _el | _els], Text,
                        Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  decode_stream_error_text(_xmlns, __IgnoreEls,
-                                                           _el),
-                                  Reason);
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 decode_stream_error_text(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                          __IgnoreEls, _el),
+                                 Reason);
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"bad-format">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_bad_format(_xmlns,
-                                                                 __IgnoreEls,
-                                                                 _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_bad_format(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                __IgnoreEls,
+                                                                _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"bad-namespace-prefix">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_bad_namespace_prefix(_xmlns,
-                                                                           __IgnoreEls,
-                                                                           _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_bad_namespace_prefix(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                          __IgnoreEls,
+                                                                          _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"conflict">>, _attrs, _} = _el | _els], Text,
                        Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_conflict(_xmlns,
-                                                               __IgnoreEls,
-                                                               _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_conflict(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                              __IgnoreEls,
+                                                              _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"connection-timeout">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_connection_timeout(_xmlns,
-                                                                         __IgnoreEls,
-                                                                         _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_connection_timeout(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                        __IgnoreEls,
+                                                                        _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"host-gone">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_host_gone(_xmlns,
-                                                                __IgnoreEls,
-                                                                _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_host_gone(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                               __IgnoreEls,
+                                                               _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"host-unknown">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_host_unknown(_xmlns,
-                                                                   __IgnoreEls,
-                                                                   _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_host_unknown(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                  __IgnoreEls,
+                                                                  _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"improper-addressing">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_improper_addressing(_xmlns,
-                                                                          __IgnoreEls,
-                                                                          _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_improper_addressing(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"internal-server-error">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_internal_server_error(_xmlns,
-                                                                            __IgnoreEls,
-                                                                            _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_internal_server_error(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                           __IgnoreEls,
+                                                                           _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"invalid-from">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_invalid_from(_xmlns,
-                                                                   __IgnoreEls,
-                                                                   _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_invalid_from(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                  __IgnoreEls,
+                                                                  _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"invalid-id">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_invalid_id(_xmlns,
-                                                                 __IgnoreEls,
-                                                                 _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_invalid_id(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                __IgnoreEls,
+                                                                _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"invalid-namespace">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_invalid_namespace(_xmlns,
-                                                                        __IgnoreEls,
-                                                                        _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_invalid_namespace(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                       __IgnoreEls,
+                                                                       _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"invalid-xml">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_invalid_xml(_xmlns,
-                                                                  __IgnoreEls,
-                                                                  _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_invalid_xml(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                 __IgnoreEls,
+                                                                 _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_not_authorized(_xmlns,
-                                                                     __IgnoreEls,
-                                                                     _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                    __IgnoreEls,
+                                                                    _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"not-well-formed">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_not_well_formed(_xmlns,
-                                                                      __IgnoreEls,
-                                                                      _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_not_well_formed(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                     __IgnoreEls,
+                                                                     _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"policy-violation">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_policy_violation(_xmlns,
-                                                                       __IgnoreEls,
-                                                                       _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_policy_violation(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                      __IgnoreEls,
+                                                                      _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"remote-connection-failed">>, _attrs, _} =
                             _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_remote_connection_failed(_xmlns,
-                                                                               __IgnoreEls,
-                                                                               _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_remote_connection_failed(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                              __IgnoreEls,
+                                                                              _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"reset">>, _attrs, _} = _el | _els], Text,
                        Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_reset(_xmlns,
-                                                            __IgnoreEls, _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_reset(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                           __IgnoreEls, _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"resource-constraint">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_resource_constraint(_xmlns,
-                                                                          __IgnoreEls,
-                                                                          _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_resource_constraint(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"restricted-xml">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_restricted_xml(_xmlns,
-                                                                     __IgnoreEls,
-                                                                     _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_restricted_xml(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                    __IgnoreEls,
+                                                                    _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"see-other-host">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_see_other_host(_xmlns,
-                                                                     __IgnoreEls,
-                                                                     _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_see_other_host(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                    __IgnoreEls,
+                                                                    _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"system-shutdown">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_system_shutdown(_xmlns,
-                                                                      __IgnoreEls,
-                                                                      _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_system_shutdown(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                     __IgnoreEls,
+                                                                     _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"undefined-condition">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_undefined_condition(_xmlns,
-                                                                          __IgnoreEls,
-                                                                          _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_undefined_condition(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"unsupported-encoding">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_unsupported_encoding(_xmlns,
-                                                                           __IgnoreEls,
-                                                                           _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_unsupported_encoding(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                          __IgnoreEls,
+                                                                          _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"unsupported-stanza-type">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_unsupported_stanza_type(_xmlns,
-                                                                              __IgnoreEls,
-                                                                              _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_unsupported_stanza_type(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                             __IgnoreEls,
+                                                                             _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"unsupported-version">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_stream_error_unsupported_version(_xmlns,
-                                                                          __IgnoreEls,
-                                                                          _el));
-       true ->
-          decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-streams">> ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_stream_error_unsupported_version(<<"urn:ietf:params:xml:ns:xmpp-streams">>,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      _ ->
+         decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_stream_error_els(__TopXMLNS, __IgnoreEls,
                        [_ | _els], Text, Reason) ->
@@ -14105,22 +16131,31 @@ decode_time_els(__TopXMLNS, __IgnoreEls, [], Utc,
 decode_time_els(__TopXMLNS, __IgnoreEls,
                [{xmlel, <<"tzo">>, _attrs, _} = _el | _els], Utc,
                Tzo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc,
-                          decode_time_tzo(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, Tzo)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:time">> ->
+         decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc,
+                         decode_time_tzo(__TopXMLNS, __IgnoreEls, _el));
+      <<"urn:xmpp:time">> ->
+         decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc,
+                         decode_time_tzo(<<"urn:xmpp:time">>, __IgnoreEls,
+                                         _el));
+      _ ->
+         decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, Tzo)
     end;
 decode_time_els(__TopXMLNS, __IgnoreEls,
                [{xmlel, <<"utc">>, _attrs, _} = _el | _els], Utc,
                Tzo) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_time_els(__TopXMLNS, __IgnoreEls, _els,
-                          decode_time_utc(__TopXMLNS, __IgnoreEls, _el), Tzo);
-       true ->
-          decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, Tzo)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:time">> ->
+         decode_time_els(__TopXMLNS, __IgnoreEls, _els,
+                         decode_time_utc(__TopXMLNS, __IgnoreEls, _el), Tzo);
+      <<"urn:xmpp:time">> ->
+         decode_time_els(__TopXMLNS, __IgnoreEls, _els,
+                         decode_time_utc(<<"urn:xmpp:time">>, __IgnoreEls,
+                                         _el),
+                         Tzo);
+      _ ->
+         decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, Tzo)
     end;
 decode_time_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                Utc, Tzo) ->
@@ -14224,12 +16259,55 @@ encode_ping({ping}, _xmlns_attrs) ->
 
 decode_session(__TopXMLNS, __IgnoreEls,
               {xmlel, <<"session">>, _attrs, _els}) ->
-    {session}.
+    Optional = decode_session_els(__TopXMLNS, __IgnoreEls,
+                                 _els, false),
+    {xmpp_session, Optional}.
+
+decode_session_els(__TopXMLNS, __IgnoreEls, [],
+                  Optional) ->
+    Optional;
+decode_session_els(__TopXMLNS, __IgnoreEls,
+                  [{xmlel, <<"optional">>, _attrs, _} = _el | _els],
+                  Optional) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-session">> ->
+         decode_session_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_session_optional(__TopXMLNS, __IgnoreEls,
+                                                    _el));
+      <<"urn:ietf:params:xml:ns:xmpp-session">> ->
+         decode_session_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_session_optional(<<"urn:ietf:params:xml:ns:xmpp-session">>,
+                                                    __IgnoreEls, _el));
+      _ ->
+         decode_session_els(__TopXMLNS, __IgnoreEls, _els,
+                            Optional)
+    end;
+decode_session_els(__TopXMLNS, __IgnoreEls, [_ | _els],
+                  Optional) ->
+    decode_session_els(__TopXMLNS, __IgnoreEls, _els,
+                      Optional).
+
+encode_session({xmpp_session, Optional},
+              _xmlns_attrs) ->
+    _els =
+       lists:reverse('encode_session_$optional'(Optional, [])),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"session">>, _attrs, _els}.
 
-encode_session({session}, _xmlns_attrs) ->
+'encode_session_$optional'(false, _acc) -> _acc;
+'encode_session_$optional'(Optional, _acc) ->
+    [encode_session_optional(Optional, []) | _acc].
+
+decode_session_optional(__TopXMLNS, __IgnoreEls,
+                       {xmlel, <<"optional">>, _attrs, _els}) ->
+    true.
+
+encode_session_optional(true, _xmlns_attrs) ->
     _els = [],
     _attrs = _xmlns_attrs,
-    {xmlel, <<"session">>, _attrs, _els}.
+    {xmlel, <<"optional">>, _attrs, _els}.
 
 decode_register(__TopXMLNS, __IgnoreEls,
                {xmlel, <<"query">>, _attrs, _els}) ->
@@ -14258,436 +16336,591 @@ decode_register_els(__TopXMLNS, __IgnoreEls,
                    Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"jabber:x:data">> ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              decode_xdata(_xmlns, __IgnoreEls, _el), Misc,
-                              Address, Instructions, Text, Last, First,
-                              Password, Registered, Date, Phone, State, Name,
-                              Username, Remove, Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"jabber:x:data">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             decode_xdata(<<"jabber:x:data">>, __IgnoreEls,
+                                          _el),
+                             Misc, Address, Instructions, Text, Last, First,
+                             Password, Registered, Date, Phone, State, Name,
+                             Username, Remove, Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"registered">>, _attrs, _} = _el | _els],
                    Zip, Xdata, Misc, Address, Instructions, Text, Last,
                    First, Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password,
-                              decode_register_registered(__TopXMLNS,
-                                                         __IgnoreEls, _el),
-                              Date, Phone, State, Name, Username, Remove, Key,
-                              City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password,
+                             decode_register_registered(__TopXMLNS,
+                                                        __IgnoreEls, _el),
+                             Date, Phone, State, Name, Username, Remove, Key,
+                             City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password,
+                             decode_register_registered(<<"jabber:iq:register">>,
+                                                        __IgnoreEls, _el),
+                             Date, Phone, State, Name, Username, Remove, Key,
+                             City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"remove">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username,
-                              decode_register_remove(__TopXMLNS, __IgnoreEls,
-                                                     _el),
-                              Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username,
+                             decode_register_remove(__TopXMLNS, __IgnoreEls,
+                                                    _el),
+                             Key, City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username,
+                             decode_register_remove(<<"jabber:iq:register">>,
+                                                    __IgnoreEls, _el),
+                             Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"instructions">>, _attrs, _} = _el | _els],
                    Zip, Xdata, Misc, Address, Instructions, Text, Last,
                    First, Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address,
-                              decode_register_instructions(__TopXMLNS,
-                                                           __IgnoreEls, _el),
-                              Text, Last, First, Password, Registered, Date,
-                              Phone, State, Name, Username, Remove, Key, City,
-                              Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address,
+                             decode_register_instructions(__TopXMLNS,
+                                                          __IgnoreEls, _el),
+                             Text, Last, First, Password, Registered, Date,
+                             Phone, State, Name, Username, Remove, Key, City,
+                             Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address,
+                             decode_register_instructions(<<"jabber:iq:register">>,
+                                                          __IgnoreEls, _el),
+                             Text, Last, First, Password, Registered, Date,
+                             Phone, State, Name, Username, Remove, Key, City,
+                             Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"username">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name,
-                              decode_register_username(__TopXMLNS, __IgnoreEls,
-                                                       _el),
-                              Remove, Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name,
+                             decode_register_username(__TopXMLNS, __IgnoreEls,
+                                                      _el),
+                             Remove, Key, City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name,
+                             decode_register_username(<<"jabber:iq:register">>,
+                                                      __IgnoreEls, _el),
+                             Remove, Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"nick">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City,
-                              decode_register_nick(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City,
+                             decode_register_nick(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City,
+                             decode_register_nick(<<"jabber:iq:register">>,
+                                                  __IgnoreEls, _el),
+                             Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"password">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First,
-                              decode_register_password(__TopXMLNS, __IgnoreEls,
-                                                       _el),
-                              Registered, Date, Phone, State, Name, Username,
-                              Remove, Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First,
+                             decode_register_password(__TopXMLNS, __IgnoreEls,
+                                                      _el),
+                             Registered, Date, Phone, State, Name, Username,
+                             Remove, Key, City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First,
+                             decode_register_password(<<"jabber:iq:register">>,
+                                                      __IgnoreEls, _el),
+                             Registered, Date, Phone, State, Name, Username,
+                             Remove, Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"name">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              decode_register_name(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              Username, Remove, Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             decode_register_name(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             Username, Remove, Key, City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             decode_register_name(<<"jabber:iq:register">>,
+                                                  __IgnoreEls, _el),
+                             Username, Remove, Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"first">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              decode_register_first(__TopXMLNS, __IgnoreEls,
-                                                    _el),
-                              Password, Registered, Date, Phone, State, Name,
-                              Username, Remove, Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             decode_register_first(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                             Password, Registered, Date, Phone, State, Name,
+                             Username, Remove, Key, City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             decode_register_first(<<"jabber:iq:register">>,
+                                                   __IgnoreEls, _el),
+                             Password, Registered, Date, Phone, State, Name,
+                             Username, Remove, Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"last">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text,
-                              decode_register_last(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text,
+                             decode_register_last(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text,
+                             decode_register_last(<<"jabber:iq:register">>,
+                                                  __IgnoreEls, _el),
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"email">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              decode_register_email(__TopXMLNS, __IgnoreEls,
-                                                    _el));
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             decode_register_email(__TopXMLNS, __IgnoreEls,
+                                                   _el));
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             decode_register_email(<<"jabber:iq:register">>,
+                                                   __IgnoreEls, _el));
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"address">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc,
-                              decode_register_address(__TopXMLNS, __IgnoreEls,
-                                                      _el),
-                              Instructions, Text, Last, First, Password,
-                              Registered, Date, Phone, State, Name, Username,
-                              Remove, Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc,
+                             decode_register_address(__TopXMLNS, __IgnoreEls,
+                                                     _el),
+                             Instructions, Text, Last, First, Password,
+                             Registered, Date, Phone, State, Name, Username,
+                             Remove, Key, City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc,
+                             decode_register_address(<<"jabber:iq:register">>,
+                                                     __IgnoreEls, _el),
+                             Instructions, Text, Last, First, Password,
+                             Registered, Date, Phone, State, Name, Username,
+                             Remove, Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"city">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key,
-                              decode_register_city(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key,
+                             decode_register_city(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key,
+                             decode_register_city(<<"jabber:iq:register">>,
+                                                  __IgnoreEls, _el),
+                             Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"state">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone,
-                              decode_register_state(__TopXMLNS, __IgnoreEls,
-                                                    _el),
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone,
+                             decode_register_state(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone,
+                             decode_register_state(<<"jabber:iq:register">>,
+                                                   __IgnoreEls, _el),
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"zip">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els,
-                              decode_register_zip(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els,
+                             decode_register_zip(__TopXMLNS, __IgnoreEls, _el),
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els,
+                             decode_register_zip(<<"jabber:iq:register">>,
+                                                 __IgnoreEls, _el),
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"phone">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date,
-                              decode_register_phone(__TopXMLNS, __IgnoreEls,
-                                                    _el),
-                              State, Name, Username, Remove, Key, City, Nick,
-                              Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date,
+                             decode_register_phone(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                             State, Name, Username, Remove, Key, City, Nick,
+                             Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date,
+                             decode_register_phone(<<"jabber:iq:register">>,
+                                                   __IgnoreEls, _el),
+                             State, Name, Username, Remove, Key, City, Nick,
+                             Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"url">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick,
-                              decode_register_url(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                              Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick,
+                             decode_register_url(__TopXMLNS, __IgnoreEls, _el),
+                             Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick,
+                             decode_register_url(<<"jabber:iq:register">>,
+                                                 __IgnoreEls, _el),
+                             Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"date">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered,
-                              decode_register_date(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              Phone, State, Name, Username, Remove, Key, City,
-                              Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered,
+                             decode_register_date(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             Phone, State, Name, Username, Remove, Key, City,
+                             Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered,
+                             decode_register_date(<<"jabber:iq:register">>,
+                                                  __IgnoreEls, _el),
+                             Phone, State, Name, Username, Remove, Key, City,
+                             Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"misc">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata,
-                              decode_register_misc(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              Address, Instructions, Text, Last, First,
-                              Password, Registered, Date, Phone, State, Name,
-                              Username, Remove, Key, City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata,
+                             decode_register_misc(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             Address, Instructions, Text, Last, First,
+                             Password, Registered, Date, Phone, State, Name,
+                             Username, Remove, Key, City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata,
+                             decode_register_misc(<<"jabber:iq:register">>,
+                                                  __IgnoreEls, _el),
+                             Address, Instructions, Text, Last, First,
+                             Password, Registered, Date, Phone, State, Name,
+                             Username, Remove, Key, City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"text">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions,
-                              decode_register_text(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              Last, First, Password, Registered, Date, Phone,
-                              State, Name, Username, Remove, Key, City, Nick,
-                              Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions,
+                             decode_register_text(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             Last, First, Password, Registered, Date, Phone,
+                             State, Name, Username, Remove, Key, City, Nick,
+                             Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions,
+                             decode_register_text(<<"jabber:iq:register">>,
+                                                  __IgnoreEls, _el),
+                             Last, First, Password, Registered, Date, Phone,
+                             State, Name, Username, Remove, Key, City, Nick,
+                             Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"key">>, _attrs, _} = _el | _els], Zip,
                    Xdata, Misc, Address, Instructions, Text, Last, First,
                    Password, Registered, Date, Phone, State, Name,
                    Username, Remove, Key, City, Nick, Url, Email) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove,
-                              decode_register_key(__TopXMLNS, __IgnoreEls,
-                                                  _el),
-                              City, Nick, Url, Email);
-       true ->
-          decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
-                              Xdata, Misc, Address, Instructions, Text, Last,
-                              First, Password, Registered, Date, Phone, State,
-                              Name, Username, Remove, Key, City, Nick, Url,
-                              Email)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove,
+                             decode_register_key(__TopXMLNS, __IgnoreEls, _el),
+                             City, Nick, Url, Email);
+      <<"jabber:iq:register">> ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove,
+                             decode_register_key(<<"jabber:iq:register">>,
+                                                 __IgnoreEls, _el),
+                             City, Nick, Url, Email);
+      _ ->
+         decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip,
+                             Xdata, Misc, Address, Instructions, Text, Last,
+                             First, Password, Registered, Date, Phone, State,
+                             Name, Username, Remove, Key, City, Nick, Url,
+                             Email)
     end;
 decode_register_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                    Zip, Xdata, Misc, Address, Instructions, Text, Last,
@@ -15394,34 +17627,50 @@ encode_feature_register({feature_register},
 
 decode_caps(__TopXMLNS, __IgnoreEls,
            {xmlel, <<"c">>, _attrs, _els}) ->
-    {Hash, Node, Ver} = decode_caps_attrs(__TopXMLNS,
-                                         _attrs, undefined, undefined,
-                                         undefined),
-    {caps, Hash, Node, Ver}.
+    {Hash, Node, Exts, Version} =
+       decode_caps_attrs(__TopXMLNS, _attrs, undefined,
+                         undefined, undefined, undefined),
+    {caps, Node, Version, Hash, Exts}.
 
 decode_caps_attrs(__TopXMLNS,
-                 [{<<"hash">>, _val} | _attrs], _Hash, Node, Ver) ->
-    decode_caps_attrs(__TopXMLNS, _attrs, _val, Node, Ver);
+                 [{<<"hash">>, _val} | _attrs], _Hash, Node, Exts,
+                 Version) ->
+    decode_caps_attrs(__TopXMLNS, _attrs, _val, Node, Exts,
+                     Version);
+decode_caps_attrs(__TopXMLNS,
+                 [{<<"node">>, _val} | _attrs], Hash, _Node, Exts,
+                 Version) ->
+    decode_caps_attrs(__TopXMLNS, _attrs, Hash, _val, Exts,
+                     Version);
 decode_caps_attrs(__TopXMLNS,
-                 [{<<"node">>, _val} | _attrs], Hash, _Node, Ver) ->
-    decode_caps_attrs(__TopXMLNS, _attrs, Hash, _val, Ver);
+                 [{<<"ext">>, _val} | _attrs], Hash, Node, _Exts,
+                 Version) ->
+    decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, _val,
+                     Version);
 decode_caps_attrs(__TopXMLNS,
-                 [{<<"ver">>, _val} | _attrs], Hash, Node, _Ver) ->
-    decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, _val);
+                 [{<<"ver">>, _val} | _attrs], Hash, Node, Exts,
+                 _Version) ->
+    decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, Exts,
+                     _val);
 decode_caps_attrs(__TopXMLNS, [_ | _attrs], Hash, Node,
-                 Ver) ->
-    decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, Ver);
-decode_caps_attrs(__TopXMLNS, [], Hash, Node, Ver) ->
+                 Exts, Version) ->
+    decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, Exts,
+                     Version);
+decode_caps_attrs(__TopXMLNS, [], Hash, Node, Exts,
+                 Version) ->
     {decode_caps_attr_hash(__TopXMLNS, Hash),
      decode_caps_attr_node(__TopXMLNS, Node),
-     decode_caps_attr_ver(__TopXMLNS, Ver)}.
+     decode_caps_attr_ext(__TopXMLNS, Exts),
+     decode_caps_attr_ver(__TopXMLNS, Version)}.
 
-encode_caps({caps, Hash, Node, Ver}, _xmlns_attrs) ->
+encode_caps({caps, Node, Version, Hash, Exts},
+           _xmlns_attrs) ->
     _els = [],
-    _attrs = encode_caps_attr_ver(Ver,
-                                 encode_caps_attr_node(Node,
-                                                       encode_caps_attr_hash(Hash,
-                                                                             _xmlns_attrs))),
+    _attrs = encode_caps_attr_ver(Version,
+                                 encode_caps_attr_ext(Exts,
+                                                      encode_caps_attr_node(Node,
+                                                                            encode_caps_attr_hash(Hash,
+                                                                                                  _xmlns_attrs)))),
     {xmlel, <<"c">>, _attrs, _els}.
 
 decode_caps_attr_hash(__TopXMLNS, undefined) ->
@@ -15440,19 +17689,26 @@ encode_caps_attr_node(undefined, _acc) -> _acc;
 encode_caps_attr_node(_val, _acc) ->
     [{<<"node">>, _val} | _acc].
 
-decode_caps_attr_ver(__TopXMLNS, undefined) ->
-    undefined;
-decode_caps_attr_ver(__TopXMLNS, _val) ->
-    case catch base64:decode(_val) of
+decode_caps_attr_ext(__TopXMLNS, undefined) -> [];
+decode_caps_attr_ext(__TopXMLNS, _val) ->
+    case catch re:split(_val, "\\h+") of
       {'EXIT', _} ->
          erlang:error({xmpp_codec,
-                       {bad_attr_value, <<"ver">>, <<"c">>, __TopXMLNS}});
+                       {bad_attr_value, <<"ext">>, <<"c">>, __TopXMLNS}});
       _res -> _res
     end.
 
+encode_caps_attr_ext([], _acc) -> _acc;
+encode_caps_attr_ext(_val, _acc) ->
+    [{<<"ext">>, join(_val, 32)} | _acc].
+
+decode_caps_attr_ver(__TopXMLNS, undefined) ->
+    undefined;
+decode_caps_attr_ver(__TopXMLNS, _val) -> _val.
+
 encode_caps_attr_ver(undefined, _acc) -> _acc;
 encode_caps_attr_ver(_val, _acc) ->
-    [{<<"ver">>, base64:encode(_val)} | _acc].
+    [{<<"ver">>, _val} | _acc].
 
 decode_p1_ack(__TopXMLNS, __IgnoreEls,
              {xmlel, <<"ack">>, _attrs, _els}) ->
@@ -15528,19 +17784,30 @@ decode_compression_els(__TopXMLNS, __IgnoreEls, [],
 decode_compression_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"method">>, _attrs, _} = _el | _els],
                       Methods) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_compression_els(__TopXMLNS, __IgnoreEls, _els,
-                                 case decode_compression_method(__TopXMLNS,
-                                                                __IgnoreEls,
-                                                                _el)
-                                     of
-                                   undefined -> Methods;
-                                   _new_el -> [_new_el | Methods]
-                                 end);
-       true ->
-          decode_compression_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Methods)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/features/compress">> ->
+         decode_compression_els(__TopXMLNS, __IgnoreEls, _els,
+                                case decode_compression_method(__TopXMLNS,
+                                                               __IgnoreEls,
+                                                               _el)
+                                    of
+                                  undefined -> Methods;
+                                  _new_el -> [_new_el | Methods]
+                                end);
+      <<"http://jabber.org/features/compress">> ->
+         decode_compression_els(__TopXMLNS, __IgnoreEls, _els,
+                                case
+                                  decode_compression_method(<<"http://jabber.org/features/compress">>,
+                                                            __IgnoreEls, _el)
+                                    of
+                                  undefined -> Methods;
+                                  _new_el -> [_new_el | Methods]
+                                end);
+      _ ->
+         decode_compression_els(__TopXMLNS, __IgnoreEls, _els,
+                                Methods)
     end;
 decode_compression_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Methods) ->
@@ -15615,18 +17882,29 @@ decode_compress_els(__TopXMLNS, __IgnoreEls, [],
 decode_compress_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"method">>, _attrs, _} = _el | _els],
                    Methods) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_compress_els(__TopXMLNS, __IgnoreEls, _els,
-                              case decode_compress_method(__TopXMLNS,
-                                                          __IgnoreEls, _el)
-                                  of
-                                undefined -> Methods;
-                                _new_el -> [_new_el | Methods]
-                              end);
-       true ->
-          decode_compress_els(__TopXMLNS, __IgnoreEls, _els,
-                              Methods)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_els(__TopXMLNS, __IgnoreEls, _els,
+                             case decode_compress_method(__TopXMLNS,
+                                                         __IgnoreEls, _el)
+                                 of
+                               undefined -> Methods;
+                               _new_el -> [_new_el | Methods]
+                             end);
+      <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_els(__TopXMLNS, __IgnoreEls, _els,
+                             case
+                               decode_compress_method(<<"http://jabber.org/protocol/compress">>,
+                                                      __IgnoreEls, _el)
+                                 of
+                               undefined -> Methods;
+                               _new_el -> [_new_el | Methods]
+                             end);
+      _ ->
+         decode_compress_els(__TopXMLNS, __IgnoreEls, _els,
+                             Methods)
     end;
 decode_compress_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                    Methods) ->
@@ -15688,46 +17966,70 @@ decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
                            [{xmlel, <<"setup-failed">>, _attrs, _} = _el
                             | _els],
                            Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
-                                      _els,
-                                      decode_compress_failure_setup_failed(__TopXMLNS,
-                                                                           __IgnoreEls,
-                                                                           _el));
-       true ->
-          decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
-                                      _els, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_compress_failure_setup_failed(__TopXMLNS,
+                                                                          __IgnoreEls,
+                                                                          _el));
+      <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_compress_failure_setup_failed(<<"http://jabber.org/protocol/compress">>,
+                                                                          __IgnoreEls,
+                                                                          _el));
+      _ ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els, Reason)
     end;
 decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
                            [{xmlel, <<"processing-failed">>, _attrs, _} = _el
                             | _els],
                            Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
-                                      _els,
-                                      decode_compress_failure_processing_failed(__TopXMLNS,
-                                                                                __IgnoreEls,
-                                                                                _el));
-       true ->
-          decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
-                                      _els, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_compress_failure_processing_failed(__TopXMLNS,
+                                                                               __IgnoreEls,
+                                                                               _el));
+      <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_compress_failure_processing_failed(<<"http://jabber.org/protocol/compress">>,
+                                                                               __IgnoreEls,
+                                                                               _el));
+      _ ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els, Reason)
     end;
 decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
                            [{xmlel, <<"unsupported-method">>, _attrs, _} = _el
                             | _els],
                            Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
-                                      _els,
-                                      decode_compress_failure_unsupported_method(__TopXMLNS,
-                                                                                 __IgnoreEls,
-                                                                                 _el));
-       true ->
-          decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
-                                      _els, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_compress_failure_unsupported_method(__TopXMLNS,
+                                                                                __IgnoreEls,
+                                                                                _el));
+      <<"http://jabber.org/protocol/compress">> ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els,
+                                     decode_compress_failure_unsupported_method(<<"http://jabber.org/protocol/compress">>,
+                                                                                __IgnoreEls,
+                                                                                _el));
+      _ ->
+         decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
+                                     _els, Reason)
     end;
 decode_compress_failure_els(__TopXMLNS, __IgnoreEls,
                            [_ | _els], Reason) ->
@@ -15828,14 +18130,20 @@ decode_starttls_els(__TopXMLNS, __IgnoreEls, [],
 decode_starttls_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"required">>, _attrs, _} = _el | _els],
                    Required) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_starttls_els(__TopXMLNS, __IgnoreEls, _els,
-                              decode_starttls_required(__TopXMLNS, __IgnoreEls,
-                                                       _el));
-       true ->
-          decode_starttls_els(__TopXMLNS, __IgnoreEls, _els,
-                              Required)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-tls">> ->
+         decode_starttls_els(__TopXMLNS, __IgnoreEls, _els,
+                             decode_starttls_required(__TopXMLNS, __IgnoreEls,
+                                                      _el));
+      <<"urn:ietf:params:xml:ns:xmpp-tls">> ->
+         decode_starttls_els(__TopXMLNS, __IgnoreEls, _els,
+                             decode_starttls_required(<<"urn:ietf:params:xml:ns:xmpp-tls">>,
+                                                      __IgnoreEls, _el));
+      _ ->
+         decode_starttls_els(__TopXMLNS, __IgnoreEls, _els,
+                             Required)
     end;
 decode_starttls_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                    Required) ->
@@ -15874,20 +18182,32 @@ decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, [],
 decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls,
                           [{xmlel, <<"mechanism">>, _attrs, _} = _el | _els],
                           List) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls,
-                                     _els,
-                                     case decode_sasl_mechanism(__TopXMLNS,
-                                                                __IgnoreEls,
-                                                                _el)
-                                         of
-                                       undefined -> List;
-                                       _new_el -> [_new_el | List]
-                                     end);
-       true ->
-          decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls,
-                                     _els, List)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls,
+                                    _els,
+                                    case decode_sasl_mechanism(__TopXMLNS,
+                                                               __IgnoreEls,
+                                                               _el)
+                                        of
+                                      undefined -> List;
+                                      _new_el -> [_new_el | List]
+                                    end);
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls,
+                                    _els,
+                                    case
+                                      decode_sasl_mechanism(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                            __IgnoreEls, _el)
+                                        of
+                                      undefined -> List;
+                                      _new_el -> [_new_el | List]
+                                    end);
+      _ ->
+         decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls,
+                                    _els, List)
     end;
 decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls,
                           [_ | _els], List) ->
@@ -15949,179 +18269,297 @@ decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [],
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"text">>, _attrs, _} = _el | _els], Text,
                        Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  [decode_sasl_failure_text(__TopXMLNS,
-                                                            __IgnoreEls, _el)
-                                   | Text],
-                                  Reason);
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_sasl_failure_text(__TopXMLNS,
+                                                           __IgnoreEls, _el)
+                                  | Text],
+                                 Reason);
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_sasl_failure_text(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                           __IgnoreEls, _el)
+                                  | Text],
+                                 Reason);
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"aborted">>, _attrs, _} = _el | _els], Text,
                        Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_aborted(__TopXMLNS,
-                                                              __IgnoreEls,
-                                                              _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_aborted(__TopXMLNS,
+                                                             __IgnoreEls,
+                                                             _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_aborted(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                             __IgnoreEls,
+                                                             _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"account-disabled">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_account_disabled(__TopXMLNS,
-                                                                       __IgnoreEls,
-                                                                       _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_account_disabled(__TopXMLNS,
+                                                                      __IgnoreEls,
+                                                                      _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_account_disabled(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                      __IgnoreEls,
+                                                                      _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"credentials-expired">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_credentials_expired(__TopXMLNS,
-                                                                          __IgnoreEls,
-                                                                          _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_credentials_expired(__TopXMLNS,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_credentials_expired(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"encryption-required">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_encryption_required(__TopXMLNS,
-                                                                          __IgnoreEls,
-                                                                          _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_encryption_required(__TopXMLNS,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_encryption_required(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                         __IgnoreEls,
+                                                                         _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"incorrect-encoding">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_incorrect_encoding(__TopXMLNS,
-                                                                         __IgnoreEls,
-                                                                         _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_incorrect_encoding(__TopXMLNS,
+                                                                        __IgnoreEls,
+                                                                        _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_incorrect_encoding(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                        __IgnoreEls,
+                                                                        _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"invalid-authzid">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_invalid_authzid(__TopXMLNS,
-                                                                      __IgnoreEls,
-                                                                      _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_invalid_authzid(__TopXMLNS,
+                                                                     __IgnoreEls,
+                                                                     _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_invalid_authzid(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                     __IgnoreEls,
+                                                                     _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"invalid-mechanism">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_invalid_mechanism(__TopXMLNS,
-                                                                        __IgnoreEls,
-                                                                        _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_invalid_mechanism(__TopXMLNS,
+                                                                       __IgnoreEls,
+                                                                       _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_invalid_mechanism(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                       __IgnoreEls,
+                                                                       _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"malformed-request">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_malformed_request(__TopXMLNS,
-                                                                        __IgnoreEls,
-                                                                        _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_malformed_request(__TopXMLNS,
+                                                                       __IgnoreEls,
+                                                                       _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_malformed_request(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                       __IgnoreEls,
+                                                                       _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"mechanism-too-weak">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_mechanism_too_weak(__TopXMLNS,
-                                                                         __IgnoreEls,
-                                                                         _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_mechanism_too_weak(__TopXMLNS,
+                                                                        __IgnoreEls,
+                                                                        _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_mechanism_too_weak(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                        __IgnoreEls,
+                                                                        _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_not_authorized(__TopXMLNS,
-                                                                     __IgnoreEls,
-                                                                     _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_not_authorized(__TopXMLNS,
+                                                                    __IgnoreEls,
+                                                                    _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                    __IgnoreEls,
+                                                                    _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
+    end;
+decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
+                       [{xmlel, <<"bad-protocol">>, _attrs, _} = _el | _els],
+                       Text, Reason) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_bad_protocol(__TopXMLNS,
+                                                                  __IgnoreEls,
+                                                                  _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_bad_protocol(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                  __IgnoreEls,
+                                                                  _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"temporary-auth-failure">>, _attrs, _} = _el
                         | _els],
                        Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text,
-                                  decode_sasl_failure_temporary_auth_failure(__TopXMLNS,
-                                                                             __IgnoreEls,
-                                                                             _el));
-       true ->
-          decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Text, Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_temporary_auth_failure(__TopXMLNS,
+                                                                            __IgnoreEls,
+                                                                            _el));
+      <<"urn:ietf:params:xml:ns:xmpp-sasl">> ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text,
+                                 decode_sasl_failure_temporary_auth_failure(<<"urn:ietf:params:xml:ns:xmpp-sasl">>,
+                                                                            __IgnoreEls,
+                                                                            _el));
+      _ ->
+         decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Text, Reason)
     end;
 decode_sasl_failure_els(__TopXMLNS, __IgnoreEls,
                        [_ | _els], Text, Reason) ->
@@ -16187,6 +18625,9 @@ encode_sasl_failure({sasl_failure, Reason, Text},
 'encode_sasl_failure_$reason'('not-authorized' = Reason,
                              _acc) ->
     [encode_sasl_failure_not_authorized(Reason, []) | _acc];
+'encode_sasl_failure_$reason'('bad-protocol' = Reason,
+                             _acc) ->
+    [encode_sasl_failure_bad_protocol(Reason, []) | _acc];
 'encode_sasl_failure_$reason'('temporary-auth-failure' =
                                  Reason,
                              _acc) ->
@@ -16205,6 +18646,17 @@ encode_sasl_failure_temporary_auth_failure('temporary-auth-failure',
     _attrs = _xmlns_attrs,
     {xmlel, <<"temporary-auth-failure">>, _attrs, _els}.
 
+decode_sasl_failure_bad_protocol(__TopXMLNS,
+                                __IgnoreEls,
+                                {xmlel, <<"bad-protocol">>, _attrs, _els}) ->
+    'bad-protocol'.
+
+encode_sasl_failure_bad_protocol('bad-protocol',
+                                _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"bad-protocol">>, _attrs, _els}.
+
 decode_sasl_failure_not_authorized(__TopXMLNS,
                                   __IgnoreEls,
                                   {xmlel, <<"not-authorized">>, _attrs,
@@ -16553,18 +19005,265 @@ decode_sasl_auth_attr_mechanism(__TopXMLNS, _val) ->
 encode_sasl_auth_attr_mechanism(_val, _acc) ->
     [{<<"mechanism">>, _val} | _acc].
 
-decode_sasl_auth_cdata(__TopXMLNS, <<>>) -> undefined;
-decode_sasl_auth_cdata(__TopXMLNS, _val) ->
-    case catch base64:decode(_val) of
-      {'EXIT', _} ->
-         erlang:error({xmpp_codec,
-                       {bad_cdata_value, <<>>, <<"auth">>, __TopXMLNS}});
-      _res -> _res
-    end.
+decode_sasl_auth_cdata(__TopXMLNS, <<>>) -> undefined;
+decode_sasl_auth_cdata(__TopXMLNS, _val) ->
+    case catch base64:decode(_val) of
+      {'EXIT', _} ->
+         erlang:error({xmpp_codec,
+                       {bad_cdata_value, <<>>, <<"auth">>, __TopXMLNS}});
+      _res -> _res
+    end.
+
+encode_sasl_auth_cdata(undefined, _acc) -> _acc;
+encode_sasl_auth_cdata(_val, _acc) ->
+    [{xmlcdata, base64:encode(_val)} | _acc].
+
+decode_legacy_auth(__TopXMLNS, __IgnoreEls,
+                  {xmlel, <<"query">>, _attrs, _els}) ->
+    {Digest, Password, Resource, Username} =
+       decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                              undefined, undefined, undefined, undefined),
+    {legacy_auth, Username, Password, Digest, Resource}.
+
+decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, [],
+                      Digest, Password, Resource, Username) ->
+    {Digest, Password, Resource, Username};
+decode_legacy_auth_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"username">>, _attrs, _} = _el | _els],
+                      Digest, Password, Resource, Username) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password, Resource,
+                                decode_legacy_auth_username(__TopXMLNS,
+                                                            __IgnoreEls, _el));
+      <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password, Resource,
+                                decode_legacy_auth_username(<<"jabber:iq:auth">>,
+                                                            __IgnoreEls, _el));
+      _ ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password, Resource, Username)
+    end;
+decode_legacy_auth_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"password">>, _attrs, _} = _el | _els],
+                      Digest, Password, Resource, Username) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest,
+                                decode_legacy_auth_password(__TopXMLNS,
+                                                            __IgnoreEls, _el),
+                                Resource, Username);
+      <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest,
+                                decode_legacy_auth_password(<<"jabber:iq:auth">>,
+                                                            __IgnoreEls, _el),
+                                Resource, Username);
+      _ ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password, Resource, Username)
+    end;
+decode_legacy_auth_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"digest">>, _attrs, _} = _el | _els], Digest,
+                      Password, Resource, Username) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_legacy_auth_digest(__TopXMLNS,
+                                                          __IgnoreEls, _el),
+                                Password, Resource, Username);
+      <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                decode_legacy_auth_digest(<<"jabber:iq:auth">>,
+                                                          __IgnoreEls, _el),
+                                Password, Resource, Username);
+      _ ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password, Resource, Username)
+    end;
+decode_legacy_auth_els(__TopXMLNS, __IgnoreEls,
+                      [{xmlel, <<"resource">>, _attrs, _} = _el | _els],
+                      Digest, Password, Resource, Username) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password,
+                                decode_legacy_auth_resource(__TopXMLNS,
+                                                            __IgnoreEls, _el),
+                                Username);
+      <<"jabber:iq:auth">> ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password,
+                                decode_legacy_auth_resource(<<"jabber:iq:auth">>,
+                                                            __IgnoreEls, _el),
+                                Username);
+      _ ->
+         decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                                Digest, Password, Resource, Username)
+    end;
+decode_legacy_auth_els(__TopXMLNS, __IgnoreEls,
+                      [_ | _els], Digest, Password, Resource, Username) ->
+    decode_legacy_auth_els(__TopXMLNS, __IgnoreEls, _els,
+                          Digest, Password, Resource, Username).
+
+encode_legacy_auth({legacy_auth, Username, Password,
+                   Digest, Resource},
+                  _xmlns_attrs) ->
+    _els =
+       lists:reverse('encode_legacy_auth_$digest'(Digest,
+                                                  'encode_legacy_auth_$password'(Password,
+                                                                                 'encode_legacy_auth_$resource'(Resource,
+                                                                                                                'encode_legacy_auth_$username'(Username,
+                                                                                                                                               []))))),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"query">>, _attrs, _els}.
+
+'encode_legacy_auth_$digest'(undefined, _acc) -> _acc;
+'encode_legacy_auth_$digest'(Digest, _acc) ->
+    [encode_legacy_auth_digest(Digest, []) | _acc].
+
+'encode_legacy_auth_$password'(undefined, _acc) -> _acc;
+'encode_legacy_auth_$password'(Password, _acc) ->
+    [encode_legacy_auth_password(Password, []) | _acc].
+
+'encode_legacy_auth_$resource'(undefined, _acc) -> _acc;
+'encode_legacy_auth_$resource'(Resource, _acc) ->
+    [encode_legacy_auth_resource(Resource, []) | _acc].
+
+'encode_legacy_auth_$username'(undefined, _acc) -> _acc;
+'encode_legacy_auth_$username'(Username, _acc) ->
+    [encode_legacy_auth_username(Username, []) | _acc].
+
+decode_legacy_auth_resource(__TopXMLNS, __IgnoreEls,
+                           {xmlel, <<"resource">>, _attrs, _els}) ->
+    Cdata = decode_legacy_auth_resource_els(__TopXMLNS,
+                                           __IgnoreEls, _els, <<>>),
+    Cdata.
+
+decode_legacy_auth_resource_els(__TopXMLNS, __IgnoreEls,
+                               [], Cdata) ->
+    decode_legacy_auth_resource_cdata(__TopXMLNS, Cdata);
+decode_legacy_auth_resource_els(__TopXMLNS, __IgnoreEls,
+                               [{xmlcdata, _data} | _els], Cdata) ->
+    decode_legacy_auth_resource_els(__TopXMLNS, __IgnoreEls,
+                                   _els, <<Cdata/binary, _data/binary>>);
+decode_legacy_auth_resource_els(__TopXMLNS, __IgnoreEls,
+                               [_ | _els], Cdata) ->
+    decode_legacy_auth_resource_els(__TopXMLNS, __IgnoreEls,
+                                   _els, Cdata).
+
+encode_legacy_auth_resource(Cdata, _xmlns_attrs) ->
+    _els = encode_legacy_auth_resource_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"resource">>, _attrs, _els}.
+
+decode_legacy_auth_resource_cdata(__TopXMLNS, <<>>) ->
+    none;
+decode_legacy_auth_resource_cdata(__TopXMLNS, _val) ->
+    _val.
+
+encode_legacy_auth_resource_cdata(none, _acc) -> _acc;
+encode_legacy_auth_resource_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_legacy_auth_digest(__TopXMLNS, __IgnoreEls,
+                         {xmlel, <<"digest">>, _attrs, _els}) ->
+    Cdata = decode_legacy_auth_digest_els(__TopXMLNS,
+                                         __IgnoreEls, _els, <<>>),
+    Cdata.
+
+decode_legacy_auth_digest_els(__TopXMLNS, __IgnoreEls,
+                             [], Cdata) ->
+    decode_legacy_auth_digest_cdata(__TopXMLNS, Cdata);
+decode_legacy_auth_digest_els(__TopXMLNS, __IgnoreEls,
+                             [{xmlcdata, _data} | _els], Cdata) ->
+    decode_legacy_auth_digest_els(__TopXMLNS, __IgnoreEls,
+                                 _els, <<Cdata/binary, _data/binary>>);
+decode_legacy_auth_digest_els(__TopXMLNS, __IgnoreEls,
+                             [_ | _els], Cdata) ->
+    decode_legacy_auth_digest_els(__TopXMLNS, __IgnoreEls,
+                                 _els, Cdata).
+
+encode_legacy_auth_digest(Cdata, _xmlns_attrs) ->
+    _els = encode_legacy_auth_digest_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"digest">>, _attrs, _els}.
+
+decode_legacy_auth_digest_cdata(__TopXMLNS, <<>>) ->
+    none;
+decode_legacy_auth_digest_cdata(__TopXMLNS, _val) ->
+    _val.
+
+encode_legacy_auth_digest_cdata(none, _acc) -> _acc;
+encode_legacy_auth_digest_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_legacy_auth_password(__TopXMLNS, __IgnoreEls,
+                           {xmlel, <<"password">>, _attrs, _els}) ->
+    Cdata = decode_legacy_auth_password_els(__TopXMLNS,
+                                           __IgnoreEls, _els, <<>>),
+    Cdata.
+
+decode_legacy_auth_password_els(__TopXMLNS, __IgnoreEls,
+                               [], Cdata) ->
+    decode_legacy_auth_password_cdata(__TopXMLNS, Cdata);
+decode_legacy_auth_password_els(__TopXMLNS, __IgnoreEls,
+                               [{xmlcdata, _data} | _els], Cdata) ->
+    decode_legacy_auth_password_els(__TopXMLNS, __IgnoreEls,
+                                   _els, <<Cdata/binary, _data/binary>>);
+decode_legacy_auth_password_els(__TopXMLNS, __IgnoreEls,
+                               [_ | _els], Cdata) ->
+    decode_legacy_auth_password_els(__TopXMLNS, __IgnoreEls,
+                                   _els, Cdata).
+
+encode_legacy_auth_password(Cdata, _xmlns_attrs) ->
+    _els = encode_legacy_auth_password_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"password">>, _attrs, _els}.
+
+decode_legacy_auth_password_cdata(__TopXMLNS, <<>>) ->
+    none;
+decode_legacy_auth_password_cdata(__TopXMLNS, _val) ->
+    _val.
+
+encode_legacy_auth_password_cdata(none, _acc) -> _acc;
+encode_legacy_auth_password_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
+
+decode_legacy_auth_username(__TopXMLNS, __IgnoreEls,
+                           {xmlel, <<"username">>, _attrs, _els}) ->
+    Cdata = decode_legacy_auth_username_els(__TopXMLNS,
+                                           __IgnoreEls, _els, <<>>),
+    Cdata.
+
+decode_legacy_auth_username_els(__TopXMLNS, __IgnoreEls,
+                               [], Cdata) ->
+    decode_legacy_auth_username_cdata(__TopXMLNS, Cdata);
+decode_legacy_auth_username_els(__TopXMLNS, __IgnoreEls,
+                               [{xmlcdata, _data} | _els], Cdata) ->
+    decode_legacy_auth_username_els(__TopXMLNS, __IgnoreEls,
+                                   _els, <<Cdata/binary, _data/binary>>);
+decode_legacy_auth_username_els(__TopXMLNS, __IgnoreEls,
+                               [_ | _els], Cdata) ->
+    decode_legacy_auth_username_els(__TopXMLNS, __IgnoreEls,
+                                   _els, Cdata).
+
+encode_legacy_auth_username(Cdata, _xmlns_attrs) ->
+    _els = encode_legacy_auth_username_cdata(Cdata, []),
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"username">>, _attrs, _els}.
+
+decode_legacy_auth_username_cdata(__TopXMLNS, <<>>) ->
+    none;
+decode_legacy_auth_username_cdata(__TopXMLNS, _val) ->
+    _val.
 
-encode_sasl_auth_cdata(undefined, _acc) -> _acc;
-encode_sasl_auth_cdata(_val, _acc) ->
-    [{xmlcdata, base64:encode(_val)} | _acc].
+encode_legacy_auth_username_cdata(none, _acc) -> _acc;
+encode_legacy_auth_username_cdata(_val, _acc) ->
+    [{xmlcdata, _val} | _acc].
 
 decode_bind(__TopXMLNS, __IgnoreEls,
            {xmlel, <<"bind">>, _attrs, _els}) ->
@@ -16578,25 +19277,38 @@ decode_bind_els(__TopXMLNS, __IgnoreEls, [], Jid,
 decode_bind_els(__TopXMLNS, __IgnoreEls,
                [{xmlel, <<"jid">>, _attrs, _} = _el | _els], Jid,
                Resource) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bind_els(__TopXMLNS, __IgnoreEls, _els,
-                          decode_bind_jid(__TopXMLNS, __IgnoreEls, _el),
-                          Resource);
-       true ->
-          decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid,
-                          Resource)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-bind">> ->
+         decode_bind_els(__TopXMLNS, __IgnoreEls, _els,
+                         decode_bind_jid(__TopXMLNS, __IgnoreEls, _el),
+                         Resource);
+      <<"urn:ietf:params:xml:ns:xmpp-bind">> ->
+         decode_bind_els(__TopXMLNS, __IgnoreEls, _els,
+                         decode_bind_jid(<<"urn:ietf:params:xml:ns:xmpp-bind">>,
+                                         __IgnoreEls, _el),
+                         Resource);
+      _ ->
+         decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid,
+                         Resource)
     end;
 decode_bind_els(__TopXMLNS, __IgnoreEls,
                [{xmlel, <<"resource">>, _attrs, _} = _el | _els], Jid,
                Resource) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid,
-                          decode_bind_resource(__TopXMLNS, __IgnoreEls, _el));
-       true ->
-          decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid,
-                          Resource)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"urn:ietf:params:xml:ns:xmpp-bind">> ->
+         decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid,
+                         decode_bind_resource(__TopXMLNS, __IgnoreEls, _el));
+      <<"urn:ietf:params:xml:ns:xmpp-bind">> ->
+         decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid,
+                         decode_bind_resource(<<"urn:ietf:params:xml:ns:xmpp-bind">>,
+                                              __IgnoreEls, _el));
+      _ ->
+         decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid,
+                         Resource)
     end;
 decode_bind_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                Jid, Resource) ->
@@ -16695,9 +19407,10 @@ decode_error(__TopXMLNS, __IgnoreEls,
             {xmlel, <<"error">>, _attrs, _els}) ->
     {Text, Reason} = decode_error_els(__TopXMLNS,
                                      __IgnoreEls, _els, undefined, undefined),
-    {Type, By} = decode_error_attrs(__TopXMLNS, _attrs,
-                                   undefined, undefined),
-    {error, Type, By, Reason, Text}.
+    {Type, Code, By} = decode_error_attrs(__TopXMLNS,
+                                         _attrs, undefined, undefined,
+                                         undefined),
+    {error, Type, Code, By, Reason, Text}.
 
 decode_error_els(__TopXMLNS, __IgnoreEls, [], Text,
                 Reason) ->
@@ -16705,314 +19418,298 @@ decode_error_els(__TopXMLNS, __IgnoreEls, [], Text,
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"text">>, _attrs, _} = _el | _els], Text,
                 Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els,
-                           decode_error_text(_xmlns, __IgnoreEls, _el),
-                           Reason);
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els,
+                          decode_error_text(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                            __IgnoreEls, _el),
+                          Reason);
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"bad-request">>, _attrs, _} = _el | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_bad_request(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_bad_request(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                   __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"conflict">>, _attrs, _} = _el | _els], Text,
                 Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_conflict(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_conflict(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"feature-not-implemented">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_feature_not_implemented(_xmlns,
-                                                                __IgnoreEls,
-                                                                _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_feature_not_implemented(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                               __IgnoreEls,
+                                                               _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"forbidden">>, _attrs, _} = _el | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_forbidden(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_forbidden(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                 __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"gone">>, _attrs, _} = _el | _els], Text,
                 Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_gone(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_gone(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                            __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"internal-server-error">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_internal_server_error(_xmlns,
-                                                              __IgnoreEls,
-                                                              _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_internal_server_error(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                             __IgnoreEls,
+                                                             _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"item-not-found">>, _attrs, _} = _el | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_item_not_found(_xmlns, __IgnoreEls,
-                                                       _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_item_not_found(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                      __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"jid-malformed">>, _attrs, _} = _el | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_jid_malformed(_xmlns, __IgnoreEls,
-                                                      _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_jid_malformed(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                     __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"not-acceptable">>, _attrs, _} = _el | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_not_acceptable(_xmlns, __IgnoreEls,
-                                                       _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_not_acceptable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                      __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"not-allowed">>, _attrs, _} = _el | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_not_allowed(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_not_allowed(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                   __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_not_authorized(_xmlns, __IgnoreEls,
-                                                       _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                      __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"policy-violation">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_policy_violation(_xmlns, __IgnoreEls,
-                                                         _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_policy_violation(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                        __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"recipient-unavailable">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_recipient_unavailable(_xmlns,
-                                                              __IgnoreEls,
-                                                              _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_recipient_unavailable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                             __IgnoreEls,
+                                                             _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"redirect">>, _attrs, _} = _el | _els], Text,
                 Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_redirect(_xmlns, __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_redirect(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"registration-required">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_registration_required(_xmlns,
-                                                              __IgnoreEls,
-                                                              _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_registration_required(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                             __IgnoreEls,
+                                                             _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"remote-server-not-found">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_remote_server_not_found(_xmlns,
-                                                                __IgnoreEls,
-                                                                _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_remote_server_not_found(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                               __IgnoreEls,
+                                                               _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"remote-server-timeout">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_remote_server_timeout(_xmlns,
-                                                              __IgnoreEls,
-                                                              _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_remote_server_timeout(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                             __IgnoreEls,
+                                                             _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"resource-constraint">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_resource_constraint(_xmlns,
-                                                            __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_resource_constraint(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                           __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"service-unavailable">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_service_unavailable(_xmlns,
-                                                            __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_service_unavailable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                           __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"subscription-required">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_subscription_required(_xmlns,
-                                                              __IgnoreEls,
-                                                              _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_subscription_required(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                             __IgnoreEls,
+                                                             _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"undefined-condition">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_undefined_condition(_xmlns,
-                                                            __IgnoreEls, _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_undefined_condition(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                           __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"unexpected-request">>, _attrs, _} = _el
                  | _els],
                 Text, Reason) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns ==
-        <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           decode_error_unexpected_request(_xmlns, __IgnoreEls,
-                                                           _el));
-       true ->
-          decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
-                           Reason)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"urn:ietf:params:xml:ns:xmpp-stanzas">> ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          decode_error_unexpected_request(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
+                                                          __IgnoreEls, _el));
+      _ ->
+         decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text,
+                          Reason)
     end;
 decode_error_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                 Text, Reason) ->
@@ -17020,25 +19717,32 @@ decode_error_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                     Reason).
 
 decode_error_attrs(__TopXMLNS,
-                  [{<<"type">>, _val} | _attrs], _Type, By) ->
-    decode_error_attrs(__TopXMLNS, _attrs, _val, By);
+                  [{<<"type">>, _val} | _attrs], _Type, Code, By) ->
+    decode_error_attrs(__TopXMLNS, _attrs, _val, Code, By);
+decode_error_attrs(__TopXMLNS,
+                  [{<<"code">>, _val} | _attrs], Type, _Code, By) ->
+    decode_error_attrs(__TopXMLNS, _attrs, Type, _val, By);
 decode_error_attrs(__TopXMLNS,
-                  [{<<"by">>, _val} | _attrs], Type, _By) ->
-    decode_error_attrs(__TopXMLNS, _attrs, Type, _val);
-decode_error_attrs(__TopXMLNS, [_ | _attrs], Type,
+                  [{<<"by">>, _val} | _attrs], Type, Code, _By) ->
+    decode_error_attrs(__TopXMLNS, _attrs, Type, Code,
+                      _val);
+decode_error_attrs(__TopXMLNS, [_ | _attrs], Type, Code,
                   By) ->
-    decode_error_attrs(__TopXMLNS, _attrs, Type, By);
-decode_error_attrs(__TopXMLNS, [], Type, By) ->
+    decode_error_attrs(__TopXMLNS, _attrs, Type, Code, By);
+decode_error_attrs(__TopXMLNS, [], Type, Code, By) ->
     {decode_error_attr_type(__TopXMLNS, Type),
+     decode_error_attr_code(__TopXMLNS, Code),
      decode_error_attr_by(__TopXMLNS, By)}.
 
-encode_error({error, Type, By, Reason, Text},
+encode_error({error, Type, Code, By, Reason, Text},
             _xmlns_attrs) ->
     _els = lists:reverse('encode_error_$text'(Text,
                                              'encode_error_$reason'(Reason,
                                                                     []))),
     _attrs = encode_error_attr_by(By,
-                                 encode_error_attr_type(Type, _xmlns_attrs)),
+                                 encode_error_attr_code(Code,
+                                                        encode_error_attr_type(Type,
+                                                                               _xmlns_attrs))),
     {xmlel, <<"error">>, _attrs, _els}.
 
 'encode_error_$text'(undefined, _acc) -> _acc;
@@ -17194,6 +19898,20 @@ decode_error_attr_type(__TopXMLNS, _val) ->
 encode_error_attr_type(_val, _acc) ->
     [{<<"type">>, enc_enum(_val)} | _acc].
 
+decode_error_attr_code(__TopXMLNS, undefined) ->
+    undefined;
+decode_error_attr_code(__TopXMLNS, _val) ->
+    case catch dec_int(_val, 0, infinity) of
+      {'EXIT', _} ->
+         erlang:error({xmpp_codec,
+                       {bad_attr_value, <<"code">>, <<"error">>, __TopXMLNS}});
+      _res -> _res
+    end.
+
+encode_error_attr_code(undefined, _acc) -> _acc;
+encode_error_attr_code(_val, _acc) ->
+    [{<<"code">>, enc_int(_val)} | _acc].
+
 decode_error_attr_by(__TopXMLNS, undefined) ->
     undefined;
 decode_error_attr_by(__TopXMLNS, _val) -> _val.
@@ -17551,57 +20269,81 @@ decode_presence_els(__TopXMLNS, __IgnoreEls, [], Error,
 decode_presence_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"error">>, _attrs, _} = _el | _els], Error,
                    Status, Show, Priority, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              decode_error(__TopXMLNS, __IgnoreEls, _el),
-                              Status, Show, Priority, __Els);
-       true ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              Error, Status, Show, Priority, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             decode_error(__TopXMLNS, __IgnoreEls, _el),
+                             Status, Show, Priority, __Els);
+      <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             decode_error(<<"jabber:client">>, __IgnoreEls,
+                                          _el),
+                             Status, Show, Priority, __Els);
+      _ ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status, Show, Priority, __Els)
     end;
 decode_presence_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"show">>, _attrs, _} = _el | _els], Error,
                    Status, Show, Priority, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              Error, Status,
-                              decode_presence_show(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                              Priority, __Els);
-       true ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              Error, Status, Show, Priority, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status,
+                             decode_presence_show(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                             Priority, __Els);
+      <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status,
+                             decode_presence_show(<<"jabber:client">>,
+                                                  __IgnoreEls, _el),
+                             Priority, __Els);
+      _ ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status, Show, Priority, __Els)
     end;
 decode_presence_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"status">>, _attrs, _} = _el | _els], Error,
                    Status, Show, Priority, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              Error,
-                              [decode_presence_status(__TopXMLNS, __IgnoreEls,
-                                                      _el)
-                               | Status],
-                              Show, Priority, __Els);
-       true ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              Error, Status, Show, Priority, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error,
+                             [decode_presence_status(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                              | Status],
+                             Show, Priority, __Els);
+      <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error,
+                             [decode_presence_status(<<"jabber:client">>,
+                                                     __IgnoreEls, _el)
+                              | Status],
+                             Show, Priority, __Els);
+      _ ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status, Show, Priority, __Els)
     end;
 decode_presence_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, <<"priority">>, _attrs, _} = _el | _els],
                    Error, Status, Show, Priority, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              Error, Status, Show,
-                              decode_presence_priority(__TopXMLNS, __IgnoreEls,
-                                                       _el),
-                              __Els);
-       true ->
-          decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
-                              Error, Status, Show, Priority, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status, Show,
+                             decode_presence_priority(__TopXMLNS, __IgnoreEls,
+                                                      _el),
+                             __Els);
+      <<"jabber:client">> ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status, Show,
+                             decode_presence_priority(<<"jabber:client">>,
+                                                      __IgnoreEls, _el),
+                             __Els);
+      _ ->
+         decode_presence_els(__TopXMLNS, __IgnoreEls, _els,
+                             Error, Status, Show, Priority, __Els)
     end;
 decode_presence_els(__TopXMLNS, __IgnoreEls,
                    [{xmlel, _, _, _} = _el | _els], Error, Status, Show,
@@ -17705,11 +20447,11 @@ encode_presence_attr_id(_val, _acc) ->
     [{<<"id">>, _val} | _acc].
 
 decode_presence_attr_type(__TopXMLNS, undefined) ->
-    undefined;
+    available;
 decode_presence_attr_type(__TopXMLNS, _val) ->
     case catch dec_enum(_val,
                        [unavailable, subscribe, subscribed, unsubscribe,
-                        unsubscribed, probe, error])
+                        unsubscribed, available, probe, error])
        of
       {'EXIT', _} ->
          erlang:error({xmpp_codec,
@@ -17718,7 +20460,7 @@ decode_presence_attr_type(__TopXMLNS, _val) ->
       _res -> _res
     end.
 
-encode_presence_attr_type(undefined, _acc) -> _acc;
+encode_presence_attr_type(available, _acc) -> _acc;
 encode_presence_attr_type(_val, _acc) ->
     [{<<"type">>, enc_enum(_val)} | _acc].
 
@@ -17913,56 +20655,80 @@ decode_message_els(__TopXMLNS, __IgnoreEls, [], Error,
 decode_message_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"error">>, _attrs, _} = _el | _els], Error,
                   Thread, Subject, Body, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els,
-                             decode_error(__TopXMLNS, __IgnoreEls, _el),
-                             Thread, Subject, Body, __Els);
-       true ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                             Thread, Subject, Body, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_error(__TopXMLNS, __IgnoreEls, _el), Thread,
+                            Subject, Body, __Els);
+      <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_error(<<"jabber:client">>, __IgnoreEls,
+                                         _el),
+                            Thread, Subject, Body, __Els);
+      _ ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread, Subject, Body, __Els)
     end;
 decode_message_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"subject">>, _attrs, _} = _el | _els], Error,
                   Thread, Subject, Body, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                             Thread,
-                             [decode_message_subject(__TopXMLNS, __IgnoreEls,
-                                                     _el)
-                              | Subject],
-                             Body, __Els);
-       true ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                             Thread, Subject, Body, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread,
+                            [decode_message_subject(__TopXMLNS, __IgnoreEls,
+                                                    _el)
+                             | Subject],
+                            Body, __Els);
+      <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread,
+                            [decode_message_subject(<<"jabber:client">>,
+                                                    __IgnoreEls, _el)
+                             | Subject],
+                            Body, __Els);
+      _ ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread, Subject, Body, __Els)
     end;
 decode_message_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"thread">>, _attrs, _} = _el | _els], Error,
                   Thread, Subject, Body, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                             decode_message_thread(__TopXMLNS, __IgnoreEls,
-                                                   _el),
-                             Subject, Body, __Els);
-       true ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                             Thread, Subject, Body, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            decode_message_thread(__TopXMLNS, __IgnoreEls,
+                                                  _el),
+                            Subject, Body, __Els);
+      <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            decode_message_thread(<<"jabber:client">>,
+                                                  __IgnoreEls, _el),
+                            Subject, Body, __Els);
+      _ ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread, Subject, Body, __Els)
     end;
 decode_message_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"body">>, _attrs, _} = _el | _els], Error,
                   Thread, Subject, Body, __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                             Thread, Subject,
-                             [decode_message_body(__TopXMLNS, __IgnoreEls, _el)
-                              | Body],
-                             __Els);
-       true ->
-          decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                             Thread, Subject, Body, __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread, Subject,
+                            [decode_message_body(__TopXMLNS, __IgnoreEls, _el)
+                             | Body],
+                            __Els);
+      <<"jabber:client">> ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread, Subject,
+                            [decode_message_body(<<"jabber:client">>,
+                                                 __IgnoreEls, _el)
+                             | Body],
+                            __Els);
+      _ ->
+         decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                            Thread, Subject, Body, __Els)
     end;
 decode_message_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, _, _, _} = _el | _els], Error, Thread, Subject,
@@ -18280,13 +21046,17 @@ decode_iq_els(__TopXMLNS, __IgnoreEls, [], Error,
 decode_iq_els(__TopXMLNS, __IgnoreEls,
              [{xmlel, <<"error">>, _attrs, _} = _el | _els], Error,
              __Els) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_iq_els(__TopXMLNS, __IgnoreEls, _els,
-                        decode_error(__TopXMLNS, __IgnoreEls, _el), __Els);
-       true ->
-          decode_iq_els(__TopXMLNS, __IgnoreEls, _els, Error,
-                        __Els)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:client">> ->
+         decode_iq_els(__TopXMLNS, __IgnoreEls, _els,
+                       decode_error(__TopXMLNS, __IgnoreEls, _el), __Els);
+      <<"jabber:client">> ->
+         decode_iq_els(__TopXMLNS, __IgnoreEls, _els,
+                       decode_error(<<"jabber:client">>, __IgnoreEls, _el),
+                       __Els);
+      _ ->
+         decode_iq_els(__TopXMLNS, __IgnoreEls, _els, Error,
+                       __Els)
     end;
 decode_iq_els(__TopXMLNS, __IgnoreEls,
              [{xmlel, _, _, _} = _el | _els], Error, __Els) ->
@@ -18425,12 +21195,19 @@ decode_stats_els(__TopXMLNS, __IgnoreEls, [], Stat) ->
     lists:reverse(Stat);
 decode_stats_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"stat">>, _attrs, _} = _el | _els], Stat) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_stats_els(__TopXMLNS, __IgnoreEls, _els,
-                           [decode_stat(__TopXMLNS, __IgnoreEls, _el) | Stat]);
-       true ->
-          decode_stats_els(__TopXMLNS, __IgnoreEls, _els, Stat)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/stats">> ->
+         decode_stats_els(__TopXMLNS, __IgnoreEls, _els,
+                          [decode_stat(__TopXMLNS, __IgnoreEls, _el) | Stat]);
+      <<"http://jabber.org/protocol/stats">> ->
+         decode_stats_els(__TopXMLNS, __IgnoreEls, _els,
+                          [decode_stat(<<"http://jabber.org/protocol/stats">>,
+                                       __IgnoreEls, _el)
+                           | Stat]);
+      _ ->
+         decode_stats_els(__TopXMLNS, __IgnoreEls, _els, Stat)
     end;
 decode_stats_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                 Stat) ->
@@ -18460,13 +21237,20 @@ decode_stat_els(__TopXMLNS, __IgnoreEls, [], Error) ->
 decode_stat_els(__TopXMLNS, __IgnoreEls,
                [{xmlel, <<"error">>, _attrs, _} = _el | _els],
                Error) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_stat_els(__TopXMLNS, __IgnoreEls, _els,
-                          [decode_stat_error(__TopXMLNS, __IgnoreEls, _el)
-                           | Error]);
-       true ->
-          decode_stat_els(__TopXMLNS, __IgnoreEls, _els, Error)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/stats">> ->
+         decode_stat_els(__TopXMLNS, __IgnoreEls, _els,
+                         [decode_stat_error(__TopXMLNS, __IgnoreEls, _el)
+                          | Error]);
+      <<"http://jabber.org/protocol/stats">> ->
+         decode_stat_els(__TopXMLNS, __IgnoreEls, _els,
+                         [decode_stat_error(<<"http://jabber.org/protocol/stats">>,
+                                            __IgnoreEls, _el)
+                          | Error]);
+      _ ->
+         decode_stat_els(__TopXMLNS, __IgnoreEls, _els, Error)
     end;
 decode_stat_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                Error) ->
@@ -18601,32 +21385,46 @@ decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
                             [{xmlel, <<"conference">>, _attrs, _} = _el
                              | _els],
                             Conference, Url) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
-                                       _els,
-                                       [decode_bookmark_conference(__TopXMLNS,
-                                                                   __IgnoreEls,
-                                                                   _el)
-                                        | Conference],
-                                       Url);
-       true ->
-          decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
-                                       _els, Conference, Url)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"storage:bookmarks">> ->
+         decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
+                                      _els,
+                                      [decode_bookmark_conference(__TopXMLNS,
+                                                                  __IgnoreEls,
+                                                                  _el)
+                                       | Conference],
+                                      Url);
+      <<"storage:bookmarks">> ->
+         decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
+                                      _els,
+                                      [decode_bookmark_conference(<<"storage:bookmarks">>,
+                                                                  __IgnoreEls,
+                                                                  _el)
+                                       | Conference],
+                                      Url);
+      _ ->
+         decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Conference, Url)
     end;
 decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
                             [{xmlel, <<"url">>, _attrs, _} = _el | _els],
                             Conference, Url) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
-                                       _els, Conference,
-                                       [decode_bookmark_url(__TopXMLNS,
-                                                            __IgnoreEls, _el)
-                                        | Url]);
-       true ->
-          decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
-                                       _els, Conference, Url)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"storage:bookmarks">> ->
+         decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Conference,
+                                      [decode_bookmark_url(__TopXMLNS,
+                                                           __IgnoreEls, _el)
+                                       | Url]);
+      <<"storage:bookmarks">> ->
+         decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Conference,
+                                      [decode_bookmark_url(<<"storage:bookmarks">>,
+                                                           __IgnoreEls, _el)
+                                       | Url]);
+      _ ->
+         decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
+                                      _els, Conference, Url)
     end;
 decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls,
                             [_ | _els], Conference, Url) ->
@@ -18721,32 +21519,45 @@ decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
 decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
                               [{xmlel, <<"nick">>, _attrs, _} = _el | _els],
                               Password, Nick) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
-                                         _els, Password,
-                                         decode_conference_nick(__TopXMLNS,
-                                                                __IgnoreEls,
-                                                                _el));
-       true ->
-          decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
-                                         _els, Password, Nick)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"storage:bookmarks">> ->
+         decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
+                                        _els, Password,
+                                        decode_conference_nick(__TopXMLNS,
+                                                               __IgnoreEls,
+                                                               _el));
+      <<"storage:bookmarks">> ->
+         decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
+                                        _els, Password,
+                                        decode_conference_nick(<<"storage:bookmarks">>,
+                                                               __IgnoreEls,
+                                                               _el));
+      _ ->
+         decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
+                                        _els, Password, Nick)
     end;
 decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
                               [{xmlel, <<"password">>, _attrs, _} = _el
                                | _els],
                               Password, Nick) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
-                                         _els,
-                                         decode_conference_password(__TopXMLNS,
-                                                                    __IgnoreEls,
-                                                                    _el),
-                                         Nick);
-       true ->
-          decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
-                                         _els, Password, Nick)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"storage:bookmarks">> ->
+         decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
+                                        _els,
+                                        decode_conference_password(__TopXMLNS,
+                                                                   __IgnoreEls,
+                                                                   _el),
+                                        Nick);
+      <<"storage:bookmarks">> ->
+         decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
+                                        _els,
+                                        decode_conference_password(<<"storage:bookmarks">>,
+                                                                   __IgnoreEls,
+                                                                   _el),
+                                        Nick);
+      _ ->
+         decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
+                                        _els, Password, Nick)
     end;
 decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls,
                               [_ | _els], Password, Nick) ->
@@ -18952,15 +21763,22 @@ decode_disco_items_els(__TopXMLNS, __IgnoreEls, [],
     lists:reverse(Items);
 decode_disco_items_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els,
-                                 [decode_disco_item(__TopXMLNS, __IgnoreEls,
-                                                    _el)
-                                  | Items]);
-       true ->
-          decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/disco#items">> ->
+         decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els,
+                                [decode_disco_item(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                                 | Items]);
+      <<"http://jabber.org/protocol/disco#items">> ->
+         decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els,
+                                [decode_disco_item(<<"http://jabber.org/protocol/disco#items">>,
+                                                   __IgnoreEls, _el)
+                                 | Items]);
+      _ ->
+         decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els,
+                                Items)
     end;
 decode_disco_items_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Items) ->
@@ -19081,44 +21899,62 @@ decode_disco_info_els(__TopXMLNS, __IgnoreEls, [],
 decode_disco_info_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"identity">>, _attrs, _} = _el | _els],
                      Xdata, Features, Identities) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
-                                Xdata, Features,
-                                [decode_disco_identity(__TopXMLNS, __IgnoreEls,
-                                                       _el)
-                                 | Identities]);
-       true ->
-          decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
-                                Xdata, Features, Identities)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/disco#info">> ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               Xdata, Features,
+                               [decode_disco_identity(__TopXMLNS, __IgnoreEls,
+                                                      _el)
+                                | Identities]);
+      <<"http://jabber.org/protocol/disco#info">> ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               Xdata, Features,
+                               [decode_disco_identity(<<"http://jabber.org/protocol/disco#info">>,
+                                                      __IgnoreEls, _el)
+                                | Identities]);
+      _ ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               Xdata, Features, Identities)
     end;
 decode_disco_info_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"feature">>, _attrs, _} = _el | _els], Xdata,
                      Features, Identities) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
-                                Xdata,
-                                [decode_disco_feature(__TopXMLNS, __IgnoreEls,
-                                                      _el)
-                                 | Features],
-                                Identities);
-       true ->
-          decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
-                                Xdata, Features, Identities)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">>
+         when __TopXMLNS ==
+                <<"http://jabber.org/protocol/disco#info">> ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               Xdata,
+                               [decode_disco_feature(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                                | Features],
+                               Identities);
+      <<"http://jabber.org/protocol/disco#info">> ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               Xdata,
+                               [decode_disco_feature(<<"http://jabber.org/protocol/disco#info">>,
+                                                     __IgnoreEls, _el)
+                                | Features],
+                               Identities);
+      _ ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               Xdata, Features, Identities)
     end;
 decode_disco_info_els(__TopXMLNS, __IgnoreEls,
                      [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata,
                      Features, Identities) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<"jabber:x:data">> ->
-          decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
-                                [decode_xdata(_xmlns, __IgnoreEls, _el)
-                                 | Xdata],
-                                Features, Identities);
-       true ->
-          decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
-                                Xdata, Features, Identities)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"jabber:x:data">> ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               [decode_xdata(<<"jabber:x:data">>, __IgnoreEls,
+                                             _el)
+                                | Xdata],
+                               Features, Identities);
+      _ ->
+         decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els,
+                               Xdata, Features, Identities)
     end;
 decode_disco_info_els(__TopXMLNS, __IgnoreEls,
                      [_ | _els], Xdata, Features, Identities) ->
@@ -19319,17 +22155,25 @@ decode_unblock_els(__TopXMLNS, __IgnoreEls, [],
     lists:reverse(Items);
 decode_unblock_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_unblock_els(__TopXMLNS, __IgnoreEls, _els,
-                             case decode_block_item(__TopXMLNS, __IgnoreEls,
-                                                    _el)
-                                 of
-                               undefined -> Items;
-                               _new_el -> [_new_el | Items]
-                             end);
-       true ->
-          decode_unblock_els(__TopXMLNS, __IgnoreEls, _els, Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:blocking">> ->
+         decode_unblock_els(__TopXMLNS, __IgnoreEls, _els,
+                            case decode_block_item(__TopXMLNS, __IgnoreEls,
+                                                   _el)
+                                of
+                              undefined -> Items;
+                              _new_el -> [_new_el | Items]
+                            end);
+      <<"urn:xmpp:blocking">> ->
+         decode_unblock_els(__TopXMLNS, __IgnoreEls, _els,
+                            case decode_block_item(<<"urn:xmpp:blocking">>,
+                                                   __IgnoreEls, _el)
+                                of
+                              undefined -> Items;
+                              _new_el -> [_new_el | Items]
+                            end);
+      _ ->
+         decode_unblock_els(__TopXMLNS, __IgnoreEls, _els, Items)
     end;
 decode_unblock_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                   Items) ->
@@ -19357,16 +22201,24 @@ decode_block_els(__TopXMLNS, __IgnoreEls, [], Items) ->
     lists:reverse(Items);
 decode_block_els(__TopXMLNS, __IgnoreEls,
                 [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_block_els(__TopXMLNS, __IgnoreEls, _els,
-                           case decode_block_item(__TopXMLNS, __IgnoreEls, _el)
-                               of
-                             undefined -> Items;
-                             _new_el -> [_new_el | Items]
-                           end);
-       true ->
-          decode_block_els(__TopXMLNS, __IgnoreEls, _els, Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"urn:xmpp:blocking">> ->
+         decode_block_els(__TopXMLNS, __IgnoreEls, _els,
+                          case decode_block_item(__TopXMLNS, __IgnoreEls, _el)
+                              of
+                            undefined -> Items;
+                            _new_el -> [_new_el | Items]
+                          end);
+      <<"urn:xmpp:blocking">> ->
+         decode_block_els(__TopXMLNS, __IgnoreEls, _els,
+                          case decode_block_item(<<"urn:xmpp:blocking">>,
+                                                 __IgnoreEls, _el)
+                              of
+                            undefined -> Items;
+                            _new_el -> [_new_el | Items]
+                          end);
+      _ ->
+         decode_block_els(__TopXMLNS, __IgnoreEls, _els, Items)
     end;
 decode_block_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                 Items) ->
@@ -19421,7 +22273,7 @@ decode_privacy(__TopXMLNS, __IgnoreEls,
     {Lists, Default, Active} =
        decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, [],
                           undefined, undefined),
-    {privacy, Lists, Default, Active}.
+    {privacy_query, Lists, Default, Active}.
 
 decode_privacy_els(__TopXMLNS, __IgnoreEls, [], Lists,
                   Default, Active) ->
@@ -19429,48 +22281,64 @@ decode_privacy_els(__TopXMLNS, __IgnoreEls, [], Lists,
 decode_privacy_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"list">>, _attrs, _} = _el | _els], Lists,
                   Default, Active) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_els(__TopXMLNS, __IgnoreEls, _els,
-                             [decode_privacy_list(__TopXMLNS, __IgnoreEls, _el)
-                              | Lists],
-                             Default, Active);
-       true ->
-          decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
-                             Default, Active)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els,
+                            [decode_privacy_list(__TopXMLNS, __IgnoreEls, _el)
+                             | Lists],
+                            Default, Active);
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els,
+                            [decode_privacy_list(<<"jabber:iq:privacy">>,
+                                                 __IgnoreEls, _el)
+                             | Lists],
+                            Default, Active);
+      _ ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
+                            Default, Active)
     end;
 decode_privacy_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"default">>, _attrs, _} = _el | _els], Lists,
                   Default, Active) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
-                             decode_privacy_default_list(__TopXMLNS,
-                                                         __IgnoreEls, _el),
-                             Active);
-       true ->
-          decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
-                             Default, Active)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
+                            decode_privacy_default_list(__TopXMLNS,
+                                                        __IgnoreEls, _el),
+                            Active);
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
+                            decode_privacy_default_list(<<"jabber:iq:privacy">>,
+                                                        __IgnoreEls, _el),
+                            Active);
+      _ ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
+                            Default, Active)
     end;
 decode_privacy_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"active">>, _attrs, _} = _el | _els], Lists,
                   Default, Active) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
-                             Default,
-                             decode_privacy_active_list(__TopXMLNS,
-                                                        __IgnoreEls, _el));
-       true ->
-          decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
-                             Default, Active)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
+                            Default,
+                            decode_privacy_active_list(__TopXMLNS, __IgnoreEls,
+                                                       _el));
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
+                            Default,
+                            decode_privacy_active_list(<<"jabber:iq:privacy">>,
+                                                       __IgnoreEls, _el));
+      _ ->
+         decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
+                            Default, Active)
     end;
 decode_privacy_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                   Lists, Default, Active) ->
     decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists,
                       Default, Active).
 
-encode_privacy({privacy, Lists, Default, Active},
+encode_privacy({privacy_query, Lists, Default, Active},
               _xmlns_attrs) ->
     _els = lists:reverse('encode_privacy_$lists'(Lists,
                                                 'encode_privacy_$default'(Default,
@@ -19577,15 +22445,20 @@ decode_privacy_list_els(__TopXMLNS, __IgnoreEls, [],
     lists:reverse(Items);
 decode_privacy_list_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els,
-                                  [decode_privacy_item(__TopXMLNS, __IgnoreEls,
-                                                       _el)
-                                   | Items]);
-       true ->
-          decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Items)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_privacy_item(__TopXMLNS, __IgnoreEls,
+                                                      _el)
+                                  | Items]);
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_privacy_item(<<"jabber:iq:privacy">>,
+                                                      __IgnoreEls, _el)
+                                  | Items]);
+      _ ->
+         decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Items)
     end;
 decode_privacy_list_els(__TopXMLNS, __IgnoreEls,
                        [_ | _els], Items) ->
@@ -19624,63 +22497,98 @@ encode_privacy_list_attr_name(_val, _acc) ->
 
 decode_privacy_item(__TopXMLNS, __IgnoreEls,
                    {xmlel, <<"item">>, _attrs, _els}) ->
-    Kinds = decode_privacy_item_els(__TopXMLNS, __IgnoreEls,
-                                   _els, []),
+    {Iq, Presence_out, Message, Presence_in} =
+       decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                               false, false, false, false),
     {Action, Order, Type, Value} =
        decode_privacy_item_attrs(__TopXMLNS, _attrs, undefined,
                                  undefined, undefined, undefined),
-    {privacy_item, Order, Action, Type, Value, Kinds}.
+    {privacy_item, Order, Action, Type, Value, Message, Iq,
+     Presence_in, Presence_out}.
 
-decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [],
-                       Kinds) ->
-    lists:reverse(Kinds);
+decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [], Iq,
+                       Presence_out, Message, Presence_in) ->
+    {Iq, Presence_out, Message, Presence_in};
 decode_privacy_item_els(__TopXMLNS, __IgnoreEls,
-                       [{xmlel, <<"message">>, _attrs, _} = _el | _els],
-                       Kinds) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds);
-       true ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds)
+                       [{xmlel, <<"message">>, _attrs, _} = _el | _els], Iq,
+                       Presence_out, Message, Presence_in) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out,
+                                 decode_privacy_message(__TopXMLNS,
+                                                        __IgnoreEls, _el),
+                                 Presence_in);
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out,
+                                 decode_privacy_message(<<"jabber:iq:privacy">>,
+                                                        __IgnoreEls, _el),
+                                 Presence_in);
+      _ ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out, Message, Presence_in)
     end;
 decode_privacy_item_els(__TopXMLNS, __IgnoreEls,
-                       [{xmlel, <<"iq">>, _attrs, _} = _el | _els], Kinds) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds);
-       true ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds)
+                       [{xmlel, <<"iq">>, _attrs, _} = _el | _els], Iq,
+                       Presence_out, Message, Presence_in) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 decode_privacy_iq(__TopXMLNS, __IgnoreEls,
+                                                   _el),
+                                 Presence_out, Message, Presence_in);
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 decode_privacy_iq(<<"jabber:iq:privacy">>,
+                                                   __IgnoreEls, _el),
+                                 Presence_out, Message, Presence_in);
+      _ ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out, Message, Presence_in)
     end;
 decode_privacy_item_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"presence-in">>, _attrs, _} = _el | _els],
-                       Kinds) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds);
-       true ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds)
+                       Iq, Presence_out, Message, Presence_in) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out, Message,
+                                 decode_privacy_presence_in(__TopXMLNS,
+                                                            __IgnoreEls, _el));
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out, Message,
+                                 decode_privacy_presence_in(<<"jabber:iq:privacy">>,
+                                                            __IgnoreEls, _el));
+      _ ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out, Message, Presence_in)
     end;
 decode_privacy_item_els(__TopXMLNS, __IgnoreEls,
                        [{xmlel, <<"presence-out">>, _attrs, _} = _el | _els],
-                       Kinds) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds);
-       true ->
-          decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                  Kinds)
+                       Iq, Presence_out, Message, Presence_in) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq,
+                                 decode_privacy_presence_out(__TopXMLNS,
+                                                             __IgnoreEls, _el),
+                                 Message, Presence_in);
+      <<"jabber:iq:privacy">> ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq,
+                                 decode_privacy_presence_out(<<"jabber:iq:privacy">>,
+                                                             __IgnoreEls, _el),
+                                 Message, Presence_in);
+      _ ->
+         decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Iq, Presence_out, Message, Presence_in)
     end;
 decode_privacy_item_els(__TopXMLNS, __IgnoreEls,
-                       [_ | _els], Kinds) ->
+                       [_ | _els], Iq, Presence_out, Message, Presence_in) ->
     decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els,
-                           Kinds).
+                           Iq, Presence_out, Message, Presence_in).
 
 decode_privacy_item_attrs(__TopXMLNS,
                          [{<<"action">>, _val} | _attrs], _Action, Order, Type,
@@ -19714,10 +22622,13 @@ decode_privacy_item_attrs(__TopXMLNS, [], Action, Order,
      decode_privacy_item_attr_value(__TopXMLNS, Value)}.
 
 encode_privacy_item({privacy_item, Order, Action, Type,
-                    Value, Kinds},
+                    Value, Message, Iq, Presence_in, Presence_out},
                    _xmlns_attrs) ->
-    _els = lists:reverse('encode_privacy_item_$kinds'(Kinds,
-                                                     [])),
+    _els = lists:reverse('encode_privacy_item_$iq'(Iq,
+                                                  'encode_privacy_item_$presence_out'(Presence_out,
+                                                                                      'encode_privacy_item_$message'(Message,
+                                                                                                                     'encode_privacy_item_$presence_in'(Presence_in,
+                                                                                                                                                        []))))),
     _attrs = encode_privacy_item_attr_value(Value,
                                            encode_privacy_item_attr_type(Type,
                                                                          encode_privacy_item_attr_order(Order,
@@ -19725,27 +22636,23 @@ encode_privacy_item({privacy_item, Order, Action, Type,
                                                                                                                                         _xmlns_attrs)))),
     {xmlel, <<"item">>, _attrs, _els}.
 
-'encode_privacy_item_$kinds'([], _acc) -> _acc;
-'encode_privacy_item_$kinds'([message = Kinds | _els],
-                            _acc) ->
-    'encode_privacy_item_$kinds'(_els,
-                                [encode_privacy_message(Kinds, []) | _acc]);
-'encode_privacy_item_$kinds'([iq = Kinds | _els],
-                            _acc) ->
-    'encode_privacy_item_$kinds'(_els,
-                                [encode_privacy_iq(Kinds, []) | _acc]);
-'encode_privacy_item_$kinds'(['presence-in' = Kinds
-                             | _els],
-                            _acc) ->
-    'encode_privacy_item_$kinds'(_els,
-                                [encode_privacy_presence_in(Kinds, [])
-                                 | _acc]);
-'encode_privacy_item_$kinds'(['presence-out' = Kinds
-                             | _els],
-                            _acc) ->
-    'encode_privacy_item_$kinds'(_els,
-                                [encode_privacy_presence_out(Kinds, [])
-                                 | _acc]).
+'encode_privacy_item_$iq'(false, _acc) -> _acc;
+'encode_privacy_item_$iq'(Iq, _acc) ->
+    [encode_privacy_iq(Iq, []) | _acc].
+
+'encode_privacy_item_$presence_out'(false, _acc) ->
+    _acc;
+'encode_privacy_item_$presence_out'(Presence_out,
+                                   _acc) ->
+    [encode_privacy_presence_out(Presence_out, []) | _acc].
+
+'encode_privacy_item_$message'(false, _acc) -> _acc;
+'encode_privacy_item_$message'(Message, _acc) ->
+    [encode_privacy_message(Message, []) | _acc].
+
+'encode_privacy_item_$presence_in'(false, _acc) -> _acc;
+'encode_privacy_item_$presence_in'(Presence_in, _acc) ->
+    [encode_privacy_presence_in(Presence_in, []) | _acc].
 
 decode_privacy_item_attr_action(__TopXMLNS,
                                undefined) ->
@@ -19802,90 +22709,111 @@ encode_privacy_item_attr_value(_val, _acc) ->
 
 decode_privacy_presence_out(__TopXMLNS, __IgnoreEls,
                            {xmlel, <<"presence-out">>, _attrs, _els}) ->
-    'presence-out'.
+    true.
 
-encode_privacy_presence_out('presence-out',
-                           _xmlns_attrs) ->
+encode_privacy_presence_out(true, _xmlns_attrs) ->
     _els = [],
     _attrs = _xmlns_attrs,
     {xmlel, <<"presence-out">>, _attrs, _els}.
 
 decode_privacy_presence_in(__TopXMLNS, __IgnoreEls,
                           {xmlel, <<"presence-in">>, _attrs, _els}) ->
-    'presence-in'.
+    true.
 
-encode_privacy_presence_in('presence-in',
-                          _xmlns_attrs) ->
+encode_privacy_presence_in(true, _xmlns_attrs) ->
     _els = [],
     _attrs = _xmlns_attrs,
     {xmlel, <<"presence-in">>, _attrs, _els}.
 
 decode_privacy_iq(__TopXMLNS, __IgnoreEls,
                  {xmlel, <<"iq">>, _attrs, _els}) ->
-    iq.
+    true.
 
-encode_privacy_iq(iq, _xmlns_attrs) ->
+encode_privacy_iq(true, _xmlns_attrs) ->
     _els = [],
     _attrs = _xmlns_attrs,
     {xmlel, <<"iq">>, _attrs, _els}.
 
 decode_privacy_message(__TopXMLNS, __IgnoreEls,
                       {xmlel, <<"message">>, _attrs, _els}) ->
-    message.
+    true.
 
-encode_privacy_message(message, _xmlns_attrs) ->
+encode_privacy_message(true, _xmlns_attrs) ->
     _els = [],
     _attrs = _xmlns_attrs,
     {xmlel, <<"message">>, _attrs, _els}.
 
-decode_roster(__TopXMLNS, __IgnoreEls,
-             {xmlel, <<"query">>, _attrs, _els}) ->
-    Items = decode_roster_els(__TopXMLNS, __IgnoreEls, _els,
-                             []),
-    Ver = decode_roster_attrs(__TopXMLNS, _attrs,
-                             undefined),
-    {roster, Items, Ver}.
+decode_rosterver_feature(__TopXMLNS, __IgnoreEls,
+                        {xmlel, <<"ver">>, _attrs, _els}) ->
+    {rosterver_feature}.
+
+encode_rosterver_feature({rosterver_feature},
+                        _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"ver">>, _attrs, _els}.
+
+decode_roster_query(__TopXMLNS, __IgnoreEls,
+                   {xmlel, <<"query">>, _attrs, _els}) ->
+    Items = decode_roster_query_els(__TopXMLNS, __IgnoreEls,
+                                   _els, []),
+    Ver = decode_roster_query_attrs(__TopXMLNS, _attrs,
+                                   undefined),
+    {roster_query, Items, Ver}.
 
-decode_roster_els(__TopXMLNS, __IgnoreEls, [], Items) ->
+decode_roster_query_els(__TopXMLNS, __IgnoreEls, [],
+                       Items) ->
     lists:reverse(Items);
-decode_roster_els(__TopXMLNS, __IgnoreEls,
-                 [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_roster_els(__TopXMLNS, __IgnoreEls, _els,
-                            [decode_roster_item(__TopXMLNS, __IgnoreEls, _el)
-                             | Items]);
-       true ->
-          decode_roster_els(__TopXMLNS, __IgnoreEls, _els, Items)
-    end;
-decode_roster_els(__TopXMLNS, __IgnoreEls, [_ | _els],
-                 Items) ->
-    decode_roster_els(__TopXMLNS, __IgnoreEls, _els, Items).
-
-decode_roster_attrs(__TopXMLNS,
-                   [{<<"ver">>, _val} | _attrs], _Ver) ->
-    decode_roster_attrs(__TopXMLNS, _attrs, _val);
-decode_roster_attrs(__TopXMLNS, [_ | _attrs], Ver) ->
-    decode_roster_attrs(__TopXMLNS, _attrs, Ver);
-decode_roster_attrs(__TopXMLNS, [], Ver) ->
-    decode_roster_attr_ver(__TopXMLNS, Ver).
-
-encode_roster({roster, Items, Ver}, _xmlns_attrs) ->
-    _els = lists:reverse('encode_roster_$items'(Items, [])),
-    _attrs = encode_roster_attr_ver(Ver, _xmlns_attrs),
+decode_roster_query_els(__TopXMLNS, __IgnoreEls,
+                       [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) ->
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:roster">> ->
+         decode_roster_query_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_roster_item(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                                  | Items]);
+      <<"jabber:iq:roster">> ->
+         decode_roster_query_els(__TopXMLNS, __IgnoreEls, _els,
+                                 [decode_roster_item(<<"jabber:iq:roster">>,
+                                                     __IgnoreEls, _el)
+                                  | Items]);
+      _ ->
+         decode_roster_query_els(__TopXMLNS, __IgnoreEls, _els,
+                                 Items)
+    end;
+decode_roster_query_els(__TopXMLNS, __IgnoreEls,
+                       [_ | _els], Items) ->
+    decode_roster_query_els(__TopXMLNS, __IgnoreEls, _els,
+                           Items).
+
+decode_roster_query_attrs(__TopXMLNS,
+                         [{<<"ver">>, _val} | _attrs], _Ver) ->
+    decode_roster_query_attrs(__TopXMLNS, _attrs, _val);
+decode_roster_query_attrs(__TopXMLNS, [_ | _attrs],
+                         Ver) ->
+    decode_roster_query_attrs(__TopXMLNS, _attrs, Ver);
+decode_roster_query_attrs(__TopXMLNS, [], Ver) ->
+    decode_roster_query_attr_ver(__TopXMLNS, Ver).
+
+encode_roster_query({roster_query, Items, Ver},
+                   _xmlns_attrs) ->
+    _els = lists:reverse('encode_roster_query_$items'(Items,
+                                                     [])),
+    _attrs = encode_roster_query_attr_ver(Ver,
+                                         _xmlns_attrs),
     {xmlel, <<"query">>, _attrs, _els}.
 
-'encode_roster_$items'([], _acc) -> _acc;
-'encode_roster_$items'([Items | _els], _acc) ->
-    'encode_roster_$items'(_els,
-                          [encode_roster_item(Items, []) | _acc]).
+'encode_roster_query_$items'([], _acc) -> _acc;
+'encode_roster_query_$items'([Items | _els], _acc) ->
+    'encode_roster_query_$items'(_els,
+                                [encode_roster_item(Items, []) | _acc]).
 
-decode_roster_attr_ver(__TopXMLNS, undefined) ->
+decode_roster_query_attr_ver(__TopXMLNS, undefined) ->
     undefined;
-decode_roster_attr_ver(__TopXMLNS, _val) -> _val.
+decode_roster_query_attr_ver(__TopXMLNS, _val) -> _val.
 
-encode_roster_attr_ver(undefined, _acc) -> _acc;
-encode_roster_attr_ver(_val, _acc) ->
+encode_roster_query_attr_ver(undefined, _acc) -> _acc;
+encode_roster_query_attr_ver(_val, _acc) ->
     [{<<"ver">>, _val} | _acc].
 
 decode_roster_item(__TopXMLNS, __IgnoreEls,
@@ -19903,15 +22831,20 @@ decode_roster_item_els(__TopXMLNS, __IgnoreEls, [],
 decode_roster_item_els(__TopXMLNS, __IgnoreEls,
                       [{xmlel, <<"group">>, _attrs, _} = _el | _els],
                       Groups) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                 [decode_roster_group(__TopXMLNS, __IgnoreEls,
-                                                      _el)
-                                  | Groups]);
-       true ->
-          decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els,
-                                 Groups)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:roster">> ->
+         decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                [decode_roster_group(__TopXMLNS, __IgnoreEls,
+                                                     _el)
+                                 | Groups]);
+      <<"jabber:iq:roster">> ->
+         decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                [decode_roster_group(<<"jabber:iq:roster">>,
+                                                     __IgnoreEls, _el)
+                                 | Groups]);
+      _ ->
+         decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els,
+                                Groups)
     end;
 decode_roster_item_els(__TopXMLNS, __IgnoreEls,
                       [_ | _els], Groups) ->
@@ -19982,10 +22915,10 @@ encode_roster_item_attr_jid(_val, _acc) ->
     [{<<"jid">>, enc_jid(_val)} | _acc].
 
 decode_roster_item_attr_name(__TopXMLNS, undefined) ->
-    undefined;
+    <<>>;
 decode_roster_item_attr_name(__TopXMLNS, _val) -> _val.
 
-encode_roster_item_attr_name(undefined, _acc) -> _acc;
+encode_roster_item_attr_name(<<>>, _acc) -> _acc;
 encode_roster_item_attr_name(_val, _acc) ->
     [{<<"name">>, _val} | _acc].
 
@@ -20067,39 +23000,53 @@ decode_version_els(__TopXMLNS, __IgnoreEls, [], Ver, Os,
 decode_version_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"name">>, _attrs, _} = _el | _els], Ver, Os,
                   Name) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
-                             Os,
-                             decode_version_name(__TopXMLNS, __IgnoreEls,
-                                                 _el));
-       true ->
-          decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
-                             Os, Name)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:version">> ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
+                            Os,
+                            decode_version_name(__TopXMLNS, __IgnoreEls, _el));
+      <<"jabber:iq:version">> ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
+                            Os,
+                            decode_version_name(<<"jabber:iq:version">>,
+                                                __IgnoreEls, _el));
+      _ ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
+                            Os, Name)
     end;
 decode_version_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"version">>, _attrs, _} = _el | _els], Ver,
                   Os, Name) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_version_els(__TopXMLNS, __IgnoreEls, _els,
-                             decode_version_ver(__TopXMLNS, __IgnoreEls, _el),
-                             Os, Name);
-       true ->
-          decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
-                             Os, Name)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:version">> ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_version_ver(__TopXMLNS, __IgnoreEls, _el),
+                            Os, Name);
+      <<"jabber:iq:version">> ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els,
+                            decode_version_ver(<<"jabber:iq:version">>,
+                                               __IgnoreEls, _el),
+                            Os, Name);
+      _ ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
+                            Os, Name)
     end;
 decode_version_els(__TopXMLNS, __IgnoreEls,
                   [{xmlel, <<"os">>, _attrs, _} = _el | _els], Ver, Os,
                   Name) ->
-    _xmlns = get_attr(<<"xmlns">>, _attrs),
-    if _xmlns == <<>>; _xmlns == __TopXMLNS ->
-          decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
-                             decode_version_os(__TopXMLNS, __IgnoreEls, _el),
-                             Name);
-       true ->
-          decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
-                             Os, Name)
+    case get_attr(<<"xmlns">>, _attrs) of
+      <<"">> when __TopXMLNS == <<"jabber:iq:version">> ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
+                            decode_version_os(__TopXMLNS, __IgnoreEls, _el),
+                            Name);
+      <<"jabber:iq:version">> ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
+                            decode_version_os(<<"jabber:iq:version">>,
+                                              __IgnoreEls, _el),
+                            Name);
+      _ ->
+         decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver,
+                            Os, Name)
     end;
 decode_version_els(__TopXMLNS, __IgnoreEls, [_ | _els],
                   Ver, Os, Name) ->
@@ -20222,21 +23169,21 @@ encode_version_name_cdata(_val, _acc) ->
 
 decode_last(__TopXMLNS, __IgnoreEls,
            {xmlel, <<"query">>, _attrs, _els}) ->
-    Text = decode_last_els(__TopXMLNS, __IgnoreEls, _els,
-                          <<>>),
+    Status = decode_last_els(__TopXMLNS, __IgnoreEls, _els,
+                            <<>>),
     Seconds = decode_last_attrs(__TopXMLNS, _attrs,
                                undefined),
-    {last, Seconds, Text}.
+    {last, Seconds, Status}.
 
-decode_last_els(__TopXMLNS, __IgnoreEls, [], Text) ->
-    decode_last_cdata(__TopXMLNS, Text);
+decode_last_els(__TopXMLNS, __IgnoreEls, [], Status) ->
+    decode_last_cdata(__TopXMLNS, Status);
 decode_last_els(__TopXMLNS, __IgnoreEls,
-               [{xmlcdata, _data} | _els], Text) ->
+               [{xmlcdata, _data} | _els], Status) ->
     decode_last_els(__TopXMLNS, __IgnoreEls, _els,
-                   <<Text/binary, _data/binary>>);
+                   <<Status/binary, _data/binary>>);
 decode_last_els(__TopXMLNS, __IgnoreEls, [_ | _els],
-               Text) ->
-    decode_last_els(__TopXMLNS, __IgnoreEls, _els, Text).
+               Status) ->
+    decode_last_els(__TopXMLNS, __IgnoreEls, _els, Status).
 
 decode_last_attrs(__TopXMLNS,
                  [{<<"seconds">>, _val} | _attrs], _Seconds) ->
@@ -20246,8 +23193,8 @@ decode_last_attrs(__TopXMLNS, [_ | _attrs], Seconds) ->
 decode_last_attrs(__TopXMLNS, [], Seconds) ->
     decode_last_attr_seconds(__TopXMLNS, Seconds).
 
-encode_last({last, Seconds, Text}, _xmlns_attrs) ->
-    _els = encode_last_cdata(Text, []),
+encode_last({last, Seconds, Status}, _xmlns_attrs) ->
+    _els = encode_last_cdata(Status, []),
     _attrs = encode_last_attr_seconds(Seconds,
                                      _xmlns_attrs),
     {xmlel, <<"query">>, _attrs, _els}.
@@ -20267,9 +23214,9 @@ encode_last_attr_seconds(undefined, _acc) -> _acc;
 encode_last_attr_seconds(_val, _acc) ->
     [{<<"seconds">>, enc_int(_val)} | _acc].
 
-decode_last_cdata(__TopXMLNS, <<>>) -> undefined;
+decode_last_cdata(__TopXMLNS, <<>>) -> <<>>;
 decode_last_cdata(__TopXMLNS, _val) -> _val.
 
-encode_last_cdata(undefined, _acc) -> _acc;
+encode_last_cdata(<<>>, _acc) -> _acc;
 encode_last_cdata(_val, _acc) ->
     [{xmlcdata, _val} | _acc].
diff --git a/src/xmpp_util.erl b/src/xmpp_util.erl
new file mode 100644 (file)
index 0000000..42b251f
--- /dev/null
@@ -0,0 +1,81 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 12 Jul 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(xmpp_util).
+
+%% API
+-export([add_delay_info/3, add_delay_info/4, unwrap_carbon/1,
+        is_standalone_chat_state/1]).
+
+-include("xmpp.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+-spec add_delay_info(stanza(), jid(), erlang:timestamp()) -> stanza().
+add_delay_info(Stz, From, Time) ->
+    add_delay_info(Stz, From, Time, <<"">>).
+
+-spec add_delay_info(stanza(), jid(),
+                    erlang:timestamp(), binary()) -> stanza().
+
+add_delay_info(Stz, From, Time, Desc) ->
+    case xmpp:get_subtag(Stz, #delay{}) of
+       #delay{from = OldFrom, desc = OldDesc} = Delay ->
+           case jid:tolower(From) == jid:tolower(OldFrom) of
+               true when Desc == <<"">> ->
+                   Stz;
+               true when OldDesc == <<"">> ->
+                   xmpp:set_subtag(Stz, Delay#delay{desc = Desc});
+               true ->
+                   case binary:match(OldDesc, Desc) of
+                       nomatch ->
+                           NewDesc = <<OldDesc/binary, ", ", Desc/binary>>,
+                           xmpp:set_subtag(Stz, Delay#delay{desc = NewDesc});
+                       _ ->
+                           Stz
+                   end;
+               false ->
+                   NewDelay = #delay{stamp = Time, from = From, desc = Desc},
+                   xmpp:set_subtag(Stz, NewDelay)
+           end;
+       false ->
+           Delay = #delay{stamp = Time, from = From, desc = Desc},
+           xmpp:set_subtag(Stz, Delay)
+    end.
+
+-spec unwrap_carbon(stanza()) -> xmpp_element().
+unwrap_carbon(#message{} = Msg) ->
+    case xmpp:get_subtag(Msg, #carbons_sent{}) of
+       #carbons_sent{forwarded = #forwarded{sub_els = [El]}} ->
+           El;
+       _ ->
+           case xmpp:get_subtag(Msg, #carbons_received{}) of
+               #carbons_received{forwarded = #forwarded{sub_els = [El]}} ->
+                   El;
+               _ ->
+                   Msg
+           end
+    end;
+unwrap_carbon(Stanza) -> Stanza.
+
+-spec is_standalone_chat_state(stanza()) -> boolean().
+is_standalone_chat_state(Stanza) ->
+    case unwrap_carbon(Stanza) of
+       #message{sub_els = Els} ->
+           IgnoreNS = [?NS_CHATSTATES, ?NS_DELAY],
+           Stripped = [El || El <- Els,
+                             not lists:member(xmpp:get_ns(El), IgnoreNS)],
+           Stripped == [];
+       _ ->
+           false
+    end.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
index acf9c3bb7e874f1a94f91f55482af1c3bee4e601..07d3a3dfd112e6ca1ccc09aa22abb6860a7c7cc0 100644 (file)
@@ -1,11 +1,11 @@
 -xml(last,
      #elem{name = <<"query">>,
            xmlns = <<"jabber:iq:last">>,
-           result = {last, '$seconds', '$text'},
+           result = {last, '$seconds', '$status'},
            attrs = [#attr{name = <<"seconds">>,
                           enc = {enc_int, []},
                           dec = {dec_int, [0, infinity]}}],
-           cdata = #cdata{label = '$text'}}).
+           cdata = #cdata{default = <<"">>, label = '$status'}}).
 
 -xml(version_name,
      #elem{name = <<"name">>,
@@ -54,7 +54,8 @@
                           required = true,
                           dec = {dec_jid, []},
                           enc = {enc_jid, []}},
-                    #attr{name = <<"name">>},
+                    #attr{name = <<"name">>,
+                         default = <<"">>},
                     #attr{name = <<"subscription">>,
                           default = none,
                           enc = {enc_enum, []},
                           dec = {dec_enum, [[subscribe]]}}],
            refs = [#ref{name = roster_group, label = '$groups'}]}).
 
--xml(roster,
+-xml(roster_query,
      #elem{name = <<"query">>,
            xmlns = <<"jabber:iq:roster">>,
-           result = {roster, '$items', '$ver'},
+           result = {roster_query, '$items', '$ver'},
            attrs = [#attr{name = <<"ver">>}],
            refs = [#ref{name = roster_item, label = '$items'}]}).
 
+-xml(rosterver_feature,
+     #elem{name = <<"ver">>,
+          xmlns = <<"urn:xmpp:features:rosterver">>,
+          result = {rosterver_feature}}).
+
 -xml(privacy_message, #elem{name = <<"message">>, xmlns = <<"jabber:iq:privacy">>,
-                            result = message}).
+                            result = true}).
 -xml(privacy_iq, #elem{name = <<"iq">>, xmlns = <<"jabber:iq:privacy">>,
-                       result = iq}).
+                       result = true}).
 -xml(privacy_presence_in, #elem{name = <<"presence-in">>,
                                 xmlns = <<"jabber:iq:privacy">>,
-                                result = 'presence-in'}).
+                                result = true}).
 -xml(privacy_presence_out, #elem{name = <<"presence-out">>,
                                  xmlns = <<"jabber:iq:privacy">>,
-                                 result = 'presence-out'}).
+                                 result = true}).
 
 -xml(privacy_item,
      #elem{name = <<"item">>,
            xmlns = <<"jabber:iq:privacy">>,
-           result = {privacy_item, '$order', '$action', '$type',
-                     '$value', '$kinds'},
+           result = {privacy_item, '$order', '$action', '$type', '$value',
+                    '$message', '$iq', '$presence_in', '$presence_out'},
            attrs = [#attr{name = <<"action">>,
                           required = true,
                           dec = {dec_enum, [[allow, deny]]},
                           dec = {dec_enum, [[group, jid, subscription]]},
                           enc = {enc_enum, []}},
                     #attr{name = <<"value">>}],
-           refs = [#ref{name = privacy_message,
-                        label = '$kinds'},
-                   #ref{name = privacy_iq,
-                        label = '$kinds'},
-                   #ref{name = privacy_presence_in,
-                        label = '$kinds'},
-                   #ref{name = privacy_presence_out,
-                        label = '$kinds'}]}).
+           refs = [#ref{name = privacy_message, default = false,
+                       min = 0, max = 1, label = '$message'},
+                   #ref{name = privacy_iq, default = false,
+                       min = 0, max = 1, label = '$iq'},
+                   #ref{name = privacy_presence_in, default = false,
+                       min = 0, max = 1, label = '$presence_in'},
+                   #ref{name = privacy_presence_out, default = false,
+                        min = 0, max = 1, label = '$presence_out'}]}).
 
 -xml(privacy_list,
      #elem{name = <<"list">>,
 -xml(privacy,
      #elem{name = <<"query">>,
            xmlns = <<"jabber:iq:privacy">>,
-           result = {privacy, '$lists', '$default', '$active'},
+           result = {privacy_query, '$lists', '$default', '$active'},
            refs = [#ref{name = privacy_list,
                         label = '$lists'},
                    #ref{name = privacy_default_list,
                      '$show', '$status', '$priority', '$error', '$_els'},
            attrs = [#attr{name = <<"id">>},
                     #attr{name = <<"type">>,
+                         default = available,
                           enc = {enc_enum, []},
                           dec = {dec_enum, [[unavailable, subscribe, subscribed,
                                              unsubscribe, unsubscribed,
-                                             probe, error]]}},
+                                             available, probe, error]]}},
                     #attr{name = <<"from">>,
                           dec = {dec_jid, []},
                           enc = {enc_jid, []}},
 -xml(error,
      #elem{name = <<"error">>,
            xmlns = <<"jabber:client">>,
-           result = {error, '$type', '$by', '$reason', '$text'},
+           result = {error, '$type', '$code', '$by', '$reason', '$text'},
            attrs = [#attr{name = <<"type">>,
                           label = '$type',
                           required = true,
                           dec = {dec_enum, [[auth, cancel, continue,
                                              modify, wait]]},
                           enc = {enc_enum, []}},
+                   #attr{name = <<"code">>,
+                         label = '$code',
+                         enc = {enc_int, []},
+                          dec = {dec_int, [0, infinity]}},
                     #attr{name = <<"by">>}],
            refs = [#ref{name = error_text,
                         min = 0, max = 1, label = '$text'},
                               min = 0, max = 1,
                               label = '$resource'}]}).
 
+-xml(legacy_auth_username,
+     #elem{name = <<"username">>,
+          xmlns = <<"jabber:iq:auth">>,
+          cdata = #cdata{default = none},
+          result = '$cdata'}).
+-xml(legacy_auth_password,
+     #elem{name = <<"password">>,
+          xmlns = <<"jabber:iq:auth">>,
+          cdata = #cdata{default = none},
+          result = '$cdata'}).
+-xml(legacy_auth_digest,
+     #elem{name = <<"digest">>,
+          xmlns = <<"jabber:iq:auth">>,
+          cdata = #cdata{default = none},
+          result = '$cdata'}).
+-xml(legacy_auth_resource,
+     #elem{name = <<"resource">>,
+          xmlns = <<"jabber:iq:auth">>,
+          cdata = #cdata{default = none},
+          result = '$cdata'}).
+
+-xml(legacy_auth,
+     #elem{name = <<"query">>,
+          xmlns = <<"jabber:iq:auth">>,
+          result = {legacy_auth, '$username', '$password',
+                    '$digest', '$resource'},
+          refs = [#ref{name = legacy_auth_username, min = 0, max = 1,
+                       label = '$username'},
+                  #ref{name = legacy_auth_password, min = 0, max = 1,
+                       label = '$password'},
+                  #ref{name = legacy_auth_digest, min = 0, max = 1,
+                       label = '$digest'},
+                  #ref{name = legacy_auth_resource, min = 0, max = 1,
+                       label = '$resource'}]}).
+
 -xml(sasl_auth,
      #elem{name = <<"auth">>,
            xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
      #elem{name = <<"not-authorized">>,
            result = 'not-authorized',
            xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}).
+-xml(sasl_failure_bad_protocol,
+     #elem{name = <<"bad-protocol">>,
+           result = 'bad-protocol',
+           xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}).
 -xml(sasl_failure_temporary_auth_failure,
      #elem{name = <<"temporary-auth-failure">>,
            result = 'temporary-auth-failure',
                         min = 0, max = 1, label = '$reason'},
                    #ref{name = sasl_failure_not_authorized,
                         min = 0, max = 1, label = '$reason'},
+                  #ref{name = sasl_failure_bad_protocol,
+                       min = 0, max = 1, label = '$reason'},
                    #ref{name = sasl_failure_temporary_auth_failure,
                         min = 0, max = 1, label = '$reason'}]}).
 
 -xml(caps,
      #elem{name = <<"c">>,
            xmlns = <<"http://jabber.org/protocol/caps">>,
-           result = {caps, '$hash', '$node', '$ver'},
+           result = {caps, '$node', '$version', '$hash', '$exts'},
            attrs = [#attr{name = <<"hash">>},
                     #attr{name = <<"node">>},
+                   #attr{name = <<"ext">>,
+                         label = '$exts',
+                         default = [],
+                         dec = {re, split, ["\\h+"]},
+                         enc = {join, [$ ]}},
                     #attr{name = <<"ver">>,
-                          enc = {base64, encode, []},
-                          dec = {base64, decode, []}}]}).
+                         label = '$version'}]}).
 
 -xml(feature_register,
      #elem{name = <<"register">>,
                    #ref{name = register_key, min = 0, max = 1,
                         label = '$key'}]}).
 
+-xml(session_optional,
+     #elem{name = <<"optional">>,
+          xmlns = <<"urn:ietf:params:xml:ns:xmpp-session">>,
+           result = true}).
+
 -xml(session,
      #elem{name = <<"session">>,
            xmlns = <<"urn:ietf:params:xml:ns:xmpp-session">>,
-           result = {session}}).
+           result = {xmpp_session, '$optional'},
+          refs = [#ref{name = session_optional,
+                       min = 0, max = 1, default = false,
+                       label = '$optional'}]}).
 
 -xml(ping,
      #elem{name = <<"ping">>,
 %%        refs = [#ref{name = vcard, min = 0, max = 1, label = '$vcard'},
 %%                #ref{name = vcard_EXTVAL, min = 0, max = 1, label = '$extval'}]}).
 
--xml(vcard,
+-xml(vcard_temp,
      #elem{name = <<"vCard">>,
            xmlns = <<"vcard-temp">>,
-           result = {vcard, '$version', '$fn', '$n', '$nickname', '$photo',
+           result = {vcard_temp, '$version', '$fn', '$n', '$nickname', '$photo',
                      '$bday', '$adr', '$label', '$tel', '$email', '$jabberid',
                      '$mailer', '$tz', '$geo', '$title', '$role', '$logo',
                      '$org', '$categories', '$note', '$prodid', %% '$agent',
           xmlns = <<"vcard-temp:x:update">>,
           result = '$cdata'}).
 
+-record(vcard_xupdate, {us :: {binary(), binary()},
+                       hash :: binary()}).
+-type vcard_xupdate() :: #vcard_xupdate{}.
+
 -xml(vcard_xupdate,
      #elem{name = <<"x">>,
           xmlns = <<"vcard-temp:x:update">>,
-          result = {vcard_xupdate, '$photo'},
+          result = {vcard_xupdate, undefined, '$hash'},
           refs = [#ref{name = vcard_xupdate_photo, min = 0, max = 1,
-                       label = '$photo'}]}).
+                       label = '$hash'}]}).
 
 -xml(xdata_field_required,
      #elem{name = <<"required">>,
            refs = [#ref{name = shim_header, label = '$headers'}]}).
 
 -record(chatstate, {type :: active | composing | gone | inactive | paused}).
+-type chatstate() :: #chatstate{}.
 
 -xml(chatstate_active,
      #elem{name = <<"active">>,
 -xml(delay,
      #elem{name = <<"delay">>,
            xmlns = <<"urn:xmpp:delay">>,
-           result = {delay, '$stamp', '$from'},
+           result = {delay, '$stamp', '$from', '$desc'},
+          cdata = #cdata{label = '$desc', default = <<"">>},
            attrs = [#attr{name = <<"stamp">>,
                           required = true,
                           dec = {dec_utc, []},
           attrs = [#attr{name = <<"xmlns">>}]}).
 
 -record(csi, {type :: active | inactive}).
+-type csi() :: #csi{}.
 
 -xml(csi_active,
      #elem{name = <<"active">>,
 
 -xml(mix_subscribe,
      #elem{name = <<"subscribe">>,
-           xmlns = <<"urn:xmpp:mix:0">>,
-           result = '$node',
-           attrs = [#attr{name = <<"node">>,
-                          required = true,
-                          label = '$node'}]}).
+          xmlns = <<"urn:xmpp:mix:0">>,
+          result = '$node',
+          attrs = [#attr{name = <<"node">>,
+                         required = true,
+                         label = '$node'}]}).
 
 -xml(mix_join,
      #elem{name = <<"join">>,
-           xmlns = <<"urn:xmpp:mix:0">>,
-           result = {mix_join, '$jid', '$subscribe'},
-           attrs = [#attr{name = <<"jid">>,
-                          label = '$jid',
-                          dec = {dec_jid, []},
+          xmlns = <<"urn:xmpp:mix:0">>,
+          result = {mix_join, '$jid', '$subscribe'},
+          attrs = [#attr{name = <<"jid">>,
+                         label = '$jid',
+                         dec = {dec_jid, []},
                           enc = {enc_jid, []}}],
-           refs = [#ref{name = mix_subscribe, min = 0, label = '$subscribe'}]}).
+          refs = [#ref{name = mix_subscribe, min = 0, label = '$subscribe'}]}).
 
 -xml(mix_leave,
      #elem{name = <<"leave">>,
-           xmlns = <<"urn:xmpp:mix:0">>,
-           result = {mix_leave}}).
+          xmlns = <<"urn:xmpp:mix:0">>,
+          result = {mix_leave}}).
 
 -xml(mix_participant,
      #elem{name = <<"participant">>,
-           xmlns = <<"urn:xmpp:mix:0">>,
-           result = {mix_participant, '$jid', '$nick'},
-           attrs = [#attr{name = <<"jid">>,
-                          required = true,
-                          label = '$jid',
-                          dec = {dec_jid, []},
+          xmlns = <<"urn:xmpp:mix:0">>,
+          result = {mix_participant, '$jid', '$nick'},
+          attrs = [#attr{name = <<"jid">>,
+                         required = true,
+                         label = '$jid',
+                         dec = {dec_jid, []},
                           enc = {enc_jid, []}},
-                    #attr{name = <<"nick">>,
-                          label = '$nick'}]}).
+                   #attr{name = <<"nick">>,
+                         label = '$nick'}]}).
+
+-record(hint, {type :: 'no-copy' | 'no-store' | 'store' | 'no-permanent-store'}).
+-type hint() :: #hint{}.
+
+-xml(hint_no_copy,
+     #elem{name = <<"no-copy">>,
+          xmlns = <<"urn:xmpp:hints">>,
+          result = {hint, 'no-copy'}}).
+
+-xml(hint_no_store,
+     #elem{name = <<"no-store">>,
+          xmlns = <<"urn:xmpp:hints">>,
+          result = {hint, 'no-store'}}).
+
+-xml(hint_store,
+     #elem{name = <<"store">>,
+          xmlns = <<"urn:xmpp:hints">>,
+          result = {hint, 'store'}}).
+
+-xml(hint_no_permanent_store,
+     #elem{name = <<"no-permanent-store">>,
+          xmlns = <<"urn:xmpp:hints">>,
+          result = {hint, 'no-permanent-store'}}).
+
+-xml(search_instructions,
+     #elem{name = <<"instructions">>,
+           xmlns = <<"jabber:iq:search">>,
+           result = '$cdata'}).
+
+-xml(search_first,
+     #elem{name = <<"first">>,
+          xmlns = <<"jabber:iq:search">>,
+          cdata = #cdata{default = <<"">>},
+           result = '$cdata'}).
+-xml(search_last,
+     #elem{name = <<"last">>,
+           xmlns = <<"jabber:iq:search">>,
+           cdata = #cdata{default = <<"">>},
+           result = '$cdata'}).
+-xml(search_nick,
+     #elem{name = <<"nick">>,
+           xmlns = <<"jabber:iq:search">>,
+           cdata = #cdata{default = <<"">>},
+           result = '$cdata'}).
+-xml(search_email,
+     #elem{name = <<"email">>,
+           xmlns = <<"jabber:iq:search">>,
+           cdata = #cdata{default = <<"">>},
+           result = '$cdata'}).
+
+-xml(search_item,
+     #elem{name = <<"item">>,
+          xmlns = <<"jabber:iq:search">>,
+          result = {search_item, '$jid', '$first', '$last', '$nick', '$email'},
+          attrs = [#attr{name = <<"jid">>,
+                         required = true,
+                         enc = {enc_jid, []},
+                         dec = {dec_jid, []}}],
+          refs = [#ref{name = search_first, min = 0, max = 1,
+                       label = '$first'},
+                  #ref{name = search_last, min = 0, max = 1,
+                       label = '$last'},
+                  #ref{name = search_nick, min = 0, max = 1,
+                       label = '$nick'},
+                  #ref{name = search_email, min = 0, max = 1,
+                       label = '$email'}]}).
+
+-xml(search,
+     #elem{name = <<"query">>,
+          xmlns = <<"jabber:iq:search">>,
+          result = {search, '$instructions', '$first', '$last',
+                    '$nick', '$email', '$items', '$xdata'},
+          refs = [#ref{name = search_instructions, min = 0, max = 1,
+                        label = '$instructions'},
+                  #ref{name = search_first, min = 0, max = 1,
+                       label = '$first'},
+                  #ref{name = search_last, min = 0, max = 1,
+                       label = '$last'},
+                  #ref{name = search_nick, min = 0, max = 1,
+                       label = '$nick'},
+                  #ref{name = search_email, min = 0, max = 1,
+                       label = '$email'},
+                  #ref{name = search_item, label = '$items'},
+                  #ref{name = xdata, min = 0, max = 1,
+                       label = '$xdata'}]}).
 
 dec_tzo(Val) ->
     [H1, M1] = str:tokens(Val, <<":">>),
@@ -2514,6 +2670,10 @@ dec_bool(<<"1">>) -> true.
 enc_bool(false) -> <<"false">>;
 enc_bool(true) -> <<"true">>.
 
+join([], _Sep) -> <<>>;
+join([H | T], Sep) ->
+    <<H/binary, (<< <<Sep, X/binary>> || X <- T >>)/binary>>.
+
 %% Local Variables:
 %% mode: erlang
 %% End: