</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
\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
{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" ->
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) ->
{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),