]> granicus.if.org Git - ejabberd/commitdiff
Rewrite captcha to use XML generator
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 28 Jul 2016 12:10:41 +0000 (15:10 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 28 Jul 2016 12:10:41 +0000 (15:10 +0300)
include/xmpp_codec.hrl
src/ejabberd_captcha.erl
src/mod_muc_room.erl
src/mod_register.erl
src/mod_register_web.erl
src/xmpp_codec.erl
tools/xmpp_codec.spec

index 43bb6b098648efa7022cd876370b457e7c2dd7a8..1ede0ff1df44b69d86749429be154b14ec73dec7 100644 (file)
                               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(),
                       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(),
                     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(),
                            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()}).
                 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(),
                    misc :: 'none' | binary(),
                    text :: 'none' | binary(),
                    key :: 'none' | binary(),
-                   xdata :: #xdata{}}).
+                   xdata :: #xdata{},
+                   sub_els = [] :: [any()]}).
 -type register() :: #register{}.
 
 -record(disco_info, {node :: binary(),
                         version() |
                         pubsub_affiliation() |
                         mam_fin() |
+                        bob_data() |
+                        media() |
                         sm_a() |
                         carbons_sent() |
                         mam_archived() |
                         sasl_failure() |
                         bookmark_storage() |
                         muc_decline() |
-                        sasl_auth() |
-                        p1_push() |
                         legacy_auth() |
                         search() |
-                        pubsub_publish() |
                         unblock() |
                         nick() |
                         p1_ack() |
                         mix_join() |
                         xmpp_session() |
                         xdata() |
+                        xcaptcha() |
                         iq() |
                         streamhost() |
                         bind() |
                         starttls() |
                         mam_prefs() |
                         sasl_mechanisms() |
+                        media_uri() |
                         muc_destroy() |
                         vcard_key() |
                         csi() |
                         expire() |
                         muc_unsubscribe() |
                         pubsub_unsubscribe() |
-                        chatstate().
+                        chatstate() |
+                        sasl_auth() |
+                        p1_push() |
+                        oob_x() |
+                        pubsub_publish().
index 157700c47619d876c74e713cc33f13d2f53d59a8..df74a68b1f1f3b52a5702cad251eadee075677ef 100644 (file)
 -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()}.
-
-create_captcha_x(SID, To, Lang, Limiter, HeadEls) ->
-    create_captcha_x(SID, To, Lang, Limiter, HeadEls, []).
+-spec create_captcha_x(binary(), jid(), binary(), any(), xdata()) ->
+                             {ok, xdata()} | {error, image_error()}.
 
--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(<<Id/binary, "/image">>),
-         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(<<Id/binary, "/image">>)}],
                         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}.
-
-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
+-spec process_reply(xmpp_element()) -> ok | {error, bad_match | not_found | malformed}.
+
+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,
index 29b7942cf0c022338c08ff5a09a495a43b9bc8d8..a539ab8488b58c517f340013434eb6f3f2e06c2e 100644 (file)
@@ -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),
index 3f9c33123d9f9e1160f5d4e92e6f97b62f15f371..1ed266d474047063c8ed38c4d7703b93f4cd55d5 100644 (file)
@@ -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(
index 76de1677f78da8d7c31754db6d9e01e6f9d89513..20b370fb97e583b89cf2ecc22d2f6a5efbbd557c 100644 (file)
@@ -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">>,
index 7eb06b11e66991c9e204c267da5be08e1ec498f1..113be860be8da08b0040f114ce668cbe5680c95c 100644 (file)
@@ -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,
+                       <<Cdata/binary, _data/binary>>);
+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,
+                      <<Cdata/binary, _data/binary>>);
+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,
+                        <<Uri/binary, _data/binary>>);
+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,
+                       <<Data/binary, _data/binary>>);
+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}.
 
index 7503eab10a600d326fe11f29a490c2e47b8e3649..f72e250f25951d6c0275e85a025088c36c7189b1 100644 (file)
                      '$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,
      #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, []},
                    #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),