25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-30 16:36:29 +01:00

Big #jid to binary() conversion.

Internal tables (ejabberd_router, ejabberd_sm, ejabberd_hooks, mod_last, mod_roster) use binary() as storage.
Basic test using the ODBC backend.

SVN Revision: 1770
This commit is contained in:
Pablo Polvorin 2009-01-03 15:15:38 +00:00
parent 1a44fe29b4
commit 4827db4f56
44 changed files with 1129 additions and 881 deletions

View File

@ -1,3 +1,29 @@
2009-01-03 Pablo Polvorin <pablo.polvorin@process-one.net>
* src/mod_pubsub_node_default.erl: Fix typo
* src/mod_vcard.erl, src/mod_vcard_ldap.erl,src/ ejabberd_hooks.erl,
mod_muc/mod_muc_room.erl, src/mod_muc/mod_muc.erl,
src/mod_muc/mod_muc_log.erl, src/mod_shared_roster.erl,
src/ejabberd_auth_odbc.erl, src/mod_offline_odbc.erl,
src/ejabberd_system_monitor.erl, src/ejabberd_s2s_in.erl,
src/mod_configure.erl, src/ejabberd_receiver.erl, src/mod_irc/mod_irc.erl,
src/ejabberd_sm.erl, src/mod_privacy_odbc.erl, src/ejabberd_c2s.erl,
src/mod_announce.erl, src/ejabberd_local.erl, src/mod_privacy.erl,
src/ejabberd_auth_internal.erl, src/mod_adhoc.erl, src/mod_echo.erl,
src/jlib.erl, src/mod_vcard_odbc.erl, src/ejabberd_s2s.erl,
src/mod_stats.erl, src/ejabberd_router.erl, src/mod_last.erl,
src/mod_private.erl, src/mod_roster.erl, src/ejabberd_service.erl,
src/mod_disco.erl, src/mod_private_odbc.erl, src/mod_service_log.erl,
src/mod_configure2.erl, src/mod_roster_odbc.erl, src/mod_offline.erl,
src/mod_register.erl, src/mod_version.erl, src/mod_caps.erl,
src/mod_last_odbc.erl: Use exmpp API to access JID fields. Keep
#jid fields in binary format when possible. Change all 'user' and
'server' arguments in all hooks to binary. Change internal tables of
ejabberd_sm, ejabberd_router, ejabberd_hooks, mod_last, mod_roster
to use binary() storage.
2009-01-03 Christophe Romain <christophe.romain@process-one.net> 2009-01-03 Christophe Romain <christophe.romain@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: deliver notification depending on * src/mod_pubsub/mod_pubsub.erl: deliver notification depending on

View File

@ -261,7 +261,9 @@ remove_user(User, Server) ->
mnesia:delete({passwd, US}) mnesia:delete({passwd, US})
end, end,
mnesia:transaction(F), mnesia:transaction(F),
ejabberd_hooks:run(remove_user, LServer, [User, Server]) ejabberd_hooks:run(remove_user,
list_to_binary(LServer),
[list_to_binary(User), list_to_binary(Server)])
catch catch
_ -> _ ->
ok ok
@ -285,7 +287,9 @@ remove_user(User, Server, Password) ->
end, end,
case mnesia:transaction(F) of case mnesia:transaction(F) of
{atomic, ok} -> {atomic, ok} ->
ejabberd_hooks:run(remove_user, LServer, [User, Server]), ejabberd_hooks:run(remove_user,
list_to_binary(LServer),
[list_to_binary(User), list_to_binary(Server)]),
ok; ok;
{atomic, Res} -> {atomic, Res} ->
Res; Res;

View File

@ -231,8 +231,8 @@ remove_user(User, Server) ->
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
catch odbc_queries:del_user(LServer, Username), catch odbc_queries:del_user(LServer, Username),
ejabberd_hooks:run(remove_user, exmpp_stringprep:nameprep(Server), ejabberd_hooks:run(remove_user, list_to_binary(LServer),
[User, Server]) [list_to_binary(User), list_to_binary(Server)])
catch catch
_ -> _ ->
error error
@ -249,8 +249,8 @@ remove_user(User, Server, Password) ->
LServer, Username, Pass), LServer, Username, Pass),
case Result of case Result of
{selected, ["password"], [{Password}]} -> {selected, ["password"], [{Password}]} ->
ejabberd_hooks:run(remove_user, exmpp_stringprep:nameprep(Server), ejabberd_hooks:run(remove_user, list_to_binary(LServer),
[User, Server]), [list_to_binary(User), list_to_binary(Server)]),
ok; ok;
{selected, ["password"], []} -> {selected, ["password"], []} ->
not_exists; not_exists;

View File

@ -37,7 +37,8 @@
send_element/2, send_element/2,
socket_type/0, socket_type/0,
get_presence/1, get_presence/1,
get_subscribed/1]). get_subscribed/1,
get_subscribed_and_online/1]).
%% gen_fsm callbacks %% gen_fsm callbacks
-export([init/1, -export([init/1,
@ -54,6 +55,9 @@
handle_info/3, handle_info/3,
terminate/3]). terminate/3]).
-export([get_state/1]).
-include_lib("exmpp/include/exmpp.hrl"). -include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -78,12 +82,13 @@
tls_options = [], tls_options = [],
authenticated = false, authenticated = false,
jid, jid,
user = undefined, server = ?MYNAME, resource = undefined, user = undefined, server = list_to_binary(?MYNAME), resource = undefined,
sid, sid,
pres_t = ?SETS:new(), pres_t = ?SETS:new(),
pres_f = ?SETS:new(), pres_f = ?SETS:new(),
pres_a = ?SETS:new(), pres_a = ?SETS:new(),
pres_i = ?SETS:new(), pres_i = ?SETS:new(),
pres_available = ?DICT:new(),
pres_last, pres_pri, pres_last, pres_pri,
pres_timestamp, pres_timestamp,
pres_invis = false, pres_invis = false,
@ -98,7 +103,7 @@
-ifdef(DBGFSM). -ifdef(DBGFSM).
-define(FSMOPTS, [{debug, [trace]}]). -define(FSMOPTS, [{debug, [trace]}]).
-else. -else.
-define(FSMOPTS, []). -define(FSMOPTS, [{spawn_opt,[{fullsweep_after,10}]}]).
-endif. -endif.
%% Module start with or without supervisor: %% Module start with or without supervisor:
@ -142,6 +147,11 @@ socket_type() ->
get_presence(FsmRef) -> get_presence(FsmRef) ->
gen_fsm:sync_send_all_state_event(FsmRef, {get_presence}, 1000). gen_fsm:sync_send_all_state_event(FsmRef, {get_presence}, 1000).
%%TODO: for debug only
get_state(FsmRef) ->
gen_fsm:sync_send_all_state_event(FsmRef, get_state, 1000).
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% Callback functions from gen_fsm %%% Callback functions from gen_fsm
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
@ -170,7 +180,6 @@ init([{SockMod, Socket}, Opts]) ->
TLSOpts = lists:filter(fun({certfile, _}) -> true; TLSOpts = lists:filter(fun({certfile, _}) -> true;
(_) -> false (_) -> false
end, Opts), end, Opts),
Zlib = lists:member(zlib, Opts) andalso (not StartTLSRequired),
IP = peerip(SockMod, Socket), IP = peerip(SockMod, Socket),
%% Check if IP is blacklisted: %% Check if IP is blacklisted:
case is_ip_blacklisted(IP) of case is_ip_blacklisted(IP) of
@ -203,8 +212,14 @@ init([{SockMod, Socket}, Opts]) ->
end. end.
%% Return list of all available resources of contacts, %% Return list of all available resources of contacts,
%% in form [{JID, Caps}].
get_subscribed(FsmRef) -> get_subscribed(FsmRef) ->
gen_fsm:sync_send_all_state_event(FsmRef, get_subscribed, 1000). gen_fsm:sync_send_all_state_event(
FsmRef, get_subscribed, 1000).
get_subscribed_and_online(FsmRef) ->
gen_fsm:sync_send_all_state_event(
FsmRef, get_subscribed_and_online, 1000).
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
%% Func: StateName/2 %% Func: StateName/2
@ -226,6 +241,7 @@ wait_for_stream({xmlstreamstart, #xmlel{ns = NS} = Opening}, StateData) ->
?NS_XMPP -> ?NS_XMPP ->
Server = exmpp_stringprep:nameprep( Server = exmpp_stringprep:nameprep(
exmpp_stream:get_receiving_entity(Opening)), exmpp_stream:get_receiving_entity(Opening)),
ServerB = list_to_binary(Server),
case lists:member(Server, ?MYHOSTS) of case lists:member(Server, ?MYHOSTS) of
true -> true ->
Lang = exmpp_stream:get_lang(Opening), Lang = exmpp_stream:get_lang(Opening),
@ -275,7 +291,7 @@ wait_for_stream({xmlstreamstart, #xmlel{ns = NS} = Opening}, StateData) ->
end, end,
Other_Feats = ejabberd_hooks:run_fold( Other_Feats = ejabberd_hooks:run_fold(
c2s_stream_features, c2s_stream_features,
Server, ServerB,
[], []), [], []),
send_element(StateData, send_element(StateData,
exmpp_stream:features( exmpp_stream:features(
@ -285,7 +301,7 @@ wait_for_stream({xmlstreamstart, #xmlel{ns = NS} = Opening}, StateData) ->
Other_Feats)), Other_Feats)),
fsm_next_state(wait_for_feature_request, fsm_next_state(wait_for_feature_request,
StateData#state{ StateData#state{
server = Server, server = ServerB,
sasl_state = SASLState, sasl_state = SASLState,
lang = Lang}); lang = Lang});
_ -> _ ->
@ -299,7 +315,7 @@ wait_for_stream({xmlstreamstart, #xmlel{ns = NS} = Opening}, StateData) ->
])), ])),
fsm_next_state(wait_for_bind, fsm_next_state(wait_for_bind,
StateData#state{ StateData#state{
server = Server, server = ServerB,
lang = Lang}); lang = Lang});
_ -> _ ->
send_element( send_element(
@ -307,7 +323,7 @@ wait_for_stream({xmlstreamstart, #xmlel{ns = NS} = Opening}, StateData) ->
exmpp_stream:features([])), exmpp_stream:features([])),
fsm_next_state(wait_for_session, fsm_next_state(wait_for_session,
StateData#state{ StateData#state{
server = Server, server = ServerB,
lang = Lang}) lang = Lang})
end end
end; end;
@ -324,7 +340,7 @@ wait_for_stream({xmlstreamstart, #xmlel{ns = NS} = Opening}, StateData) ->
send_element(StateData, Header), send_element(StateData, Header),
fsm_next_state(wait_for_auth, fsm_next_state(wait_for_auth,
StateData#state{ StateData#state{
server = Server, server = ServerB,
lang = Lang}) lang = Lang})
end end
end; end;
@ -368,10 +384,11 @@ wait_for_stream(closed, StateData) ->
wait_for_auth({xmlstreamelement, El}, StateData) -> wait_for_auth({xmlstreamelement, El}, StateData) ->
ServerString = binary_to_list(StateData#state.server),
case is_auth_packet(El) of case is_auth_packet(El) of
{auth, _ID, get, {_U, _, _, _}} -> {auth, _ID, get, {_U, _, _, _}} ->
Fields = case ejabberd_auth:plain_password_required( Fields = case ejabberd_auth:plain_password_required(
StateData#state.server) of ServerString) of
false -> both; false -> both;
true -> plain true -> plain
end, end,
@ -386,11 +403,12 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
{auth, _ID, set, {U, P, D, R}} -> {auth, _ID, set, {U, P, D, R}} ->
try try
JID = exmpp_jid:make_jid(U, StateData#state.server, R), JID = exmpp_jid:make_jid(U, StateData#state.server, R),
case acl:match_rule(StateData#state.server, UBinary = exmpp_jid:lnode(JID),
case acl:match_rule(ServerString,
StateData#state.access, JID) of StateData#state.access, JID) of
allow -> allow ->
case ejabberd_auth:check_password_with_authmodule( case ejabberd_auth:check_password_with_authmodule(
U, StateData#state.server, P, U, ServerString, P,
StateData#state.streamid, D) of StateData#state.streamid, D) of
{true, AuthModule} -> {true, AuthModule} ->
?INFO_MSG( ?INFO_MSG(
@ -402,7 +420,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
Info = [{ip, StateData#state.ip}, {conn, Conn}, Info = [{ip, StateData#state.ip}, {conn, Conn},
{auth_module, AuthModule}], {auth_module, AuthModule}],
ejabberd_sm:open_session( ejabberd_sm:open_session(
SID, U, StateData#state.server, R, Info), SID, exmpp_jid:make_jid(U, StateData#state.server, R), Info),
Res = exmpp_server_legacy_auth:success(El), Res = exmpp_server_legacy_auth:success(El),
send_element(StateData, Res), send_element(StateData, Res),
change_shaper(StateData, JID), change_shaper(StateData, JID),
@ -410,18 +428,20 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
roster_get_subscription_lists, roster_get_subscription_lists,
StateData#state.server, StateData#state.server,
{[], []}, {[], []},
[U, StateData#state.server]), [UBinary, StateData#state.server]),
LJID = jlib:short_prepd_bare_jid(JID), LJID = jlib:short_prepd_bare_jid(JID),
Fs1 = [LJID | Fs], Fs1 = [LJID | Fs],
Ts1 = [LJID | Ts], Ts1 = [LJID | Ts],
PrivList = ejabberd_hooks:run_fold( PrivList = ejabberd_hooks:run_fold(
privacy_get_user_list, StateData#state.server, privacy_get_user_list, StateData#state.server,
#userlist{}, #userlist{},
[U, StateData#state.server]), [UBinary, StateData#state.server]),
fsm_next_state(session_established, fsm_next_state(session_established,
StateData#state{ StateData#state{
user = U, sasl_state = 'undefined',
resource = R, %not used anymore, let the GC work.
user = list_to_binary(U),
resource = list_to_binary(R),
jid = JID, jid = JID,
sid = SID, sid = SID,
conn = Conn, conn = Conn,
@ -504,7 +524,7 @@ wait_for_feature_request({xmlstreamelement, #xmlel{ns = NS, name = Name} = El},
StateData#state{ StateData#state{
streamid = new_id(), streamid = new_id(),
authenticated = true, authenticated = true,
user = U }); user = list_to_binary(U) });
{continue, ServerOut, NewSASLState} -> {continue, ServerOut, NewSASLState} ->
send_element(StateData, send_element(StateData,
exmpp_server_sasl:challenge(ServerOut)), exmpp_server_sasl:challenge(ServerOut)),
@ -528,8 +548,9 @@ wait_for_feature_request({xmlstreamelement, #xmlel{ns = NS, name = Name} = El},
{?NS_TLS, 'starttls'} when TLS == true, {?NS_TLS, 'starttls'} when TLS == true,
TLSEnabled == false, TLSEnabled == false,
SockMod == gen_tcp -> SockMod == gen_tcp ->
ServerString = binary_to_list(StateData#state.server),
TLSOpts = case ejabberd_config:get_local_option( TLSOpts = case ejabberd_config:get_local_option(
{domain_certfile, StateData#state.server}) of {domain_certfile, ServerString}) of
undefined -> undefined ->
StateData#state.tls_options; StateData#state.tls_options;
CertFile -> CertFile ->
@ -619,7 +640,7 @@ wait_for_sasl_response({xmlstreamelement, #xmlel{ns = NS, name = Name} = El},
streamid = new_id(), streamid = new_id(),
authenticated = true, authenticated = true,
auth_module = AuthModule, auth_module = AuthModule,
user = U}); user = list_to_binary(U)});
{continue, ServerOut, NewSASLState} -> {continue, ServerOut, NewSASLState} ->
send_element(StateData, send_element(StateData,
exmpp_server_sasl:challenge(ServerOut)), exmpp_server_sasl:challenge(ServerOut)),
@ -662,18 +683,17 @@ wait_for_sasl_response(closed, StateData) ->
wait_for_bind({xmlstreamelement, El}, StateData) -> wait_for_bind({xmlstreamelement, El}, StateData) ->
try try
U = StateData#state.user,
R = case exmpp_server_binding:wished_resource(El) of R = case exmpp_server_binding:wished_resource(El) of
undefined -> undefined ->
lists:concat([randoms:get_string() | tuple_to_list(now())]); lists:concat([randoms:get_string() | tuple_to_list(now())]);
Resource -> Resource ->
Resource Resource
end, end,
JID = exmpp_jid:make_jid(U, StateData#state.server, R), JID = exmpp_jid:make_jid(StateData#state.user, StateData#state.server, R),
Res = exmpp_server_binding:bind(El, JID), Res = exmpp_server_binding:bind(El, JID),
send_element(StateData, Res), send_element(StateData, Res),
fsm_next_state(wait_for_session, fsm_next_state(wait_for_session,
StateData#state{resource = R, jid = JID}) StateData#state{resource = exmpp_jid:resource(JID), jid = JID})
catch catch
throw:{stringprep, resourceprep, _, _} -> throw:{stringprep, resourceprep, _, _} ->
Err = exmpp_server_binding:error(El, 'bad-request'), Err = exmpp_server_binding:error(El, 'bad-request'),
@ -702,11 +722,10 @@ wait_for_bind(closed, StateData) ->
wait_for_session({xmlstreamelement, El}, StateData) -> wait_for_session({xmlstreamelement, El}, StateData) ->
try try
U = StateData#state.user, ServerString = binary_to_list(StateData#state.server),
R = StateData#state.resource,
JID = StateData#state.jid, JID = StateData#state.jid,
true = exmpp_server_session:want_establishment(El), true = exmpp_server_session:want_establishment(El),
case acl:match_rule(StateData#state.server, case acl:match_rule(ServerString,
StateData#state.access, JID) of StateData#state.access, JID) of
allow -> allow ->
?INFO_MSG("(~w) Opened session for ~s", ?INFO_MSG("(~w) Opened session for ~s",
@ -717,7 +736,7 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
Info = [{ip, StateData#state.ip}, {conn, Conn}, Info = [{ip, StateData#state.ip}, {conn, Conn},
{auth_module, StateData#state.auth_module}], {auth_module, StateData#state.auth_module}],
ejabberd_sm:open_session( ejabberd_sm:open_session(
SID, U, StateData#state.server, R, Info), SID, JID, Info),
Res = exmpp_server_session:establish(El), Res = exmpp_server_session:establish(El),
send_element(StateData, Res), send_element(StateData, Res),
change_shaper(StateData, JID), change_shaper(StateData, JID),
@ -725,7 +744,7 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
roster_get_subscription_lists, roster_get_subscription_lists,
StateData#state.server, StateData#state.server,
{[], []}, {[], []},
[U, StateData#state.server]), [StateData#state.user, StateData#state.server]),
LJID = jlib:short_prepd_bare_jid(JID), LJID = jlib:short_prepd_bare_jid(JID),
Fs1 = [LJID | Fs], Fs1 = [LJID | Fs],
Ts1 = [LJID | Ts], Ts1 = [LJID | Ts],
@ -733,9 +752,11 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
privacy_get_user_list, StateData#state.server, privacy_get_user_list, StateData#state.server,
#userlist{}, #userlist{},
[U, StateData#state.server]), [StateData#state.user, StateData#state.server]),
fsm_next_state(session_established, fsm_next_state(session_established,
StateData#state{ StateData#state{
sasl_state = 'undefined',
%not used anymore, let the GC work.
sid = SID, sid = SID,
conn = Conn, conn = Conn,
pres_f = ?SETS:from_list(Fs1), pres_f = ?SETS:from_list(Fs1),
@ -773,14 +794,12 @@ wait_for_session(closed, StateData) ->
session_established({xmlstreamelement, El}, StateData) -> session_established({xmlstreamelement, El}, StateData) ->
FromJID = StateData#state.jid, case check_from(El, StateData#state.jid) of
% Check 'from' attribute in stanza RFC 3920 Section 9.1.2
case check_from(El, FromJID) of
'invalid-from' -> 'invalid-from' ->
send_element(StateData, exmpp_stream:error('invalid-from')), send_element(StateData, exmpp_stream:error('invalid-from')),
send_element(StateData, exmpp_stream:closing()), send_element(StateData, exmpp_stream:closing()),
{stop, normal, StateData}; {stop, normal, StateData};
_NewEl -> _ ->
session_established2(El, StateData) session_established2(El, StateData)
end; end;
@ -810,11 +829,13 @@ session_established2(El, StateData) ->
try try
User = StateData#state.user, User = StateData#state.user,
Server = StateData#state.server, Server = StateData#state.server,
% TODO: check 'from' attribute in stanza
FromJID = StateData#state.jid, FromJID = StateData#state.jid,
To = exmpp_stanza:get_recipient(El), To = exmpp_stanza:get_recipient(El),
ToJID = case To of ToJID = case To of
undefined -> undefined ->
exmpp_jid:make_bare_jid(User, Server); exmpp_jid:jid_to_bare_jid(StateData#state.jid);
_ -> _ ->
exmpp_jid:list_to_jid(To) exmpp_jid:list_to_jid(To)
end, end,
@ -839,10 +860,10 @@ session_established2(El, StateData) ->
user_send_packet, user_send_packet,
Server, Server,
[FromJID, ToJID, PresenceEl]), [FromJID, ToJID, PresenceEl]),
case ToJID of case {exmpp_jid:node(ToJID),
#jid{node = User, exmpp_jid:domain(ToJID),
domain = Server, exmpp_jid:resource(ToJID)} of
resource = undefined} -> {User, Server,undefined} ->
?DEBUG("presence_update(~p,~n\t~p,~n\t~p)", ?DEBUG("presence_update(~p,~n\t~p,~n\t~p)",
[FromJID, PresenceEl, StateData]), [FromJID, PresenceEl, StateData]),
presence_update(FromJID, PresenceEl, presence_update(FromJID, PresenceEl,
@ -894,6 +915,7 @@ session_established2(El, StateData) ->
fsm_next_state(session_established, StateData) fsm_next_state(session_established, StateData)
end. end.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
%% Func: StateName/3 %% Func: StateName/3
%% Returns: {next_state, NextStateName, NextStateData} | %% Returns: {next_state, NextStateName, NextStateData} |
@ -925,8 +947,12 @@ handle_event(_Event, StateName, StateData) ->
%% {stop, Reason, NewStateData} | %% {stop, Reason, NewStateData} |
%% {stop, Reason, Reply, NewStateData} %% {stop, Reason, Reply, NewStateData}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
%TODO: for debug only
handle_sync_event(get_state,_From,StateName,StateData) ->
{reply,{StateName, StateData}, StateName, StateData};
handle_sync_event({get_presence}, _From, StateName, StateData) -> handle_sync_event({get_presence}, _From, StateName, StateData) ->
User = StateData#state.user, User = binary_to_list(StateData#state.user),
PresLast = StateData#state.pres_last, PresLast = StateData#state.pres_last,
Show = case PresLast of Show = case PresLast of
@ -937,14 +963,35 @@ handle_sync_event({get_presence}, _From, StateName, StateData) ->
undefined -> ""; undefined -> "";
_ -> exmpp_presence:get_status(PresLast) _ -> exmpp_presence:get_status(PresLast)
end, end,
Resource = StateData#state.resource, Resource = binary_to_list(StateData#state.resource),
Reply = {User, Resource, atom_to_list(Show), Status}, Reply = {User, Resource, atom_to_list(Show), Status},
fsm_reply(Reply, StateName, StateData); fsm_reply(Reply, StateName, StateData);
handle_sync_event(get_subscribed, _From, StateName, StateData) -> handle_sync_event(get_subscribed, _From, StateName, StateData) ->
Subscribed = ?SETS:to_list(StateData#state.pres_f), Subscribed = StateData#state.pres_f,
{reply, Subscribed, StateName, StateData}; Online = StateData#state.pres_available,
Pred = fun({U, S, _} = User, _Caps) ->
?SETS:is_element({U, S, undefined},
Subscribed) orelse
?SETS:is_element(User, Subscribed)
end,
SubscribedAndOnline = ?DICT:filter(Pred, Online),
SubscribedWithCaps = ?SETS:fold(fun(User, Acc) ->
[{User, undefined}|Acc]
end, ?DICT:to_list(SubscribedAndOnline), Subscribed),
{reply, SubscribedWithCaps, StateName, StateData};
handle_sync_event(get_subscribed_and_online, _From, StateName, StateData) ->
Subscribed = StateData#state.pres_f,
Online = StateData#state.pres_available,
Pred = fun({U, S, _R} = User, _Caps) ->
?SETS:is_element({U, S, undefined},
Subscribed) orelse
?SETS:is_element(User, Subscribed)
end,
SubscribedAndOnline = ?DICT:filter(Pred, Online),
{reply, ?DICT:to_list(SubscribedAndOnline), StateName, StateData};
handle_sync_event(_Event, _From, StateName, StateData) -> handle_sync_event(_Event, _From, StateName, StateData) ->
Reply = ok, Reply = ok,
@ -1036,39 +1083,44 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
LFrom = jlib:short_prepd_jid(From), LFrom = jlib:short_prepd_jid(From),
LBFrom = jlib:short_prepd_bare_jid(From), LBFrom = jlib:short_prepd_bare_jid(From),
%% Note contact availability %% Note contact availability
case exmpp_presence:get_type(Packet) of Els = Packet#xmlel.children,
Caps = mod_caps:read_caps(Els),
ServerString = binary_to_list(StateData#state.server),
mod_caps:note_caps(ServerString, From, Caps),
NewAvailable = case exmpp_presence:get_type(Packet) of
'unavailable' -> 'unavailable' ->
mod_caps:clear_caps(From); ?DICT:erase(LFrom, StateData#state.pres_available);
_ -> _ ->
Caps = mod_caps:read_caps(Packet#xmlel.children), %?DICT:store(LFrom, Caps, StateData#state.pres_available)
mod_caps:note_caps(StateData#state.server, From, Caps) StateData#state.pres_available
end, end,
NewStateData = StateData#state{pres_available = NewAvailable},
case ?SETS:is_element( case ?SETS:is_element(
LFrom, StateData#state.pres_a) orelse LFrom, NewStateData#state.pres_a) orelse
?SETS:is_element( ?SETS:is_element(
LBFrom, StateData#state.pres_a) of LBFrom, NewStateData#state.pres_a) of
true -> true ->
{true, Attrs, StateData}; {true, Attrs, NewStateData};
false -> false ->
case ?SETS:is_element( case ?SETS:is_element(
LFrom, StateData#state.pres_f) of LFrom, NewStateData#state.pres_f) of
true -> true ->
A = ?SETS:add_element( A = ?SETS:add_element(
LFrom, LFrom,
StateData#state.pres_a), NewStateData#state.pres_a),
{true, Attrs, {true, Attrs,
StateData#state{pres_a = A}}; NewStateData#state{pres_a = A}};
false -> false ->
case ?SETS:is_element( case ?SETS:is_element(
LBFrom, StateData#state.pres_f) of LBFrom, NewStateData#state.pres_f) of
true -> true ->
A = ?SETS:add_element( A = ?SETS:add_element(
LBFrom, LBFrom,
StateData#state.pres_a), NewStateData#state.pres_a),
{true, Attrs, {true, Attrs,
StateData#state{pres_a = A}}; NewStateData#state{pres_a = A}};
false -> false ->
{true, Attrs, StateData} {true, Attrs, NewStateData}
end end
end end
end; end;
@ -1080,7 +1132,9 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
?DEBUG("broadcast~n~p~n", [Packet#xmlel.children]), ?DEBUG("broadcast~n~p~n", [Packet#xmlel.children]),
case Packet#xmlel.children of case Packet#xmlel.children of
[{item, {U, S, R} = _IJIDShort, ISubscription}] -> [{item, {U, S, R} = _IJIDShort, ISubscription}] ->
IJID = exmpp_jid:make_jid(U, S, R), IJID = exmpp_jid:make_jid(U,
S,
R),
{false, Attrs, {false, Attrs,
roster_change(IJID, ISubscription, roster_change(IJID, ISubscription,
StateData)}; StateData)};
@ -1108,7 +1162,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
true -> true ->
case exmpp_iq:get_request(Packet) of case exmpp_iq:get_request(Packet) of
#xmlel{ns = ?NS_VCARD} -> #xmlel{ns = ?NS_VCARD} ->
Host = StateData#state.server, Host = binary_to_list(StateData#state.server),
case ets:lookup(sm_iqtable, {?NS_VCARD, Host}) of case ets:lookup(sm_iqtable, {?NS_VCARD, Host}) of
[{_, Module, Function, Opts}] -> [{_, Module, Function, Opts}] ->
gen_iq_handler:handle(Host, Module, Function, Opts, gen_iq_handler:handle(Host, Module, Function, Opts,
@ -1186,6 +1240,7 @@ handle_info(Info, StateName, StateData) ->
%% Returns: any %% Returns: any
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
terminate(_Reason, StateName, StateData) -> terminate(_Reason, StateName, StateData) ->
%%TODO: resource could be 'undefined' if terminate before bind?
case StateName of case StateName of
session_established -> session_established ->
case StateData#state.authenticated of case StateData#state.authenticated of
@ -1199,9 +1254,7 @@ terminate(_Reason, StateName, StateData) ->
"Replaced by new connection"), "Replaced by new connection"),
ejabberd_sm:close_session_unset_presence( ejabberd_sm:close_session_unset_presence(
StateData#state.sid, StateData#state.sid,
StateData#state.user, StateData#state.jid,
StateData#state.server,
StateData#state.resource,
"Replaced by new connection"), "Replaced by new connection"),
presence_broadcast( presence_broadcast(
StateData, From, StateData#state.pres_a, Packet1), StateData, From, StateData#state.pres_a, Packet1),
@ -1219,17 +1272,13 @@ terminate(_Reason, StateName, StateData) ->
pres_i = EmptySet, pres_i = EmptySet,
pres_invis = false} -> pres_invis = false} ->
ejabberd_sm:close_session(StateData#state.sid, ejabberd_sm:close_session(StateData#state.sid,
StateData#state.user, StateData#state.jid);
StateData#state.server,
StateData#state.resource);
_ -> _ ->
From = StateData#state.jid, From = StateData#state.jid,
Packet = exmpp_presence:unavailable(), Packet = exmpp_presence:unavailable(),
ejabberd_sm:close_session_unset_presence( ejabberd_sm:close_session_unset_presence(
StateData#state.sid, StateData#state.sid,
StateData#state.user, StateData#state.jid,
StateData#state.server,
StateData#state.resource,
""), ""),
presence_broadcast( presence_broadcast(
StateData, From, StateData#state.pres_a, Packet), StateData, From, StateData#state.pres_a, Packet),
@ -1248,7 +1297,7 @@ terminate(_Reason, StateName, StateData) ->
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
change_shaper(StateData, JID) -> change_shaper(StateData, JID) ->
Shaper = acl:match_rule(StateData#state.server, Shaper = acl:match_rule(binary_to_list(StateData#state.server),
StateData#state.shaper, JID), StateData#state.shaper, JID),
(StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper). (StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper).
@ -1257,9 +1306,9 @@ send_text(StateData, Text) ->
(StateData#state.sockmod):send(StateData#state.socket, Text). (StateData#state.sockmod):send(StateData#state.socket, Text).
send_element(StateData, #xmlel{ns = ?NS_XMPP, name = 'stream'} = El) -> send_element(StateData, #xmlel{ns = ?NS_XMPP, name = 'stream'} = El) ->
send_text(StateData, exmpp_stream:to_list(El)); send_text(StateData, exmpp_stream:to_iolist(El));
send_element(StateData, El) -> send_element(StateData, El) ->
send_text(StateData, exmpp_stanza:to_list(El)). send_text(StateData, exmpp_stanza:to_iolist(El)).
new_id() -> new_id() ->
@ -1372,9 +1421,7 @@ presence_update(From, Packet, StateData) ->
Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn}, Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn},
{auth_module, StateData#state.auth_module}], {auth_module, StateData#state.auth_module}],
ejabberd_sm:unset_presence(StateData#state.sid, ejabberd_sm:unset_presence(StateData#state.sid,
StateData#state.user, StateData#state.jid,
StateData#state.server,
StateData#state.resource,
Status, Status,
Info), Info),
presence_broadcast(StateData, From, StateData#state.pres_a, Packet), presence_broadcast(StateData, From, StateData#state.pres_a, Packet),
@ -1476,8 +1523,6 @@ presence_update(From, Packet, StateData) ->
presence_track(From, To, Packet, StateData) -> presence_track(From, To, Packet, StateData) ->
LTo = jlib:short_prepd_jid(To), LTo = jlib:short_prepd_jid(To),
User = StateData#state.user,
Server = StateData#state.server,
BFrom = exmpp_jid:jid_to_bare_jid(From), BFrom = exmpp_jid:jid_to_bare_jid(From),
case exmpp_presence:get_type(Packet) of case exmpp_presence:get_type(Packet) of
'unavailable' -> 'unavailable' ->
@ -1494,26 +1539,26 @@ presence_track(From, To, Packet, StateData) ->
pres_a = A}; pres_a = A};
'subscribe' -> 'subscribe' ->
ejabberd_hooks:run(roster_out_subscription, ejabberd_hooks:run(roster_out_subscription,
Server, StateData#state.server,
[User, Server, To, subscribe]), [StateData#state.user, StateData#state.server, To, subscribe]),
ejabberd_router:route(BFrom, To, Packet), ejabberd_router:route(BFrom, To, Packet),
StateData; StateData;
'subscribed' -> 'subscribed' ->
ejabberd_hooks:run(roster_out_subscription, ejabberd_hooks:run(roster_out_subscription,
Server, StateData#state.server,
[User, Server, To, subscribed]), [StateData#state.user, StateData#state.server, To, subscribed]),
ejabberd_router:route(BFrom, To, Packet), ejabberd_router:route(BFrom, To, Packet),
StateData; StateData;
'unsubscribe' -> 'unsubscribe' ->
ejabberd_hooks:run(roster_out_subscription, ejabberd_hooks:run(roster_out_subscription,
Server, StateData#state.server,
[User, Server, To, unsubscribe]), [StateData#state.user, StateData#state.server, To, unsubscribe]),
ejabberd_router:route(BFrom, To, Packet), ejabberd_router:route(BFrom, To, Packet),
StateData; StateData;
'unsubscribed' -> 'unsubscribed' ->
ejabberd_hooks:run(roster_out_subscription, ejabberd_hooks:run(roster_out_subscription,
Server, StateData#state.server,
[User, Server, To, unsubscribed]), [StateData#state.user, StateData#state.server, To, unsubscribed]),
ejabberd_router:route(BFrom, To, Packet), ejabberd_router:route(BFrom, To, Packet),
StateData; StateData;
'error' -> 'error' ->
@ -1718,9 +1763,7 @@ update_priority(Priority, Packet, StateData) ->
Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn}, Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn},
{auth_module, StateData#state.auth_module}], {auth_module, StateData#state.auth_module}],
ejabberd_sm:set_presence(StateData#state.sid, ejabberd_sm:set_presence(StateData#state.sid,
StateData#state.user, StateData#state.jid,
StateData#state.server,
StateData#state.resource,
Priority, Priority,
Packet, Packet,
Info). Info).
@ -1761,22 +1804,23 @@ process_privacy_iq(From, To,
NewStateData. NewStateData.
resend_offline_messages(#state{user = User, resend_offline_messages(#state{user = UserB,
server = Server, server = ServerB,
privacy_list = PrivList} = StateData) -> privacy_list = PrivList} = StateData) ->
case ejabberd_hooks:run_fold(resend_offline_messages_hook, case ejabberd_hooks:run_fold(resend_offline_messages_hook,
Server, StateData#state.server,
[], [],
[User, Server]) of [UserB, ServerB]) of
Rs when list(Rs) -> Rs when list(Rs) ->
lists:foreach( lists:foreach(
fun({route, fun({route,
From, To, Packet}) -> From, To, Packet}) ->
Pass = case ejabberd_hooks:run_fold( Pass = case ejabberd_hooks:run_fold(
privacy_check_packet, Server, privacy_check_packet, StateData#state.server,
allow, allow,
[User, [StateData#state.user,
Server, StateData#state.server,
PrivList, PrivList,
{From, To, Packet}, {From, To, Packet},
in]) of in]) of
@ -1799,13 +1843,13 @@ resend_offline_messages(#state{user = User,
end, Rs) end, Rs)
end. end.
resend_subscription_requests(#state{user = User, resend_subscription_requests(#state{user = UserB,
server = Server} = StateData) -> server = ServerB} = StateData) ->
PendingSubscriptions = ejabberd_hooks:run_fold( PendingSubscriptions = ejabberd_hooks:run_fold(
resend_subscription_requests_hook, resend_subscription_requests_hook,
Server, StateData#state.server,
[], [],
[User, Server]), [UserB, ServerB]),
lists:foreach(fun(XMLPacket) -> lists:foreach(fun(XMLPacket) ->
send_element(StateData, send_element(StateData,
XMLPacket) XMLPacket)
@ -1813,6 +1857,7 @@ resend_subscription_requests(#state{user = User,
PendingSubscriptions). PendingSubscriptions).
process_unauthenticated_stanza(StateData, El) when ?IS_IQ(El) -> process_unauthenticated_stanza(StateData, El) when ?IS_IQ(El) ->
ServerString = binary_to_list(StateData#state.server),
case exmpp_iq:get_kind(El) of case exmpp_iq:get_kind(El) of
request -> request ->
IQ_Rec = exmpp_iq:xmlel_to_iq(El), IQ_Rec = exmpp_iq:xmlel_to_iq(El),
@ -1828,7 +1873,7 @@ process_unauthenticated_stanza(StateData, El) when ?IS_IQ(El) ->
ResIQ = exmpp_iq:error_without_original(El, ResIQ = exmpp_iq:error_without_original(El,
'service-unavailable'), 'service-unavailable'),
Res1 = exmpp_stanza:set_sender(ResIQ, Res1 = exmpp_stanza:set_sender(ResIQ,
exmpp_jid:make_bare_jid(StateData#state.server)), exmpp_jid:make_bare_jid(ServerString)),
Res2 = exmpp_stanza:remove_recipient(Res1), Res2 = exmpp_stanza:remove_recipient(Res1),
send_element(StateData, Res2); send_element(StateData, Res2);
_ -> _ ->

View File

@ -61,19 +61,21 @@ start_link() ->
add(Hook, Module, Function, Seq) -> add(Hook, Module, Function, Seq) ->
add(Hook, global, Module, Function, Seq). add(Hook, global, Module, Function, Seq).
add(Hook, Host, Module, Function, Seq) -> add(Hook, Host, Module, Function, Seq)
when is_binary(Host) orelse is_atom(Host) ->
gen_server:call(ejabberd_hooks, {add, Hook, Host, Module, Function, Seq}). gen_server:call(ejabberd_hooks, {add, Hook, Host, Module, Function, Seq}).
delete(Hook, Module, Function, Seq) -> delete(Hook, Module, Function, Seq) ->
delete(Hook, global, Module, Function, Seq). delete(Hook, global, Module, Function, Seq).
delete(Hook, Host, Module, Function, Seq) -> delete(Hook, Host, Module, Function, Seq)
when is_binary(Host) orelse is_atom(Host) ->
gen_server:call(ejabberd_hooks, {delete, Hook, Host, Module, Function, Seq}). gen_server:call(ejabberd_hooks, {delete, Hook, Host, Module, Function, Seq}).
run(Hook, Args) -> run(Hook, Args) ->
run(Hook, global, Args). run(Hook, global, Args).
run(Hook, Host, Args) -> run(Hook, Host, Args) when is_binary(Host) orelse is_atom(Host) ->
case ets:lookup(hooks, {Hook, Host}) of case ets:lookup(hooks, {Hook, Host}) of
[{_, Ls}] -> [{_, Ls}] ->
run1(Ls, Hook, Args); run1(Ls, Hook, Args);
@ -84,7 +86,7 @@ run(Hook, Host, Args) ->
run_fold(Hook, Val, Args) -> run_fold(Hook, Val, Args) ->
run_fold(Hook, global, Val, Args). run_fold(Hook, global, Val, Args).
run_fold(Hook, Host, Val, Args) -> run_fold(Hook, Host, Val, Args) when is_binary(Host) orelse is_atom(Host) ->
case ets:lookup(hooks, {Hook, Host}) of case ets:lookup(hooks, {Hook, Host}) of
[{_, Ls}] -> [{_, Ls}] ->
run_fold1(Ls, Hook, Val, Args); run_fold1(Ls, Hook, Val, Args);

View File

@ -76,7 +76,7 @@ start_link() ->
process_iq(From, To, Packet) -> process_iq(From, To, Packet) ->
case exmpp_iq:xmlel_to_iq(Packet) of case exmpp_iq:xmlel_to_iq(Packet) of
#iq{kind = request, ns = XMLNS} = IQ_Rec -> #iq{kind = request, ns = XMLNS} = IQ_Rec ->
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
case ets:lookup(?IQTABLE, {XMLNS, Host}) of case ets:lookup(?IQTABLE, {XMLNS, Host}) of
[{_, Module, Function}] -> [{_, Module, Function}] ->
ResIQ = Module:Function(From, To, IQ_Rec), ResIQ = Module:Function(From, To, IQ_Rec),
@ -182,7 +182,7 @@ init([]) ->
lists:foreach( lists:foreach(
fun(Host) -> fun(Host) ->
ejabberd_router:register_route(Host, {apply, ?MODULE, route}), ejabberd_router:register_route(Host, {apply, ?MODULE, route}),
ejabberd_hooks:add(local_send_to_resource_hook, Host, ejabberd_hooks:add(local_send_to_resource_hook, list_to_binary(Host),
?MODULE, bounce_resource_packet, 100) ?MODULE, bounce_resource_packet, 100)
end, ?MYHOSTS), end, ?MYHOSTS),
catch ets:new(?IQTABLE, [named_table, public]), catch ets:new(?IQTABLE, [named_table, public]),
@ -302,10 +302,13 @@ code_change(_OldVsn, State, _Extra) ->
do_route(From, To, Packet) -> do_route(From, To, Packet) ->
?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n", ?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]), [From, To, Packet, 8]),
LNode = exmpp_jid:lnode(To),
LResource = exmpp_jid:lresource(To),
if if
To#jid.lnode /= undefined -> LNode /= undefined ->
ejabberd_sm:route(From, To, Packet); ejabberd_sm:route(From, To, Packet);
To#jid.lresource == undefined -> LResource == undefined ->
case Packet of case Packet of
_ when ?IS_IQ(Packet) -> _ when ?IS_IQ(Packet) ->
process_iq(From, To, Packet); process_iq(From, To, Packet);
@ -322,7 +325,7 @@ do_route(From, To, Packet) ->
"result" -> ok; "result" -> ok;
_ -> _ ->
ejabberd_hooks:run(local_send_to_resource_hook, ejabberd_hooks:run(local_send_to_resource_hook,
To#jid.ldomain, exmpp_jid:ldomain(To),
[From, To, Packet]) [From, To, Packet])
end end
end. end.

View File

@ -134,13 +134,14 @@ init([Socket, SockMod, Shaper, MaxStanzaSize]) ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
handle_call({starttls, TLSSocket}, _From, handle_call({starttls, TLSSocket}, _From,
#state{xml_stream_state = XMLStreamState} = State) -> #state{xml_stream_state = XMLStreamState} = State) ->
NewXMLStreamState = exmpp_xmlstream:reset(XMLStreamState), NewXMLStreamState = do_reset_stream(XMLStreamState),
NewState = State#state{socket = TLSSocket, NewState = State#state{socket = TLSSocket,
sock_mod = tls, sock_mod = tls,
xml_stream_state = NewXMLStreamState}, xml_stream_state = NewXMLStreamState},
case tls:recv_data(TLSSocket, "") of case tls:recv_data(TLSSocket, "") of
{ok, TLSData} -> {ok, TLSData} ->
{reply, ok, process_data(TLSData, NewState), ?HIBERNATE_TIMEOUT}; {NextState, Hib} = process_data(TLSData, NewState),
{reply, ok, NextState, Hib};
{error, _Reason} -> {error, _Reason} ->
{stop, normal, ok, NewState} {stop, normal, ok, NewState}
end; end;
@ -152,7 +153,8 @@ handle_call({compress, ZlibSocket}, _From,
xml_stream_state = NewXMLStreamState}, xml_stream_state = NewXMLStreamState},
case ejabberd_zlib:recv_data(ZlibSocket, "") of case ejabberd_zlib:recv_data(ZlibSocket, "") of
{ok, ZlibData} -> {ok, ZlibData} ->
{reply, ok, process_data(ZlibData, NewState), ?HIBERNATE_TIMEOUT}; {NextState, Hib} = process_data(ZlibData, NewState),
{reply, ok, NextState, Hib};
{error, _Reason} -> {error, _Reason} ->
{stop, normal, ok, NewState} {stop, normal, ok, NewState}
end; end;
@ -164,7 +166,10 @@ handle_call(reset_stream, _From,
?HIBERNATE_TIMEOUT}; ?HIBERNATE_TIMEOUT};
handle_call({become_controller, C2SPid}, _From, State) -> handle_call({become_controller, C2SPid}, _From, State) ->
Parser = exmpp_xml:start_parser([ Parser = exmpp_xml:start_parser([
names_as_atom, {names_as_atom, true},
{check_nss, xmpp},
{check_elems, xmpp},
{check_attrs, xmpp},
{max_size, State#state.max_stanza_size} {max_size, State#state.max_stanza_size}
]), ]),
XMLStreamState = exmpp_xmlstream:start( XMLStreamState = exmpp_xmlstream:start(
@ -208,21 +213,22 @@ handle_info({Tag, _TCPSocket, Data},
tls -> tls ->
case tls:recv_data(Socket, Data) of case tls:recv_data(Socket, Data) of
{ok, TLSData} -> {ok, TLSData} ->
{noreply, process_data(TLSData, State), {NextState, Hib} = process_data(TLSData, State),
?HIBERNATE_TIMEOUT}; {noreply, NextState, Hib};
{error, _Reason} -> {error, _Reason} ->
{stop, normal, State} {stop, normal, State}
end; end;
ejabberd_zlib -> ejabberd_zlib ->
case ejabberd_zlib:recv_data(Socket, Data) of case ejabberd_zlib:recv_data(Socket, Data) of
{ok, ZlibData} -> {ok, ZlibData} ->
{noreply, process_data(ZlibData, State), {NextState, Hib} = process_data(ZlibData, State),
?HIBERNATE_TIMEOUT}; {noreply, NextState, Hib};
{error, _Reason} -> {error, _Reason} ->
{stop, normal, State} {stop, normal, State}
end; end;
_ -> _ ->
{noreply, process_data(Data, State), ?HIBERNATE_TIMEOUT} {NextState, Hib} = process_data(Data, State),
{noreply, NextState, Hib}
end; end;
handle_info({Tag, _TCPSocket}, State) handle_info({Tag, _TCPSocket}, State)
when (Tag == tcp_closed) or (Tag == ssl_closed) -> when (Tag == tcp_closed) or (Tag == ssl_closed) ->
@ -239,8 +245,8 @@ handle_info({timeout, _Ref, activate}, State) ->
activate_socket(State), activate_socket(State),
{noreply, State, ?HIBERNATE_TIMEOUT}; {noreply, State, ?HIBERNATE_TIMEOUT};
handle_info(timeout, State) -> handle_info(timeout, State) ->
proc_lib:hibernate(gen_server, enter_loop, [?MODULE, [], State]), {noreply, State, hibernate};
{noreply, State, ?HIBERNATE_TIMEOUT};
handle_info(_Info, State) -> handle_info(_Info, State) ->
{noreply, State, ?HIBERNATE_TIMEOUT}. {noreply, State, ?HIBERNATE_TIMEOUT}.
@ -299,19 +305,30 @@ process_data(Data,
?DEBUG("Received XML on stream = ~p", [binary_to_list(Data)]), ?DEBUG("Received XML on stream = ~p", [binary_to_list(Data)]),
{ok, XMLStreamState1} = exmpp_xmlstream:parse(XMLStreamState, Data), {ok, XMLStreamState1} = exmpp_xmlstream:parse(XMLStreamState, Data),
{NewShaperState, Pause} = shaper:update(ShaperState, size(Data)), {NewShaperState, Pause} = shaper:update(ShaperState, size(Data)),
HibTimeout =
if if
C2SPid == undefined -> C2SPid == undefined ->
ok; infinity;
Pause > 0 -> Pause > 0 ->
erlang:start_timer(Pause, self(), activate); erlang:start_timer(Pause, self(), activate),
hibernate;
true -> true ->
activate_socket(State) activate_socket(State),
?HIBERNATE_TIMEOUT
end, end,
State#state{xml_stream_state = XMLStreamState1, {State#state{xml_stream_state = XMLStreamState1,
shaper_state = NewShaperState}. shaper_state = NewShaperState}, HibTimeout}.
close_stream(undefined) -> close_stream(undefined) ->
ok; ok;
close_stream(XMLStreamState) -> close_stream(XMLStreamState) ->
exmpp_xml:stop_parser(exmpp_xmlstream:get_parser(XMLStreamState)), exmpp_xml:stop_parser(exmpp_xmlstream:get_parser(XMLStreamState)),
exmpp_xmlstream:stop(XMLStreamState). exmpp_xmlstream:stop(XMLStreamState).
do_reset_stream(undefined) ->
undefined;
do_reset_stream(XMLStreamState) ->
exmpp_xmlstream:reset(XMLStreamState).

View File

@ -89,27 +89,28 @@ register_route(Domain) ->
register_route(Domain, LocalHint) -> register_route(Domain, LocalHint) ->
try try
LDomain = exmpp_stringprep:nameprep(Domain), LDomain = exmpp_stringprep:nameprep(Domain),
LDomainB = list_to_binary(LDomain),
Pid = self(), Pid = self(),
case get_component_number(LDomain) of case get_component_number(LDomain) of
undefined -> undefined ->
F = fun() -> F = fun() ->
mnesia:write(#route{domain = LDomain, mnesia:write(#route{domain = LDomainB,
pid = Pid, pid = Pid,
local_hint = LocalHint}) local_hint = LocalHint})
end, end,
mnesia:transaction(F); mnesia:transaction(F);
N -> N ->
F = fun() -> F = fun() ->
case mnesia:read({route, LDomain}) of case mnesia:read({route, LDomainB}) of
[] -> [] ->
mnesia:write( mnesia:write(
#route{domain = LDomain, #route{domain = LDomainB,
pid = Pid, pid = Pid,
local_hint = 1}), local_hint = 1}),
lists:foreach( lists:foreach(
fun(I) -> fun(I) ->
mnesia:write( mnesia:write(
#route{domain = LDomain, #route{domain = LDomainB,
pid = undefined, pid = undefined,
local_hint = I}) local_hint = I})
end, lists:seq(2, N)); end, lists:seq(2, N));
@ -118,7 +119,7 @@ register_route(Domain, LocalHint) ->
fun(#route{pid = undefined, fun(#route{pid = undefined,
local_hint = I} = R) -> local_hint = I} = R) ->
mnesia:write( mnesia:write(
#route{domain = LDomain, #route{domain = LDomainB,
pid = Pid, pid = Pid,
local_hint = I}), local_hint = I}),
mnesia:delete_object(R), mnesia:delete_object(R),
@ -143,12 +144,13 @@ register_routes(Domains) ->
unregister_route(Domain) -> unregister_route(Domain) ->
try try
LDomain = exmpp_stringprep:nameprep(Domain), LDomain = exmpp_stringprep:nameprep(Domain),
LDomainB = list_to_binary(LDomain),
Pid = self(), Pid = self(),
case get_component_number(LDomain) of case get_component_number(LDomain) of
undefined -> undefined ->
F = fun() -> F = fun() ->
case mnesia:match_object( case mnesia:match_object(
#route{domain = LDomain, #route{domain = LDomainB,
pid = Pid, pid = Pid,
_ = '_'}) of _ = '_'}) of
[R] -> [R] ->
@ -160,13 +162,13 @@ unregister_route(Domain) ->
mnesia:transaction(F); mnesia:transaction(F);
_ -> _ ->
F = fun() -> F = fun() ->
case mnesia:match_object(#route{domain=LDomain, case mnesia:match_object(#route{domain=LDomainB,
pid = Pid, pid = Pid,
_ = '_'}) of _ = '_'}) of
[R] -> [R] ->
I = R#route.local_hint, I = R#route.local_hint,
mnesia:write( mnesia:write(
#route{domain = LDomain, #route{domain = LDomainB,
pid = undefined, pid = undefined,
local_hint = I}), local_hint = I}),
mnesia:delete_object(R); mnesia:delete_object(R);
@ -188,10 +190,14 @@ unregister_routes(Domains) ->
dirty_get_all_routes() -> dirty_get_all_routes() ->
lists:usort(mnesia:dirty_all_keys(route)) -- ?MYHOSTS. lists:usort(
lists:map(fun erlang:binary_to_list/1,
mnesia:dirty_all_keys(route))) -- ?MYHOSTS.
dirty_get_all_domains() -> dirty_get_all_domains() ->
lists:usort(mnesia:dirty_all_keys(route)). lists:usort(
lists:map(fun erlang:binary_to_list/1,
mnesia:dirty_all_keys(route))).
%%==================================================================== %%====================================================================
@ -326,8 +332,8 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
case ejabberd_hooks:run_fold(filter_packet, case ejabberd_hooks:run_fold(filter_packet,
{OrigFrom, OrigTo, OrigPacket}, []) of {OrigFrom, OrigTo, OrigPacket}, []) of
{From, To, Packet} -> {From, To, Packet} ->
LDstDomain = To#jid.ldomain, LDomain = exmpp_jid:ldomain(To),
case mnesia:dirty_read(route, LDstDomain) of case mnesia:dirty_read(route, LDomain) of
[] -> [] ->
ejabberd_s2s:route(From, To, Packet); ejabberd_s2s:route(From, To, Packet);
[R] -> [R] ->
@ -346,6 +352,7 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
drop drop
end; end;
Rs -> Rs ->
LDstDomain = exmpp_jid:ldomain_as_list(To),
Value = case ejabberd_config:get_local_option( Value = case ejabberd_config:get_local_option(
{domain_balancing, LDstDomain}) of {domain_balancing, LDstDomain}) of
undefined -> now(); undefined -> now();

View File

@ -281,7 +281,7 @@ do_route(From, To, Packet) ->
?DEBUG("sending to process ~p~n", [Pid]), ?DEBUG("sending to process ~p~n", [Pid]),
NewPacket1 = exmpp_stanza:set_sender(Packet, From), NewPacket1 = exmpp_stanza:set_sender(Packet, From),
NewPacket = exmpp_stanza:set_recipient(NewPacket1, To), NewPacket = exmpp_stanza:set_recipient(NewPacket1, To),
#jid{ldomain = MyServer} = From, MyServer = exmpp_jid:ldomain(From),
ejabberd_hooks:run( ejabberd_hooks:run(
s2s_send_packet, s2s_send_packet,
MyServer, MyServer,
@ -301,8 +301,8 @@ do_route(From, To, Packet) ->
end. end.
find_connection(From, To) -> find_connection(From, To) ->
#jid{ldomain = MyServer} = From, MyServer = exmpp_jid:ldomain_as_list(From),
#jid{ldomain = Server} = To, Server = exmpp_jid:ldomain_as_list(To),
FromTo = {MyServer, Server}, FromTo = {MyServer, Server},
MaxS2SConnectionsNumber = max_s2s_connections_number(FromTo), MaxS2SConnectionsNumber = max_s2s_connections_number(FromTo),
MaxS2SConnectionsNumberPerNode = MaxS2SConnectionsNumberPerNode =
@ -430,12 +430,12 @@ needed_connections_number(Ls, MaxS2SConnectionsNumber,
%% service. %% service.
%% -------------------------------------------------------------------- %% --------------------------------------------------------------------
is_service(From, To) -> is_service(From, To) ->
LFromDomain = From#jid.ldomain, LFromDomain = exmpp_jid:ldomain_as_list(From),
case ejabberd_config:get_local_option({route_subdomains, LFromDomain}) of case ejabberd_config:get_local_option({route_subdomains, LFromDomain}) of
s2s -> % bypass RFC 3920 10.3 s2s -> % bypass RFC 3920 10.3
false; false;
_ -> _ ->
LDstDomain = To#jid.ldomain, LDstDomain = exmpp_jid:ldomain_as_list(To),
P = fun(Domain) -> is_subdomain(LDstDomain, Domain) end, P = fun(Domain) -> is_subdomain(LDstDomain, Domain) end,
lists:any(P, ?MYHOSTS) lists:any(P, ?MYHOSTS)
end. end.

View File

@ -390,8 +390,8 @@ stream_established({xmlstreamelement, El}, StateData) ->
% This is handled by C2S and S2S send_element functions. % This is handled by C2S and S2S send_element functions.
if if
(To /= error) and (From /= error) -> (To /= error) and (From /= error) ->
LFrom = From#jid.ldomain, LFrom = exmpp_jid:ldomain_as_list(From),
LTo = To#jid.ldomain, LTo = exmpp_jid:ldomain_as_list(To),
if if
StateData#state.authenticated -> StateData#state.authenticated ->
case (LFrom == StateData#state.auth_domain) case (LFrom == StateData#state.auth_domain)
@ -406,7 +406,7 @@ stream_established({xmlstreamelement, El}, StateData) ->
(Name == 'presence')) -> (Name == 'presence')) ->
ejabberd_hooks:run( ejabberd_hooks:run(
s2s_receive_packet, s2s_receive_packet,
LFrom, exmpp_jid:ldomain(From),
[From, To, El]), [From, To, El]),
ejabberd_router:route( ejabberd_router:route(
From, To, El); From, To, El);
@ -426,7 +426,7 @@ stream_established({xmlstreamelement, El}, StateData) ->
(Name == 'presence')) -> (Name == 'presence')) ->
ejabberd_hooks:run( ejabberd_hooks:run(
s2s_receive_packet, s2s_receive_packet,
LFrom, exmpp_jid:ldomain(From),
[From, To, El]), [From, To, El]),
ejabberd_router:route( ejabberd_router:route(
From, To, El); From, To, El);
@ -612,10 +612,11 @@ get_cert_domains(Cert) ->
end, end,
if if
D /= error -> D /= error ->
case exmpp_jid:list_to_jid(D) of JID = exmpp_jid:list_to_jid(D),
#jid{lnode = undefined, case {exmpp_jid:lnode_as_list(JID),
ldomain = LD, exmpp_jid:ldomain_as_list(JID),
lresource = undefined} -> exmpp_jid:lresource_as_list(JID)} of
{undefined, LD, undefined} ->
[LD]; [LD];
_ -> _ ->
[] []
@ -647,11 +648,11 @@ get_cert_domains(Cert) ->
case 'XmppAddr':decode( case 'XmppAddr':decode(
'XmppAddr', XmppAddr) of 'XmppAddr', XmppAddr) of
{ok, D} when is_binary(D) -> {ok, D} when is_binary(D) ->
case exmpp_jid:list_to_jid( JID2 = exmpp_jid:list_to_jid(binary_to_list(D)),
binary_to_list(D)) of case {exmpp_jid:lnode_as_list(JID2),
#jid{lnode = undefined, exmpp_jid:ldomain_as_list(JID2),
ldomain = LD, exmpp_jid:lresource_as_list(JID2)} of
lresource = undefined} -> { undefined, LD, undefined} ->
case idna:domain_utf8_to_ascii(LD) of case idna:domain_utf8_to_ascii(LD) of
false -> false ->
[]; [];
@ -665,10 +666,11 @@ get_cert_domains(Cert) ->
[] []
end; end;
({dNSName, D}) when is_list(D) -> ({dNSName, D}) when is_list(D) ->
case exmpp_jid:list_to_jid(D) of JID3 = exmpp_jid:list_to_jid(D),
#jid{lnode = undefined, case {exmpp_jid:lnode_as_list(JID3),
ldomain = LD, exmpp_jid:ldomain_as_list(JID3),
lresource = undefined} -> exmpp_jid:lresource_as_list(JID3)} of
{undefined, LD, undefined} ->
[LD]; [LD];
_ -> _ ->
[] []

View File

@ -231,13 +231,10 @@ stream_established({xmlstreamelement, El}, StateData) ->
%% The default is the standard behaviour in XEP-0114 %% The default is the standard behaviour in XEP-0114
_ -> _ ->
FromJID1 = exmpp_jib:string_to_jid(From), FromJID1 = exmpp_jib:string_to_jid(From),
case FromJID1 of Server = exmpp_jid:ldomain_as_list(FromJID1),
#jid{ldomain = Server} ->
case lists:member(Server, StateData#state.hosts) of case lists:member(Server, StateData#state.hosts) of
true -> FromJID1; true -> FromJID1;
false -> error false -> error
end;
_ -> error
end end
end, end,
To = exmpp_stanza:get_recipient(El), To = exmpp_stanza:get_recipient(El),

View File

@ -32,14 +32,14 @@
%% API %% API
-export([start_link/0, -export([start_link/0,
route/3, route/3,
open_session/5, close_session/4, open_session/3, close_session/2,
check_in_subscription/6, check_in_subscription/6,
bounce_offline_message/3, bounce_offline_message/3,
disconnect_removed_user/2, disconnect_removed_user/2,
get_user_resources/2, get_user_resources/2,
set_presence/7, set_presence/5,
unset_presence/6, unset_presence/4,
close_session_unset_presence/5, close_session_unset_presence/3,
dirty_get_sessions_list/0, dirty_get_sessions_list/0,
dirty_get_my_sessions_list/0, dirty_get_my_sessions_list/0,
get_vh_session_list/1, get_vh_session_list/1,
@ -49,9 +49,9 @@
connected_users/0, connected_users/0,
connected_users_number/0, connected_users_number/0,
user_resources/2, user_resources/2,
get_session_pid/3, get_session_pid/1,
get_user_info/3, get_user_info/3,
get_user_ip/3 get_user_ip/1
]). ]).
%% gen_server callbacks %% gen_server callbacks
@ -76,6 +76,9 @@
{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx} {?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}
]). ]).
-define(IS_BINARY_OR_UNDEF(X),
(is_binary(X) orelse X == 'undefined')).
%%==================================================================== %%====================================================================
%% API %% API
%%==================================================================== %%====================================================================
@ -105,14 +108,13 @@ route(From, To, Packet) ->
ok ok
end. end.
open_session(SID, User, Server, Resource, Info) -> open_session(SID, JID, Info) when ?IS_JID(JID) ->
set_session(SID, User, Server, Resource, undefined, Info), set_session(SID, JID, undefined, Info),
check_for_sessions_to_replace(User, Server, Resource), check_for_sessions_to_replace(JID),
JID = exmpp_jid:make_jid(User, Server, Resource), ejabberd_hooks:run(sm_register_connection_hook, exmpp_jid:ldomain(JID),
ejabberd_hooks:run(sm_register_connection_hook, JID#jid.ldomain,
[SID, JID, Info]). [SID, JID, Info]).
close_session(SID, User, Server, Resource) -> close_session(SID, JID ) when ?IS_JID(JID)->
Info = case mnesia:dirty_read({session, SID}) of Info = case mnesia:dirty_read({session, SID}) of
[] -> []; [] -> [];
[#session{info=I}] -> I [#session{info=I}] -> I
@ -121,12 +123,12 @@ close_session(SID, User, Server, Resource) ->
mnesia:delete({session, SID}) mnesia:delete({session, SID})
end, end,
mnesia:sync_dirty(F), mnesia:sync_dirty(F),
JID = exmpp_jid:make_jid(User, Server, Resource), ejabberd_hooks:run(sm_remove_connection_hook, exmpp_jid:ldomain(JID),
ejabberd_hooks:run(sm_remove_connection_hook, JID#jid.ldomain,
[SID, JID, Info]). [SID, JID, Info]).
check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) -> check_in_subscription(Acc, User, Server, _JID, _Type, _Reason)
case ejabberd_auth:is_user_exists(User, Server) of when is_binary(User), is_binary(Server)->
case ejabberd_auth:is_user_exists(binary_to_list(User), binary_to_list(Server)) of
true -> true ->
Acc; Acc;
false -> false ->
@ -139,27 +141,26 @@ bounce_offline_message(From, To, Packet) ->
stop. stop.
disconnect_removed_user(User, Server) -> disconnect_removed_user(User, Server) ->
ejabberd_sm:route(#jid{}, ejabberd_sm:route(exmpp_jid:make_jid(),
exmpp_jid:make_bare_jid(User, Server), exmpp_jid:make_bare_jid(User,
Server),
#xmlel{name = 'broadcast', #xmlel{name = 'broadcast',
children = [{exit, "User removed"}]}). children = [{exit, "User removed"}]}).
get_user_resources(User, Server) -> get_user_resources(User, Server)
LUser = exmpp_stringprep:nodeprep(User), when is_binary(User), is_binary(Server) ->
LServer = exmpp_stringprep:nameprep(Server), US = {User, Server},
US = {LUser, LServer},
case catch mnesia:dirty_index_read(session, US, #session.us) of case catch mnesia:dirty_index_read(session, US, #session.us) of
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
[]; [];
Ss -> Ss ->
[element(3, S#session.usr) || S <- clean_session_list(Ss)] [binary_to_list(element(3, S#session.usr)) || S <- clean_session_list(Ss)]
end. end.
get_user_ip(User, Server, Resource) -> get_user_ip(JID) when ?IS_JID(JID) ->
LUser = exmpp_stringprep:nodeprep(User), USR = {exmpp_jid:lnode(JID),
LServer = exmpp_stringprep:nameprep(Server), exmpp_jid:ldomain(JID),
LResource = exmpp_stringprep:resourceprep(Resource), exmpp_jid:lresource(JID)},
USR = {LUser, LServer, LResource},
case mnesia:dirty_index_read(session, USR, #session.usr) of case mnesia:dirty_index_read(session, USR, #session.usr) of
[] -> [] ->
undefined; undefined;
@ -168,11 +169,16 @@ get_user_ip(User, Server, Resource) ->
proplists:get_value(ip, Session#session.info) proplists:get_value(ip, Session#session.info)
end. end.
get_user_info(User, Server, Resource) -> get_user_info(User, Server, Resource)
when is_binary(User),
is_binary(Server),
is_binary(Resource) ->
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
LResource = exmpp_stringprep:resourceprep(Resource), LResource = exmpp_stringprep:resourceprep(Resource),
USR = {LUser, LServer, LResource}, USR = {list_to_binary(LUser),
list_to_binary(LServer),
list_to_binary(LResource)},
case mnesia:dirty_index_read(session, USR, #session.usr) of case mnesia:dirty_index_read(session, USR, #session.usr) of
[] -> [] ->
offline; offline;
@ -184,26 +190,37 @@ get_user_info(User, Server, Resource) ->
[{node, Node}, {conn, Conn}, {ip, IP}] [{node, Node}, {conn, Conn}, {ip, IP}]
end. end.
set_presence(SID, User, Server, Resource, Priority, Presence, Info) -> set_presence(SID, JID, Priority, Presence, Info) when ?IS_JID(JID) ->
set_session(SID, User, Server, Resource, Priority, Info), set_session(SID, JID, Priority, Info),
ejabberd_hooks:run(set_presence_hook, exmpp_stringprep:nameprep(Server), ejabberd_hooks:run(set_presence_hook,
[User, Server, Resource, Presence]). exmpp_jid:ldomain(JID),
[exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID),
exmpp_jid:lresource(JID),
Presence]).
unset_presence(SID, User, Server, Resource, Status, Info) -> unset_presence(SID, JID, Status, Info) when ?IS_JID(JID)->
set_session(SID, User, Server, Resource, undefined, Info), set_session(SID, JID, undefined, Info),
ejabberd_hooks:run(unset_presence_hook, exmpp_stringprep:nameprep(Server), ejabberd_hooks:run(unset_presence_hook,
[User, Server, Resource, Status]). exmpp_jid:ldomain(JID),
[exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID),
exmpp_jid:lresource(JID),
Status]).
close_session_unset_presence(SID, User, Server, Resource, Status) -> close_session_unset_presence(SID, JID, Status) when ?IS_JID(JID) ->
close_session(SID, User, Server, Resource), close_session(SID, JID),
ejabberd_hooks:run(unset_presence_hook, exmpp_stringprep:nameprep(Server), ejabberd_hooks:run(unset_presence_hook,
[User, Server, Resource, Status]). exmpp_jid:ldomain(JID),
[exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID),
exmpp_jid:lresource(JID),
Status]).
get_session_pid(User, Server, Resource) -> get_session_pid(JID) when ?IS_JID(JID) ->
LUser = exmpp_stringprep:nodeprep(User), USR = {exmpp_jid:lnode(JID),
LServer = exmpp_stringprep:nameprep(Server), exmpp_jid:ldomain(JID),
LResource = exmpp_stringprep:resourceprep(Resource), exmpp_jid:lresource(JID)},
USR = {LUser, LServer, LResource},
case catch mnesia:dirty_index_read(session, USR, #session.usr) of case catch mnesia:dirty_index_read(session, USR, #session.usr) of
[#session{sid = {_, Pid}}] -> Pid; [#session{sid = {_, Pid}}] -> Pid;
_ -> none _ -> none
@ -223,8 +240,9 @@ dirty_get_my_sessions_list() ->
[{'==', {node, '$1'}, node()}], [{'==', {node, '$1'}, node()}],
['$_']}]). ['$_']}]).
get_vh_session_list(Server) -> get_vh_session_list(Server) when is_binary(Server) ->
LServer = exmpp_stringprep:nameprep(Server), LServer = list_to_binary(
exmpp_stringprep:nameprep(Server)),
mnesia:dirty_select( mnesia:dirty_select(
session, session,
[{#session{usr = '$1', _ = '_'}, [{#session{usr = '$1', _ = '_'},
@ -264,11 +282,12 @@ init([]) ->
ets:new(sm_iqtable, [named_table]), ets:new(sm_iqtable, [named_table]),
lists:foreach( lists:foreach(
fun(Host) -> fun(Host) ->
ejabberd_hooks:add(roster_in_subscription, Host, HostB = list_to_binary(Host),
ejabberd_hooks:add(roster_in_subscription, HostB,
ejabberd_sm, check_in_subscription, 20), ejabberd_sm, check_in_subscription, 20),
ejabberd_hooks:add(offline_message_hook, Host, ejabberd_hooks:add(offline_message_hook, HostB,
ejabberd_sm, bounce_offline_message, 100), ejabberd_sm, bounce_offline_message, 100),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
ejabberd_sm, disconnect_removed_user, 100) ejabberd_sm, disconnect_removed_user, 100)
end, ?MYHOSTS), end, ?MYHOSTS),
ejabberd_commands:register_commands(commands()), ejabberd_commands:register_commands(commands()),
@ -365,12 +384,11 @@ code_change(_OldVsn, State, _Extra) ->
%%% Internal functions %%% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
set_session(SID, User, Server, Resource, Priority, Info) -> set_session(SID, JID, Priority, Info) ->
LUser = exmpp_stringprep:nodeprep(User), US = {exmpp_jid:node(JID), exmpp_jid:ldomain(JID)},
LServer = exmpp_stringprep:nameprep(Server), USR = {exmpp_jid:node(JID),
LResource = exmpp_stringprep:resourceprep(Resource), exmpp_jid:ldomain(JID),
US = {LUser, LServer}, exmpp_jid:lresource(JID)},
USR = {LUser, LServer, LResource},
F = fun() -> F = fun() ->
mnesia:write(#session{sid = SID, mnesia:write(#session{sid = SID,
usr = USR, usr = USR,
@ -398,9 +416,7 @@ clean_table_from_bad_node(Node) ->
do_route(From, To, Packet) -> do_route(From, To, Packet) ->
?DEBUG("session manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n", ?DEBUG("session manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]), [From, To, Packet, 8]),
#jid{node = User, domain = Server, case exmpp_jid:lresource(To) of
lnode = LUser, ldomain = LServer, lresource = LResource} = To,
case LResource of
undefined -> undefined ->
case Packet of case Packet of
_ when ?IS_PRESENCE(Packet) -> _ when ?IS_PRESENCE(Packet) ->
@ -410,37 +426,37 @@ do_route(From, To, Packet) ->
Reason = exmpp_presence:get_status(Packet), Reason = exmpp_presence:get_status(Packet),
{ejabberd_hooks:run_fold( {ejabberd_hooks:run_fold(
roster_in_subscription, roster_in_subscription,
LServer, exmpp_jid:ldomain(To),
false, false,
[User, Server, From, subscribe, Reason]), [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), From, subscribe, Reason]),
true}; true};
'subscribed' -> 'subscribed' ->
{ejabberd_hooks:run_fold( {ejabberd_hooks:run_fold(
roster_in_subscription, roster_in_subscription,
LServer, exmpp_jid:ldomain(To),
false, false,
[User, Server, From, subscribed, <<>>]), [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), From, subscribed, <<>>]),
true}; true};
'unsubscribe' -> 'unsubscribe' ->
{ejabberd_hooks:run_fold( {ejabberd_hooks:run_fold(
roster_in_subscription, roster_in_subscription,
LServer, exmpp_jid:ldomain(To),
false, false,
[User, Server, From, unsubscribe, <<>>]), [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), From, unsubscribe, <<>>]),
true}; true};
'unsubscribed' -> 'unsubscribed' ->
{ejabberd_hooks:run_fold( {ejabberd_hooks:run_fold(
roster_in_subscription, roster_in_subscription,
LServer, exmpp_jid:ldomain(To),
false, false,
[User, Server, From, unsubscribed, <<>>]), [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), From, unsubscribed, <<>>]),
true}; true};
_ -> _ ->
{true, false} {true, false}
end, end,
if Pass -> if Pass ->
PResources = get_user_present_resources( PResources = get_user_present_resources(
LUser, LServer), exmpp_jid:lnode(To), exmpp_jid:ldomain(To)),
lists:foreach( lists:foreach(
fun({_, R}) -> fun({_, R}) ->
do_route( do_route(
@ -461,12 +477,15 @@ do_route(From, To, Packet) ->
do_route(From, do_route(From,
exmpp_jid:bare_jid_to_jid(To, R), exmpp_jid:bare_jid_to_jid(To, R),
Packet) Packet)
end, get_user_resources(User, Server)); end, get_user_resources(exmpp_jid:lnode(To),
exmpp_jid:ldomain(To)));
_ -> _ ->
ok ok
end; end;
_ -> _ ->
USR = {LUser, LServer, LResource}, USR = {exmpp_jid:lnode(To),
exmpp_jid:ldomain(To),
exmpp_jid:lresource(To)},
case mnesia:dirty_index_read(session, USR, #session.usr) of case mnesia:dirty_index_read(session, USR, #session.usr) of
[] -> [] ->
case Packet of case Packet of
@ -494,8 +513,8 @@ do_route(From, To, Packet) ->
end. end.
route_message(From, To, Packet) -> route_message(From, To, Packet) ->
LUser = To#jid.lnode, LUser = exmpp_jid:lnode(To),
LServer = To#jid.ldomain, LServer = exmpp_jid:ldomain(To),
PrioRes = get_user_present_resources(LUser, LServer), PrioRes = get_user_present_resources(LUser, LServer),
case catch lists:max(PrioRes) of case catch lists:max(PrioRes) of
{Priority, _R} when is_integer(Priority), Priority >= 0 -> {Priority, _R} when is_integer(Priority), Priority >= 0 ->
@ -503,8 +522,7 @@ route_message(From, To, Packet) ->
%% Route messages to all priority that equals the max, if %% Route messages to all priority that equals the max, if
%% positive %% positive
fun({P, R}) when P == Priority -> fun({P, R}) when P == Priority ->
LResource = exmpp_stringprep:resourceprep(R), USR = {LUser, LServer, R},
USR = {LUser, LServer, LResource},
case mnesia:dirty_index_read(session, USR, #session.usr) of case mnesia:dirty_index_read(session, USR, #session.usr) of
[] -> [] ->
ok; % Race condition ok; % Race condition
@ -528,10 +546,11 @@ route_message(From, To, Packet) ->
'headline' -> 'headline' ->
bounce_offline_message(From, To, Packet); bounce_offline_message(From, To, Packet);
_ -> _ ->
case ejabberd_auth:is_user_exists(LUser, LServer) of case ejabberd_auth:is_user_exists(exmpp_jid:lnode_as_list(To),
exmpp_jid:ldomain_as_list(To)) of
true -> true ->
ejabberd_hooks:run(offline_message_hook, ejabberd_hooks:run(offline_message_hook,
LServer, exmpp_jid:ldomain(To),
[From, To, Packet]); [From, To, Packet]);
_ -> _ ->
Err = exmpp_stanza:reply_with_error( Err = exmpp_stanza:reply_with_error(
@ -580,18 +599,16 @@ get_user_present_resources(LUser, LServer) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% On new session, check if some existing connections need to be replace %% On new session, check if some existing connections need to be replace
check_for_sessions_to_replace(User, Server, Resource) -> check_for_sessions_to_replace(JID) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
LResource = exmpp_stringprep:resourceprep(Resource),
%% TODO: Depending on how this is executed, there could be an unneeded %% TODO: Depending on how this is executed, there could be an unneeded
%% replacement for max_sessions. We need to check this at some point. %% replacement for max_sessions. We need to check this at some point.
check_existing_resources(LUser, LServer, LResource), check_existing_resources(JID),
check_max_sessions(LUser, LServer). check_max_sessions(JID).
check_existing_resources(LUser, LServer, LResource) -> check_existing_resources(JID) ->
USR = {LUser, LServer, LResource}, USR = {exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID),
exmpp_jid:lresource(JID)},
%% A connection exist with the same resource. We replace it: %% A connection exist with the same resource. We replace it:
SIDs = mnesia:dirty_select( SIDs = mnesia:dirty_select(
session, session,
@ -607,14 +624,16 @@ check_existing_resources(LUser, LServer, LResource) ->
end, SIDs) end, SIDs)
end. end.
check_max_sessions(LUser, LServer) -> check_max_sessions(JID) ->
%% If the max number of sessions for a given is reached, we replace the %% If the max number of sessions for a given is reached, we replace the
%% first one %% first one
SIDs = mnesia:dirty_select( SIDs = mnesia:dirty_select(
session, session,
[{#session{sid = '$1', us = {LUser, LServer}, _ = '_'}, [], [{#session{sid = '$1',
us = {exmpp_jid:lnode(JID), exmpp_jid:ldomain(JID)},
_ = '_'}, [],
['$1']}]), ['$1']}]),
MaxSessions = get_max_user_sessions(LUser, LServer), MaxSessions = get_max_user_sessions(JID),
if if
length(SIDs) =< MaxSessions -> length(SIDs) =< MaxSessions ->
ok; ok;
@ -628,9 +647,9 @@ check_max_sessions(LUser, LServer) ->
%% This option defines the max number of time a given users are allowed to %% This option defines the max number of time a given users are allowed to
%% log in %% log in
%% Defaults to infinity %% Defaults to infinity
get_max_user_sessions(LUser, Host) -> get_max_user_sessions(JID) ->
case acl:match_rule( case acl:match_rule(
Host, max_user_sessions, exmpp_jid:make_bare_jid(LUser, Host)) of exmpp_jid:ldomain_as_list(JID), max_user_sessions, exmpp_jid:jid_to_bare_jid(JID)) of
Max when is_integer(Max) -> Max; Max when is_integer(Max) -> Max;
infinity -> infinity; infinity -> infinity;
_ -> ?MAX_USER_SESSIONS _ -> ?MAX_USER_SESSIONS
@ -642,8 +661,8 @@ get_max_user_sessions(LUser, Host) ->
process_iq(From, To, Packet) -> process_iq(From, To, Packet) ->
case exmpp_iq:xmlel_to_iq(Packet) of case exmpp_iq:xmlel_to_iq(Packet) of
#iq{kind = request, ns = XMLNS} = IQ_Rec -> #iq{kind = request, ns = XMLNS} = IQ_Rec ->
Host = To#jid.ldomain, LServer = exmpp_jid:ldomain_as_list(To),
case ets:lookup(sm_iqtable, {XMLNS, Host}) of case ets:lookup(sm_iqtable, {XMLNS, LServer}) of
[{_, Module, Function}] -> [{_, Module, Function}] ->
ResIQ = Module:Function(From, To, IQ_Rec), ResIQ = Module:Function(From, To, IQ_Rec),
if if
@ -654,8 +673,8 @@ process_iq(From, To, Packet) ->
ok ok
end; end;
[{_, Module, Function, Opts}] -> [{_, Module, Function, Opts}] ->
gen_iq_handler:handle(Host, Module, Function, Opts, gen_iq_handler:handle(LServer,
From, To, IQ_Rec); Module, Function, Opts, From, To, IQ_Rec);
[] -> [] ->
Err = exmpp_iq:error(Packet, 'service-unavailable'), Err = exmpp_iq:error(Packet, 'service-unavailable'),
ejabberd_router:route(To, From, Err) ejabberd_router:route(To, From, Err)
@ -703,7 +722,8 @@ connected_users_number() ->
length(dirty_get_sessions_list()). length(dirty_get_sessions_list()).
user_resources(User, Server) -> user_resources(User, Server) ->
Resources = get_user_resources(User, Server), Resources = get_user_resources(list_to_binary(User),
list_to_binary(Server)),
lists:sort(Resources). lists:sort(Resources).

View File

@ -55,12 +55,13 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
process_command(From, To, Packet) -> process_command(From, To, Packet) ->
case To of case {exmpp_jid:lnode(To), exmpp_jid:lresource(To) } of
#jid{lnode = undefined, lresource = "watchdog"} -> {undefined, <<"watchdog">>} ->
case Packet#xmlel.name of case Packet#xmlel.name of
'message' -> 'message' ->
LFrom = jlib:short_prepd_bare_jid(From), case lists:any(fun(J) ->
case lists:member(LFrom, get_admin_jids()) of exmpp_jid:compare_jids(J,From)
end, get_admin_jids()) of
true -> true ->
Body = exmpp_xml:get_path( Body = exmpp_xml:get_path(
Packet, [{element, 'body'}, cdata_as_list]), Packet, [{element, 'body'}, cdata_as_list]),
@ -95,7 +96,8 @@ init([]) ->
erlang:system_monitor(self(), [{large_heap, 1000000}]), erlang:system_monitor(self(), [{large_heap, 1000000}]),
lists:foreach( lists:foreach(
fun(Host) -> fun(Host) ->
ejabberd_hooks:add(local_send_to_resource_hook, Host, ejabberd_hooks:add(local_send_to_resource_hook,
list_to_binary(Host),
?MODULE, process_command, 50) ?MODULE, process_command, 50)
end, ?MYHOSTS), end, ?MYHOSTS),
{ok, #state{}}. {ok, #state{}}.
@ -168,7 +170,7 @@ process_large_heap(Pid, Info) ->
"(~w) The process ~w is consuming too much memory: ~w.~n" "(~w) The process ~w is consuming too much memory: ~w.~n"
"~s", "~s",
[node(), Pid, Info, DetailedInfo]), [node(), Pid, Info, DetailedInfo]),
From = exmpp_jid:make_jid(undefined, Host, "watchdog"), From = exmpp_jid:make_jid(undefined, Host, <<"watchdog">>),
lists:foreach( lists:foreach(
fun(S) -> fun(S) ->
try try
@ -195,7 +197,9 @@ get_admin_jids() ->
fun(S) -> fun(S) ->
try try
JID = exmpp_jid:list_to_jid(S), JID = exmpp_jid:list_to_jid(S),
[jlib:short_prepd_jid(JID)] [{exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID),
exmpp_jid:lresource(JID)}]
catch catch
_ -> _ ->
[] []

View File

@ -37,7 +37,6 @@
encode_base64/1, encode_base64/1,
ip_to_list/1, ip_to_list/1,
from_old_jid/1, from_old_jid/1,
to_old_jid/1,
short_jid/1, short_jid/1,
short_bare_jid/1, short_bare_jid/1,
short_prepd_jid/1, short_prepd_jid/1,
@ -295,49 +294,26 @@ ip_to_list({A,B,C,D}) ->
%% %%
%% Empty fields are set to `undefined', not the empty string. %% Empty fields are set to `undefined', not the empty string.
from_old_jid(#jid{node = Node, resource = Resource, %%TODO: this doesn't make sence!, it is still used?.
lnode = LNode, lresource = LResource} = JID) -> from_old_jid(JID) ->
{Node1, LNode1} = case Node of Node = exmpp_jid:node(JID),
"" -> {undefined, undefined}; Resource = exmpp_jid:resource(JID),
_ -> {Node, LNode} Domain = exmpp_jid:domain(JID),
end, exmpp_jid:make_jid(Node,Domain,Resource).
{Resource1, LResource1} = case Resource of
"" -> {undefined, undefined};
_ -> {Resource, LResource}
end,
JID#jid{node = Node1, resource = Resource1,
lnode = LNode1, lresource = LResource1}.
%% @spec (JID) -> New_JID
%% JID = jid()
%% New_JID = jid()
%% @doc Convert a JID from its exmpp form to its ejabberd form.
%%
%% Empty fields are set to the empty string, not `undefined'.
to_old_jid(#jid{node = Node, resource = Resource,
lnode = LNode, lresource = LResource} = JID) ->
{Node1, LNode1} = case Node of
undefined -> {"", ""};
_ -> {Node, LNode}
end,
{Resource1, LResource1} = case Resource of
undefined -> {"", ""};
_ -> {Resource, LResource}
end,
JID#jid{node = Node1, resource = Resource1,
lnode = LNode1, lresource = LResource1}.
short_jid(JID) -> short_jid(JID) ->
{JID#jid.node, JID#jid.domain, JID#jid.resource}. {exmpp_jid:node(JID), exmpp_jid:domain(JID), exmpp_jid:resource(JID)}.
short_bare_jid(JID) -> short_bare_jid(JID) ->
Bare_JID = exmpp_jid:jid_to_bare_jid(JID), short_jid(exmpp_jid:jid_to_bare_jid(JID)).
{Bare_JID#jid.node, Bare_JID#jid.domain, Bare_JID#jid.resource}.
short_prepd_jid(JID) -> short_prepd_jid(JID) ->
{JID#jid.lnode, JID#jid.ldomain, JID#jid.lresource}. {exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID),
exmpp_jid:lresource(JID)}.
short_prepd_bare_jid(JID) -> short_prepd_bare_jid(JID) ->
Bare_JID = exmpp_jid:jid_to_bare_jid(JID), short_prepd_jid(exmpp_jid:jid_to_bare_jid(JID)).
{Bare_JID#jid.lnode, Bare_JID#jid.ldomain, Bare_JID#jid.lresource}.

View File

@ -48,6 +48,7 @@
-include("adhoc.hrl"). -include("adhoc.hrl").
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
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_ADHOC, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_ADHOC,
@ -55,31 +56,34 @@ start(Host, Opts) ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ADHOC, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ADHOC,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 99), ejabberd_hooks:add(disco_local_identity, HostB, ?MODULE, get_local_identity, 99),
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 99), ejabberd_hooks:add(disco_local_features, HostB, ?MODULE, get_local_features, 99),
ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_commands, 99), ejabberd_hooks:add(disco_local_items, HostB, ?MODULE, get_local_commands, 99),
ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 99), ejabberd_hooks:add(disco_sm_identity, HostB, ?MODULE, get_sm_identity, 99),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 99), ejabberd_hooks:add(disco_sm_features, HostB, ?MODULE, get_sm_features, 99),
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_commands, 99), ejabberd_hooks:add(disco_sm_items, HostB, ?MODULE, get_sm_commands, 99),
ejabberd_hooks:add(adhoc_local_items, Host, ?MODULE, ping_item, 100), ejabberd_hooks:add(adhoc_local_items, HostB, ?MODULE, ping_item, 100),
ejabberd_hooks:add(adhoc_local_commands, Host, ?MODULE, ping_command, 100). ejabberd_hooks:add(adhoc_local_commands, HostB, ?MODULE, ping_command, 100).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(adhoc_local_commands, Host, ?MODULE, ping_command, 100), HostB = list_to_binary(Host),
ejabberd_hooks:delete(adhoc_local_items, Host, ?MODULE, ping_item, 100), ejabberd_hooks:delete(adhoc_local_commands, HostB, ?MODULE, ping_command, 100),
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_commands, 99), ejabberd_hooks:delete(adhoc_local_items, HostB, ?MODULE, ping_item, 100),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 99), ejabberd_hooks:delete(disco_sm_items, HostB, ?MODULE, get_sm_commands, 99),
ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 99), ejabberd_hooks:delete(disco_sm_features, HostB, ?MODULE, get_sm_features, 99),
ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_commands, 99), ejabberd_hooks:delete(disco_sm_identity, HostB, ?MODULE, get_sm_identity, 99),
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 99), ejabberd_hooks:delete(disco_local_items, HostB, ?MODULE, get_local_commands, 99),
ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 99), ejabberd_hooks:delete(disco_local_features, HostB, ?MODULE, get_local_features, 99),
ejabberd_hooks:delete(disco_local_identity, HostB, ?MODULE, get_local_identity, 99),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ADHOC), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ADHOC),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ADHOC). gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ADHOC).
%------------------------------------------------------------------------- %-------------------------------------------------------------------------
get_local_commands(Acc, _From, #jid{domain = Server, ldomain = LServer} = _To, "", Lang) -> get_local_commands(Acc, _From, To, "", Lang) ->
Server = exmpp_jid:domain_as_list(To),
LServer = exmpp_jid:ldomain_as_list(To),
Display = gen_mod:get_module_opt(LServer, ?MODULE, report_commands_node, false), Display = gen_mod:get_module_opt(LServer, ?MODULE, report_commands_node, false),
case Display of case Display of
false -> false ->
@ -98,8 +102,8 @@ get_local_commands(Acc, _From, #jid{domain = Server, ldomain = LServer} = _To, "
{result, Items ++ Nodes} {result, Items ++ Nodes}
end; end;
get_local_commands(_Acc, From, #jid{ldomain = LServer} = To, ?NS_ADHOC_s, Lang) -> get_local_commands(_Acc, From, To, ?NS_ADHOC_s, Lang) ->
ejabberd_hooks:run_fold(adhoc_local_items, LServer, {result, []}, [From, To, Lang]); ejabberd_hooks:run_fold(adhoc_local_items, exmpp_jid:ldomain(To), {result, []}, [From, To, Lang]);
get_local_commands(_Acc, _From, _To, "ping", _Lang) -> get_local_commands(_Acc, _From, _To, "ping", _Lang) ->
{result, []}; {result, []};
@ -109,7 +113,8 @@ get_local_commands(Acc, _From, _To, _Node, _Lang) ->
%------------------------------------------------------------------------- %-------------------------------------------------------------------------
get_sm_commands(Acc, _From, #jid{ldomain = LServer} = To, "", Lang) -> get_sm_commands(Acc, _From, To, "", Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
Display = gen_mod:get_module_opt(LServer, ?MODULE, report_commands_node, false), Display = gen_mod:get_module_opt(LServer, ?MODULE, report_commands_node, false),
case Display of case Display of
false -> false ->
@ -128,8 +133,8 @@ get_sm_commands(Acc, _From, #jid{ldomain = LServer} = To, "", Lang) ->
{result, Items ++ Nodes} {result, Items ++ Nodes}
end; end;
get_sm_commands(_Acc, From, #jid{ldomain = LServer} = To, ?NS_ADHOC_s, Lang) -> get_sm_commands(_Acc, From, To, ?NS_ADHOC_s, Lang) ->
ejabberd_hooks:run_fold(adhoc_sm_items, LServer, {result, []}, [From, To, Lang]); ejabberd_hooks:run_fold(adhoc_sm_items, exmpp_jid:ldomain(To), {result, []}, [From, To, Lang]);
get_sm_commands(Acc, _From, _To, _Node, _Lang) -> get_sm_commands(Acc, _From, _To, _Node, _Lang) ->
Acc. Acc.
@ -216,8 +221,7 @@ process_adhoc_request(From, To, IQ_Rec, Hook) ->
{error, Error} -> {error, Error} ->
exmpp_iq:error(IQ_Rec, Error); exmpp_iq:error(IQ_Rec, Error);
#adhoc_request{} = AdhocRequest -> #adhoc_request{} = AdhocRequest ->
Host = To#jid.ldomain, case ejabberd_hooks:run_fold(Hook, exmpp_jid:ldomain(To), empty,
case ejabberd_hooks:run_fold(Hook, Host, empty,
[From, To, AdhocRequest]) of [From, To, AdhocRequest]) of
ignore -> ignore ->
ignore; ignore;
@ -231,7 +235,8 @@ process_adhoc_request(From, To, IQ_Rec, Hook) ->
end. end.
ping_item(Acc, _From, #jid{domain = Server} = _To, Lang) -> ping_item(Acc, _From, To, Lang) ->
Server = exmpp_jid:domain_as_list(To),
Items = case Acc of Items = case Acc of
{result, I} -> {result, I} ->
I; I;

View File

@ -59,19 +59,20 @@
tokenize(Node) -> string:tokens(Node, "/#"). tokenize(Node) -> string:tokens(Node, "/#").
start(Host, _Opts) -> start(Host, _Opts) ->
HostB = list_to_binary(Host),
mnesia:create_table(motd, [{disc_copies, [node()]}, mnesia:create_table(motd, [{disc_copies, [node()]},
{attributes, record_info(fields, motd)}]), {attributes, record_info(fields, motd)}]),
mnesia:create_table(motd_users, [{disc_copies, [node()]}, mnesia:create_table(motd_users, [{disc_copies, [node()]},
{attributes, record_info(fields, motd_users)}]), {attributes, record_info(fields, motd_users)}]),
update_tables(), update_tables(),
ejabberd_hooks:add(local_send_to_resource_hook, Host, ejabberd_hooks:add(local_send_to_resource_hook, HostB,
?MODULE, announce, 50), ?MODULE, announce, 50),
ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, disco_identity, 50), ejabberd_hooks:add(disco_local_identity, HostB, ?MODULE, disco_identity, 50),
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50), ejabberd_hooks:add(disco_local_features, HostB, ?MODULE, disco_features, 50),
ejabberd_hooks:add(disco_local_items, Host, ?MODULE, disco_items, 50), ejabberd_hooks:add(disco_local_items, HostB, ?MODULE, disco_items, 50),
ejabberd_hooks:add(adhoc_local_items, Host, ?MODULE, announce_items, 50), ejabberd_hooks:add(adhoc_local_items, HostB, ?MODULE, announce_items, 50),
ejabberd_hooks:add(adhoc_local_commands, Host, ?MODULE, announce_commands, 50), ejabberd_hooks:add(adhoc_local_commands, HostB, ?MODULE, announce_commands, 50),
ejabberd_hooks:add(user_available_hook, Host, ejabberd_hooks:add(user_available_hook, HostB,
?MODULE, send_motd, 50), ?MODULE, send_motd, 50),
register(gen_mod:get_module_proc(Host, ?PROCNAME), register(gen_mod:get_module_proc(Host, ?PROCNAME),
proc_lib:spawn(?MODULE, init, [])). proc_lib:spawn(?MODULE, init, [])).
@ -116,14 +117,15 @@ loop() ->
end. end.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(adhoc_local_commands, Host, ?MODULE, announce_commands, 50), HostB = list_to_binary(Host),
ejabberd_hooks:delete(adhoc_local_items, Host, ?MODULE, announce_items, 50), ejabberd_hooks:delete(adhoc_local_commands, HostB, ?MODULE, announce_commands, 50),
ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, disco_identity, 50), ejabberd_hooks:delete(adhoc_local_items, HostB, ?MODULE, announce_items, 50),
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50), ejabberd_hooks:delete(disco_local_identity, HostB, ?MODULE, disco_identity, 50),
ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, disco_items, 50), ejabberd_hooks:delete(disco_local_features, HostB, ?MODULE, disco_features, 50),
ejabberd_hooks:delete(local_send_to_resource_hook, Host, ejabberd_hooks:delete(disco_local_items, HostB, ?MODULE, disco_items, 50),
ejabberd_hooks:delete(local_send_to_resource_hook, HostB,
?MODULE, announce, 50), ?MODULE, announce, 50),
ejabberd_hooks:delete(user_available_hook, Host, ejabberd_hooks:delete(user_available_hook, HostB,
?MODULE, send_motd, 50), ?MODULE, send_motd, 50),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
exit(whereis(Proc), stop), exit(whereis(Proc), stop),
@ -131,39 +133,39 @@ stop(Host) ->
%% Announcing via messages to a custom resource %% Announcing via messages to a custom resource
announce(From, To, Packet) -> announce(From, To, Packet) ->
case To of case {exmpp_jid:lnode(To), exmpp_jid:lresource(To)} of
#jid{lnode = undefined, lresource = Res} -> {undefined, Res} ->
Name = Packet#xmlel.name, Name = Packet#xmlel.name,
Proc = gen_mod:get_module_proc(To#jid.ldomain, ?PROCNAME), Proc = gen_mod:get_module_proc(exmpp_jid:ldomain_as_list(To), ?PROCNAME),
case {Res, Name} of case {Res, Name} of
{"announce/all", 'message'} -> {<<"announce/all">>, 'message'} ->
Proc ! {announce_all, From, To, Packet}, Proc ! {announce_all, From, To, Packet},
stop; stop;
{"announce/all-hosts/all", 'message'} -> {<<"announce/all-hosts/all">>, 'message'} ->
Proc ! {announce_all_hosts_all, From, To, Packet}, Proc ! {announce_all_hosts_all, From, To, Packet},
stop; stop;
{"announce/online", 'message'} -> {<<"announce/online">>, 'message'} ->
Proc ! {announce_online, From, To, Packet}, Proc ! {announce_online, From, To, Packet},
stop; stop;
{"announce/all-hosts/online", 'message'} -> {<<"announce/all-hosts/online">>, 'message'} ->
Proc ! {announce_all_hosts_online, From, To, Packet}, Proc ! {announce_all_hosts_online, From, To, Packet},
stop; stop;
{"announce/motd", 'message'} -> {<<"announce/motd">>, 'message'} ->
Proc ! {announce_motd, From, To, Packet}, Proc ! {announce_motd, From, To, Packet},
stop; stop;
{"announce/all-hosts/motd", 'message'} -> {<<"announce/all-hosts/motd">>, 'message'} ->
Proc ! {announce_all_hosts_motd, From, To, Packet}, Proc ! {announce_all_hosts_motd, From, To, Packet},
stop; stop;
{"announce/motd/update", 'message'} -> {<<"announce/motd/update">>, 'message'} ->
Proc ! {announce_motd_update, From, To, Packet}, Proc ! {announce_motd_update, From, To, Packet},
stop; stop;
{"announce/all-hosts/motd/update", 'message'} -> {<<"announce/all-hosts/motd/update">>, 'message'} ->
Proc ! {announce_all_hosts_motd_update, From, To, Packet}, Proc ! {announce_all_hosts_motd_update, From, To, Packet},
stop; stop;
{"announce/motd/delete", 'message'} -> {<<"announce/motd/delete">>, 'message'} ->
Proc ! {announce_motd_delete, From, To, Packet}, Proc ! {announce_motd_delete, From, To, Packet},
stop; stop;
{"announce/all-hosts/motd/delete", 'message'} -> {<<"announce/all-hosts/motd/delete">>, 'message'} ->
Proc ! {announce_all_hosts_motd_delete, From, To, Packet}, Proc ! {announce_all_hosts_motd_delete, From, To, Packet},
stop; stop;
_ -> _ ->
@ -218,8 +220,8 @@ disco_identity(Acc, _From, _To, Node, Lang) ->
{result, Feats} {result, Feats}
end). end).
disco_features(Acc, From, #jid{ldomain = LServer} = _To, disco_features(Acc, From, To, "announce", _Lang) ->
"announce", _Lang) -> LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -235,8 +237,8 @@ disco_features(Acc, From, #jid{ldomain = LServer} = _To,
end end
end; end;
disco_features(Acc, From, #jid{ldomain = LServer} = _To, disco_features(Acc, From, To, Node, _Lang) ->
Node, _Lang) -> LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -287,8 +289,10 @@ disco_features(Acc, From, #jid{ldomain = LServer} = _To,
{result, Items} {result, Items}
end). end).
disco_items(Acc, From, #jid{ldomain = LServer, domain = Server} = _To, disco_items(Acc, From, To, "", Lang) ->
"", Lang) -> LServer = exmpp_jid:ldomain_as_list(To),
Server = exmpp_jid:domain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -309,7 +313,8 @@ disco_items(Acc, From, #jid{ldomain = LServer, domain = Server} = _To,
end end
end; end;
disco_items(Acc, From, #jid{ldomain = LServer} = To, "announce", Lang) -> disco_items(Acc, From, To, "announce", Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -317,7 +322,8 @@ disco_items(Acc, From, #jid{ldomain = LServer} = To, "announce", Lang) ->
announce_items(Acc, From, To, Lang) announce_items(Acc, From, To, Lang)
end; end;
disco_items(Acc, From, #jid{ldomain = LServer} = _To, Node, _Lang) -> disco_items(Acc, From, To, Node, _Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -354,7 +360,9 @@ disco_items(Acc, From, #jid{ldomain = LServer} = _To, Node, _Lang) ->
%%------------------------------------------------------------------------- %%-------------------------------------------------------------------------
announce_items(Acc, From, #jid{ldomain = LServer, domain = Server} = _To, Lang) -> announce_items(Acc, From, To, Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
Server = exmpp_jid:domain_as_list(To),
Access1 = gen_mod:get_module_opt(LServer, ?MODULE, access, none), Access1 = gen_mod:get_module_opt(LServer, ?MODULE, access, none),
Nodes1 = case acl:match_rule(LServer, Access1, From) of Nodes1 = case acl:match_rule(LServer, Access1, From) of
allow -> allow ->
@ -399,8 +407,8 @@ commands_result(Allow, From, To, Request) ->
end. end.
announce_commands(Acc, From, #jid{ldomain = LServer} = To, announce_commands(Acc, From, To, #adhoc_request{ node = Node} = Request) ->
#adhoc_request{ node = Node} = Request) -> LServer = exmpp_jid:ldomain_as_list(To),
LNode = tokenize(Node), LNode = tokenize(Node),
F = fun() -> F = fun() ->
Access = gen_mod:get_module_opt(global, ?MODULE, access, none), Access = gen_mod:get_module_opt(global, ?MODULE, access, none),
@ -455,7 +463,7 @@ announce_commands(From, To,
#adhoc_response{status = canceled}); #adhoc_response{status = canceled});
XData == false, ActionIsExecute -> XData == false, ActionIsExecute ->
%% User requests form %% User requests form
Elements = generate_adhoc_form(Lang, Node, To#jid.ldomain), Elements = generate_adhoc_form(Lang, Node, exmpp_jid:ldomain_as_list(To)),
adhoc:produce_response( adhoc:produce_response(
Request, Request,
#adhoc_response{status = executing, #adhoc_response{status = executing,
@ -529,11 +537,12 @@ join_lines([], Acc) ->
%% Remove last newline %% Remove last newline
lists:flatten(lists:reverse(tl(Acc))). lists:flatten(lists:reverse(tl(Acc))).
handle_adhoc_form(From, #jid{ldomain = LServer} = To, handle_adhoc_form(From, To,
#adhoc_request{lang = Lang, #adhoc_request{lang = Lang,
node = Node, node = Node,
sessionid = SessionID}, sessionid = SessionID},
Fields) -> Fields) ->
LServer = exmpp_jid:ldomain_as_list(To),
Confirm = case lists:keysearch("confirm", 1, Fields) of Confirm = case lists:keysearch("confirm", 1, Fields) of
{value, {"confirm", ["true"]}} -> {value, {"confirm", ["true"]}} ->
true; true;
@ -654,14 +663,14 @@ get_title(Lang, ?NS_ADMIN_s ++ "#delete-motd-allhosts") ->
%%------------------------------------------------------------------------- %%-------------------------------------------------------------------------
announce_all(From, To, Packet) -> announce_all(From, To, Packet) ->
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none), Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
case acl:match_rule(Host, Access, From) of case acl:match_rule(Host, Access, From) of
deny -> deny ->
Err = exmpp_stanza:reply_with_error(Packet, 'forbidden'), Err = exmpp_stanza:reply_with_error(Packet, 'forbidden'),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
allow -> allow ->
Local = exmpp_jid:make_jid(To#jid.domain), Local = exmpp_jid:make_jid(exmpp_jid:domain(To)),
lists:foreach( lists:foreach(
fun({User, Server}) -> fun({User, Server}) ->
Dest = exmpp_jid:make_jid(User, Server), Dest = exmpp_jid:make_jid(User, Server),
@ -676,7 +685,7 @@ announce_all_hosts_all(From, To, Packet) ->
Err = exmpp_stanza:reply_with_error(Packet, 'forbidden'), Err = exmpp_stanza:reply_with_error(Packet, 'forbidden'),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
allow -> allow ->
Local = exmpp_jid:make_jid(To#jid.domain), Local = exmpp_jid:make_jid(exmpp_jid:domain(To)),
lists:foreach( lists:foreach(
fun({User, Server}) -> fun({User, Server}) ->
Dest = exmpp_jid:make_jid(User, Server), Dest = exmpp_jid:make_jid(User, Server),
@ -685,15 +694,15 @@ announce_all_hosts_all(From, To, Packet) ->
end. end.
announce_online(From, To, Packet) -> announce_online(From, To, Packet) ->
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none), Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
case acl:match_rule(Host, Access, From) of case acl:match_rule(Host, Access, From) of
deny -> deny ->
Err = exmpp_stanza:reply_with_error(Packet, 'forbidden'), Err = exmpp_stanza:reply_with_error(Packet, 'forbidden'),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
allow -> allow ->
announce_online1(ejabberd_sm:get_vh_session_list(Host), announce_online1(ejabberd_sm:get_vh_session_list(exmpp_jid:ldomain(To)),
To#jid.domain, exmpp_jid:domain_as_list(To),
Packet) Packet)
end. end.
@ -705,7 +714,7 @@ announce_all_hosts_online(From, To, Packet) ->
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
allow -> allow ->
announce_online1(ejabberd_sm:dirty_get_sessions_list(), announce_online1(ejabberd_sm:dirty_get_sessions_list(),
To#jid.domain, exmpp_jid:domain_as_list(To),
Packet) Packet)
end. end.
@ -718,7 +727,7 @@ announce_online1(Sessions, Server, Packet) ->
end, Sessions). end, Sessions).
announce_motd(From, To, Packet) -> announce_motd(From, To, Packet) ->
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none), Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
case acl:match_rule(Host, Access, From) of case acl:match_rule(Host, Access, From) of
deny -> deny ->
@ -741,7 +750,7 @@ announce_all_hosts_motd(From, To, Packet) ->
announce_motd(Host, Packet) -> announce_motd(Host, Packet) ->
announce_motd_update(Host, Packet), announce_motd_update(Host, Packet),
Sessions = ejabberd_sm:get_vh_session_list(Host), Sessions = ejabberd_sm:get_vh_session_list(list_to_binary(Host)),
announce_online1(Sessions, Host, Packet), announce_online1(Sessions, Host, Packet),
F = fun() -> F = fun() ->
lists:foreach( lists:foreach(
@ -752,7 +761,7 @@ announce_motd(Host, Packet) ->
mnesia:transaction(F). mnesia:transaction(F).
announce_motd_update(From, To, Packet) -> announce_motd_update(From, To, Packet) ->
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none), Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
case acl:match_rule(Host, Access, From) of case acl:match_rule(Host, Access, From) of
deny -> deny ->
@ -781,7 +790,7 @@ announce_motd_update(LServer, Packet) ->
mnesia:transaction(F). mnesia:transaction(F).
announce_motd_delete(From, To, Packet) -> announce_motd_delete(From, To, Packet) ->
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none), Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
case acl:match_rule(Host, Access, From) of case acl:match_rule(Host, Access, From) of
deny -> deny ->
@ -817,7 +826,9 @@ announce_motd_delete(LServer) ->
end, end,
mnesia:transaction(F). mnesia:transaction(F).
send_motd(#jid{lnode = LUser, ldomain = LServer} = JID) -> send_motd(JID) ->
LServer = exmpp_jid:ldomain_as_list(JID),
LUser = exmpp_jid:lnode_as_list(JID),
case catch mnesia:dirty_read({motd, LServer}) of case catch mnesia:dirty_read({motd, LServer}) of
[#motd{packet = Packet}] -> [#motd{packet = Packet}] ->
US = {LUser, LServer}, US = {LUser, LServer},
@ -825,7 +836,7 @@ send_motd(#jid{lnode = LUser, ldomain = LServer} = JID) ->
[#motd_users{}] -> [#motd_users{}] ->
ok; ok;
_ -> _ ->
Local = exmpp_jid:make_jid(LServer), Local = exmpp_jid:make_jid(exmpp_jid:ldomain(JID)),
ejabberd_router:route(Local, JID, Packet), ejabberd_router:route(Local, JID, Packet),
F = fun() -> F = fun() ->
mnesia:write(#motd_users{us = US}) mnesia:write(#motd_users{us = US})

View File

@ -87,7 +87,7 @@ read_caps([], Result) ->
%% get_caps reads user caps from database %% get_caps reads user caps from database
get_caps({U, S, R}) -> get_caps({U, S, R}) ->
BJID = exmpp_jlib:jid_to_binary(U, S, R), BJID = exmpp_jid:jid_to_binary(U, S, R),
case catch mnesia:dirty_read({user_caps, BJID}) of case catch mnesia:dirty_read({user_caps, BJID}) of
[#user_caps{caps=Caps}] -> [#user_caps{caps=Caps}] ->
Caps; Caps;
@ -97,8 +97,8 @@ get_caps({U, S, R}) ->
%% clear_caps removes user caps from database %% clear_caps removes user caps from database
clear_caps({U, S, R}) -> clear_caps({U, S, R}) ->
BJID = exmpp_jlib:jid_to_binary(U, S, R), BJID = exmpp_jid:jid_to_binary(U, S, R),
BUID = exmpp_jlib:jid_to_binary(U, S), BUID = exmpp_jid:jid_to_binary(U, S),
catch mnesia:dirty_delete({user_caps, BJID}), catch mnesia:dirty_delete({user_caps, BJID}),
case catch mnesia:dirty_read({user_caps_default, BUID}) of case catch mnesia:dirty_read({user_caps_default, BUID}) of
[#user_caps_default{resource=R}] -> [#user_caps_default{resource=R}] ->
@ -109,7 +109,7 @@ clear_caps({U, S, R}) ->
%% give default user resource %% give default user resource
get_user_resource(U, S) -> get_user_resource(U, S) ->
BUID = exmpp_jlib:bare_jid_to_binary(U, S), BUID = exmpp_jid:bare_jid_to_binary(U, S),
case catch mnesia:dirty_read({user_caps_default, BUID}) of case catch mnesia:dirty_read({user_caps_default, BUID}) of
[#user_caps_default{resource=R}] -> [#user_caps_default{resource=R}] ->
R; R;
@ -225,15 +225,18 @@ handle_cast({note_caps, From,
#state{host = Host, disco_requests = Requests} = State) -> #state{host = Host, disco_requests = Requests} = State) ->
%% XXX: this leads to race conditions where ejabberd will send %% XXX: this leads to race conditions where ejabberd will send
%% lots of caps disco requests. %% lots of caps disco requests.
#jid{node = U, domain = S, resource = R} = From, %#jid{node = U, domain = S, resource = R} = From,
BJID = exmpp_jlib:jid_to_binary(From), U = exmpp_jid:lnode(From),
S = exmpp_jid:ldomain(From),
R = exmpp_jid:resource(From),
BJID = exmpp_jid:jid_to_binary(From),
mnesia:dirty_write(#user_caps{jid = BJID, caps = Caps}), mnesia:dirty_write(#user_caps{jid = BJID, caps = Caps}),
case ejabberd_sm:get_user_resources(U, S) of case ejabberd_sm:get_user_resources(U, S) of
[] -> [] ->
ok; ok;
_ -> _ ->
% only store default resource of external contacts % only store default resource of external contacts
BUID = exmpp_jlib:bare_jid_to_binary(From), BUID = exmpp_jid:bare_jid_to_binary(From),
mnesia:dirty_write(#user_caps_default{uid = BUID, resource = R}) mnesia:dirty_write(#user_caps_default{uid = BUID, resource = R})
end, end,
SubNodes = [Version | Exts], SubNodes = [Version | Exts],
@ -340,7 +343,7 @@ handle_cast(visit_feature_queries, #state{feature_queries = FeatureQueries} = St
{noreply, State#state{feature_queries = NewFeatureQueries}}. {noreply, State#state{feature_queries = NewFeatureQueries}}.
handle_disco_response(From, To, IQ_Rec) -> handle_disco_response(From, To, IQ_Rec) ->
#jid{ldomain = Host} = To, Host = exmpp_jid:ldomain_as_list(To),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
gen_server:cast(Proc, {disco_response, From, To, IQ_Rec}). gen_server:cast(Proc, {disco_response, From, To, IQ_Rec}).

View File

@ -59,29 +59,31 @@
-define(NS_ADMIN_s, "http://jabber.org/protocol/admin"). -define(NS_ADMIN_s, "http://jabber.org/protocol/admin").
start(Host, _Opts) -> start(Host, _Opts) ->
ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_items, 50), HostB = list_to_binary(Host),
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 50), ejabberd_hooks:add(disco_local_items, HostB, ?MODULE, get_local_items, 50),
ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 50), ejabberd_hooks:add(disco_local_features, HostB, ?MODULE, get_local_features, 50),
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 50), ejabberd_hooks:add(disco_local_identity, HostB, ?MODULE, get_local_identity, 50),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_sm_items, HostB, ?MODULE, get_sm_items, 50),
ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 50), ejabberd_hooks:add(disco_sm_features, HostB, ?MODULE, get_sm_features, 50),
ejabberd_hooks:add(adhoc_local_items, Host, ?MODULE, adhoc_local_items, 50), ejabberd_hooks:add(disco_sm_identity, HostB, ?MODULE, get_sm_identity, 50),
ejabberd_hooks:add(adhoc_local_commands, Host, ?MODULE, adhoc_local_commands, 50), ejabberd_hooks:add(adhoc_local_items, HostB, ?MODULE, adhoc_local_items, 50),
ejabberd_hooks:add(adhoc_sm_items, Host, ?MODULE, adhoc_sm_items, 50), ejabberd_hooks:add(adhoc_local_commands, HostB, ?MODULE, adhoc_local_commands, 50),
ejabberd_hooks:add(adhoc_sm_commands, Host, ?MODULE, adhoc_sm_commands, 50), ejabberd_hooks:add(adhoc_sm_items, HostB, ?MODULE, adhoc_sm_items, 50),
ejabberd_hooks:add(adhoc_sm_commands, HostB, ?MODULE, adhoc_sm_commands, 50),
ok. ok.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(adhoc_sm_commands, Host, ?MODULE, adhoc_sm_commands, 50), HostB = list_to_binary(Host),
ejabberd_hooks:delete(adhoc_sm_items, Host, ?MODULE, adhoc_sm_items, 50), ejabberd_hooks:delete(adhoc_sm_commands, HostB, ?MODULE, adhoc_sm_commands, 50),
ejabberd_hooks:delete(adhoc_local_commands, Host, ?MODULE, adhoc_local_commands, 50), ejabberd_hooks:delete(adhoc_sm_items, HostB, ?MODULE, adhoc_sm_items, 50),
ejabberd_hooks:delete(adhoc_local_items, Host, ?MODULE, adhoc_local_items, 50), ejabberd_hooks:delete(adhoc_local_commands, HostB, ?MODULE, adhoc_local_commands, 50),
ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 50), ejabberd_hooks:delete(adhoc_local_items, HostB, ?MODULE, adhoc_local_items, 50),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:delete(disco_sm_identity, HostB, ?MODULE, get_sm_identity, 50),
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 50), ejabberd_hooks:delete(disco_sm_features, HostB, ?MODULE, get_sm_features, 50),
ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 50), ejabberd_hooks:delete(disco_sm_items, HostB, ?MODULE, get_sm_items, 50),
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 50), ejabberd_hooks:delete(disco_local_identity, HostB, ?MODULE, get_local_identity, 50),
ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_items, 50), ejabberd_hooks:delete(disco_local_features, HostB, ?MODULE, get_local_features, 50),
ejabberd_hooks:delete(disco_local_items, HostB, ?MODULE, get_local_items, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ADHOC), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ADHOC),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ADHOC). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ADHOC).
@ -181,7 +183,8 @@ get_local_identity(Acc, _From, _To, Node, Lang) ->
{result, Feats} {result, Feats}
end). end).
get_sm_features(Acc, From, #jid{ldomain = LServer} = _To, Node, _Lang) -> get_sm_features(Acc, From, To, Node, _Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -195,7 +198,8 @@ get_sm_features(Acc, From, #jid{ldomain = LServer} = _To, Node, _Lang) ->
end end
end. end.
get_local_features(Acc, From, #jid{ldomain = LServer} = _To, Node, _Lang) -> get_local_features(Acc, From, To, Node, _Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -250,7 +254,8 @@ get_local_features(Acc, From, #jid{ldomain = LServer} = _To, Node, _Lang) ->
%%%----------------------------------------------------------------------- %%%-----------------------------------------------------------------------
adhoc_sm_items(Acc, From, #jid{ldomain = LServer} = To, Lang) -> adhoc_sm_items(Acc, From, To, Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
case acl:match_rule(LServer, configure, From) of case acl:match_rule(LServer, configure, From) of
allow -> allow ->
Items = case Acc of Items = case Acc of
@ -268,9 +273,8 @@ adhoc_sm_items(Acc, From, #jid{ldomain = LServer} = To, Lang) ->
%%%----------------------------------------------------------------------- %%%-----------------------------------------------------------------------
get_sm_items(Acc, From, get_sm_items(Acc, From, To, Node, Lang) ->
#jid{node = User, domain = Server, ldomain = LServer} = To, LServer = exmpp_jid:ldomain_as_list(To),
Node, Lang) ->
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -283,7 +287,7 @@ get_sm_items(Acc, From,
{allow, ""} -> {allow, ""} ->
Nodes = [?NODEJID(To, "Configuration", "config"), Nodes = [?NODEJID(To, "Configuration", "config"),
?NODEJID(To, "User Management", "user")], ?NODEJID(To, "User Management", "user")],
{result, Items ++ Nodes ++ get_user_resources(User, Server)}; {result, Items ++ Nodes ++ get_user_resources(To)};
{allow, "config"} -> {allow, "config"} ->
{result, []}; {result, []};
{_, "config"} -> {_, "config"} ->
@ -293,18 +297,23 @@ get_sm_items(Acc, From,
end end
end. end.
get_user_resources(User, Server) -> get_user_resources(BareJID) ->
Rs = ejabberd_sm:get_user_resources(User, Server), Rs = ejabberd_sm:get_user_resources(exmpp_jid:lnode(BareJID),
exmpp_jid:ldomain(BareJID)),
lists:map(fun(R) -> lists:map(fun(R) ->
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs =
[#xmlattr{name = 'jid', value = exmpp_jid:jid_to_list(User, Server, R)}, [#xmlattr{name = 'jid',
#xmlattr{name = 'name', value = User}]} value = exmpp_jid:jid_to_list(
exmpp_jid:bare_jid_to_jid(BareJID, R))},
#xmlattr{name = 'name',
value = exmpp_jid:lnode_as_list(BareJID)}]}
end, lists:sort(Rs)). end, lists:sort(Rs)).
%%%----------------------------------------------------------------------- %%%-----------------------------------------------------------------------
adhoc_local_items(Acc, From, #jid{ldomain = LServer, domain = Server} = To, adhoc_local_items(Acc, From, To, Lang) ->
Lang) -> LServer = exmpp_jid:ldomain_as_list(To),
Server = exmpp_jid:domain_as_list(To),
case acl:match_rule(LServer, configure, From) of case acl:match_rule(LServer, configure, From) of
allow -> allow ->
Items = case Acc of Items = case Acc of
@ -373,7 +382,8 @@ recursively_get_local_items(LServer, Node, Server, Lang) ->
end end
end). end).
get_local_items(Acc, From, #jid{ldomain = LServer} = To, "", Lang) -> get_local_items(Acc, From, To, "", Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -397,7 +407,8 @@ get_local_items(Acc, From, #jid{ldomain = LServer} = To, "", Lang) ->
end end
end; end;
get_local_items(Acc, From, #jid{ldomain = LServer} = To, Node, Lang) -> get_local_items(Acc, From, To, Node, Lang) ->
LServer = exmpp_jid:ldomain_as_list(To),
case gen_mod:is_loaded(LServer, mod_adhoc) of case gen_mod:is_loaded(LServer, mod_adhoc) of
false -> false ->
Acc; Acc;
@ -584,7 +595,7 @@ get_local_items(_Host, _, _Server, _Lang) ->
get_online_vh_users(Host) -> get_online_vh_users(Host) ->
case catch ejabberd_sm:get_vh_session_list(Host) of case catch ejabberd_sm:get_vh_session_list(list_to_binary(Host)) of
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
[]; [];
USRs -> USRs ->
@ -716,8 +727,8 @@ get_stopped_nodes(_Lang) ->
adhoc_local_commands(From, To, Request) adhoc_local_commands(From, To, Request)
end). end).
adhoc_local_commands(Acc, From, #jid{ldomain = LServer} = To, adhoc_local_commands(Acc, From, To, #adhoc_request{node = Node} = Request) ->
#adhoc_request{node = Node} = Request) -> LServer = exmpp_jid:ldomain_as_list(To),
LNode = tokenize(Node), LNode = tokenize(Node),
Allow = acl:match_rule(LServer, configure, From), Allow = acl:match_rule(LServer, configure, From),
case LNode of case LNode of
@ -741,12 +752,13 @@ adhoc_local_commands(Acc, From, #jid{ldomain = LServer} = To,
Acc Acc
end. end.
adhoc_local_commands(From, #jid{ldomain = LServer} = _To, adhoc_local_commands(From, To,
#adhoc_request{lang = Lang, #adhoc_request{lang = Lang,
node = Node, node = Node,
sessionid = SessionID, sessionid = SessionID,
action = Action, action = Action,
xdata = XData} = Request) -> xdata = XData} = Request) ->
LServer = exmpp_jid:ldomain_as_list(To),
LNode = tokenize(Node), LNode = tokenize(Node),
%% If the "action" attribute is not present, it is %% If the "action" attribute is not present, it is
%% understood as "execute". If there was no <actions/> %% understood as "execute". If there was no <actions/>
@ -1247,7 +1259,7 @@ get_form(Host, ?NS_ADMINL("get-registered-users-num"), Lang) ->
}]}]}; }]}]};
get_form(Host, ?NS_ADMINL("get-online-users-num"), Lang) -> get_form(Host, ?NS_ADMINL("get-online-users-num"), Lang) ->
Num = io_lib:format("~p", [length(ejabberd_sm:get_vh_session_list(Host))]), Num = io_lib:format("~p", [length(ejabberd_sm:get_vh_session_list(list_to_binary(Host)))]),
{result, completed, {result, completed,
[#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children = [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children =
[?HFIELD(), [?HFIELD(),
@ -1535,8 +1547,8 @@ set_form(_From, _Host, ?NS_ADMINL("add-user"), _Lang, XData) ->
Password = get_value("password", XData), Password = get_value("password", XData),
Password = get_value("password-verify", XData), Password = get_value("password-verify", XData),
AccountJID = exmpp_jid:list_to_jid(AccountString), AccountJID = exmpp_jid:list_to_jid(AccountString),
User = AccountJID#jid.lnode, User = exmpp_jid:lnode_as_list(AccountJID),
Server = AccountJID#jid.ldomain, Server = exmpp_jid:ldomain_as_list(AccountJID),
true = lists:member(Server, ?MYHOSTS), true = lists:member(Server, ?MYHOSTS),
ejabberd_auth:try_register(User, Server, Password), ejabberd_auth:try_register(User, Server, Password),
{result, []}; {result, []};
@ -1547,9 +1559,8 @@ set_form(_From, _Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
ASL2 = lists:map( ASL2 = lists:map(
fun(AccountString) -> fun(AccountString) ->
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
[_|_] = JID#jid.lnode, User = [_|_] = exmpp_jid:lnode_as_list(JID),
User = JID#jid.lnode, Server = exmpp_jid:ldomain_as_list(JID),
Server = JID#jid.ldomain,
true = ejabberd_auth:is_user_exists(User, Server), true = ejabberd_auth:is_user_exists(User, Server),
{User, Server} {User, Server}
end, end,
@ -1560,11 +1571,10 @@ set_form(_From, _Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
set_form(_From, _Host, ?NS_ADMINL("end-user-session"), _Lang, XData) -> set_form(_From, _Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
[_|_] = JID#jid.lnode, LUser = [_|_] = exmpp_jid:lnode_as_list(JID),
LUser = JID#jid.lnode, LServer = exmpp_jid:ldomain_as_list(JID),
LServer = JID#jid.ldomain,
%% Code copied from ejabberd_sm.erl %% Code copied from ejabberd_sm.erl
case JID#jid.lresource of case exmpp_jid:lresource_as_list(JID) of
undefined -> undefined ->
SIDs = mnesia:dirty_select(session, SIDs = mnesia:dirty_select(session,
[{#session{sid = '$1', usr = {LUser, LServer, '_'}, _ = '_'}, [], ['$1']}]), [{#session{sid = '$1', usr = {LUser, LServer, '_'}, _ = '_'}, [], ['$1']}]),
@ -1579,9 +1589,8 @@ set_form(_From, _Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
set_form(_From, _Host, ?NS_ADMINL("get-user-password"), Lang, XData) -> set_form(_From, _Host, ?NS_ADMINL("get-user-password"), Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
[_|_] = JID#jid.lnode, User = [_|_] = exmpp_jid:lnode_as_list(JID),
User = JID#jid.lnode, Server = exmpp_jid:ldomain_as_list(JID),
Server = JID#jid.ldomain,
Password = ejabberd_auth:get_password(User, Server), Password = ejabberd_auth:get_password(User, Server),
true = is_list(Password), true = is_list(Password),
{result, [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children = {result, [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children =
@ -1594,9 +1603,8 @@ set_form(_From, _Host, ?NS_ADMINL("change-user-password"), _Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
Password = get_value("password", XData), Password = get_value("password", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
[_|_] = JID#jid.lnode, User = [_|_] = exmpp_jid:lnode_as_list(JID),
User = JID#jid.lnode, Server = exmpp_jid:ldomain_as_list(JID),
Server = JID#jid.ldomain,
true = ejabberd_auth:is_user_exists(User, Server), true = ejabberd_auth:is_user_exists(User, Server),
ejabberd_auth:set_password(User, Server, Password), ejabberd_auth:set_password(User, Server, Password),
{result, []}; {result, []};
@ -1604,14 +1612,14 @@ set_form(_From, _Host, ?NS_ADMINL("change-user-password"), _Lang, XData) ->
set_form(_From, _Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) -> set_form(_From, _Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
[_|_] = JID#jid.lnode, User = [_|_] = exmpp_jid:lnode_as_list(JID),
User = JID#jid.lnode, Server = exmpp_jid:ldomain_as_list(JID),
Server = JID#jid.ldomain,
%% Code copied from web/ejabberd_web_admin.erl %% Code copied from web/ejabberd_web_admin.erl
%% TODO: Update time format to XEP-0202: Entity Time %% TODO: Update time format to XEP-0202: Entity Time
FLast = FLast =
case ejabberd_sm:get_user_resources(User, Server) of case ejabberd_sm:get_user_resources(exmpp_jid:lnode(User),
exmpp_jid:ldomain(Server)) of
[] -> [] ->
_US = {User, Server}, _US = {User, Server},
case get_last_info(User, Server) of case get_last_info(User, Server) of
@ -1641,15 +1649,19 @@ set_form(_From, _Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) ->
set_form(_From, _Host, ?NS_ADMINL("user-stats"), Lang, XData) -> set_form(_From, _Host, ?NS_ADMINL("user-stats"), Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
[_|_] = JID#jid.lnode, User = [_|_] = exmpp_jid:lnode_as_list(JID),
User = JID#jid.lnode, Server = exmpp_jid:ldomain_as_list(JID),
Server = JID#jid.ldomain,
Resources = ejabberd_sm:get_user_resources(User, Server), Resources = ejabberd_sm:get_user_resources(exmpp_jid:lnode(JID),
IPs1 = [ejabberd_sm:get_user_ip(User, Server, Resource) || Resource <- Resources], exmpp_jid:ldomain(JID)),
IPs1 = [ejabberd_sm:get_user_ip(exmpp_jid:bare_jid_to_jid(JID,Resource))
|| Resource <- Resources],
IPs = [inet_parse:ntoa(IP)++":"++integer_to_list(Port) || {IP, Port} <- IPs1], IPs = [inet_parse:ntoa(IP)++":"++integer_to_list(Port) || {IP, Port} <- IPs1],
Items = ejabberd_hooks:run_fold(roster_get, Server, [], [{User, Server}]), Items = ejabberd_hooks:run_fold(roster_get,
exmpp_jid:ldomain(JID),
[],
[{list_to_binary(User), list_to_binary(Server)}]),
Rostersize = integer_to_list(erlang:length(Items)), Rostersize = integer_to_list(erlang:length(Items)),
{result, [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children = {result, [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children =
@ -1729,12 +1741,14 @@ get_last_info(User, Server) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
adhoc_sm_commands(_Acc, From, adhoc_sm_commands(_Acc, From, To,
#jid{node = User, domain = Server, ldomain = LServer} = _To,
#adhoc_request{lang = Lang, #adhoc_request{lang = Lang,
node = "config", node = "config",
action = Action, action = Action,
xdata = XData} = Request) -> xdata = XData} = Request) ->
User = exmpp_jid:node_as_list(To),
Server = exmpp_jid:domain_as_list(To),
LServer = exmpp_jid:ldomain_as_list(To),
case acl:match_rule(LServer, configure, From) of case acl:match_rule(LServer, configure, From) of
deny -> deny ->
{error, 'forbidden'}; {error, 'forbidden'};

View File

@ -71,7 +71,7 @@ stop(Host) ->
process_local_iq(From, To, #iq{type = Type, payload = Request} = IQ_Rec) -> process_local_iq(From, To, #iq{type = Type, payload = Request} = IQ_Rec) ->
case acl:match_rule(To#jid.ldomain, configure, From) of case acl:match_rule(exmpp_jid:ldomain_as_list(To), configure, From) of
deny -> deny ->
exmpp_iq:error(IQ_Rec, 'not-allowed'); exmpp_iq:error(IQ_Rec, 'not-allowed');
allow -> allow ->

View File

@ -54,6 +54,7 @@
-record(disco_publish, {owner_node, jid, name, node}). -record(disco_publish, {owner_node, jid, name, node}).
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
mnesia:create_table(disco_publish, mnesia:create_table(disco_publish,
[{disc_only_copies, [node()]}, [{disc_only_copies, [node()]},
{attributes, record_info(fields, disco_publish)}, {attributes, record_info(fields, disco_publish)},
@ -84,23 +85,24 @@ start(Host, Opts) ->
ExtraDomains), ExtraDomains),
catch ets:new(disco_sm_features, [named_table, ordered_set, public]), catch ets:new(disco_sm_features, [named_table, ordered_set, public]),
catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]), catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]),
ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_services, 100), ejabberd_hooks:add(disco_local_items, HostB, ?MODULE, get_local_services, 100),
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 100), ejabberd_hooks:add(disco_local_features, HostB, ?MODULE, get_local_features, 100),
ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 100), ejabberd_hooks:add(disco_local_identity, HostB, ?MODULE, get_local_identity, 100),
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 100), ejabberd_hooks:add(disco_sm_items, HostB, ?MODULE, get_sm_items, 100),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 100), ejabberd_hooks:add(disco_sm_features, HostB, ?MODULE, get_sm_features, 100),
ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100), ejabberd_hooks:add(disco_sm_identity, HostB, ?MODULE, get_sm_identity, 100),
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_publish_items, 75), ejabberd_hooks:add(disco_sm_items, HostB, ?MODULE, get_publish_items, 75),
ok. ok.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_publish_items, 75), HostB = list_to_binary(Host),
ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100), ejabberd_hooks:delete(disco_sm_items, HostB, ?MODULE, get_publish_items, 75),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 100), ejabberd_hooks:delete(disco_sm_identity, HostB, ?MODULE, get_sm_identity, 100),
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 100), ejabberd_hooks:delete(disco_sm_features, HostB, ?MODULE, get_sm_features, 100),
ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 100), ejabberd_hooks:delete(disco_sm_items, HostB, ?MODULE, get_sm_items, 100),
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 100), ejabberd_hooks:delete(disco_local_identity, HostB, ?MODULE, get_local_identity, 100),
ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_services, 100), ejabberd_hooks:delete(disco_local_features, HostB, ?MODULE, get_local_features, 100),
ejabberd_hooks:delete(disco_local_items, HostB, ?MODULE, get_local_services, 100),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS),
@ -128,11 +130,10 @@ unregister_extra_domain(Host, Domain) ->
process_local_iq_items(From, To, #iq{type = get, payload = SubEl, process_local_iq_items(From, To, #iq{type = get, payload = SubEl,
lang = Lang} = IQ_Rec) -> lang = Lang} = IQ_Rec) ->
Host = To#jid.ldomain,
Node = exmpp_xml:get_attribute(SubEl, 'node', ""), Node = exmpp_xml:get_attribute(SubEl, 'node', ""),
case ejabberd_hooks:run_fold(disco_local_items, case ejabberd_hooks:run_fold(disco_local_items,
Host, exmpp_jid:ldomain(To),
empty, empty,
[From, To, Node, Lang]) of [From, To, Node, Lang]) of
{result, Items} -> {result, Items} ->
@ -152,14 +153,13 @@ process_local_iq_items(_From, _To, #iq{type = set} = IQ_Rec) ->
process_local_iq_info(From, To, #iq{type = get, payload = SubEl, process_local_iq_info(From, To, #iq{type = get, payload = SubEl,
lang = Lang} = IQ_Rec) -> lang = Lang} = IQ_Rec) ->
Host = To#jid.ldomain,
Node = exmpp_xml:get_attribute(SubEl, 'node', ""), Node = exmpp_xml:get_attribute(SubEl, 'node', ""),
Identity = ejabberd_hooks:run_fold(disco_local_identity, Identity = ejabberd_hooks:run_fold(disco_local_identity,
Host, exmpp_jid:ldomain(To),
[], [],
[From, To, Node, Lang]), [From, To, Node, Lang]),
case ejabberd_hooks:run_fold(disco_local_features, case ejabberd_hooks:run_fold(disco_local_features,
Host, exmpp_jid:ldomain(To),
empty, empty,
[From, To, Node, Lang]) of [From, To, Node, Lang]) of
{result, Features} -> {result, Features} ->
@ -196,7 +196,7 @@ get_local_features(Acc, _From, To, [], _Lang) ->
{result, Features} -> Features; {result, Features} -> Features;
empty -> [] empty -> []
end, end,
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
{result, {result,
ets:select(disco_features, [{{{'_', Host}}, [], ['$_']}]) ++ Feats}; ets:select(disco_features, [{{{'_', Host}}, [], ['$_']}]) ++ Feats};
@ -237,7 +237,7 @@ get_local_services(Acc, _From, To, [], _Lang) ->
{result, Its} -> Its; {result, Its} -> Its;
empty -> [] empty -> []
end, end,
Host = To#jid.ldomain, Host = exmpp_jid:ldomain_as_list(To),
{result, {result,
lists:usort( lists:usort(
lists:map(fun domain_to_xml/1, lists:map(fun domain_to_xml/1,
@ -270,10 +270,9 @@ get_vh_services(Host) ->
process_sm_iq_items(From, To, #iq{type = get, payload = SubEl, process_sm_iq_items(From, To, #iq{type = get, payload = SubEl,
lang = Lang} = IQ_Rec) -> lang = Lang} = IQ_Rec) ->
Host = To#jid.ldomain,
Node = exmpp_xml:get_attribute(SubEl, 'node', ""), Node = exmpp_xml:get_attribute(SubEl, 'node', ""),
case ejabberd_hooks:run_fold(disco_sm_items, case ejabberd_hooks:run_fold(disco_sm_items,
Host, exmpp_jid:ldomain(To),
empty, empty,
[From, To, Node, Lang]) of [From, To, Node, Lang]) of
{result, Items} -> {result, Items} ->
@ -288,8 +287,10 @@ process_sm_iq_items(From, To, #iq{type = get, payload = SubEl,
exmpp_iq:error(IQ_Rec, Error) exmpp_iq:error(IQ_Rec, Error)
end; end;
process_sm_iq_items(From, To, #iq{type = set, payload = SubEl} = IQ_Rec) -> process_sm_iq_items(From, To, #iq{type = set, payload = SubEl} = IQ_Rec) ->
#jid{lnode = LTo, ldomain = ToServer} = To, LTo = exmpp_jid:lnode_as_list(To),
#jid{lnode = LFrom, ldomain = LServer} = From, ToServer = exmpp_jid:ldomain_as_list(To),
LFrom = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
Self = (LTo == LFrom) andalso (ToServer == LServer), Self = (LTo == LFrom) andalso (ToServer == LServer),
Node = exmpp_xml:get_attribute(SubEl, 'node', ""), Node = exmpp_xml:get_attribute(SubEl, 'node', ""),
if if
@ -310,16 +311,18 @@ process_sm_iq_items(From, To, #iq{type = set, payload = SubEl} = IQ_Rec) ->
get_sm_items({error, _Error} = Acc, _From, _To, _Node, _Lang) -> get_sm_items({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
Acc; Acc;
get_sm_items(Acc, get_sm_items(Acc, From, To, [], _Lang) ->
#jid{lnode = LFrom, ldomain = LSFrom}, LFrom = exmpp_jid:lnode_as_list(From),
#jid{node = User, domain = Server, lnode = LTo, ldomain = LSTo} = _To, LSFrom = exmpp_jid:ldomain_as_list(From),
[], _Lang) -> LTo = exmpp_jid:lnode_as_list(To),
LSTo = exmpp_jid:ldomain_as_list(To),
Items = case Acc of Items = case Acc of
{result, Its} -> Its; {result, Its} -> Its;
empty -> [] empty -> []
end, end,
Items1 = case {LFrom, LSFrom} of Items1 = case {LFrom, LSFrom} of
{LTo, LSTo} -> get_user_resources(User, Server); {LTo, LSTo} -> get_user_resources(To);
_ -> [] _ -> []
end, end,
{result, Items ++ Items1}; {result, Items ++ Items1};
@ -328,8 +331,10 @@ get_sm_items({result, _} = Acc, _From, _To, _Node, _Lang) ->
Acc; Acc;
get_sm_items(empty, From, To, _Node, _Lang) -> get_sm_items(empty, From, To, _Node, _Lang) ->
#jid{lnode = LFrom, ldomain = LSFrom} = From, LFrom = exmpp_jid:lnode_as_list(From),
#jid{lnode = LTo, ldomain = LSTo} = To, LSFrom = exmpp_jid:ldomain_as_list(From),
LTo = exmpp_jid:lnode_as_list(To),
LSTo = exmpp_jid:ldomain_as_list(To),
case {LFrom, LSFrom} of case {LFrom, LSFrom} of
{LTo, LSTo} -> {LTo, LSTo} ->
{error, 'item-not-found'}; {error, 'item-not-found'};
@ -339,14 +344,13 @@ get_sm_items(empty, From, To, _Node, _Lang) ->
process_sm_iq_info(From, To, #iq{type = get, payload = SubEl, process_sm_iq_info(From, To, #iq{type = get, payload = SubEl,
lang = Lang} = IQ_Rec) -> lang = Lang} = IQ_Rec) ->
Host = To#jid.ldomain,
Node = exmpp_xml:get_attribute(SubEl, 'node', ""), Node = exmpp_xml:get_attribute(SubEl, 'node', ""),
Identity = ejabberd_hooks:run_fold(disco_sm_identity, Identity = ejabberd_hooks:run_fold(disco_sm_identity,
Host, exmpp_jid:ldomain(To),
[], [],
[From, To, Node, Lang]), [From, To, Node, Lang]),
case ejabberd_hooks:run_fold(disco_sm_features, case ejabberd_hooks:run_fold(disco_sm_features,
Host, exmpp_jid:ldomain(To),
empty, empty,
[From, To, Node, Lang]) of [From, To, Node, Lang]) of
{result, Features} -> {result, Features} ->
@ -369,8 +373,10 @@ get_sm_identity(Acc, _From, _To, _Node, _Lang) ->
Acc. Acc.
get_sm_features(empty, From, To, _Node, _Lang) -> get_sm_features(empty, From, To, _Node, _Lang) ->
#jid{lnode = LFrom, ldomain = LSFrom} = From, LFrom = exmpp_jid:lnode_as_list(From),
#jid{lnode = LTo, ldomain = LSTo} = To, LSFrom = exmpp_jid:ldomain_as_list(From),
LTo = exmpp_jid:lnode_as_list(To),
LSTo = exmpp_jid:ldomain_as_list(To),
case {LFrom, LSFrom} of case {LFrom, LSFrom} of
{LTo, LSTo} -> {LTo, LSTo} ->
{error, 'item-not-found'}; {error, 'item-not-found'};
@ -383,21 +389,23 @@ get_sm_features(Acc, _From, _To, _Node, _Lang) ->
get_user_resources(User, Server) -> get_user_resources(JID) ->
Rs = ejabberd_sm:get_user_resources(User, Server), Rs = ejabberd_sm:get_user_resources(exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID)),
lists:map(fun(R) -> lists:map(fun(R) ->
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [ #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [
#xmlattr{name = 'jid', value = #xmlattr{name = 'jid', value =
exmpp_jid:jid_to_list(User, Server, R)}, exmpp_jid:jid_to_list(exmpp_jid:bare_jid_to_jid(JID, R))},
#xmlattr{name = 'name', value = User} #xmlattr{name = 'name', value = exmpp_jid:lnode_as_list(JID)}
]} ]}
end, lists:sort(Rs)). end, lists:sort(Rs)).
get_publish_items(empty, get_publish_items(empty, From, To, Node, _Lang) ->
#jid{lnode = LFrom, ldomain = LSFrom}, LFrom = exmpp_jid:lnode_as_list(From),
#jid{lnode = LTo, ldomain = LSTo} = _To, LSFrom = exmpp_jid:ldomain_as_list(From),
Node, _Lang) -> LTo = exmpp_jid:lnode_as_list(To),
LSTo = exmpp_jid:ldomain_as_list(To),
if if
(LFrom == LTo) and (LSFrom == LSTo) -> (LFrom == LTo) and (LSFrom == LSTo) ->
retrieve_disco_publish({LTo, LSTo}, Node); retrieve_disco_publish({LTo, LSTo}, Node);

View File

@ -118,7 +118,7 @@ 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.node of Packet2 = case exmpp_jid:node(From) of
undefined -> exmpp_stanza:reply_with_error(Packet, 'bad-request'); undefined -> exmpp_stanza:reply_with_error(Packet, 'bad-request');
_ -> Packet _ -> Packet
end, end,
@ -174,8 +174,7 @@ do_client_version(disabled, _From, _To) ->
do_client_version(enabled, From, To) -> do_client_version(enabled, From, 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 = exmpp_jid:bare_jid_to_jid(From,Random_resource),
lresource = Random_resource},
%% Build an iq:query request %% Build an iq:query request
Request = #xmlel{ns = ?NS_SOFT_VERSION, name = 'query'}, Request = #xmlel{ns = ?NS_SOFT_VERSION, name = 'query'},

View File

@ -204,7 +204,8 @@ do_route(Host, ServerHost, Access, From, To, Packet, DefEnc) ->
end. end.
do_route1(Host, ServerHost, From, To, Packet, DefEnc) -> do_route1(Host, ServerHost, From, To, Packet, DefEnc) ->
#jid{node = ChanServ, resource = Resource} = To, ChanServ = exmpp_jid:node_as_list(To),
Resource = exmpp_jid:resource_as_list(To),
case ChanServ of case ChanServ of
undefined -> undefined ->
case Resource of case Resource of
@ -400,8 +401,10 @@ process_irc_register(Host, From, _To, _DefEnc,
get_form(Host, From, [], Lang, DefEnc) -> get_form(Host, From, [], Lang, DefEnc) ->
#jid{node = User, domain = Server, User = exmpp_jid:node_as_list(From),
lnode = LUser, ldomain = LServer} = From, Server = exmpp_jid:domain_as_list(From),
LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
US = {LUser, LServer}, US = {LUser, LServer},
Customs = Customs =
case catch mnesia:dirty_read({irc_custom, {US, Host}}) of case catch mnesia:dirty_read({irc_custom, {US, Host}}) of
@ -485,7 +488,8 @@ get_form(_Host, _, _, _Lang, _) ->
set_form(Host, From, [], _Lang, XData) -> set_form(Host, From, [], _Lang, XData) ->
{LUser, LServer, _} = jlib:short_prepd_jid(From), LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
US = {LUser, LServer}, US = {LUser, LServer},
case {lists:keysearch("username", 1, XData), case {lists:keysearch("username", 1, XData),
lists:keysearch("encodings", 1, XData)} of lists:keysearch("encodings", 1, XData)} of
@ -529,8 +533,9 @@ set_form(_Host, _, _, _Lang, _XData) ->
get_user_and_encoding(Host, From, IRCServer, DefEnc) -> get_user_and_encoding(Host, From, IRCServer, DefEnc) ->
#jid{node = User, domain = _Server, User = exmpp_jid:node_as_list(From),
lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
US = {LUser, LServer}, US = {LUser, LServer},
case catch mnesia:dirty_read({irc_custom, {US, Host}}) of case catch mnesia:dirty_read({irc_custom, {US, Host}}) of
{'EXIT', _Reason} -> {'EXIT', _Reason} ->

View File

@ -47,6 +47,7 @@
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
mnesia:create_table(last_activity, mnesia:create_table(last_activity,
[{disc_copies, [node()]}, [{disc_copies, [node()]},
@ -56,15 +57,16 @@ start(Host, Opts) ->
?MODULE, process_local_iq, IQDisc), ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(unset_presence_hook, Host, ejabberd_hooks:add(unset_presence_hook, HostB,
?MODULE, on_presence_update, 50). ?MODULE, on_presence_update, 50).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(unset_presence_hook, Host, ejabberd_hooks:delete(unset_presence_hook, HostB,
?MODULE, on_presence_update, 50), ?MODULE, on_presence_update, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY).
@ -79,27 +81,25 @@ process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) ->
process_sm_iq(From, To, #iq{type = get} = IQ_Rec) -> process_sm_iq(From, To, #iq{type = get} = IQ_Rec) ->
User = To#jid.lnode,
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, exmpp_jid:ldomain(To),
{none, []}, [User, Server, From]), {none, []}, [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), From]),
if if
(Subscription == both) or (Subscription == from) -> (Subscription == both) or (Subscription == from) ->
UserListRecord = ejabberd_hooks:run_fold( UserListRecord = ejabberd_hooks:run_fold(
privacy_get_user_list, Server, privacy_get_user_list, exmpp_jid:ldomain(To),
#userlist{}, #userlist{},
[User, Server]), [exmpp_jid:lnode(To), exmpp_jid:ldomain(To)]),
case ejabberd_hooks:run_fold( case ejabberd_hooks:run_fold(
privacy_check_packet, Server, privacy_check_packet, exmpp_jid:ldomain(To),
allow, allow,
[User, Server, UserListRecord, [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), UserListRecord,
{From, To, {From, To,
exmpp_presence:available()}, exmpp_presence:available()},
out]) of out]) of
allow -> allow ->
get_last(IQ_Rec, User, Server); get_last(IQ_Rec, exmpp_jid:lnode(To), exmpp_jid:ldomain(To));
deny -> deny ->
exmpp_iq:error(IQ_Rec, 'not-allowed') exmpp_iq:error(IQ_Rec, 'not-allowed')
end; end;
@ -133,11 +133,10 @@ on_presence_update(User, Server, _Resource, Status) ->
TimeStamp = MegaSecs * 1000000 + Secs, TimeStamp = MegaSecs * 1000000 + Secs,
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)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), US = {User, Server},
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() -> F = fun() ->
mnesia:write(#last_activity{us = US, mnesia:write(#last_activity{us = US,
timestamp = TimeStamp, timestamp = TimeStamp,
@ -150,7 +149,7 @@ store_last_info(User, Server, TimeStamp, Status) ->
end. end.
%% Returns: {ok, Timestamp, Status} | not_found %% Returns: {ok, Timestamp, Status} | not_found
get_last_info(LUser, LServer) -> get_last_info(LUser, LServer) when is_binary(LUser), is_binary(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} ->
not_found; not_found;
@ -160,7 +159,7 @@ get_last_info(LUser, LServer) ->
{ok, TimeStamp, Status} {ok, TimeStamp, Status}
end. end.
remove_user(User, Server) -> remove_user(User, Server) when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
@ -250,7 +249,8 @@ convert_to_exmpp2(#last_activity{us = {U, S} = Key, status = Status} = LA,
% Convert status. % Convert status.
Status1 = list_to_binary(Status), Status1 = list_to_binary(Status),
% Prepare the new record. % Prepare the new record.
New_LA = LA#last_activity{us = {U1, S}, status = Status1}, New_LA = LA#last_activity{us = {list_to_binary(U1), list_to_binary(S)},
status = Status1},
% Write the new record. % Write the new record.
mnesia:write(New_LA), mnesia:write(New_LA),
Acc. Acc.

View File

@ -44,20 +44,22 @@
-include("mod_privacy.hrl"). -include("mod_privacy.hrl").
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
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_ACTIVITY, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY,
?MODULE, process_local_iq, IQDisc), ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(unset_presence_hook, Host, ejabberd_hooks:add(unset_presence_hook, HostB,
?MODULE, on_presence_update, 50). ?MODULE, on_presence_update, 50).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(unset_presence_hook, Host, ejabberd_hooks:delete(unset_presence_hook, HostB,
?MODULE, on_presence_update, 50), ?MODULE, on_presence_update, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY).
@ -71,22 +73,22 @@ process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) ->
exmpp_iq:error(IQ_Rec, 'not-allowed'). exmpp_iq:error(IQ_Rec, 'not-allowed').
process_sm_iq(From, To, #iq{type = get} = IQ_Rec) -> process_sm_iq(From, To, #iq{type = get} = IQ_Rec) ->
User = To#jid.lnode, User = exmpp_jid:lnode_as_list(To),
Server = To#jid.ldomain, Server = exmpp_jid:ldomain_as_list(To),
{Subscription, _Groups} = {Subscription, _Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, Server, roster_get_jid_info, exmpp_jid:ldomain(To),
{none, []}, [User, Server, From]), {none, []}, [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), From]),
if if
(Subscription == both) or (Subscription == from) -> (Subscription == both) or (Subscription == from) ->
UserListRecord = ejabberd_hooks:run_fold( UserListRecord = ejabberd_hooks:run_fold(
privacy_get_user_list, Server, privacy_get_user_list, exmpp_jid:ldomain(To),
#userlist{}, #userlist{},
[User, Server]), [exmpp_jid:lnode(To), exmpp_jid:ldomain(To)]),
case ejabberd_hooks:run_fold( case ejabberd_hooks:run_fold(
privacy_check_packet, Server, privacy_check_packet, exmpp_jid:ldomain(To),
allow, allow,
[User, Server, UserListRecord, [exmpp_jid:lnode(To), exmpp_jid:ldomain(To), UserListRecord,
{From, To, {From, To,
exmpp_presence:available()}, exmpp_presence:available()},
out]) of out]) of
@ -129,13 +131,17 @@ on_presence_update(User, Server, _Resource, Status) ->
TimeStamp = MegaSecs * 1000000 + Secs, TimeStamp = MegaSecs * 1000000 + Secs,
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)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), %LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), %LServer = exmpp_stringprep:nameprep(Server),
LUser = binary_to_list(User),
LServer = binary_to_list(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(binary_to_list(Status)), State = ejabberd_odbc:escape(Status),
odbc_queries:set_last_t(LServer, Username, Seconds, State) odbc_queries:set_last_t(LServer, Username, Seconds, State)
catch catch
_ -> _ ->
@ -151,7 +157,7 @@ get_last_info(LUser, LServer) ->
{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) ->
{ok, TimeStamp, list_to_binary(Status)}; {ok, TimeStamp, Status};
_ -> _ ->
not_found not_found
end; end;

View File

@ -136,7 +136,7 @@ process_iq_disco_items(Host, From, To, #iq{} = IQ) ->
can_use_nick(_Host, _JID, "") -> can_use_nick(_Host, _JID, "") ->
false; false;
can_use_nick(Host, JID, Nick) -> can_use_nick(Host, JID, Nick) ->
LUS = {JID#jid.lnode, JID#jid.ldomain}, LUS = {exmpp_jid:lnode_as_list(JID), exmpp_jid:ldomain_as_list(JID)},
case catch mnesia:dirty_select( case catch mnesia:dirty_select(
muc_registered, muc_registered,
[{#muc_registered{us_host = '$1', [{#muc_registered{us_host = '$1',
@ -312,8 +312,8 @@ do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
From, To, Packet, DefRoomOpts) -> From, To, Packet, DefRoomOpts) ->
{_AccessRoute, AccessCreate, AccessAdmin, _AccessPersistent} = Access, {_AccessRoute, AccessCreate, AccessAdmin, _AccessPersistent} = Access,
Room = To#jid.lnode, Room = exmpp_jid:lnode_as_list(To),
Nick = To#jid.lresource, Nick = exmpp_jid:lresource_as_list(To),
#xmlel{name = Name} = Packet, #xmlel{name = Name} = Packet,
case Room of case Room of
'undefined' -> 'undefined' ->
@ -554,8 +554,8 @@ flush() ->
children = [#xmlcdata{cdata = Val}]}]}). children = [#xmlcdata{cdata = Val}]}]}).
iq_get_register_info(Host, From, Lang) -> iq_get_register_info(Host, From, Lang) ->
LUser = From#jid.lnode, LUser = exmpp_jid:lnode_as_list(From),
LServer = From#jid.ldomain, LServer = exmpp_jid:ldomain_as_list(From),
LUS = {LUser, LServer}, LUS = {LUser, LServer},
{Nick, Registered} = {Nick, Registered} =
case catch mnesia:dirty_read(muc_registered, {LUS, Host}) of case catch mnesia:dirty_read(muc_registered, {LUS, Host}) of
@ -584,8 +584,8 @@ iq_get_register_info(Host, From, Lang) ->
iq_set_register_info(Host, From, Nick, Lang) -> iq_set_register_info(Host, From, Nick, Lang) ->
LUser = From#jid.lnode, LUser = exmpp_jid:lnode_as_list(From),
LServer = From#jid.ldomain, LServer = exmpp_jid:ldomain_as_list(From),
LUS = {LUser, LServer}, LUS = {LUser, LServer},
F = fun() -> F = fun() ->
case Nick of case Nick of

View File

@ -272,7 +272,7 @@ build_filename_string(TimeStamp, OutDir, RoomJID, DirType, DirName, FileFormat)
get_room_name(RoomJID) -> get_room_name(RoomJID) ->
JID = exmpp_jid:list_to_jid(RoomJID), JID = exmpp_jid:list_to_jid(RoomJID),
JID#jid.node. exmpp_jid:node_as_list(JID).
%% calculate day before %% calculate day before
get_timestamp_daydiff(TimeStamp, Daydiff) -> get_timestamp_daydiff(TimeStamp, Daydiff) ->

View File

@ -261,6 +261,7 @@ normal_state({route, From, undefined,
StateData#state.jid, StateData#state.jid,
From, exmpp_stanza:reply_with_error(Packet, Err)), From, exmpp_stanza:reply_with_error(Packet, Err)),
{next_state, normal_state, StateData}; {next_state, normal_state, StateData};
%%TODO: currently exmpp_message:get_type/1 never returns 'undefined'
Type when (Type == 'normal') orelse (Type == 'undefined') -> Type when (Type == 'normal') orelse (Type == 'undefined') ->
case catch check_invitation(From, case catch check_invitation(From,
exmpp_xml:get_child_elements(Packet), exmpp_xml:get_child_elements(Packet),
@ -2139,11 +2140,16 @@ process_admin_items_set(UJID, Items, Lang, StateData) ->
fun(E, SD) -> fun(E, SD) ->
case catch ( case catch (
case E of case E of
{JID, affiliation, owner, _} {JID, affiliation, owner, _} ->
when (JID#jid.lnode == "") -> case exmpp_jid:lnode(JID) of
<<>> ->
SD;
%% TODO: <<>> or 'undefined' ?
%% TODO: double case on the E var, because
%% exmpp_jid:lnode/1 can't be used in guards
%% If the provided JID does not have username, %% If the provided JID does not have username,
%% forget the affiliation completely %% forget the affiliation completely
SD; _ -> case E of
{JID, role, none, Reason} -> {JID, role, none, Reason} ->
catch send_kickban_presence( catch send_kickban_presence(
JID, Reason, "307", SD), JID, Reason, "307", SD),
@ -2187,6 +2193,8 @@ process_admin_items_set(UJID, Items, Lang, StateData) ->
send_update_presence(JID, SD1), send_update_presence(JID, SD1),
SD1 SD1
end end
end
end
) of ) of
{'EXIT', ErrReason} -> {'EXIT', ErrReason} ->
?ERROR_MSG("MUC ITEMS SET ERR: ~p~n", ?ERROR_MSG("MUC ITEMS SET ERR: ~p~n",
@ -3285,7 +3293,7 @@ check_invitation(From, Els, Lang, StateData) ->
_ -> [" (", Reason, ") "] _ -> [" (", Reason, ") "]
end end
])}]}, ])}]},
%%TODO: always NS_JABER_CLIENT? %%TODO: always NS_JABBER_CLIENT?
Msg = Msg =
#xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message',
attrs = [#xmlattr{name = 'type', value = "normal"}], attrs = [#xmlattr{name = 'type', value = "normal"}],
@ -3370,8 +3378,8 @@ add_to_log(Type, Data, StateData) ->
%% Users number checking %% Users number checking
tab_add_online_user(JID, StateData) -> tab_add_online_user(JID, StateData) ->
LUser = JID#jid.lnode, LUser = exmpp_jid:lnode(JID),
LServer = JID#jid.ldomain, LServer = exmpp_jid:ldomain(JID),
US = {LUser, LServer}, US = {LUser, LServer},
Room = StateData#state.room, Room = StateData#state.room,
Host = StateData#state.host, Host = StateData#state.host,
@ -3381,7 +3389,9 @@ tab_add_online_user(JID, StateData) ->
tab_remove_online_user(#jid{lnode = LUser, ldomain = LServer}, StateData) -> tab_remove_online_user(JID, StateData) when ?IS_JID(JID) ->
LUser = exmpp_jid:lnode(JID),
LServer = exmpp_jid:ldomain(JID),
tab_remove_online_user({LUser, LServer, none},StateData); tab_remove_online_user({LUser, LServer, none},StateData);
tab_remove_online_user({LUser, LServer,_}, StateData) -> tab_remove_online_user({LUser, LServer,_}, StateData) ->
@ -3393,8 +3403,8 @@ tab_remove_online_user({LUser, LServer,_}, StateData) ->
#muc_online_users{us = US, room = Room, host = Host}). #muc_online_users{us = US, room = Room, host = Host}).
tab_count_user(JID) -> tab_count_user(JID) ->
LUser = JID#jid.lnode, LUser = exmpp_jid:lnode(JID),
LServer = JID#jid.ldomain, LServer = exmpp_jid:ldomain(JID),
US = {LUser, LServer}, US = {LUser, LServer},
case catch ets:select( case catch ets:select(
muc_online_users, muc_online_users,
@ -3407,11 +3417,7 @@ tab_count_user(JID) ->
jid_replace_resource(JID, Resource) -> jid_replace_resource(JID, Resource) ->
case exmpp_stringprep:resourceprep(Resource) of exmpp_jid:bare_jid_to_jid(JID, Resource).
error -> error;
LResource ->
JID#jid{resource = Resource, lresource = LResource}
end.

View File

@ -59,24 +59,25 @@
-define(PREFIXED_NS, [{?NS_XMPP, ?NS_XMPP_pfx}]). -define(PREFIXED_NS, [{?NS_XMPP, ?NS_XMPP_pfx}]).
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
mnesia:create_table(offline_msg, mnesia:create_table(offline_msg,
[{disc_only_copies, [node()]}, [{disc_only_copies, [node()]},
{type, bag}, {type, bag},
{attributes, record_info(fields, offline_msg)}]), {attributes, record_info(fields, offline_msg)}]),
update_table(), update_table(),
ejabberd_hooks:add(offline_message_hook, Host, ejabberd_hooks:add(offline_message_hook, HostB,
?MODULE, store_packet, 50), ?MODULE, store_packet, 50),
ejabberd_hooks:add(resend_offline_messages_hook, Host, ejabberd_hooks:add(resend_offline_messages_hook, HostB,
?MODULE, pop_offline_messages, 50), ?MODULE, pop_offline_messages, 50),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(anonymous_purge_hook, Host, ejabberd_hooks:add(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(webadmin_page_host, Host, ejabberd_hooks:add(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:add(webadmin_user, Host, ejabberd_hooks:add(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
ejabberd_hooks:add(webadmin_user_parse_query, Host, ejabberd_hooks:add(webadmin_user_parse_query, HostB,
?MODULE, webadmin_user_parse_query, 50), ?MODULE, webadmin_user_parse_query, 50),
MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity), MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
register(gen_mod:get_module_proc(Host, ?PROCNAME), register(gen_mod:get_module_proc(Host, ?PROCNAME),
@ -134,19 +135,20 @@ receive_all(US, Msgs) ->
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(offline_message_hook, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(offline_message_hook, HostB,
?MODULE, store_packet, 50), ?MODULE, store_packet, 50),
ejabberd_hooks:delete(resend_offline_messages_hook, Host, ejabberd_hooks:delete(resend_offline_messages_hook, HostB,
?MODULE, pop_offline_messages, 50), ?MODULE, pop_offline_messages, 50),
ejabberd_hooks:delete(remove_user, Host, ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(anonymous_purge_hook, Host, ejabberd_hooks:delete(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(webadmin_page_host, Host, ejabberd_hooks:delete(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:delete(webadmin_user, Host, ejabberd_hooks:delete(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
ejabberd_hooks:delete(webadmin_user_parse_query, Host, ejabberd_hooks:delete(webadmin_user_parse_query, HostB,
?MODULE, webadmin_user_parse_query, 50), ?MODULE, webadmin_user_parse_query, 50),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
exit(whereis(Proc), stop), exit(whereis(Proc), stop),
@ -159,10 +161,11 @@ store_packet(From, To, Packet) ->
(Type /= "headline") -> (Type /= "headline") ->
case check_event(From, To, Packet) of case check_event(From, To, Packet) of
true -> true ->
#jid{lnode = LUser, ldomain = LServer} = To, LUser = exmpp_jid:lnode_as_list(To),
LServer = exmpp_jid:ldomain_as_list(To),
TimeStamp = now(), TimeStamp = now(),
Expire = find_x_expire(TimeStamp, Packet#xmlel.children), Expire = find_x_expire(TimeStamp, Packet#xmlel.children),
gen_mod:get_module_proc(To#jid.ldomain, ?PROCNAME) ! gen_mod:get_module_proc(LServer, ?PROCNAME) !
#offline_msg{us = {LUser, LServer}, #offline_msg{us = {LUser, LServer},
timestamp = TimeStamp, timestamp = TimeStamp,
expire = Expire, expire = Expire,
@ -267,10 +270,11 @@ resend_offline_messages(User, Server) ->
ok ok
end. end.
pop_offline_messages(Ls, User, Server) -> pop_offline_messages(Ls, User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
US = {LUser, LServer}, US = {LUser, LServer},
F = fun() -> F = fun() ->
Rs = mnesia:wread({offline_msg, US}), Rs = mnesia:wread({offline_msg, US}),
@ -347,7 +351,7 @@ remove_old_messages(Days) ->
end, end,
mnesia:transaction(F). mnesia:transaction(F).
remove_user(User, Server) -> remove_user(User, Server) when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),

View File

@ -58,19 +58,20 @@
-define(PREFIXED_NS, [{?NS_XMPP, ?NS_XMPP_pfx}]). -define(PREFIXED_NS, [{?NS_XMPP, ?NS_XMPP_pfx}]).
start(Host, Opts) -> start(Host, Opts) ->
ejabberd_hooks:add(offline_message_hook, Host, HostB = list_to_binary(Host),
ejabberd_hooks:add(offline_message_hook, HostB,
?MODULE, store_packet, 50), ?MODULE, store_packet, 50),
ejabberd_hooks:add(resend_offline_messages_hook, Host, ejabberd_hooks:add(resend_offline_messages_hook, HostB,
?MODULE, pop_offline_messages, 50), ?MODULE, pop_offline_messages, 50),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(anonymous_purge_hook, Host, ejabberd_hooks:add(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(webadmin_page_host, Host, ejabberd_hooks:add(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:add(webadmin_user, Host, ejabberd_hooks:add(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
ejabberd_hooks:add(webadmin_user_parse_query, Host, ejabberd_hooks:add(webadmin_user_parse_query, HostB,
?MODULE, webadmin_user_parse_query, 50), ?MODULE, webadmin_user_parse_query, 50),
MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity), MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
register(gen_mod:get_module_proc(Host, ?PROCNAME), register(gen_mod:get_module_proc(Host, ?PROCNAME),
@ -102,7 +103,7 @@ loop(Host, MaxOfflineMsgs) ->
fun(M) -> fun(M) ->
Username = Username =
ejabberd_odbc:escape( ejabberd_odbc:escape(
(M#offline_msg.to)#jid.lnode), exmpp_jid:lnode_as_list(M#offline_msg.to)),
From = M#offline_msg.from, From = M#offline_msg.from,
To = M#offline_msg.to, To = M#offline_msg.to,
Packet0 = exmpp_stanza:set_jids( Packet0 = exmpp_stanza:set_jids(
@ -142,19 +143,20 @@ receive_all(Username, Msgs) ->
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(offline_message_hook, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(offline_message_hook, HostB,
?MODULE, store_packet, 50), ?MODULE, store_packet, 50),
ejabberd_hooks:delete(resend_offline_messages_hook, Host, ejabberd_hooks:delete(resend_offline_messages_hook, HostB,
?MODULE, pop_offline_messages, 50), ?MODULE, pop_offline_messages, 50),
ejabberd_hooks:delete(remove_user, Host, ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(anonymous_purge_hook, Host, ejabberd_hooks:delete(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(webadmin_page_host, Host, ejabberd_hooks:delete(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:delete(webadmin_user, Host, ejabberd_hooks:delete(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
ejabberd_hooks:delete(webadmin_user_parse_query, Host, ejabberd_hooks:delete(webadmin_user_parse_query, HostB,
?MODULE, webadmin_user_parse_query, 50), ?MODULE, webadmin_user_parse_query, 50),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
exit(whereis(Proc), stop), exit(whereis(Proc), stop),
@ -167,10 +169,10 @@ store_packet(From, To, Packet) ->
(Type /= "headline") -> (Type /= "headline") ->
case check_event(From, To, Packet) of case check_event(From, To, Packet) of
true -> true ->
#jid{lnode = LUser} = To, LUser = exmpp_jid:lnode_as_list(To),
TimeStamp = now(), TimeStamp = now(),
Expire = find_x_expire(TimeStamp, Packet#xmlel.children), Expire = find_x_expire(TimeStamp, Packet#xmlel.children),
gen_mod:get_module_proc(To#jid.ldomain, ?PROCNAME) ! gen_mod:get_module_proc(exmpp_jid:ldomain_as_list(To), ?PROCNAME) !
#offline_msg{user = LUser, #offline_msg{user = LUser,
timestamp = TimeStamp, timestamp = TimeStamp,
expire = Expire, expire = Expire,
@ -241,17 +243,20 @@ find_x_expire(TimeStamp, [_ | Els]) ->
find_x_expire(TimeStamp, Els). find_x_expire(TimeStamp, Els).
pop_offline_messages(Ls, User, Server) -> pop_offline_messages(Ls, User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(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}) ->
try try
[El] = exmpp_xml:parse_document(XML, [names_as_atom]), [El] = exmpp_xml:parse_document(XML,
[names_as_atom, {check_elems, xmpp},
{check_nss,xmpp}, {check_attrs,xmpp}]),
To = exmpp_jid:list_to_jid( To = exmpp_jid:list_to_jid(
exmpp_stanza:get_recipient(El)), exmpp_stanza:get_recipient(El)),
From = exmpp_jid:list_to_jid( From = exmpp_jid:list_to_jid(
@ -271,7 +276,8 @@ pop_offline_messages(Ls, User, Server) ->
end. end.
remove_user(User, Server) -> remove_user(User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
@ -327,7 +333,9 @@ user_queue(User, Server, Query, Lang) ->
{selected, ["username", "xml"], Rs} -> {selected, ["username", "xml"], Rs} ->
lists:flatmap( lists:flatmap(
fun({_, XML}) -> fun({_, XML}) ->
try exmpp_xml:parse_document(XML, [names_as_atom]) of try exmpp_xml:parse_document(XML,
[names_as_atom, {check_elems, xmpp},
{check_nss,xmpp}, {check_attrs,xmpp}]) of
[El] -> [El] ->
[El] [El]
catch catch
@ -394,7 +402,9 @@ 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}) ->
try exmpp_xml:parse_document(XML, [names_as_atom]) of try exmpp_xml:parse_document(XML,
[names_as_atom, {check_elems, xmpp},
{check_nss,xmpp}, {check_attrs,xmpp}]) of
[El] -> [El] ->
[{El, Seq}] [{El, Seq}]
catch catch

View File

@ -44,33 +44,35 @@
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
mnesia:create_table(privacy, [{disc_copies, [node()]}, mnesia:create_table(privacy, [{disc_copies, [node()]},
{attributes, record_info(fields, privacy)}]), {attributes, record_info(fields, privacy)}]),
update_table(), update_table(),
ejabberd_hooks:add(privacy_iq_get, Host, ejabberd_hooks:add(privacy_iq_get, HostB,
?MODULE, process_iq_get, 50), ?MODULE, process_iq_get, 50),
ejabberd_hooks:add(privacy_iq_set, Host, ejabberd_hooks:add(privacy_iq_set, HostB,
?MODULE, process_iq_set, 50), ?MODULE, process_iq_set, 50),
ejabberd_hooks:add(privacy_get_user_list, Host, ejabberd_hooks:add(privacy_get_user_list, HostB,
?MODULE, get_user_list, 50), ?MODULE, get_user_list, 50),
ejabberd_hooks:add(privacy_check_packet, Host, ejabberd_hooks:add(privacy_check_packet, HostB,
?MODULE, check_packet, 50), ?MODULE, check_packet, 50),
ejabberd_hooks:add(privacy_updated_list, Host, ejabberd_hooks:add(privacy_updated_list, HostB,
?MODULE, updated_list, 50), ?MODULE, updated_list, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY,
?MODULE, process_iq, IQDisc). ?MODULE, process_iq, IQDisc).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(privacy_iq_get, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(privacy_iq_get, HostB,
?MODULE, process_iq_get, 50), ?MODULE, process_iq_get, 50),
ejabberd_hooks:delete(privacy_iq_set, Host, ejabberd_hooks:delete(privacy_iq_set, HostB,
?MODULE, process_iq_set, 50), ?MODULE, process_iq_set, 50),
ejabberd_hooks:delete(privacy_get_user_list, Host, ejabberd_hooks:delete(privacy_get_user_list, HostB,
?MODULE, get_user_list, 50), ?MODULE, get_user_list, 50),
ejabberd_hooks:delete(privacy_check_packet, Host, ejabberd_hooks:delete(privacy_check_packet, HostB,
?MODULE, check_packet, 50), ?MODULE, check_packet, 50),
ejabberd_hooks:delete(privacy_updated_list, Host, ejabberd_hooks:delete(privacy_updated_list, HostB,
?MODULE, updated_list, 50), ?MODULE, updated_list, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY).
@ -80,7 +82,8 @@ process_iq(_From, _To, IQ_Rec) ->
process_iq_get(_, From, _To, #iq{payload = SubEl}, process_iq_get(_, From, _To, #iq{payload = SubEl},
#userlist{name = Active}) -> #userlist{name = Active}) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case exmpp_xml:get_child_elements(SubEl) of case exmpp_xml:get_child_elements(SubEl) of
[] -> [] ->
process_lists_get(LUser, LServer, Active); process_lists_get(LUser, LServer, Active);
@ -238,7 +241,8 @@ list_to_action(S) ->
process_iq_set(_, From, _To, #iq{payload = SubEl}) -> process_iq_set(_, From, _To, #iq{payload = SubEl}) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case exmpp_xml:get_child_elements(SubEl) of case exmpp_xml:get_child_elements(SubEl) of
[#xmlel{name = Name} = Child] -> [#xmlel{name = Name} = Child] ->
ListName = exmpp_xml:get_attribute(Child, 'name', false), ListName = exmpp_xml:get_attribute(Child, 'name', false),
@ -510,10 +514,11 @@ parse_matches1(_Item, [#xmlel{} | _Els]) ->
get_user_list(_, User, Server) -> get_user_list(_, User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
case catch mnesia:dirty_read(privacy, {LUser, LServer}) of case catch mnesia:dirty_read(privacy, {LUser, LServer}) of
[] -> [] ->
#userlist{}; #userlist{};
@ -542,7 +547,8 @@ get_user_list(_, User, Server) ->
check_packet(_, User, Server, check_packet(_, User, Server,
#userlist{list = List}, #userlist{list = List},
{From, To, #xmlel{name = PName}}, {From, To, #xmlel{name = PName}},
Dir) when PName =:= message ; Dir) when
PName =:= message ;
PName =:= iq ; PName =:= iq ;
PName =:= presence -> PName =:= presence ->
case List of case List of
@ -554,7 +560,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(From), LJID = jlib:short_prepd_jid(From),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, From]), {none, []}, [User, Server, From]),
check_packet_aux(List, message, check_packet_aux(List, message,
LJID, Subscription, Groups); LJID, Subscription, Groups);
@ -562,7 +569,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(From), LJID = jlib:short_prepd_jid(From),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, From]), {none, []}, [User, Server, From]),
check_packet_aux(List, iq, check_packet_aux(List, iq,
LJID, Subscription, Groups); LJID, Subscription, Groups);
@ -570,7 +578,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(From), LJID = jlib:short_prepd_jid(From),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, From]), {none, []}, [User, Server, From]),
check_packet_aux(List, presence_in, check_packet_aux(List, presence_in,
LJID, Subscription, Groups); LJID, Subscription, Groups);
@ -578,7 +587,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(To), LJID = jlib:short_prepd_jid(To),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, To]), {none, []}, [User, Server, To]),
check_packet_aux(List, presence_out, check_packet_aux(List, presence_out,
LJID, Subscription, Groups); LJID, Subscription, Groups);

View File

@ -43,30 +43,32 @@
-include("mod_privacy.hrl"). -include("mod_privacy.hrl").
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
ejabberd_hooks:add(privacy_iq_get, Host, ejabberd_hooks:add(privacy_iq_get, HostB,
?MODULE, process_iq_get, 50), ?MODULE, process_iq_get, 50),
ejabberd_hooks:add(privacy_iq_set, Host, ejabberd_hooks:add(privacy_iq_set, HostB,
?MODULE, process_iq_set, 50), ?MODULE, process_iq_set, 50),
ejabberd_hooks:add(privacy_get_user_list, Host, ejabberd_hooks:add(privacy_get_user_list, HostB,
?MODULE, get_user_list, 50), ?MODULE, get_user_list, 50),
ejabberd_hooks:add(privacy_check_packet, Host, ejabberd_hooks:add(privacy_check_packet, HostB,
?MODULE, check_packet, 50), ?MODULE, check_packet, 50),
ejabberd_hooks:add(privacy_updated_list, Host, ejabberd_hooks:add(privacy_updated_list, HostB,
?MODULE, updated_list, 50), ?MODULE, updated_list, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY,
?MODULE, process_iq, IQDisc). ?MODULE, process_iq, IQDisc).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(privacy_iq_get, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(privacy_iq_get, HostB,
?MODULE, process_iq_get, 50), ?MODULE, process_iq_get, 50),
ejabberd_hooks:delete(privacy_iq_set, Host, ejabberd_hooks:delete(privacy_iq_set, HostB,
?MODULE, process_iq_set, 50), ?MODULE, process_iq_set, 50),
ejabberd_hooks:delete(privacy_get_user_list, Host, ejabberd_hooks:delete(privacy_get_user_list, HostB,
?MODULE, get_user_list, 50), ?MODULE, get_user_list, 50),
ejabberd_hooks:delete(privacy_check_packet, Host, ejabberd_hooks:delete(privacy_check_packet, HostB,
?MODULE, check_packet, 50), ?MODULE, check_packet, 50),
ejabberd_hooks:delete(privacy_updated_list, Host, ejabberd_hooks:delete(privacy_updated_list, HostB,
?MODULE, updated_list, 50), ?MODULE, updated_list, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY).
@ -76,7 +78,8 @@ process_iq(_From, _To, IQ_Rec) ->
process_iq_get(_, From, _To, #iq{payload = SubEl}, process_iq_get(_, From, _To, #iq{payload = SubEl},
#userlist{name = Active}) -> #userlist{name = Active}) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case exmpp_xml:get_child_elements(SubEl) of case exmpp_xml:get_child_elements(SubEl) of
[] -> [] ->
process_lists_get(LUser, LServer, Active); process_lists_get(LUser, LServer, Active);
@ -244,7 +247,8 @@ list_to_action(S) ->
process_iq_set(_, From, _To, #iq{payload = SubEl}) -> process_iq_set(_, From, _To, #iq{payload = SubEl}) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case exmpp_xml:get_child_elements(SubEl) of case exmpp_xml:get_child_elements(SubEl) of
[#xmlel{name = Name} = Child] -> [#xmlel{name = Name} = Child] ->
ListName = exmpp_xml:get_attribute(Child, 'name', false), ListName = exmpp_xml:get_attribute(Child, 'name', false),
@ -511,10 +515,11 @@ parse_matches1(_Item, [#xmlel{} | _Els]) ->
get_user_list(_, User, Server) -> get_user_list(_, User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
case catch sql_get_default_privacy_list(LUser, LServer) of case catch sql_get_default_privacy_list(LUser, LServer) of
{selected, ["name"], []} -> {selected, ["name"], []} ->
#userlist{}; #userlist{};
@ -541,7 +546,8 @@ get_user_list(_, User, Server) ->
check_packet(_, User, Server, check_packet(_, User, Server,
#userlist{list = List}, #userlist{list = List},
{From, To, #xmlel{name = PName}}, {From, To, #xmlel{name = PName}},
Dir) when PName =:= message ; Dir) when
PName =:= message ;
PName =:= iq ; PName =:= iq ;
PName =:= presence -> PName =:= presence ->
case List of case List of
@ -553,7 +559,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(From), LJID = jlib:short_prepd_jid(From),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, From]), {none, []}, [User, Server, From]),
check_packet_aux(List, message, check_packet_aux(List, message,
LJID, Subscription, Groups); LJID, Subscription, Groups);
@ -561,7 +568,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(From), LJID = jlib:short_prepd_jid(From),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, From]), {none, []}, [User, Server, From]),
check_packet_aux(List, iq, check_packet_aux(List, iq,
LJID, Subscription, Groups); LJID, Subscription, Groups);
@ -569,7 +577,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(From), LJID = jlib:short_prepd_jid(From),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, From]), {none, []}, [User, Server, From]),
check_packet_aux(List, presence_in, check_packet_aux(List, presence_in,
LJID, Subscription, Groups); LJID, Subscription, Groups);
@ -577,7 +586,8 @@ check_packet(_, User, Server,
LJID = jlib:short_prepd_jid(To), LJID = jlib:short_prepd_jid(To),
{Subscription, Groups} = {Subscription, Groups} =
ejabberd_hooks:run_fold( ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_stringprep:nameprep(Server), roster_get_jid_info,
Server,
{none, []}, [User, Server, To]), {none, []}, [User, Server, To]),
check_packet_aux(List, presence_out, check_packet_aux(List, presence_out,
LJID, Subscription, Groups); LJID, Subscription, Groups);

View File

@ -41,18 +41,20 @@
-record(private_storage, {usns, xml}). -record(private_storage, {usns, xml}).
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
mnesia:create_table(private_storage, mnesia:create_table(private_storage,
[{disc_only_copies, [node()]}, [{disc_only_copies, [node()]},
{attributes, record_info(fields, private_storage)}]), {attributes, record_info(fields, private_storage)}]),
update_table(), update_table(),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE,
?MODULE, process_sm_iq, IQDisc). ?MODULE, process_sm_iq, IQDisc).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE).
@ -71,7 +73,8 @@ process_sm_iq(From, To, #iq{type = Type} = IQ_Rec) ->
end. end.
process_iq_get(From, _To, #iq{payload = SubEl} = IQ_Rec) -> process_iq_get(From, _To, #iq{payload = SubEl} = IQ_Rec) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case catch get_data(LUser, case catch get_data(LUser,
LServer, LServer,
exmpp_xml:get_child_elements(SubEl)) of exmpp_xml:get_child_elements(SubEl)) of
@ -85,7 +88,8 @@ process_iq_get(From, _To, #iq{payload = SubEl} = IQ_Rec) ->
process_iq_set(From, _To, #iq{payload = SubEl} = IQ_Rec) -> process_iq_set(From, _To, #iq{payload = SubEl} = IQ_Rec) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
F = fun() -> F = fun() ->
lists:foreach( lists:foreach(
fun(El) -> fun(El) ->
@ -108,7 +112,8 @@ check_packet(From, To, IQ_Rec, [F | R]) ->
ok -> check_packet(From, To, IQ_Rec, R) ok -> check_packet(From, To, IQ_Rec, R)
end. end.
check_domain(#jid{ldomain = LServer}, _To, _IQ_Rec) -> check_domain(From, _To, _IQ_Rec) ->
LServer = exmpp_jid:ldomain_as_list(From),
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> ok; true -> ok;
false -> {error, 'not-allowed'} false -> {error, 'not-allowed'}
@ -158,7 +163,8 @@ get_data(LUser, LServer, [El | Els], Res) ->
[El | Res]) [El | Res])
end. end.
remove_user(User, Server) -> remove_user(User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),

View File

@ -39,14 +39,16 @@
-include("ejabberd.hrl"). -include("ejabberd.hrl").
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE,
?MODULE, process_sm_iq, IQDisc). ?MODULE, process_sm_iq, IQDisc).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE).
@ -65,7 +67,8 @@ process_sm_iq(From, To, #iq{type = Type} = IQ_Rec) ->
end. end.
process_iq_get(From, _To, #iq{payload = SubEl} = IQ_Rec) -> process_iq_get(From, _To, #iq{payload = SubEl} = IQ_Rec) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case catch get_data(LUser, case catch get_data(LUser,
LServer, LServer,
exmpp_xml:get_child_elements(SubEl)) of exmpp_xml:get_child_elements(SubEl)) of
@ -79,7 +82,8 @@ process_iq_get(From, _To, #iq{payload = SubEl} = IQ_Rec) ->
process_iq_set(From, _To, #iq{payload = SubEl} = IQ_Rec) -> process_iq_set(From, _To, #iq{payload = SubEl} = IQ_Rec) ->
#jid{lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
F = fun() -> F = fun() ->
lists:foreach( lists:foreach(
fun(El) -> fun(El) ->
@ -102,7 +106,8 @@ check_packet(From, To, IQ_Rec, [F | R]) ->
ok -> check_packet(From, To, IQ_Rec, R) ok -> check_packet(From, To, IQ_Rec, R)
end. end.
check_domain(#jid{ldomain = LServer}, _To, _IQ_Rec) -> check_domain(From, _To, _IQ_Rec) ->
LServer = exmpp_jid:ldomain_as_list(From),
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> ok; true -> ok;
false -> {error, 'not-allowed'} false -> {error, 'not-allowed'}
@ -151,7 +156,9 @@ get_data(LUser, LServer, [El | Els], Res) ->
LXMLNS = ejabberd_odbc:escape(XMLNS), LXMLNS = ejabberd_odbc:escape(XMLNS),
case catch odbc_queries:get_private_data(LServer, Username, LXMLNS) of case catch odbc_queries:get_private_data(LServer, Username, LXMLNS) of
{selected, ["data"], [{SData}]} -> {selected, ["data"], [{SData}]} ->
[Data] = exmpp_xml:parse_document(SData,[names_as_atom]), [Data] = exmpp_xml:parse_document(SData,
[names_as_atom, {check_elems, xmpp},
{check_nss,xmpp}, {check_attrs,xmpp}]),
get_data(LUser, LServer, Els, [Data | Res]); get_data(LUser, LServer, Els, [Data | Res]);
%% MREMOND: I wonder when the query could return a vcard ? %% MREMOND: I wonder when the query could return a vcard ?
{selected, ["vcard"], []} -> {selected, ["vcard"], []} ->
@ -162,7 +169,7 @@ get_data(LUser, LServer, [El | Els], Res) ->
end. end.
remove_user(User, Server) -> remove_user(User, Server) when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),

View File

@ -631,7 +631,7 @@ get_states(Host, Node) ->
get_state(Host, Node, JID) -> get_state(Host, Node, JID) ->
StateId = {JID, {Host, Node}}, StateId = {JID, {Host, Node}},
case mnesia:read({pubsub_state, StateId}) of case mnesia:read({pubsub_state, StateId}) of
[State] when is_record(State, pubsub_state) -> State [State] when is_record(State, pubsub_state) -> State;
_ -> #pubsub_state{stateid=StateId} _ -> #pubsub_state{stateid=StateId}
end. end.

View File

@ -40,14 +40,15 @@
-include("ejabberd.hrl"). -include("ejabberd.hrl").
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
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_INBAND_REGISTER, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_INBAND_REGISTER,
?MODULE, process_iq, IQDisc), ?MODULE, process_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_INBAND_REGISTER, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_INBAND_REGISTER,
?MODULE, process_iq, IQDisc), ?MODULE, process_iq, IQDisc),
ejabberd_hooks:add(c2s_stream_features, Host, ejabberd_hooks:add(c2s_stream_features, HostB,
?MODULE, stream_feature_register, 50), ?MODULE, stream_feature_register, 50),
ejabberd_hooks:add(c2s_unauthenticated_iq, Host, ejabberd_hooks:add(c2s_unauthenticated_iq, HostB,
?MODULE, unauthenticated_iq_register, 50), ?MODULE, unauthenticated_iq_register, 50),
mnesia:create_table(mod_register_ip, mnesia:create_table(mod_register_ip,
[{ram_copies, [node()]}, [{ram_copies, [node()]},
@ -57,9 +58,10 @@ start(Host, Opts) ->
ok. ok.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(c2s_stream_features, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(c2s_stream_features, HostB,
?MODULE, stream_feature_register, 50), ?MODULE, stream_feature_register, 50),
ejabberd_hooks:delete(c2s_unauthenticated_iq, Host, ejabberd_hooks:delete(c2s_unauthenticated_iq, HostB,
?MODULE, unauthenticated_iq_register, 50), ?MODULE, unauthenticated_iq_register, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_INBAND_REGISTER), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_INBAND_REGISTER),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_INBAND_REGISTER). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_INBAND_REGISTER).
@ -74,17 +76,20 @@ unauthenticated_iq_register(_Acc,
{A, _Port} -> A; {A, _Port} -> A;
_ -> undefined _ -> undefined
end, end,
ResIQ = process_iq(#jid{}, BareJID = exmpp_jid:make_bare_jid(Server),
exmpp_jid:make_bare_jid(Server), ResIQ = process_iq(exmpp_jid:make_jid(),
BareJID,
IQ_Rec, IQ_Rec,
Address), Address),
exmpp_iq:iq_to_xmlel(ResIQ, exmpp_jid:make_bare_jid(Server), undefined); exmpp_iq:iq_to_xmlel(ResIQ, BareJID, undefined);
unauthenticated_iq_register(Acc, _Server, _IQ, _IP) -> unauthenticated_iq_register(Acc, _Server, _IQ, _IP) ->
Acc. Acc.
process_iq(From, To, IQ) -> process_iq(From, To, IQ) ->
process_iq(From, To, IQ, jlib:short_prepd_bare_jid(From)). process_iq(From, To, IQ, {exmpp_jid:lnode_as_list(From),
exmpp_jid:ldomain_as_list(From),
exmpp_jid:lresource_as_list(From)}).
process_iq(From, To, process_iq(From, To,
#iq{type = Type, lang = Lang, payload = SubEl} = IQ_Rec, #iq{type = Type, lang = Lang, payload = SubEl} = IQ_Rec,
@ -94,12 +99,12 @@ process_iq(From, To,
UTag = exmpp_xml:get_element(SubEl, 'username'), UTag = exmpp_xml:get_element(SubEl, 'username'),
PTag = exmpp_xml:get_element(SubEl, 'password'), PTag = exmpp_xml:get_element(SubEl, 'password'),
RTag = exmpp_xml:get_element(SubEl, 'remove'), RTag = exmpp_xml:get_element(SubEl, 'remove'),
Server = To#jid.ldomain, Server = exmpp_jid:ldomain_as_list(To),
if if
(UTag /= undefined) and (RTag /= undefined) -> (UTag /= undefined) and (RTag /= undefined) ->
User = exmpp_xml:get_cdata_as_list(UTag), User = exmpp_xml:get_cdata_as_list(UTag),
case From of case {exmpp_jid:node_as_list(From), exmpp_jid:ldomain_as_list(From)} of
#jid{node = User, ldomain = Server} -> {User, Server} ->
ejabberd_auth:remove_user(User, Server), ejabberd_auth:remove_user(User, Server),
exmpp_iq:result(IQ_Rec, SubEl); exmpp_iq:result(IQ_Rec, SubEl);
_ -> _ ->
@ -132,14 +137,18 @@ process_iq(From, To,
end end
end; end;
(UTag == undefined) and (RTag /= undefined) -> (UTag == undefined) and (RTag /= undefined) ->
case From of case {exmpp_jid:node_as_list(From),
#jid{node = User, exmpp_jid:ldomain_as_list(From),
ldomain = Server, exmpp_jid:resource_as_list(From)}of
resource = Resource} -> {User, Server, Resource} ->
ResIQ = exmpp_iq:result(IQ_Rec, SubEl), ResIQ = exmpp_iq:result(IQ_Rec, SubEl),
ejabberd_router:route( ejabberd_router:route(
exmpp_jid:make_jid(User, Server, Resource), exmpp_jid:make_jid(User,
exmpp_jid:make_jid(User, Server, Resource), Server,
Resource),
exmpp_jid:make_jid(User,
Server,
Resource),
exmpp_iq:iq_to_xmlel(ResIQ)), exmpp_iq:iq_to_xmlel(ResIQ)),
ejabberd_auth:remove_user(User, Server), ejabberd_auth:remove_user(User, Server),
ignore; ignore;
@ -149,8 +158,8 @@ process_iq(From, To,
(UTag /= undefined) and (PTag /= undefined) -> (UTag /= undefined) and (PTag /= undefined) ->
User = exmpp_xml:get_cdata_as_list(UTag), User = exmpp_xml:get_cdata_as_list(UTag),
Password = exmpp_xml:get_cdata_as_list(PTag), Password = exmpp_xml:get_cdata_as_list(PTag),
case From of case {exmpp_jid:node_as_list(From), exmpp_jid:ldomain_as_list(From)} of
#jid{node = User, ldomain = Server} -> {User, Server} ->
try_set_password(User, Server, Password, IQ_Rec, SubEl); try_set_password(User, Server, Password, IQ_Rec, SubEl);
_ -> _ ->
case try_register(User, Server, Password, case try_register(User, Server, Password,
@ -195,7 +204,8 @@ try_register(User, Server, Password, Source, Lang) ->
false -> false ->
{error, 'bad-request'}; {error, 'bad-request'};
_ -> _ ->
JID = exmpp_jid:make_bare_jid(User, Server), JID = exmpp_jid:make_bare_jid(User,
Server),
Access = gen_mod:get_module_opt(Server, ?MODULE, access, all), Access = gen_mod:get_module_opt(Server, ?MODULE, access, all),
case acl:match_rule(Server, Access, JID) of case acl:match_rule(Server, Access, JID) of
deny -> deny ->
@ -205,8 +215,8 @@ try_register(User, Server, Password, Source, Lang) ->
true -> true ->
case ejabberd_auth:try_register(User, Server, Password) of case ejabberd_auth:try_register(User, Server, Password) of
{atomic, ok} -> {atomic, ok} ->
ejabberd_hooks:run(user_registered, Server, ejabberd_hooks:run(user_registered, exmpp_jid:domain(JID),
[User, Server]), [exmpp_jid:node(JID), exmpp_jid:domain(JID)]),
send_welcome_message(JID), send_welcome_message(JID),
send_registration_notifications(JID), send_registration_notifications(JID),
ok; ok;
@ -233,7 +243,7 @@ try_register(User, Server, Password, Source, Lang) ->
send_welcome_message(JID) -> send_welcome_message(JID) ->
Host = JID#jid.ldomain, Host = exmpp_jid:ldomain_as_list(JID),
case gen_mod:get_module_opt(Host, ?MODULE, welcome_message, {"", ""}) of case gen_mod:get_module_opt(Host, ?MODULE, welcome_message, {"", ""}) of
{"", ""} -> {"", ""} ->
ok; ok;
@ -247,7 +257,7 @@ send_welcome_message(JID) ->
end. end.
send_registration_notifications(UJID) -> send_registration_notifications(UJID) ->
Host = UJID#jid.ldomain, Host = exmpp_jid:ldomain_as_list(UJID),
case gen_mod:get_module_opt(Host, ?MODULE, registration_watchers, []) of case gen_mod:get_module_opt(Host, ?MODULE, registration_watchers, []) of
[] -> ok; [] -> ok;
JIDs when is_list(JIDs) -> JIDs when is_list(JIDs) ->

View File

@ -53,61 +53,63 @@
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
mnesia:create_table(roster,[{disc_copies, [node()]}, mnesia:create_table(roster,[{disc_copies, [node()]},
{attributes, record_info(fields, roster)}]), {attributes, record_info(fields, roster)}]),
update_table(), update_table(),
mnesia:add_table_index(roster, us), mnesia:add_table_index(roster, us),
ejabberd_hooks:add(roster_get, Host, ejabberd_hooks:add(roster_get, HostB,
?MODULE, get_user_roster, 50), ?MODULE, get_user_roster, 50),
ejabberd_hooks:add(roster_in_subscription, Host, ejabberd_hooks:add(roster_in_subscription, HostB,
?MODULE, in_subscription, 50), ?MODULE, in_subscription, 50),
ejabberd_hooks:add(roster_out_subscription, Host, ejabberd_hooks:add(roster_out_subscription, HostB,
?MODULE, out_subscription, 50), ?MODULE, out_subscription, 50),
ejabberd_hooks:add(roster_get_subscription_lists, Host, ejabberd_hooks:add(roster_get_subscription_lists, HostB,
?MODULE, get_subscription_lists, 50), ?MODULE, get_subscription_lists, 50),
ejabberd_hooks:add(roster_get_jid_info, Host, ejabberd_hooks:add(roster_get_jid_info, HostB,
?MODULE, get_jid_info, 50), ?MODULE, get_jid_info, 50),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(anonymous_purge_hook, Host, ejabberd_hooks:add(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(resend_subscription_requests_hook, Host, ejabberd_hooks:add(resend_subscription_requests_hook, HostB,
?MODULE, get_in_pending_subscriptions, 50), ?MODULE, get_in_pending_subscriptions, 50),
ejabberd_hooks:add(webadmin_page_host, Host, ejabberd_hooks:add(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:add(webadmin_user, Host, ejabberd_hooks:add(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
?MODULE, process_iq, IQDisc). ?MODULE, process_iq, IQDisc).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(roster_get, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(roster_get, HostB,
?MODULE, get_user_roster, 50), ?MODULE, get_user_roster, 50),
ejabberd_hooks:delete(roster_in_subscription, Host, ejabberd_hooks:delete(roster_in_subscription, HostB,
?MODULE, in_subscription, 50), ?MODULE, in_subscription, 50),
ejabberd_hooks:delete(roster_out_subscription, Host, ejabberd_hooks:delete(roster_out_subscription, HostB,
?MODULE, out_subscription, 50), ?MODULE, out_subscription, 50),
ejabberd_hooks:delete(roster_get_subscription_lists, Host, ejabberd_hooks:delete(roster_get_subscription_lists, HostB,
?MODULE, get_subscription_lists, 50), ?MODULE, get_subscription_lists, 50),
ejabberd_hooks:delete(roster_get_jid_info, Host, ejabberd_hooks:delete(roster_get_jid_info, HostB,
?MODULE, get_jid_info, 50), ?MODULE, get_jid_info, 50),
ejabberd_hooks:delete(remove_user, Host, ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(anonymous_purge_hook, Host, ejabberd_hooks:delete(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(resend_subscription_requests_hook, Host, ejabberd_hooks:delete(resend_subscription_requests_hook, HostB,
?MODULE, get_in_pending_subscriptions, 50), ?MODULE, get_in_pending_subscriptions, 50),
ejabberd_hooks:delete(webadmin_page_host, Host, ejabberd_hooks:delete(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:delete(webadmin_user, Host, ejabberd_hooks:delete(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_ROSTER). ?NS_ROSTER).
process_iq(From, To, IQ_Rec) -> process_iq(From, To, IQ_Rec) ->
#jid{ldomain = LServer} = From, LServer = exmpp_jid:ldomain_as_list(From),
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> true ->
process_local_iq(From, To, IQ_Rec); process_local_iq(From, To, IQ_Rec);
@ -123,8 +125,8 @@ process_local_iq(From, To, #iq{type = set} = IQ_Rec) ->
process_iq_get(From, To, IQ_Rec) -> process_iq_get(From, To, IQ_Rec) ->
US = {From#jid.lnode, From#jid.ldomain}, US = {exmpp_jid:lnode(From), exmpp_jid:ldomain_(From)},
case catch ejabberd_hooks:run_fold(roster_get, To#jid.ldomain, [], [US]) of case catch ejabberd_hooks:run_fold(roster_get, exmpp_jid:ldomain(To), [], [US]) of
Items when is_list(Items) -> Items when is_list(Items) ->
XItems = lists:map(fun item_to_xml/1, Items), XItems = lists:map(fun item_to_xml/1, Items),
Result = #xmlel{ns = ?NS_ROSTER, name = 'query', Result = #xmlel{ns = ?NS_ROSTER, name = 'query',
@ -189,7 +191,9 @@ process_iq_set(From, To, #iq{payload = Request} = IQ_Rec) ->
process_item_set(From, To, #xmlel{} = El) -> process_item_set(From, To, #xmlel{} = El) ->
try try
JID1 = exmpp_jid:list_to_jid(exmpp_xml:get_attribute(El, 'jid', "")), JID1 = exmpp_jid:list_to_jid(exmpp_xml:get_attribute(El, 'jid', "")),
#jid{node = User, lnode = LUser, ldomain = LServer} = From, User = exmpp_jid:node(From),
LUser = exmpp_jid:lnode(From),
LServer = exmpp_jid:ldomain(From),
JID = jlib:short_jid(JID1), JID = jlib:short_jid(JID1),
LJID = jlib:short_prepd_jid(JID1), LJID = jlib:short_prepd_jid(JID1),
F = fun() -> F = fun() ->
@ -216,7 +220,7 @@ process_item_set(From, To, #xmlel{} = El) ->
%% If the item exist in shared roster, take the %% If the item exist in shared roster, take the
%% subscription information from there: %% subscription information from there:
Item3 = ejabberd_hooks:run_fold(roster_process_item, Item3 = ejabberd_hooks:run_fold(roster_process_item,
LServer, Item2, [LServer]), exmpp_jid:ldomain(From), Item2, [exmpp_jid:ldomain(From)]),
{Item, Item3} {Item, Item3}
end, end,
case mnesia:transaction(F) of case mnesia:transaction(F) of
@ -305,8 +309,8 @@ process_item_els(Item, []) ->
Item. Item.
push_item(User, Server, From, Item) -> push_item(User, Server, From, Item) when is_binary(User), is_binary(Server) ->
ejabberd_sm:route(#jid{}, ejabberd_sm:route(exmpp_jid:make_jid(),
exmpp_jid:make_bare_jid(User, Server), exmpp_jid:make_bare_jid(User, Server),
#xmlel{name = 'broadcast', children = #xmlel{name = 'broadcast', children =
[{item, [{item,
@ -317,7 +321,8 @@ push_item(User, Server, From, Item) ->
end, ejabberd_sm:get_user_resources(User, Server)). end, ejabberd_sm:get_user_resources(User, Server)).
% TODO: don't push to those who didn't load roster % TODO: don't push to those who didn't load roster
push_item(User, Server, Resource, From, Item) -> push_item(User, Server, Resource, From, Item) when is_binary(User),
is_binary(Server) ->
Request = #xmlel{ns = ?NS_ROSTER, name = 'query', Request = #xmlel{ns = ?NS_ROSTER, name = 'query',
children = [item_to_xml(Item)]}, children = [item_to_xml(Item)]},
ResIQ = exmpp_iq:set(?NS_JABBER_CLIENT, Request, ResIQ = exmpp_iq:set(?NS_JABBER_CLIENT, Request,
@ -327,11 +332,10 @@ push_item(User, Server, Resource, From, Item) ->
exmpp_jid:make_jid(User, Server, Resource), exmpp_jid:make_jid(User, Server, Resource),
ResIQ). ResIQ).
get_subscription_lists(_, User, Server) -> get_subscription_lists(_, User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), US = {User,Server},
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
case mnesia:dirty_index_read(roster, US, #roster.us) of case mnesia:dirty_index_read(roster, US, #roster.us) of
Items when is_list(Items) -> Items when is_list(Items) ->
fill_subscription_lists(Items, [], []); fill_subscription_lists(Items, [], []);
@ -370,17 +374,16 @@ in_subscription(_, User, Server, JID, Type, Reason) ->
out_subscription(User, Server, JID, Type) -> out_subscription(User, Server, JID, Type) ->
process_subscription(out, User, Server, JID, Type, <<>>). process_subscription(out, User, Server, JID, Type, <<>>).
process_subscription(Direction, User, Server, JID1, Type, Reason) -> process_subscription(Direction, User, Server, JID1, Type, Reason)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), US = {User, Server},
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
LJID = jlib:short_prepd_jid(JID1), LJID = jlib:short_prepd_jid(JID1),
F = fun() -> F = fun() ->
Item = case mnesia:read({roster, {LUser, LServer, LJID}}) of Item = case mnesia:read({roster, {User, Server, LJID}}) of
[] -> [] ->
JID = jlib:short_jid(JID1), JID = jlib:short_jid(JID1),
#roster{usj = {LUser, LServer, LJID}, #roster{usj = {User, Server, LJID},
us = US, us = US,
jid = JID}; jid = JID};
[I] -> [I] ->
@ -414,7 +417,7 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
{none, AutoReply}; {none, AutoReply};
{none, none} when Item#roster.subscription == none, {none, none} when Item#roster.subscription == none,
Item#roster.ask == in -> Item#roster.ask == in ->
mnesia:delete({roster, {LUser, LServer, LJID}}), mnesia:delete({roster, {User, Server, LJID}}),
{none, AutoReply}; {none, AutoReply};
{Subscription, Pending} -> {Subscription, Pending} ->
AskBinary = case AskMessage of AskBinary = case AskMessage of
@ -556,10 +559,11 @@ in_auto_reply(both, none, unsubscribe) -> unsubscribed;
in_auto_reply(_, _, _) -> none. in_auto_reply(_, _, _) -> none.
remove_user(User, Server) -> remove_user(User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = list_to_binary(exmpp_stringprep:nodeprep(User)),
LServer = exmpp_stringprep:nameprep(Server), LServer = list_to_binary(exmpp_stringprep:nameprep(Server)),
US = {LUser, LServer}, US = {LUser, LServer},
F = fun() -> F = fun() ->
lists:foreach(fun(R) -> lists:foreach(fun(R) ->
@ -645,9 +649,10 @@ process_item_attrs_ws(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) ->
process_item_attrs_ws(Item, []) -> process_item_attrs_ws(Item, []) ->
Item. Item.
get_in_pending_subscriptions(Ls, User, Server) -> get_in_pending_subscriptions(Ls, User, Server)
when is_binary(User), is_binary(Server) ->
JID = exmpp_jid:make_bare_jid(User, Server), JID = exmpp_jid:make_bare_jid(User, Server),
US = {JID#jid.lnode, JID#jid.ldomain}, US = {exmpp_jid:lnode(JID), exmpp_jid:ldomain(JID)},
case mnesia:dirty_index_read(roster, US, #roster.us) of case mnesia:dirty_index_read(roster, US, #roster.us) of
Result when list(Result) -> Result when list(Result) ->
Ls ++ lists:map( Ls ++ lists:map(
@ -676,12 +681,10 @@ get_in_pending_subscriptions(Ls, User, Server) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_jid_info(_, User, Server, JID) -> get_jid_info(_, User, Server, JID) when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
LJID = jlib:short_prepd_jid(JID), LJID = jlib:short_prepd_jid(JID),
case catch mnesia:dirty_read(roster, {LUser, LServer, LJID}) of case catch mnesia:dirty_read(roster, {User, Server, LJID}) of
[#roster{subscription = Subscription, groups = Groups}] -> [#roster{subscription = Subscription, groups = Groups}] ->
{Subscription, Groups}; {Subscription, Groups};
_ -> _ ->
@ -691,7 +694,7 @@ get_jid_info(_, User, Server, JID) ->
{none, []}; {none, []};
true -> true ->
case catch mnesia:dirty_read( case catch mnesia:dirty_read(
roster, {LUser, LServer, LRJID}) of roster, {User, Server, LRJID}) of
[#roster{subscription = Subscription, [#roster{subscription = Subscription,
groups = Groups}] -> groups = Groups}] ->
{Subscription, Groups}; {Subscription, Groups};

View File

@ -52,56 +52,58 @@
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
ejabberd_hooks:add(roster_get, Host, ejabberd_hooks:add(roster_get, HostB,
?MODULE, get_user_roster, 50), ?MODULE, get_user_roster, 50),
ejabberd_hooks:add(roster_in_subscription, Host, ejabberd_hooks:add(roster_in_subscription, HostB,
?MODULE, in_subscription, 50), ?MODULE, in_subscription, 50),
ejabberd_hooks:add(roster_out_subscription, Host, ejabberd_hooks:add(roster_out_subscription, HostB,
?MODULE, out_subscription, 50), ?MODULE, out_subscription, 50),
ejabberd_hooks:add(roster_get_subscription_lists, Host, ejabberd_hooks:add(roster_get_subscription_lists, HostB,
?MODULE, get_subscription_lists, 50), ?MODULE, get_subscription_lists, 50),
ejabberd_hooks:add(roster_get_jid_info, Host, ejabberd_hooks:add(roster_get_jid_info, HostB,
?MODULE, get_jid_info, 50), ?MODULE, get_jid_info, 50),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(anonymous_purge_hook, Host, ejabberd_hooks:add(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:add(resend_subscription_requests_hook, Host, ejabberd_hooks:add(resend_subscription_requests_hook, HostB,
?MODULE, get_in_pending_subscriptions, 50), ?MODULE, get_in_pending_subscriptions, 50),
ejabberd_hooks:add(webadmin_page_host, Host, ejabberd_hooks:add(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:add(webadmin_user, Host, ejabberd_hooks:add(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
?MODULE, process_iq, IQDisc). ?MODULE, process_iq, IQDisc).
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(roster_get, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(roster_get, HostB,
?MODULE, get_user_roster, 50), ?MODULE, get_user_roster, 50),
ejabberd_hooks:delete(roster_in_subscription, Host, ejabberd_hooks:delete(roster_in_subscription, HostB,
?MODULE, in_subscription, 50), ?MODULE, in_subscription, 50),
ejabberd_hooks:delete(roster_out_subscription, Host, ejabberd_hooks:delete(roster_out_subscription, HostB,
?MODULE, out_subscription, 50), ?MODULE, out_subscription, 50),
ejabberd_hooks:delete(roster_get_subscription_lists, Host, ejabberd_hooks:delete(roster_get_subscription_lists, HostB,
?MODULE, get_subscription_lists, 50), ?MODULE, get_subscription_lists, 50),
ejabberd_hooks:delete(roster_get_jid_info, Host, ejabberd_hooks:delete(roster_get_jid_info, HostB,
?MODULE, get_jid_info, 50), ?MODULE, get_jid_info, 50),
ejabberd_hooks:delete(remove_user, Host, ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(anonymous_purge_hook, Host, ejabberd_hooks:delete(anonymous_purge_hook, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
ejabberd_hooks:delete(resend_subscription_requests_hook, Host, ejabberd_hooks:delete(resend_subscription_requests_hook, HostB,
?MODULE, get_in_pending_subscriptions, 50), ?MODULE, get_in_pending_subscriptions, 50),
ejabberd_hooks:delete(webadmin_page_host, Host, ejabberd_hooks:delete(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:delete(webadmin_user, Host, ejabberd_hooks:delete(webadmin_user, HostB,
?MODULE, webadmin_user, 50), ?MODULE, webadmin_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER). gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER).
process_iq(From, To, IQ_Rec) -> process_iq(From, To, IQ_Rec) ->
#jid{ldomain = LServer} = From, LServer = exmpp_jid:ldomain_as_list(From),
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> true ->
process_local_iq(From, To, IQ_Rec); process_local_iq(From, To, IQ_Rec);
@ -117,8 +119,8 @@ process_local_iq(From, To, #iq{type = set} = IQ_Rec) ->
process_iq_get(From, To, IQ_Rec) -> process_iq_get(From, To, IQ_Rec) ->
US = {From#jid.lnode, From#jid.ldomain}, US = {exmpp_jid:lnode(From), exmpp_jid:ldomain(From)},
case catch ejabberd_hooks:run_fold(roster_get, To#jid.ldomain, [], [US]) of case catch ejabberd_hooks:run_fold(roster_get, exmpp_jid:ldomain(To), [], [US]) of
Items when is_list(Items) -> Items when is_list(Items) ->
XItems = lists:map(fun item_to_xml/1, Items), XItems = lists:map(fun item_to_xml/1, Items),
Result = #xmlel{ns = ?NS_ROSTER, name = 'query', Result = #xmlel{ns = ?NS_ROSTER, name = 'query',
@ -136,13 +138,14 @@ get_user_roster(Acc, {LUser, LServer}) ->
true true
end, Items) ++ Acc. end, Items) ++ Acc.
get_roster(LUser, LServer) -> get_roster(LUser, LServer) when is_binary(LUser), is_binary(LServer)->
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(binary_to_list(LUser)),
case catch odbc_queries:get_roster(LServer, Username) of DomainString = binary_to_list(LServer),
case catch odbc_queries:get_roster(DomainString, Username) of
{selected, ["username", "jid", "nick", "subscription", "ask", {selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"], "askmessage", "server", "subscribe", "type"],
Items} when is_list(Items) -> Items} when is_list(Items) ->
JIDGroups = case catch odbc_queries:get_roster_jid_groups(LServer, Username) of JIDGroups = case catch odbc_queries:get_roster_jid_groups(DomainString, Username) of
{selected, ["jid","grp"], JGrps} {selected, ["jid","grp"], JGrps}
when is_list(JGrps) -> when is_list(JGrps) ->
JGrps; JGrps;
@ -214,7 +217,8 @@ process_iq_set(From, To, #iq{payload = Request} = IQ_Rec) ->
process_item_set(From, To, #xmlel{} = El) -> process_item_set(From, To, #xmlel{} = El) ->
try try
JID1 = exmpp_jid:list_to_jid(exmpp_xml:get_attribute(El, 'jid', "")), JID1 = exmpp_jid:list_to_jid(exmpp_xml:get_attribute(El, 'jid', "")),
#jid{node = User, lnode = LUser, ldomain = LServer} = From, LUser = exmpp_jid:lnode_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
{U0, S0, R0} = LJID = jlib:short_prepd_jid(JID1), {U0, S0, R0} = LJID = jlib:short_prepd_jid(JID1),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(U0, S0, R0)), SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(U0, S0, R0)),
@ -229,7 +233,7 @@ process_item_set(From, To, #xmlel{} = El) ->
us = {LUser, LServer}, us = {LUser, LServer},
jid = LJID}; jid = LJID};
[I] -> [I] ->
R = raw_to_record(LServer, I), R = raw_to_record(exmpp_jid:ldomain(From), I),
case R of case R of
%% Bad JID in database: %% Bad JID in database:
error -> error ->
@ -257,12 +261,12 @@ process_item_set(From, To, #xmlel{} = El) ->
%% If the item exist in shared roster, take the %% If the item exist in shared roster, take the
%% subscription information from there: %% subscription information from there:
Item3 = ejabberd_hooks:run_fold(roster_process_item, Item3 = ejabberd_hooks:run_fold(roster_process_item,
LServer, Item2, [LServer]), exmpp_jid:ldomain(From), Item2, [exmpp_jid:ldomain(From)]),
{Item, Item3} {Item, Item3}
end, end,
case odbc_queries:sql_transaction(LServer, F) of case odbc_queries:sql_transaction(LServer, F) of
{atomic, {OldItem, Item}} -> {atomic, {OldItem, Item}} ->
push_item(User, LServer, To, Item), push_item(exmpp_jid:node(From), exmpp_jid:ldomain(From), To, Item),
case Item#roster.subscription of case Item#roster.subscription of
remove -> remove ->
IsTo = case OldItem#roster.subscription of IsTo = case OldItem#roster.subscription of
@ -340,8 +344,8 @@ process_item_els(Item, []) ->
Item. Item.
push_item(User, Server, From, Item) -> push_item(User, Server, From, Item) when is_binary(User), is_binary(Server) ->
ejabberd_sm:route(#jid{}, ejabberd_sm:route(exmpp_jid:make_jid(),
exmpp_jid:make_bare_jid(User, Server), exmpp_jid:make_bare_jid(User, Server),
#xmlel{name = 'broadcast', children = #xmlel{name = 'broadcast', children =
[{item, [{item,
@ -362,16 +366,17 @@ push_item(User, Server, Resource, From, Item) ->
exmpp_jid:make_jid(User, Server, Resource), exmpp_jid:make_jid(User, Server, Resource),
ResIQ). ResIQ).
get_subscription_lists(_, User, Server) -> get_subscription_lists(_, User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_roster(LServer, Username) of case catch odbc_queries:get_roster(LServer, Username) of
{selected, ["username", "jid", "nick", "subscription", "ask", {selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"], "askmessage", "server", "subscribe", "type"],
Items} when is_list(Items) -> Items} when is_list(Items) ->
fill_subscription_lists(LServer, Items, [], []); fill_subscription_lists(Server, Items, [], []);
_ -> _ ->
{[], []} {[], []}
end end
@ -414,10 +419,11 @@ in_subscription(_, User, Server, JID, Type, Reason) ->
out_subscription(User, Server, JID, Type) -> out_subscription(User, Server, JID, Type) ->
process_subscription(out, User, Server, JID, Type, <<>>). process_subscription(out, User, Server, JID, Type, <<>>).
process_subscription(Direction, User, Server, JID1, Type, Reason) -> process_subscription(Direction, User, Server, JID1, Type, Reason)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
{N0,D0,R0} = LJID = jlib:short_prepd_jid(JID1), {N0,D0,R0} = LJID = jlib:short_prepd_jid(JID1),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(N0,D0,R0)), SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(N0,D0,R0)),
@ -430,7 +436,7 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
[I]} -> [I]} ->
%% raw_to_record can return error, but %% raw_to_record can return error, but
%% jlib_to_string would fail before this point %% jlib_to_string would fail before this point
R = raw_to_record(LServer, I), R = raw_to_record(list_to_binary(LServer), I),
Groups = Groups =
case odbc_queries:get_roster_groups(LServer, Username, SJID) of case odbc_queries:get_roster_groups(LServer, Username, SJID) of
{selected, ["grp"], JGrps} when is_list(JGrps) -> {selected, ["grp"], JGrps} when is_list(JGrps) ->
@ -443,8 +449,8 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
["username", "jid", "nick", "subscription", "ask", ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"], "askmessage", "server", "subscribe", "type"],
[]} -> []} ->
#roster{usj = {LUser, LServer, LJID}, #roster{usj = {list_to_binary(LUser), list_to_binary(LServer), LJID},
us = {LUser, LServer}, us = {list_to_binary(LUser), list_to_binary(LServer)},
jid = LJID} jid = LJID}
end, end,
NewState = case Direction of NewState = case Direction of
@ -619,7 +625,7 @@ in_auto_reply(both, none, unsubscribe) -> unsubscribed;
in_auto_reply(_, _, _) -> none. in_auto_reply(_, _, _) -> none.
remove_user(User, Server) -> remove_user(User, Server) when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
@ -705,10 +711,11 @@ process_item_attrs_ws(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) ->
process_item_attrs_ws(Item, []) -> process_item_attrs_ws(Item, []) ->
Item. Item.
get_in_pending_subscriptions(Ls, User, Server) -> get_in_pending_subscriptions(Ls, User, Server)
when is_binary(User), is_binary(Server) ->
JID = exmpp_jid:make_bare_jid(User, Server), JID = exmpp_jid:make_bare_jid(User, Server),
LUser = JID#jid.lnode, LUser = exmpp_jid:lnode_as_list(JID),
LServer = JID#jid.ldomain, LServer = exmpp_jid:ldomain_as_list(JID),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_roster(LServer, Username) of case catch odbc_queries:get_roster(LServer, Username) of
{selected, ["username", "jid", "nick", "subscription", "ask", {selected, ["username", "jid", "nick", "subscription", "ask",
@ -726,7 +733,7 @@ get_in_pending_subscriptions(Ls, User, Server) ->
end, end,
lists:flatmap( lists:flatmap(
fun(I) -> fun(I) ->
case raw_to_record(LServer, I) of case raw_to_record(exmpp_jid:ldomain(JID), I) of
%% Bad JID in database: %% Bad JID in database:
error -> error ->
[]; [];
@ -745,12 +752,12 @@ get_in_pending_subscriptions(Ls, User, Server) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% JID is #jid record, because it's used latter on for both short_prepd_jid %% JID is jid() record, because it's used latter on for both short_prepd_jid
%% and short_prepd_bare_jid %% and short_prepd_bare_jid
get_jid_info(_, User, Server, JID) -> get_jid_info(_, User, Server, JID) when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
LJID = {N, D, R} = jlib:short_prepd_jid(JID), LJID = {N, D, R} = jlib:short_prepd_jid(JID),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(N, D, R)), SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(N, D, R)),
@ -805,7 +812,7 @@ get_jid_info(_, User, Server, JID) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
raw_to_record(LServer, {User, SJID, Nick, SSubscription, SAsk, SAskMessage, raw_to_record(LServer, {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
_SServer, _SSubscribe, _SType}) -> _SServer, _SSubscribe, _SType}) when is_binary(LServer) ->
try try
JID = exmpp_jid:list_to_jid(SJID), JID = exmpp_jid:list_to_jid(SJID),
LJID = jlib:short_prepd_jid(JID), LJID = jlib:short_prepd_jid(JID),
@ -823,8 +830,9 @@ raw_to_record(LServer, {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
"I" -> in; "I" -> in;
_ -> none _ -> none
end, end,
#roster{usj = {User, LServer, LJID}, UserB = list_to_binary(User),
us = {User, LServer}, #roster{usj = {UserB, LServer, LJID},
us = {UserB, LServer},
jid = LJID, jid = LJID,
name = Nick, name = Nick,
subscription = Subscription, subscription = Subscription,
@ -841,7 +849,7 @@ record_to_string(#roster{us = {User, _Server},
subscription = Subscription, subscription = Subscription,
ask = Ask, ask = Ask,
askmessage = AskMessage}) -> askmessage = AskMessage}) ->
Username = ejabberd_odbc:escape(User), Username = ejabberd_odbc:escape(binary_to_list(User)),
{U, S, R} = JID, {U, S, R} = JID,
SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(U, S, R)), SJID = ejabberd_odbc:escape(exmpp_jid:jid_to_list(U, S, R)),
Nick = ejabberd_odbc:escape(Name), Nick = ejabberd_odbc:escape(Name),

View File

@ -39,35 +39,37 @@
-include("ejabberd.hrl"). -include("ejabberd.hrl").
start(Host, _Opts) -> start(Host, _Opts) ->
ejabberd_hooks:add(user_send_packet, Host, HostB = list_to_binary(Host),
ejabberd_hooks:add(user_send_packet, HostB,
?MODULE, log_user_send, 50), ?MODULE, log_user_send, 50),
ejabberd_hooks:add(user_receive_packet, Host, ejabberd_hooks:add(user_receive_packet, HostB,
?MODULE, log_user_receive, 50), ?MODULE, log_user_receive, 50),
ok. ok.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(user_send_packet, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(user_send_packet, HostB,
?MODULE, log_user_send, 50), ?MODULE, log_user_send, 50),
ejabberd_hooks:delete(user_receive_packet, Host, ejabberd_hooks:delete(user_receive_packet, HostB,
?MODULE, log_user_receive, 50), ?MODULE, log_user_receive, 50),
ok. ok.
log_user_send(From, To, Packet) -> log_user_send(From, To, Packet) ->
log_packet(From, To, Packet, From#jid.ldomain). log_packet(From, To, Packet, exmpp_jid:ldomain_as_list(From)).
log_user_receive(_JID, From, To, Packet) -> log_user_receive(_JID, From, To, Packet) ->
log_packet(From, To, Packet, To#jid.ldomain). log_packet(From, To, Packet, exmpp_jid:ldomain_as_list(To)).
log_packet(From, To, Packet, Host) -> log_packet(From, To, Packet, Host) ->
Loggers = gen_mod:get_module_opt(Host, ?MODULE, loggers, []), Loggers = gen_mod:get_module_opt(Host, ?MODULE, loggers, []),
ServerJID = #jid{domain = Host, ldomain = Host}, ServerJID = exmpp_jid:make_bare_jid(Host),
FixedPacket = exmpp_stanza:set_jids(Packet, From, To), FixedPacket = exmpp_stanza:set_jids(Packet, From, To),
lists:foreach( lists:foreach(
fun(Logger) -> fun(Logger) ->
ejabberd_router:route( ejabberd_router:route(
ServerJID, ServerJID,
#jid{domain = Logger, ldomain = Logger}, exmpp_jid:make_bare_jid(Logger),
#xmlel{name = 'route', children = [FixedPacket]}) #xmlel{name = 'route', children = [FixedPacket]})
end, Loggers). end, Loggers).

View File

@ -60,6 +60,7 @@
-record(sr_user, {us, group_host}). -record(sr_user, {us, group_host}).
start(Host, _Opts) -> start(Host, _Opts) ->
HostB = list_to_binary(Host),
mnesia:create_table(sr_group, mnesia:create_table(sr_group,
[{disc_copies, [node()]}, [{disc_copies, [node()]},
{attributes, record_info(fields, sr_group)}]), {attributes, record_info(fields, sr_group)}]),
@ -68,47 +69,48 @@ start(Host, _Opts) ->
{type, bag}, {type, bag},
{attributes, record_info(fields, sr_user)}]), {attributes, record_info(fields, sr_user)}]),
mnesia:add_table_index(sr_user, group_host), mnesia:add_table_index(sr_user, group_host),
ejabberd_hooks:add(webadmin_menu_host, Host, ejabberd_hooks:add(webadmin_menu_host, HostB,
?MODULE, webadmin_menu, 70), ?MODULE, webadmin_menu, 70),
ejabberd_hooks:add(webadmin_page_host, Host, ejabberd_hooks:add(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:add(roster_get, Host, ejabberd_hooks:add(roster_get, HostB,
?MODULE, get_user_roster, 70), ?MODULE, get_user_roster, 70),
ejabberd_hooks:add(roster_in_subscription, Host, ejabberd_hooks:add(roster_in_subscription, HostB,
?MODULE, in_subscription, 30), ?MODULE, in_subscription, 30),
ejabberd_hooks:add(roster_out_subscription, Host, ejabberd_hooks:add(roster_out_subscription, HostB,
?MODULE, out_subscription, 30), ?MODULE, out_subscription, 30),
ejabberd_hooks:add(roster_get_subscription_lists, Host, ejabberd_hooks:add(roster_get_subscription_lists, HostB,
?MODULE, get_subscription_lists, 70), ?MODULE, get_subscription_lists, 70),
ejabberd_hooks:add(roster_get_jid_info, Host, ejabberd_hooks:add(roster_get_jid_info, HostB,
?MODULE, get_jid_info, 70), ?MODULE, get_jid_info, 70),
ejabberd_hooks:add(roster_process_item, Host, ejabberd_hooks:add(roster_process_item, HostB,
?MODULE, process_item, 50), ?MODULE, process_item, 50),
ejabberd_hooks:add(user_registered, Host, ejabberd_hooks:add(user_registered, HostB,
?MODULE, user_registered, 50). ?MODULE, user_registered, 50).
%%ejabberd_hooks:add(remove_user, Host, %%ejabberd_hooks:add(remove_user, HostB,
%% ?MODULE, remove_user, 50), %% ?MODULE, remove_user, 50),
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(webadmin_menu_host, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(webadmin_menu_host, HostB,
?MODULE, webadmin_menu, 70), ?MODULE, webadmin_menu, 70),
ejabberd_hooks:delete(webadmin_page_host, Host, ejabberd_hooks:delete(webadmin_page_host, HostB,
?MODULE, webadmin_page, 50), ?MODULE, webadmin_page, 50),
ejabberd_hooks:delete(roster_get, Host, ejabberd_hooks:delete(roster_get, HostB,
?MODULE, get_user_roster, 70), ?MODULE, get_user_roster, 70),
ejabberd_hooks:delete(roster_in_subscription, Host, ejabberd_hooks:delete(roster_in_subscription, HostB,
?MODULE, in_subscription, 30), ?MODULE, in_subscription, 30),
ejabberd_hooks:delete(roster_out_subscription, Host, ejabberd_hooks:delete(roster_out_subscription, HostB,
?MODULE, out_subscription, 30), ?MODULE, out_subscription, 30),
ejabberd_hooks:delete(roster_get_subscription_lists, Host, ejabberd_hooks:delete(roster_get_subscription_lists, HostB,
?MODULE, get_subscription_lists, 70), ?MODULE, get_subscription_lists, 70),
ejabberd_hooks:delete(roster_get_jid_info, Host, ejabberd_hooks:delete(roster_get_jid_info, HostB,
?MODULE, get_jid_info, 70), ?MODULE, get_jid_info, 70),
ejabberd_hooks:delete(roster_process_item, Host, ejabberd_hooks:delete(roster_process_item, HostB,
?MODULE, process_item, 50), ?MODULE, process_item, 50),
ejabberd_hooks:delete(user_registered, Host, ejabberd_hooks:delete(user_registered, HostB,
?MODULE, user_registered, 50). ?MODULE, user_registered, 50).
%%ejabberd_hooks:delete(remove_user, Host, %%ejabberd_hooks:delete(remove_user, HostB,
%% ?MODULE, remove_user, 50), %% ?MODULE, remove_user, 50),
@ -252,10 +254,11 @@ set_item(User, Server, Resource, Item) ->
ResIQ). ResIQ).
get_subscription_lists({F, T}, User, Server) -> get_subscription_lists({F, T}, User, Server)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
US = {LUser, LServer}, US = {LUser, LServer},
DisplayedGroups = get_user_displayed_groups(US), DisplayedGroups = get_user_displayed_groups(US),
SRUsers = SRUsers =
@ -271,10 +274,11 @@ get_subscription_lists({F, T}, User, Server) ->
{[], []} {[], []}
end. end.
get_jid_info({Subscription, Groups}, User, Server, JID) -> get_jid_info({Subscription, Groups}, User, Server, JID)
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = binary_to_list(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = binary_to_list(Server),
US = {LUser, LServer}, US = {LUser, LServer},
{U1, S1, _} = jlib:short_prepd_jid(JID), {U1, S1, _} = jlib:short_prepd_jid(JID),
US1 = {U1, S1}, US1 = {U1, S1},
@ -574,7 +578,7 @@ push_item(User, Server, From, Item) ->
fun(Resource) -> fun(Resource) ->
JID = exmpp_jid:make_jid(User, Server, Resource), JID = exmpp_jid:make_jid(User, Server, Resource),
ejabberd_router:route(JID, JID, Stanza) ejabberd_router:route(JID, JID, Stanza)
end, ejabberd_sm:get_user_resources(User, Server)). end, ejabberd_sm:get_user_resources(list_to_binary(User), list_to_binary(Server))).
item_to_xml(Item) -> item_to_xml(Item) ->
{U, S, R} = Item#roster.jid, {U, S, R} = Item#roster.jid,
@ -807,7 +811,7 @@ shared_roster_group_parse_query(Host, Group, Query) ->
_ -> _ ->
try try
JID = exmpp_jid:list_to_jid(SJID), JID = exmpp_jid:list_to_jid(SJID),
[{JID#jid.lnode, JID#jid.ldomain} | USs] [{exmpp_jid:lnode_as_list(JID), exmpp_jid:ldomain_as_list(JID)} | USs]
catch catch
_ -> _ ->
error error

View File

@ -49,7 +49,7 @@ process_local_iq(_From, To, #iq{type = get,
Node = string:tokens(exmpp_xml:get_attribute(SubEl, 'node', ""), "/"), Node = string:tokens(exmpp_xml:get_attribute(SubEl, 'node', ""), "/"),
Names = get_names(exmpp_xml:get_child_elements(SubEl), []), Names = get_names(exmpp_xml:get_child_elements(SubEl), []),
case get_local_stats(To#jid.domain, Node, Names) of case get_local_stats(exmpp_jid:domain_as_list(To), Node, Names) of
{result, Res} -> {result, Res} ->
Result = #xmlel{ns = XMLNS, name = 'query', children = Res}, Result = #xmlel{ns = XMLNS, name = 'query', children = Res},
exmpp_iq:result(IQ_Rec, Result); exmpp_iq:result(IQ_Rec, Result);
@ -130,7 +130,7 @@ get_local_stats(_Server, _, _) ->
get_local_stat(Server, [], Name) when Name == "users/online" -> get_local_stat(Server, [], Name) when Name == "users/online" ->
case catch ejabberd_sm:get_vh_session_list(Server) of case catch ejabberd_sm:get_vh_session_list(list_to_binary(Server)) of
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
?STATERR("500", "Internal Server Error"); ?STATERR("500", "Internal Server Error");
Users -> Users ->

View File

@ -62,6 +62,7 @@
-define(PROCNAME, ejabberd_mod_vcard). -define(PROCNAME, ejabberd_mod_vcard).
start(Host, Opts) -> start(Host, Opts) ->
HostB = list_to_binary(Host),
mnesia:create_table(vcard, [{disc_only_copies, [node()]}, mnesia:create_table(vcard, [{disc_only_copies, [node()]},
{attributes, record_info(fields, vcard)}]), {attributes, record_info(fields, vcard)}]),
mnesia:create_table(vcard_search, mnesia:create_table(vcard_search,
@ -81,14 +82,14 @@ start(Host, Opts) ->
mnesia:add_table_index(vcard_search, lorgname), mnesia:add_table_index(vcard_search, lorgname),
mnesia:add_table_index(vcard_search, lorgunit), mnesia:add_table_index(vcard_search, lorgunit),
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
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_VCARD, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
?MODULE, process_local_iq, IQDisc), ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_sm_features, HostB, ?MODULE, get_sm_features, 50),
MyHost = gen_mod:get_opt_host(Host, Opts, "vjud.@HOST@"), MyHost = gen_mod:get_opt_host(Host, Opts, "vjud.@HOST@"),
Search = gen_mod:get_opt(search, Opts, true), Search = gen_mod:get_opt(search, Opts, true),
register(gen_mod:get_module_proc(Host, ?PROCNAME), register(gen_mod:get_module_proc(Host, ?PROCNAME),
@ -122,13 +123,14 @@ loop(Host, ServerHost) ->
end. end.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
?NS_VCARD), ?NS_VCARD),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_VCARD), ?NS_VCARD),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:delete(disco_sm_features, HostB, ?MODULE, get_sm_features, 50),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop, Proc ! stop,
{wait, Proc}. {wait, Proc}.
@ -167,7 +169,8 @@ process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) ->
process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) -> process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) ->
#jid{lnode = LUser, ldomain = LServer} = To, LUser = exmpp_jid:lnode_as_list(To),
LServer = exmpp_jid:ldomain_as_list(To),
US = {LUser, LServer}, US = {LUser, LServer},
F = fun() -> F = fun() ->
mnesia:read({vcard, US}) mnesia:read({vcard, US})
@ -187,7 +190,8 @@ process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) ->
exmpp_iq:result(IQ_Rec) exmpp_iq:result(IQ_Rec)
end; end;
process_sm_iq(From, _To, #iq{type = set, payload = Request} = IQ_Rec) -> process_sm_iq(From, _To, #iq{type = set, payload = Request} = IQ_Rec) ->
#jid{node = User, ldomain = LServer} = From, User = exmpp_jid:node_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> true ->
set_vcard(User, LServer, Request), set_vcard(User, LServer, Request),
@ -307,7 +311,8 @@ set_vcard(User, LServer, VCARD) ->
do_route(ServerHost, From, To, Packet) -> do_route(ServerHost, From, To, Packet) ->
#jid{node = User, resource = Resource} = To, User = exmpp_jid:node(To),
Resource = exmpp_jid:resource(To),
if if
(User /= undefined) or (Resource /= undefined) -> (User /= undefined) or (Resource /= undefined) ->
Err = exmpp_stanza:reply_with_error(Packet, 'service-unavailable'), Err = exmpp_stanza:reply_with_error(Packet, 'service-unavailable'),
@ -651,7 +656,7 @@ reindex_vcards() ->
mnesia:transaction(F). mnesia:transaction(F).
remove_user(User, Server) -> remove_user(User, Server) when is_binary(User), is_binary(Server) ->
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer}, US = {LUser, LServer},

View File

@ -155,7 +155,7 @@ terminate(_Reason, State) ->
Host = State#state.serverhost, Host = State#state.serverhost,
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:delete(disco_sm_features, list_to_binary(Host), ?MODULE, get_sm_features, 50),
case State#state.search of case State#state.search of
true -> true ->
ejabberd_router:unregister_route(State#state.myhost); ejabberd_router:unregister_route(State#state.myhost);
@ -174,7 +174,8 @@ init([Host, Opts]) ->
?MODULE, process_local_iq, IQDisc), ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_sm_features,
list_to_binary(Host), ?MODULE, get_sm_features, 50),
eldap_pool:start_link(State#state.eldap_id, eldap_pool:start_link(State#state.eldap_id,
State#state.servers, State#state.servers,
State#state.backups, State#state.backups,
@ -234,7 +235,8 @@ process_local_iq(_From, _To, #iq{type = get, lang = Lang} = IQ_Rec) ->
process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) -> process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) ->
exmpp_iq:error(IQ_Rec, 'not-allowed'). exmpp_iq:error(IQ_Rec, 'not-allowed').
process_sm_iq(_From, #jid{ldomain=LServer} = To, #iq{} = IQ_Rec) -> process_sm_iq(_From, To, #iq{} = IQ_Rec) ->
LServer = exmpp_jid:ldomain_as_list(To),
case catch process_vcard_ldap(To, IQ_Rec, LServer) of case catch process_vcard_ldap(To, IQ_Rec, LServer) of
{'EXIT', _} -> {'EXIT', _} ->
exmpp_iq:error(IQ_Rec, 'internal-server-error'); exmpp_iq:error(IQ_Rec, 'internal-server-error');
@ -248,7 +250,7 @@ process_vcard_ldap(To, IQ_Rec, Server) ->
set -> set ->
exmpp_iq:error(IQ_Rec, 'not-allowed'); exmpp_iq:error(IQ_Rec, 'not-allowed');
get -> get ->
#jid{lnode = LUser} = To, LUser = exmpp_jid:lnode_as_list(To),
LServer = State#state.serverhost, LServer = State#state.serverhost,
case ejabberd_auth:is_user_exists(LUser, LServer) of case ejabberd_auth:is_user_exists(LUser, LServer) of
true -> true ->
@ -402,7 +404,8 @@ do_route(State, From, To, Packet) ->
spawn(?MODULE, route, [State, From, To, Packet]). spawn(?MODULE, route, [State, From, To, Packet]).
route(State, From, To, Packet) -> route(State, From, To, Packet) ->
#jid{node = User, resource = Resource} = To, User = exmpp_jid:node(To),
Resource = exmpp_jid:resource(To),
if if
(User /= undefined) or (Resource /= undefined) -> (User /= undefined) or (Resource /= undefined) ->
Err = exmpp_stanza:reply_with_error(Packet, 'service-unavailable'), Err = exmpp_stanza:reply_with_error(Packet, 'service-unavailable'),

View File

@ -45,14 +45,15 @@
-define(PROCNAME, ejabberd_mod_vcard). -define(PROCNAME, ejabberd_mod_vcard).
start(Host, Opts) -> start(Host, Opts) ->
ejabberd_hooks:add(remove_user, Host, HostB = list_to_binary(Host),
ejabberd_hooks:add(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
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_VCARD, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
?MODULE, process_local_iq, IQDisc), ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_sm_features, HostB, ?MODULE, get_sm_features, 50),
MyHost = gen_mod:get_opt_host(Host, Opts, "vjud.@HOST@"), MyHost = gen_mod:get_opt_host(Host, Opts, "vjud.@HOST@"),
Search = gen_mod:get_opt(search, Opts, true), Search = gen_mod:get_opt(search, Opts, true),
register(gen_mod:get_module_proc(Host, ?PROCNAME), register(gen_mod:get_module_proc(Host, ?PROCNAME),
@ -86,11 +87,12 @@ loop(Host, ServerHost) ->
end. end.
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, HostB = list_to_binary(Host),
ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:delete(disco_sm_features, HostB, ?MODULE, get_sm_features, 50),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop, Proc ! stop,
{wait, Proc}. {wait, Proc}.
@ -129,12 +131,14 @@ process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) ->
process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) -> process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) ->
#jid{lnode = LUser, ldomain = LServer} = To, LUser = exmpp_jid:lnode_as_list(To),
LServer = exmpp_jid:ldomain_as_list(To),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_vcard(LServer, Username) of case catch odbc_queries:get_vcard(LServer, Username) of
{selected, ["vcard"], [{SVCARD}]} -> {selected, ["vcard"], [{SVCARD}]} ->
try exmpp_xml:parse_document(SVCARD, try exmpp_xml:parse_document(SVCARD,
[names_as_atom]) of [names_as_atom, {check_elems, xmpp},
{check_nss,xmpp}, {check_attrs,xmpp}]) of
[VCARD] -> [VCARD] ->
exmpp_iq:result(IQ_Rec, VCARD) exmpp_iq:result(IQ_Rec, VCARD)
catch catch
@ -148,7 +152,8 @@ process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) ->
exmpp_iq:error(IQ_Rec, 'internal-server-error') exmpp_iq:error(IQ_Rec, 'internal-server-error')
end; end;
process_sm_iq(From, _To, #iq{type = set, payload = Request} = IQ_Rec) -> process_sm_iq(From, _To, #iq{type = set, payload = Request} = IQ_Rec) ->
#jid{node = User, ldomain = LServer} = From, User = exmpp_jid:node_as_list(From),
LServer = exmpp_jid:ldomain_as_list(From),
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> true ->
set_vcard(User, LServer, Request), set_vcard(User, LServer, Request),
@ -277,7 +282,8 @@ set_vcard(User, LServer, VCARD) ->
]}]). ]}]).
do_route(ServerHost, From, To, Packet) -> do_route(ServerHost, From, To, Packet) ->
#jid{node = User, resource = Resource} = To, User = exmpp_jid:node(To),
Resource = exmpp_jid:resource(To),
if if
(User /= undefined) or (Resource /= undefined) -> (User /= undefined) or (Resource /= undefined) ->
Err = exmpp_stanza:reply_with_error(Packet, 'service-unavailable'), Err = exmpp_stanza:reply_with_error(Packet, 'service-unavailable'),
@ -615,7 +621,7 @@ make_val(Match, Field, Val) ->
% mnesia:transaction(F). % mnesia:transaction(F).
remove_user(User, Server) -> remove_user(User, Server) when is_binary(User), is_binary(server) ->
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),

View File

@ -53,7 +53,7 @@ process_local_iq(_From, To, #iq{type = Type} = IQ_Rec) ->
set -> set ->
exmpp_iq:error(IQ_Rec, 'not-allowed'); exmpp_iq:error(IQ_Rec, 'not-allowed');
get -> get ->
Host = To#jid.domain, Host = exmpp_jid:domain_as_list(To),
OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os, true) of OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os, true) of
true -> [get_os()]; true -> [get_os()];
false -> [] false -> []