]> granicus.if.org Git - ejabberd/commitdiff
* src/mod_announce.erl: Added support to all the announce features described in docum...
authorMickaël Rémond <mickael.remond@process-one.net>
Fri, 3 Aug 2007 08:53:05 +0000 (08:53 +0000)
committerMickaël Rémond <mickael.remond@process-one.net>
Fri, 3 Aug 2007 08:53:05 +0000 (08:53 +0000)
* src/gen_mod.erl: Likewise.
* doc/guide.tex: Likewise.

SVN Revision: 858

ChangeLog
doc/guide.html
doc/guide.tex
src/gen_mod.erl
src/mod_announce.erl

index d959002e8e1c4ffeecf29cefd129744bf5f92cfb..cfba33ef81a0ba320f495ac4143830b58aaf6bcb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index a61d0893ca85060f5b38b3f392c15bc4ae40d531..8012e5b7609676f4134f15df937037e42afe5d69 100644 (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
index 8d8c1f0d8059f48c8b1252b23e9548759311c36b..ed608075bdb76aa215171338ddf81b3736a52bf6 100644 (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}
index 7ba6db1827cf3af2df376c5c4aaeff912905a3a5..eed3e4405dc2e006f72af044525494ca46a91371 100644 (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
index 8cabf748aa9c1f983c0f70b6db5c78896ef715df..deccafcb045baf48166999b590f340e5413bbb2c 100644 (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.
-