Commit 548d1b29 authored by Tom Evans's avatar Tom Evans

OF-122: Fix inconsistent MUC subject handling

Ensure that the MUC room subject is set correctly from initial request
and upon subsequent reload.
parent b19ca358
...@@ -181,20 +181,17 @@ public class HistoryStrategy { ...@@ -181,20 +181,17 @@ public class HistoryStrategy {
} }
// Room subject change messages are special // Room subject change messages are special
boolean subjectChange = false; boolean subjectChange = isSubjectChangeRequest(packet);
if (packet.getSubject() != null && packet.getSubject().length() > 0){ if (subjectChange) {
subjectChange = true;
roomSubject = packet; roomSubject = packet;
} }
// store message according to active strategy // store message according to active strategy
if (strategyType == Type.none){ if (strategyType == Type.none && subjectChange) {
if (subjectChange) { history.clear();
history.clear(); history.add(packet);
history.add(packet);
}
} }
else if (strategyType == Type.all) { else if (strategyType == Type.all || subjectChange) {
history.add(packet); history.add(packet);
} }
else if (strategyType == Type.number) { else if (strategyType == Type.number) {
...@@ -322,7 +319,30 @@ public class HistoryStrategy { ...@@ -322,7 +319,30 @@ public class HistoryStrategy {
return roomSubject; return roomSubject;
} }
private static class MessageComparator implements Comparator<Message> { /**
* Returns true if the given message qualifies as a subject change request for
* the target MUC room, per XEP-0045. Note that this does not validate whether
* the sender has permission to make the change, because subject change requests
* may be loaded from history or processed "live" during a user's session.
*
* Refer to http://xmpp.org/extensions/xep-0045.html#subject-mod for details.
*
* @return true if the given packet is a subject change request
*/
public boolean isSubjectChangeRequest(Message message) {
// The subject is changed by sending a message of type "groupchat" to the <room@service>,
// where the <message/> MUST contain a <subject/> element that specifies the new subject
// but MUST NOT contain a <body/> element (or a <thread/> element).
// An empty <subject/> value means that the room subject should be removed.
return Message.Type.groupchat == message.getType() &&
message.getSubject() != null &&
message.getBody() == null &&
message.getThread() == null;
}
private static class MessageComparator implements Comparator<Message> {
@Override @Override
public int compare(Message o1, Message o2) { public int compare(Message o1, Message o2) {
String stamp1 = o1.getChildElement("delay", "urn:xmpp:delay").attributeValue("stamp"); String stamp1 = o1.getChildElement("delay", "urn:xmpp:delay").attributeValue("stamp");
......
...@@ -51,23 +51,23 @@ public final class MUCRoomHistory { ...@@ -51,23 +51,23 @@ public final class MUCRoomHistory {
} }
public void addMessage(Message packet) { public void addMessage(Message packet) {
boolean isSubjectChangeRequest = isSubjectChangeRequest(packet);
JID fromJID = packet.getFrom();
// Don't keep messages whose sender is the room itself (thus address without resource) // Don't keep messages whose sender is the room itself (thus address without resource)
// unless the message is changing the room's subject // unless the message is changing the room's subject
if ((packet.getFrom() == null || packet.getFrom().toString().length() == 0 || if (!isSubjectChangeRequest &&
packet.getFrom().equals(room.getRole().getRoleAddress())) && (fromJID == null || fromJID.toString().length() == 0 ||
packet.getSubject() == null) { fromJID.equals(room.getRole().getRoleAddress()))) {
return; return;
} }
// Do not store messages is strategy is none and message is not changing the room subject // Do not store regular messages if there is no message strategy (keep subject change requests)
if (!historyStrategy.isHistoryEnabled()) { if (!isSubjectChangeRequest && !historyStrategy.isHistoryEnabled()) {
if (packet.getSubject() == null || packet.getSubject().trim().length() == 0) { return;
return;
}
} }
// Ignore messages with no subject AND no body // Ignore empty messages (no subject AND no body)
if ((packet.getSubject() == null || "".equals(packet.getSubject().trim())) && if (!isSubjectChangeRequest &&
(packet.getBody() == null || "".equals(packet.getBody().trim()))) { (packet.getBody() == null || packet.getBody().trim().length() == 0)) {
return; return;
} }
...@@ -198,4 +198,13 @@ public final class MUCRoomHistory { ...@@ -198,4 +198,13 @@ public final class MUCRoomHistory {
public Message getChangedSubject() { public Message getChangedSubject() {
return historyStrategy.getChangedSubject(); return historyStrategy.getChangedSubject();
} }
/**
* Returns true if the given message qualifies as a subject change request, per XEP-0045.
*
* @return true if the given packet is a subject change request
*/
public boolean isSubjectChangeRequest(Message message) {
return historyStrategy.isSubjectChangeRequest(message);
}
} }
\ No newline at end of file
...@@ -2010,10 +2010,6 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener { ...@@ -2010,10 +2010,6 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
public void changeSubject(Message packet, MUCRole role) throws ForbiddenException { public void changeSubject(Message packet, MUCRole role) throws ForbiddenException {
if ((canOccupantsChangeSubject() && role.getRole().compareTo(MUCRole.Role.visitor) < 0) || if ((canOccupantsChangeSubject() && role.getRole().compareTo(MUCRole.Role.visitor) < 0) ||
MUCRole.Role.moderator == role.getRole()) { MUCRole.Role.moderator == role.getRole()) {
// Do nothing if the new subject is the same as the existing one
if (packet.getSubject().equals(subject)) {
return;
}
// Set the new subject to the room // Set the new subject to the room
subject = packet.getSubject(); subject = packet.getSubject();
MUCPersistenceManager.updateRoomSubject(this); MUCPersistenceManager.updateRoomSubject(this);
...@@ -2024,10 +2020,8 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener { ...@@ -2024,10 +2020,8 @@ public class LocalMUCRoom implements MUCRoom, GroupEventListener {
// Fire event signifying that the room's subject has changed. // Fire event signifying that the room's subject has changed.
MUCEventDispatcher.roomSubjectChanged(getJID(), role.getUserAddress(), subject); MUCEventDispatcher.roomSubjectChanged(getJID(), role.getUserAddress(), subject);
if (!"local-only".equals(packet.getID())) { // Let other cluster nodes that the room has been updated
// Let other cluster nodes that the room has been updated CacheFactory.doClusterTask(new RoomUpdatedEvent(this));
CacheFactory.doClusterTask(new RoomUpdatedEvent(this));
}
} }
else { else {
throw new ForbiddenException(); throw new ForbiddenException();
......
...@@ -271,9 +271,7 @@ public class LocalMUCUser implements MUCUser { ...@@ -271,9 +271,7 @@ public class LocalMUCUser implements MUCUser {
} }
else { else {
try { try {
if (packet.getSubject() != null && packet.getSubject().trim().length() > 0 && if (role.getChatRoom().getRoomHistory().isSubjectChangeRequest(packet)) {
Message.Type.groupchat == packet.getType() &&
(packet.getBody() == null || packet.getBody().trim().length() == 0)) {
// An occupant is trying to change the room's subject // An occupant is trying to change the room's subject
role.getChatRoom().changeSubject(packet, role); role.getChatRoom().changeSubject(packet, role);
......
...@@ -269,7 +269,6 @@ ...@@ -269,7 +269,6 @@
message.setSubject(roomSubject); message.setSubject(roomSubject);
message.setFrom(room.getRole().getRoleAddress()); message.setFrom(room.getRole().getRoleAddress());
message.setTo(room.getRole().getRoleAddress()); message.setTo(room.getRole().getRoleAddress());
message.setID("local-only");
room.changeSubject(message, room.getRole()); room.changeSubject(message, room.getRole());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment