in server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java [157:297]
private List<Stanza> available(PresenceStanza stanza, Entity roomJid, Entity newOccupantJid, String nick,
ServerRuntimeContext serverRuntimeContext, StanzaBroker stanzaBroker) {
boolean newRoom = false;
// TODO what to use for the room name?
Room room = conference.findRoom(roomJid);
if (room == null) {
room = conference.createRoom(roomJid, roomJid.getNode());
newRoom = true;
}
if (room == null) {
// room not existing or access not allowed
return createPresenceErrorStanza(roomJid, newOccupantJid, stanza.getID(), "auth", "not-authorized");
}
final Occupant occupant = room.findOccupantByJID(newOccupantJid);
if (occupant != null) {
// occupant is already in room
room.recordLatestPresence(newOccupantJid, stanza);
if (nick.equals(occupant.getNick())) {
// nick unchanged, change show and status
logger.debug("{} has updated presence in room {}", newOccupantJid, roomJid);
for (Occupant receiver : room.getOccupants()) {
sendChangeShowStatus(occupant, receiver, room, getInnerElementText(stanza, "show"),
getInnerElementText(stanza, "status"), serverRuntimeContext, stanzaBroker);
}
} else {
logger.debug("{} has requested to change nick in room {}", newOccupantJid, roomJid);
if (room.isInRoom(nick)) {
// user with this nick is already in room
return createPresenceErrorStanza(roomJid, newOccupantJid, stanza.getID(), "cancel", "conflict");
}
String oldNick = occupant.getNick();
// update the nick
occupant.setNick(nick);
// send out unavailable presences to all existing occupants
for (Occupant receiver : room.getOccupants()) {
sendChangeNickUnavailable(occupant, oldNick, receiver, room, serverRuntimeContext, stanzaBroker);
}
// send out available presences to all existing occupants
for (Occupant receiver : room.getOccupants()) {
sendChangeNickAvailable(occupant, receiver, room, serverRuntimeContext, stanzaBroker);
}
}
room.updateLastActivity();
} else {
logger.debug("{} has requested to enter room {}", newOccupantJid, roomJid);
boolean nickConflict = room.isInRoom(nick);
boolean nickRewritten = false;
int counter = 1; // max conflicts, to avoid DoS attacks
String rewrittenNick = null;
while (nickConflict && counter < 100 && room.rewritesDuplicateNick()) {
rewrittenNick = nick + "_" + counter;
nickConflict = room.isInRoom(rewrittenNick);
if (nickConflict) {
counter++;
} else {
nick = rewrittenNick;
nickRewritten = true;
}
}
if (nickConflict) {
logger.debug("persistent nick confict for {} entering {}", newOccupantJid, roomJid);
// user with this nick is already in room
return createPresenceErrorStanza(roomJid, newOccupantJid, stanza.getID(), "cancel", "conflict");
}
// check password if password protected
if (room.isRoomType(RoomType.PasswordProtected)) {
X x = X.fromStanza(stanza);
String password = null;
if (x != null) {
password = x.getPasswordValue();
}
if (password == null || !password.equals(room.getPassword())) {
logger.debug("{} is not allowed to enter room {}", newOccupantJid, roomJid);
// password missing or not matching
return createPresenceErrorStanza(roomJid, newOccupantJid, stanza.getID(), "auth", "not-authorized");
}
}
Occupant newOccupant;
try {
newOccupant = room.addOccupant(newOccupantJid, nick);
room.recordLatestPresence(newOccupantJid, stanza);
} catch (RuntimeException e) {
final String message = e.getMessage();
logger.debug("{} has not been added as occupant to room {}, reason: " + message, newOccupantJid,
roomJid);
return createPresenceErrorStanza(roomJid, newOccupantJid, stanza.getID(), "auth", message);
}
if (newRoom) {
room.getAffiliations().add(newOccupantJid, Affiliation.Owner);
newOccupant.setRole(Role.Moderator);
}
// if the new occupant is a server admin, he will be for the room, too
final ServerAdministrationService adhocCommandsService = (ServerAdministrationService) serverRuntimeContext
.getServerRuntimeContextService(ServerAdministrationService.SERVICE_ID);
if (adhocCommandsService != null && adhocCommandsService.isAdmin(newOccupantJid.getBareJID())) {
final Affiliations roomAffiliations = room.getAffiliations();
// make new occupant an Admin, but do not downgrade from Owner
// Admin affilitation implies Moderator role (see XEP-0045 5.1.2)
if (roomAffiliations.getAffiliation(newOccupantJid) != Affiliation.Owner) {
roomAffiliations.add(newOccupantJid, Affiliation.Admin);
newOccupant.setRole(Role.Moderator);
}
}
// relay presence of all existing room occupants to the now joined occupant
for (Occupant existingOccupant : room.getOccupants()) {
sendOccupantPresenceToNewOccupant(newOccupant, existingOccupant, room, serverRuntimeContext,
stanzaBroker);
}
// relay presence of the newly added occupant to all existing occupants
for (Occupant existingOccupant : room.getOccupants()) {
sendNewOccupantPresenceToExisting(newOccupant, existingOccupant, room, serverRuntimeContext, stanza,
nickRewritten, stanzaBroker);
}
room.updateLastActivity();
// send discussion history to user
boolean includeJid = room.isRoomType(RoomType.NonAnonymous);
List<Stanza> history = room.getHistory().createStanzas(newOccupant, includeJid, History.fromStanza(stanza));
relayStanzas(newOccupantJid, history, serverRuntimeContext, stanzaBroker);
logger.debug("{} successfully entered room {}", newOccupantJid, roomJid);
}
return null;
}