diff options
Diffstat (limited to 'src/mod_announce.erl')
-rw-r--r-- | src/mod_announce.erl | 180 |
1 files changed, 150 insertions, 30 deletions
diff --git a/src/mod_announce.erl b/src/mod_announce.erl index b8164aab0..495eac260 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -20,8 +20,8 @@ -include("ejabberd.hrl"). -include("jlib.hrl"). --record(motd, {id, packet}). --record(motd_users, {luser, dummy = []}). +-record(motd, {server, packet}). +-record(motd_users, {us, dummy = []}). -define(PROCNAME, ejabberd_announce). @@ -30,6 +30,7 @@ start(_) -> {attributes, record_info(fields, motd)}]), mnesia:create_table(motd_users, [{disc_copies, [node()]}, {attributes, record_info(fields, motd_users)}]), + update_tables(), ejabberd_hooks:add(local_send_to_resource_hook, ?MODULE, announce, 50), ejabberd_hooks:add(user_available_hook, @@ -47,6 +48,9 @@ loop() -> {announce_online, From, To, Packet} -> announce_online(From, To, Packet), loop(); + {announce_all_hosts_online, From, To, Packet} -> + announce_all_hosts_online(From, To, Packet), + loop(); {announce_motd, From, To, Packet} -> announce_motd(From, To, Packet), loop(); @@ -79,6 +83,9 @@ announce(From, To, Packet) -> {"announce/online", "message"} -> ?PROCNAME ! {announce_online, From, To, Packet}, stop; + {"announce/all-hosts/online", "message"} -> + ?PROCNAME ! {announce_all_hosts_online, From, To, Packet}, + stop; {"announce/motd", "message"} -> ?PROCNAME ! {announce_motd, From, To, Packet}, stop; @@ -102,13 +109,12 @@ announce_all(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); allow -> - Server = ?MYNAME, - Local = jlib:make_jid("", Server, ""), + Local = jlib:make_jid("", To#jid.server, ""), lists:foreach( - fun(U) -> - Dest = jlib:make_jid(U, Server, ""), + fun({User, Server}) -> + Dest = jlib:make_jid(User, Server, ""), ejabberd_router:route(Local, Dest, Packet) - end, ejabberd_auth:dirty_get_registered_users()) + end, ejabberd_auth:get_vh_registered_users(To#jid.lserver)) end. announce_online(From, To, Packet) -> @@ -118,15 +124,28 @@ announce_online(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); allow -> - announce_online1(ejabberd_sm:dirty_get_sessions_list(), Packet) + announce_online1(ejabberd_sm:get_vh_session_list(To#jid.lserver), + To#jid.server, + Packet) end. -announce_online1(Sessions, Packet) -> - Server = ?MYNAME, +announce_all_hosts_online(From, To, Packet) -> + Access = gen_mod:get_module_opt(?MODULE, access, none), + case acl:match_rule(Access, From) of + deny -> + Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), + ejabberd_router:route(To, From, Err); + allow -> + announce_online1(ejabberd_sm:dirty_get_sessions_list(), + To#jid.server, + Packet) + end. + +announce_online1(Sessions, Server, Packet) -> Local = jlib:make_jid("", Server, ""), lists:foreach( - fun({U, R}) -> - Dest = jlib:make_jid(U, Server, R), + fun({U, S, R}) -> + Dest = jlib:make_jid(U, S, R), ejabberd_router:route(Local, Dest, Packet) end, Sessions). @@ -137,13 +156,13 @@ announce_motd(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); allow -> - announce_motd_update(Packet), - Sessions = ejabberd_sm:dirty_get_sessions_list(), - announce_online1(Sessions, Packet), + announce_motd_update(To#jid.lserver, Packet), + Sessions = ejabberd_sm:get_vh_session_list(To#jid.lserver), + announce_online1(Sessions, To#jid.server, Packet), F = fun() -> lists:foreach( - fun({U, _R}) -> - mnesia:write(#motd_users{luser = U}) + fun({U, S, _R}) -> + mnesia:write(#motd_users{us = {U, S}}) end, Sessions) end, mnesia:transaction(F) @@ -156,13 +175,13 @@ announce_motd_update(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); allow -> - announce_motd_update(Packet) + announce_motd_update(To#jid.lserver, Packet) end. -announce_motd_update(Packet) -> - announce_motd_delete(), +announce_motd_update(LServer, Packet) -> + announce_motd_delete(LServer), F = fun() -> - mnesia:write(#motd{id = motd, packet = Packet}) + mnesia:write(#motd{server = LServer, packet = Packet}) end, mnesia:transaction(F). @@ -173,24 +192,36 @@ announce_motd_delete(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); allow -> - announce_motd_delete() + announce_motd_delete(To#jid.lserver) end. -announce_motd_delete() -> - mnesia:clear_table(motd), - mnesia:clear_table(motd_users). +announce_motd_delete(LServer) -> + F = fun() -> + mnesia:delete({motd, LServer}), + mnesia:write_lock_table(motd_users), + Users = mnesia:select( + motd_users, + [{#motd_users{us = '$1', _ = '_'}, + [{'==', {element, 2, '$1'}, LServer}], + ['$1']}]), + lists:foreach(fun(US) -> + mnesia:delete({motd_users, US}) + end, Users) + end, + mnesia:transaction(F). -send_motd(#jid{luser = LUser} = JID) -> - case catch mnesia:dirty_read({motd, motd}) of +send_motd(#jid{luser = LUser, lserver = LServer} = JID) -> + case catch mnesia:dirty_read({motd, LServer}) of [#motd{packet = Packet}] -> - case catch mnesia:dirty_read({motd_users, LUser}) of + US = {LUser, LServer}, + case catch mnesia:dirty_read({motd_users, US}) of [#motd_users{}] -> ok; _ -> - Local = jlib:make_jid("", ?MYNAME, ""), + Local = jlib:make_jid("", LServer, ""), ejabberd_router:route(Local, JID, Packet), F = fun() -> - mnesia:write(#motd_users{luser = LUser}) + mnesia:write(#motd_users{us = US}) end, mnesia:transaction(F) end; @@ -198,3 +229,92 @@ send_motd(#jid{luser = LUser} = JID) -> ok end. + +update_tables() -> + update_motd_table(), + update_motd_users_table(). + +update_motd_table() -> + Fields = record_info(fields, motd), + case mnesia:table_info(motd, attributes) of + Fields -> + ok; + [id, packet] -> + ?INFO_MSG("Converting motd table from " + "{id, packet} format", []), + Host = ?MYNAME, + {atomic, ok} = mnesia:create_table( + mod_announce_tmp_table, + [{disc_only_copies, [node()]}, + {type, bag}, + {local_content, true}, + {record_name, motd}, + {attributes, record_info(fields, motd)}]), + mnesia:transform_table(motd, ignore, Fields), + F1 = fun() -> + mnesia:write_lock_table(mod_announce_tmp_table), + mnesia:foldl( + fun(#motd{server = _} = R, _) -> + mnesia:dirty_write( + mod_announce_tmp_table, + R#motd{server = Host}) + end, ok, motd) + end, + mnesia:transaction(F1), + mnesia:clear_table(motd), + F2 = fun() -> + mnesia:write_lock_table(motd), + mnesia:foldl( + fun(R, _) -> + mnesia:dirty_write(R) + end, ok, mod_announce_tmp_table) + end, + mnesia:transaction(F2), + mnesia:delete_table(mod_announce_tmp_table); + _ -> + ?INFO_MSG("Recreating motd table", []), + mnesia:transform_table(motd, ignore, Fields) + end. + + +update_motd_users_table() -> + Fields = record_info(fields, motd_users), + case mnesia:table_info(motd_users, attributes) of + Fields -> + ok; + [luser, dummy] -> + ?INFO_MSG("Converting motd_users table from " + "{luser, dummy} format", []), + Host = ?MYNAME, + {atomic, ok} = mnesia:create_table( + mod_announce_tmp_table, + [{disc_only_copies, [node()]}, + {type, bag}, + {local_content, true}, + {record_name, motd_users}, + {attributes, record_info(fields, motd_users)}]), + mnesia:transform_table(motd_users, ignore, Fields), + F1 = fun() -> + mnesia:write_lock_table(mod_announce_tmp_table), + mnesia:foldl( + fun(#motd_users{us = U} = R, _) -> + mnesia:dirty_write( + mod_announce_tmp_table, + R#motd_users{us = {U, Host}}) + end, ok, motd_users) + end, + mnesia:transaction(F1), + mnesia:clear_table(motd_users), + F2 = fun() -> + mnesia:write_lock_table(motd_users), + mnesia:foldl( + fun(R, _) -> + mnesia:dirty_write(R) + end, ok, mod_announce_tmp_table) + end, + mnesia:transaction(F2), + mnesia:delete_table(mod_announce_tmp_table); + _ -> + ?INFO_MSG("Recreating motd_users table", []), + mnesia:transform_table(motd_users, ignore, Fields) + end. |