%@ page contentType="text/html; charset=UTF-8" %> <%-- - - Copyright (C) 2004-2008 Jive Software, 2017-2025 Ignite Realtime Foundation. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> <%@ page import="gnu.inet.encoding.Stringprep, gnu.inet.encoding.StringprepException, java.net.URLEncoder, java.nio.charset.StandardCharsets, java.util.*, org.dom4j.Element, org.jivesoftware.openfire.muc.MUCRoom, org.jivesoftware.openfire.muc.NotAllowedException, org.jivesoftware.openfire.muc.Role, org.jivesoftware.openfire.muc.spi.MUCPersistenceManager, org.jivesoftware.openfire.vcard.VCardBean, org.jivesoftware.openfire.vcard.VCardManager, org.jivesoftware.util.CookieUtils, org.jivesoftware.util.ParamUtils, org.jivesoftware.util.StringUtils, org.xmpp.forms.*, org.xmpp.packet.IQ, org.xmpp.packet.JID, org.xmpp.packet.Message" errorPage="error.jsp" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <%@ taglib uri="admin" prefix="admin" %> <% webManager.init(request, response, session, application, out); %> <% // Get parameters Map errors = new HashMap<>(); boolean create = ParamUtils.getBooleanParameter(request,"create"); boolean save = ParamUtils.getBooleanParameter(request,"save"); boolean success = ParamUtils.getBooleanParameter(request,"success"); boolean addsuccess = ParamUtils.getBooleanParameter(request,"addsuccess"); boolean clearchatsuccess = ParamUtils.getBooleanParameter(request,"clearchatsuccess"); String roomName = ParamUtils.getParameter(request,"roomName"); String mucName = ParamUtils.getParameter(request,"mucName"); String roomJIDStr = ParamUtils.getParameter(request,"roomJID"); JID roomJID = null; if (roomName != null && mucName != null) { try { JID.nodeprep( roomName ); } catch ( IllegalArgumentException e ) { errors.put("roomName","roomName"); } try { JID.domainprep( mucName ); } catch ( IllegalArgumentException e ) { errors.put("mucName","mucName"); } if ( errors.isEmpty() ) { roomJID = new JID( roomName, mucName, null ); } } else if (roomJIDStr != null) { try { roomJID = new JID( roomJIDStr ); } catch ( IllegalArgumentException e ) { errors.put( "roomJID", "roomJID" ); } if ( roomJID != null ) { roomName = roomJID.getNode(); mucName = roomJID.getDomain(); } } String naturalName = ParamUtils.getParameter(request,"roomconfig_roomname"); String description = ParamUtils.getParameter(request,"roomconfig_roomdesc"); String maxUsers = ParamUtils.getParameter(request, "roomconfig_maxusers"); boolean broadcastModerator = ParamUtils.getBooleanParameter(request, "roomconfig_presencebroadcast"); boolean broadcastParticipant = ParamUtils.getBooleanParameter(request, "roomconfig_presencebroadcast2"); boolean broadcastVisitor = ParamUtils.getBooleanParameter(request, "roomconfig_presencebroadcast3"); String password = ParamUtils.getParameter(request, "roomconfig_roomsecret"); String confirmPassword = ParamUtils.getParameter(request, "roomconfig_roomsecret2"); String whois = ParamUtils.getParameter(request, "roomconfig_whois"); String allowpm = ParamUtils.getParameter(request, "roomconfig_allowpm"); boolean publicRoom = ParamUtils.getBooleanParameter(request, "roomconfig_publicroom"); boolean persistentRoom = ParamUtils.getBooleanParameter(request, "roomconfig_persistentroom"); boolean retireOnDeletion = ParamUtils.getBooleanParameter(request, "roomconfig_retireondel"); boolean moderatedRoom = ParamUtils.getBooleanParameter(request, "roomconfig_moderatedroom"); boolean membersOnly = ParamUtils.getBooleanParameter(request, "roomconfig_membersonly"); boolean allowInvites = ParamUtils.getBooleanParameter(request, "roomconfig_allowinvites"); boolean changeSubject = ParamUtils.getBooleanParameter(request, "roomconfig_changesubject"); boolean enableLog = ParamUtils.getBooleanParameter(request, "roomconfig_enablelogging"); boolean preserveHistOnRoomDeletion = ParamUtils.getBooleanParameter(request, "roomconfig_preservehistondel"); boolean reservedNick = ParamUtils.getBooleanParameter(request, "roomconfig_reservednick"); boolean canchangenick = ParamUtils.getBooleanParameter(request, "roomconfig_canchangenick"); boolean registration = ParamUtils.getBooleanParameter(request, "roomconfig_registration"); String roomSubject = ParamUtils.getParameter(request, "room_topic", true); if (webManager.getMultiUserChatManager().getMultiUserChatServicesCount() < 1) { // No services exist, so redirect to where one can configure the services response.sendRedirect("muc-service-summary.jsp"); return; } // Handle a cancel if (request.getParameter("cancel") != null) { if (roomJID == null) { // case when canceling creating a new room response.sendRedirect("muc-room-summary.jsp"); } else { // case when canceling a room edit, used on summary to set service response.sendRedirect("muc-room-summary.jsp?roomJID="+URLEncoder.encode(roomJID.toBareJID(), StandardCharsets.UTF_8)); } return; } // Load the room object MUCRoom room = null; if (!create) { room = webManager.getMultiUserChatManager().getMultiUserChatService(roomJID).getChatRoom(roomName); if (room == null) { // The requested room name does not exist so return to the list of the existing rooms response.sendRedirect("muc-room-summary.jsp?roomJID="+URLEncoder.encode(roomJID.toBareJID(), StandardCharsets.UTF_8)); return; } } // Handle an save Cookie csrfCookie = CookieUtils.getCookie(request, "csrf"); String csrfParam = ParamUtils.getParameter(request, "csrf"); if (save) { if (csrfCookie == null || csrfParam == null || !csrfCookie.getValue().equals(csrfParam)) { save = false; errors.put("csrf", "CSRF Failure!"); } } csrfParam = StringUtils.randomString(15); CookieUtils.setCookie(request, response, "csrf", csrfParam, -1); pageContext.setAttribute("csrf", csrfParam); if (save) { // do validation if (naturalName == null) { errors.put("roomconfig_roomname","roomconfig_roomname"); } if (description == null) { errors.put("roomconfig_roomdesc","roomconfig_roomdesc"); } if (maxUsers == null || maxUsers.isEmpty()) { maxUsers = "0"; // 0 indicates no limit. } try { Integer.parseInt(maxUsers); } catch ( NumberFormatException e ) { errors.put("roomconfig_maxusers", "roomconfig_maxusers"); } if (password != null && !password.equals(confirmPassword)) { errors.put("roomconfig_roomsecret2","roomconfig_roomsecret2"); } if (whois == null) { errors.put("roomconfig_whois","roomconfig_whois"); } if ( allowpm == null || !( allowpm.equals( "anyone" ) || allowpm.equals( "moderators" ) || allowpm.equals( "participants" ) || allowpm.equals( "none" )) ) { errors.put("roomconfig_allowpm","romconfig_allowpm"); } if (roomSubject != null && roomSubject.length() > 100) { errors.put("room_topic_longer","room_topic_longer"); } if (create && errors.isEmpty()) { if (roomName == null || roomName.contains("@")) { errors.put("roomName","roomName"); } else { // Check that the room name is a valid node try { roomName = Stringprep.nodeprep(roomName); } catch (StringprepException e) { errors.put("roomName","roomName"); } } if (errors.isEmpty()) { // Check that the requested room ID is available room = webManager.getMultiUserChatManager().getMultiUserChatService(roomJID).getChatRoom(roomName); if (room != null) { errors.put("room_already_exists", "room_already_exists"); } else { // Try to create a new room JID address = new JID(webManager.getUser().getUsername(), webManager.getServerInfo().getXMPPDomain(), null); try { room = webManager.getMultiUserChatManager().getMultiUserChatService(roomJID).getChatRoom(roomName, address); // Check if the room was created concurrently by another user if (!room.getOwners().contains(address.asBareJID())) { errors.put("room_already_exists", "room_already_exists"); } } catch (NotAllowedException e) { // This user is not allowed to create rooms, or it has been retired String cause = switch(e.getReason()) { case ROOM_RETIRED -> "room_retired"; case INSUFFICIENT_PERMISSIONS -> "not_enough_permissions"; }; errors.put(cause, cause); } } } } if (errors.isEmpty()) { // Set the new configuration sending an IQ packet with an dataform final DataForm dataForm = new DataForm(DataForm.Type.submit); dataForm.addField("FORM_TYPE", null, FormField.Type.hidden).addValue("http://jabber.org/protocol/muc#roomconfig"); dataForm.addField("muc#roomconfig_roomname", null, null).addValue(naturalName); dataForm.addField("muc#roomconfig_roomdesc", null, null).addValue(description); dataForm.addField("muc#roomconfig_changesubject", null, null).addValue(changeSubject ? "1": "0"); dataForm.addField("muc#roomconfig_maxusers", null, null).addValue(maxUsers); final FormField broadcastField = dataForm.addField("muc#roomconfig_presencebroadcast", null, null); if (broadcastModerator) { broadcastField.addValue(Role.moderator); } if (broadcastParticipant) { broadcastField.addValue(Role.participant); } if (broadcastVisitor) { broadcastField.addValue(Role.visitor); } dataForm.addField("muc#roomconfig_publicroom", null, null).addValue(publicRoom ? "1": "0"); dataForm.addField("muc#roomconfig_persistentroom", null, null).addValue(persistentRoom ? "1": "0"); dataForm.addField("{http://igniterealtime.org}muc#roomconfig_retireondel", null, null).addValue(retireOnDeletion ? "1": "0"); dataForm.addField("muc#roomconfig_moderatedroom", null, null).addValue(moderatedRoom ? "1": "0"); dataForm.addField("muc#roomconfig_membersonly", null, null).addValue(membersOnly ? "1": "0"); dataForm.addField("muc#roomconfig_allowinvites", null, null).addValue(allowInvites ? "1": "0"); dataForm.addField("muc#roomconfig_passwordprotectedroom", null, null).addValue((password == null) ? "0": "1"); dataForm.addField("muc#roomconfig_roomsecret", null, null).addValue(password); dataForm.addField("muc#roomconfig_whois", null, null).addValue(whois); dataForm.addField("muc#roomconfig_allowpm", null, null).addValue(allowpm); dataForm.addField("muc#roomconfig_enablelogging", null, null).addValue(enableLog ? "1": "0"); dataForm.addField("{http://igniterealtime.org}muc#roomconfig_preservehistondel", null, null).addValue(preserveHistOnRoomDeletion ? "1": "0"); dataForm.addField("x-muc#roomconfig_reservednick", null, null).addValue(reservedNick ? "1": "0"); dataForm.addField("x-muc#roomconfig_canchangenick", null, null).addValue(canchangenick ? "1": "0"); dataForm.addField("x-muc#roomconfig_registration", null, null).addValue(registration ? "1": "0"); final FormField roomAdminsField = dataForm.addField("muc#roomconfig_roomadmins", null, null); room.getAdmins().forEach( admin -> roomAdminsField.addValue( admin.toString() )); // Keep the existing list of owners final FormField roomOwnersField = dataForm.addField("muc#roomconfig_roomowners", null, null); room.getOwners().forEach( owner -> roomOwnersField.addValue( owner.toString() )); // update subject before sending IQ (to include subject with cluster update) if (roomSubject != null) { // Change the subject of the room by sending a new message Message message = new Message(); message.setType(Message.Type.groupchat); message.setSubject(roomSubject); message.setFrom(room.getSelfRepresentation().getOccupantJID()); message.setTo(room.getSelfRepresentation().getOccupantJID()); room.changeSubject(message, room.getSelfRepresentation()); } // Create an IQ packet and set the dataform as the main fragment IQ iq = new IQ(IQ.Type.set); Element element = iq.setChildElement("query", "http://jabber.org/protocol/muc#owner"); element.add(dataForm.getElement()); // Send the IQ packet that will modify the room's configuration room.getIQOwnerHandler().handleIQ(iq, room.getSelfRepresentation()); webManager.getMultiUserChatManager().getMultiUserChatService(roomJID).syncChatRoom(room); // Changes good, so redirect String params; if (create) { params = "addsuccess=true&roomJID=" + URLEncoder.encode(roomJID.toBareJID(), StandardCharsets.UTF_8); // Log the event webManager.logEvent("created new MUC room "+roomName, "subject = "+roomSubject+"\nroomdesc = "+description+"\nroomname = "+naturalName+"\nmaxusers = "+maxUsers); } else { params = "success=true&roomJID=" + URLEncoder.encode(roomJID.toBareJID(), StandardCharsets.UTF_8); // Log the event webManager.logEvent("updated MUC room "+roomName, "subject = "+roomSubject+"\nroomdesc = "+description+"\nroomname = "+naturalName+"\nmaxusers = "+maxUsers); } response.sendRedirect("muc-room-edit-form.jsp?" + params); return; } } else { if (create) { // Before a selection for a service has been made (which is part of the room creation process in cases where // more than one service exists) it's impossible to predict what service-specific configuration to use. To prevent // having the user to go through a second step, we'll use the first available service. Given that having more than one // service is a very uncommon scenario, this is an acceptable shortcut. final String serviceName = webManager.getMultiUserChatManager().getMultiUserChatServices().iterator().next().getServiceName(); maxUsers = MUCPersistenceManager.getProperty(serviceName, "room.maxUsers", "30"); broadcastModerator = MUCPersistenceManager.getBooleanProperty(serviceName, "room.broadcastModerator", true); broadcastParticipant = MUCPersistenceManager.getBooleanProperty(serviceName, "room.broadcastParticipant", true); broadcastVisitor = MUCPersistenceManager.getBooleanProperty(serviceName, "room.broadcastVisitor", true); whois = MUCPersistenceManager.getBooleanProperty(serviceName, "room.canAnyoneDiscoverJID", true) ? "anyone" : "moderator"; allowpm = MUCPersistenceManager.getProperty(serviceName, "room.allowpm", "anyone"); publicRoom = MUCPersistenceManager.getBooleanProperty(serviceName, "room.publicRoom", true); persistentRoom = true; // Rooms created from the admin console are always persistent retireOnDeletion = MUCPersistenceManager.getBooleanProperty(serviceName, "room.retireOnDeletion", false); moderatedRoom = MUCPersistenceManager.getBooleanProperty(serviceName, "room.moderated", false); membersOnly = MUCPersistenceManager.getBooleanProperty(serviceName, "room.membersOnly", false); allowInvites = MUCPersistenceManager.getBooleanProperty(serviceName, "room.canOccupantsInvite", false); changeSubject = MUCPersistenceManager.getBooleanProperty(serviceName, "room.canOccupantsChangeSubject", false); enableLog = MUCPersistenceManager.getBooleanProperty(serviceName, "room.logEnabled", true); preserveHistOnRoomDeletion = MUCPersistenceManager.getBooleanProperty(serviceName, "room.preserveHistOnRoomDeletion", true); reservedNick = MUCPersistenceManager.getBooleanProperty(serviceName, "room.loginRestrictedToNickname", false); canchangenick = MUCPersistenceManager.getBooleanProperty(serviceName, "room.canChangeNickname", true); registration = MUCPersistenceManager.getBooleanProperty(serviceName, "room.registrationEnabled", true); } else { naturalName = room.getNaturalLanguageName(); description = room.getDescription(); roomSubject = room.getSubject(); maxUsers = Integer.toString(room.getMaxUsers()); broadcastModerator = room.canBroadcastPresence(Role.moderator); broadcastParticipant = room.canBroadcastPresence(Role.participant); broadcastVisitor = room.canBroadcastPresence(Role.visitor); password = room.getPassword(); confirmPassword = room.getPassword(); whois = (room.canAnyoneDiscoverJID() ? "anyone" : "moderator"); allowpm = room.canSendPrivateMessage(); publicRoom = room.isPublicRoom(); persistentRoom = room.isPersistent(); retireOnDeletion = room.isRetireOnDeletion(); moderatedRoom = room.isModerated(); membersOnly = room.isMembersOnly(); allowInvites = room.canOccupantsInvite(); changeSubject = room.canOccupantsChangeSubject(); enableLog = room.isLogEnabled(); preserveHistOnRoomDeletion = room.isPreserveHistOnRoomDeletionEnabled(); reservedNick = room.isLoginRestrictedToNickname(); canchangenick = room.canChangeNickname(); registration = room.isRegistrationEnabled(); } } roomName = roomName == null ? "" : roomName; if (roomJID != null) { final Element vCardElement = VCardManager.getInstance().getVCard(roomJID.toString()); VCardBean vCardBean = new VCardBean(); vCardBean.loadFromElement(vCardElement); pageContext.setAttribute("vCard", vCardBean); } pageContext.setAttribute("errors", errors); pageContext.setAttribute("create", create); pageContext.setAttribute("success", success); pageContext.setAttribute("addsuccess", addsuccess); pageContext.setAttribute("clearchatsuccess", clearchatsuccess); pageContext.setAttribute("room", room); pageContext.setAttribute("roomJID", roomJID); pageContext.setAttribute("roomJIDBare", roomJID != null ? roomJID.toBareJID() : null); pageContext.setAttribute("persistentRoom", persistentRoom); pageContext.setAttribute("roomName", roomName); pageContext.setAttribute("mucName", mucName); pageContext.setAttribute("naturalName", naturalName); pageContext.setAttribute("description", description); pageContext.setAttribute("roomSubject", roomSubject); pageContext.setAttribute("maxUser", maxUsers); pageContext.setAttribute("broadcastModerator", broadcastModerator); pageContext.setAttribute("broadcastParticipant", broadcastParticipant); pageContext.setAttribute("broadcastVisitor", broadcastVisitor); pageContext.setAttribute("password", password); pageContext.setAttribute("confirmPassword", confirmPassword); pageContext.setAttribute("whois", whois); pageContext.setAttribute("allowpm", allowpm); pageContext.setAttribute("publicRoom", publicRoom); pageContext.setAttribute("retireOnDeletion", retireOnDeletion); pageContext.setAttribute("moderatedRoom", moderatedRoom); pageContext.setAttribute("membersonly", membersOnly); pageContext.setAttribute("allowInvites", allowInvites); pageContext.setAttribute("changeSubject", changeSubject); pageContext.setAttribute("reservedNick", reservedNick); pageContext.setAttribute("canchangenick", canchangenick); pageContext.setAttribute("registration", registration); pageContext.setAttribute("enableLog", enableLog); pageContext.setAttribute("preserveHistOnRoomDeletion", preserveHistOnRoomDeletion); %> "/> : () / / : * @ @ : : * : * : : : : value="${fn:escapeXml(password)}"> : value="${fn:escapeXml(confirmPassword)}"> : : "> "> * ×