Packages
ejabberd
16.6.2
26.4.0
26.3.0
26.2.0
26.1.0
25.10.0
25.8.0
25.7.0
25.4.0
25.3.0
24.12.0
24.10.0
24.7.0
24.6.0
24.2.6
23.10.0
23.4.0
23.1.0
22.10.0
22.5.0
21.12.0
21.7.0
21.4.0
21.1.0
20.12.0
20.7.0
20.4.0
20.3.0
20.2.0
20.1.0
19.9.1
19.9.0
19.8.0
19.5.0
19.2.0
18.12.1
18.12.0
18.6.0
18.4.0
18.3.0
18.1.0
17.11.0
17.9.0
17.6.0
17.3.0
17.1.0
16.12.0-beta1
16.9.0
16.8.0
16.6.2
16.6.1
16.6.0
16.4.1
16.4.0
16.3.0
16.2.0
16.1.0-beta1
Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
Current section
Files
Jump to
Current section
Files
src/mod_vcard_xupdate.erl
%%%----------------------------------------------------------------------
%%% File : mod_vcard_xupdate.erl
%%% Author : Igor Goryachev <igor@goryachev.org>
%%% Purpose : Add avatar hash in presence on behalf of client (XEP-0153)
%%% Created : 9 Mar 2007 by Igor Goryachev <igor@goryachev.org>
%%%----------------------------------------------------------------------
-module(mod_vcard_xupdate).
-behaviour(gen_mod).
%% gen_mod callbacks
-export([start/2, stop/1]).
-export([update_presence/3, vcard_set/3, export/1,
import/1, import/3, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("mod_vcard_xupdate.hrl").
-include("jlib.hrl").
-callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #vcard_xupdate{}) -> ok | pass.
-callback add_xupdate(binary(), binary(), binary()) -> {atomic, any()}.
-callback get_xupdate(binary(), binary()) -> binary() | undefined.
-callback remove_xupdate(binary(), binary()) -> {atomic, any()}.
%%====================================================================
%% gen_mod callbacks
%%====================================================================
start(Host, Opts) ->
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
Mod:init(Host, Opts),
ejabberd_hooks:add(c2s_update_presence, Host, ?MODULE,
update_presence, 100),
ejabberd_hooks:add(vcard_set, Host, ?MODULE, vcard_set,
100),
ok.
stop(Host) ->
ejabberd_hooks:delete(c2s_update_presence, Host,
?MODULE, update_presence, 100),
ejabberd_hooks:delete(vcard_set, Host, ?MODULE,
vcard_set, 100),
ok.
%%====================================================================
%% Hooks
%%====================================================================
update_presence(#xmlel{name = <<"presence">>, attrs = Attrs} = Packet,
User, Host) ->
case fxml:get_attr_s(<<"type">>, Attrs) of
<<>> -> presence_with_xupdate(Packet, User, Host);
_ -> Packet
end;
update_presence(Packet, _User, _Host) -> Packet.
vcard_set(LUser, LServer, VCARD) ->
US = {LUser, LServer},
case fxml:get_path_s(VCARD,
[{elem, <<"PHOTO">>}, {elem, <<"BINVAL">>}, cdata])
of
<<>> -> remove_xupdate(LUser, LServer);
BinVal ->
add_xupdate(LUser, LServer,
p1_sha:sha(jlib:decode_base64(BinVal)))
end,
ejabberd_sm:force_update_presence(US).
%%====================================================================
%% Storage
%%====================================================================
add_xupdate(LUser, LServer, Hash) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:add_xupdate(LUser, LServer, Hash).
get_xupdate(LUser, LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:get_xupdate(LUser, LServer).
remove_xupdate(LUser, LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:remove_xupdate(LUser, LServer).
%%%----------------------------------------------------------------------
%%% Presence stanza rebuilding
%%%----------------------------------------------------------------------
presence_with_xupdate(#xmlel{name = <<"presence">>,
attrs = Attrs, children = Els},
User, Host) ->
XPhotoEl = build_xphotoel(User, Host),
Els2 = presence_with_xupdate2(Els, [], XPhotoEl),
#xmlel{name = <<"presence">>, attrs = Attrs,
children = Els2}.
presence_with_xupdate2([], Els2, XPhotoEl) ->
lists:reverse([XPhotoEl | Els2]);
%% This clause assumes that the x element contains only the XMLNS attribute:
presence_with_xupdate2([#xmlel{name = <<"x">>,
attrs = [{<<"xmlns">>, ?NS_VCARD_UPDATE}]}
| Els],
Els2, XPhotoEl) ->
presence_with_xupdate2(Els, Els2, XPhotoEl);
presence_with_xupdate2([El | Els], Els2, XPhotoEl) ->
presence_with_xupdate2(Els, [El | Els2], XPhotoEl).
build_xphotoel(User, Host) ->
Hash = get_xupdate(User, Host),
PhotoSubEls = case Hash of
Hash when is_binary(Hash) -> [{xmlcdata, Hash}];
_ -> []
end,
PhotoEl = [#xmlel{name = <<"photo">>, attrs = [],
children = PhotoSubEls}],
#xmlel{name = <<"x">>,
attrs = [{<<"xmlns">>, ?NS_VCARD_UPDATE}],
children = PhotoEl}.
export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer).
import(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:import(LServer).
import(LServer, DBType, LA) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, LA).
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(_) -> [db_type].