/**
   * Create a new role.
   *
   * @param chatserver the server hosting the role.
   * @param chatroom the room the role is valid in.
   * @param nickname the nickname of the user in the role.
   * @param role the role of the user in the room.
   * @param affiliation the affiliation of the user in the room.
   * @param chatuser the user on the chat server.
   * @param presence the presence sent by the user to join the room.
   * @param packetRouter the packet router for sending messages from this role.
   */
  public LocalMUCRole(
      MultiUserChatService chatserver,
      LocalMUCRoom chatroom,
      String nickname,
      MUCRole.Role role,
      MUCRole.Affiliation affiliation,
      LocalMUCUser chatuser,
      Presence presence,
      PacketRouter packetRouter) {
    this.room = chatroom;
    this.nick = nickname;
    this.user = chatuser;
    this.server = chatserver;
    this.router = packetRouter;
    this.role = role;
    this.affiliation = affiliation;
    // Cache the user's session (will only work for local users)
    this.session = XMPPServer.getInstance().getSessionManager().getSession(presence.getFrom());

    extendedInformation =
        DocumentHelper.createElement(QName.get("x", "http://jabber.org/protocol/muc#user"));
    calculateExtendedInformation();
    rJID = new JID(room.getName(), server.getServiceDomain(), nick);
    setPresence(presence);
    // Check if new occupant wants to be a deaf occupant
    Element element =
        presence.getElement().element(QName.get("x", "http://jivesoftware.org/protocol/muc"));
    if (element != null) {
      voiceOnly = element.element("deaf-occupant") != null;
    }
    // Add the new role to the list of roles
    user.addRole(room.getName(), this);
  }
  /**
   * Handles the IQ packet sent by an owner of the room. Possible actions are:
   *
   * <ul>
   *   <li>Return the list of owners
   *   <li>Return the list of admins
   *   <li>Change user's affiliation to owner
   *   <li>Change user's affiliation to admin
   *   <li>Change user's affiliation to member
   *   <li>Change user's affiliation to none
   *   <li>Destroy the room
   *   <li>Return the room configuration within a dataform
   *   <li>Update the room configuration based on the sent dataform
   * </ul>
   *
   * @param packet the IQ packet sent by an owner of the room.
   * @param role the role of the user that sent the packet.
   * @throws ForbiddenException if the user does not have enough permissions (ie. is not an owner).
   * @throws ConflictException If the room was going to lose all of its owners.
   */
  @SuppressWarnings("unchecked")
  public void handleIQ(IQ packet, MUCRole role)
      throws ForbiddenException, ConflictException, CannotBeInvitedException {
    // Only owners can send packets with the namespace "http://jabber.org/protocol/muc#owner"
    if (MUCRole.Affiliation.owner != role.getAffiliation()) {
      throw new ForbiddenException();
    }

    IQ reply = IQ.createResultIQ(packet);
    Element element = packet.getChildElement();

    // Analyze the action to perform based on the included element
    Element formElement = element.element(QName.get("x", "jabber:x:data"));
    if (formElement != null) {
      handleDataFormElement(role, formElement);
    } else {
      Element destroyElement = element.element("destroy");
      if (destroyElement != null) {
        if (((MultiUserChatServiceImpl) room.getMUCService()).getMUCDelegate() != null) {
          if (!((MultiUserChatServiceImpl) room.getMUCService())
              .getMUCDelegate()
              .destroyingRoom(room.getName(), role.getUserAddress())) {
            // Delegate said no, reject destroy request.
            throw new ForbiddenException();
          }
        }

        JID alternateJID = null;
        final String jid = destroyElement.attributeValue("jid");
        if (jid != null) {
          alternateJID = new JID(jid);
        }
        room.destroyRoom(alternateJID, destroyElement.elementTextTrim("reason"));
      } else {
        // If no element was included in the query element then answer the
        // configuration form
        if (!element.elementIterator().hasNext()) {
          refreshConfigurationFormValues();
          reply.setChildElement(probeResult.createCopy());
        }
        // An unknown and possibly incorrect element was included in the query
        // element so answer a BAD_REQUEST error
        else {
          reply.setChildElement(packet.getChildElement().createCopy());
          reply.setError(PacketError.Condition.bad_request);
        }
      }
    }
    if (reply.getTo() != null) {
      // Send a reply only if the sender of the original packet was from a real JID. (i.e. not
      // a packet generated locally)
      router.route(reply);
    }
  }
Beispiel #3
0
 private void process(Presence presence) {
   if (presence.getType() == Presence.Type.unavailable) {
     MUCRole mucRole = room.getOccupantByFullJID(realjid);
     if (mucRole != null) {
       room.leaveRoom(mucRole);
     }
   } else {
     throw new UnsupportedOperationException(
         "Cannot process Presence packets of remote users: " + presence);
   }
 }
  /**
   * Handles packets that includes a data form. The data form was sent using an element with name
   * "x" and namespace "jabber:x:data".
   *
   * @param senderRole the role of the user that sent the data form.
   * @param formElement the element that contains the data form specification.
   * @throws ForbiddenException if the user does not have enough privileges.
   * @throws ConflictException If the room was going to lose all of its owners.
   */
  private void handleDataFormElement(MUCRole senderRole, Element formElement)
      throws ForbiddenException, ConflictException {
    DataForm completedForm = new DataForm(formElement);

    switch (completedForm.getType()) {
      case cancel:
        // If the room was just created (i.e. is locked) and the owner cancels the configuration
        // form then destroy the room
        if (room.isLocked()) {
          room.destroyRoom(null, null);
        }
        break;

      case submit:
        // The owner is requesting an instant room
        if (completedForm.getFields().isEmpty()) {
          // Do nothing
        }
        // The owner is requesting a reserved room or is changing the current configuration
        else {
          processConfigurationForm(completedForm, senderRole);
        }
        // If the room was locked, unlock it and send to the owner the "room is now unlocked"
        // message
        if (room.isLocked() && !room.isManuallyLocked()) {
          room.unlock(senderRole);
        }
        if (!room.isDestroyed) {
          // Let other cluster nodes that the room has been updated
          CacheFactory.doClusterTask(new RoomUpdatedEvent(room));
        }
        break;

      default:
        Log.warn("cannot handle data form element: " + formElement.asXML());
        break;
    }
  }
  private void init() {
    Element element =
        DocumentHelper.createElement(QName.get("query", "http://jabber.org/protocol/muc#owner"));

    configurationForm = new DataForm(DataForm.Type.form);
    configurationForm.setTitle(LocaleUtils.getLocalizedString("muc.form.conf.title"));
    List<String> params = new ArrayList<String>();
    params.add(room.getName());
    configurationForm.addInstruction(
        LocaleUtils.getLocalizedString("muc.form.conf.instruction", params));

    configurationForm
        .addField("FORM_TYPE", null, Type.hidden)
        .addValue("http://jabber.org/protocol/muc#roomconfig");

    configurationForm.addField(
        "muc#roomconfig_roomname",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_roomname"),
        Type.text_single);

    configurationForm.addField(
        "muc#roomconfig_roomdesc",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_roomdesc"),
        Type.text_single);

    configurationForm.addField(
        "muc#roomconfig_changesubject",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_changesubject"),
        Type.boolean_type);

    final FormField maxUsers =
        configurationForm.addField(
            "muc#roomconfig_maxusers",
            LocaleUtils.getLocalizedString("muc.form.conf.owner_maxusers"),
            Type.list_single);
    maxUsers.addOption("10", "10");
    maxUsers.addOption("20", "20");
    maxUsers.addOption("30", "30");
    maxUsers.addOption("40", "40");
    maxUsers.addOption("50", "50");
    maxUsers.addOption(LocaleUtils.getLocalizedString("muc.form.conf.none"), "0");

    final FormField broadcast =
        configurationForm.addField(
            "muc#roomconfig_presencebroadcast",
            LocaleUtils.getLocalizedString("muc.form.conf.owner_presencebroadcast"),
            Type.list_multi);
    broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator"), "moderator");
    broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.participant"), "participant");
    broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.visitor"), "visitor");

    configurationForm.addField(
        "muc#roomconfig_publicroom",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_publicroom"),
        Type.boolean_type);

    configurationForm.addField(
        "muc#roomconfig_persistentroom",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_persistentroom"),
        Type.boolean_type);

    configurationForm.addField(
        "muc#roomconfig_moderatedroom",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_moderatedroom"),
        Type.boolean_type);

    configurationForm.addField(
        "muc#roomconfig_membersonly",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_membersonly"),
        Type.boolean_type);

    configurationForm
        .addField(null, null, Type.fixed)
        .addValue(LocaleUtils.getLocalizedString("muc.form.conf.allowinvitesfixed"));

    configurationForm.addField(
        "muc#roomconfig_allowinvites",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_allowinvites"),
        Type.boolean_type);

    configurationForm.addField(
        "muc#roomconfig_passwordprotectedroom",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_passwordprotectedroom"),
        Type.boolean_type);

    configurationForm
        .addField(null, null, Type.fixed)
        .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomsecretfixed"));

    configurationForm.addField(
        "muc#roomconfig_roomsecret",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_roomsecret"),
        Type.text_private);

    final FormField whois =
        configurationForm.addField(
            "muc#roomconfig_whois",
            LocaleUtils.getLocalizedString("muc.form.conf.owner_whois"),
            Type.list_single);
    whois.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator"), "moderators");
    whois.addOption(LocaleUtils.getLocalizedString("muc.form.conf.anyone"), "anyone");

    configurationForm.addField(
        "muc#roomconfig_enablelogging",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_enablelogging"),
        Type.boolean_type);

    configurationForm.addField(
        "x-muc#roomconfig_reservednick",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_reservednick"),
        Type.boolean_type);

    configurationForm.addField(
        "x-muc#roomconfig_canchangenick",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_canchangenick"),
        Type.boolean_type);

    configurationForm
        .addField(null, null, Type.fixed)
        .addValue(LocaleUtils.getLocalizedString("muc.form.conf.owner_registration"));

    configurationForm.addField(
        "x-muc#roomconfig_registration",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_registration"),
        Type.boolean_type);

    configurationForm
        .addField(null, null, Type.fixed)
        .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomadminsfixed"));

    configurationForm.addField(
        "muc#roomconfig_roomadmins",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_roomadmins"),
        Type.jid_multi);

    configurationForm
        .addField(null, null, Type.fixed)
        .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomownersfixed"));

    configurationForm.addField(
        "muc#roomconfig_roomowners",
        LocaleUtils.getLocalizedString("muc.form.conf.owner_roomowners"),
        Type.jid_multi);

    // Create the probeResult and add the basic info together with the configuration form
    probeResult = element;
    probeResult.add(configurationForm.getElement());
  }
  private void refreshConfigurationFormValues() {
    room.lock.readLock().lock();
    try {
      FormField field = configurationForm.getField("muc#roomconfig_roomname");
      field.clearValues();
      field.addValue(room.getNaturalLanguageName());

      field = configurationForm.getField("muc#roomconfig_roomdesc");
      field.clearValues();
      field.addValue(room.getDescription());

      field = configurationForm.getField("muc#roomconfig_changesubject");
      field.clearValues();
      field.addValue((room.canOccupantsChangeSubject() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_maxusers");
      field.clearValues();
      field.addValue(Integer.toString(room.getMaxUsers()));

      field = configurationForm.getField("muc#roomconfig_presencebroadcast");
      field.clearValues();
      for (String roleToBroadcast : room.getRolesToBroadcastPresence()) {
        field.addValue(roleToBroadcast);
      }

      field = configurationForm.getField("muc#roomconfig_publicroom");
      field.clearValues();
      field.addValue((room.isPublicRoom() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_persistentroom");
      field.clearValues();
      field.addValue((room.isPersistent() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_moderatedroom");
      field.clearValues();
      field.addValue((room.isModerated() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_membersonly");
      field.clearValues();
      field.addValue((room.isMembersOnly() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_allowinvites");
      field.clearValues();
      field.addValue((room.canOccupantsInvite() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_passwordprotectedroom");
      field.clearValues();
      field.addValue((room.isPasswordProtected() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_roomsecret");
      field.clearValues();
      field.addValue(room.getPassword());

      field = configurationForm.getField("muc#roomconfig_whois");
      field.clearValues();
      field.addValue((room.canAnyoneDiscoverJID() ? "anyone" : "moderators"));

      field = configurationForm.getField("muc#roomconfig_enablelogging");
      field.clearValues();
      field.addValue((room.isLogEnabled() ? "1" : "0"));

      field = configurationForm.getField("x-muc#roomconfig_reservednick");
      field.clearValues();
      field.addValue((room.isLoginRestrictedToNickname() ? "1" : "0"));

      field = configurationForm.getField("x-muc#roomconfig_canchangenick");
      field.clearValues();
      field.addValue((room.canChangeNickname() ? "1" : "0"));

      field = configurationForm.getField("x-muc#roomconfig_registration");
      field.clearValues();
      field.addValue((room.isRegistrationEnabled() ? "1" : "0"));

      field = configurationForm.getField("muc#roomconfig_roomadmins");
      field.clearValues();
      for (JID jid : room.getAdmins()) {
        field.addValue(jid.toString());
      }

      field = configurationForm.getField("muc#roomconfig_roomowners");
      field.clearValues();
      for (JID jid : room.getOwners()) {
        field.addValue(jid.toString());
      }

      // Remove the old element
      probeResult.remove(probeResult.element(QName.get("x", "jabber:x:data")));
      // Add the new representation of configurationForm as an element
      probeResult.add(configurationForm.getElement());

    } finally {
      room.lock.readLock().unlock();
    }
  }
  /**
   * Processes the completed form sent by an owner of the room. This will modify the room's
   * configuration as well as the list of owners and admins.
   *
   * @param completedForm the completed form sent by an owner of the room.
   * @param senderRole the role of the user that sent the completed form.
   * @throws ForbiddenException if the user does not have enough privileges.
   * @throws ConflictException If the room was going to lose all of its owners.
   */
  private void processConfigurationForm(DataForm completedForm, MUCRole senderRole)
      throws ForbiddenException, ConflictException {
    List<String> values;
    String booleanValue;
    FormField field;

    // Get the new list of admins
    field = completedForm.getField("muc#roomconfig_roomadmins");
    boolean adminsSent = field != null;
    List<JID> admins = new ArrayList<JID>();
    if (field != null) {
      for (String value : field.getValues()) {
        // XEP-0045: "Affiliations are granted, revoked, and
        // maintained based on the user's bare JID, (...)"
        if (value != null && value.trim().length() != 0) {
          admins.add(new JID(value.trim()).asBareJID());
        }
      }
    }

    // Get the new list of owners
    field = completedForm.getField("muc#roomconfig_roomowners");
    boolean ownersSent = field != null;
    List<JID> owners = new ArrayList<JID>();
    if (field != null) {
      for (String value : field.getValues()) {
        // XEP-0045: "Affiliations are granted, revoked, and
        // maintained based on the user's bare JID, (...)"
        if (value != null && value.trim().length() != 0) {
          owners.add(new JID(value.trim()).asBareJID());
        }
      }
    }

    // Answer a conflic error if all the current owners will be removed
    if (ownersSent && owners.isEmpty()) {
      throw new ConflictException();
    }

    // Keep a registry of the updated presences
    List<Presence> presences = new ArrayList<Presence>(admins.size() + owners.size());

    field = completedForm.getField("muc#roomconfig_roomname");
    if (field != null) {
      final String value = field.getFirstValue();
      room.setNaturalLanguageName((value != null ? value : " "));
    }

    field = completedForm.getField("muc#roomconfig_roomdesc");
    if (field != null) {
      final String value = field.getFirstValue();
      room.setDescription((value != null ? value : " "));
    }

    field = completedForm.getField("muc#roomconfig_changesubject");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setCanOccupantsChangeSubject(("1".equals(booleanValue)));
    }

    field = completedForm.getField("muc#roomconfig_maxusers");
    if (field != null) {
      final String value = field.getFirstValue();
      room.setMaxUsers((value != null ? Integer.parseInt(value) : 30));
    }

    field = completedForm.getField("muc#roomconfig_presencebroadcast");
    if (field != null) {
      values = new ArrayList<String>(field.getValues());
      room.setRolesToBroadcastPresence(values);
    }

    field = completedForm.getField("muc#roomconfig_publicroom");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setPublicRoom(("1".equals(booleanValue)));
    }

    field = completedForm.getField("muc#roomconfig_persistentroom");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      boolean isPersistent = ("1".equals(booleanValue));
      // Delete the room from the DB if it's no longer persistent
      if (room.isPersistent() && !isPersistent) {
        MUCPersistenceManager.deleteFromDB(room);
      }
      room.setPersistent(isPersistent);
    }

    field = completedForm.getField("muc#roomconfig_moderatedroom");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setModerated(("1".equals(booleanValue)));
    }

    field = completedForm.getField("muc#roomconfig_membersonly");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      presences.addAll(room.setMembersOnly(("1".equals(booleanValue))));
    }

    field = completedForm.getField("muc#roomconfig_allowinvites");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setCanOccupantsInvite(("1".equals(booleanValue)));
    }

    field = completedForm.getField("muc#roomconfig_passwordprotectedroom");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      boolean isPasswordProtected = "1".equals(booleanValue);
      if (isPasswordProtected) {
        // The room is password protected so set the new password
        field = completedForm.getField("muc#roomconfig_roomsecret");
        if (field != null) {
          final String secret = completedForm.getField("muc#roomconfig_roomsecret").getFirstValue();
          room.setPassword(secret);
        }
      } else {
        // The room is not password protected so remove any previous password
        room.setPassword(null);
      }
    }

    field = completedForm.getField("muc#roomconfig_whois");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setCanAnyoneDiscoverJID(("anyone".equals(booleanValue)));
    }

    field = completedForm.getField("muc#roomconfig_enablelogging");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setLogEnabled(("1".equals(booleanValue)));
    }

    field = completedForm.getField("x-muc#roomconfig_reservednick");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setLoginRestrictedToNickname(("1".equals(booleanValue)));
    }

    field = completedForm.getField("x-muc#roomconfig_canchangenick");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setChangeNickname(("1".equals(booleanValue)));
    }

    field = completedForm.getField("x-muc#roomconfig_registration");
    if (field != null) {
      final String value = field.getFirstValue();
      booleanValue = ((value != null ? value : "1"));
      room.setRegistrationEnabled(("1".equals(booleanValue)));
    }

    // Update the modification date to reflect the last time when the room's configuration
    // was modified
    room.setModificationDate(new Date());

    if (room.isPersistent()) {
      room.saveToDB();
    }

    // Set the new owners and admins of the room
    presences.addAll(room.addOwners(owners, senderRole));
    presences.addAll(room.addAdmins(admins, senderRole));

    if (ownersSent) {
      // Change the affiliation to "member" for the current owners that won't be neither
      // owner nor admin (if the form included the owners field)
      List<JID> ownersToRemove = new ArrayList<JID>(room.owners);
      ownersToRemove.removeAll(admins);
      ownersToRemove.removeAll(owners);
      for (JID jid : ownersToRemove) {
        presences.addAll(room.addMember(jid, null, senderRole));
      }
    }

    if (adminsSent) {
      // Change the affiliation to "member" for the current admins that won't be neither
      // owner nor admin (if the form included the admins field)
      List<JID> adminsToRemove = new ArrayList<JID>(room.admins);
      adminsToRemove.removeAll(admins);
      adminsToRemove.removeAll(owners);
      for (JID jid : adminsToRemove) {
        presences.addAll(room.addMember(jid, null, senderRole));
      }
    }

    // Destroy the room if the room is no longer persistent and there are no occupants in
    // the room
    if (!room.isPersistent() && room.getOccupantsCount() == 0) {
      room.destroyRoom(null, null);
    }

    // Send the updated presences to the room occupants
    for (Object presence : presences) {
      room.send((Presence) presence);
    }
  }
 public void destroy() {
   // Notify the user that he/she is no longer in the room
   user.removeRole(room.getName());
 }
 public void changeNickname(String nickname) {
   this.nick = nickname;
   setRoleAddress(new JID(room.getName(), server.getServiceDomain(), nick));
 }