From 9a0b951855c649a2aeb262389d7479f42067d86f Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov <ekhramtsov@process-one.net> Date: Thu, 30 Oct 2014 23:54:02 +0300 Subject: [PATCH] Add tests for mod_vcard_xupdate --- test/ejabberd_SUITE.erl | 68 +++++++++++++++++++--- test/ejabberd_SUITE_data/ejabberd.yml | 8 +++ tools/xmpp_codec.erl | 84 +++++++++++++++++++++++++++ tools/xmpp_codec.hrl | 2 + tools/xmpp_codec.spec | 12 ++++ 5 files changed, 165 insertions(+), 9 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 471265c59..bb39795ea 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -210,6 +210,8 @@ db_tests(riak) -> [muc_master, muc_slave]}, {test_announce, [sequence], [announce_master, announce_slave]}, + {test_vcard_xupdate, [parallel], + [vcard_xupdate_master, vcard_xupdate_slave]}, {test_roster_remove, [parallel], [roster_remove_master, roster_remove_slave]}]; @@ -243,6 +245,8 @@ db_tests(mnesia) -> [muc_master, muc_slave]}, {test_announce, [sequence], [announce_master, announce_slave]}, + {test_vcard_xupdate, [parallel], + [vcard_xupdate_master, vcard_xupdate_slave]}, {test_roster_remove, [parallel], [roster_remove_master, roster_remove_slave]}]; @@ -273,6 +277,8 @@ db_tests(_) -> [muc_master, muc_slave]}, {test_announce, [sequence], [announce_master, announce_slave]}, + {test_vcard_xupdate, [parallel], + [vcard_xupdate_master, vcard_xupdate_slave]}, {test_roster_remove, [parallel], [roster_remove_master, roster_remove_slave]}]. @@ -722,6 +728,42 @@ vcard_get(Config) -> send_recv(Config, #iq{type = get, sub_els = [#vcard{}]}), disconnect(Config). +vcard_xupdate_master(Config) -> + Img = <<137, "PNG\r\n", 26, $\n>>, + ImgHash = p1_sha:sha(Img), + MyJID = my_jid(Config), + Peer = ?config(slave, Config), + wait_for_slave(Config), + send(Config, #presence{}), + ?recv2(#presence{from = MyJID, type = undefined}, + #presence{from = Peer, type = undefined}), + VCard = #vcard{photo = #vcard_photo{type = <<"image/png">>, binval = Img}}, + I1 = send(Config, #iq{type = set, sub_els = [VCard]}), + ?recv2(#iq{type = result, sub_els = [], id = I1}, + #presence{from = MyJID, type = undefined, + sub_els = [#vcard_xupdate{photo = ImgHash}]}), + I2 = send(Config, #iq{type = set, sub_els = [#vcard{}]}), + ?recv3(#iq{type = result, sub_els = [], id = I2}, + #presence{from = MyJID, type = undefined, + sub_els = [#vcard_xupdate{photo = undefined}]}, + #presence{from = Peer, type = unavailable}), + disconnect(Config). + +vcard_xupdate_slave(Config) -> + Img = <<137, "PNG\r\n", 26, $\n>>, + ImgHash = p1_sha:sha(Img), + MyJID = my_jid(Config), + Peer = ?config(master, Config), + send(Config, #presence{}), + #presence{from = MyJID, type = undefined} = recv(), + wait_for_master(Config), + #presence{from = Peer, type = undefined} = recv(), + #presence{from = Peer, type = undefined, + sub_els = [#vcard_xupdate{photo = ImgHash}]} = recv(), + #presence{from = Peer, type = undefined, + sub_els = [#vcard_xupdate{photo = undefined}]} = recv(), + disconnect(Config). + stats(Config) -> #iq{type = result, sub_els = [#stats{stat = Stats}]} = send_recv(Config, #iq{type = get, sub_els = [#stats{}], @@ -1018,7 +1060,8 @@ muc_master(Config) -> %% As this is the newly created room, we receive only the 2nd stanza. #presence{ from = MyNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ status_codes = Codes, items = [#muc_item{role = moderator, jid = MyJID, @@ -1087,7 +1130,8 @@ muc_master(Config) -> [#muc_invite{to = PeerJID}]}]}), %% Peer is joining #presence{from = PeerNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ items = [#muc_item{role = visitor, jid = PeerJID, affiliation = none}]}]} = recv(), @@ -1120,7 +1164,8 @@ muc_master(Config) -> fields = ReplyVoiceReqFs}]}), %% Peer is becoming a participant #presence{from = PeerNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ items = [#muc_item{role = participant, jid = PeerJID, affiliation = none}]}]} = recv(), @@ -1138,7 +1183,8 @@ muc_master(Config) -> affiliation = member}]}]}), %% Peer became a member #presence{from = PeerNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ items = [#muc_item{affiliation = member, jid = PeerJID, role = participant}]}]} = recv(), @@ -1155,7 +1201,7 @@ muc_master(Config) -> role = none}]}]}), %% Got notification the peer is kicked %% 307 -> Inform user that he or she has been kicked from the room - #presence{from = PeerNickJID, + #presence{from = PeerNickJID, type = unavailable, sub_els = [#muc_user{ status_codes = [307], items = [#muc_item{affiliation = member, @@ -1213,14 +1259,16 @@ muc_slave(Config) -> %% First presence is from the participant, i.e. from the peer #presence{ from = PeerNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ status_codes = [], items = [#muc_item{role = moderator, affiliation = owner}]}]} = recv(), %% The next is the self-presence (code 110 means it) #presence{ from = MyNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ status_codes = [110], items = [#muc_item{role = visitor, affiliation = none}]}]} = recv(), @@ -1251,7 +1299,8 @@ muc_slave(Config) -> send(Config, #message{to = Room, sub_els = [VoiceReq]}), %% Becoming a participant #presence{from = MyNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ items = [#muc_item{role = participant, affiliation = none}]}]} = recv(), %% Sending private message to the peer @@ -1259,7 +1308,8 @@ muc_slave(Config) -> body = [#text{data = Subject}]}), %% Becoming a member #presence{from = MyNickJID, - sub_els = [#muc_user{ + sub_els = [#vcard_xupdate{}, + #muc_user{ items = [#muc_item{role = participant, affiliation = member}]}]} = recv(), %% Retrieving a member list diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 597ba5be7..9bd8a8b0a 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -40,6 +40,8 @@ host_config: db_type: odbc mod_vcard: db_type: odbc + mod_vcard_xupdate: + db_type: odbc mod_adhoc: [] mod_configure: [] mod_disco: [] @@ -94,6 +96,8 @@ Welcome to this XMPP server." db_type: odbc mod_vcard: db_type: odbc + mod_vcard_xupdate: + db_type: odbc mod_adhoc: [] mod_configure: [] mod_disco: [] @@ -141,6 +145,8 @@ Welcome to this XMPP server." db_type: internal mod_vcard: db_type: internal + mod_vcard_xupdate: + db_type: internal mod_carboncopy: db_type: internal mod_client_state: @@ -185,6 +191,8 @@ Welcome to this XMPP server." db_type: riak mod_vcard: db_type: riak + mod_vcard_xupdate: + db_type: riak mod_adhoc: [] mod_configure: [] mod_disco: [] diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 58749af28..1d5cd88e0 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -287,6 +287,12 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> {<<"required">>, <<"jabber:x:data">>} -> decode_xdata_field_required(<<"jabber:x:data">>, IgnoreEls, _el); + {<<"x">>, <<"vcard-temp:x:update">>} -> + decode_vcard_xupdate(<<"vcard-temp:x:update">>, + IgnoreEls, _el); + {<<"photo">>, <<"vcard-temp:x:update">>} -> + decode_vcard_xupdate_photo(<<"vcard-temp:x:update">>, + IgnoreEls, _el); {<<"vCard">>, <<"vcard-temp">>} -> decode_vcard(<<"vcard-temp">>, IgnoreEls, _el); {<<"CLASS">>, <<"vcard-temp">>} -> @@ -1182,6 +1188,8 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) -> {<<"value">>, <<"jabber:x:data">>} -> true; {<<"desc">>, <<"jabber:x:data">>} -> true; {<<"required">>, <<"jabber:x:data">>} -> true; + {<<"x">>, <<"vcard-temp:x:update">>} -> true; + {<<"photo">>, <<"vcard-temp:x:update">>} -> true; {<<"vCard">>, <<"vcard-temp">>} -> true; {<<"CLASS">>, <<"vcard-temp">>} -> true; {<<"CATEGORIES">>, <<"vcard-temp">>} -> true; @@ -1841,6 +1849,9 @@ encode({vcard, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Vcard) -> encode_vcard(Vcard, [{<<"xmlns">>, <<"vcard-temp">>}]); +encode({vcard_xupdate, _} = X) -> + encode_vcard_xupdate(X, + [{<<"xmlns">>, <<"vcard-temp:x:update">>}]); encode({xdata_field, _, _, _, _, _, _, _} = Field) -> encode_xdata_field(Field, [{<<"xmlns">>, <<"jabber:x:data">>}]); @@ -2126,6 +2137,7 @@ get_ns({vcard_key, _, _}) -> <<"vcard-temp">>; get_ns({vcard, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> <<"vcard-temp">>; +get_ns({vcard_xupdate, _}) -> <<"vcard-temp:x:update">>; get_ns({xdata_field, _, _, _, _, _, _, _}) -> <<"jabber:x:data">>; get_ns({xdata, _, _, _, _, _, _}) -> @@ -2339,6 +2351,7 @@ pp(vcard, 29) -> email, jabberid, mailer, tz, geo, title, role, logo, org, categories, note, prodid, rev, sort_string, sound, uid, url, class, key, desc]; +pp(vcard_xupdate, 1) -> [photo]; pp(xdata_field, 7) -> [label, type, var, required, desc, values, options]; pp(xdata, 6) -> @@ -7515,6 +7528,77 @@ encode_xdata_field_required(true, _xmlns_attrs) -> _attrs = _xmlns_attrs, {xmlel, <<"required">>, _attrs, _els}. +decode_vcard_xupdate(__TopXMLNS, __IgnoreEls, + {xmlel, <<"x">>, _attrs, _els}) -> + Photo = decode_vcard_xupdate_els(__TopXMLNS, + __IgnoreEls, _els, undefined), + {vcard_xupdate, Photo}. + +decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, [], + Photo) -> + Photo; +decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"photo">>, _attrs, _} = _el | _els], + Photo) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els, + decode_vcard_xupdate_photo(__TopXMLNS, + __IgnoreEls, + _el)); + true -> + decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els, + Photo) + end; +decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Photo) -> + decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els, + Photo). + +encode_vcard_xupdate({vcard_xupdate, Photo}, + _xmlns_attrs) -> + _els = + lists:reverse('encode_vcard_xupdate_$photo'(Photo, [])), + _attrs = _xmlns_attrs, + {xmlel, <<"x">>, _attrs, _els}. + +'encode_vcard_xupdate_$photo'(undefined, _acc) -> _acc; +'encode_vcard_xupdate_$photo'(Photo, _acc) -> + [encode_vcard_xupdate_photo(Photo, []) | _acc]. + +decode_vcard_xupdate_photo(__TopXMLNS, __IgnoreEls, + {xmlel, <<"photo">>, _attrs, _els}) -> + Cdata = decode_vcard_xupdate_photo_els(__TopXMLNS, + __IgnoreEls, _els, <<>>), + Cdata. + +decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, + [], Cdata) -> + decode_vcard_xupdate_photo_cdata(__TopXMLNS, Cdata); +decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, + _els, <<Cdata/binary, _data/binary>>); +decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Cdata) -> + decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, + _els, Cdata). + +encode_vcard_xupdate_photo(Cdata, _xmlns_attrs) -> + _els = encode_vcard_xupdate_photo_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"photo">>, _attrs, _els}. + +decode_vcard_xupdate_photo_cdata(__TopXMLNS, <<>>) -> + undefined; +decode_vcard_xupdate_photo_cdata(__TopXMLNS, _val) -> + _val. + +encode_vcard_xupdate_photo_cdata(undefined, _acc) -> + _acc; +encode_vcard_xupdate_photo_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + decode_vcard(__TopXMLNS, __IgnoreEls, {xmlel, <<"vCard">>, _attrs, _els}) -> {Mailer, Adr, Class, Categories, Desc, Uid, Prodid, diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index c421aa1d6..4098a7fd6 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -252,6 +252,8 @@ status_codes = [] :: [pos_integer()], password :: binary()}). +-record(vcard_xupdate, {photo :: binary()}). + -record(carbons_disable, {}). -record(bytestreams, {hosts = [] :: [#streamhost{}], diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index f8ed72af9..61f438cbe 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -1486,6 +1486,18 @@ label = '$categories'}, #ref{name = vcard_CLASS, min = 0, max = 1, label = '$class'}]}). +-xml(vcard_xupdate_photo, + #elem{name = <<"photo">>, + xmlns = <<"vcard-temp:x:update">>, + result = '$cdata'}). + +-xml(vcard_xupdate, + #elem{name = <<"x">>, + xmlns = <<"vcard-temp:x:update">>, + result = {vcard_xupdate, '$photo'}, + refs = [#ref{name = vcard_xupdate_photo, min = 0, max = 1, + label = '$photo'}]}). + -xml(xdata_field_required, #elem{name = <<"required">>, xmlns = <<"jabber:x:data">>, -- 2.40.0