]> granicus.if.org Git - ejabberd/commitdiff
* src/ejabberd_c2s.erl: Bugfix in resend_offline_messages/1
authorAlexey Shchepin <alexey@process-one.net>
Thu, 12 Aug 2004 22:34:19 +0000 (22:34 +0000)
committerAlexey Shchepin <alexey@process-one.net>
Thu, 12 Aug 2004 22:34:19 +0000 (22:34 +0000)
* src/mod_announce.erl: New module to manage announce messages
(thanks to Sergei Golovan)

* src/ejabberd_local.erl: Moved processing of announce messages to
mod_announce (thanks to Sergei Golovan)

* src/ejabberd_c2s.erl: Added several hooks

* src/ejabberd_hooks.erl: Fixed run_fold (thanks to Sergei
Golovan)

* src/ejabberd.cfg.example: Updated (thanks to Sergei Golovan)

* doc/guide.tex: Updated (thanks to Sergei Golovan)

SVN Revision: 256

ChangeLog
doc/guide.html
doc/guide.tex
src/cyrsasl_digest.erl
src/ejabberd.cfg.example
src/ejabberd_c2s.erl
src/ejabberd_hooks.erl
src/ejabberd_local.erl
src/mod_announce.erl [new file with mode: 0644]

index e6043d3b91a1819a2e88a3d8331d2ee107cd5f0f..56c36a72749da989454b9d4c6da77fcacca60773 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2004-08-12  Alexey Shchepin  <alexey@sevcom.net>
+
+       * src/ejabberd_c2s.erl: Bugfix in resend_offline_messages/1
+
+       * src/mod_announce.erl: New module to manage announce messages
+       (thanks to Sergei Golovan)
+
+       * src/ejabberd_local.erl: Moved processing of announce messages to
+       mod_announce (thanks to Sergei Golovan)
+
+       * src/ejabberd_c2s.erl: Added several hooks
+
+       * src/ejabberd_hooks.erl: Fixed run_fold (thanks to Sergei
+       Golovan)
+
+       * src/ejabberd.cfg.example: Updated (thanks to Sergei Golovan)
+
+       * doc/guide.tex: Updated (thanks to Sergei Golovan)
+
 2004-08-08  Alexey Shchepin  <alexey@sevcom.net>
 
        * src/ejabberd_c2s.erl: Use resend_offline_messages_hook to fetch
index 851bb0384792980d698353c777f4ac75268f87cb..1d0927ac83e59c9b972f56f752692ce0ae0b4fc0 100644 (file)
 <A HREF="#htoc30">A.1.1&nbsp;&nbsp;Option <TT>iqdisc</TT></A>
 <LI><A HREF="#htoc31">A.1.2&nbsp;&nbsp;Option <TT>host</TT></A>
 </UL>
-<LI><A HREF="#htoc32">A.2&nbsp;&nbsp;<TT>mod_configure</TT></A>
-<LI><A HREF="#htoc33">A.3&nbsp;&nbsp;<TT>mod_disco</TT></A>
-<LI><A HREF="#htoc34">A.4&nbsp;&nbsp;<TT>mod_echo</TT></A>
-<LI><A HREF="#htoc35">A.5&nbsp;&nbsp;<TT>mod_irc</TT></A>
-<LI><A HREF="#htoc36">A.6&nbsp;&nbsp;<TT>mod_last</TT></A>
-<LI><A HREF="#htoc37">A.7&nbsp;&nbsp;<TT>mod_muc</TT></A>
-<LI><A HREF="#htoc38">A.8&nbsp;&nbsp;<TT>mod_offline</TT></A>
-<LI><A HREF="#htoc39">A.9&nbsp;&nbsp;<TT>mod_privacy</TT></A>
-<LI><A HREF="#htoc40">A.10&nbsp;&nbsp;<TT>mod_private</TT></A>
-<LI><A HREF="#htoc41">A.11&nbsp;&nbsp;<TT>mod_pubsub</TT></A>
-<LI><A HREF="#htoc42">A.12&nbsp;&nbsp;<TT>mod_register</TT></A>
-<LI><A HREF="#htoc43">A.13&nbsp;&nbsp;<TT>mod_roster</TT></A>
-<LI><A HREF="#htoc44">A.14&nbsp;&nbsp;<TT>mod_stats</TT></A>
-<LI><A HREF="#htoc45">A.15&nbsp;&nbsp;<TT>mod_time</TT></A>
-<LI><A HREF="#htoc46">A.16&nbsp;&nbsp;<TT>mod_vcard</TT></A>
-<LI><A HREF="#htoc47">A.17&nbsp;&nbsp;<TT>mod_version</TT></A>
+<LI><A HREF="#htoc32">A.2&nbsp;&nbsp;<TT>mod_announce</TT></A>
+<LI><A HREF="#htoc33">A.3&nbsp;&nbsp;<TT>mod_configure</TT></A>
+<LI><A HREF="#htoc34">A.4&nbsp;&nbsp;<TT>mod_disco</TT></A>
+<LI><A HREF="#htoc35">A.5&nbsp;&nbsp;<TT>mod_echo</TT></A>
+<LI><A HREF="#htoc36">A.6&nbsp;&nbsp;<TT>mod_irc</TT></A>
+<LI><A HREF="#htoc37">A.7&nbsp;&nbsp;<TT>mod_last</TT></A>
+<LI><A HREF="#htoc38">A.8&nbsp;&nbsp;<TT>mod_muc</TT></A>
+<LI><A HREF="#htoc39">A.9&nbsp;&nbsp;<TT>mod_offline</TT></A>
+<LI><A HREF="#htoc40">A.10&nbsp;&nbsp;<TT>mod_privacy</TT></A>
+<LI><A HREF="#htoc41">A.11&nbsp;&nbsp;<TT>mod_private</TT></A>
+<LI><A HREF="#htoc42">A.12&nbsp;&nbsp;<TT>mod_pubsub</TT></A>
+<LI><A HREF="#htoc43">A.13&nbsp;&nbsp;<TT>mod_register</TT></A>
+<LI><A HREF="#htoc44">A.14&nbsp;&nbsp;<TT>mod_roster</TT></A>
+<LI><A HREF="#htoc45">A.15&nbsp;&nbsp;<TT>mod_stats</TT></A>
+<LI><A HREF="#htoc46">A.16&nbsp;&nbsp;<TT>mod_time</TT></A>
+<LI><A HREF="#htoc47">A.17&nbsp;&nbsp;<TT>mod_vcard</TT></A>
+<LI><A HREF="#htoc48">A.18&nbsp;&nbsp;<TT>mod_version</TT></A>
 </UL>
-<LI><A HREF="#htoc48">B&nbsp;&nbsp;I18n/L10n</A>
+<LI><A HREF="#htoc49">B&nbsp;&nbsp;I18n/L10n</A>
 </UL>
 
 <!--TOC section Introduction-->
@@ -474,15 +475,15 @@ The following options are defined:
  <DT><B><TT>{ip, IPAddress}</TT></B><DD> This option specifies which network interface to
  listen on. For example <CODE>{ip, {192, 168, 1, 1}}</CODE>.
  <DT><B><TT>inet6</TT></B><DD> Set up the socket for IPv6.
- <DT><B><TT>tls</TT></B><DD> This option specifies that STARTTLS extension is available on
- connections to this port. You should also set ``<CODE>certfile</CODE>'' option.
- <DT><B><TT>tls_from_start</TT></B><DD> Among with <TT>tls</TT> this option specifies that
- traffic on this port will be encrypted using SSL immediately after
- connecting.
+ <DT><B><TT>starttls</TT></B><DD> This option specifies that STARTTLS extension is available
+ on connections to this port. You should also set ``<CODE>certfile</CODE>''
+ option.
+ <DT><B><TT>tls</TT></B><DD> This option specifies that traffic on this port will be
+ encrypted using SSL immediately after connecting. You should also set
+ ``<CODE>certfile</CODE>'' option.
  <DT><B><TT>ssl</TT></B><DD> This option specifies that traffic on this port will be
  encrypted using SSL. You should also set ``<CODE>certfile</CODE>'' option. It
- is recommended to use <TT>tls</TT> and <TT>tls_from_start</TT> options
- instead.
+ is recommended to use <TT>tls</TT> option instead.
  <DT><B><TT>{certfile, Path}</TT></B><DD> Path to a file containing the SSL certificate.
  </DL>
  <DT><B><TT>ejabberd_s2s_in</TT></B><DD> This module serves incoming S2S connections.
@@ -818,9 +819,33 @@ Example:
     ...
    ]}.
 </PRE>
+<!--TOC subsection <TT>mod_announce</TT>-->
+
+<H3><A NAME="htoc32">A.2</A>&nbsp;&nbsp;<TT>mod_announce</TT></H3><!--SEC END -->
+
+<A NAME="sec:modannounce"></A>
+This module adds support for broadcast announce messages and MOTD.<BR>
+<BR>
+Options:
+<DL COMPACT=compact><DT>
+<B><TT>access</TT></B><DD> Specifies who is allowed to send announce messages
+and set MOTD (default value is <TT>none</TT>).
+</DL>
+Example:
+<PRE>
+  % Only admins can send announcement messages:
+  {access, announce, [{allow, admin}]}.
+
+  {modules,
+   [
+    ...
+    {mod_announce, [{access, announce}]},
+    ...
+   ]}.
+</PRE>
 <!--TOC subsection <TT>mod_configure</TT>-->
 
-<H3><A NAME="htoc32">A.2</A>&nbsp;&nbsp;<TT>mod_configure</TT></H3><!--SEC END -->
+<H3><A NAME="htoc33">A.3</A>&nbsp;&nbsp;<TT>mod_configure</TT></H3><!--SEC END -->
 
 <A NAME="sec:modconfigure"></A>
 Options:
@@ -830,7 +855,7 @@ discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
 </DL>
 <!--TOC subsection <TT>mod_disco</TT>-->
 
-<H3><A NAME="htoc33">A.3</A>&nbsp;&nbsp;<TT>mod_disco</TT></H3><!--SEC END -->
+<H3><A NAME="htoc34">A.4</A>&nbsp;&nbsp;<TT>mod_disco</TT></H3><!--SEC END -->
 
 <A NAME="sec:moddisco"></A>
 This module adds support for <A HREF="http://www.jabber.org/jeps/jep-0030.html">JEP-0030</A> (Service Discovery).<BR>
@@ -855,7 +880,7 @@ Example:
 </PRE>
 <!--TOC subsection <TT>mod_echo</TT>-->
 
-<H3><A NAME="htoc34">A.4</A>&nbsp;&nbsp;<TT>mod_echo</TT></H3><!--SEC END -->
+<H3><A NAME="htoc35">A.5</A>&nbsp;&nbsp;<TT>mod_echo</TT></H3><!--SEC END -->
 
 <A NAME="sec:modecho"></A>
 This module acts as a service and simply returns to sender any Jabber packet. Module may be
@@ -869,7 +894,7 @@ then prefix <TT>echo.</TT> is added to main <TT>ejabberd</TT> hostname.
 </DL>
 <!--TOC subsection <TT>mod_irc</TT>-->
 
-<H3><A NAME="htoc35">A.5</A>&nbsp;&nbsp;<TT>mod_irc</TT></H3><!--SEC END -->
+<H3><A NAME="htoc36">A.6</A>&nbsp;&nbsp;<TT>mod_irc</TT></H3><!--SEC END -->
 
 <A NAME="sec:modirc"></A>
 This module implements IRC transport.<BR>
@@ -892,7 +917,7 @@ Example:
 </PRE>
 <!--TOC subsection <TT>mod_last</TT>-->
 
-<H3><A NAME="htoc36">A.6</A>&nbsp;&nbsp;<TT>mod_last</TT></H3><!--SEC END -->
+<H3><A NAME="htoc37">A.7</A>&nbsp;&nbsp;<TT>mod_last</TT></H3><!--SEC END -->
 
 <A NAME="sec:modlast"></A>
 This module adds support for <A HREF="http://www.jabber.org/jeps/jep-0012.html">JEP-0012</A> (Last Activity)<BR>
@@ -904,7 +929,7 @@ discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
 </DL>
 <!--TOC subsection <TT>mod_muc</TT>-->
 
-<H3><A NAME="htoc37">A.7</A>&nbsp;&nbsp;<TT>mod_muc</TT></H3><!--SEC END -->
+<H3><A NAME="htoc38">A.8</A>&nbsp;&nbsp;<TT>mod_muc</TT></H3><!--SEC END -->
 
 <A NAME="sec:modmuc"></A>
 This module implements <A HREF="http://www.jabber.org/jeps/jep-0045.html">JEP-0045</A> (Multi-User Chat) service.<BR>
@@ -939,14 +964,14 @@ Example:
 </PRE>
 <!--TOC subsection <TT>mod_offline</TT>-->
 
-<H3><A NAME="htoc38">A.8</A>&nbsp;&nbsp;<TT>mod_offline</TT></H3><!--SEC END -->
+<H3><A NAME="htoc39">A.9</A>&nbsp;&nbsp;<TT>mod_offline</TT></H3><!--SEC END -->
 
 <A NAME="sec:modoffline"></A>
 This module implements offline message storage.<BR>
 <BR>
 <!--TOC subsection <TT>mod_privacy</TT>-->
 
-<H3><A NAME="htoc39">A.9</A>&nbsp;&nbsp;<TT>mod_privacy</TT></H3><!--SEC END -->
+<H3><A NAME="htoc40">A.10</A>&nbsp;&nbsp;<TT>mod_privacy</TT></H3><!--SEC END -->
 
 <A NAME="sec:modprivacy"></A>
 This module implements Privacy Rules as defined in XMPP IM
@@ -959,7 +984,7 @@ discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
 </DL>
 <!--TOC subsection <TT>mod_private</TT>-->
 
-<H3><A NAME="htoc40">A.10</A>&nbsp;&nbsp;<TT>mod_private</TT></H3><!--SEC END -->
+<H3><A NAME="htoc41">A.11</A>&nbsp;&nbsp;<TT>mod_private</TT></H3><!--SEC END -->
 
 <A NAME="sec:modprivate"></A>
 This module adds support of <A HREF="http://www.jabber.org/jeps/jep-0049.html">JEP-0049</A> (Private XML Storage).<BR>
@@ -971,7 +996,7 @@ discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
 </DL>
 <!--TOC subsection <TT>mod_pubsub</TT>-->
 
-<H3><A NAME="htoc41">A.11</A>&nbsp;&nbsp;<TT>mod_pubsub</TT></H3><!--SEC END -->
+<H3><A NAME="htoc42">A.12</A>&nbsp;&nbsp;<TT>mod_pubsub</TT></H3><!--SEC END -->
 
 <A NAME="sec:modpubsub"></A>
 This module implements <A HREF="http://www.jabber.org/jeps/jep-0060.html">JEP-0060</A> (Publish-Subscribe Service).<BR>
@@ -996,7 +1021,7 @@ Example:
 </PRE>
 <!--TOC subsection <TT>mod_register</TT>-->
 
-<H3><A NAME="htoc42">A.12</A>&nbsp;&nbsp;<TT>mod_register</TT></H3><!--SEC END -->
+<H3><A NAME="htoc43">A.13</A>&nbsp;&nbsp;<TT>mod_register</TT></H3><!--SEC END -->
 
 <A NAME="sec:modregister"></A>
 This module adds support for <A HREF="http://www.jabber.org/jeps/jep-0077.html">JEP-0077</A> (In-Band Registration).<BR>
@@ -1029,7 +1054,7 @@ Example:
 </PRE>
 <!--TOC subsection <TT>mod_roster</TT>-->
 
-<H3><A NAME="htoc43">A.13</A>&nbsp;&nbsp;<TT>mod_roster</TT></H3><!--SEC END -->
+<H3><A NAME="htoc44">A.14</A>&nbsp;&nbsp;<TT>mod_roster</TT></H3><!--SEC END -->
 
 <A NAME="sec:modroster"></A>
 This module implements roster management.<BR>
@@ -1041,7 +1066,7 @@ discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
 </DL>
 <!--TOC subsection <TT>mod_stats</TT>-->
 
-<H3><A NAME="htoc44">A.14</A>&nbsp;&nbsp;<TT>mod_stats</TT></H3><!--SEC END -->
+<H3><A NAME="htoc45">A.15</A>&nbsp;&nbsp;<TT>mod_stats</TT></H3><!--SEC END -->
 
 <A NAME="sec:modstats"></A>
 This module adds support for <A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A> (Statistics Gathering).<BR>
@@ -1055,7 +1080,7 @@ TBD about access.<BR>
 <BR>
 <!--TOC subsection <TT>mod_time</TT>-->
 
-<H3><A NAME="htoc45">A.15</A>&nbsp;&nbsp;<TT>mod_time</TT></H3><!--SEC END -->
+<H3><A NAME="htoc46">A.16</A>&nbsp;&nbsp;<TT>mod_time</TT></H3><!--SEC END -->
 
 <A NAME="sec:modtime"></A>
 This module answers UTC time on <TT>jabber:iq:time</TT> queries.<BR>
@@ -1067,7 +1092,7 @@ discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
 </DL>
 <!--TOC subsection <TT>mod_vcard</TT>-->
 
-<H3><A NAME="htoc46">A.16</A>&nbsp;&nbsp;<TT>mod_vcard</TT></H3><!--SEC END -->
+<H3><A NAME="htoc47">A.17</A>&nbsp;&nbsp;<TT>mod_vcard</TT></H3><!--SEC END -->
 
 <A NAME="sec:modvcard"></A>
 This module implements simple Jabber User Directory (based on user vCards)
@@ -1095,7 +1120,7 @@ Example:
 </PRE>
 <!--TOC subsection <TT>mod_version</TT>-->
 
-<H3><A NAME="htoc47">A.17</A>&nbsp;&nbsp;<TT>mod_version</TT></H3><!--SEC END -->
+<H3><A NAME="htoc48">A.18</A>&nbsp;&nbsp;<TT>mod_version</TT></H3><!--SEC END -->
 
 <A NAME="sec:modversion"></A>
 This module answers <TT>ejabberd</TT> version on <TT>jabber:iq:version</TT> queries.<BR>
@@ -1107,7 +1132,7 @@ discipline (see&nbsp;<A HREF="#sec:modiqdiscoption">A.1.1</A>).
 </DL>
 <!--TOC section I18n/L10n-->
 
-<H2><A NAME="htoc48">B</A>&nbsp;&nbsp;I18n/L10n</H2><!--SEC END -->
+<H2><A NAME="htoc49">B</A>&nbsp;&nbsp;I18n/L10n</H2><!--SEC END -->
 
 <A NAME="sec:i18nl10n"></A>
 All built-in modules support <TT>xml:lang</TT> attribute inside IQ queries.
index dd78dbb9853f30695564d078bb7c32dc6a25fbb9..5e12c70db4c56cddf78cbc345373127ba58ab497 100644 (file)
@@ -34,6 +34,7 @@
 \newcommand{\Jabber}{Jabber}
 
 \newcommand{\module}[1]{\texttt{#1}}
+\newcommand{\modannounce}{\module{mod\_announce}}
 \newcommand{\modconfigure}{\module{mod\_configure}}
 \newcommand{\moddisco}{\module{mod\_disco}}
 \newcommand{\modirc}{\module{mod\_irc}}
@@ -812,6 +813,31 @@ Example:
 \end{verbatim}
 
 
+\subsection{\modannounce{}}
+\label{sec:modannounce}
+
+This module adds support for broadcast announce messages and MOTD.
+
+Options:
+\begin{description}
+\titem{access} Specifies who is allowed to send announce messages
+and set MOTD (default value is \term{none}).
+\end{description}
+
+Example:
+\begin{verbatim}
+  % Only admins can send announcement messages:
+  {access, announce, [{allow, admin}]}.
+
+  {modules,
+   [
+    ...
+    {mod_announce, [{access, announce}]},
+    ...
+   ]}.
+\end{verbatim}
+
+
 \subsection{\modconfigure{}}
 \label{sec:modconfigure}
 
index ae94c181f72a32aa6119225d403346a3c09bc2ee..2e5e94e5ac342129ca45007519353ee0933f6f74 100644 (file)
@@ -51,7 +51,7 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
            AuthzId = xml:get_attr_s("authzid", KeyVals),
            case ejabberd_auth:get_password(UserName) of
                false ->
-                   {error, "no-user"};
+                   {error, "not-authorized"};
                Passwd ->
                    Response = response(KeyVals, UserName, Passwd,
                                        Nonce, AuthzId, "AUTHENTICATE"),
@@ -66,7 +66,7 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
                                         username = UserName,
                                         authzid = AuthzId}};
                        _ ->
-                           {error, "bad-auth"}
+                           {error, "not-authorized"}
                    end
            end
     end;
index 82e1cc43cad8ddf380344880fa84d57e55274922..253752f534e8293a44b29e9ce7a5b64eaf82679b 100644 (file)
   {mod_stats,      []},
   {mod_vcard,      []},
   {mod_offline,    []},
+  {mod_announce,   [{access, announce}]},
   {mod_echo,       [{host, "echo.localhost"}]},
   {mod_private,    []},
   {mod_irc,        []},
index 844e7bcfb268452f0421a6de67e82445658706bb..d8021606faa24e4614e54690ab54af90c02a3694 100644 (file)
@@ -673,12 +673,17 @@ session_established({xmlstreamelement, El}, StateData) ->
                                        process_privacy_iq(
                                          FromJID, ToJID, IQ, StateData);
                                    _ ->
+                                       ejabberd_hooks:run(
+                                         user_send_packet,
+                                         [FromJID, ToJID, NewEl]),
                                        ejabberd_router:route(
                                          FromJID, ToJID, NewEl),
                                        StateData
                                end
                        end;
                    "message" ->
+                       ejabberd_hooks:run(user_send_packet,
+                                          [FromJID, ToJID, NewEl]),
                        ejabberd_router:route(FromJID, ToJID, NewEl),
                        StateData;
                    _ ->
@@ -882,8 +887,11 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
            Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From),
                                                jlib:jid_to_string(To),
                                                NewAttrs),
-           Text = xml:element_to_string({xmlelement, Name, Attrs2, Els}),
+           FixedPacket = {xmlelement, Name, Attrs2, Els},
+           Text = xml:element_to_string(FixedPacket),
            send_text(StateData, Text),
+           ejabberd_hooks:run(user_receive_packet,
+                              [StateData#state.jid, From, To, FixedPacket]),
            {next_state, StateName, NewState};
        true ->
            {next_state, StateName, NewState}
@@ -1102,6 +1110,8 @@ presence_update(From, Packet, StateData) ->
            NewState =
                if
                    FromUnavail ->
+                       ejabberd_hooks:run(user_available_hook,
+                                          [StateData#state.jid]),
                        resend_offline_messages(StateData),
                        presence_broadcast_first(
                          From, StateData#state{pres_last = Packet,
@@ -1385,17 +1395,37 @@ process_privacy_iq(From, To,
     NewStateData.
 
 
-resend_offline_messages(StateData) ->
+resend_offline_messages(#state{user = User,
+                              privacy_list = PrivList} = StateData) ->
     case ejabberd_hooks:run_fold(resend_offline_messages_hook, [],
-                                [StateData#state.user]) of
+                                [User]) of
        Rs when list(Rs) ->
            lists:foreach(
-             fun({route, From, To, {xmlelement, Name, Attrs, Els}}) ->
-                     Attrs2 = jlib:replace_from_to_attrs(
-                                jlib:jid_to_string(From),
-                                jlib:jid_to_string(To),
-                                Attrs),
-                     send_element(StateData, {xmlelement, Name, Attrs2, Els})
+             fun({route,
+                  From, To, {xmlelement, Name, Attrs, Els} = Packet}) ->
+                     Pass = case catch mod_privacy:check_packet(
+                                         User,
+                                         PrivList,
+                                         {From, To, Packet},
+                                         in) of
+                                {'EXIT', _Reason} ->
+                                    true;
+                                allow ->
+                                    true;
+                                deny ->
+                                    false
+                            end,
+                     if
+                         Pass ->
+                             Attrs2 = jlib:replace_from_to_attrs(
+                                        jlib:jid_to_string(From),
+                                        jlib:jid_to_string(To),
+                                        Attrs),
+                             send_element(StateData,
+                                          {xmlelement, Name, Attrs2, Els});
+                         true ->
+                             ok
+                     end
              end, Rs)
     end.
 
index c00035b4127d35cef536cf66f70fd4ac12ef62b7..d316fae89e2526bc5ec365625e98faf62e147891 100644 (file)
@@ -55,7 +55,7 @@ run_fold(Hook, Val, Args) ->
        [{_, Ls}] ->
            run_fold1(Ls, Hook, Val, Args);
        [] ->
-           ok
+           Val
     end.
 
 %%%----------------------------------------------------------------------
index 446ec292b0c191e28fec4324045f426ae8fd1e53..5da4cfaa110867d135e412dc55b07eeda2b76cc0 100644 (file)
@@ -15,7 +15,8 @@
 -export([register_iq_handler/3,
         register_iq_handler/4,
         unregister_iq_handler/1,
-        refresh_iq_handlers/0
+        refresh_iq_handlers/0,
+        bounce_resource_packet/3
        ]).
 
 -include("ejabberd.hrl").
@@ -32,6 +33,8 @@ init() ->
     MyDomain = ?MYNAME,
     ejabberd_router:register_route(MyDomain),
     catch ets:new(local_iqtable, [named_table, public]),
+    ejabberd_hooks:add(local_send_to_resource_hook,
+                      ?MODULE, bounce_resource_packet, 100),
     loop(#state{mydomain = MyDomain,
                iqtable = local_iqtable}).
 
@@ -104,14 +107,8 @@ do_route(State, From, To, Packet) ->
                "error" -> ok;
                "result" -> ok;
                _ ->
-                   case {Res, Name} of
-                       {"announce/online", "message"} ->
-                           announce_online(From, To, Packet);
-                       _ ->
-                           Err = jlib:make_error_reply(
-                                   Packet, ?ERR_ITEM_NOT_FOUND),
-                           ejabberd_router:route(To, From, Err)
-                   end
+                   ejabberd_hooks:run(local_send_to_resource_hook,
+                                      [From, To, Packet])
            end;
        _ ->
            ejabberd_sm ! {route, From, To, Packet}
@@ -159,17 +156,7 @@ unregister_iq_handler(XMLNS) ->
 refresh_iq_handlers() ->
     ejabberd_local ! refresh_iq_handlers.
 
-announce_online(From, To, Packet) ->
-    case acl:match_rule(announce, From) of
-       deny ->
-           Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
-           ejabberd_router:route(To, From, Err);
-       allow ->
-           Local = jlib:make_jid("", ?MYNAME, ""),
-           lists:foreach(
-             fun({U, R}) ->
-                     Dest = jlib:make_jid(U, ?MYNAME, R),
-                     ejabberd_router:route(Local, Dest, Packet)
-             end, ejabberd_sm:dirty_get_sessions_list())
-    end.
-
+bounce_resource_packet(From, To, Packet) ->
+    Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND),
+    ejabberd_router:route(To, From, Err),
+    stop.
diff --git a/src/mod_announce.erl b/src/mod_announce.erl
new file mode 100644 (file)
index 0000000..29ac65e
--- /dev/null
@@ -0,0 +1,178 @@
+%%%----------------------------------------------------------------------
+%%% File    : mod_announce.erl
+%%% Author  : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose : Manage announce messages
+%%% Created : 11 Aug 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%% Id      : $Id$
+%%%----------------------------------------------------------------------
+
+-module(mod_announce).
+-author('alexey@sevcom.net').
+
+-behaviour(gen_mod).
+
+-export([start/1,
+        init/0,
+        stop/0,
+        announce/3,
+        send_motd/1]).
+
+-include("ejabberd.hrl").
+-include("jlib.hrl").
+
+-record(motd, {id, packet}).
+-record(motd_users, {luser, dummy = []}).
+
+-define(PROCNAME, ejabberd_announce).
+
+start(_) ->
+    mnesia:create_table(motd, [{disc_copies, [node()]},
+                              {attributes, record_info(fields, motd)}]),
+    mnesia:create_table(motd_users, [{disc_copies, [node()]},
+                                    {attributes, record_info(fields, motd_users)}]),
+    ejabberd_hooks:add(local_send_to_resource_hook,
+                      ?MODULE, announce, 50),
+    ejabberd_hooks:add(user_available_hook,
+                      ?MODULE, send_motd, 50),
+    register(?PROCNAME, proc_lib:spawn(?MODULE, init, [])).
+
+init() ->
+    loop().
+
+loop() ->
+    receive
+       {announce_online, From, To, Packet} ->
+           announce_online(From, To, Packet),
+           loop();
+       {announce_motd, From, To, Packet} ->
+           announce_motd(From, To, Packet),
+           loop();
+       {announce_motd_update, From, To, Packet} ->
+           announce_motd_update(From, To, Packet),
+           loop();
+       {announce_motd_delete, From, To, Packet} ->
+           announce_motd_delete(From, To, Packet),
+           loop();
+       _ ->
+           loop()
+    end.
+
+stop() ->
+    ejabberd_hooks:delete(local_send_to_resource_hook,
+                         ?MODULE, announce, 50),
+    ejabberd_hooks:delete(sm_register_connection_hook,
+                         ?MODULE, send_motd, 50),
+    exit(whereis(?PROCNAME), stop),
+    ok.
+
+announce(From, To, Packet) ->
+    case To of
+       #jid{luser = "", lresource = Res} ->
+           {xmlelement, Name, _Attrs, _Els} = Packet,
+               case {Res, Name} of
+                   {"announce/online", "message"} ->
+                       ?PROCNAME ! {announce_online, From, To, Packet},
+                       stop;
+                   {"announce/motd", "message"} ->
+                       ?PROCNAME ! {announce_motd, From, To, Packet},
+                       stop;
+                   {"announce/motd/update", "message"} ->
+                       ?PROCNAME ! {announce_motd_update, From, To, Packet},
+                       stop;
+                   {"announce/motd/delete", "message"} ->
+                       ?PROCNAME ! {announce_motd_delete, From, To, Packet},
+                       stop;
+                   _ ->
+                       ok
+           end;
+       _ ->
+           ok
+    end.
+
+announce_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(), Packet)
+    end.
+
+announce_online1(Sessions, Packet) ->
+    Server = ?MYNAME,
+    Local = jlib:make_jid("", Server, ""),
+    lists:foreach(
+      fun({U, R}) ->
+             Dest = jlib:make_jid(U, Server, R),
+             ejabberd_router:route(Local, Dest, Packet)
+      end, Sessions).
+
+announce_motd(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_motd_update(Packet),
+           Sessions = ejabberd_sm:dirty_get_sessions_list(),
+           announce_online1(Sessions, Packet),
+           F = fun() ->
+                       lists:foreach(
+                         fun({U, _R}) ->
+                                 mnesia:write(#motd_users{luser = U})
+                         end, Sessions)
+               end,
+           mnesia:transaction(F)
+    end.
+
+announce_motd_update(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_motd_update(Packet)
+    end.
+
+announce_motd_update(Packet) ->
+    announce_motd_delete(),
+    F = fun() ->
+               mnesia:write(#motd{id = motd, packet = Packet})
+       end,
+    mnesia:transaction(F).
+
+announce_motd_delete(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_motd_delete()
+    end.
+
+announce_motd_delete() ->
+    mnesia:clear_table(motd),
+    mnesia:clear_table(motd_users).
+
+send_motd(#jid{luser = LUser} = JID) ->
+    case catch mnesia:dirty_read({motd, motd}) of
+       [#motd{packet = Packet}] ->
+           case catch mnesia:dirty_read({motd_users, LUser}) of
+               [#motd_users{}] ->
+                   ok;
+               _ ->
+                   Local = jlib:make_jid("", ?MYNAME, ""),
+                   ejabberd_router:route(Local, JID, Packet),
+                   F = fun() ->
+                               mnesia:write(#motd_users{luser = LUser})
+                       end,
+                   mnesia:transaction(F)
+           end;
+       _ ->
+           ok
+    end.
+