use of org.jivesoftware.openfire.muc.MUCRoom in project Openfire by igniterealtime.
the class CreateMUCRoom method execute.
@Override
public void execute(SessionData sessionData, Element command) {
Element note = command.addElement("note");
Collection<JID> admins = XMPPServer.getInstance().getAdmins();
if (admins.size() <= 0) {
note.addAttribute("type", "error");
note.setText("Server needs admin user to be able to create rooms.");
return;
}
Map<String, List<String>> data = sessionData.getData();
// Let's find the requested MUC service to create the room in
String servicehostname = get(data, "servicename", 0);
if (servicehostname == null) {
note.addAttribute("type", "error");
note.setText("Service name must be specified.");
return;
}
// Remove the server's domain name from the passed hostname
String servicename = servicehostname.replace("." + XMPPServer.getInstance().getServerInfo().getXMPPDomain(), "");
MultiUserChatService mucService;
mucService = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService(servicename);
if (mucService == null) {
note.addAttribute("type", "error");
note.setText("Invalid service name specified.");
return;
}
if (!mucService.isServiceEnabled()) {
note.addAttribute("type", "error");
note.setText("Multi user chat is disabled for specified service.");
return;
}
// Let's create the jid and check that they are a local user
String roomname = get(data, "roomname", 0);
if (roomname == null) {
note.addAttribute("type", "error");
note.setText("Room name must be specified.");
return;
}
JID admin = admins.iterator().next();
MUCRoom room;
try {
room = mucService.getChatRoom(roomname, admin);
} catch (NotAllowedException e) {
note.addAttribute("type", "error");
note.setText("No permission to create rooms.");
return;
}
boolean isPersistent = "1".equals(get(data, "persistent", 0));
room.setPersistent(isPersistent);
boolean isPublic = "1".equals(get(data, "public", 0));
room.setPublicRoom(isPublic);
String password = get(data, "password", 0);
if (password != null) {
room.setPassword(password);
}
}
use of org.jivesoftware.openfire.muc.MUCRoom in project Openfire by igniterealtime.
the class IQMUCRegisterHandler method handleIQ.
public IQ handleIQ(IQ packet) {
IQ reply = null;
// Get the target room
MUCRoom room = null;
String name = packet.getTo().getNode();
if (name != null) {
room = mucService.getChatRoom(name);
}
if (room == null) {
// The room doesn't exist so answer a NOT_FOUND error
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(PacketError.Condition.item_not_found);
return reply;
} else if (!room.isRegistrationEnabled() || (packet.getFrom() != null && MUCRole.Affiliation.outcast == room.getAffiliation(packet.getFrom().asBareJID()))) {
// The room does not accept users to register or
// the user is an outcast and is not allowed to register
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(PacketError.Condition.not_allowed);
return reply;
}
if (IQ.Type.get == packet.getType()) {
reply = IQ.createResultIQ(packet);
String nickname = room.getReservedNickname(packet.getFrom());
Element currentRegistration = probeResult.createCopy();
if (nickname != null) {
// The user is already registered with the room so answer a completed form
ElementUtil.setProperty(currentRegistration, "query.registered", null);
currentRegistration.addElement("username").addText(nickname);
Element form = currentRegistration.element(QName.get("x", "jabber:x:data"));
currentRegistration.remove(form);
// @SuppressWarnings("unchecked")
// Iterator<Element> fields = form.elementIterator("field");
//
// Element field;
// while (fields.hasNext()) {
// field = fields.next();
// if ("muc#register_roomnick".equals(field.attributeValue("var"))) {
// field.addElement("value").addText(nickname);
// }
// }
reply.setChildElement(currentRegistration);
} else {
// The user is not registered with the room so answer an empty form
reply.setChildElement(currentRegistration);
}
} else if (IQ.Type.set == packet.getType()) {
try {
// Keep a registry of the updated presences
List<Presence> presences = new ArrayList<>();
reply = IQ.createResultIQ(packet);
Element iq = packet.getChildElement();
if (ElementUtil.includesProperty(iq, "query.remove")) {
// The user is deleting his registration
presences.addAll(room.addNone(packet.getFrom(), room.getRole()));
} else {
// The user is trying to register with a room
Element formElement = iq.element("x");
// Check if a form was used to provide the registration info
if (formElement != null) {
// Get the sent form
final DataForm registrationForm = new DataForm(formElement);
// Get the desired nickname sent in the form
List<String> values = registrationForm.getField("muc#register_roomnick").getValues();
String nickname = (!values.isEmpty() ? values.get(0) : null);
// TODO The rest of the fields of the form are ignored. If we have a
// requirement in the future where we need those fields we'll have to change
// MUCRoom.addMember in order to receive a RegistrationInfo (new class)
// Add the new member to the members list
presences.addAll(room.addMember(packet.getFrom(), nickname, room.getRole()));
} else {
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(PacketError.Condition.bad_request);
}
}
// Send the updated presences to the room occupants
for (Presence presence : presences) {
room.send(presence);
}
} catch (ForbiddenException e) {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(PacketError.Condition.forbidden);
} catch (ConflictException e) {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(PacketError.Condition.conflict);
} catch (Exception e) {
Log.error(e.getMessage(), e);
}
}
return reply;
}
use of org.jivesoftware.openfire.muc.MUCRoom in project Openfire by igniterealtime.
the class IQMUCSearchHandler method handleIQ.
/**
* Constructs an answer on a IQ stanza that contains a search request. The
* answer will be an IQ stanza of type 'result' or 'error'.
*
* @param iq
* The IQ stanza that is the search request.
* @return An answer to the provided request.
*/
public IQ handleIQ(IQ iq) {
final IQ reply = IQ.createResultIQ(iq);
final Element formElement = iq.getChildElement().element(QName.get("x", "jabber:x:data"));
if (formElement == null) {
reply.setChildElement(getDataElement());
return reply;
}
// parse params from request.
final DataForm df = new DataForm(formElement);
boolean name_is_exact_match = false;
String subject = null;
int numusers = -1;
int numaxusers = -1;
boolean includePasswordProtectedRooms = true;
final Set<String> names = new HashSet<>();
for (final FormField field : df.getFields()) {
if (field.getVariable().equals("name")) {
names.add(field.getFirstValue());
}
}
final FormField matchFF = df.getField("name_is_exact_match");
if (matchFF != null) {
final String b = matchFF.getFirstValue();
if (b != null) {
name_is_exact_match = b.equals("1") || b.equalsIgnoreCase("true") || b.equalsIgnoreCase("yes");
}
}
final FormField subjectFF = df.getField("subject");
if (subjectFF != null) {
subject = subjectFF.getFirstValue();
}
try {
final FormField userAmountFF = df.getField("num_users");
if (userAmountFF != null) {
String value = userAmountFF.getFirstValue();
if (value != null && !"".equals(value)) {
numusers = Integer.parseInt(value);
}
}
final FormField maxUsersFF = df.getField("num_max_users");
if (maxUsersFF != null) {
String value = maxUsersFF.getFirstValue();
if (value != null && !"".equals(value)) {
numaxusers = Integer.parseInt(value);
}
}
} catch (NumberFormatException e) {
reply.setError(PacketError.Condition.bad_request);
return reply;
}
final FormField includePasswordProtectedRoomsFF = df.getField("include_password_protected");
if (includePasswordProtectedRoomsFF != null) {
final String b = includePasswordProtectedRoomsFF.getFirstValue();
if (b != null) {
if (b.equals("0") || b.equalsIgnoreCase("false") || b.equalsIgnoreCase("no")) {
includePasswordProtectedRooms = false;
}
}
}
// search for chatrooms matching the request params.
final List<MUCRoom> mucs = new ArrayList<>();
for (MUCRoom room : mucService.getChatRooms()) {
boolean find = false;
if (names.size() > 0) {
for (final String name : names) {
if (name_is_exact_match) {
if (name.equalsIgnoreCase(room.getNaturalLanguageName())) {
find = true;
break;
}
} else {
if (room.getNaturalLanguageName().toLowerCase().indexOf(name.toLowerCase()) != -1) {
find = true;
break;
}
}
}
}
if (subject != null && room.getSubject().toLowerCase().indexOf(subject.toLowerCase()) != -1) {
find = true;
}
if (numusers > -1 && room.getParticipants().size() < numusers) {
find = false;
}
if (numaxusers > -1 && room.getMaxUsers() < numaxusers) {
find = false;
}
if (!includePasswordProtectedRooms && room.isPasswordProtected()) {
find = false;
}
if (find && canBeIncludedInResult(room)) {
mucs.add(room);
}
}
final ResultSet<MUCRoom> searchResults = new ResultSetImpl<>(sortByUserAmount(mucs));
// See if the requesting entity would like to apply 'result set
// management'
final Element set = iq.getChildElement().element(QName.get("set", ResultSet.NAMESPACE_RESULT_SET_MANAGEMENT));
final List<MUCRoom> mucrsm;
// apply RSM only if the element exists, and the (total) results
// set is not empty.
final boolean applyRSM = set != null && !mucs.isEmpty();
if (applyRSM) {
if (!ResultSet.isValidRSMRequest(set)) {
reply.setError(Condition.bad_request);
return reply;
}
try {
mucrsm = searchResults.applyRSMDirectives(set);
} catch (NullPointerException e) {
final IQ itemNotFound = IQ.createResultIQ(iq);
itemNotFound.setError(Condition.item_not_found);
return itemNotFound;
}
} else {
// if no rsm, all found rooms are part of the result.
mucrsm = new ArrayList<>(searchResults);
}
final Element res = DocumentHelper.createElement(QName.get("query", "jabber:iq:search"));
final DataForm resultform = new DataForm(DataForm.Type.result);
boolean atLeastoneResult = false;
for (MUCRoom room : mucrsm) {
final Map<String, Object> fields = new HashMap<>();
fields.put("name", room.getNaturalLanguageName());
fields.put("subject", room.getSubject());
fields.put("num_users", room.getOccupantsCount());
fields.put("num_max_users", room.getMaxUsers());
fields.put("is_password_protected", room.isPasswordProtected());
fields.put("is_member_only", room.isMembersOnly());
fields.put("jid", room.getRole().getRoleAddress().toString());
resultform.addItemFields(fields);
atLeastoneResult = true;
}
if (atLeastoneResult) {
resultform.addReportedField("name", "Name", FormField.Type.text_single);
resultform.addReportedField("subject", "Subject", FormField.Type.text_single);
resultform.addReportedField("num_users", "Number of users", FormField.Type.text_single);
resultform.addReportedField("num_max_users", "Max number allowed of users", FormField.Type.text_single);
resultform.addReportedField("is_password_protected", "Is a password protected room.", FormField.Type.boolean_type);
resultform.addReportedField("is_member_only", "Is a member only room.", FormField.Type.boolean_type);
resultform.addReportedField("jid", "JID", FormField.Type.jid_single);
}
res.add(resultform.getElement());
if (applyRSM) {
res.add(searchResults.generateSetElementFromResults(mucrsm));
}
reply.setChildElement(res);
return reply;
}
use of org.jivesoftware.openfire.muc.MUCRoom in project Openfire by igniterealtime.
the class MultiUserChatServiceImpl method broadcastShutdown.
/**
* Informs all users local to this cluster node that he or she is being removed from the room because the MUC
* service is being shut down.
*
* The implementation is optimized to run as fast as possible (to prevent prolonging the shutdown).
*/
private void broadcastShutdown() {
Log.debug("Notifying all local users about the imminent destruction of chat service '{}'", chatServiceName);
if (users.isEmpty()) {
return;
}
// A thread pool is used to broadcast concurrently, as well as to limit the execution time of this service.
final ExecutorService service = Executors.newFixedThreadPool(Math.min(users.size(), 10));
// Queue all tasks in the executor service.
for (final LocalMUCUser user : users.values()) {
// Submit a concurrent task for each local user (that could be in more than one (local) room).
service.submit(new Runnable() {
@Override
public void run() {
try {
for (final LocalMUCRole role : user.getRoles()) {
final MUCRoom room = role.getChatRoom();
// Send a presence stanza of type "unavailable" to the occupant
final Presence presence = room.createPresence(Presence.Type.unavailable);
presence.setFrom(role.getRoleAddress());
// A fragment containing the x-extension.
final Element fragment = presence.addChildElement("x", "http://jabber.org/protocol/muc#user");
final Element item = fragment.addElement("item");
item.addAttribute("affiliation", "none");
item.addAttribute("role", "none");
fragment.addElement("status").addAttribute("code", "332");
// Make sure that the presence change for each user is only sent to that user (and not broadcasted in the room)!
role.send(presence);
}
} catch (Exception e) {
Log.debug("Unable to inform {} about the imminent destruction of chat service '{}'", user.getAddress(), chatServiceName, e);
}
}
});
}
// Try to shutdown - wait - force shutdown.
service.shutdown();
try {
service.awaitTermination(JiveGlobals.getIntProperty("xmpp.muc.await-termination-millis", 500), TimeUnit.MILLISECONDS);
Log.debug("Successfully notified all {} local users about the imminent destruction of chat service '{}'", users.size(), chatServiceName);
} catch (InterruptedException e) {
Log.debug("Interrupted while waiting for all users to be notified of shutdown of chat service '{}'. Shutting down immediately.", chatServiceName);
}
service.shutdownNow();
}
use of org.jivesoftware.openfire.muc.MUCRoom in project Openfire by igniterealtime.
the class MultiUserChatServiceImpl method checkForTimedOutUsers.
private void checkForTimedOutUsers() {
final long deadline = System.currentTimeMillis() - user_idle;
for (LocalMUCUser user : users.values()) {
try {
// the list of users
if (!user.isJoined()) {
removeUser(user.getAddress());
continue;
}
// Do nothing if this feature is disabled (i.e USER_IDLE equals -1)
if (user_idle == -1) {
continue;
}
if (user.getLastPacketTime() < deadline) {
// Kick the user from all the rooms that he/she had previuosly joined
MUCRoom room;
Presence kickedPresence;
for (LocalMUCRole role : user.getRoles()) {
room = role.getChatRoom();
try {
kickedPresence = room.kickOccupant(user.getAddress(), null, null, null);
// Send the updated presence to the room occupants
room.send(kickedPresence);
} catch (NotAllowedException e) {
// Do nothing since we cannot kick owners or admins
}
}
}
} catch (Throwable e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
}
}
Aggregations