Rewrite mod_mix to use XML generator

This commit is contained in:
Evgeniy Khramtsov 2016-07-31 08:51:47 +03:00
parent eb1d385d4e
commit 0bcbd12776
6 changed files with 383 additions and 475 deletions

View File

@ -15,6 +15,14 @@
'no-permanent-store' | 'no-permanent-storage'}). 'no-permanent-store' | 'no-permanent-storage'}).
-type hint() :: #hint{}. -type hint() :: #hint{}.
-record(iq, {id :: binary(),
type :: 'error' | 'get' | 'result' | 'set',
lang :: binary(),
from :: any(),
to :: any(),
sub_els = [] :: [any()]}).
-type iq() :: #iq{}.
-record(feature_register, {}). -record(feature_register, {}).
-type feature_register() :: #feature_register{}. -type feature_register() :: #feature_register{}.
@ -170,6 +178,14 @@
-record(private, {xml_els = [] :: [any()]}). -record(private, {xml_els = [] :: [any()]}).
-type private() :: #private{}. -type private() :: #private{}.
-record(db_verify, {from :: any(),
to :: any(),
id :: binary(),
type :: 'error' | 'invalid' | 'valid',
key = <<>> :: binary(),
sub_els = [] :: [any()]}).
-type db_verify() :: #db_verify{}.
-record(nick, {name :: binary()}). -record(nick, {name :: binary()}).
-type nick() :: #nick{}. -type nick() :: #nick{}.
@ -267,6 +283,17 @@
jid :: any()}). jid :: any()}).
-type pubsub_subscribe() :: #pubsub_subscribe{}. -type pubsub_subscribe() :: #pubsub_subscribe{}.
-record(message, {id :: binary(),
type = normal :: 'chat' | 'error' | 'groupchat' | 'headline' | 'normal',
lang :: binary(),
from :: any(),
to :: any(),
subject = [] :: [#text{}],
body = [] :: [#text{}],
thread :: binary(),
sub_els = [] :: [any()]}).
-type message() :: #message{}.
-record(sasl_auth, {mechanism :: binary(), -record(sasl_auth, {mechanism :: binary(),
text :: any()}). text :: any()}).
-type sasl_auth() :: #sasl_auth{}. -type sasl_auth() :: #sasl_auth{}.
@ -349,6 +376,17 @@
items = [] :: [#pubsub_item{}]}). items = [] :: [#pubsub_item{}]}).
-type pubsub_items() :: #pubsub_items{}. -type pubsub_items() :: #pubsub_items{}.
-record(presence, {id :: binary(),
type = available :: 'available' | 'error' | 'probe' | 'subscribe' | 'subscribed' | 'unavailable' | 'unsubscribe' | 'unsubscribed',
lang :: binary(),
from :: any(),
to :: any(),
show :: 'away' | 'chat' | 'dnd' | 'xa',
status = [] :: [#text{}],
priority :: integer(),
sub_els = [] :: [any()]}).
-type presence() :: #presence{}.
-record(sic, {ip :: any(), -record(sic, {ip :: any(),
port :: non_neg_integer(), port :: non_neg_integer(),
xmlns :: binary()}). xmlns :: binary()}).
@ -385,6 +423,13 @@
userid :: binary()}). userid :: binary()}).
-type vcard_email() :: #vcard_email{}. -type vcard_email() :: #vcard_email{}.
-record(db_result, {from :: any(),
to :: any(),
type :: 'error' | 'invalid' | 'valid',
key = <<>> :: binary(),
sub_els = [] :: [any()]}).
-type db_result() :: #db_result{}.
-record(carbons_received, {forwarded :: #forwarded{}}). -record(carbons_received, {forwarded :: #forwarded{}}).
-type carbons_received() :: #carbons_received{}. -type carbons_received() :: #carbons_received{}.
@ -729,57 +774,10 @@
code :: non_neg_integer(), code :: non_neg_integer(),
by :: binary(), by :: binary(),
reason :: atom() | #gone{} | #redirect{}, reason :: atom() | #gone{} | #redirect{},
text :: #text{}}). text :: #text{},
sub_els = [] :: [any()]}).
-type error() :: #error{}. -type error() :: #error{}.
-record(db_verify, {from :: any(),
to :: any(),
id :: binary(),
type :: 'error' | 'invalid' | 'valid',
key = <<>> :: binary(),
error :: #error{}}).
-type db_verify() :: #db_verify{}.
-record(db_result, {from :: any(),
to :: any(),
type :: 'error' | 'invalid' | 'valid',
key = <<>> :: binary(),
error :: #error{}}).
-type db_result() :: #db_result{}.
-record(presence, {id :: binary(),
type = available :: 'available' | 'error' | 'probe' | 'subscribe' | 'subscribed' | 'unavailable' | 'unsubscribe' | 'unsubscribed',
lang :: binary(),
from :: any(),
to :: any(),
show :: 'away' | 'chat' | 'dnd' | 'xa',
status = [] :: [#text{}],
priority :: integer(),
error :: #error{},
sub_els = [] :: [any()]}).
-type presence() :: #presence{}.
-record(message, {id :: binary(),
type = normal :: 'chat' | 'error' | 'groupchat' | 'headline' | 'normal',
lang :: binary(),
from :: any(),
to :: any(),
subject = [] :: [#text{}],
body = [] :: [#text{}],
thread :: binary(),
error :: #error{},
sub_els = [] :: [any()]}).
-type message() :: #message{}.
-record(iq, {id :: binary(),
type :: 'error' | 'get' | 'result' | 'set',
lang :: binary(),
from :: any(),
to :: any(),
error :: #error{},
sub_els = [] :: [any()]}).
-type iq() :: #iq{}.
-record(mix_join, {jid :: any(), -record(mix_join, {jid :: any(),
subscribe = [] :: [binary()]}). subscribe = [] :: [binary()]}).
-type mix_join() :: #mix_join{}. -type mix_join() :: #mix_join{}.
@ -861,6 +859,7 @@
mam_archived() | mam_archived() |
p1_rebind() | p1_rebind() |
sasl_abort() | sasl_abort() |
db_result() |
carbons_received() | carbons_received() |
pubsub_retract() | pubsub_retract() |
upload_slot() | upload_slot() |
@ -868,7 +867,6 @@
compressed() | compressed() |
block_list() | block_list() |
rsm_set() | rsm_set() |
db_result() |
'see-other-host'() | 'see-other-host'() |
hint() | hint() |
stream_start() | stream_start() |
@ -939,8 +937,8 @@
mix_join() | mix_join() |
xmpp_session() | xmpp_session() |
xdata() | xdata() |
xcaptcha() |
iq() | iq() |
xcaptcha() |
streamhost() | streamhost() |
bind() | bind() |
last() | last() |
@ -971,9 +969,9 @@
muc_destroy() | muc_destroy() |
vcard_key() | vcard_key() |
csi() | csi() |
db_verify() |
roster_query() | roster_query() |
mam_query() | mam_query() |
db_verify() |
bookmark_url() | bookmark_url() |
vcard_email() | vcard_email() |
vcard_label() | vcard_label() |
@ -992,8 +990,8 @@
muc_unique() | muc_unique() |
sasl_response() | sasl_response() |
pubsub_subscribe() | pubsub_subscribe() |
presence() |
message() | message() |
presence() |
gone() | gone() |
sm_resume() | sm_resume() |
carbons_enable() | carbons_enable() |

View File

@ -12,7 +12,7 @@
-behaviour(gen_mod). -behaviour(gen_mod).
%% API %% API
-export([start_link/2, start/2, stop/1, process_iq/3, -export([start_link/2, start/2, stop/1, process_iq/1,
disco_items/5, disco_identity/5, disco_info/5, disco_items/5, disco_identity/5, disco_info/5,
disco_features/5, mod_opt_type/1, depends/2]). disco_features/5, mod_opt_type/1, depends/2]).
@ -21,8 +21,7 @@
terminate/2, code_change/3]). terminate/2, code_change/3]).
-include("logger.hrl"). -include("logger.hrl").
-include("jlib.hrl"). -include("xmpp.hrl").
-include("pubsub.hrl").
-define(PROCNAME, ejabberd_mod_mix). -define(PROCNAME, ejabberd_mod_mix).
-define(NODES, [?NS_MIX_NODES_MESSAGES, -define(NODES, [?NS_MIX_NODES_MESSAGES,
@ -57,84 +56,59 @@ disco_features(_Acc, _From, _To, _Node, _Lang) ->
{result, [?NS_MIX_0]}. {result, [?NS_MIX_0]}.
disco_items(_Acc, _From, To, _Node, _Lang) when To#jid.luser /= <<"">> -> disco_items(_Acc, _From, To, _Node, _Lang) when To#jid.luser /= <<"">> ->
To_s = jid:to_string(jid:remove_resource(To)), BareTo = jid:remove_resource(To),
{result, [#xmlel{name = <<"item">>, {result, [#disco_item{jid = BareTo, node = Node} || Node <- ?NODES]};
attrs = [{<<"jid">>, To_s},
{<<"node">>, Node}]} || Node <- ?NODES]};
disco_items(_Acc, _From, _To, _Node, _Lang) -> disco_items(_Acc, _From, _To, _Node, _Lang) ->
{result, []}. {result, []}.
disco_identity(Acc, _From, To, _Node, _Lang) when To#jid.luser == <<"">> -> disco_identity(Acc, _From, To, _Node, _Lang) when To#jid.luser == <<"">> ->
Acc ++ [#xmlel{name = <<"identity">>, Acc ++ [#identity{category = <<"conference">>,
attrs = name = <<"MIX service">>,
[{<<"category">>, <<"conference">>}, type = <<"text">>}];
{<<"name">>, <<"MIX service">>},
{<<"type">>, <<"text">>}]}];
disco_identity(Acc, _From, _To, _Node, _Lang) -> disco_identity(Acc, _From, _To, _Node, _Lang) ->
Acc ++ [#xmlel{name = <<"identity">>, Acc ++ [#identity{category = <<"conference">>,
attrs = type = <<"mix">>}].
[{<<"category">>, <<"conference">>},
{<<"type">>, <<"mix">>}]}].
disco_info(_Acc, _From, To, _Node, _Lang) when is_atom(To) -> disco_info(_Acc, _From, To, _Node, _Lang) when is_atom(To) ->
[#xmlel{name = <<"x">>, [#xdata{type = result,
attrs = [{<<"xmlns">>, ?NS_XDATA}, fields = [#xdata_field{var = <<"FORM_TYPE">>,
{<<"type">>, <<"result">>}], type = hidden,
children = [#xmlel{name = <<"field">>, values = [?NS_MIX_SERVICEINFO_0]}]}];
attrs = [{<<"var">>, <<"FORM_TYPE">>},
{<<"type">>, <<"hidden">>}],
children = [#xmlel{name = <<"value">>,
children = [{xmlcdata,
?NS_MIX_SERVICEINFO_0}]}]}]}];
disco_info(Acc, _From, _To, _Node, _Lang) -> disco_info(Acc, _From, _To, _Node, _Lang) ->
Acc. Acc.
process_iq(From, To, process_iq(#iq{type = set, from = From, to = To,
#iq{type = set, sub_el = #xmlel{name = <<"join">>} = SubEl} = IQ) -> sub_els = [#mix_join{subscribe = SubNodes}]} = IQ) ->
Nodes = lists:flatmap( Nodes = [Node || Node <- SubNodes, lists:member(Node, ?NODES)],
fun(#xmlel{name = <<"subscribe">>, attrs = Attrs}) ->
Node = fxml:get_attr_s(<<"node">>, Attrs),
case lists:member(Node, ?NODES) of
true -> [Node];
false -> []
end;
(_) ->
[]
end, SubEl#xmlel.children),
case subscribe_nodes(From, To, Nodes) of case subscribe_nodes(From, To, Nodes) of
{result, _} -> {result, _} ->
case publish_participant(From, To) of case publish_participant(From, To) of
{result, _} -> {result, _} ->
LFrom_s = jid:to_string(jid:tolower(jid:remove_resource(From))), BareFrom = jid:remove_resource(From),
Subscribe = [#xmlel{name = <<"subscribe">>, xmpp:make_iq_result(
attrs = [{<<"node">>, Node}]} || Node <- Nodes], IQ, #mix_join{jid = BareFrom, subscribe = Nodes});
IQ#iq{type = result,
sub_el = [#xmlel{name = <<"join">>,
attrs = [{<<"jid">>, LFrom_s},
{<<"xmlns">>, ?NS_MIX_0}],
children = Subscribe}]};
{error, Err} -> {error, Err} ->
IQ#iq{type = error, sub_el = [SubEl, Err]} xmpp:make_error(IQ, Err)
end; end;
{error, Err} -> {error, Err} ->
IQ#iq{type = error, sub_el = [SubEl, Err]} xmpp:make_error(IQ, Err)
end; end;
process_iq(From, To, process_iq(#iq{type = set, from = From, to = To,
#iq{type = set, sub_el = #xmlel{name = <<"leave">>} = SubEl} = IQ) -> sub_els = [#mix_leave{}]} = IQ) ->
case delete_participant(From, To) of case delete_participant(From, To) of
{result, _} -> {result, _} ->
case unsubscribe_nodes(From, To, ?NODES) of case unsubscribe_nodes(From, To, ?NODES) of
{result, _} -> {result, _} ->
IQ#iq{type = result, sub_el = []}; xmpp:make_iq_result(IQ);
{error, Err} -> {error, Err} ->
IQ#iq{type = error, sub_el = [SubEl, Err]} xmpp:make_error(IQ, Err)
end; end;
{error, Err} -> {error, Err} ->
IQ#iq{type = error, sub_el = [SubEl, Err]} xmpp:make_error(IQ, Err)
end; end;
process_iq(_From, _To, #iq{sub_el = SubEl, lang = Lang} = IQ) -> process_iq(#iq{lang = Lang} = IQ) ->
Txt = <<"Unsupported MIX query">>, Txt = <<"Unsupported MIX query">>,
IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}. xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang)).
%%%=================================================================== %%%===================================================================
%%% gen_server callbacks %%% gen_server callbacks
@ -185,8 +159,8 @@ handle_info({route, From, To, Packet}, State) ->
try try
?ERROR_MSG("failed to route packet ~p from '~s' to '~s': ~p", ?ERROR_MSG("failed to route packet ~p from '~s' to '~s': ~p",
[Packet, jid:to_string(From), jid:to_string(To), Err]), [Packet, jid:to_string(From), jid:to_string(To), Err]),
ErrPkt = jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR), Error = xmpp:err_internal_server_error(),
ejabberd_router:route_error(To, From, ErrPkt, Packet) ejabberd_router:route_error(To, From, Packet, Error)
catch _:_ -> catch _:_ ->
ok ok
end; end;
@ -220,20 +194,11 @@ code_change(_OldVsn, State, _Extra) ->
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions
%%%=================================================================== %%%===================================================================
do_route(_State, From, To, #xmlel{name = <<"iq">>} = Packet) -> do_route(_State, From, To, #iq{} = Packet) ->
if To#jid.luser == <<"">> -> ejabberd_router:process_iq(From, To, Packet);
ejabberd_local:process_iq(From, To, Packet); do_route(_State, From, To, #presence{type = unavailable})
true ->
ejabberd_sm:process_iq(From, To, Packet)
end;
do_route(_State, From, To, #xmlel{name = <<"presence">>} = Packet)
when To#jid.luser /= <<"">> -> when To#jid.luser /= <<"">> ->
case fxml:get_tag_attr_s(<<"type">>, Packet) of delete_presence(From, To);
<<"unavailable">> ->
delete_presence(From, To);
_ ->
ok
end;
do_route(_State, _From, _To, _Packet) -> do_route(_State, _From, _To, _Packet) ->
ok. ok.
@ -284,15 +249,14 @@ unsubscribe_nodes(From, To, Nodes) ->
end, {result, []}, Nodes). end, {result, []}, Nodes).
publish_participant(From, To) -> publish_participant(From, To) ->
LFrom = jid:tolower(jid:remove_resource(From)), BareFrom = jid:remove_resource(From),
LFrom = jid:tolower(BareFrom),
LTo = jid:tolower(jid:remove_resource(To)), LTo = jid:tolower(jid:remove_resource(To)),
Participant = #xmlel{name = <<"participant">>, Participant = #mix_participant{jid = BareFrom},
attrs = [{<<"xmlns">>, ?NS_MIX_0},
{<<"jid">>, jid:to_string(LFrom)}]},
ItemID = p1_sha:sha(jid:to_string(LFrom)), ItemID = p1_sha:sha(jid:to_string(LFrom)),
mod_pubsub:publish_item( mod_pubsub:publish_item(
LTo, To#jid.lserver, ?NS_MIX_NODES_PARTICIPANTS, LTo, To#jid.lserver, ?NS_MIX_NODES_PARTICIPANTS,
From, ItemID, [Participant]). From, ItemID, [xmpp:encode(Participant)]).
delete_presence(From, To) -> delete_presence(From, To) ->
LFrom = jid:tolower(From), LFrom = jid:tolower(From),
@ -300,8 +264,8 @@ delete_presence(From, To) ->
case mod_pubsub:get_items(LTo, ?NS_MIX_NODES_PRESENCE) of case mod_pubsub:get_items(LTo, ?NS_MIX_NODES_PRESENCE) of
Items when is_list(Items) -> Items when is_list(Items) ->
lists:foreach( lists:foreach(
fun(#pubsub_item{modification = {_, LJID}, fun({pubsub_item, {ItemID, _}, _, {_, LJID}, _})
itemid = {ItemID, _}}) when LJID == LFrom -> when LJID == LFrom ->
delete_item(From, To, ?NS_MIX_NODES_PRESENCE, ItemID); delete_item(From, To, ?NS_MIX_NODES_PRESENCE, ItemID);
(_) -> (_) ->
ok ok

View File

@ -1110,8 +1110,9 @@ change_stanzaid(ToJID, #iq{id = PreviousId} = Packet) ->
-spec decide_fate_message(message(), jid(), state()) -> -spec decide_fate_message(message(), jid(), state()) ->
continue_delivery | forget_message | continue_delivery | forget_message |
{expulse_sender, binary()}. {expulse_sender, binary()}.
decide_fate_message(#message{type = error, error = Err}, decide_fate_message(#message{type = error} = Msg,
From, StateData) -> From, StateData) ->
Err = xmpp:get_error(Msg),
PD = case check_error_kick(Err) of PD = case check_error_kick(Err) of
%% If this is an error stanza and its condition matches a criteria %% If this is an error stanza and its condition matches a criteria
true -> true ->

View File

@ -88,10 +88,10 @@ make_iq_result(#iq{type = Type, from = From, to = To} = IQ, El)
end, end,
IQ#iq{type = result, to = From, from = To, sub_els = SubEls}. IQ#iq{type = result, to = From, from = To, sub_els = SubEls}.
-spec make_error(message(), error()) -> message(); -spec make_error(message(), error() | xmlel()) -> message();
(presence(), error()) -> presence(); (presence(), error() | xmlel()) -> presence();
(iq(), error()) -> iq(); (iq(), error() | xmlel()) -> iq();
(xmlel(), error()) -> xmlel(). (xmlel(), error() | xmlel()) -> xmlel().
make_error(#message{type = Type, from = From, to = To, sub_els = Els} = Msg, make_error(#message{type = Type, from = From, to = To, sub_els = Els} = Msg,
Err) when Type /= error -> Err) when Type /= error ->
Msg#message{type = error, from = To, to = From, sub_els = Els ++ [Err]}; Msg#message{type = error, from = To, to = From, sub_els = Els ++ [Err]};
@ -159,9 +159,11 @@ get_to(#message{to = J}) -> J;
get_to(#presence{to = J}) -> J. get_to(#presence{to = J}) -> J.
-spec get_error(iq() | message() | presence()) -> undefined | error(). -spec get_error(iq() | message() | presence()) -> undefined | error().
get_error(#iq{error = E}) -> E; get_error(Stanza) ->
get_error(#message{error = E}) -> E; case get_subtag(Stanza, #error{}) of
get_error(#presence{error = E}) -> E. false -> undefined;
Error -> Error
end.
-spec get_els(iq() | message() | presence()) -> [xmpp_element() | xmlel()]; -spec get_els(iq() | message() | presence()) -> [xmpp_element() | xmlel()];
(xmlel()) -> [xmlel()]. (xmlel()) -> [xmlel()].
@ -215,9 +217,7 @@ set_from_to(#presence{} = Pres, F, T) -> Pres#presence{from = F, to = T}.
-spec set_error(iq(), error()) -> iq(); -spec set_error(iq(), error()) -> iq();
(message(), error()) -> message(); (message(), error()) -> message();
(presence(), error()) -> presence(). (presence(), error()) -> presence().
set_error(#iq{} = IQ, E) -> IQ#iq{error = E}; set_error(Stanza, E) -> set_subtag(Stanza, E).
set_error(#message{} = Msg, E) -> Msg#message{error = E};
set_error(#presence{} = Pres, E) -> Pres#presence{error = E}.
-spec set_els(iq(), [xmpp_element() | xmlel()]) -> iq(); -spec set_els(iq(), [xmpp_element() | xmlel()]) -> iq();
(message(), [xmpp_element() | xmlel()]) -> message(); (message(), [xmpp_element() | xmlel()]) -> message();

File diff suppressed because it is too large Load Diff

View File

@ -316,8 +316,7 @@
-xml(iq, -xml(iq,
#elem{name = <<"iq">>, #elem{name = <<"iq">>,
xmlns = <<"jabber:client">>, xmlns = <<"jabber:client">>,
result = {iq, '$id', '$type', '$lang', '$from', '$to', result = {iq, '$id', '$type', '$lang', '$from', '$to', '$_els'},
'$error', '$_els'},
attrs = [#attr{name = <<"id">>, attrs = [#attr{name = <<"id">>,
required = true}, required = true},
#attr{name = <<"type">>, #attr{name = <<"type">>,
@ -331,8 +330,7 @@
dec = {dec_jid, []}, dec = {dec_jid, []},
enc = {enc_jid, []}}, enc = {enc_jid, []}},
#attr{name = <<"xml:lang">>, #attr{name = <<"xml:lang">>,
label = '$lang'}], label = '$lang'}]}).
refs = [#ref{name = error, min = 0, max = 1, label = '$error'}]}).
-xml(message_subject, -xml(message_subject,
#elem{name = <<"subject">>, #elem{name = <<"subject">>,
@ -357,7 +355,7 @@
#elem{name = <<"message">>, #elem{name = <<"message">>,
xmlns = <<"jabber:client">>, xmlns = <<"jabber:client">>,
result = {message, '$id', '$type', '$lang', '$from', '$to', result = {message, '$id', '$type', '$lang', '$from', '$to',
'$subject', '$body', '$thread', '$error', '$_els'}, '$subject', '$body', '$thread', '$_els'},
attrs = [#attr{name = <<"id">>}, attrs = [#attr{name = <<"id">>},
#attr{name = <<"type">>, #attr{name = <<"type">>,
default = normal, default = normal,
@ -372,8 +370,7 @@
enc = {enc_jid, []}}, enc = {enc_jid, []}},
#attr{name = <<"xml:lang">>, #attr{name = <<"xml:lang">>,
label = '$lang'}], label = '$lang'}],
refs = [#ref{name = error, min = 0, max = 1, label = '$error'}, refs = [#ref{name = message_subject, label = '$subject'},
#ref{name = message_subject, label = '$subject'},
#ref{name = message_thread, min = 0, max = 1, label = '$thread'}, #ref{name = message_thread, min = 0, max = 1, label = '$thread'},
#ref{name = message_body, label = '$body'}]}). #ref{name = message_body, label = '$body'}]}).
@ -403,7 +400,7 @@
#elem{name = <<"presence">>, #elem{name = <<"presence">>,
xmlns = <<"jabber:client">>, xmlns = <<"jabber:client">>,
result = {presence, '$id', '$type', '$lang', '$from', '$to', result = {presence, '$id', '$type', '$lang', '$from', '$to',
'$show', '$status', '$priority', '$error', '$_els'}, '$show', '$status', '$priority', '$_els'},
attrs = [#attr{name = <<"id">>}, attrs = [#attr{name = <<"id">>},
#attr{name = <<"type">>, #attr{name = <<"type">>,
default = available, default = available,
@ -419,8 +416,7 @@
enc = {enc_jid, []}}, enc = {enc_jid, []}},
#attr{name = <<"xml:lang">>, #attr{name = <<"xml:lang">>,
label = '$lang'}], label = '$lang'}],
refs = [#ref{name = error, min = 0, max = 1, label = '$error'}, refs = [#ref{name = presence_show, min = 0, max = 1, label = '$show'},
#ref{name = presence_show, min = 0, max = 1, label = '$show'},
#ref{name = presence_status, label = '$status'}, #ref{name = presence_status, label = '$status'},
#ref{name = presence_priority, min = 0, max = 1, #ref{name = presence_priority, min = 0, max = 1,
label = '$priority'}]}). label = '$priority'}]}).
@ -531,7 +527,7 @@
-xml(error, -xml(error,
#elem{name = <<"error">>, #elem{name = <<"error">>,
xmlns = <<"jabber:client">>, xmlns = <<"jabber:client">>,
result = {error, '$type', '$code', '$by', '$reason', '$text'}, result = {error, '$type', '$code', '$by', '$reason', '$text', '$_els'},
attrs = [#attr{name = <<"type">>, attrs = [#attr{name = <<"type">>,
label = '$type', label = '$type',
required = true, required = true,
@ -2880,8 +2876,7 @@
-xml(db_result, -xml(db_result,
#elem{name = <<"db:result">>, #elem{name = <<"db:result">>,
xmlns = <<"jabber:client">>, xmlns = <<"jabber:client">>,
result = {db_result, '$from', '$to', '$type', '$key', '$error'}, result = {db_result, '$from', '$to', '$type', '$key', '$_els'},
refs = [#ref{name = error, min = 0, max = 1}],
cdata = #cdata{default = <<"">>, label = '$key'}, cdata = #cdata{default = <<"">>, label = '$key'},
attrs = [#attr{name = <<"from">>, required = true, attrs = [#attr{name = <<"from">>, required = true,
dec = {dec_jid, []}, enc = {enc_jid, []}}, dec = {dec_jid, []}, enc = {enc_jid, []}},
@ -2894,8 +2889,7 @@
-xml(db_verify, -xml(db_verify,
#elem{name = <<"db:verify">>, #elem{name = <<"db:verify">>,
xmlns = <<"jabber:client">>, xmlns = <<"jabber:client">>,
result = {db_verify, '$from', '$to', '$id', '$type', '$key', '$error'}, result = {db_verify, '$from', '$to', '$id', '$type', '$key', '$_els'},
refs = [#ref{name = error, min = 0, max = 1}],
cdata = #cdata{default = <<"">>, label = '$key'}, cdata = #cdata{default = <<"">>, label = '$key'},
attrs = [#attr{name = <<"from">>, required = true, attrs = [#attr{name = <<"from">>, required = true,
dec = {dec_jid, []}, enc = {enc_jid, []}}, dec = {dec_jid, []}, enc = {enc_jid, []}},