Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/processone/ejabberd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/ejabberd_SUITE.erl68
-rw-r--r--test/ejabberd_SUITE_data/ejabberd.yml8
-rw-r--r--tools/xmpp_codec.erl84
-rw-r--r--tools/xmpp_codec.hrl2
-rw-r--r--tools/xmpp_codec.spec12
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">>,