* src/mod_announce.erl: Added support to all the announce features described in documentation. Access to all announce features through command line, adhoc commands and disco (Thanks to Badlop) (EJAB-18).

* src/gen_mod.erl: Likewise.
* doc/guide.tex: Likewise.

SVN Revision: 858
This commit is contained in:
Mickaël Rémond 2007-08-03 08:53:05 +00:00
parent bd00eb8898
commit c72cb51c73
5 changed files with 180 additions and 23 deletions

View File

@ -1,3 +1,12 @@
2007-08-03 Mickael Remond <mickael.remond@process-one.net>
* src/mod_announce.erl: Added support to all the announce features
described in documentation. Access to all announce features
through command line, adhoc commands and disco (Thanks to
Badlop) (EJAB-18).
* src/gen_mod.erl: Likewise.
* doc/guide.tex: Likewise.
2007-08-02 Alexey Shchepin <alexey@sevcom.net>
* src/mod_muc/mod_muc.erl: Added default_room_options option

View File

@ -1410,7 +1410,7 @@ with:
<A NAME="modannounce"></A>
</P><P>This module enables configured users to broadcast announcements and to set
the message of the day (MOTD). Configured users can do these actions with their
Jabber client by sending messages to specific JIDs. These JIDs are listed in
Jabber client using Ad-hoc commands or by sending messages to specific JIDs. These JIDs are listed in
next paragraph. The first JID in each entry will apply only to the virtual host
<TT>example.org</TT>, while the JID between brackets will apply to all virtual
hosts:
@ -1463,7 +1463,9 @@ Only administrators can send announcements:
{mod_announce, [{access, announce}]},
...
]}.
</PRE></LI></UL><!--TOC subsection <TT>mod_disco</TT>-->
</PRE></LI></UL><P>Note that <TT>mod_announce</TT> can be resource intensive on large
deployments as it can broadcast lot of messages. This module should be
disabled for instances of ejabberd with hundreds of thousands users.</P><!--TOC subsection <TT>mod_disco</TT>-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc33">3.3.4</A>&#XA0;&#XA0;<TT>mod_disco</TT></H3><!--SEC END --><P>
<A NAME="moddisco"></A>
</P><P>This module adds support for Service Discovery (<A HREF="http://www.xmpp.org/extensions/xep-0030.html">XEP-0030</A>). With

View File

@ -1744,7 +1744,7 @@ Examples:
This module enables configured users to broadcast announcements and to set
the message of the day (MOTD). Configured users can do these actions with their
\Jabber{} client by sending messages to specific JIDs. These JIDs are listed in
\Jabber{} client using Ad-hoc commands or by sending messages to specific JIDs. These JIDs are listed in
next paragraph. The first JID in each entry will apply only to the virtual host
\jid{example.org}, while the JID between brackets will apply to all virtual
hosts:
@ -1790,7 +1790,7 @@ Examples:
]}.
\end{verbatim}
\item Administrators as well as the direction can send announcements:
\begin{verbatim}
\begin{verbatim}
{acl, direction, {user, "big_boss", "example.org"}}.
{acl, direction, {user, "assistant", "example.org"}}.
{acl, admins, {user, "admin", "example.org"}}.
@ -1807,6 +1807,10 @@ Examples:
\end{verbatim}
\end{itemize}
Note that \modannounce{} can be resource intensive on large
deployments as it can broadcast lot of messages. This module should be
disabled for instances of ejabberd with hundreds of thousands users.
\subsection{\moddisco{}}
\label{moddisco}
\ind{modules!\moddisco{}}\ind{protocols!XEP-0030: Service Discovery}\ind{protocols!XEP-0011: Jabber Browsing}\ind{protocols!XEP-0094: Agent Information}

View File

@ -107,6 +107,23 @@ get_opt(Opt, Opts, Default) ->
Val
end.
get_module_opt(global, Module, Opt, Default) ->
Hosts = ?MYHOSTS,
[Value | Values] = lists:map(
fun(Host) ->
get_module_opt(Host, Module, Opt, Default)
end,
Hosts),
Same_all = lists:all(
fun(Other_value) ->
Other_value == Value
end,
Values),
case Same_all of
true -> Value;
false -> Default
end;
get_module_opt(Host, Module, Opt, Default) ->
OptsList = ets:lookup(ejabberd_modules, {Module, Host}),
case OptsList of

View File

@ -57,6 +57,9 @@ loop() ->
{announce_all, From, To, Packet} ->
announce_all(From, To, Packet),
loop();
{announce_all_hosts_all, From, To, Packet} ->
announce_all_hosts_all(From, To, Packet),
loop();
{announce_online, From, To, Packet} ->
announce_online(From, To, Packet),
loop();
@ -66,12 +69,21 @@ loop() ->
{announce_motd, From, To, Packet} ->
announce_motd(From, To, Packet),
loop();
{announce_all_hosts_motd, From, To, Packet} ->
announce_all_hosts_motd(From, To, Packet),
loop();
{announce_motd_update, From, To, Packet} ->
announce_motd_update(From, To, Packet),
loop();
{announce_all_hosts_motd_update, From, To, Packet} ->
announce_all_hosts_motd_update(From, To, Packet),
loop();
{announce_motd_delete, From, To, Packet} ->
announce_motd_delete(From, To, Packet),
loop();
{announce_all_hosts_motd_delete, From, To, Packet} ->
announce_all_hosts_motd_delete(From, To, Packet),
loop();
_ ->
loop()
end.
@ -100,6 +112,9 @@ announce(From, To, Packet) ->
{"announce/all", "message"} ->
Proc ! {announce_all, From, To, Packet},
stop;
{"announce/all-hosts/all", "message"} ->
Proc ! {announce_all_hosts_all, From, To, Packet},
stop;
{"announce/online", "message"} ->
Proc ! {announce_online, From, To, Packet},
stop;
@ -109,12 +124,21 @@ announce(From, To, Packet) ->
{"announce/motd", "message"} ->
Proc ! {announce_motd, From, To, Packet},
stop;
{"announce/all-hosts/motd", "message"} ->
Proc ! {announce_all_hosts_motd, From, To, Packet},
stop;
{"announce/motd/update", "message"} ->
Proc ! {announce_motd_update, From, To, Packet},
stop;
{"announce/all-hosts/motd/update", "message"} ->
Proc ! {announce_all_hosts_motd_update, From, To, Packet},
stop;
{"announce/motd/delete", "message"} ->
Proc ! {announce_motd_delete, From, To, Packet},
stop;
{"announce/all-hosts/motd/delete", "message"} ->
Proc ! {announce_all_hosts_motd_delete, From, To, Packet},
stop;
_ ->
ok
end;
@ -134,16 +158,24 @@ disco_identity(Acc, _From, _To, Node, Lang) ->
case Node of
"announce/all" ->
?INFO_COMMAND(Lang, Node);
"announce/all-hosts/online" ->
"announce/all-hosts/all" ->
?INFO_COMMAND(Lang, Node);
"announce/online" ->
?INFO_COMMAND(Lang, Node);
"announce/all-hosts/online" ->
?INFO_COMMAND(Lang, Node);
"announce/motd" ->
?INFO_COMMAND(Lang, Node);
"announce/all-hosts/motd" ->
?INFO_COMMAND(Lang, Node);
"announce/motd/delete" ->
?INFO_COMMAND(Lang, Node);
"announce/all-hosts/motd/delete" ->
?INFO_COMMAND(Lang, Node);
"announce/motd/update" ->
?INFO_COMMAND(Lang, Node);
"announce/all-hosts/motd/update" ->
?INFO_COMMAND(Lang, Node);
_ ->
Acc
end.
@ -176,7 +208,12 @@ disco_features(Acc, From, #jid{lserver = LServer} = _To,
end;
disco_features(Acc, From, #jid{lserver = LServer} = _To,
"announce/all-hosts/online", _Lang) ->
Node, _Lang)
when (Node == "announce/all-hosts/online")
or (Node == "announce/all-hosts/all")
or (Node == "announce/all-hosts/motd")
or (Node == "announce/all-hosts/motd/update")
or (Node == "announce/all-hosts/motd/delete") ->
case gen_mod:is_loaded(LServer, mod_adhoc) of
false ->
Acc;
@ -257,8 +294,12 @@ disco_items(Acc, From, #jid{lserver = LServer} = To, "announce", Lang) ->
announce_items(Acc, From, To, Lang)
end;
disco_items(Acc, From, #jid{lserver = LServer} = _To,
"announce/all-hosts/online", _Lang) ->
disco_items(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang)
when (Node == "announce/all-hosts/online")
or (Node == "announce/all-hosts/all")
or (Node == "announce/all-hosts/motd")
or (Node == "announce/all-hosts/motd/update")
or (Node == "announce/all-hosts/motd/delete") ->
case gen_mod:is_loaded(LServer, mod_adhoc) of
false ->
Acc;
@ -308,7 +349,11 @@ announce_items(Acc, From, #jid{lserver = LServer, server = Server} = _To, Lang)
Access2 = gen_mod:get_module_opt(global, ?MODULE, access, none),
Nodes2 = case acl:match_rule(global, Access2, From) of
allow ->
[?NODE_TO_ITEM(Lang, Server, "announce/all-hosts/online")];
[?NODE_TO_ITEM(Lang, Server, "announce/all-hosts/all"),
?NODE_TO_ITEM(Lang, Server, "announce/all-hosts/online"),
?NODE_TO_ITEM(Lang, Server, "announce/all-hosts/motd"),
?NODE_TO_ITEM(Lang, Server, "announce/all-hosts/motd/update"),
?NODE_TO_ITEM(Lang, Server, "announce/all-hosts/motd/delete")];
deny ->
[]
end,
@ -335,7 +380,12 @@ announce_items(Acc, From, #jid{lserver = LServer, server = Server} = _To, Lang)
announce_commands(_Acc, From, To,
#adhoc_request{
node = "announce/all-hosts/online"} = Request) ->
node = Node} = Request)
when (Node == "announce/all-hosts/online")
or (Node == "announce/all-hosts/all")
or (Node == "announce/all-hosts/motd")
or (Node == "announce/all-hosts/motd/update")
or (Node == "announce/all-hosts/motd/delete") ->
Access = gen_mod:get_module_opt(global, ?MODULE, access, none),
Allow = acl:match_rule(global, Access, From),
?COMMANDS_RESULT(Allow, From, To, Request);
@ -400,7 +450,8 @@ generate_adhoc_form(Lang, Node) ->
{"type", "form"}],
[{xmlelement, "title", [], [{xmlcdata, get_title(Lang, Node)}]}]
++
if Node == "announce/motd/delete" ->
if (Node == "announce/motd/delete")
or (Node == "announce/all-hosts/motd/delete") ->
[{xmlelement, "field",
[{"var", "confirm"},
{"type", "boolean"},
@ -485,6 +536,13 @@ handle_adhoc_form(From, #jid{lserver = LServer} = To,
true ->
adhoc:produce_response(Response)
end;
{"announce/all-hosts/motd/delete", _} ->
if Confirm ->
Proc ! {announce_all_hosts_motd_delete, From, To, Packet},
adhoc:produce_response(Response);
true ->
adhoc:produce_response(Response)
end;
{_, []} ->
%% An announce message with no body is definitely an operator error.
%% Throw an error and give him/her a chance to send message again.
@ -497,6 +555,9 @@ handle_adhoc_form(From, #jid{lserver = LServer} = To,
{"announce/all", _} ->
Proc ! {announce_all, From, To, Packet},
adhoc:produce_response(Response);
{"announce/all-hosts/all", _} ->
Proc ! {announce_all_hosts_all, From, To, Packet},
adhoc:produce_response(Response);
{"announce/online", _} ->
Proc ! {announce_online, From, To, Packet},
adhoc:produce_response(Response);
@ -506,9 +567,15 @@ handle_adhoc_form(From, #jid{lserver = LServer} = To,
{"announce/motd", _} ->
Proc ! {announce_motd, From, To, Packet},
adhoc:produce_response(Response);
{"announce/all-hosts/motd", _} ->
Proc ! {announce_all_hosts_motd, From, To, Packet},
adhoc:produce_response(Response);
{"announce/motd/update", _} ->
Proc ! {announce_motd_update, From, To, Packet},
adhoc:produce_response(Response);
{"announce/all-hosts/motd/update", _} ->
Proc ! {announce_all_hosts_motd_update, From, To, Packet},
adhoc:produce_response(Response);
_ ->
%% This can't happen, as we haven't registered any other
%% command nodes.
@ -519,16 +586,24 @@ get_title(Lang, "announce") ->
translate:translate(Lang, "Announcements");
get_title(Lang, "announce/all") ->
translate:translate(Lang, "Send announcement to all users");
get_title(Lang, "announce/all-hosts/all") ->
translate:translate(Lang, "Send announcement to all users on all hosts");
get_title(Lang, "announce/online") ->
translate:translate(Lang, "Send announcement to all online users");
get_title(Lang, "announce/all-hosts/online") ->
translate:translate(Lang, "Send announcement to all online users on all hosts");
get_title(Lang, "announce/motd") ->
translate:translate(Lang, "Set message of the day and send to online users");
get_title(Lang, "announce/all-hosts/motd") ->
translate:translate(Lang, "Set message of the day on all hosts and send to online users");
get_title(Lang, "announce/motd/update") ->
translate:translate(Lang, "Update message of the day (don't send)");
get_title(Lang, "announce/all-hosts/motd/update") ->
translate:translate(Lang, "Update message of the day on all hosts (don't send)");
get_title(Lang, "announce/motd/delete") ->
translate:translate(Lang, "Delete message of the day").
translate:translate(Lang, "Delete message of the day");
get_title(Lang, "announce/all-hosts/motd/delete") ->
translate:translate(Lang, "Delete message of the day on all hosts").
%-------------------------------------------------------------------------
@ -548,6 +623,21 @@ announce_all(From, To, Packet) ->
end, ejabberd_auth:get_vh_registered_users(Host))
end.
announce_all_hosts_all(From, To, Packet) ->
Access = gen_mod:get_module_opt(global, ?MODULE, access, none),
case acl:match_rule(global, Access, From) of
deny ->
Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN),
ejabberd_router:route(To, From, Err);
allow ->
Local = jlib:make_jid("", To#jid.server, ""),
lists:foreach(
fun({User, Server}) ->
Dest = jlib:make_jid(User, Server, ""),
ejabberd_router:route(Local, Dest, Packet)
end, ejabberd_auth:dirty_get_registered_users())
end.
announce_online(From, To, Packet) ->
Host = To#jid.lserver,
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
@ -589,18 +679,32 @@ announce_motd(From, To, Packet) ->
Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN),
ejabberd_router:route(To, From, Err);
allow ->
announce_motd_update(To#jid.lserver, Packet),
Sessions = ejabberd_sm:get_vh_session_list(Host),
announce_online1(Sessions, To#jid.server, Packet),
F = fun() ->
lists:foreach(
fun({U, S, _R}) ->
mnesia:write(#motd_users{us = {U, S}})
end, Sessions)
end,
mnesia:transaction(F)
announce_motd(Host, Packet)
end.
announce_all_hosts_motd(From, To, Packet) ->
Access = gen_mod:get_module_opt(global, ?MODULE, access, none),
case acl:match_rule(global, Access, From) of
deny ->
Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN),
ejabberd_router:route(To, From, Err);
allow ->
Hosts = ?MYHOSTS,
[announce_motd(Host, Packet) || Host <- Hosts]
end.
announce_motd(Host, Packet) ->
announce_motd_update(Host, Packet),
Sessions = ejabberd_sm:get_vh_session_list(Host),
announce_online1(Sessions, Host, Packet),
F = fun() ->
lists:foreach(
fun({U, S, _R}) ->
mnesia:write(#motd_users{us = {U, S}})
end, Sessions)
end,
mnesia:transaction(F).
announce_motd_update(From, To, Packet) ->
Host = To#jid.lserver,
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
@ -612,6 +716,17 @@ announce_motd_update(From, To, Packet) ->
announce_motd_update(Host, Packet)
end.
announce_all_hosts_motd_update(From, To, Packet) ->
Access = gen_mod:get_module_opt(global, ?MODULE, access, none),
case acl:match_rule(global, Access, From) of
deny ->
Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN),
ejabberd_router:route(To, From, Err);
allow ->
Hosts = ?MYHOSTS,
[announce_motd_update(Host, Packet) || Host <- Hosts]
end.
announce_motd_update(LServer, Packet) ->
announce_motd_delete(LServer),
F = fun() ->
@ -630,6 +745,17 @@ announce_motd_delete(From, To, Packet) ->
announce_motd_delete(Host)
end.
announce_all_hosts_motd_delete(From, To, Packet) ->
Access = gen_mod:get_module_opt(global, ?MODULE, access, none),
case acl:match_rule(global, Access, From) of
deny ->
Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN),
ejabberd_router:route(To, From, Err);
allow ->
Hosts = ?MYHOSTS,
[announce_motd_delete(Host) || Host <- Hosts]
end.
announce_motd_delete(LServer) ->
F = fun() ->
mnesia:delete({motd, LServer}),
@ -754,4 +880,3 @@ update_motd_users_table() ->
?INFO_MSG("Recreating motd_users table", []),
mnesia:transform_table(motd_users, ignore, Fields)
end.