From b31ebd2ea012ba2a81ec095189f46974e1905929 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 28 Jul 2016 15:10:41 +0300 Subject: [PATCH] Rewrite captcha to use XML generator --- include/xmpp_codec.hrl | 42 +- src/ejabberd_captcha.erl | 259 ++++-------- src/mod_muc_room.erl | 5 +- src/mod_register.erl | 4 +- src/mod_register_web.erl | 4 +- src/xmpp_codec.erl | 845 +++++++++++++++++++++++++++++++-------- tools/xmpp_codec.spec | 64 ++- 7 files changed, 862 insertions(+), 361 deletions(-) diff --git a/include/xmpp_codec.hrl b/include/xmpp_codec.hrl index 43bb6b098..1ede0ff1d 100644 --- a/include/xmpp_codec.hrl +++ b/include/xmpp_codec.hrl @@ -294,6 +294,12 @@ type :: 'none' | 'pending' | 'subscribed' | 'unconfigured'}). -type pubsub_subscription() :: #pubsub_subscription{}. +-record(bob_data, {cid :: binary(), + 'max-age' :: non_neg_integer(), + type :: binary(), + data = <<>> :: any()}). +-type bob_data() :: #bob_data{}. + -record(muc_item, {actor :: #muc_actor{}, continue :: binary(), reason = <<>> :: 'undefined' | binary(), @@ -404,7 +410,8 @@ required = false :: boolean(), desc :: binary(), values = [] :: [binary()], - options = [] :: [#xdata_option{}]}). + options = [] :: [#xdata_option{}], + sub_els = [] :: [any()]}). -type xdata_field() :: #xdata_field{}. -record(version, {name :: binary(), @@ -482,6 +489,15 @@ number :: binary()}). -type vcard_tel() :: #vcard_tel{}. +-record(media_uri, {type :: binary(), + uri = <<>> :: binary()}). +-type media_uri() :: #media_uri{}. + +-record(media, {height :: non_neg_integer(), + width :: non_neg_integer(), + uri = [] :: [#media_uri{}]}). +-type media() :: #media{}. + -record(muc_destroy, {xmlns :: binary(), jid :: any(), reason = <<>> :: 'undefined' | binary(), @@ -531,6 +547,11 @@ url = [] :: [#bookmark_url{}]}). -type bookmark_storage() :: #bookmark_storage{}. +-record(oob_x, {url :: binary(), + desc = <<>> :: binary(), + sid = <<>> :: binary()}). +-type oob_x() :: #oob_x{}. + -record(vcard_sound, {phonetic :: binary(), binval :: any(), extval :: binary()}). @@ -582,6 +603,9 @@ fields = [] :: [#xdata_field{}]}). -type xdata() :: #xdata{}. +-record(xcaptcha, {xdata :: #xdata{}}). +-type xcaptcha() :: #xcaptcha{}. + -record(adhoc_command, {node :: binary(), action = execute :: 'cancel' | 'complete' | 'execute' | 'next' | 'prev', sid :: binary(), @@ -647,7 +671,8 @@ misc :: 'none' | binary(), text :: 'none' | binary(), key :: 'none' | binary(), - xdata :: #xdata{}}). + xdata :: #xdata{}, + sub_els = [] :: [any()]}). -type register() :: #register{}. -record(disco_info, {node :: binary(), @@ -807,6 +832,8 @@ version() | pubsub_affiliation() | mam_fin() | + bob_data() | + media() | sm_a() | carbons_sent() | mam_archived() | @@ -880,11 +907,8 @@ sasl_failure() | bookmark_storage() | muc_decline() | - sasl_auth() | - p1_push() | legacy_auth() | search() | - pubsub_publish() | unblock() | nick() | p1_ack() | @@ -892,6 +916,7 @@ mix_join() | xmpp_session() | xdata() | + xcaptcha() | iq() | streamhost() | bind() | @@ -917,6 +942,7 @@ starttls() | mam_prefs() | sasl_mechanisms() | + media_uri() | muc_destroy() | vcard_key() | csi() | @@ -949,4 +975,8 @@ expire() | muc_unsubscribe() | pubsub_unsubscribe() | - chatstate(). + chatstate() | + sasl_auth() | + p1_push() | + oob_x() | + pubsub_publish(). diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 157700c47..df74a68b1 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -41,31 +41,17 @@ -export([create_captcha/6, build_captcha_html/2, check_captcha/2, process_reply/1, process/2, is_feature_available/0, create_captcha_x/5, - create_captcha_x/6, opt_type/1]). - --include("jlib.hrl"). + opt_type/1]). +-include("xmpp.hrl"). -include("ejabberd.hrl"). -include("logger.hrl"). - -include("ejabberd_http.hrl"). --define(VFIELD(Type, Var, Value), - #xmlel{name = <<"field">>, - attrs = [{<<"type">>, Type}, {<<"var">>, Var}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = [Value]}]}). - --define(CAPTCHA_TEXT(Lang), - translate:translate(Lang, - <<"Enter the text you see">>)). - -define(CAPTCHA_LIFETIME, 120000). - -define(LIMIT_PERIOD, 60*1000*1000). --type error() :: efbig | enodata | limit | malformed_image | timeout. +-type image_error() :: efbig | enodata | limit | malformed_image | timeout. -record(state, {limits = treap:empty() :: treap:treap()}). @@ -79,188 +65,82 @@ start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). +-spec captcha_text(undefined | binary()) -> binary(). +captcha_text(Lang) -> + translate:translate(Lang, <<"Enter the text you see">>). + +-spec mk_ocr_field(binary() | undefined, binary(), binary()) -> xdata_field(). +mk_ocr_field(Lang, CID, Type) -> + URI = #media_uri{type = Type, uri = <<"cid:", CID/binary>>}, + #xdata_field{var = <<"ocr">>, + label = captcha_text(Lang), + required = true, + sub_els = [#media{uri = [URI]}]}. + +mk_field(Type, Var, Value) -> + #xdata_field{type = Type, var = Var, values = [Value]}. + -spec create_captcha(binary(), jid(), jid(), - binary(), any(), any()) -> {error, error()} | - {ok, binary(), [xmlel()]}. + binary(), any(), any()) -> {error, image_error()} | + {ok, binary(), [text()], [xmlel()]}. create_captcha(SID, From, To, Lang, Limiter, Args) -> case create_image(Limiter) of {ok, Type, Key, Image} -> Id = <<(randoms:get_string())/binary>>, - B64Image = jlib:encode_base64((Image)), JID = jid:to_string(From), - CID = <<"sha1+", (p1_sha:sha(Image))/binary, - "@bob.xmpp.org">>, - Data = #xmlel{name = <<"data">>, - attrs = - [{<<"xmlns">>, ?NS_BOB}, {<<"cid">>, CID}, - {<<"max-age">>, <<"0">>}, {<<"type">>, Type}], - children = [{xmlcdata, B64Image}]}, - Captcha = #xmlel{name = <<"captcha">>, - attrs = [{<<"xmlns">>, ?NS_CAPTCHA}], - children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - [?VFIELD(<<"hidden">>, - <<"FORM_TYPE">>, - {xmlcdata, ?NS_CAPTCHA}), - ?VFIELD(<<"hidden">>, <<"from">>, - {xmlcdata, - jid:to_string(To)}), - ?VFIELD(<<"hidden">>, - <<"challenge">>, - {xmlcdata, Id}), - ?VFIELD(<<"hidden">>, <<"sid">>, - {xmlcdata, SID}), - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"ocr">>}, - {<<"label">>, - ?CAPTCHA_TEXT(Lang)}], - children = - [#xmlel{name = - <<"required">>, - attrs = [], - children = []}, - #xmlel{name = - <<"media">>, - attrs = - [{<<"xmlns">>, - ?NS_MEDIA}], - children = - [#xmlel{name - = - <<"uri">>, - attrs - = - [{<<"type">>, - Type}], - children - = - [{xmlcdata, - <<"cid:", - CID/binary>>}]}]}]}]}]}, + CID = <<"sha1+", (p1_sha:sha(Image))/binary, "@bob.xmpp.org">>, + Data = #bob_data{cid = CID, 'max-age' = 0, type = Type, + data = Image}, + Fs = [mk_field(hidden, <<"FORM_TYPE">>, ?NS_CAPTCHA), + mk_field(hidden, <<"from">>, jid:to_string(To)), + mk_field(hidden, <<"challenge">>, Id), + mk_field(hidden, <<"sid">>, SID), + mk_ocr_field(Lang, CID, Type)], + X = #xdata{type = form, fields = Fs}, + Captcha = #xcaptcha{xdata = X}, BodyString1 = translate:translate(Lang, <<"Your messages to ~s are being blocked. " "To unblock them, visit ~s">>), BodyString = iolist_to_binary(io_lib:format(BodyString1, [JID, get_url(Id)])), - Body = #xmlel{name = <<"body">>, attrs = [], - children = [{xmlcdata, BodyString}]}, - OOB = #xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, ?NS_OOB}], - children = - [#xmlel{name = <<"url">>, attrs = [], - children = [{xmlcdata, get_url(Id)}]}]}, + Body = xmpp:mk_text(BodyString, Lang), + OOB = #oob_x{url = get_url(Id)}, Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}), ets:insert(captcha, #captcha{id = Id, pid = self(), key = Key, tref = Tref, args = Args}), - {ok, Id, [Body, OOB, Captcha, Data]}; + {ok, Id, Body, [OOB, Captcha, Data]}; Err -> Err end. --spec create_captcha_x(binary(), jid(), binary(), - any(), [xmlel()]) -> {ok, [xmlel()]} | - {error, error()}. +-spec create_captcha_x(binary(), jid(), binary(), any(), xdata()) -> + {ok, xdata()} | {error, image_error()}. -create_captcha_x(SID, To, Lang, Limiter, HeadEls) -> - create_captcha_x(SID, To, Lang, Limiter, HeadEls, []). - --spec create_captcha_x(binary(), jid(), binary(), - any(), [xmlel()], [xmlel()]) -> {ok, [xmlel()]} | - {error, error()}. - -create_captcha_x(SID, To, Lang, Limiter, HeadEls, - TailEls) -> +create_captcha_x(SID, To, Lang, Limiter, #xdata{fields = Fs} = X) -> case create_image(Limiter) of {ok, Type, Key, Image} -> Id = <<(randoms:get_string())/binary>>, - B64Image = jlib:encode_base64((Image)), - CID = <<"sha1+", (p1_sha:sha(Image))/binary, - "@bob.xmpp.org">>, - Data = #xmlel{name = <<"data">>, - attrs = - [{<<"xmlns">>, ?NS_BOB}, {<<"cid">>, CID}, - {<<"max-age">>, <<"0">>}, {<<"type">>, Type}], - children = [{xmlcdata, B64Image}]}, + CID = <<"sha1+", (p1_sha:sha(Image))/binary, "@bob.xmpp.org">>, + Data = #bob_data{cid = CID, 'max-age' = 0, type = Type, data = Image}, HelpTxt = translate:translate(Lang, <<"If you don't see the CAPTCHA image here, " "visit the web page.">>), Imageurl = get_url(<>), - Captcha = #xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - [?VFIELD(<<"hidden">>, <<"FORM_TYPE">>, - {xmlcdata, ?NS_CAPTCHA}) - | HeadEls] - ++ - [#xmlel{name = <<"field">>, - attrs = [{<<"type">>, <<"fixed">>}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - HelpTxt}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"hidden">>}, - {<<"var">>, <<"captchahidden">>}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - <<"workaround-for-psi">>}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"text-single">>}, - {<<"label">>, - translate:translate(Lang, - <<"CAPTCHA web page">>)}, - {<<"var">>, <<"url">>}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - Imageurl}]}]}, - ?VFIELD(<<"hidden">>, <<"from">>, - {xmlcdata, jid:to_string(To)}), - ?VFIELD(<<"hidden">>, <<"challenge">>, - {xmlcdata, Id}), - ?VFIELD(<<"hidden">>, <<"sid">>, - {xmlcdata, SID}), - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"ocr">>}, - {<<"label">>, - ?CAPTCHA_TEXT(Lang)}], - children = - [#xmlel{name = <<"required">>, - attrs = [], children = []}, - #xmlel{name = <<"media">>, - attrs = - [{<<"xmlns">>, - ?NS_MEDIA}], - children = - [#xmlel{name = - <<"uri">>, - attrs = - [{<<"type">>, - Type}], - children = - [{xmlcdata, - <<"cid:", - CID/binary>>}]}]}]}] - ++ TailEls}, + NewFs = [mk_field(hidden, <<"FORM_TYPE">>, ?NS_CAPTCHA)|Fs] ++ + [#xdata_field{type = fixed, values = [HelpTxt]}, + #xdata_field{type = hidden, var = <<"captchahidden">>, + values = [<<"workaround-for-psi">>]}, + #xdata_field{type = 'text-single', var = <<"url">>, + label = translate:translate( + Lang, <<"CAPTCHA web page">>), + values = [Imageurl]}, + mk_field(hidden, <<"from">>, jid:to_string(To)), + mk_field(hidden, <<"challenge">>, Id), + mk_field(hidden, <<"sid">>, SID), + mk_ocr_field(Lang, CID, Type)], + Captcha = X#xdata{type = form, fields = NewFs}, Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}), ets:insert(captcha, @@ -281,7 +161,7 @@ build_captcha_html(Id, Lang) -> attrs = [{<<"src">>, get_url(<>)}], children = []}, - TextEl = {xmlcdata, ?CAPTCHA_TEXT(Lang)}, + TextEl = {xmlcdata, captcha_text(Lang)}, IdEl = #xmlel{name = <<"input">>, attrs = [{<<"type">>, <<"hidden">>}, {<<"name">>, <<"id">>}, @@ -317,27 +197,24 @@ build_captcha_html(Id, Lang) -> _ -> captcha_not_found end. --spec process_reply(xmlel()) -> ok | {error, bad_match | not_found | malformed}. +-spec process_reply(xmpp_element()) -> ok | {error, bad_match | not_found | malformed}. -process_reply(#xmlel{} = El) -> - case fxml:get_subtag(El, <<"x">>) of - false -> {error, malformed}; - Xdata -> - Fields = jlib:parse_xdata_submit(Xdata), - case catch {proplists:get_value(<<"challenge">>, - Fields), - proplists:get_value(<<"ocr">>, Fields)} - of - {[Id | _], [OCR | _]} -> - case check_captcha(Id, OCR) of - captcha_valid -> ok; - captcha_non_valid -> {error, bad_match}; - captcha_not_found -> {error, not_found} - end; - _ -> {error, malformed} - end +process_reply(#xdata{} = X) -> + case {xmpp_util:get_xdata_values(<<"challenge">>, X), + xmpp_util:get_xdata_values(<<"ocr">>, X)} of + {[Id], [OCR]} -> + case check_captcha(Id, OCR) of + captcha_valid -> ok; + captcha_non_valid -> {error, bad_match}; + captcha_not_found -> {error, not_found} + end; + _ -> + {error, malformed} end; -process_reply(_) -> {error, malformed}. +process_reply(#xcaptcha{xdata = #xdata{} = X}) -> + process_reply(X); +process_reply(_) -> + {error, malformed}. process(_Handlers, #request{method = 'GET', lang = Lang, diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 29b7942cf..a539ab848 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1824,8 +1824,9 @@ add_new_user(From, Nick, Packet, StateData) -> case ejabberd_captcha:create_captcha(SID, RoomJID, To, Lang, Limiter, From) of - {ok, ID, CaptchaEls} -> - MsgPkt = #message{id = ID, sub_els = CaptchaEls}, + {ok, ID, Body, CaptchaEls} -> + MsgPkt = #message{id = ID, body = Body, + sub_els = CaptchaEls}, Robots = (?DICT):store(From, {Nick, Packet}, StateData#state.robots), ejabberd_router:route(RoomJID, From, MsgPkt), diff --git a/src/mod_register.erl b/src/mod_register.erl index 3f9c33123..1ed266d47 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -218,10 +218,10 @@ process_iq(#iq{type = get, from = From, to = To, id = ID, lang = Lang} = IQ, X = #xdata{type = form, instructions = [Instr], fields = [UField, PField]}, case ejabberd_captcha:create_captcha_x(ID, To, Lang, Source, X) of - {ok, Captcha} -> + {ok, CaptchaEls} -> xmpp:make_iq_result( IQ, #register{instructions = TopInstr, - xdata = Captcha}); + sub_els = CaptchaEls}); {error, limit} -> ErrText = <<"Too many CAPTCHA requests">>, xmpp:make_error( diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index 76de1677f..20b370fb9 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -60,7 +60,7 @@ -include("ejabberd.hrl"). -include("logger.hrl"). --include("jlib.hrl"). +-include("xmpp.hrl"). -include("ejabberd_http.hrl"). @@ -334,7 +334,7 @@ build_captcha_li_list2(Lang, IP) -> case ejabberd_captcha:create_captcha(SID, From, To, Lang, IP, Args) of - {ok, Id, _} -> + {ok, Id, _, _} -> {_, {CImg, CText, CId, CKey}} = ejabberd_captcha:build_captcha_html(Id, Lang), [?XE(<<"li">>, diff --git a/src/xmpp_codec.erl b/src/xmpp_codec.erl index 7eb06b11e..113be860b 100644 --- a/src/xmpp_codec.erl +++ b/src/xmpp_codec.erl @@ -15,6 +15,22 @@ decode(_el) -> decode(_el, []). decode({xmlel, _name, _attrs, _} = _el, Opts) -> IgnoreEls = proplists:get_bool(ignore_els, Opts), case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"x">>, <<"jabber:x:oob">>} -> + decode_oob_x(<<"jabber:x:oob">>, IgnoreEls, _el); + {<<"desc">>, <<"jabber:x:oob">>} -> + decode_oob_desc(<<"jabber:x:oob">>, IgnoreEls, _el); + {<<"url">>, <<"jabber:x:oob">>} -> + decode_oob_url(<<"jabber:x:oob">>, IgnoreEls, _el); + {<<"media">>, <<"urn:xmpp:media-element">>} -> + decode_media(<<"urn:xmpp:media-element">>, IgnoreEls, + _el); + {<<"uri">>, <<"urn:xmpp:media-element">>} -> + decode_media_uri(<<"urn:xmpp:media-element">>, + IgnoreEls, _el); + {<<"captcha">>, <<"urn:xmpp:captcha">>} -> + decode_captcha(<<"urn:xmpp:captcha">>, IgnoreEls, _el); + {<<"data">>, <<"urn:xmpp:bob">>} -> + decode_bob_data(<<"urn:xmpp:bob">>, IgnoreEls, _el); {<<"stream:stream">>, <<"jabber:client">>} -> decode_stream_start(<<"jabber:client">>, IgnoreEls, _el); @@ -1293,6 +1309,13 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> is_known_tag({xmlel, _name, _attrs, _} = _el) -> case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"x">>, <<"jabber:x:oob">>} -> true; + {<<"desc">>, <<"jabber:x:oob">>} -> true; + {<<"url">>, <<"jabber:x:oob">>} -> true; + {<<"media">>, <<"urn:xmpp:media-element">>} -> true; + {<<"uri">>, <<"urn:xmpp:media-element">>} -> true; + {<<"captcha">>, <<"urn:xmpp:captcha">>} -> true; + {<<"data">>, <<"urn:xmpp:bob">>} -> true; {<<"stream:stream">>, <<"jabber:client">>} -> true; {<<"stream:stream">>, <<"jabber:server">>} -> true; {<<"stream:stream">>, <<"jabber:component:accept">>} -> @@ -2216,7 +2239,7 @@ encode({feature_register} = Register) -> [{<<"xmlns">>, <<"http://jabber.org/features/iq-register">>}]); encode({register, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _} = + _, _, _, _, _, _, _, _, _} = Query) -> encode_register(Query, [{<<"xmlns">>, <<"jabber:iq:register">>}]); @@ -2285,7 +2308,7 @@ encode({vcard_xupdate, undefined, _} = X) -> encode({xdata_option, _, _} = Option) -> encode_xdata_field_option(Option, [{<<"xmlns">>, <<"jabber:x:data">>}]); -encode({xdata_field, _, _, _, _, _, _, _} = Field) -> +encode({xdata_field, _, _, _, _, _, _, _, _} = Field) -> encode_xdata_field(Field, [{<<"xmlns">>, <<"jabber:x:data">>}]); encode({xdata, _, _, _, _, _, _} = X) -> @@ -2572,7 +2595,21 @@ encode({handshake, _} = Handshake) -> [{<<"xmlns">>, <<"jabber:client">>}]); encode({stream_start, _, _, _, _, _, _, _, _} = Stream_stream) -> - encode_stream_start(Stream_stream, []). + encode_stream_start(Stream_stream, []); +encode({bob_data, _, _, _, _} = Data) -> + encode_bob_data(Data, + [{<<"xmlns">>, <<"urn:xmpp:bob">>}]); +encode({xcaptcha, _} = Captcha) -> + encode_captcha(Captcha, + [{<<"xmlns">>, <<"urn:xmpp:captcha">>}]); +encode({media_uri, _, _} = Uri) -> + encode_media_uri(Uri, + [{<<"xmlns">>, <<"urn:xmpp:media-element">>}]); +encode({media, _, _, _} = Media) -> + encode_media(Media, + [{<<"xmlns">>, <<"urn:xmpp:media-element">>}]); +encode({oob_x, _, _, _} = X) -> + encode_oob_x(X, [{<<"xmlns">>, <<"jabber:x:oob">>}]). get_name({last, _, _}) -> <<"query">>; get_name({version, _, _, _}) -> <<"query">>; @@ -2628,7 +2665,7 @@ 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">>; @@ -2659,7 +2696,7 @@ get_name({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, <<"vCard">>; get_name({vcard_xupdate, undefined, _}) -> <<"x">>; get_name({xdata_option, _, _}) -> <<"option">>; -get_name({xdata_field, _, _, _, _, _, _, _}) -> +get_name({xdata_field, _, _, _, _, _, _, _, _}) -> <<"field">>; get_name({xdata, _, _, _, _, _, _}) -> <<"x">>; get_name({pubsub_subscription, _, _, _, _}) -> @@ -2760,7 +2797,12 @@ get_name({db_verify, _, _, _, _, _, _}) -> <<"db:verify">>; get_name({handshake, _}) -> <<"handshake">>; get_name({stream_start, _, _, _, _, _, _, _, _}) -> - <<"stream:stream">>. + <<"stream:stream">>; +get_name({bob_data, _, _, _, _}) -> <<"data">>; +get_name({xcaptcha, _}) -> <<"captcha">>; +get_name({media_uri, _, _}) -> <<"uri">>; +get_name({media, _, _, _}) -> <<"media">>; +get_name({oob_x, _, _, _}) -> <<"x">>. get_ns({last, _, _}) -> <<"jabber:iq:last">>; get_ns({version, _, _, _}) -> <<"jabber:iq:version">>; @@ -2848,7 +2890,7 @@ get_ns({caps, _, _, _, _}) -> get_ns({feature_register}) -> <<"http://jabber.org/features/iq-register">>; get_ns({register, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _}) -> + _, _, _, _, _, _, _, _, _}) -> <<"jabber:iq:register">>; get_ns({xmpp_session, _}) -> <<"urn:ietf:params:xml:ns:xmpp-session">>; @@ -2881,7 +2923,7 @@ get_ns({vcard_temp, _, _, _, _, _, _, _, _, _, _, _, _, get_ns({vcard_xupdate, undefined, _}) -> <<"vcard-temp:x:update">>; get_ns({xdata_option, _, _}) -> <<"jabber:x:data">>; -get_ns({xdata_field, _, _, _, _, _, _, _}) -> +get_ns({xdata_field, _, _, _, _, _, _, _, _}) -> <<"jabber:x:data">>; get_ns({xdata, _, _, _, _, _, _}) -> <<"jabber:x:data">>; @@ -3021,7 +3063,14 @@ get_ns({db_verify, _, _, _, _, _, _}) -> <<"jabber:client">>; get_ns({handshake, _}) -> <<"jabber:client">>; get_ns({stream_start, _, _, _, _, Xmlns, _, _, _}) -> - Xmlns. + Xmlns; +get_ns({bob_data, _, _, _, _}) -> <<"urn:xmpp:bob">>; +get_ns({xcaptcha, _}) -> <<"urn:xmpp:captcha">>; +get_ns({media_uri, _, _}) -> + <<"urn:xmpp:media-element">>; +get_ns({media, _, _, _}) -> + <<"urn:xmpp:media-element">>; +get_ns({oob_x, _, _, _}) -> <<"jabber:x:oob">>. dec_int(Val) -> dec_int(Val, infinity, infinity). @@ -3129,10 +3178,11 @@ pp(p1_rebind, 0) -> []; pp(p1_ack, 0) -> []; pp(caps, 4) -> [node, version, hash, exts]; pp(feature_register, 0) -> []; -pp(register, 21) -> +pp(register, 22) -> [registered, remove, instructions, username, nick, password, name, first, last, email, address, city, - state, zip, phone, url, date, misc, text, key, xdata]; + state, zip, phone, url, date, misc, text, key, xdata, + sub_els]; pp(xmpp_session, 1) -> [optional]; pp(ping, 0) -> []; pp(time, 2) -> [tzo, utc]; @@ -3164,8 +3214,9 @@ pp(vcard_temp, 29) -> uid, url, class, key, desc]; pp(vcard_xupdate, 2) -> [us, hash]; pp(xdata_option, 2) -> [label, value]; -pp(xdata_field, 7) -> - [label, type, var, required, desc, values, options]; +pp(xdata_field, 8) -> + [label, type, var, required, desc, values, options, + sub_els]; pp(xdata, 6) -> [type, instructions, title, reported, items, fields]; pp(pubsub_subscription, 4) -> [jid, node, subid, type]; @@ -3263,6 +3314,11 @@ pp(handshake, 1) -> [data]; pp(stream_start, 8) -> [from, to, id, version, xmlns, stream_xmlns, db_xmlns, lang]; +pp(bob_data, 4) -> [cid, 'max-age', type, data]; +pp(xcaptcha, 1) -> [xdata]; +pp(media_uri, 2) -> [type, uri]; +pp(media, 3) -> [height, width, uri]; +pp(oob_x, 3) -> [url, desc, sid]; pp(_, _) -> no. join([], _Sep) -> <<>>; @@ -3309,6 +3365,423 @@ dec_tzo(Val) -> M = jlib:binary_to_integer(M1), if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end. +decode_oob_x(__TopXMLNS, __IgnoreEls, + {xmlel, <<"x">>, _attrs, _els}) -> + {Desc, Url} = decode_oob_x_els(__TopXMLNS, __IgnoreEls, + _els, <<>>, error), + Sid = decode_oob_x_attrs(__TopXMLNS, _attrs, undefined), + {oob_x, Url, Desc, Sid}. + +decode_oob_x_els(__TopXMLNS, __IgnoreEls, [], Desc, + Url) -> + {Desc, + case Url of + error -> + erlang:error({xmpp_codec, + {missing_tag, <<"url">>, __TopXMLNS}}); + {value, Url1} -> Url1 + end}; +decode_oob_x_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"url">>, _attrs, _} = _el | _els], Desc, + Url) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> when __TopXMLNS == <<"jabber:x:oob">> -> + decode_oob_x_els(__TopXMLNS, __IgnoreEls, _els, Desc, + {value, + decode_oob_url(__TopXMLNS, __IgnoreEls, _el)}); + <<"jabber:x:oob">> -> + decode_oob_x_els(__TopXMLNS, __IgnoreEls, _els, Desc, + {value, + decode_oob_url(<<"jabber:x:oob">>, __IgnoreEls, + _el)}); + _ -> + decode_oob_x_els(__TopXMLNS, __IgnoreEls, _els, Desc, + Url) + end; +decode_oob_x_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"desc">>, _attrs, _} = _el | _els], Desc, + Url) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> when __TopXMLNS == <<"jabber:x:oob">> -> + decode_oob_x_els(__TopXMLNS, __IgnoreEls, _els, + decode_oob_desc(__TopXMLNS, __IgnoreEls, _el), Url); + <<"jabber:x:oob">> -> + decode_oob_x_els(__TopXMLNS, __IgnoreEls, _els, + decode_oob_desc(<<"jabber:x:oob">>, __IgnoreEls, + _el), + Url); + _ -> + decode_oob_x_els(__TopXMLNS, __IgnoreEls, _els, Desc, + Url) + end; +decode_oob_x_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Desc, Url) -> + decode_oob_x_els(__TopXMLNS, __IgnoreEls, _els, Desc, + Url). + +decode_oob_x_attrs(__TopXMLNS, + [{<<"sid">>, _val} | _attrs], _Sid) -> + decode_oob_x_attrs(__TopXMLNS, _attrs, _val); +decode_oob_x_attrs(__TopXMLNS, [_ | _attrs], Sid) -> + decode_oob_x_attrs(__TopXMLNS, _attrs, Sid); +decode_oob_x_attrs(__TopXMLNS, [], Sid) -> + decode_oob_x_attr_sid(__TopXMLNS, Sid). + +encode_oob_x({oob_x, Url, Desc, Sid}, _xmlns_attrs) -> + _els = lists:reverse('encode_oob_x_$desc'(Desc, + 'encode_oob_x_$url'(Url, []))), + _attrs = encode_oob_x_attr_sid(Sid, _xmlns_attrs), + {xmlel, <<"x">>, _attrs, _els}. + +'encode_oob_x_$desc'(<<>>, _acc) -> _acc; +'encode_oob_x_$desc'(Desc, _acc) -> + [encode_oob_desc(Desc, []) | _acc]. + +'encode_oob_x_$url'(Url, _acc) -> + [encode_oob_url(Url, []) | _acc]. + +decode_oob_x_attr_sid(__TopXMLNS, undefined) -> <<>>; +decode_oob_x_attr_sid(__TopXMLNS, _val) -> _val. + +encode_oob_x_attr_sid(<<>>, _acc) -> _acc; +encode_oob_x_attr_sid(_val, _acc) -> + [{<<"sid">>, _val} | _acc]. + +decode_oob_desc(__TopXMLNS, __IgnoreEls, + {xmlel, <<"desc">>, _attrs, _els}) -> + Cdata = decode_oob_desc_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_oob_desc_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_oob_desc_cdata(__TopXMLNS, Cdata); +decode_oob_desc_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_oob_desc_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_oob_desc_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_oob_desc_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_oob_desc(Cdata, _xmlns_attrs) -> + _els = encode_oob_desc_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"desc">>, _attrs, _els}. + +decode_oob_desc_cdata(__TopXMLNS, <<>>) -> <<>>; +decode_oob_desc_cdata(__TopXMLNS, _val) -> _val. + +encode_oob_desc_cdata(<<>>, _acc) -> _acc; +encode_oob_desc_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_oob_url(__TopXMLNS, __IgnoreEls, + {xmlel, <<"url">>, _attrs, _els}) -> + Cdata = decode_oob_url_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_oob_url_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_oob_url_cdata(__TopXMLNS, Cdata); +decode_oob_url_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_oob_url_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_oob_url_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_oob_url_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_oob_url(Cdata, _xmlns_attrs) -> + _els = encode_oob_url_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"url">>, _attrs, _els}. + +decode_oob_url_cdata(__TopXMLNS, <<>>) -> + erlang:error({xmpp_codec, + {missing_cdata, <<>>, <<"url">>, __TopXMLNS}}); +decode_oob_url_cdata(__TopXMLNS, _val) -> _val. + +encode_oob_url_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_media(__TopXMLNS, __IgnoreEls, + {xmlel, <<"media">>, _attrs, _els}) -> + Uri = decode_media_els(__TopXMLNS, __IgnoreEls, _els, + []), + {Height, Width} = decode_media_attrs(__TopXMLNS, _attrs, + undefined, undefined), + {media, Height, Width, Uri}. + +decode_media_els(__TopXMLNS, __IgnoreEls, [], Uri) -> + lists:reverse(Uri); +decode_media_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"uri">>, _attrs, _} = _el | _els], Uri) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == <<"urn:xmpp:media-element">> -> + decode_media_els(__TopXMLNS, __IgnoreEls, _els, + [decode_media_uri(__TopXMLNS, __IgnoreEls, _el) + | Uri]); + <<"urn:xmpp:media-element">> -> + decode_media_els(__TopXMLNS, __IgnoreEls, _els, + [decode_media_uri(<<"urn:xmpp:media-element">>, + __IgnoreEls, _el) + | Uri]); + _ -> + decode_media_els(__TopXMLNS, __IgnoreEls, _els, Uri) + end; +decode_media_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Uri) -> + decode_media_els(__TopXMLNS, __IgnoreEls, _els, Uri). + +decode_media_attrs(__TopXMLNS, + [{<<"height">>, _val} | _attrs], _Height, Width) -> + decode_media_attrs(__TopXMLNS, _attrs, _val, Width); +decode_media_attrs(__TopXMLNS, + [{<<"width">>, _val} | _attrs], Height, _Width) -> + decode_media_attrs(__TopXMLNS, _attrs, Height, _val); +decode_media_attrs(__TopXMLNS, [_ | _attrs], Height, + Width) -> + decode_media_attrs(__TopXMLNS, _attrs, Height, Width); +decode_media_attrs(__TopXMLNS, [], Height, Width) -> + {decode_media_attr_height(__TopXMLNS, Height), + decode_media_attr_width(__TopXMLNS, Width)}. + +encode_media({media, Height, Width, Uri}, + _xmlns_attrs) -> + _els = lists:reverse('encode_media_$uri'(Uri, [])), + _attrs = encode_media_attr_width(Width, + encode_media_attr_height(Height, + _xmlns_attrs)), + {xmlel, <<"media">>, _attrs, _els}. + +'encode_media_$uri'([], _acc) -> _acc; +'encode_media_$uri'([Uri | _els], _acc) -> + 'encode_media_$uri'(_els, + [encode_media_uri(Uri, []) | _acc]). + +decode_media_attr_height(__TopXMLNS, undefined) -> + undefined; +decode_media_attr_height(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, infinity) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"height">>, <<"media">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_media_attr_height(undefined, _acc) -> _acc; +encode_media_attr_height(_val, _acc) -> + [{<<"height">>, enc_int(_val)} | _acc]. + +decode_media_attr_width(__TopXMLNS, undefined) -> + undefined; +decode_media_attr_width(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, inifinity) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"width">>, <<"media">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_media_attr_width(undefined, _acc) -> _acc; +encode_media_attr_width(_val, _acc) -> + [{<<"width">>, enc_int(_val)} | _acc]. + +decode_media_uri(__TopXMLNS, __IgnoreEls, + {xmlel, <<"uri">>, _attrs, _els}) -> + Uri = decode_media_uri_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Type = decode_media_uri_attrs(__TopXMLNS, _attrs, + undefined), + {media_uri, Type, Uri}. + +decode_media_uri_els(__TopXMLNS, __IgnoreEls, [], + Uri) -> + decode_media_uri_cdata(__TopXMLNS, Uri); +decode_media_uri_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Uri) -> + decode_media_uri_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_media_uri_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Uri) -> + decode_media_uri_els(__TopXMLNS, __IgnoreEls, _els, + Uri). + +decode_media_uri_attrs(__TopXMLNS, + [{<<"type">>, _val} | _attrs], _Type) -> + decode_media_uri_attrs(__TopXMLNS, _attrs, _val); +decode_media_uri_attrs(__TopXMLNS, [_ | _attrs], + Type) -> + decode_media_uri_attrs(__TopXMLNS, _attrs, Type); +decode_media_uri_attrs(__TopXMLNS, [], Type) -> + decode_media_uri_attr_type(__TopXMLNS, Type). + +encode_media_uri({media_uri, Type, Uri}, + _xmlns_attrs) -> + _els = encode_media_uri_cdata(Uri, []), + _attrs = encode_media_uri_attr_type(Type, _xmlns_attrs), + {xmlel, <<"uri">>, _attrs, _els}. + +decode_media_uri_attr_type(__TopXMLNS, undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"type">>, <<"uri">>, __TopXMLNS}}); +decode_media_uri_attr_type(__TopXMLNS, _val) -> _val. + +encode_media_uri_attr_type(_val, _acc) -> + [{<<"type">>, _val} | _acc]. + +decode_media_uri_cdata(__TopXMLNS, <<>>) -> <<>>; +decode_media_uri_cdata(__TopXMLNS, _val) -> _val. + +encode_media_uri_cdata(<<>>, _acc) -> _acc; +encode_media_uri_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_captcha(__TopXMLNS, __IgnoreEls, + {xmlel, <<"captcha">>, _attrs, _els}) -> + Xdata = decode_captcha_els(__TopXMLNS, __IgnoreEls, + _els, error), + {xcaptcha, Xdata}. + +decode_captcha_els(__TopXMLNS, __IgnoreEls, [], + Xdata) -> + case Xdata of + error -> + erlang:error({xmpp_codec, + {missing_tag, <<"x">>, __TopXMLNS}}); + {value, Xdata1} -> Xdata1 + end; +decode_captcha_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"jabber:x:data">> -> + decode_captcha_els(__TopXMLNS, __IgnoreEls, _els, + {value, + decode_xdata(<<"jabber:x:data">>, __IgnoreEls, + _el)}); + _ -> + decode_captcha_els(__TopXMLNS, __IgnoreEls, _els, Xdata) + end; +decode_captcha_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Xdata) -> + decode_captcha_els(__TopXMLNS, __IgnoreEls, _els, + Xdata). + +encode_captcha({xcaptcha, Xdata}, _xmlns_attrs) -> + _els = lists:reverse('encode_captcha_$xdata'(Xdata, + [])), + _attrs = _xmlns_attrs, + {xmlel, <<"captcha">>, _attrs, _els}. + +'encode_captcha_$xdata'(Xdata, _acc) -> + [encode_xdata(Xdata, + [{<<"xmlns">>, <<"jabber:x:data">>}]) + | _acc]. + +decode_bob_data(__TopXMLNS, __IgnoreEls, + {xmlel, <<"data">>, _attrs, _els}) -> + Data = decode_bob_data_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + {Cid, Max_age, Type} = decode_bob_data_attrs(__TopXMLNS, + _attrs, undefined, undefined, + undefined), + {bob_data, Cid, Max_age, Type, Data}. + +decode_bob_data_els(__TopXMLNS, __IgnoreEls, [], + Data) -> + decode_bob_data_cdata(__TopXMLNS, Data); +decode_bob_data_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Data) -> + decode_bob_data_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_bob_data_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Data) -> + decode_bob_data_els(__TopXMLNS, __IgnoreEls, _els, + Data). + +decode_bob_data_attrs(__TopXMLNS, + [{<<"cid">>, _val} | _attrs], _Cid, Max_age, Type) -> + decode_bob_data_attrs(__TopXMLNS, _attrs, _val, Max_age, + Type); +decode_bob_data_attrs(__TopXMLNS, + [{<<"max-age">>, _val} | _attrs], Cid, _Max_age, + Type) -> + decode_bob_data_attrs(__TopXMLNS, _attrs, Cid, _val, + Type); +decode_bob_data_attrs(__TopXMLNS, + [{<<"type">>, _val} | _attrs], Cid, Max_age, _Type) -> + decode_bob_data_attrs(__TopXMLNS, _attrs, Cid, Max_age, + _val); +decode_bob_data_attrs(__TopXMLNS, [_ | _attrs], Cid, + Max_age, Type) -> + decode_bob_data_attrs(__TopXMLNS, _attrs, Cid, Max_age, + Type); +decode_bob_data_attrs(__TopXMLNS, [], Cid, Max_age, + Type) -> + {decode_bob_data_attr_cid(__TopXMLNS, Cid), + 'decode_bob_data_attr_max-age'(__TopXMLNS, Max_age), + decode_bob_data_attr_type(__TopXMLNS, Type)}. + +encode_bob_data({bob_data, Cid, Max_age, Type, Data}, + _xmlns_attrs) -> + _els = encode_bob_data_cdata(Data, []), + _attrs = encode_bob_data_attr_type(Type, + 'encode_bob_data_attr_max-age'(Max_age, + encode_bob_data_attr_cid(Cid, + _xmlns_attrs))), + {xmlel, <<"data">>, _attrs, _els}. + +decode_bob_data_attr_cid(__TopXMLNS, undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"cid">>, <<"data">>, __TopXMLNS}}); +decode_bob_data_attr_cid(__TopXMLNS, _val) -> _val. + +encode_bob_data_attr_cid(_val, _acc) -> + [{<<"cid">>, _val} | _acc]. + +'decode_bob_data_attr_max-age'(__TopXMLNS, undefined) -> + undefined; +'decode_bob_data_attr_max-age'(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, infinity) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"max-age">>, <<"data">>, + __TopXMLNS}}); + _res -> _res + end. + +'encode_bob_data_attr_max-age'(undefined, _acc) -> _acc; +'encode_bob_data_attr_max-age'(_val, _acc) -> + [{<<"max-age">>, enc_int(_val)} | _acc]. + +decode_bob_data_attr_type(__TopXMLNS, undefined) -> + undefined; +decode_bob_data_attr_type(__TopXMLNS, _val) -> _val. + +encode_bob_data_attr_type(undefined, _acc) -> _acc; +encode_bob_data_attr_type(_val, _acc) -> + [{<<"type">>, _val} | _acc]. + +decode_bob_data_cdata(__TopXMLNS, <<>>) -> <<>>; +decode_bob_data_cdata(__TopXMLNS, _val) -> + case catch base64:decode(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"data">>, __TopXMLNS}}); + _res -> _res + end. + +encode_bob_data_cdata(<<>>, _acc) -> _acc; +encode_bob_data_cdata(_val, _acc) -> + [{xmlcdata, base64:encode(_val)} | _acc]. + decode_stream_start(__TopXMLNS, __IgnoreEls, {xmlel, <<"stream:stream">>, _attrs, _els}) -> {From, To, Xmlns, Stream_xmlns, Db_xmlns, Lang, Version, @@ -12727,60 +13200,62 @@ encode_xdata_instructions_cdata(_val, _acc) -> decode_xdata_field(__TopXMLNS, __IgnoreEls, {xmlel, <<"field">>, _attrs, _els}) -> - {Options, Values, Desc, Required} = + {Options, Values, Desc, Required, __Els} = decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, - [], [], undefined, false), + [], [], undefined, false, []), {Label, Type, Var} = decode_xdata_field_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {xdata_field, Label, Type, Var, Required, Desc, Values, - Options}. + Options, __Els}. decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [], - Options, Values, Desc, Required) -> + Options, Values, Desc, Required, __Els) -> {lists:reverse(Options), lists:reverse(Values), Desc, - Required}; + Required, lists:reverse(__Els)}; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"required">>, _attrs, _} = _el | _els], - Options, Values, Desc, Required) -> + Options, Values, Desc, Required, __Els) -> 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)); + __IgnoreEls, _el), + __Els); <<"jabber:x:data">> -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, Desc, decode_xdata_field_required(<<"jabber:x:data">>, - __IgnoreEls, _el)); + __IgnoreEls, _el), + __Els); _ -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, - Options, Values, Desc, Required) + Options, Values, Desc, Required, __Els) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"desc">>, _attrs, _} = _el | _els], Options, - Values, Desc, Required) -> + Values, Desc, Required, __Els) -> 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); + Required, __Els); <<"jabber:x:data">> -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, decode_xdata_field_desc(<<"jabber:x:data">>, __IgnoreEls, _el), - Required); + Required, __Els); _ -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, - Options, Values, Desc, Required) + Options, Values, Desc, Required, __Els) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"value">>, _attrs, _} = _el | _els], Options, - Values, Desc, Required) -> + Values, Desc, Required, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:x:data">> -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, @@ -12791,7 +13266,7 @@ decode_xdata_field_els(__TopXMLNS, __IgnoreEls, undefined -> Values; _new_el -> [_new_el | Values] end, - Desc, Required); + Desc, Required, __Els); <<"jabber:x:data">> -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, @@ -12802,35 +13277,53 @@ decode_xdata_field_els(__TopXMLNS, __IgnoreEls, undefined -> Values; _new_el -> [_new_el | Values] end, - Desc, Required); + Desc, Required, __Els); _ -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, - Options, Values, Desc, Required) + Options, Values, Desc, Required, __Els) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"option">>, _attrs, _} = _el | _els], - Options, Values, Desc, Required) -> + Options, Values, Desc, Required, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:x:data">> -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, [decode_xdata_field_option(__TopXMLNS, __IgnoreEls, _el) | Options], - Values, Desc, Required); + Values, Desc, Required, __Els); <<"jabber:x:data">> -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, [decode_xdata_field_option(<<"jabber:x:data">>, __IgnoreEls, _el) | Options], - Values, Desc, Required); + Values, Desc, Required, __Els); _ -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, - Options, Values, Desc, Required) + Options, Values, Desc, Required, __Els) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, - [_ | _els], Options, Values, Desc, Required) -> + [{xmlel, _, _, _} = _el | _els], Options, Values, Desc, + Required, __Els) -> + if __IgnoreEls -> + decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, + Options, Values, Desc, Required, + [_el | __Els]); + true -> + case is_known_tag(_el) of + true -> + decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, + Options, Values, Desc, Required, + [decode(_el) | __Els]); + false -> + decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, + Options, Values, Desc, Required, __Els) + end + end; +decode_xdata_field_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Options, Values, Desc, Required, __Els) -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, - Options, Values, Desc, Required). + Options, Values, Desc, Required, __Els). decode_xdata_field_attrs(__TopXMLNS, [{<<"label">>, _val} | _attrs], _Label, Type, Var) -> @@ -12855,14 +13348,14 @@ decode_xdata_field_attrs(__TopXMLNS, [], Label, Type, decode_xdata_field_attr_var(__TopXMLNS, Var)}. encode_xdata_field({xdata_field, Label, Type, Var, - Required, Desc, Values, Options}, + Required, Desc, Values, Options, __Els}, _xmlns_attrs) -> - _els = - lists:reverse('encode_xdata_field_$options'(Options, - 'encode_xdata_field_$values'(Values, - 'encode_xdata_field_$desc'(Desc, - 'encode_xdata_field_$required'(Required, - []))))), + _els = [encode(_el) || _el <- __Els] ++ + lists:reverse('encode_xdata_field_$options'(Options, + 'encode_xdata_field_$values'(Values, + 'encode_xdata_field_$desc'(Desc, + 'encode_xdata_field_$required'(Required, + []))))), _attrs = encode_xdata_field_attr_var(Var, encode_xdata_field_attr_type(Type, encode_xdata_field_attr_label(Label, @@ -18909,29 +19402,31 @@ decode_register(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email} = + Username, Remove, Key, City, Nick, Url, Email, __Els} = decode_register_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, false, undefined, undefined, undefined, undefined, undefined, false, undefined, undefined, - undefined, undefined, undefined), + undefined, undefined, undefined, []), {register, Registered, Remove, Instructions, Username, Nick, Password, Name, First, Last, Email, Address, City, - State, Zip, Phone, Url, Date, Misc, Text, Key, Xdata}. + State, Zip, Phone, Url, Date, Misc, Text, Key, Xdata, + __Els}. decode_register_els(__TopXMLNS, __IgnoreEls, [], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> {Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email}; + Username, Remove, Key, City, Nick, Url, Email, + lists:reverse(__Els)}; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"x">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"jabber:x:data">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -18939,19 +19434,20 @@ decode_register_els(__TopXMLNS, __IgnoreEls, _el), Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email); + Username, Remove, Key, City, Nick, Url, Email, + __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -18960,7 +19456,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_registered(__TopXMLNS, __IgnoreEls, _el), Date, Phone, State, Name, Username, Remove, Key, - City, Nick, Url, Email); + City, Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -18968,19 +19464,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_registered(<<"jabber:iq:register">>, __IgnoreEls, _el), Date, Phone, State, Name, Username, Remove, Key, - City, Nick, Url, Email); + City, Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -18989,7 +19485,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, decode_register_remove(__TopXMLNS, __IgnoreEls, _el), - Key, City, Nick, Url, Email); + Key, City, Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -18997,19 +19493,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, decode_register_remove(<<"jabber:iq:register">>, __IgnoreEls, _el), - Key, City, Nick, Url, Email); + Key, City, Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19018,7 +19514,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, __IgnoreEls, _el), Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, - Nick, Url, Email); + Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, @@ -19026,19 +19522,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, __IgnoreEls, _el), Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, - Nick, Url, Email); + Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19047,7 +19543,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, decode_register_username(__TopXMLNS, __IgnoreEls, _el), - Remove, Key, City, Nick, Url, Email); + Remove, Key, City, Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19055,19 +19551,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, decode_register_username(<<"jabber:iq:register">>, __IgnoreEls, _el), - Remove, Key, City, Nick, Url, Email); + Remove, Key, City, Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19076,7 +19572,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, Remove, Key, City, decode_register_nick(__TopXMLNS, __IgnoreEls, _el), - Url, Email); + Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19084,19 +19580,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, Remove, Key, City, decode_register_nick(<<"jabber:iq:register">>, __IgnoreEls, _el), - Url, Email); + Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19105,7 +19601,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_password(__TopXMLNS, __IgnoreEls, _el), Registered, Date, Phone, State, Name, Username, - Remove, Key, City, Nick, Url, Email); + Remove, Key, City, Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19113,19 +19609,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_password(<<"jabber:iq:register">>, __IgnoreEls, _el), Registered, Date, Phone, State, Name, Username, - Remove, Key, City, Nick, Url, Email); + Remove, Key, City, Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19133,26 +19629,28 @@ decode_register_els(__TopXMLNS, __IgnoreEls, First, Password, Registered, Date, Phone, State, decode_register_name(__TopXMLNS, __IgnoreEls, _el), - Username, Remove, Key, City, Nick, Url, Email); + Username, Remove, Key, City, Nick, Url, Email, + __Els); <<"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); + Username, Remove, Key, City, Nick, Url, Email, + __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19160,26 +19658,28 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_first(__TopXMLNS, __IgnoreEls, _el), Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email); + Username, Remove, Key, City, Nick, Url, Email, + __Els); <<"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); + Username, Remove, Key, City, Nick, Url, Email, + __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19188,7 +19688,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, _el), First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, - Email); + Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, @@ -19196,19 +19696,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, __IgnoreEls, _el), First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, - Email); + Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19216,26 +19716,28 @@ decode_register_els(__TopXMLNS, __IgnoreEls, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, decode_register_email(__TopXMLNS, __IgnoreEls, - _el)); + _el), + __Els); <<"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)); + __IgnoreEls, _el), + __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19244,7 +19746,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, _el), Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, - Remove, Key, City, Nick, Url, Email); + Remove, Key, City, Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, @@ -19252,19 +19754,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, __IgnoreEls, _el), Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, - Remove, Key, City, Nick, Url, Email); + Remove, Key, City, Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19273,7 +19775,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, Remove, Key, decode_register_city(__TopXMLNS, __IgnoreEls, _el), - Nick, Url, Email); + Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19281,19 +19783,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, Remove, Key, decode_register_city(<<"jabber:iq:register">>, __IgnoreEls, _el), - Nick, Url, Email); + Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19302,7 +19804,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_state(__TopXMLNS, __IgnoreEls, _el), Name, Username, Remove, Key, City, Nick, Url, - Email); + Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19310,19 +19812,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_state(<<"jabber:iq:register">>, __IgnoreEls, _el), Name, Username, Remove, Key, City, Nick, Url, - Email); + Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, @@ -19330,7 +19832,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, - Email); + Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, decode_register_zip(<<"jabber:iq:register">>, @@ -19338,19 +19840,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, - Email); + Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19359,7 +19861,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_phone(__TopXMLNS, __IgnoreEls, _el), State, Name, Username, Remove, Key, City, Nick, - Url, Email); + Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19367,19 +19869,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_phone(<<"jabber:iq:register">>, __IgnoreEls, _el), State, Name, Username, Remove, Key, City, Nick, - Url, Email); + Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19387,7 +19889,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, decode_register_url(__TopXMLNS, __IgnoreEls, _el), - Email); + Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19395,19 +19897,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, Remove, Key, City, Nick, decode_register_url(<<"jabber:iq:register">>, __IgnoreEls, _el), - Email); + Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19416,7 +19918,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_date(__TopXMLNS, __IgnoreEls, _el), Phone, State, Name, Username, Remove, Key, City, - Nick, Url, Email); + Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19424,19 +19926,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, decode_register_date(<<"jabber:iq:register">>, __IgnoreEls, _el), Phone, State, Name, Username, Remove, Key, City, - Nick, Url, Email); + Nick, Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19445,7 +19947,8 @@ decode_register_els(__TopXMLNS, __IgnoreEls, _el), Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email); + Username, Remove, Key, City, Nick, Url, Email, + __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, @@ -19453,19 +19956,20 @@ decode_register_els(__TopXMLNS, __IgnoreEls, __IgnoreEls, _el), Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, - Username, Remove, Key, City, Nick, Url, Email); + Username, Remove, Key, City, Nick, Url, Email, + __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19474,7 +19978,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, _el), Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, - Url, Email); + Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, @@ -19482,19 +19986,19 @@ decode_register_els(__TopXMLNS, __IgnoreEls, __IgnoreEls, _el), Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, - Url, Email); + Url, Email, __Els); _ -> 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) + Email, __Els) 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> case get_attr(<<"xmlns">>, _attrs) of <<"">> when __TopXMLNS == <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, @@ -19502,7 +20006,7 @@ decode_register_els(__TopXMLNS, __IgnoreEls, First, Password, Registered, Date, Phone, State, Name, Username, Remove, decode_register_key(__TopXMLNS, __IgnoreEls, _el), - City, Nick, Url, Email); + City, Nick, Url, Email, __Els); <<"jabber:iq:register">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, @@ -19510,50 +20014,79 @@ decode_register_els(__TopXMLNS, __IgnoreEls, Name, Username, Remove, decode_register_key(<<"jabber:iq:register">>, __IgnoreEls, _el), - City, Nick, Url, Email); + City, Nick, Url, Email, __Els); _ -> 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) + Email, __Els) + end; +decode_register_els(__TopXMLNS, __IgnoreEls, + [{xmlel, _, _, _} = _el | _els], Zip, Xdata, Misc, + Address, Instructions, Text, Last, First, Password, + Registered, Date, Phone, State, Name, Username, Remove, + Key, City, Nick, Url, Email, __Els) -> + if __IgnoreEls -> + 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, [_el | __Els]); + true -> + case is_known_tag(_el) of + 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, + [decode(_el) | __Els]); + false -> + 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, __Els) + end end; 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) -> + Username, Remove, Key, City, Nick, Url, Email, __Els) -> 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). + Username, Remove, Key, City, Nick, Url, Email, __Els). encode_register({register, Registered, Remove, Instructions, Username, Nick, Password, Name, First, Last, Email, Address, City, State, Zip, Phone, Url, - Date, Misc, Text, Key, Xdata}, + Date, Misc, Text, Key, Xdata, __Els}, _xmlns_attrs) -> - _els = lists:reverse('encode_register_$zip'(Zip, - 'encode_register_$xdata'(Xdata, - 'encode_register_$misc'(Misc, - 'encode_register_$address'(Address, - 'encode_register_$instructions'(Instructions, - 'encode_register_$text'(Text, - 'encode_register_$last'(Last, - 'encode_register_$first'(First, - 'encode_register_$password'(Password, - 'encode_register_$registered'(Registered, - 'encode_register_$date'(Date, - 'encode_register_$phone'(Phone, - 'encode_register_$state'(State, - 'encode_register_$name'(Name, - 'encode_register_$username'(Username, - 'encode_register_$remove'(Remove, - 'encode_register_$key'(Key, - 'encode_register_$city'(City, - 'encode_register_$nick'(Nick, - 'encode_register_$url'(Url, - 'encode_register_$email'(Email, - [])))))))))))))))))))))), + _els = [encode(_el) || _el <- __Els] ++ + lists:reverse('encode_register_$zip'(Zip, + 'encode_register_$xdata'(Xdata, + 'encode_register_$misc'(Misc, + 'encode_register_$address'(Address, + 'encode_register_$instructions'(Instructions, + 'encode_register_$text'(Text, + 'encode_register_$last'(Last, + 'encode_register_$first'(First, + 'encode_register_$password'(Password, + 'encode_register_$registered'(Registered, + 'encode_register_$date'(Date, + 'encode_register_$phone'(Phone, + 'encode_register_$state'(State, + 'encode_register_$name'(Name, + 'encode_register_$username'(Username, + 'encode_register_$remove'(Remove, + 'encode_register_$key'(Key, + 'encode_register_$city'(City, + 'encode_register_$nick'(Nick, + 'encode_register_$url'(Url, + 'encode_register_$email'(Email, + [])))))))))))))))))))))), _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 7503eab10..f72e250f2 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -1010,7 +1010,7 @@ '$username', '$nick', '$password', '$name', '$first', '$last', '$email', '$address', '$city', '$state', '$zip', '$phone', '$url', - '$date', '$misc', '$text', '$key', '$xdata'}, + '$date', '$misc', '$text', '$key', '$xdata', '$_els'}, refs = [#ref{name = xdata, min = 0, max = 1, label = '$xdata'}, #ref{name = register_registered, min = 0, max = 1, @@ -1600,7 +1600,7 @@ #elem{name = <<"field">>, xmlns = <<"jabber:x:data">>, result = {xdata_field, '$label', '$type', '$var', - '$required', '$desc', '$values', '$options'}, + '$required', '$desc', '$values', '$options', '$_els'}, attrs = [#attr{name = <<"label">>}, #attr{name = <<"type">>, enc = {enc_enum, []}, @@ -2937,6 +2937,66 @@ #attr{name = <<"version">>, default = <<"">>}, #attr{name = <<"id">>, default = <<"">>}]}). +-xml(bob_data, + #elem{name = <<"data">>, + xmlns = <<"urn:xmpp:bob">>, + result = {bob_data, '$cid', '$max-age', '$type', '$data'}, + attrs = [#attr{name = <<"cid">>, required = true}, + #attr{name = <<"max-age">>, + dec = {dec_int, [0, infinity]}, + enc = {enc_int, []}}, + #attr{name = <<"type">>}], + cdata = #cdata{label = '$data', default = <<"">>, + dec = {base64, decode, []}, + enc = {base64, encode, []}}}). + +-xml(captcha, + #elem{name = <<"captcha">>, + xmlns = <<"urn:xmpp:captcha">>, + result = {xcaptcha, '$xdata'}, + refs = [#ref{name = xdata, min = 1, max = 1}]}). + +-xml(media_uri, + #elem{name = <<"uri">>, + xmlns = <<"urn:xmpp:media-element">>, + result = {media_uri, '$type', '$uri'}, + attrs = [#attr{name = <<"type">>, required = true}], + cdata = #cdata{label = '$uri', default = <<"">>}}). + +-xml(media, + #elem{name = <<"media">>, + xmlns = <<"urn:xmpp:media-element">>, + result = {media, '$height', '$width', '$uri'}, + attrs = [#attr{name = <<"height">>, + dec = {dec_int, [0, infinity]}, + enc = {enc_int, []}}, + #attr{name = <<"width">>, + dec = {dec_int, [0, inifinity]}, + enc = {enc_int, []}}], + refs = [#ref{name = media_uri, label = '$uri'}]}). + +-xml(oob_url, + #elem{name = <<"url">>, + xmlns = <<"jabber:x:oob">>, + result = '$cdata', + cdata = #cdata{required = true}}). + +-xml(oob_desc, + #elem{name = <<"desc">>, + xmlns = <<"jabber:x:oob">>, + result = '$cdata', + cdata = #cdata{default = <<"">>}}). + +-xml(oob_x, + #elem{name = <<"x">>, + xmlns = <<"jabber:x:oob">>, + result = {oob_x, '$url', '$desc', '$sid'}, + attrs = [#attr{name = <<"sid">>, default = <<"">>}], + refs = [#ref{name = oob_url, min = 1, max = 1, + label = '$url'}, + #ref{name = oob_desc, default = <<"">>, + min = 0, max = 1, label = '$desc'}]}). + dec_tzo(Val) -> [H1, M1] = str:tokens(Val, <<":">>), H = jlib:binary_to_integer(H1),