From cbf63d06a8b77c15b783e7d90f9580e8601c86c2 Mon Sep 17 00:00:00 2001
From: Badlop <badlop@process-one.net>
Date: Fri, 13 Jun 2008 18:55:26 +0000
Subject: [PATCH] * src/mod_muc/mod_muc_room.erl: Allow admins to send messages
 to rooms even if not joined (EJAB-645) * doc/guide.tex: Likewise *
 doc/guide.html: Likewise

SVN Revision: 1356
---
 ChangeLog                    |  5 +++++
 doc/guide.html               |  8 +++++---
 doc/guide.tex                |  8 +++++---
 src/mod_muc/mod_muc_room.erl | 40 +++++++++++++++++++++++++++++++-----
 4 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8f63ca567..a982a99e0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2008-06-13  Badlop  <badlop@process-one.net>
 
+	* src/mod_muc/mod_muc_room.erl: Allow admins to send messages to
+	rooms even if not joined (EJAB-645)
+	* doc/guide.tex: Likewise
+	* doc/guide.html: Likewise
+
 	* src/ejabberd.cfg.example: Add registration_timeout (EJAB-653)
 
 	* doc/guide.tex: Table of listener modules converted to
diff --git a/doc/guide.html b/doc/guide.html
index 23a4703d9..b94c65959 100644
--- a/doc/guide.html
+++ b/doc/guide.html
@@ -1922,9 +1922,11 @@ allowed to modify the &#X2019;persistent&#X2019; chatroom option
 </DD><DT CLASS="dt-description"><B><TT>access_admin</TT></B></DT><DD CLASS="dd-description"> This option specifies
 who is allowed to administrate the Multi-User Chat service (the default
 value is <TT>none</TT>, which means that only the room creator can
-administer his room). By sending a message to the service JID,
-administrators can send service messages that will be displayed in every
-active room.
+administer his room).
+The administrators can send a normal message to the service JID,
+and it will be shown in every active room as a service message.
+The administrators can send a groupchat message to the JID of an active room,
+and the message will be shown in the room as a service message.
 </DD><DT CLASS="dt-description"><B><TT>history_size</TT></B></DT><DD CLASS="dd-description"> A small history of
 the current discussion is sent to users when they enter the
 room. With this option you can define the number of history messages
diff --git a/doc/guide.tex b/doc/guide.tex
index 7612c9a29..73d889fc5 100644
--- a/doc/guide.tex
+++ b/doc/guide.tex
@@ -2522,9 +2522,11 @@ Module options:
 \titem{access\_admin} \ind{options!access\_admin}This option specifies
   who is allowed to administrate the Multi-User Chat service (the default
   value is \term{none}, which means that only the room creator can
-  administer his room). By sending a message to the service JID,
-  administrators can send service messages that will be displayed in every
-  active room.
+  administer his room).
+  The administrators can send a normal message to the service JID,
+  and it will be shown in every active room as a service message.
+  The administrators can send a groupchat message to the JID of an active room,
+  and the message will be shown in the room as a service message.
 \titem{history\_size} \ind{options!history\_size}A small history of
   the current discussion is sent to users when they enter the
   room. With this option you can define the number of history messages
diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl
index 91da61e2b..e858d680f 100644
--- a/src/mod_muc/mod_muc_room.erl
+++ b/src/mod_muc/mod_muc_room.erl
@@ -204,7 +204,8 @@ normal_state({route, From, "",
 	      {xmlelement, "message", Attrs, Els} = Packet},
 	     StateData) ->
     Lang = xml:get_attr_s("xml:lang", Attrs),
-    case is_user_online(From, StateData) of
+    case is_user_online(From, StateData) orelse
+	is_user_allowed_message_nonparticipant(From, StateData) of
 	true ->
 	    case xml:get_attr_s("type", Attrs) of
 		"groupchat" ->
@@ -784,11 +785,10 @@ route(Pid, From, ToNick, Packet) ->
 process_groupchat_message(From, {xmlelement, "message", Attrs, _Els} = Packet,
 			  StateData) ->
     Lang = xml:get_attr_s("xml:lang", Attrs),
-    case is_user_online(From, StateData) of
+    case is_user_online(From, StateData) orelse
+	is_user_allowed_message_nonparticipant(From, StateData) of
 	true ->
-	    {ok, #user{nick = FromNick, role = Role}} =
-		?DICT:find(jlib:jid_tolower(From),
-			   StateData#state.users),
+	    {FromNick, Role} = get_participant_data(From, StateData),
 	    if
 		(Role == moderator) or (Role == participant) 
 		or ((StateData#state.config)#config.moderated == false) ->
@@ -873,6 +873,36 @@ process_groupchat_message(From, {xmlelement, "message", Attrs, _Els} = Packet,
 	    {next_state, normal_state, StateData}
     end.
 
+
+%% @doc Check if this non participant can send message to room.
+%%
+%% XEP-0045 v1.23:
+%% 7.9 Sending a Message to All Occupants
+%% an implementation MAY allow users with certain privileges
+%% (e.g., a room owner, room admin, or service-level admin)
+%% to send messages to the room even if those users are not occupants.
+%%
+%% Check the mod_muc option access_message_nonparticipant and wether this JID
+%% is allowed or denied
+is_user_allowed_message_nonparticipant(JID, StateData) ->
+    {_AccessRoute, _AccessCreate, AccessAdmin, _AccessPersistent} = StateData#state.access,
+    case acl:match_rule(StateData#state.server_host, AccessAdmin, JID) of
+	allow ->
+	    true;
+	_ -> false
+    end.
+
+%% @doc Get information of this participant, or default values.
+%% If the JID is not a participant, return values for a service message.
+get_participant_data(From, StateData) ->
+    case ?DICT:find(jlib:jid_tolower(From), StateData#state.users) of
+	{ok, #user{nick = FromNick, role = Role}} ->
+	    {FromNick, Role};
+	error ->
+	    {"", moderator}
+    end.
+
+
 process_presence(From, Nick, {xmlelement, "presence", Attrs, _Els} = Packet,
 		 StateData) ->
     Type = xml:get_attr_s("type", Attrs),
-- 
2.40.0