Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 86 additions & 4 deletions xmppserver/src/main/webapp/muc-room-create.jsp
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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<String, String, String> 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
);
%>

36 changes: 30 additions & 6 deletions xmppserver/src/main/webapp/muc-room-edit-form.jsp
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
Loading