diff --git a/Makefile.in b/Makefile.in index eb1474926..07502f06e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 index 000000000..965985c31 --- /dev/null +++ b/include/jid.hrl @@ -0,0 +1,17 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 10 Jul 2016 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-record(jid, {user = <<"">> :: binary(), + server = <<"">> :: binary(), + resource = <<"">> :: binary(), + luser = <<"">> :: binary(), + lserver = <<"">> :: binary(), + lresource = <<"">> :: binary()}). + +-type(jid() :: #jid{}). +-type(ljid() :: {binary(), binary(), binary()}). diff --git a/include/mod_privacy.hrl b/include/mod_privacy.hrl index 8fe5abcca..0d263d659 100644 --- a/include/mod_privacy.hrl +++ b/include/mod_privacy.hrl @@ -22,9 +22,11 @@ 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 index 000000000..e1bdaeed0 --- /dev/null +++ b/include/xmpp.hrl @@ -0,0 +1,29 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2015, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 10 Dec 2015 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-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))). diff --git a/tools/xmpp_codec.hrl b/include/xmpp_codec.hrl similarity index 55% rename from tools/xmpp_codec.hrl rename to include/xmpp_codec.hrl index 6d4b750b6..64a185a30 100644 --- a/tools/xmpp_codec.hrl +++ b/include/xmpp_codec.hrl @@ -1,179 +1,249 @@ %% 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(), @@ -182,42 +252,57 @@ 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(), @@ -225,25 +310,33 @@ 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', @@ -252,17 +345,24 @@ 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{}, @@ -270,10 +370,10 @@ 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(), @@ -281,9 +381,11 @@ 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(), @@ -292,11 +394,13 @@ 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(), @@ -312,40 +416,52 @@ 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(), @@ -355,6 +471,7 @@ intl = false :: boolean(), pref = false :: boolean(), line = [] :: [binary()]}). +-type vcard_label() :: #vcard_label{}. -record(vcard_adr, {home = false :: boolean(), work = false :: boolean(), @@ -370,6 +487,14 @@ 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()], @@ -377,6 +502,16 @@ 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(), @@ -385,14 +520,17 @@ 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{}], @@ -402,6 +540,7 @@ options :: #pubsub_options{}, items :: #pubsub_items{}, retract :: #pubsub_retract{}}). +-type pubsub() :: #pubsub{}. -record(register, {registered = false :: boolean(), remove = false :: boolean(), @@ -424,32 +563,40 @@ 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(), @@ -458,6 +605,7 @@ priority :: integer(), error :: #error{}, sub_els = [] :: [any()]}). +-type presence() :: #presence{}. -record(message, {id :: binary(), type = normal :: 'chat' | 'error' | 'groupchat' | 'headline' | 'normal', @@ -469,6 +617,7 @@ thread :: binary(), error :: #error{}, sub_els = [] :: [any()]}). +-type message() :: #message{}. -record(iq, {id :: binary(), type :: 'error' | 'get' | 'result' | 'set', @@ -477,61 +626,203 @@ 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()}). +-type vcard_logo() :: #vcard_logo{}. --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()}). +-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(). diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index a101e1380..46b23384e 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -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, diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index 0d408fc48..150aa854c 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -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), "", []). diff --git a/src/cyrsasl_oauth.erl b/src/cyrsasl_oauth.erl index 16f1e3dfb..09d143ef5 100644 --- a/src/cyrsasl_oauth.erl +++ b/src/cyrsasl_oauth.erl @@ -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) -> diff --git a/src/cyrsasl_plain.erl b/src/cyrsasl_plain.erl index 82d68f87f..8e9b32b99 100644 --- a/src/cyrsasl_plain.erl +++ b/src/cyrsasl_plain.erl @@ -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) -> diff --git a/src/cyrsasl_scram.erl b/src/cyrsasl_scram.erl index 18f52b48f..8643a8924 100644 --- a/src/cyrsasl_scram.erl +++ b/src/cyrsasl_scram.erl @@ -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(<<"">>) -> <<"">>; diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 9ddb8511d..8d217a354 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -67,7 +67,8 @@ -include("ejabberd.hrl"). -include("logger.hrl"). --include("jlib.hrl"). +-include("xmpp.hrl"). +%%-include("legacy.hrl"). -include("mod_privacy.hrl"). @@ -117,6 +118,16 @@ 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). @@ -143,55 +154,13 @@ -define(STREAM_TRAILER, <<"">>). --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), - fsm_next_state(wait_for_auth, StateData); - {auth, _ID, set, {_U, _P, _D, <<"">>}} -> - Lang = StateData#state.lang, - Txt = <<"No resource provided">>, - Err = jlib:make_error_reply(El, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)), +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, 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), + 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 = <<"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) 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}. + {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, #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) +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) +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, - 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 - 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, El}]), - fsm_next_state(session_established, NewState). + [{xmlstreamelement, Pkt}]), + fsm_next_state(session_established, NewState); +session_established2(Pkt, StateData) -> + ejabberd_hooks:run(c2s_loop_debug, + [{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]). +get_statustag(#presence{status = [#text{data = Status}|_]}) -> Status; +get_statustag(_) -> <<"">>. -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. +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 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 diff --git a/src/ejabberd_frontend_socket.erl b/src/ejabberd_frontend_socket.erl index b8e706f23..ab5b6a701 100644 --- a/src/ejabberd_frontend_socket.erl +++ b/src/ejabberd_frontend_socket.erl @@ -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}; diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 2ba943693..dca456427 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -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 -> diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index e29d6acfb..5924d92c0 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -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)) diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 8d94bc6aa..ec9ef43c6 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -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"). @@ -98,6 +99,15 @@ %% 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(). diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index 887b4a0f3..aa916867a 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -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). diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index 3f6c05667..ae7cb2d88 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -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( diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index c2b4252c9..f78ba7e40 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -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(). diff --git a/src/jid.erl b/src/jid.erl index 0c3ac77c0..d81cbcefd 100644 --- a/src/jid.erl +++ b/src/jid.erl @@ -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), diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 3ed3149bb..7c7ebf7b3 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -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, @@ -54,24 +56,12 @@ -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(). +-spec read_caps(#presence{}) -> nothing | caps(). +read_caps(Presence) -> + case xmpp:get_subtag(Presence, #caps{}) of + false -> nothing; + Caps -> Caps + end. -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. - -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">>, - <>}], - children = []}]}, + IQ = #iq{type = get, + sub_els = [#disco_info{node = <>}]}, 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_features(#disco_info{features = Features}) -> + lists:usort([[Feat, $<] || Feat <- Features]). -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_identities(#disco_info{identities = Identities}) -> + lists:sort( + [[Cat, $/, T, $/, Lang, $/, Name, $<] || + #identity{category = Cat, type = T, + lang = Lang, name = Name} <- Identities]). -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_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|_] -> diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index de8d8e1a7..b70ccbc2a 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -36,37 +36,28 @@ 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 or 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 +-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}. + Msg#message{from = From}; +complete_packet(_From, Msg, _Direction) -> + Msg. -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">>) =/= <<"">>. +-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), diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 036175cce..a6a6ddc20 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -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. +-spec get_pep_node(message()) -> binary() | undefined. -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 +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. diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 2e7b80c18..03fdab209 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -32,10 +32,10 @@ -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">>, - <>}, - {<<"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) -> []. diff --git a/src/mod_echo.erl b/src/mod_echo.erl index ee904d798..fe4b8d90d 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -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) -> []. diff --git a/src/mod_last.erl b/src/mod_last.erl index ce9148841..b267aa89b 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -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; diff --git a/src/mod_ping.erl b/src/mod_ping.erl index d1b3f9322..b09ca9ab2 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -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 -> diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 18ff78371..e88c1fb5b 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -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, @@ -41,15 +41,15 @@ -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 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)). +-spec item_to_xml(listitem()) -> xmlel(). +item_to_xml(ListItem) -> + xmpp:encode(encode_list_item(ListItem)). -type_to_list(Type) -> +-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. + +-spec encode_value(listitem_type(), listitem_value()) -> undefined | binary(). +encode_value(Type, Val) -> case Type of - jid -> <<"jid">>; - group -> <<"group">>; - subscription -> <<"subscription">> + jid -> jid:to_string(Val); + group -> Val; + subscription -> + case Val of + both -> <<"both">>; + to -> <<"to">>; + from -> <<"from">>; + none -> <<"none">> + end; + none -> undefined end. -value_to_list(Type, Val) -> +-spec decode_value(jid | subscription | group | undefined, binary()) -> + listitem_value(). +decode_value(Type, Value) -> 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:from_string(Value); + subscription -> + case Value of + <<"from">> -> from; + <<"to">> -> to; + <<"both">> -> both; + <<"none">> -> none + end; + group -> Value; + undefined -> none end. -list_to_action(S) -> - case S of - <<"allow">> -> allow; - <<"deny">> -> deny - 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: " + ", or ">>, + {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}. +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. -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 +-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; diff --git a/src/mod_privacy_mnesia.erl b/src/mod_privacy_mnesia.erl index 4026b7f64..1a9172b5a 100644 --- a/src/mod_privacy_mnesia.erl +++ b/src/mod_privacy_mnesia.erl @@ -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) -> diff --git a/src/mod_privacy_riak.erl b/src/mod_privacy_riak.erl index 0c43e74f9..40e92005c 100644 --- a/src/mod_privacy_riak.erl +++ b/src/mod_privacy_riak.erl @@ -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) -> diff --git a/src/mod_privacy_sql.erl b/src/mod_privacy_sql.erl index 6da917e9d..66926f236 100644 --- a/src/mod_privacy_sql.erl +++ b/src/mod_privacy_sql.erl @@ -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 diff --git a/src/mod_private.erl b/src/mod_private.erl index f0e4632f6..28d49bb3f 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -31,14 +31,14 @@ -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(). @@ -46,10 +46,7 @@ -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)]}. + xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang)). -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). +-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). diff --git a/src/mod_roster.erl b/src/mod_roster.erl index a75041bc7..58dc51983 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -41,12 +41,12 @@ -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,144 +295,83 @@ 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 = []}. + Items), + xmpp:make_iq_result(IQ). -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 +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_set(_From, _To, _, _Managed) -> ok. -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 - end; -process_item_els(Item, [{xmlcdata, _} | Els]) -> - process_item_els(Item, Els); -process_item_els(Item, []) -> Item. - push_item(User, Server, From, Item) -> ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), jid:make(User, Server, <<"">>), @@ -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; diff --git a/src/mod_time.erl b/src/mod_time.erl index 90296f3d8..0aeb6831c 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -32,13 +32,13 @@ -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, - <>}]}]}]} - 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) -> []. diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index aca9d7462..de9fce00d 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -33,13 +33,15 @@ -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">>}]}]}]} +-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 = <>, + 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. -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 - 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 = <>}). +-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 = []}). +-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}. --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">>)]}]). +-spec mk_field(binary(), binary()) -> xdata_field(). +mk_field(Var, Val) -> + #xdata_field{var = Var, values = [Val]}. -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. +-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}. -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 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">>, - <>), - ?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">>, <>), + 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">>, <>), - ?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))]}. + [mk_field(<<"jid">>, <>), + 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))]. -search(LServer, Data) -> +-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, diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index f2101df91..27ea8461a 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -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), diff --git a/src/mod_version.erl b/src/mod_version.erl index 8a035763f..80b22554d 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -31,13 +31,13 @@ -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 = <>, - #xmlel{name = <<"os">>, attrs = [], - children = [{xmlcdata, OS}]}. + <>. depends(_Host, _Opts) -> []. diff --git a/src/translate.erl b/src/translate.erl index e9f61ab8c..c8a924585 100644 --- a/src/translate.erl +++ b/src/translate.erl @@ -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 index 000000000..ca6ed5e4c --- /dev/null +++ b/src/xmpp.erl @@ -0,0 +1,712 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2015, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 9 Dec 2015 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-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. diff --git a/tools/xmpp_codec.erl b/src/xmpp_codec.erl similarity index 68% rename from tools/xmpp_codec.erl rename to src/xmpp_codec.erl index ef1421962..568c5fbc7 100644 --- a/tools/xmpp_codec.erl +++ b/src/xmpp_codec.erl @@ -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) -> + <> || 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, + <>); +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, + <>); +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, + <>); +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, + <>); +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, <>); +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,311 +3832,289 @@ 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) + 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) -> @@ -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, + <>); +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,33 +9250,52 @@ 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) + 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) -> @@ -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) +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_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) +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_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) +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_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) +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_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) +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_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) +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_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) +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_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) +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_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) +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_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) +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_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) +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_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, <<"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) + 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_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) +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_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) +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_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) +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_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, +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) + 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_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) +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_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). +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({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, - [])))))))))))))))))))))))))))))), +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,13 +16259,56 @@ 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}. -encode_session({session}, _xmlns_attrs) -> - _els = [], +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_$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, <<"optional">>, _attrs, _els}. + decode_register(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -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, Ver) -> - decode_caps_attrs(__TopXMLNS, _attrs, Hash, _val, Ver); + [{<<"node">>, _val} | _attrs], Hash, _Node, Exts, + Version) -> + decode_caps_attrs(__TopXMLNS, _attrs, Hash, _val, Exts, + Version); decode_caps_attrs(__TopXMLNS, - [{<<"ver">>, _val} | _attrs], Hash, Node, _Ver) -> - decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, _val); + [{<<"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, 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, @@ -16566,6 +19018,253 @@ 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, <>); +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, <>); +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, <>); +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, <>); +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_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}) -> {Jid, Resource} = decode_bind_els(__TopXMLNS, @@ -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, - [{<<"by">>, _val} | _attrs], Type, _By) -> - decode_error_attrs(__TopXMLNS, _attrs, Type, _val); -decode_error_attrs(__TopXMLNS, [_ | _attrs], Type, + [{<<"code">>, _val} | _attrs], Type, _Code, By) -> + decode_error_attrs(__TopXMLNS, _attrs, Type, _val, By); +decode_error_attrs(__TopXMLNS, + [{<<"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}. -decode_roster_els(__TopXMLNS, __IgnoreEls, [], Items) -> +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_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) +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_els(__TopXMLNS, __IgnoreEls, [_ | _els], - Items) -> - decode_roster_els(__TopXMLNS, __IgnoreEls, _els, Items). +decode_roster_query_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Items) -> + decode_roster_query_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). +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({roster, Items, Ver}, _xmlns_attrs) -> - _els = lists:reverse('encode_roster_$items'(Items, [])), - _attrs = encode_roster_attr_ver(Ver, _xmlns_attrs), +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, - <>); + <>); 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 index 000000000..42b251fc1 --- /dev/null +++ b/src/xmpp_util.erl @@ -0,0 +1,81 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 12 Jul 2016 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-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 = <>, + 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 +%%%=================================================================== diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index acf9c3bb7..07d3a3dfd 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -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, []}, @@ -64,29 +65,34 @@ 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]]}, @@ -99,14 +105,14 @@ 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">>, @@ -134,7 +140,7 @@ -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, @@ -396,10 +402,11 @@ '$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, []}}, @@ -516,13 +523,17 @@ -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'}, @@ -595,6 +606,41 @@ 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">>, @@ -682,6 +728,10 @@ #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', @@ -713,6 +763,8 @@ 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'}]}). @@ -827,12 +879,16 @@ -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">>, @@ -988,10 +1044,18 @@ #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">>, @@ -1444,10 +1508,10 @@ %% 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', @@ -1491,12 +1555,16 @@ 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">>, @@ -1770,6 +1838,7 @@ refs = [#ref{name = shim_header, label = '$headers'}]}). -record(chatstate, {type :: active | composing | gone | inactive | paused}). +-type chatstate() :: #chatstate{}. -xml(chatstate_active, #elem{name = <<"active">>, @@ -1799,7 +1868,8 @@ -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, []}, @@ -2263,6 +2333,7 @@ attrs = [#attr{name = <<"xmlns">>}]}). -record(csi, {type :: active | inactive}). +-type csi() :: #csi{}. -xml(csi_active, #elem{name = <<"active">>, @@ -2432,38 +2503,123 @@ -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) -> + <> || X <- T >>)/binary>>. + %% Local Variables: %% mode: erlang %% End: