mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Convert to exmpp.
SVN Revision: 1513
This commit is contained in:
parent
70956ece12
commit
d9a493561b
@ -1,3 +1,9 @@
|
|||||||
|
2008-08-06 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
|
||||||
|
|
||||||
|
* src/mod_offline.erl, src/mod_offline_odbc.erl, src/mod_echo.erl,
|
||||||
|
src/mod_last.erl, src/mod_configure2.erl, src/mod_last_odbc.erl,
|
||||||
|
src/gen_iq_handler.erl: Convert to exmpp.
|
||||||
|
|
||||||
2008-07-25 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
|
2008-07-25 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
|
||||||
|
|
||||||
* src/adhoc.erl, src/mod_configure.erl, src/mod_announce.erl,
|
* src/adhoc.erl, src/mod_configure.erl, src/mod_announce.erl,
|
||||||
|
@ -63,7 +63,11 @@
|
|||||||
mod_annouce,
|
mod_annouce,
|
||||||
mod_caps,
|
mod_caps,
|
||||||
mod_configure,
|
mod_configure,
|
||||||
|
mod_configure2,
|
||||||
mod_disco,
|
mod_disco,
|
||||||
|
mod_echo,
|
||||||
|
mod_offline,
|
||||||
|
mod_offline_odbc,
|
||||||
mod_roster,
|
mod_roster,
|
||||||
mod_vcard
|
mod_vcard
|
||||||
]).
|
]).
|
||||||
|
@ -33,30 +33,36 @@
|
|||||||
stop/1,
|
stop/1,
|
||||||
process_local_iq/3]).
|
process_local_iq/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include_lib("exmpp/include/exmpp.hrl").
|
||||||
-include("jlib.hrl").
|
|
||||||
|
|
||||||
-define(NS_ECONFIGURE, "http://ejabberd.jabberstudio.org/protocol/configure").
|
-include("ejabberd.hrl").
|
||||||
|
|
||||||
|
% XXX The namespace used in this module isn't known by Exmpp: if the
|
||||||
|
% known list isn't updated by Ejabberd, some element names will be
|
||||||
|
% represented with strings.
|
||||||
|
% XXX This module currently supposed that they'll be atoms.
|
||||||
|
|
||||||
|
-define(NS_ECONFIGURE, 'http://ejabberd.jabberstudio.org/protocol/configure').
|
||||||
|
-define(NS_ECONFIGURE_s, "http://ejabberd.jabberstudio.org/protocol/configure").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_ECONFIGURE,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_ECONFIGURE_s,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
stop(Host) ->
|
stop(Host) ->
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ECONFIGURE).
|
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ECONFIGURE_s).
|
||||||
|
|
||||||
|
|
||||||
process_local_iq(From, To, #iq{type = Type, lang = _Lang, sub_el = SubEl} = IQ) ->
|
process_local_iq(From, To, IQ) ->
|
||||||
case acl:match_rule(To#jid.lserver, configure, From) of
|
case acl:match_rule(To#jid.ldomain, configure, From) of
|
||||||
deny ->
|
deny ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
exmpp_iq:error(IQ, 'not-allowed');
|
||||||
allow ->
|
allow ->
|
||||||
case Type of
|
case exmpp_iq:get_type(IQ) of
|
||||||
set ->
|
set ->
|
||||||
IQ#iq{type = error,
|
exmpp_iq:error(IQ, 'feature-not-implemented');
|
||||||
sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]};
|
|
||||||
%%case xml:get_tag_attr_s("type", SubEl) of
|
%%case xml:get_tag_attr_s("type", SubEl) of
|
||||||
%% "cancel" ->
|
%% "cancel" ->
|
||||||
%% IQ#iq{type = result,
|
%% IQ#iq{type = result,
|
||||||
@ -90,56 +96,57 @@ process_local_iq(From, To, #iq{type = Type, lang = _Lang, sub_el = SubEl} = IQ)
|
|||||||
%% sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
%% sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
||||||
%%end;
|
%%end;
|
||||||
get ->
|
get ->
|
||||||
case process_get(SubEl) of
|
case process_get(IQ#xmlel.children) of
|
||||||
{result, Res} ->
|
{result, Res} ->
|
||||||
IQ#iq{type = result, sub_el = [Res]};
|
exmpp_iq:result(IQ, Res);
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, Error]}
|
exmpp_iq:error(IQ, Error)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
process_get({xmlelement, "info", _Attrs, _SubEls}) ->
|
process_get(#xmlel{ns = ?NS_ECONFIGURE, name = 'info'}) ->
|
||||||
S2SConns = ejabberd_s2s:dirty_get_connections(),
|
S2SConns = ejabberd_s2s:dirty_get_connections(),
|
||||||
TConns = lists:usort([element(2, C) || C <- S2SConns]),
|
TConns = lists:usort([element(2, C) || C <- S2SConns]),
|
||||||
Attrs = [{"registered-users",
|
Attrs = [#xmlattr{name = 'registered-users', value =
|
||||||
integer_to_list(mnesia:table_info(passwd, size))},
|
integer_to_list(mnesia:table_info(passwd, size))},
|
||||||
{"online-users",
|
#xmlattr{name = 'online-users', value =
|
||||||
integer_to_list(mnesia:table_info(presence, size))},
|
integer_to_list(mnesia:table_info(presence, size))},
|
||||||
{"running-nodes",
|
#xmlattr{name = 'running-nodes', value =
|
||||||
integer_to_list(length(mnesia:system_info(running_db_nodes)))},
|
integer_to_list(length(mnesia:system_info(running_db_nodes)))},
|
||||||
{"stopped-nodes",
|
#xmlattr{name = 'stopped-nodes', value =
|
||||||
integer_to_list(
|
integer_to_list(
|
||||||
length(lists:usort(mnesia:system_info(db_nodes) ++
|
length(lists:usort(mnesia:system_info(db_nodes) ++
|
||||||
mnesia:system_info(extra_db_nodes)) --
|
mnesia:system_info(extra_db_nodes)) --
|
||||||
mnesia:system_info(running_db_nodes)))},
|
mnesia:system_info(running_db_nodes)))},
|
||||||
{"outgoing-s2s-servers", integer_to_list(length(TConns))}],
|
#xmlattr{name = 'outgoing-s2s-servers', value =
|
||||||
{result, {xmlelement, "info",
|
integer_to_list(length(TConns))}],
|
||||||
[{"xmlns", ?NS_ECONFIGURE} | Attrs], []}};
|
{result, #xmlel{ns = ?NS_ECONFIGURE, name = 'info', attrs = Attrs}};
|
||||||
process_get({xmlelement, "welcome-message", Attrs, _SubEls}) ->
|
process_get(#xmlel{ns = ?NS_ECONFIGURE, name = 'welcome-message', attrs = Attrs}) ->
|
||||||
{Subj, Body} = case ejabberd_config:get_local_option(welcome_message) of
|
{Subj, Body} = case ejabberd_config:get_local_option(welcome_message) of
|
||||||
{_Subj, _Body} = SB -> SB;
|
{_Subj, _Body} = SB -> SB;
|
||||||
_ -> {"", ""}
|
_ -> {"", ""}
|
||||||
end,
|
end,
|
||||||
{result, {xmlelement, "welcome-message", Attrs,
|
{result, #xmlel{ns = ?NS_ECONFIGURE, name = 'welcome-message',
|
||||||
[{xmlelement, "subject", [], [{xmlcdata, Subj}]},
|
attrs = Attrs, children =
|
||||||
{xmlelement, "body", [], [{xmlcdata, Body}]}]}};
|
[#xmlel{ns = ?NS_ECONFIGURE, name = 'subject', children = [#xmlcdata{cdata = list_to_binary(Subj)}]},
|
||||||
process_get({xmlelement, "registration-watchers", Attrs, _SubEls}) ->
|
#xmlel{ns = ?NS_ECONFIGURE, name = 'body', children = [#xmlcdata{cdata = list_to_binary(Body)}]}]}};
|
||||||
|
process_get(#xmlel{ns = ?NS_ECONFIGURE, name = 'registration-watchers', attrs = Attrs}) ->
|
||||||
SubEls =
|
SubEls =
|
||||||
case ejabberd_config:get_local_option(registration_watchers) of
|
case ejabberd_config:get_local_option(registration_watchers) of
|
||||||
JIDs when is_list(JIDs) ->
|
JIDs when is_list(JIDs) ->
|
||||||
lists:map(fun(JID) ->
|
lists:map(fun(JID) ->
|
||||||
{xmlelement, "jid", [], [{xmlcdata, JID}]}
|
#xmlel{ns = ?NS_ECONFIGURE, name = 'jid', children = [#xmlcdata{cdata = list_to_binary(JID)}]}
|
||||||
end, JIDs);
|
end, JIDs);
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
end,
|
end,
|
||||||
{result, {xmlelement, "registration_watchers", Attrs, SubEls}};
|
{result, #xmlel{ns = ?NS_ECONFIGURE, name = 'registration_watchers', attrs = Attrs, children = SubEls}};
|
||||||
process_get({xmlelement, "acls", Attrs, _SubEls}) ->
|
process_get(#xmlel{ns = ?NS_ECONFIGURE, name = 'acls', attrs = Attrs}) ->
|
||||||
Str = lists:flatten(io_lib:format("~p.", [ets:tab2list(acl)])),
|
Str = lists:flatten(io_lib:format("~p.", [ets:tab2list(acl)])),
|
||||||
{result, {xmlelement, "acls", Attrs, [{xmlcdata, Str}]}};
|
{result, #xmlel{ns = ?NS_ECONFIGURE, name = 'acls', attrs = Attrs, children = [#xmlcdata{cdata = list_to_binary(Str)}]}};
|
||||||
process_get({xmlelement, "access", Attrs, _SubEls}) ->
|
process_get(#xmlel{ns = ?NS_ECONFIGURE, name = 'access', attrs = Attrs}) ->
|
||||||
Str =
|
Str =
|
||||||
lists:flatten(
|
lists:flatten(
|
||||||
io_lib:format(
|
io_lib:format(
|
||||||
@ -149,22 +156,22 @@ process_get({xmlelement, "access", Attrs, _SubEls}) ->
|
|||||||
[],
|
[],
|
||||||
[{{access, '$1', '$2'}}]}])
|
[{{access, '$1', '$2'}}]}])
|
||||||
])),
|
])),
|
||||||
{result, {xmlelement, "access", Attrs, [{xmlcdata, Str}]}};
|
{result, #xmlel{ns = ?NS_ECONFIGURE, name = 'access', attrs = Attrs, children = [#xmlcdata{cdata = list_to_binary(Str)}]}};
|
||||||
process_get({xmlelement, "last", Attrs, _SubEls}) ->
|
process_get(#xmlel{ns = ?NS_ECONFIGURE, name = 'last', attrs = Attrs}) ->
|
||||||
case catch mnesia:dirty_select(
|
case catch mnesia:dirty_select(
|
||||||
last_activity, [{{last_activity, '_', '$1', '_'}, [], ['$1']}]) of
|
last_activity, [{{last_activity, '_', '$1', '_'}, [], ['$1']}]) of
|
||||||
{'EXIT', _Reason} ->
|
{'EXIT', _Reason} ->
|
||||||
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
{error, 'internal-server-error'};
|
||||||
Vals ->
|
Vals ->
|
||||||
{MegaSecs, Secs, _MicroSecs} = now(),
|
{MegaSecs, Secs, _MicroSecs} = now(),
|
||||||
TimeStamp = MegaSecs * 1000000 + Secs,
|
TimeStamp = MegaSecs * 1000000 + Secs,
|
||||||
Str = lists:flatten(
|
Str = lists:flatten(
|
||||||
lists:append(
|
lists:append(
|
||||||
[[integer_to_list(TimeStamp - V), " "] || V <- Vals])),
|
[[integer_to_list(TimeStamp - V), " "] || V <- Vals])),
|
||||||
{result, {xmlelement, "last", Attrs, [{xmlcdata, Str}]}}
|
{result, #xmlel{ns = ?NS_ECONFIGURE, name = 'last', attrs = Attrs, children = [#xmlcdata{cdata = list_to_binary(Str)}]}}
|
||||||
end;
|
end;
|
||||||
%%process_get({xmlelement, Name, Attrs, SubEls}) ->
|
%%process_get({xmlelement, Name, Attrs, SubEls}) ->
|
||||||
%% {result, };
|
%% {result, };
|
||||||
process_get(_) ->
|
process_get(_) ->
|
||||||
{error, ?ERR_BAD_REQUEST}.
|
{error, 'bad-request'}.
|
||||||
|
|
||||||
|
@ -37,8 +37,9 @@
|
|||||||
-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]).
|
||||||
|
|
||||||
|
-include_lib("exmpp/include/exmpp.hrl").
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
|
||||||
|
|
||||||
-record(state, {host}).
|
-record(state, {host}).
|
||||||
|
|
||||||
@ -117,8 +118,8 @@ handle_cast(_Msg, State) ->
|
|||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, From, To, Packet}, State) ->
|
||||||
Packet2 = case From#jid.user of
|
Packet2 = case From#jid.node of
|
||||||
"" -> jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST);
|
<<>> -> exmpp_stanza:reply_with_error(Packet, 'bad-request');
|
||||||
_ -> Packet
|
_ -> Packet
|
||||||
end,
|
end,
|
||||||
do_client_version(disabled, To, From), % Put 'enabled' to enable it
|
do_client_version(disabled, To, From), % Put 'enabled' to enable it
|
||||||
@ -171,16 +172,16 @@ code_change(_OldVsn, State, _Extra) ->
|
|||||||
do_client_version(disabled, _From, _To) ->
|
do_client_version(disabled, _From, _To) ->
|
||||||
ok;
|
ok;
|
||||||
do_client_version(enabled, From, To) ->
|
do_client_version(enabled, From, To) ->
|
||||||
ToS = jlib:jid_to_string(To),
|
|
||||||
%% It is important to identify this process and packet
|
%% It is important to identify this process and packet
|
||||||
Random_resource = integer_to_list(random:uniform(100000)),
|
Random_resource = integer_to_list(random:uniform(100000)),
|
||||||
From2 = From#jid{resource = Random_resource,
|
From2 = From#jid{resource = Random_resource,
|
||||||
lresource = Random_resource},
|
lresource = Random_resource},
|
||||||
|
|
||||||
%% Build an iq:query request
|
%% Build an iq:query request
|
||||||
Packet = {xmlelement, "iq",
|
Request = #xmlel{ns = ?NS_SOFT_VERSION, name = 'query'},
|
||||||
[{"to", ToS}, {"type", "get"}],
|
Packet = exmpp_stanza:set_recipient(
|
||||||
[{xmlelement, "query", [{"xmlns", ?NS_VERSION}], []}]},
|
exmpp_iq:get(?NS_JABBER_CLIENT, Request),
|
||||||
|
To),
|
||||||
|
|
||||||
%% Send the request
|
%% Send the request
|
||||||
ejabberd_router:route(From2, To, Packet),
|
ejabberd_router:route(From2, To, Packet),
|
||||||
@ -189,15 +190,15 @@ do_client_version(enabled, From, To) ->
|
|||||||
%% It is very important to only accept a packet which is the
|
%% It is very important to only accept a packet which is the
|
||||||
%% response to the request that he sent
|
%% response to the request that he sent
|
||||||
Els = receive {route, To, From2, IQ} ->
|
Els = receive {route, To, From2, IQ} ->
|
||||||
{xmlelement, "query", _, List} = xml:get_subtag(IQ, "query"),
|
#xmlel{ns = ?NS_SOFT_VERSION, name = 'query', children = List} = exmpp_iq:get_payload(IQ),
|
||||||
List
|
List
|
||||||
after 5000 -> % Timeout in miliseconds: 5 seconds
|
after 5000 -> % Timeout in miliseconds: 5 seconds
|
||||||
[]
|
[]
|
||||||
end,
|
end,
|
||||||
Values = [{Name, Value} || {xmlelement,Name,[],[{xmlcdata,Value}]} <- Els],
|
Values = [{Name, binary_to_list(Value)} || #xmlel{name = Name, children = [#xmlcdata{cdata = Value}]} <- Els],
|
||||||
|
|
||||||
%% Print in log
|
%% Print in log
|
||||||
Values_string1 = [io_lib:format("~n~s: ~p", [N, V]) || {N, V} <- Values],
|
Values_string1 = [io_lib:format("~n~s: ~p", [N, V]) || {N, V} <- Values],
|
||||||
Values_string2 = lists:concat(Values_string1),
|
Values_string2 = lists:concat(Values_string1),
|
||||||
?INFO_MSG("Information of the client: ~s~s", [ToS, Values_string2]).
|
?INFO_MSG("Information of the client: ~s~s", [exmpp_jid:jid_to_string(To), Values_string2]).
|
||||||
|
|
||||||
|
@ -38,8 +38,9 @@
|
|||||||
get_last_info/2,
|
get_last_info/2,
|
||||||
remove_user/2]).
|
remove_user/2]).
|
||||||
|
|
||||||
|
-include_lib("exmpp/include/exmpp.hrl").
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
|
||||||
-include("mod_privacy.hrl").
|
-include("mod_privacy.hrl").
|
||||||
|
|
||||||
-record(last_activity, {us, timestamp, status}).
|
-record(last_activity, {us, timestamp, status}).
|
||||||
@ -51,9 +52,9 @@ start(Host, Opts) ->
|
|||||||
[{disc_copies, [node()]},
|
[{disc_copies, [node()]},
|
||||||
{attributes, record_info(fields, last_activity)}]),
|
{attributes, record_info(fields, last_activity)}]),
|
||||||
update_table(),
|
update_table(),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY_s,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY_s,
|
||||||
?MODULE, process_sm_iq, IQDisc),
|
?MODULE, process_sm_iq, IQDisc),
|
||||||
ejabberd_hooks:add(remove_user, Host,
|
ejabberd_hooks:add(remove_user, Host,
|
||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
@ -65,30 +66,28 @@ stop(Host) ->
|
|||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:delete(unset_presence_hook, Host,
|
ejabberd_hooks:delete(unset_presence_hook, Host,
|
||||||
?MODULE, on_presence_update, 50),
|
?MODULE, on_presence_update, 50),
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST),
|
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY_s),
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST).
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY_s).
|
||||||
|
|
||||||
process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
process_local_iq(_From, _To, IQ) ->
|
||||||
case Type of
|
case exmpp_iq:get_type(IQ) of
|
||||||
set ->
|
set ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
exmpp_iq:error(IQ, 'not-allowed');
|
||||||
get ->
|
get ->
|
||||||
Sec = trunc(element(1, erlang:statistics(wall_clock))/1000),
|
Sec = trunc(element(1, erlang:statistics(wall_clock))/1000),
|
||||||
IQ#iq{type = result,
|
Response = #xmlel{ns = ?NS_LAST_ACTIVITY, name = 'query', attrs =
|
||||||
sub_el = [{xmlelement, "query",
|
[#xmlattr{name = 'seconds', value = integer_to_list(Sec)}]},
|
||||||
[{"xmlns", ?NS_LAST},
|
exmpp_iq:result(IQ, Response)
|
||||||
{"seconds", integer_to_list(Sec)}],
|
|
||||||
[]}]}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
process_sm_iq(From, To, IQ) ->
|
||||||
case Type of
|
case exmpp_iq:get_type(IQ) of
|
||||||
set ->
|
set ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
exmpp_iq:error(IQ, 'not-allowed');
|
||||||
get ->
|
get ->
|
||||||
User = To#jid.luser,
|
User = To#jid.lnode,
|
||||||
Server = To#jid.lserver,
|
Server = To#jid.ldomain,
|
||||||
{Subscription, _Groups} =
|
{Subscription, _Groups} =
|
||||||
ejabberd_hooks:run_fold(
|
ejabberd_hooks:run_fold(
|
||||||
roster_get_jid_info, Server,
|
roster_get_jid_info, Server,
|
||||||
@ -104,36 +103,33 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
|||||||
allow,
|
allow,
|
||||||
[User, Server, UserListRecord,
|
[User, Server, UserListRecord,
|
||||||
{From, To,
|
{From, To,
|
||||||
{xmlelement, "presence", [], []}},
|
exmpp_presence:available()},
|
||||||
out]) of
|
out]) of
|
||||||
allow ->
|
allow ->
|
||||||
get_last(IQ, SubEl, User, Server);
|
get_last(IQ, User, Server);
|
||||||
deny ->
|
deny ->
|
||||||
IQ#iq{type = error,
|
exmpp_iq:error(IQ, 'not-allowed')
|
||||||
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
|
||||||
end;
|
end;
|
||||||
true ->
|
true ->
|
||||||
IQ#iq{type = error,
|
exmpp_iq:error(IQ, 'not-allowed')
|
||||||
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% TODO: This function could use get_last_info/2
|
%% TODO: This function could use get_last_info/2
|
||||||
get_last(IQ, SubEl, LUser, LServer) ->
|
get_last(IQ, LUser, LServer) ->
|
||||||
case catch mnesia:dirty_read(last_activity, {LUser, LServer}) of
|
case catch mnesia:dirty_read(last_activity, {LUser, LServer}) of
|
||||||
{'EXIT', _Reason} ->
|
{'EXIT', _Reason} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
|
exmpp_iq:error(IQ, 'internal-server-error');
|
||||||
[] ->
|
[] ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
|
exmpp_iq:error(IQ, 'service-unavailable');
|
||||||
[#last_activity{timestamp = TimeStamp, status = Status}] ->
|
[#last_activity{timestamp = TimeStamp, status = Status}] ->
|
||||||
{MegaSecs, Secs, _MicroSecs} = now(),
|
{MegaSecs, Secs, _MicroSecs} = now(),
|
||||||
TimeStamp2 = MegaSecs * 1000000 + Secs,
|
TimeStamp2 = MegaSecs * 1000000 + Secs,
|
||||||
Sec = TimeStamp2 - TimeStamp,
|
Sec = TimeStamp2 - TimeStamp,
|
||||||
IQ#iq{type = result,
|
Response = #xmlel{ns = ?NS_LAST_ACTIVITY, name = 'query',
|
||||||
sub_el = [{xmlelement, "query",
|
attrs = [#xmlattr{name = 'seconds', value = integer_to_list(Sec)}],
|
||||||
[{"xmlns", ?NS_LAST},
|
children = [#xmlcdata{cdata = list_to_binary(Status)}]},
|
||||||
{"seconds", integer_to_list(Sec)}],
|
exmpp_iq:result(IQ, Response)
|
||||||
[{xmlcdata, Status}]}]}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@ -144,8 +140,8 @@ on_presence_update(User, Server, _Resource, Status) ->
|
|||||||
store_last_info(User, Server, TimeStamp, Status).
|
store_last_info(User, Server, TimeStamp, Status).
|
||||||
|
|
||||||
store_last_info(User, Server, TimeStamp, Status) ->
|
store_last_info(User, Server, TimeStamp, Status) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
mnesia:write(#last_activity{us = US,
|
mnesia:write(#last_activity{us = US,
|
||||||
@ -166,8 +162,8 @@ get_last_info(LUser, LServer) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
remove_user(User, Server) ->
|
remove_user(User, Server) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
mnesia:delete({last_activity, US})
|
mnesia:delete({last_activity, US})
|
||||||
|
@ -38,15 +38,16 @@
|
|||||||
get_last_info/2,
|
get_last_info/2,
|
||||||
remove_user/2]).
|
remove_user/2]).
|
||||||
|
|
||||||
|
-include_lib("exmpp/include/exmpp.hrl").
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
|
||||||
-include("mod_privacy.hrl").
|
-include("mod_privacy.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY_s,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY_s,
|
||||||
?MODULE, process_sm_iq, IQDisc),
|
?MODULE, process_sm_iq, IQDisc),
|
||||||
ejabberd_hooks:add(remove_user, Host,
|
ejabberd_hooks:add(remove_user, Host,
|
||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
@ -58,29 +59,27 @@ stop(Host) ->
|
|||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:delete(unset_presence_hook, Host,
|
ejabberd_hooks:delete(unset_presence_hook, Host,
|
||||||
?MODULE, on_presence_update, 50),
|
?MODULE, on_presence_update, 50),
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST),
|
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY_s),
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST).
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY_s).
|
||||||
|
|
||||||
process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
process_local_iq(_From, _To, IQ) ->
|
||||||
case Type of
|
case exmpp_iq:get_type(IQ) of
|
||||||
set ->
|
set ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
exmpp_iq:error(IQ, 'not-allowed');
|
||||||
get ->
|
get ->
|
||||||
Sec = trunc(element(1, erlang:statistics(wall_clock))/1000),
|
Sec = trunc(element(1, erlang:statistics(wall_clock))/1000),
|
||||||
IQ#iq{type = result,
|
Response = #xmlel{ns = ?NS_LAST_ACTIVITY, name = 'query', attrs =
|
||||||
sub_el = [{xmlelement, "query",
|
[#xmlattr{name = 'seconds', value = integer_to_list(Sec)}]},
|
||||||
[{"xmlns", ?NS_LAST},
|
exmpp_iq:result(IQ, Response)
|
||||||
{"seconds", integer_to_list(Sec)}],
|
|
||||||
[]}]}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
process_sm_iq(From, To, IQ) ->
|
||||||
case Type of
|
case exmpp_iq:get_type(IQ) of
|
||||||
set ->
|
set ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
exmpp_iq:error(IQ, 'not-allowed');
|
||||||
get ->
|
get ->
|
||||||
User = To#jid.luser,
|
User = To#jid.lnode,
|
||||||
Server = To#jid.lserver,
|
Server = To#jid.ldomain,
|
||||||
{Subscription, _Groups} =
|
{Subscription, _Groups} =
|
||||||
ejabberd_hooks:run_fold(
|
ejabberd_hooks:run_fold(
|
||||||
roster_get_jid_info, Server,
|
roster_get_jid_info, Server,
|
||||||
@ -96,42 +95,38 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
|||||||
allow,
|
allow,
|
||||||
[User, Server, UserListRecord,
|
[User, Server, UserListRecord,
|
||||||
{From, To,
|
{From, To,
|
||||||
{xmlelement, "presence", [], []}},
|
exmpp_presence:available()},
|
||||||
out]) of
|
out]) of
|
||||||
allow ->
|
allow ->
|
||||||
get_last(IQ, SubEl, User, Server);
|
get_last(IQ, User, Server);
|
||||||
deny ->
|
deny ->
|
||||||
IQ#iq{type = error,
|
exmpp_iq:error(IQ, 'not-allowed')
|
||||||
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
|
||||||
end;
|
end;
|
||||||
true ->
|
true ->
|
||||||
IQ#iq{type = error,
|
exmpp_iq:error(IQ, 'not-allowed')
|
||||||
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% TODO: This function could use get_last_info/2
|
%% TODO: This function could use get_last_info/2
|
||||||
get_last(IQ, SubEl, LUser, LServer) ->
|
get_last(IQ, LUser, LServer) ->
|
||||||
Username = ejabberd_odbc:escape(LUser),
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
case catch odbc_queries:get_last(LServer, Username) of
|
case catch odbc_queries:get_last(LServer, Username) of
|
||||||
{'EXIT', _Reason} ->
|
{'EXIT', _Reason} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
|
exmpp_iq:error(IQ, 'internal-server-error');
|
||||||
{selected, ["seconds","state"], []} ->
|
{selected, ["seconds","state"], []} ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
|
exmpp_iq:error(IQ, 'service-unavailable');
|
||||||
{selected, ["seconds","state"], [{STimeStamp, Status}]} ->
|
{selected, ["seconds","state"], [{STimeStamp, Status}]} ->
|
||||||
case catch list_to_integer(STimeStamp) of
|
case catch list_to_integer(STimeStamp) of
|
||||||
TimeStamp when is_integer(TimeStamp) ->
|
TimeStamp when is_integer(TimeStamp) ->
|
||||||
{MegaSecs, Secs, _MicroSecs} = now(),
|
{MegaSecs, Secs, _MicroSecs} = now(),
|
||||||
TimeStamp2 = MegaSecs * 1000000 + Secs,
|
TimeStamp2 = MegaSecs * 1000000 + Secs,
|
||||||
Sec = TimeStamp2 - TimeStamp,
|
Sec = TimeStamp2 - TimeStamp,
|
||||||
IQ#iq{type = result,
|
Response = #xmlel{ns = ?NS_LAST_ACTIVITY, name = 'query',
|
||||||
sub_el = [{xmlelement, "query",
|
attrs = [#xmlattr{name = 'seconds', value = integer_to_list(Sec)}],
|
||||||
[{"xmlns", ?NS_LAST},
|
children = [#xmlcdata{cdata = list_to_binary(Status)}]},
|
||||||
{"seconds", integer_to_list(Sec)}],
|
exmpp_iq:result(IQ, Response);
|
||||||
[{xmlcdata, Status}]}]};
|
|
||||||
_ ->
|
_ ->
|
||||||
IQ#iq{type = error,
|
exmpp_iq:error(IQ, 'internal-server-error')
|
||||||
sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -141,8 +136,8 @@ on_presence_update(User, Server, _Resource, Status) ->
|
|||||||
store_last_info(User, Server, TimeStamp, Status).
|
store_last_info(User, Server, TimeStamp, Status).
|
||||||
|
|
||||||
store_last_info(User, Server, TimeStamp, Status) ->
|
store_last_info(User, Server, TimeStamp, Status) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
Username = ejabberd_odbc:escape(LUser),
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
|
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
|
||||||
State = ejabberd_odbc:escape(Status),
|
State = ejabberd_odbc:escape(Status),
|
||||||
@ -166,7 +161,7 @@ get_last_info(LUser, LServer) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
remove_user(User, Server) ->
|
remove_user(User, Server) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
Username = ejabberd_odbc:escape(LUser),
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
odbc_queries:del_last(LServer, Username).
|
odbc_queries:del_last(LServer, Username).
|
||||||
|
@ -41,8 +41,9 @@
|
|||||||
webadmin_page/3,
|
webadmin_page/3,
|
||||||
webadmin_user/4]).
|
webadmin_user/4]).
|
||||||
|
|
||||||
|
-include_lib("exmpp/include/exmpp.hrl").
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
|
||||||
-include("web/ejabberd_http.hrl").
|
-include("web/ejabberd_http.hrl").
|
||||||
-include("web/ejabberd_web_admin.hrl").
|
-include("web/ejabberd_web_admin.hrl").
|
||||||
|
|
||||||
@ -51,6 +52,11 @@
|
|||||||
-define(PROCNAME, ejabberd_offline).
|
-define(PROCNAME, ejabberd_offline).
|
||||||
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
|
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
|
||||||
|
|
||||||
|
% These are the namespace already declared by the stream opening. This is
|
||||||
|
% used at serialization time.
|
||||||
|
-define(DEFAULT_NS, ?NS_JABBER_CLIENT).
|
||||||
|
-define(PREFIXED_NS, [{?NS_XMPP, ?NS_XMPP_pfx}]).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
mnesia:create_table(offline_msg,
|
mnesia:create_table(offline_msg,
|
||||||
[{disc_only_copies, [node()]},
|
[{disc_only_copies, [node()]},
|
||||||
@ -142,23 +148,25 @@ stop(Host) ->
|
|||||||
{wait, Proc}.
|
{wait, Proc}.
|
||||||
|
|
||||||
store_packet(From, To, Packet) ->
|
store_packet(From, To, Packet) ->
|
||||||
Type = xml:get_tag_attr_s("type", Packet),
|
Type = exmpp_stanza:get_type(Packet),
|
||||||
if
|
if
|
||||||
(Type /= "error") and (Type /= "groupchat") and
|
(Type /= "error") and (Type /= "groupchat") and
|
||||||
(Type /= "headline") ->
|
(Type /= "headline") ->
|
||||||
case check_event(From, To, Packet) of
|
case check_event(From, To, Packet) of
|
||||||
true ->
|
true ->
|
||||||
#jid{luser = LUser, lserver = LServer} = To,
|
#jid{lnode = LUser, ldomain = LServer} = To,
|
||||||
TimeStamp = now(),
|
TimeStamp = now(),
|
||||||
{xmlelement, _Name, _Attrs, Els} = Packet,
|
Expire = find_x_expire(TimeStamp, Packet#xmlel.children),
|
||||||
Expire = find_x_expire(TimeStamp, Els),
|
% XXX OLD FORMAT: Packet is stored in the old format.
|
||||||
gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) !
|
PacketOld = exmpp_xml:xmlel_to_xmlelement(Packet,
|
||||||
|
[?DEFAULT_NS], ?PREFIXED_NS),
|
||||||
|
gen_mod:get_module_proc(To#jid.ldomain, ?PROCNAME) !
|
||||||
#offline_msg{us = {LUser, LServer},
|
#offline_msg{us = {LUser, LServer},
|
||||||
timestamp = TimeStamp,
|
timestamp = TimeStamp,
|
||||||
expire = Expire,
|
expire = Expire,
|
||||||
from = From,
|
from = From,
|
||||||
to = To,
|
to = To,
|
||||||
packet = Packet},
|
packet = PacketOld},
|
||||||
stop;
|
stop;
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
@ -168,31 +176,28 @@ store_packet(From, To, Packet) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
check_event(From, To, Packet) ->
|
check_event(From, To, Packet) ->
|
||||||
{xmlelement, Name, Attrs, Els} = Packet,
|
case find_x_event(Packet#xmlel.children) of
|
||||||
case find_x_event(Els) of
|
|
||||||
false ->
|
false ->
|
||||||
true;
|
true;
|
||||||
El ->
|
El ->
|
||||||
case xml:get_subtag(El, "id") of
|
case exmpp_xml:get_element(El, 'id') of
|
||||||
false ->
|
undefined ->
|
||||||
case xml:get_subtag(El, "offline") of
|
case exmpp_xml:get_element(El, 'offline') of
|
||||||
false ->
|
undefined ->
|
||||||
true;
|
true;
|
||||||
_ ->
|
_ ->
|
||||||
ID = case xml:get_tag_attr_s("id", Packet) of
|
ID = case exmpp_stanza:get_id(Packet) of
|
||||||
"" ->
|
undefined ->
|
||||||
{xmlelement, "id", [], []};
|
#xmlel{ns = ?NS_MESSAGE_EVENT, name = 'id'};
|
||||||
S ->
|
S ->
|
||||||
{xmlelement, "id", [],
|
#xmlel{ns = ?NS_MESSAGE_EVENT, name = 'id',
|
||||||
[{xmlcdata, S}]}
|
children = [#xmlcdata{cdata =
|
||||||
|
list_to_binary(S)}]}
|
||||||
end,
|
end,
|
||||||
|
X = #xmlel{ns = ?NS_MESSAGE_EVENT, name = 'x', children =
|
||||||
|
[ID, #xmlel{ns = ?NS_MESSAGE_EVENT, name = 'offline'}]},
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
To, From, {xmlelement, Name, Attrs,
|
To, From, exmpp_xml:set_children(Packet, [X])),
|
||||||
[{xmlelement, "x",
|
|
||||||
[{"xmlns", ?NS_EVENT}],
|
|
||||||
[ID,
|
|
||||||
{xmlelement, "offline", [], []}]}]
|
|
||||||
}),
|
|
||||||
true
|
true
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
@ -202,44 +207,34 @@ check_event(From, To, Packet) ->
|
|||||||
|
|
||||||
find_x_event([]) ->
|
find_x_event([]) ->
|
||||||
false;
|
false;
|
||||||
find_x_event([{xmlcdata, _} | Els]) ->
|
find_x_event([#xmlel{ns = ?NS_MESSAGE_EVENT} = El | _Els]) ->
|
||||||
find_x_event(Els);
|
El;
|
||||||
find_x_event([El | Els]) ->
|
find_x_event([_ | Els]) ->
|
||||||
case xml:get_tag_attr_s("xmlns", El) of
|
find_x_event(Els).
|
||||||
?NS_EVENT ->
|
|
||||||
El;
|
|
||||||
_ ->
|
|
||||||
find_x_event(Els)
|
|
||||||
end.
|
|
||||||
|
|
||||||
find_x_expire(_, []) ->
|
find_x_expire(_, []) ->
|
||||||
never;
|
never;
|
||||||
find_x_expire(TimeStamp, [{xmlcdata, _} | Els]) ->
|
find_x_expire(TimeStamp, [#xmlel{ns = ?NS_MESSAGE_EXPIRE} = El | _Els]) ->
|
||||||
find_x_expire(TimeStamp, Els);
|
Val = exmpp_xml:get_attribute(El, 'seconds', ""),
|
||||||
find_x_expire(TimeStamp, [El | Els]) ->
|
case catch list_to_integer(Val) of
|
||||||
case xml:get_tag_attr_s("xmlns", El) of
|
{'EXIT', _} ->
|
||||||
?NS_EXPIRE ->
|
never;
|
||||||
Val = xml:get_tag_attr_s("seconds", El),
|
Int when Int > 0 ->
|
||||||
case catch list_to_integer(Val) of
|
{MegaSecs, Secs, MicroSecs} = TimeStamp,
|
||||||
{'EXIT', _} ->
|
S = MegaSecs * 1000000 + Secs + Int,
|
||||||
never;
|
MegaSecs1 = S div 1000000,
|
||||||
Int when Int > 0 ->
|
Secs1 = S rem 1000000,
|
||||||
{MegaSecs, Secs, MicroSecs} = TimeStamp,
|
{MegaSecs1, Secs1, MicroSecs};
|
||||||
S = MegaSecs * 1000000 + Secs + Int,
|
|
||||||
MegaSecs1 = S div 1000000,
|
|
||||||
Secs1 = S rem 1000000,
|
|
||||||
{MegaSecs1, Secs1, MicroSecs};
|
|
||||||
_ ->
|
|
||||||
never
|
|
||||||
end;
|
|
||||||
_ ->
|
_ ->
|
||||||
find_x_expire(TimeStamp, Els)
|
never
|
||||||
end.
|
end;
|
||||||
|
find_x_expire(TimeStamp, [_ | Els]) ->
|
||||||
|
find_x_expire(TimeStamp, Els).
|
||||||
|
|
||||||
|
|
||||||
resend_offline_messages(User, Server) ->
|
resend_offline_messages(User, Server) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
Rs = mnesia:wread({offline_msg, US}),
|
Rs = mnesia:wread({offline_msg, US}),
|
||||||
@ -250,16 +245,22 @@ resend_offline_messages(User, Server) ->
|
|||||||
{atomic, Rs} ->
|
{atomic, Rs} ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(R) ->
|
fun(R) ->
|
||||||
{xmlelement, Name, Attrs, Els} = R#offline_msg.packet,
|
Packet = case R#offline_msg.packet of
|
||||||
|
#xmlelement{} = P ->
|
||||||
|
exmpp_xml:xmlelement_to_xmlel(P,
|
||||||
|
[?DEFAULT_NS], ?PREFIXED_NS);
|
||||||
|
#xmlel{} = P ->
|
||||||
|
P
|
||||||
|
end,
|
||||||
|
% XXX OLD FORMAT: Convert From & To.
|
||||||
ejabberd_sm !
|
ejabberd_sm !
|
||||||
{route,
|
{route,
|
||||||
R#offline_msg.from,
|
jlib:from_old_jid(R#offline_msg.from),
|
||||||
R#offline_msg.to,
|
jlib:from_old_jid(R#offline_msg.to),
|
||||||
{xmlelement, Name, Attrs,
|
exmpp_xml:append_child(Packet,
|
||||||
Els ++
|
jlib:timestamp_to_xml(
|
||||||
[jlib:timestamp_to_xml(
|
|
||||||
calendar:now_to_universal_time(
|
calendar:now_to_universal_time(
|
||||||
R#offline_msg.timestamp))]}}
|
R#offline_msg.timestamp)))}
|
||||||
end,
|
end,
|
||||||
lists:keysort(#offline_msg.timestamp, Rs));
|
lists:keysort(#offline_msg.timestamp, Rs));
|
||||||
_ ->
|
_ ->
|
||||||
@ -267,8 +268,8 @@ resend_offline_messages(User, Server) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
pop_offline_messages(Ls, User, Server) ->
|
pop_offline_messages(Ls, User, Server) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
Rs = mnesia:wread({offline_msg, US}),
|
Rs = mnesia:wread({offline_msg, US}),
|
||||||
@ -280,15 +281,21 @@ pop_offline_messages(Ls, User, Server) ->
|
|||||||
TS = now(),
|
TS = now(),
|
||||||
Ls ++ lists:map(
|
Ls ++ lists:map(
|
||||||
fun(R) ->
|
fun(R) ->
|
||||||
{xmlelement, Name, Attrs, Els} = R#offline_msg.packet,
|
Packet = case R#offline_msg.packet of
|
||||||
|
#xmlelement{} = P ->
|
||||||
|
exmpp_xml:xmlelement_to_xmlel(P,
|
||||||
|
[?DEFAULT_NS], ?PREFIXED_NS);
|
||||||
|
#xmlel{} = P ->
|
||||||
|
P
|
||||||
|
end,
|
||||||
|
% XXX OLD FORMAT: Convert From & To.
|
||||||
{route,
|
{route,
|
||||||
R#offline_msg.from,
|
jlib:from_old_jid(R#offline_msg.from),
|
||||||
R#offline_msg.to,
|
jlib:from_old_jid(R#offline_msg.to),
|
||||||
{xmlelement, Name, Attrs,
|
exmpp_xml:append_child(Packet,
|
||||||
Els ++
|
jlib:timestamp_to_xml(
|
||||||
[jlib:timestamp_to_xml(
|
|
||||||
calendar:now_to_universal_time(
|
calendar:now_to_universal_time(
|
||||||
R#offline_msg.timestamp))]}}
|
R#offline_msg.timestamp)))}
|
||||||
end,
|
end,
|
||||||
lists:filter(
|
lists:filter(
|
||||||
fun(R) ->
|
fun(R) ->
|
||||||
@ -343,8 +350,8 @@ remove_old_messages(Days) ->
|
|||||||
mnesia:transaction(F).
|
mnesia:transaction(F).
|
||||||
|
|
||||||
remove_user(User, Server) ->
|
remove_user(User, Server) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
mnesia:delete({offline_msg, US})
|
mnesia:delete({offline_msg, US})
|
||||||
@ -371,10 +378,15 @@ update_table() ->
|
|||||||
F1 = fun() ->
|
F1 = fun() ->
|
||||||
mnesia:write_lock_table(mod_offline_tmp_table),
|
mnesia:write_lock_table(mod_offline_tmp_table),
|
||||||
mnesia:foldl(
|
mnesia:foldl(
|
||||||
fun(#offline_msg{us = U} = R, _) ->
|
fun(#offline_msg{us = U, packet = P} = R, _) ->
|
||||||
|
New_R = R#offline_msg{
|
||||||
|
us = {U, Host},
|
||||||
|
packet = exmpp_xml:xmlelement_to_xmlel(P,
|
||||||
|
[?DEFAULT_NS], ?PREFIXED_NS)
|
||||||
|
},
|
||||||
mnesia:dirty_write(
|
mnesia:dirty_write(
|
||||||
mod_offline_tmp_table,
|
mod_offline_tmp_table,
|
||||||
R#offline_msg{us = {U, Host}})
|
New_R)
|
||||||
end, ok, offline_msg)
|
end, ok, offline_msg)
|
||||||
end,
|
end,
|
||||||
mnesia:transaction(F1),
|
mnesia:transaction(F1),
|
||||||
@ -402,8 +414,7 @@ update_table() ->
|
|||||||
mnesia:transform_table(
|
mnesia:transform_table(
|
||||||
offline_msg,
|
offline_msg,
|
||||||
fun({_, U, TS, F, T, P}) ->
|
fun({_, U, TS, F, T, P}) ->
|
||||||
{xmlelement, _Name, _Attrs, Els} = P,
|
Expire = find_x_expire(TS, P#xmlelement.children),
|
||||||
Expire = find_x_expire(TS, Els),
|
|
||||||
#offline_msg{us = U,
|
#offline_msg{us = U,
|
||||||
timestamp = TS,
|
timestamp = TS,
|
||||||
expire = Expire,
|
expire = Expire,
|
||||||
@ -442,14 +453,21 @@ update_table() ->
|
|||||||
%% Warn senders that their messages have been discarded:
|
%% Warn senders that their messages have been discarded:
|
||||||
discard_warn_sender(Msgs) ->
|
discard_warn_sender(Msgs) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(#offline_msg{from=From, to=To, packet=Packet}) ->
|
fun(#offline_msg{from=From, to=To, packet=Packet0}) ->
|
||||||
|
Packet = case Packet0 of
|
||||||
|
#xmlelement{} = P ->
|
||||||
|
exmpp_xml:xmlelement_to_xmlel(P,
|
||||||
|
[?DEFAULT_NS], ?PREFIXED_NS);
|
||||||
|
#xmlel{} = P ->
|
||||||
|
P
|
||||||
|
end,
|
||||||
ErrText = "Your contact offline message queue is full. The message has been discarded.",
|
ErrText = "Your contact offline message queue is full. The message has been discarded.",
|
||||||
Lang = xml:get_tag_attr_s("xml:lang", Packet),
|
Error = exmpp_stanza:error('resource-constraint',
|
||||||
Err = jlib:make_error_reply(
|
{"en", ErrText}),
|
||||||
Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
|
Err = exmpp_stanza:reply_with_error(Packet, Error),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
To,
|
jlib:from_old_jid(To),
|
||||||
From, Err)
|
jlib:from_old_jid(From), Err)
|
||||||
end, Msgs).
|
end, Msgs).
|
||||||
|
|
||||||
|
|
||||||
@ -464,14 +482,14 @@ webadmin_page(_, Host,
|
|||||||
webadmin_page(Acc, _, _) -> Acc.
|
webadmin_page(Acc, _, _) -> Acc.
|
||||||
|
|
||||||
user_queue(User, Server, Query, Lang) ->
|
user_queue(User, Server, Query, Lang) ->
|
||||||
US = {jlib:nodeprep(User), jlib:nameprep(Server)},
|
US = {exmpp_stringprep:nodeprep(User), exmpp_stringprep:nameprep(Server)},
|
||||||
Res = user_queue_parse_query(US, Query),
|
Res = user_queue_parse_query(US, Query),
|
||||||
Msgs = lists:keysort(#offline_msg.timestamp,
|
Msgs = lists:keysort(#offline_msg.timestamp,
|
||||||
mnesia:dirty_read({offline_msg, US})),
|
mnesia:dirty_read({offline_msg, US})),
|
||||||
FMsgs =
|
FMsgs =
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(#offline_msg{timestamp = TimeStamp, from = From, to = To,
|
fun(#offline_msg{timestamp = TimeStamp, from = From, to = To,
|
||||||
packet = {xmlelement, Name, Attrs, Els}} = Msg) ->
|
packet = Packet} = Msg) ->
|
||||||
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
||||||
{{Year, Month, Day}, {Hour, Minute, Second}} =
|
{{Year, Month, Day}, {Hour, Minute, Second}} =
|
||||||
calendar:now_to_local_time(TimeStamp),
|
calendar:now_to_local_time(TimeStamp),
|
||||||
@ -479,11 +497,14 @@ user_queue(User, Server, Query, Lang) ->
|
|||||||
io_lib:format(
|
io_lib:format(
|
||||||
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
||||||
[Year, Month, Day, Hour, Minute, Second])),
|
[Year, Month, Day, Hour, Minute, Second])),
|
||||||
SFrom = jlib:jid_to_string(From),
|
SFrom = exmpp_jid:jid_to_string(jlib:from_old_jid(From)),
|
||||||
STo = jlib:jid_to_string(To),
|
STo = exmpp_jid:jid_to_string(jlib:from_old_jid(To)),
|
||||||
Attrs2 = jlib:replace_from_to_attrs(SFrom, STo, Attrs),
|
Packet0 = exmpp_xml:xmlelement_to_xmlel(Packet,
|
||||||
Packet = {xmlelement, Name, Attrs2, Els},
|
[?DEFAULT_NS], ?PREFIXED_NS),
|
||||||
FPacket = ejabberd_web_admin:pretty_print_xml(Packet),
|
Packet1 = exmpp_stanza:set_jids(Packet0, SFrom, STo),
|
||||||
|
FPacket = exmpp_xml:node_to_list(
|
||||||
|
exmpp_xml:indent_document(Packet1, <<" ">>),
|
||||||
|
[?DEFAULT_NS], ?PREFIXED_NS),
|
||||||
?XE("tr",
|
?XE("tr",
|
||||||
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
||||||
?XAC("td", [{"class", "valign"}], Time),
|
?XAC("td", [{"class", "valign"}], Time),
|
||||||
@ -547,10 +568,10 @@ user_queue_parse_query(US, Query) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
us_to_list({User, Server}) ->
|
us_to_list({User, Server}) ->
|
||||||
jlib:jid_to_string({User, Server, ""}).
|
exmpp_jid:jid_to_string(User, Server).
|
||||||
|
|
||||||
webadmin_user(Acc, User, Server, Lang) ->
|
webadmin_user(Acc, User, Server, Lang) ->
|
||||||
US = {jlib:nodeprep(User), jlib:nameprep(Server)},
|
US = {exmpp_stringprep:nodeprep(User), exmpp_stringprep:nameprep(Server)},
|
||||||
QueueLen = length(mnesia:dirty_read({offline_msg, US})),
|
QueueLen = length(mnesia:dirty_read({offline_msg, US})),
|
||||||
FQueueLen = [?AC("queue/",
|
FQueueLen = [?AC("queue/",
|
||||||
integer_to_list(QueueLen))],
|
integer_to_list(QueueLen))],
|
||||||
|
@ -40,8 +40,9 @@
|
|||||||
webadmin_page/3,
|
webadmin_page/3,
|
||||||
webadmin_user/4]).
|
webadmin_user/4]).
|
||||||
|
|
||||||
|
-include_lib("exmpp/include/exmpp.hrl").
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
|
||||||
-include("web/ejabberd_http.hrl").
|
-include("web/ejabberd_http.hrl").
|
||||||
-include("web/ejabberd_web_admin.hrl").
|
-include("web/ejabberd_web_admin.hrl").
|
||||||
|
|
||||||
@ -50,6 +51,11 @@
|
|||||||
-define(PROCNAME, ejabberd_offline).
|
-define(PROCNAME, ejabberd_offline).
|
||||||
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
|
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
|
||||||
|
|
||||||
|
% These are the namespace already declared by the stream opening. This is
|
||||||
|
% used at serialization time.
|
||||||
|
-define(DEFAULT_NS, ?NS_JABBER_CLIENT).
|
||||||
|
-define(PREFIXED_NS, [{?NS_XMPP, ?NS_XMPP_pfx}]).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
ejabberd_hooks:add(offline_message_hook, Host,
|
ejabberd_hooks:add(offline_message_hook, Host,
|
||||||
?MODULE, store_packet, 50),
|
?MODULE, store_packet, 50),
|
||||||
@ -93,24 +99,20 @@ loop(Host, MaxOfflineMsgs) ->
|
|||||||
fun(M) ->
|
fun(M) ->
|
||||||
Username =
|
Username =
|
||||||
ejabberd_odbc:escape(
|
ejabberd_odbc:escape(
|
||||||
(M#offline_msg.to)#jid.luser),
|
(M#offline_msg.to)#jid.lnode),
|
||||||
From = M#offline_msg.from,
|
From = M#offline_msg.from,
|
||||||
To = M#offline_msg.to,
|
To = M#offline_msg.to,
|
||||||
{xmlelement, Name, Attrs, Els} =
|
Packet0 = exmpp_stanza:set_jids(
|
||||||
M#offline_msg.packet,
|
From,
|
||||||
Attrs2 = jlib:replace_from_to_attrs(
|
To,
|
||||||
jlib:jid_to_string(From),
|
M#offline_msg.packet),
|
||||||
jlib:jid_to_string(To),
|
Packet1 = exmpp_xml:append_child(Packet0,
|
||||||
Attrs),
|
jlib:timestamp_to_xml(
|
||||||
Packet = {xmlelement, Name, Attrs2,
|
|
||||||
Els ++
|
|
||||||
[jlib:timestamp_to_xml(
|
|
||||||
calendar:now_to_universal_time(
|
calendar:now_to_universal_time(
|
||||||
M#offline_msg.timestamp))]},
|
M#offline_msg.timestamp))),
|
||||||
XML =
|
XML =
|
||||||
ejabberd_odbc:escape(
|
ejabberd_odbc:escape(
|
||||||
lists:flatten(
|
exmpp_xml:document_to_string(Packet1)),
|
||||||
xml:element_to_string(Packet))),
|
|
||||||
odbc_queries:add_spool_sql(Username, XML)
|
odbc_queries:add_spool_sql(Username, XML)
|
||||||
end, Msgs),
|
end, Msgs),
|
||||||
case catch odbc_queries:add_spool(Host, Query) of
|
case catch odbc_queries:add_spool(Host, Query) of
|
||||||
@ -152,17 +154,16 @@ stop(Host) ->
|
|||||||
ok.
|
ok.
|
||||||
|
|
||||||
store_packet(From, To, Packet) ->
|
store_packet(From, To, Packet) ->
|
||||||
Type = xml:get_tag_attr_s("type", Packet),
|
Type = exmpp_stanza_:get_type(Packet, 'type'),
|
||||||
if
|
if
|
||||||
(Type /= "error") and (Type /= "groupchat") and
|
(Type /= "error") and (Type /= "groupchat") and
|
||||||
(Type /= "headline") ->
|
(Type /= "headline") ->
|
||||||
case check_event(From, To, Packet) of
|
case check_event(From, To, Packet) of
|
||||||
true ->
|
true ->
|
||||||
#jid{luser = LUser} = To,
|
#jid{lnode = LUser} = To,
|
||||||
TimeStamp = now(),
|
TimeStamp = now(),
|
||||||
{xmlelement, _Name, _Attrs, Els} = Packet,
|
Expire = find_x_expire(TimeStamp, Packet#xmlel.children),
|
||||||
Expire = find_x_expire(TimeStamp, Els),
|
gen_mod:get_module_proc(To#jid.ldomain, ?PROCNAME) !
|
||||||
gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) !
|
|
||||||
#offline_msg{user = LUser,
|
#offline_msg{user = LUser,
|
||||||
timestamp = TimeStamp,
|
timestamp = TimeStamp,
|
||||||
expire = Expire,
|
expire = Expire,
|
||||||
@ -178,31 +179,27 @@ store_packet(From, To, Packet) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
check_event(From, To, Packet) ->
|
check_event(From, To, Packet) ->
|
||||||
{xmlelement, Name, Attrs, Els} = Packet,
|
case find_x_event(Packet#xmlel.children) of
|
||||||
case find_x_event(Els) of
|
|
||||||
false ->
|
false ->
|
||||||
true;
|
true;
|
||||||
El ->
|
El ->
|
||||||
case xml:get_subtag(El, "id") of
|
case exmpp_xml:get_element(El, 'id') of
|
||||||
false ->
|
undefined ->
|
||||||
case xml:get_subtag(El, "offline") of
|
case exmpp_xml:get_element(El, 'offline') of
|
||||||
false ->
|
undefined ->
|
||||||
true;
|
true;
|
||||||
_ ->
|
_ ->
|
||||||
ID = case xml:get_tag_attr_s("id", Packet) of
|
ID = case exmpp_xml:get_attribute(Packet, 'id', "") of
|
||||||
"" ->
|
"" ->
|
||||||
{xmlelement, "id", [], []};
|
#xmlel{ns = ?NS_MESSAGE_EVENT, name = 'id'};
|
||||||
S ->
|
S ->
|
||||||
{xmlelement, "id", [],
|
#xmlel{ns = ?NS_MESSAGE_EVENT, name = 'id',
|
||||||
[{xmlcdata, S}]}
|
children = [#xmlcdata{cdata = list_to_binary(S)}]}
|
||||||
end,
|
end,
|
||||||
|
X = #xmlel{ns = ?NS_MESSAGE_EVENT, name = 'x', children =
|
||||||
|
[ID, #xmlel{ns = ?NS_MESSAGE_EVENT, name = 'offline'}]},
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
To, From, {xmlelement, Name, Attrs,
|
To, From, exmpp_xml:set_children(Packet, [X])),
|
||||||
[{xmlelement, "x",
|
|
||||||
[{"xmlns", ?NS_EVENT}],
|
|
||||||
[ID,
|
|
||||||
{xmlelement, "offline", [], []}]}]
|
|
||||||
}),
|
|
||||||
true
|
true
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
@ -212,64 +209,49 @@ check_event(From, To, Packet) ->
|
|||||||
|
|
||||||
find_x_event([]) ->
|
find_x_event([]) ->
|
||||||
false;
|
false;
|
||||||
find_x_event([{xmlcdata, _} | Els]) ->
|
find_x_event([#xmlel{ns = ?NS_MESSAGE_EVENT} = El | _Els]) ->
|
||||||
find_x_event(Els);
|
El;
|
||||||
find_x_event([El | Els]) ->
|
find_x_event([_ | Els]) ->
|
||||||
case xml:get_tag_attr_s("xmlns", El) of
|
find_x_event(Els).
|
||||||
?NS_EVENT ->
|
|
||||||
El;
|
|
||||||
_ ->
|
|
||||||
find_x_event(Els)
|
|
||||||
end.
|
|
||||||
|
|
||||||
find_x_expire(_, []) ->
|
find_x_expire(_, []) ->
|
||||||
never;
|
never;
|
||||||
find_x_expire(TimeStamp, [{xmlcdata, _} | Els]) ->
|
find_x_expire(TimeStamp, [#xmlel{ns = ?NS_MESSAGE_EXPIRE} = El | _Els]) ->
|
||||||
find_x_expire(TimeStamp, Els);
|
Val = exmpp_xml:get_attribute(El, 'seconds', ""),
|
||||||
find_x_expire(TimeStamp, [El | Els]) ->
|
case catch list_to_integer(Val) of
|
||||||
case xml:get_tag_attr_s("xmlns", El) of
|
{'EXIT', _} ->
|
||||||
?NS_EXPIRE ->
|
never;
|
||||||
Val = xml:get_tag_attr_s("seconds", El),
|
Int when Int > 0 ->
|
||||||
case catch list_to_integer(Val) of
|
{MegaSecs, Secs, MicroSecs} = TimeStamp,
|
||||||
{'EXIT', _} ->
|
S = MegaSecs * 1000000 + Secs + Int,
|
||||||
never;
|
MegaSecs1 = S div 1000000,
|
||||||
Int when Int > 0 ->
|
Secs1 = S rem 1000000,
|
||||||
{MegaSecs, Secs, MicroSecs} = TimeStamp,
|
{MegaSecs1, Secs1, MicroSecs};
|
||||||
S = MegaSecs * 1000000 + Secs + Int,
|
|
||||||
MegaSecs1 = S div 1000000,
|
|
||||||
Secs1 = S rem 1000000,
|
|
||||||
{MegaSecs1, Secs1, MicroSecs};
|
|
||||||
_ ->
|
|
||||||
never
|
|
||||||
end;
|
|
||||||
_ ->
|
_ ->
|
||||||
find_x_expire(TimeStamp, Els)
|
never
|
||||||
end.
|
end;
|
||||||
|
find_x_expire(TimeStamp, [_ | Els]) ->
|
||||||
|
find_x_expire(TimeStamp, Els).
|
||||||
|
|
||||||
|
|
||||||
pop_offline_messages(Ls, User, Server) ->
|
pop_offline_messages(Ls, User, Server) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
EUser = ejabberd_odbc:escape(LUser),
|
EUser = ejabberd_odbc:escape(LUser),
|
||||||
case odbc_queries:get_and_del_spool_msg_t(LServer, EUser) of
|
case odbc_queries:get_and_del_spool_msg_t(LServer, EUser) of
|
||||||
{atomic, {selected, ["username","xml"], Rs}} ->
|
{atomic, {selected, ["username","xml"], Rs}} ->
|
||||||
Ls ++ lists:flatmap(
|
Ls ++ lists:flatmap(
|
||||||
fun({_, XML}) ->
|
fun({_, XML}) ->
|
||||||
case xml_stream:parse_element(XML) of
|
try
|
||||||
{error, _Reason} ->
|
[El] = exmpp_xml:parse_document(XML, [namespace, name_as_atom]),
|
||||||
[];
|
To = exmpp_jid:list_to_jid(
|
||||||
El ->
|
exmpp_stanza:get_recipient(El)),
|
||||||
To = jlib:string_to_jid(
|
From = exmpp_jid:list_to_jid(
|
||||||
xml:get_tag_attr_s("to", El)),
|
exmpp_stanza:get_sender(El)),
|
||||||
From = jlib:string_to_jid(
|
[{route, From, To, El}]
|
||||||
xml:get_tag_attr_s("from", El)),
|
catch
|
||||||
if
|
_ ->
|
||||||
(To /= error) and
|
[]
|
||||||
(From /= error) ->
|
|
||||||
[{route, From, To, El}];
|
|
||||||
true ->
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end, Rs);
|
end, Rs);
|
||||||
_ ->
|
_ ->
|
||||||
@ -278,8 +260,8 @@ pop_offline_messages(Ls, User, Server) ->
|
|||||||
|
|
||||||
|
|
||||||
remove_user(User, Server) ->
|
remove_user(User, Server) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
Username = ejabberd_odbc:escape(LUser),
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
odbc_queries:del_spool_msg(LServer, Username).
|
odbc_queries:del_spool_msg(LServer, Username).
|
||||||
|
|
||||||
@ -294,9 +276,9 @@ discard_warn_sender(Msgs) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(#offline_msg{from=From, to=To, packet=Packet}) ->
|
fun(#offline_msg{from=From, to=To, packet=Packet}) ->
|
||||||
ErrText = "Your contact offline message queue is full. The message has been discarded.",
|
ErrText = "Your contact offline message queue is full. The message has been discarded.",
|
||||||
Lang = xml:get_tag_attr_s("xml:lang", Packet),
|
Error = exmpp_stanza:error('resource-constraint',
|
||||||
Err = jlib:make_error_reply(
|
{"en", ErrText}),
|
||||||
Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
|
Err = exmpp_stanza:reply_with_error(Packet, Error),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
To,
|
To,
|
||||||
From, Err)
|
From, Err)
|
||||||
@ -314,8 +296,8 @@ webadmin_page(_, Host,
|
|||||||
webadmin_page(Acc, _, _) -> Acc.
|
webadmin_page(Acc, _, _) -> Acc.
|
||||||
|
|
||||||
user_queue(User, Server, Query, Lang) ->
|
user_queue(User, Server, Query, Lang) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
Username = ejabberd_odbc:escape(LUser),
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
Res = user_queue_parse_query(Username, LServer, Query),
|
Res = user_queue_parse_query(Username, LServer, Query),
|
||||||
@ -327,11 +309,12 @@ user_queue(User, Server, Query, Lang) ->
|
|||||||
{selected, ["username", "xml"], Rs} ->
|
{selected, ["username", "xml"], Rs} ->
|
||||||
lists:flatmap(
|
lists:flatmap(
|
||||||
fun({_, XML}) ->
|
fun({_, XML}) ->
|
||||||
case xml_stream:parse_element(XML) of
|
try exmpp_xml:parse_document(XML, [namespace, name_as_atom]) of
|
||||||
{error, _Reason} ->
|
[El] ->
|
||||||
[];
|
|
||||||
El ->
|
|
||||||
[El]
|
[El]
|
||||||
|
catch
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
end
|
end
|
||||||
end, Rs);
|
end, Rs);
|
||||||
_ ->
|
_ ->
|
||||||
@ -339,10 +322,12 @@ user_queue(User, Server, Query, Lang) ->
|
|||||||
end,
|
end,
|
||||||
FMsgs =
|
FMsgs =
|
||||||
lists:map(
|
lists:map(
|
||||||
fun({xmlelement, _Name, _Attrs, _Els} = Msg) ->
|
fun(#xmlel{} = Msg) ->
|
||||||
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
||||||
Packet = Msg,
|
Packet = Msg,
|
||||||
FPacket = ejabberd_web_admin:pretty_print_xml(Packet),
|
FPacket = exmpp_xml:node_to_list(
|
||||||
|
exmpp_xml:indent_document(Packet, <<" ">>),
|
||||||
|
[?DEFAULT_NS], ?PREFIXED_NS),
|
||||||
?XE("tr",
|
?XE("tr",
|
||||||
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
||||||
?XAE("td", [{"class", "valign"}], [?XC("pre", FPacket)])]
|
?XAE("td", [{"class", "valign"}], [?XC("pre", FPacket)])]
|
||||||
@ -386,11 +371,12 @@ user_queue_parse_query(Username, LServer, Query) ->
|
|||||||
{selected, ["xml", "seq"], Rs} ->
|
{selected, ["xml", "seq"], Rs} ->
|
||||||
lists:flatmap(
|
lists:flatmap(
|
||||||
fun({XML, Seq}) ->
|
fun({XML, Seq}) ->
|
||||||
case xml_stream:parse_element(XML) of
|
try exmpp_xml:parse_document(XML, [namespace, name_as_atom]) of
|
||||||
{error, _Reason} ->
|
[El] ->
|
||||||
[];
|
|
||||||
El ->
|
|
||||||
[{El, Seq}]
|
[{El, Seq}]
|
||||||
|
catch
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
end
|
end
|
||||||
end, Rs);
|
end, Rs);
|
||||||
_ ->
|
_ ->
|
||||||
@ -421,11 +407,11 @@ user_queue_parse_query(Username, LServer, Query) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
us_to_list({User, Server}) ->
|
us_to_list({User, Server}) ->
|
||||||
jlib:jid_to_string({User, Server, ""}).
|
exmpp_jid:jid_to_list(User, Server).
|
||||||
|
|
||||||
webadmin_user(Acc, User, Server, Lang) ->
|
webadmin_user(Acc, User, Server, Lang) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = exmpp_stringprep:nodeprep(User),
|
||||||
LServer = jlib:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
Username = ejabberd_odbc:escape(LUser),
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
QueueLen = case catch ejabberd_odbc:sql_query(
|
QueueLen = case catch ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
|
Loading…
Reference in New Issue
Block a user