diff --git a/xmppserver/src/main/webapp/muc-room-create.jsp b/xmppserver/src/main/webapp/muc-room-create.jsp index 0d62c2c44e..29e37cf929 100644 --- a/xmppserver/src/main/webapp/muc-room-create.jsp +++ b/xmppserver/src/main/webapp/muc-room-create.jsp @@ -1,7 +1,7 @@ <%@ page contentType="text/html; charset=UTF-8" %> <%-- - - - Copyright (C) 2004-2008 Jive Software, 2017-2018 Ignite Realtime Foundation. All rights reserved. + - Copyright (C) 2004-2008 Jive Software, 2017-2026 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. @@ -16,8 +16,90 @@ - limitations under the License. --%> - +<%@ page import="java.util.function.BiFunction" %> +<%@ page import="java.util.regex.Pattern" %> +<%@ page import="java.util.regex.Matcher" %> +<%@ page import="static java.nio.charset.StandardCharsets.UTF_8" %> +<%@ page import="java.net.URLEncoder,java.net.URLDecoder" %> <% - // Redirect to muc-room-edit-form and set that a room will be created - response.sendRedirect("muc-room-edit-form.jsp?create=true"); + // OF-31: To select the current conference service automatically on room creation, + // we extract the active service context from the HTTP Referer header. This allows us + // to preserve context from top-level sidebar navigation links (which are statically + // defined in admin-sidebar.xml and do not support dynamic parameters) without having + // to introduce session state or perform intrusive layout changes. + // + // The extraction is done here in the redirector page (muc-room-create.jsp), but the + // validation is kept inside muc-room-edit-form.jsp to preserve clean separation of + // concerns and fallback behaviors. + + String referrer = request.getHeader("Referer"); + String serviceParam = ""; + + BiFunction extractParam = (url, key) -> { + Matcher m = Pattern + .compile("(?:[?&])" + Pattern.quote(key) + "=([^&#]*)") + .matcher(url); + + return m.find() ? m.group(1) : null; + }; + + if (referrer != null) { + String val; + + if ((val = extractParam.apply(referrer, "mucname")) != null) { + try { + String decodedVal = URLDecoder.decode( + val, + UTF_8.name() + ); + + String encodedVal = URLEncoder.encode( + decodedVal, + UTF_8.name() + ); + + serviceParam = "&mucName=" + encodedVal; + } catch (Exception e) { + // Ignore parsing errors and let validation handle fallbacks + } + } else if ((val = extractParam.apply(referrer, "mucName")) != null) { + try { + String decodedVal = URLDecoder.decode( + val, + UTF_8.name() + ); + + String encodedVal = URLEncoder.encode( + decodedVal, + UTF_8.name() + ); + + serviceParam = "&mucName=" + encodedVal; + } catch (Exception e) { + // Ignore parsing errors and let validation handle fallbacks + } + } else if ((val = extractParam.apply(referrer, "roomJID")) != null) { + try { + val = URLDecoder.decode( + val, + UTF_8.name() + ); + + org.xmpp.packet.JID jid = new org.xmpp.packet.JID(val); + + serviceParam = "&mucName=" + + URLEncoder.encode( + jid.getDomain(), + UTF_8.name() + ); + } catch (Exception e) { + // Ignore parsing errors and let validation handle fallbacks + } + } + } + + response.sendRedirect( + "muc-room-edit-form.jsp?create=true" + serviceParam + ); %> + diff --git a/xmppserver/src/main/webapp/muc-room-edit-form.jsp b/xmppserver/src/main/webapp/muc-room-edit-form.jsp index 5681cb1569..3a76b58f25 100644 --- a/xmppserver/src/main/webapp/muc-room-edit-form.jsp +++ b/xmppserver/src/main/webapp/muc-room-edit-form.jsp @@ -1,7 +1,7 @@ <%@ page contentType="text/html; charset=UTF-8" %> <%-- - - - Copyright (C) 2004-2008 Jive Software, 2017-2025 Ignite Realtime Foundation. All rights reserved. + - Copyright (C) 2004-2008 Jive Software, 2017-2026 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. @@ -54,6 +54,9 @@ boolean clearchatsuccess = ParamUtils.getBooleanParameter(request,"clearchatsuccess"); String roomName = ParamUtils.getParameter(request,"roomName"); String mucName = ParamUtils.getParameter(request,"mucName"); + if (mucName == null) { + mucName = ParamUtils.getParameter(request,"mucname"); + } String roomJIDStr = ParamUtils.getParameter(request,"roomJID"); JID roomJID = null; if (roomName != null && mucName != null) { @@ -306,11 +309,32 @@ } 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(); + // OF-31: Retrieve and validate the candidate service context parameter (mucName). + // Fall back to the alphabetically first service if missing, invalid, or does not exist. + // This ensures backwards compatibility and graceful fallback when accessed directly. + String resolvedServiceName = null; + if (mucName != null) { + if (webManager.getMultiUserChatManager().isServiceRegistered(mucName)) { + resolvedServiceName = mucName; + } else { + try { + org.jivesoftware.openfire.muc.MultiUserChatService service = webManager.getMultiUserChatManager().getMultiUserChatService(new JID(null, mucName, null)); + if (service != null) { + resolvedServiceName = service.getServiceName(); + } + } catch (Exception e) { + // ignore + } + } + } + if (resolvedServiceName == null) { + resolvedServiceName = webManager.getMultiUserChatManager().getMultiUserChatServices().iterator().next().getServiceName(); + } + final String serviceName = resolvedServiceName; + org.jivesoftware.openfire.muc.MultiUserChatService resolvedService = webManager.getMultiUserChatManager().getMultiUserChatService(serviceName); + if (resolvedService != null) { + mucName = resolvedService.getServiceDomain(); + } maxUsers = MUCPersistenceManager.getProperty(serviceName, "room.maxUsers", "30"); broadcastModerator = MUCPersistenceManager.getBooleanProperty(serviceName, "room.broadcastModerator", true); broadcastParticipant = MUCPersistenceManager.getBooleanProperty(serviceName, "room.broadcastParticipant", true);