Update to work with recent ejabberd
TODO: - Registration does not support enabling/disabling different features - Avatar does not work at all - Check all he configurable options are really used
This commit is contained in:
parent
cd54f70943
commit
721ca125ea
|
@ -12,51 +12,48 @@
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start_link/2,
|
-export([start/2,
|
||||||
start/2,
|
|
||||||
stop/1,
|
stop/1,
|
||||||
remove_user/2,
|
remove_user/2,
|
||||||
web_menu_host/3, web_page_host/3,
|
web_menu_host/3, web_page_host/3,
|
||||||
|
process_disco_info/1,
|
||||||
|
process_disco_items/1,
|
||||||
|
process_vcard/1,
|
||||||
|
process_register/1,
|
||||||
process/2
|
process/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3]).
|
terminate/2, code_change/3,
|
||||||
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([start_link/0]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("ejabberd_web_admin.hrl").
|
-include("ejabberd_web_admin.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
|
|
||||||
-record(webpresence, {us, ridurl = false, jidurl = false, xml = false, avatar = false, js = false, text = false, icon = "---"}).
|
-record(webpresence, {us, ridurl = false, jidurl = false, xml = false, avatar = false, js = false, text = false, icon = "jsf-text"}).
|
||||||
-record(state, {host, server_host, base_url, access}).
|
-record(state, {host, server_host, base_url, access}).
|
||||||
-record(presence, {resource, show, priority, status}).
|
-record(presence2, {resource, show, priority, status}).
|
||||||
|
|
||||||
%% Copied from ejabberd_sm.erl
|
%% Copied from ejabberd_sm.erl
|
||||||
-record(session, {sid, usr, us, priority, info}).
|
-record(session, {sid, usr, us, priority, info}).
|
||||||
|
|
||||||
-define(PROCNAME, ejabberd_mod_webpresence).
|
|
||||||
-define(PIXMAPS_DIR, <<"pixmaps">>).
|
-define(PIXMAPS_DIR, <<"pixmaps">>).
|
||||||
-define(AUTO_ACL, webpresence_auto).
|
-define(AUTO_ACL, webpresence_auto).
|
||||||
|
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% API
|
%% API
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
%%--------------------------------------------------------------------
|
start_link() ->
|
||||||
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
%% Description: Starts the server
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
start_link(Host, Opts) ->
|
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
|
||||||
gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []).
|
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
|
||||||
ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
|
|
||||||
temporary, 1000, worker, [?MODULE]},
|
|
||||||
Default_dir = case code:priv_dir(ejabberd) of
|
Default_dir = case code:priv_dir(ejabberd) of
|
||||||
{error, _} -> ?PIXMAPS_DIR;
|
{error, _} -> ?PIXMAPS_DIR;
|
||||||
Path -> filename:join([Path, ?PIXMAPS_DIR])
|
Path -> filename:join([Path, ?PIXMAPS_DIR])
|
||||||
|
@ -64,13 +61,42 @@ start(Host, Opts) ->
|
||||||
Dir = gen_mod:get_opt(pixmaps_path, Opts, fun(D) -> D end, Default_dir),
|
Dir = gen_mod:get_opt(pixmaps_path, Opts, fun(D) -> D end, Default_dir),
|
||||||
catch ets:new(pixmaps_dirs, [named_table, public]),
|
catch ets:new(pixmaps_dirs, [named_table, public]),
|
||||||
ets:insert(pixmaps_dirs, {directory, Dir}),
|
ets:insert(pixmaps_dirs, {directory, Dir}),
|
||||||
supervisor:start_child(ejabberd_sup, ChildSpec).
|
case gen_mod:start_child(?MODULE, Host, Opts) of
|
||||||
|
{ok, Ref} ->
|
||||||
|
{ok, Ref};
|
||||||
|
{error, {already_started, Ref}} ->
|
||||||
|
{ok, Ref};
|
||||||
|
{error, Reason} ->
|
||||||
|
{error, Reason}
|
||||||
|
end.
|
||||||
|
|
||||||
stop(Host) ->
|
stop(Host) ->
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
Proc = gen_mod:get_module_proc(Host, ?MODULE),
|
||||||
gen_server:call(Proc, stop),
|
gen_server:call(Proc, stop),
|
||||||
supervisor:terminate_child(ejabberd_sup, Proc),
|
gen_mod:stop_child(?MODULE, Host),
|
||||||
supervisor:delete_child(ejabberd_sup, Proc).
|
ok.
|
||||||
|
|
||||||
|
-spec mod_opt_type(atom()) -> fun((term()) -> term()).
|
||||||
|
mod_opt_type(host) -> fun iolist_to_binary/1;
|
||||||
|
mod_opt_type(access) -> fun acl:access_rules_validator/1;
|
||||||
|
mod_opt_type(pixmaps_path) -> fun iolist_to_binary/1;
|
||||||
|
mod_opt_type(port) ->
|
||||||
|
fun(I) when is_integer(I), I>0, I<65536 -> I end;
|
||||||
|
mod_opt_type(path) -> fun iolist_to_binary/1;
|
||||||
|
mod_opt_type(baseurl) -> fun iolist_to_binary/1.
|
||||||
|
|
||||||
|
-spec mod_options(binary()) -> [{atom(), any()}].
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{host, <<"webpresence.@HOST@">>},
|
||||||
|
{access, none},
|
||||||
|
{pixmaps_path, ?PIXMAPS_DIR},
|
||||||
|
{port, 5280},
|
||||||
|
{path, <<"presence">>},
|
||||||
|
{baseurl, iolist_to_binary(io_lib:format(<<"http://~s:5280/presence/">>, [Host]))}].
|
||||||
|
|
||||||
|
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
||||||
|
depends(_Host, _Opts) ->
|
||||||
|
[].
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
|
@ -96,7 +122,8 @@ init([Host, Opts]) ->
|
||||||
BaseURL1 = gen_mod:get_opt(baseurl, Opts, fun(O) -> O end,
|
BaseURL1 = gen_mod:get_opt(baseurl, Opts, fun(O) -> O end,
|
||||||
iolist_to_binary(io_lib:format(<<"http://~s:~p/~s/">>, [Host, Port, Path]))),
|
iolist_to_binary(io_lib:format(<<"http://~s:~p/~s/">>, [Host, Port, Path]))),
|
||||||
BaseURL2 = ejabberd_regexp:greplace(BaseURL1, <<"@HOST@">>, Host),
|
BaseURL2 = ejabberd_regexp:greplace(BaseURL1, <<"@HOST@">>, Host),
|
||||||
ejabberd_router:register_route(MyHost),
|
register_iq_handlers(MyHost),
|
||||||
|
ejabberd_router:register_route(MyHost, Host),
|
||||||
ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50),
|
ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
|
ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
|
||||||
ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, web_page_host, 50),
|
ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, web_page_host, 50),
|
||||||
|
@ -105,6 +132,22 @@ init([Host, Opts]) ->
|
||||||
base_url = BaseURL2,
|
base_url = BaseURL2,
|
||||||
access = Access}}.
|
access = Access}}.
|
||||||
|
|
||||||
|
register_iq_handlers(Host) ->
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_REGISTER,
|
||||||
|
?MODULE, process_register),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
|
||||||
|
?MODULE, process_vcard),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
|
||||||
|
?MODULE, process_disco_info),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
|
||||||
|
?MODULE, process_disco_items).
|
||||||
|
|
||||||
|
unregister_iq_handlers(Host) ->
|
||||||
|
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_REGISTER),
|
||||||
|
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
|
||||||
|
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
|
||||||
|
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
|
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
|
||||||
%% {reply, Reply, State, Timeout} |
|
%% {reply, Reply, State, Timeout} |
|
||||||
|
@ -132,26 +175,19 @@ handle_cast(_Msg, State) ->
|
||||||
%% {stop, Reason, State}
|
%% {stop, Reason, State}
|
||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_info({route, From, To, Packet},
|
handle_info({route, Packet},
|
||||||
#state{host = Host,
|
#state{host = Host,
|
||||||
server_host = ServerHost,
|
server_host = ServerHost,
|
||||||
base_url = BaseURL,
|
base_url = BaseURL,
|
||||||
access = Access} = State) ->
|
access = Access} = State) ->
|
||||||
|
From = xmpp:get_from(Packet),
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
case catch do_route(Host, ServerHost, Access, From, To, Packet, BaseURL) of
|
case catch do_route(Host, ServerHost, Access, From, To, Packet, BaseURL) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("~p", [Reason]);
|
?ERROR_MSG("~p", [Reason]);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
{noreply, State};
|
|
||||||
|
|
||||||
|
|
||||||
handle_info({tell_baseurl, Pid},
|
|
||||||
#state{base_url = BaseURL} = State) ->
|
|
||||||
Pid ! {baseurl_is, BaseURL},
|
|
||||||
{noreply, State};
|
|
||||||
|
|
||||||
handle_info(_Info, State) ->
|
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -163,6 +199,7 @@ handle_info(_Info, State) ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
terminate(_Reason, #state{host = Host}) ->
|
terminate(_Reason, #state{host = Host}) ->
|
||||||
ejabberd_router:unregister_route(Host),
|
ejabberd_router:unregister_route(Host),
|
||||||
|
unregister_iq_handlers(Host),
|
||||||
ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50),
|
ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:delete(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
|
ejabberd_hooks:delete(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
|
||||||
ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, web_page_host, 50),
|
ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, web_page_host, 50),
|
||||||
|
@ -183,100 +220,86 @@ do_route(Host, ServerHost, Access, From, To, Packet, BaseURL) ->
|
||||||
allow ->
|
allow ->
|
||||||
do_route1(Host, From, To, Packet, BaseURL);
|
do_route1(Host, From, To, Packet, BaseURL);
|
||||||
_ ->
|
_ ->
|
||||||
#xmlel{attrs = Attrs} = Packet,
|
Lang = xmpp:get_lang(Packet),
|
||||||
Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs),
|
|
||||||
ErrText = <<"Access denied by service policy">>,
|
ErrText = <<"Access denied by service policy">>,
|
||||||
Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route(To, From, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_route1(Host, From, To, Packet, BaseURL) ->
|
-spec process_vcard(iq()) -> iq().
|
||||||
#xmlel{name = Name, attrs = Attrs} = Packet,
|
process_vcard(#iq{type = get, lang = Lang, sub_els = [#vcard_temp{}]} = IQ) ->
|
||||||
case Name of
|
Desc = translate:translate(Lang, <<"ejabberd Web Presence module">>),
|
||||||
<<"iq">> -> do_route1_iq(Host, From, To, Packet, BaseURL, jlib:iq_query_info(Packet));
|
xmpp:make_iq_result(
|
||||||
_ -> case fxml:get_attr_s(<<"type">>, Attrs) of
|
IQ, #vcard_temp{fn = <<"ejabberd/mod_webpresence">>,
|
||||||
<<"error">> -> ok;
|
url = ?EJABBERD_URI,
|
||||||
<<"result">> -> ok;
|
desc = <<Desc/binary, $\n, ?COPYRIGHT>>});
|
||||||
_ -> Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND),
|
process_vcard(#iq{type = set, lang = Lang} = IQ) ->
|
||||||
ejabberd_router:route(To, From, Err)
|
Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
|
||||||
end
|
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
||||||
|
process_vcard(#iq{lang = Lang} = IQ) ->
|
||||||
|
Txt = <<"No module is handling this query">>,
|
||||||
|
xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang)).
|
||||||
|
|
||||||
|
do_route1(_Host, _From, _To, #iq{} = IQ, _BaseURL) ->
|
||||||
|
ejabberd_local:process_iq(IQ);
|
||||||
|
do_route1(_Host, _From, _To, Packet, _BaseURL) ->
|
||||||
|
case xmpp:get_type(Packet) of
|
||||||
|
error -> ok;
|
||||||
|
result -> ok;
|
||||||
|
_ ->
|
||||||
|
Err = xmpp:err_item_not_found(),
|
||||||
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_route1_iq(_, From, To, _, _,
|
-spec process_register(iq()) -> iq().
|
||||||
#iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} = IQ) ->
|
process_register(#iq{type = get, from = From, to = To, lang = Lang,
|
||||||
SubEl = #xmlel{
|
sub_els = [#register{}]} = IQ) ->
|
||||||
name = <<"query">>,
|
Host = To#jid.lserver,
|
||||||
attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}],
|
ServerHost = ejabberd_router:host_of_route(Host),
|
||||||
children = iq_disco_info(Lang)
|
xmpp:make_iq_result(IQ, iq_get_register_info(Host, From, Lang));
|
||||||
},
|
process_register(#iq{type = set, from = From, to = To,
|
||||||
Res = IQ#iq{type = result, sub_el = [SubEl]},
|
lang = Lang, sub_els = [El = #register{}]} = IQ) ->
|
||||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
Host = To#jid.lserver,
|
||||||
|
ServerHost = ejabberd_router:host_of_route(Host),
|
||||||
|
case process_iq_register_set(ServerHost, Host, From, El, Lang) of
|
||||||
|
{result, Result} ->
|
||||||
|
xmpp:make_iq_result(IQ, Result);
|
||||||
|
{error, Err} ->
|
||||||
|
xmpp:make_error(IQ, Err)
|
||||||
|
end.
|
||||||
|
|
||||||
do_route1_iq(_, _, _, _, _,
|
|
||||||
#iq{type = get, xmlns = ?NS_DISCO_ITEMS}) ->
|
|
||||||
ok;
|
|
||||||
|
|
||||||
do_route1_iq(Host, From, To, _, _,
|
-spec process_disco_info(iq()) -> iq().
|
||||||
#iq{type = get, xmlns = ?NS_REGISTER, lang = Lang} = IQ) ->
|
process_disco_info(#iq{type = set, lang = Lang} = IQ) ->
|
||||||
SubEl = #xmlel{
|
Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
|
||||||
name = <<"query">>,
|
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
||||||
attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}],
|
process_disco_info(#iq{type = get, lang = Lang,
|
||||||
children = iq_get_register_info(Host, From, Lang)
|
sub_els = [#disco_info{node = <<"">>}]} = IQ) ->
|
||||||
},
|
Features = [?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
|
||||||
Res = IQ#iq{type = result, sub_el = [SubEl]},
|
?NS_REGISTER, ?NS_VCARD],
|
||||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
Identity = #identity{category = <<"component">>,
|
||||||
|
type = <<"presence">>,
|
||||||
|
name = translate:translate(Lang, <<"Web Presence">>)},
|
||||||
|
xmpp:make_iq_result(
|
||||||
|
IQ, #disco_info{features = Features,
|
||||||
|
identities = [Identity]});
|
||||||
|
process_disco_info(#iq{type = get, lang = Lang,
|
||||||
|
sub_els = [#disco_info{}]} = IQ) ->
|
||||||
|
xmpp:make_error(IQ, xmpp:err_item_not_found(<<"Node not found">>, Lang));
|
||||||
|
process_disco_info(#iq{lang = Lang} = IQ) ->
|
||||||
|
Txt = <<"No module is handling this query">>,
|
||||||
|
xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang)).
|
||||||
|
|
||||||
do_route1_iq(Host, From, To, Packet, BaseURL,
|
-spec process_disco_items(iq()) -> iq().
|
||||||
#iq{type = set, xmlns = ?NS_REGISTER, lang = Lang, sub_el = SubEl} = IQ) ->
|
process_disco_items(#iq{type = set, lang = Lang} = IQ) ->
|
||||||
case process_iq_register_set(From, SubEl, Host, BaseURL, Lang) of
|
Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
|
||||||
{result, IQRes} ->
|
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
||||||
SubEl2 = #xmlel{
|
process_disco_items(#iq{type = get,
|
||||||
name = <<"query">>,
|
sub_els = [#disco_items{}]} = IQ) ->
|
||||||
attrs = [{<<"xmlns">>, ?NS_REGISTER}],
|
xmpp:make_iq_result(IQ, #disco_items{});
|
||||||
children = IQRes
|
process_disco_items(#iq{lang = Lang} = IQ) ->
|
||||||
},
|
Txt = <<"No module is handling this query">>,
|
||||||
Res = IQ#iq{type = result, sub_el = [SubEl2]},
|
xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang)).
|
||||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
|
||||||
{error, Error} ->
|
|
||||||
Err = jlib:make_error_reply(Packet, Error),
|
|
||||||
ejabberd_router:route(To, From, Err)
|
|
||||||
end;
|
|
||||||
|
|
||||||
do_route1_iq(_Host, From, To, _, _,
|
|
||||||
#iq{type = get, xmlns = ?NS_VCARD = XMLNS} = IQ) ->
|
|
||||||
SubEl = #xmlel{
|
|
||||||
name = <<"vCard">>,
|
|
||||||
attrs = [{<<"xmlns">>, XMLNS}],
|
|
||||||
children = iq_get_vcard()
|
|
||||||
},
|
|
||||||
Res = IQ#iq{type = result, sub_el = [SubEl]},
|
|
||||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
|
||||||
|
|
||||||
do_route1_iq(_Host, From, To, Packet, _, #iq{}) ->
|
|
||||||
Err = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
|
|
||||||
ejabberd_router:route(To, From, Err);
|
|
||||||
|
|
||||||
do_route1_iq(_, _, _, _, _, _) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
iq_disco_info(Lang) ->
|
|
||||||
[#xmlel{
|
|
||||||
name = <<"identity">>,
|
|
||||||
attrs = [{<<"category">>, <<"component">>},
|
|
||||||
{<<"type">>, <<"presence">>},
|
|
||||||
{<<"name">>, ?T(<<"Web Presence">>)}],
|
|
||||||
children = []
|
|
||||||
},
|
|
||||||
#xmlel{
|
|
||||||
name = <<"feature">>,
|
|
||||||
attrs = [{<<"var">>, ?NS_REGISTER}],
|
|
||||||
children = []
|
|
||||||
},
|
|
||||||
#xmlel{
|
|
||||||
name = <<"feature">>,
|
|
||||||
attrs = [{<<"var">>, ?NS_VCARD}],
|
|
||||||
children = []
|
|
||||||
}].
|
|
||||||
|
|
||||||
-define(XFIELDS(Type, Label, Var, Vals),
|
-define(XFIELDS(Type, Label, Var, Vals),
|
||||||
#xmlel{
|
#xmlel{
|
||||||
|
@ -319,124 +342,94 @@ iq_disco_info(Lang) ->
|
||||||
ridurl_out(false) -> <<"false">>;
|
ridurl_out(false) -> <<"false">>;
|
||||||
ridurl_out(Id) when is_binary(Id) -> <<"true">>.
|
ridurl_out(Id) when is_binary(Id) -> <<"true">>.
|
||||||
|
|
||||||
to_bool(<<"false">>) -> false;
|
|
||||||
to_bool(<<"true">>) -> true;
|
|
||||||
to_bool(<<"0">>) -> false;
|
|
||||||
to_bool(<<"1">>) -> true.
|
|
||||||
|
|
||||||
get_pr(LUS) ->
|
get_pr(LUS) ->
|
||||||
case catch mnesia:dirty_read(webpresence, LUS) of
|
case catch mnesia:dirty_read(webpresence, LUS) of
|
||||||
[#webpresence{jidurl = J, ridurl = H, xml = X, avatar = A, js = S, text = T, icon = I}] ->
|
[#webpresence{jidurl = J, ridurl = H, xml = X, avatar = A, js = S, text = T, icon = I}] ->
|
||||||
{J, H, X, A, S, T, I, true};
|
{J, H, X, A, S, T, I, true};
|
||||||
_ ->
|
_ ->
|
||||||
{true, false, false, false, false, false, <<"---">>, false}
|
{true, false, false, false, false, false, <<"">>, false}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_pr_rid(LUS) ->
|
|
||||||
{_, H, _, _, _, _, _, _} = get_pr(LUS),
|
|
||||||
H.
|
|
||||||
|
|
||||||
iq_get_register_info(_Host, From, Lang) ->
|
iq_get_register_info(Host, From, Lang) ->
|
||||||
{LUser, LServer, _} = jlib:jid_tolower(From),
|
LUS = {From#jid.luser, From#jid.lserver},
|
||||||
LUS = {LUser, LServer},
|
{_JidUrl, _RidUrl, _XML, _Avatar, _JS, _Text, Icon, Registered} = get_pr(LUS),
|
||||||
{JidUrl, RidUrl, XML, Avatar, JS, Text, Icon, Registered} = get_pr(LUS),
|
Nick = Icon,
|
||||||
RegisteredXML = case Registered of
|
Title = <<(translate:translate(
|
||||||
true -> [#xmlel{name = <<"registered">>, attrs = [], children = []}];
|
Lang, <<"Web Presence Registration at ">>))/binary, Host/binary>>,
|
||||||
false -> []
|
Inst = translate:translate(Lang, <<"Enter iconset you want to use by default">>),
|
||||||
end,
|
Fields = muc_register:encode([{roomnick, Nick}], Lang),
|
||||||
RegisteredXML ++
|
X = #xdata{type = form, title = Title,
|
||||||
[
|
instructions = [Inst], fields = Fields},
|
||||||
#xmlel{
|
#register{nick = Nick,
|
||||||
name = <<"instructions">>,
|
registered = Registered,
|
||||||
attrs = [],
|
instructions =
|
||||||
children = [{xmlcdata, ?T(<<"You need an x:data capable client to register presence">>)}]
|
translate:translate(
|
||||||
},
|
Lang, <<"You need a client that supports x:data "
|
||||||
#xmlel{
|
"to register to Web Presence">>),
|
||||||
name = <<"x">>,
|
xdata = X}.
|
||||||
attrs = [{<<"xmlns">>, ?NS_XDATA}],
|
|
||||||
children = [
|
|
||||||
#xmlel{
|
|
||||||
name = <<"title">>,
|
|
||||||
attrs = [],
|
|
||||||
children = [{xmlcdata, ?T(<<"Web Presence">>)}]
|
|
||||||
},
|
|
||||||
#xmlel{
|
|
||||||
name = <<"instructions">>,
|
|
||||||
attrs = [],
|
|
||||||
children = [{xmlcdata, ?T(<<"What features do you want to enable?">>)}]
|
|
||||||
},
|
|
||||||
?XFIELDFIXED(?BC([?T(<<"URL Type">>), <<". ">>, ?T(<<"Select one at least">>)])),
|
|
||||||
?XFIELD(<<"boolean">>, <<"Jabber ID">>, <<"jidurl">>, ?ATOM2BINARY(JidUrl)),
|
|
||||||
?XFIELD(<<"boolean">>, <<"Random ID">>, <<"ridurl">>, ridurl_out(RidUrl)),
|
|
||||||
?XFIELDFIXED(?BC([?T(<<"Output Type">>), <<". ">>, ?T(<<"Select one at least">>)])),
|
|
||||||
?XFIELDS(<<"list-single">>, ?T(<<"Icon Theme">>), <<"icon">>,
|
|
||||||
[
|
|
||||||
#xmlel{
|
|
||||||
name = <<"value">>,
|
|
||||||
attrs = [],
|
|
||||||
children = [{xmlcdata, Icon}]
|
|
||||||
},
|
|
||||||
#xmlel{
|
|
||||||
name = <<"option">>,
|
|
||||||
attrs = [{<<"label">>, <<"---">>}],
|
|
||||||
children = [
|
|
||||||
#xmlel{
|
|
||||||
name = <<"value">>,
|
|
||||||
attrs = [],
|
|
||||||
children = [{xmlcdata, <<"---">>}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
] ++ available_themes(xdata)
|
|
||||||
),
|
|
||||||
?XFIELD(<<"boolean">>, <<"XML">>, <<"xml">>, ?ATOM2BINARY(XML)),
|
|
||||||
?XFIELD(<<"boolean">>, <<"JavaScript">>, <<"js">>, ?ATOM2BINARY(JS)),
|
|
||||||
?XFIELD(<<"boolean">>, <<"Text">>, <<"text">>, ?ATOM2BINARY(Text)),
|
|
||||||
?XFIELD(<<"boolean">>, <<"Avatar">>, <<"avatar">>, ?ATOM2BINARY(Avatar))
|
|
||||||
]
|
|
||||||
}
|
|
||||||
].
|
|
||||||
|
|
||||||
%%%% TODO: Check if remote users are allowed to reach here: they should not be allowed
|
process_iq_register_set(ServerHost, Host, From,
|
||||||
iq_set_register_info(From, {Host, JidUrl, RidUrl, XML, Avatar, JS, Text, Icon, _, Lang} = Opts) ->
|
#register{remove = true}, Lang) ->
|
||||||
{LUser, LServer, _} = jlib:jid_tolower(From),
|
unregister_webpresence(From, Host, Lang);
|
||||||
LUS = {LUser, LServer},
|
process_iq_register_set(_ServerHost, _Host, _From,
|
||||||
Check_URLTypes = (JidUrl == true) or (RidUrl =/= false),
|
#register{xdata = #xdata{type = cancel}}, _Lang) ->
|
||||||
Check_OutputTypes = (XML == true) or (Avatar == true) or (JS == true) or (Text == true) or (Icon =/= <<"---">>),
|
{result, undefined};
|
||||||
case Check_URLTypes and Check_OutputTypes of
|
process_iq_register_set(ServerHost, Host, From,
|
||||||
true -> iq_set_register_info2(From, LUS, Opts);
|
#register{nick = Nick, xdata = XData}, Lang) ->
|
||||||
false -> unregister_webpresence(From, Host, Lang)
|
case XData of
|
||||||
|
#xdata{type = submit, fields = Fs} ->
|
||||||
|
try
|
||||||
|
Options = muc_register:decode(Fs),
|
||||||
|
N = proplists:get_value(roomnick, Options),
|
||||||
|
iq_set_register_info(ServerHost, Host, From, N, Lang)
|
||||||
|
catch _:{muc_register, Why} ->
|
||||||
|
ErrText = muc_register:format_error(Why),
|
||||||
|
{error, xmpp:err_bad_request(ErrText, Lang)}
|
||||||
|
end;
|
||||||
|
#xdata{} ->
|
||||||
|
Txt = <<"Incorrect data form">>,
|
||||||
|
{error, xmpp:err_bad_request(Txt, Lang)};
|
||||||
|
_ when is_binary(Nick), Nick /= <<"">> ->
|
||||||
|
iq_set_register_info(ServerHost, Host, From, Nick, Lang);
|
||||||
|
_ ->
|
||||||
|
ErrText = <<"You must fill in field \"Nickname\" in the form">>,
|
||||||
|
{error, xmpp:err_not_acceptable(ErrText, Lang)}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
iq_set_register_info2(From, LUS, {Host, JidUrl, RidUrl, XML, Avatar, JS, Text, Icon, BaseURL, Lang}) ->
|
iq_set_register_info(ServerHost, Host, From, Nick,
|
||||||
RidUrl2 = get_rid_final_value(RidUrl, LUS),
|
Lang) ->
|
||||||
|
case iq_set_register_info2(ServerHost, Host, From, Nick, Lang) of
|
||||||
|
{atomic, ok} -> {result, undefined};
|
||||||
|
{atomic, false} ->
|
||||||
|
ErrText = <<"That nickname is registered by another "
|
||||||
|
"person">>,
|
||||||
|
{error, xmpp:err_conflict(ErrText, Lang)};
|
||||||
|
_ ->
|
||||||
|
Txt = <<"Database failure">>,
|
||||||
|
{error, xmpp:err_internal_server_error(Txt, Lang)}
|
||||||
|
end.
|
||||||
|
|
||||||
|
iq_set_register_info2(ServerHost, Host, From, Icon, Lang) ->
|
||||||
|
LServer = jid:nameprep(ServerHost),
|
||||||
|
%% RidUrl2 = get_rid_final_value(RidUrl, LUS),
|
||||||
|
LUS = {From#jid.luser, From#jid.lserver},
|
||||||
WP = #webpresence{us = LUS,
|
WP = #webpresence{us = LUS,
|
||||||
jidurl = JidUrl,
|
jidurl = true,
|
||||||
ridurl = RidUrl2,
|
ridurl = false,
|
||||||
xml = XML,
|
xml = true,
|
||||||
avatar = Avatar,
|
avatar = false,
|
||||||
js = JS,
|
js = true,
|
||||||
text = Text,
|
text = true,
|
||||||
icon = Icon},
|
icon = Icon},
|
||||||
F = fun() -> mnesia:write(WP) end,
|
F = fun() -> mnesia:write(WP) end,
|
||||||
case mnesia:transaction(F) of
|
case mnesia:transaction(F) of
|
||||||
{atomic, ok} ->
|
{atomic, ok} ->
|
||||||
|
BaseURL = get_baseurl(ServerHost),
|
||||||
send_message_registered(WP, From, Host, BaseURL, Lang),
|
send_message_registered(WP, From, Host, BaseURL, Lang),
|
||||||
{result, []};
|
{atomic, ok};
|
||||||
_ ->
|
_ ->
|
||||||
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
{error, xmpp:err_internal_server_error()}
|
||||||
end.
|
|
||||||
|
|
||||||
get_rid_final_value(false, _) -> false;
|
|
||||||
get_rid_final_value(true, {U, S} = LUS) ->
|
|
||||||
case get_pr_rid(LUS) of
|
|
||||||
false ->
|
|
||||||
iolist_to_binary(integer_to_list(erlang:phash2(U) * erlang:phash2(S)
|
|
||||||
* calendar:datetime_to_gregorian_seconds(
|
|
||||||
calendar:local_time()))
|
|
||||||
++ randoms:get_string());
|
|
||||||
H when is_binary(H) ->
|
|
||||||
H
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
send_message_registered(WP, To, Host, BaseURL, Lang) ->
|
send_message_registered(WP, To, Host, BaseURL, Lang) ->
|
||||||
|
@ -536,74 +529,14 @@ send_headline(Host, To, Subject, Body) ->
|
||||||
]
|
]
|
||||||
}).
|
}).
|
||||||
|
|
||||||
get_attr(Attr, XData, Default) ->
|
|
||||||
case lists:keysearch(Attr, 1, XData) of
|
|
||||||
{value, {_, [Value]}} -> Value;
|
|
||||||
false -> Default
|
|
||||||
end.
|
|
||||||
|
|
||||||
process_iq_register_set(From, SubEl, Host, BaseURL, Lang) ->
|
|
||||||
#xmlel{name = _, attrs = _, children = Els} = SubEl,
|
|
||||||
case fxml:get_subtag(SubEl, <<"remove">>) of
|
|
||||||
false -> case catch process_iq_register_set2(From, Els, Host, BaseURL, Lang) of
|
|
||||||
{'EXIT', _} -> {error, ?ERR_BAD_REQUEST};
|
|
||||||
R -> R
|
|
||||||
end;
|
|
||||||
_ -> unregister_webpresence(From, Host, Lang)
|
|
||||||
end.
|
|
||||||
|
|
||||||
process_iq_register_set2(From, Els, Host, BaseURL, Lang) ->
|
|
||||||
[
|
|
||||||
#xmlel{
|
|
||||||
name = <<"x">>,
|
|
||||||
attrs = _Attrs1,
|
|
||||||
children = _Els1
|
|
||||||
} = XEl
|
|
||||||
] = fxml:remove_cdata(Els),
|
|
||||||
case {fxml:get_tag_attr_s(<<"xmlns">>, XEl), fxml:get_tag_attr_s(<<"type">>, XEl)} of
|
|
||||||
{?NS_XDATA, <<"cancel">>} ->
|
|
||||||
{result, []};
|
|
||||||
{?NS_XDATA, <<"submit">>} ->
|
|
||||||
XData = jlib:parse_xdata_submit(XEl),
|
|
||||||
false = (invalid == XData),
|
|
||||||
JidUrl = get_attr(<<"jidurl">>, XData, <<"false">>),
|
|
||||||
RidUrl = get_attr(<<"ridurl">>, XData, <<"false">>),
|
|
||||||
XML = get_attr(<<"xml">>, XData, <<"false">>),
|
|
||||||
Avatar = get_attr(<<"avatar">>, XData, <<"false">>),
|
|
||||||
JS = get_attr(<<"js">>, XData, <<"false">>),
|
|
||||||
Text = get_attr(<<"text">>, XData, <<"false">>),
|
|
||||||
Icon = get_attr(<<"icon">>, XData, <<"---">>),
|
|
||||||
iq_set_register_info(From, {Host, to_bool(JidUrl), to_bool(RidUrl), to_bool(XML), to_bool(Avatar), to_bool(JS), to_bool(Text), Icon, BaseURL, Lang})
|
|
||||||
end.
|
|
||||||
|
|
||||||
unregister_webpresence(From, Host, Lang) ->
|
unregister_webpresence(From, Host, Lang) ->
|
||||||
{LUser, LServer, _} = jlib:jid_tolower(From),
|
remove_user(From#jid.luser, From#jid.lserver),
|
||||||
remove_user(LUser, LServer),
|
|
||||||
send_message_unregistered(From, Host, Lang),
|
send_message_unregistered(From, Host, Lang),
|
||||||
{result, []}.
|
{result, undefined}.
|
||||||
|
|
||||||
remove_user(User, Server) ->
|
remove_user(User, Server) ->
|
||||||
mnesia:dirty_delete(webpresence, {User, Server}).
|
mnesia:dirty_delete(webpresence, {User, Server}).
|
||||||
|
|
||||||
iq_get_vcard() ->
|
|
||||||
[
|
|
||||||
#xmlel{
|
|
||||||
name = <<"FN">>,
|
|
||||||
attrs = [],
|
|
||||||
children = [{xmlcdata, <<"ejabberd/mod_webpresence">>}]
|
|
||||||
},
|
|
||||||
#xmlel{
|
|
||||||
name = <<"URL">>,
|
|
||||||
attrs = [],
|
|
||||||
children = [{xmlcdata, <<"http://www.ejabberd.im/mod_webpresence">>}]
|
|
||||||
},
|
|
||||||
#xmlel{
|
|
||||||
name = <<"DESC">>,
|
|
||||||
attrs = [],
|
|
||||||
children = [{xmlcdata, <<"ejabberd web presence module\nCopyright (c) 2006-2007 Igor Goryachev, 2007 Badlop, 2014 runcom <antonio.murdaca@gmail.com>">>}]
|
|
||||||
}
|
|
||||||
].
|
|
||||||
|
|
||||||
get_wp(LUser, LServer) ->
|
get_wp(LUser, LServer) ->
|
||||||
LUS = {LUser, LServer},
|
LUS = {LUser, LServer},
|
||||||
case catch mnesia:dirty_read(webpresence, LUS) of
|
case catch mnesia:dirty_read(webpresence, LUS) of
|
||||||
|
@ -625,10 +558,10 @@ try_auto_webpresence(LUser, LServer) ->
|
||||||
ridurl = false,
|
ridurl = false,
|
||||||
jidurl = true,
|
jidurl = true,
|
||||||
xml = true,
|
xml = true,
|
||||||
avatar = true,
|
avatar = false,
|
||||||
js = true,
|
js = true,
|
||||||
text = true,
|
text = true,
|
||||||
icon = <<"jsf-jabber-text">>}
|
icon = "jsf-jabber-text"}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_status_weight(Show) ->
|
get_status_weight(Show) ->
|
||||||
|
@ -641,12 +574,12 @@ get_status_weight(Show) ->
|
||||||
_ -> 9
|
_ -> 9
|
||||||
end.
|
end.
|
||||||
|
|
||||||
session_to_presence(#session{sid = {_, Pid}, priority = Priority}) ->
|
session_to_presence(#session{sid = {_, Pid}}) ->
|
||||||
{_User, Resource, Show, Status} = ejabberd_c2s:get_presence(Pid),
|
P = ejabberd_c2s:get_presence(Pid),
|
||||||
#presence{resource = Resource,
|
#presence2{resource = (P#presence.from)#jid.resource,
|
||||||
show = Show,
|
show = misc:atom_to_binary(P#presence.show),
|
||||||
priority = Priority,
|
priority = P#presence.priority,
|
||||||
status = Status}.
|
status = xmpp:get_text(P#presence.status)}.
|
||||||
|
|
||||||
get_presences({bare, LUser, LServer}) ->
|
get_presences({bare, LUser, LServer}) ->
|
||||||
[session_to_presence(Session) ||
|
[session_to_presence(Session) ||
|
||||||
|
@ -656,12 +589,12 @@ get_presences({sorted, LUser, LServer}) ->
|
||||||
lists:sort(
|
lists:sort(
|
||||||
fun(A, B) ->
|
fun(A, B) ->
|
||||||
if
|
if
|
||||||
A#presence.priority == B#presence.priority ->
|
A#presence2.priority == B#presence2.priority ->
|
||||||
WA = get_status_weight(A#presence.show),
|
WA = get_status_weight(A#presence2.show),
|
||||||
WB = get_status_weight(B#presence.show),
|
WB = get_status_weight(B#presence2.show),
|
||||||
WA < WB;
|
WA < WB;
|
||||||
true ->
|
true ->
|
||||||
A#presence.priority > B#presence.priority
|
A#presence2.priority > B#presence2.priority
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
get_presences({bare, LUser, LServer}));
|
get_presences({bare, LUser, LServer}));
|
||||||
|
@ -678,11 +611,11 @@ get_presences({xml, LUser, LServer, Show_us}) ->
|
||||||
#xmlel{
|
#xmlel{
|
||||||
name = <<"resource">>,
|
name = <<"resource">>,
|
||||||
attrs = [
|
attrs = [
|
||||||
{<<"name">>, Presence#presence.resource},
|
{<<"name">>, Presence#presence2.resource},
|
||||||
{<<"show">>, Presence#presence.show},
|
{<<"show">>, Presence#presence2.show},
|
||||||
{<<"priority">>, iolist_to_binary(integer_to_list(Presence#presence.priority))}
|
{<<"priority">>, iolist_to_binary(integer_to_list(Presence#presence2.priority))}
|
||||||
],
|
],
|
||||||
children = [{xmlcdata, Presence#presence.status}]
|
children = [{xmlcdata, Presence#presence2.status}]
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
get_presences({sorted, LUser, LServer})
|
get_presences({sorted, LUser, LServer})
|
||||||
|
@ -694,13 +627,13 @@ get_presences({status, LUser, LServer, LResource}) ->
|
||||||
[] -> <<"unavailable">>;
|
[] -> <<"unavailable">>;
|
||||||
Rs ->
|
Rs ->
|
||||||
{value, R} = lists:keysearch(LResource, 2, Rs),
|
{value, R} = lists:keysearch(LResource, 2, Rs),
|
||||||
R#presence.show %% TODO why was this "status"?!
|
R#presence2.status
|
||||||
end;
|
end;
|
||||||
|
|
||||||
get_presences({status, LUser, LServer}) ->
|
get_presences({status, LUser, LServer}) ->
|
||||||
case get_presences({sorted, LUser, LServer}) of
|
case get_presences({sorted, LUser, LServer}) of
|
||||||
[Highest | _Rest] ->
|
[Highest | _Rest] ->
|
||||||
Highest#presence.show; %% TODO why was this "status"?!
|
Highest#presence2.status;
|
||||||
_ ->
|
_ ->
|
||||||
<<"unavailable">>
|
<<"unavailable">>
|
||||||
end;
|
end;
|
||||||
|
@ -710,13 +643,13 @@ get_presences({show, LUser, LServer, LResource}) ->
|
||||||
[] -> <<"unavailable">>;
|
[] -> <<"unavailable">>;
|
||||||
Rs ->
|
Rs ->
|
||||||
{value, R} = lists:keysearch(LResource, 2, Rs),
|
{value, R} = lists:keysearch(LResource, 2, Rs),
|
||||||
R#presence.show
|
R#presence2.show
|
||||||
end;
|
end;
|
||||||
|
|
||||||
get_presences({show, LUser, LServer}) ->
|
get_presences({show, LUser, LServer}) ->
|
||||||
case get_presences({sorted, LUser, LServer}) of
|
case get_presences({sorted, LUser, LServer}) of
|
||||||
[Highest | _Rest] ->
|
[Highest | _Rest] ->
|
||||||
Highest#presence.show;
|
Highest#presence2.show;
|
||||||
_ ->
|
_ ->
|
||||||
<<"unavailable">>
|
<<"unavailable">>
|
||||||
end.
|
end.
|
||||||
|
@ -744,12 +677,12 @@ make_js(WP, Prs, Show_us, Lang, Q) ->
|
||||||
<<"}">>])];
|
<<"}">>])];
|
||||||
_ -> lists:map(
|
_ -> lists:map(
|
||||||
fun(Pr) ->
|
fun(Pr) ->
|
||||||
Show = Pr#presence.show,
|
Show = Pr#presence2.show,
|
||||||
?BC([<<"{name:'">>, Pr#presence.resource, <<"',\n">>,
|
?BC([<<"{name:'">>, Pr#presence2.resource, <<"',\n">>,
|
||||||
<<" priority:">>, intund2string(Pr#presence.priority), <<",\n">>,
|
<<" priority:">>, intund2string(Pr#presence2.priority), <<",\n">>,
|
||||||
<<" show:'">>, Show, <<"',\n">>,
|
<<" show:'">>, Show, <<"',\n">>,
|
||||||
<<" long_show:'">>, long_show(Show, Lang), <<"',\n">>,
|
<<" long_show:'">>, long_show(Show, Lang), <<"',\n">>,
|
||||||
<<" status:'">>, escape(Pr#presence.status), <<"',\n">>,
|
<<" status:'">>, escape(Pr#presence2.status), <<"',\n">>,
|
||||||
FunImage(WP#webpresence.icon, Show),
|
FunImage(WP#webpresence.icon, Show),
|
||||||
<<"}">>])
|
<<"}">>])
|
||||||
end,
|
end,
|
||||||
|
@ -785,11 +718,8 @@ escape(S1) ->
|
||||||
re:replace(S2, "\n", "\\n", [global, {return, list}]).
|
re:replace(S2, "\n", "\\n", [global, {return, list}]).
|
||||||
|
|
||||||
get_baseurl(Host) ->
|
get_baseurl(Host) ->
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
BaseURL1 = gen_mod:get_module_opt(Host, ?MODULE, baseurl),
|
||||||
Proc ! {tell_baseurl, self()},
|
ejabberd_regexp:greplace(BaseURL1, <<"@HOST@">>, Host).
|
||||||
receive
|
|
||||||
{baseurl_is, BaseURL} -> BaseURL
|
|
||||||
end.
|
|
||||||
|
|
||||||
-define(XML_HEADER, <<"<?xml version='1.0' encoding='utf-8'?>">>).
|
-define(XML_HEADER, <<"<?xml version='1.0' encoding='utf-8'?>">>).
|
||||||
|
|
||||||
|
@ -878,9 +808,9 @@ show_presence({avatar, WP, LUser, LServer}) ->
|
||||||
true = WP#webpresence.avatar,
|
true = WP#webpresence.avatar,
|
||||||
[{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, LServer}),
|
[{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, LServer}),
|
||||||
JID = jlib:make_jid(LUser, LServer, <<"">>),
|
JID = jlib:make_jid(LUser, LServer, <<"">>),
|
||||||
IQ = #iq{type = get, xmlns = ?NS_VCARD},
|
IQ = #iq{type = get}, %%+++++, xmlns = ?NS_VCARD},
|
||||||
IQr = Module:Function(JID, JID, IQ),
|
IQr = Module:Function(JID, JID, IQ),
|
||||||
[VCard] = IQr#iq.sub_el,
|
[VCard] = ok, %%+++++ IQr#iq.sub_el,
|
||||||
Mime = fxml:get_path_s(VCard, [{elem, <<"PHOTO">>}, {elem, <<"TYPE">>}, cdata]),
|
Mime = fxml:get_path_s(VCard, [{elem, <<"PHOTO">>}, {elem, <<"TYPE">>}, cdata]),
|
||||||
BinVal = fxml:get_path_s(VCard, [{elem, <<"PHOTO">>}, {elem, <<"BINVAL">>}, cdata]),
|
BinVal = fxml:get_path_s(VCard, [{elem, <<"PHOTO">>}, {elem, <<"BINVAL">>}, cdata]),
|
||||||
Photo = jlib:decode_base64(BinVal),
|
Photo = jlib:decode_base64(BinVal),
|
||||||
|
|
Loading…
Reference in New Issue