Search in sources :

Example 36 with Roster

use of org.jivesoftware.openfire.roster.Roster in project Openfire by igniterealtime.

the class BaseTransport method addOrUpdateRosterItem.

/**
     * Either updates or adds a JID to a user's roster.
     *
     * Tries to only edit the roster if it has to.
     *
     * @param userjid JID of user to have item added to their roster.
     * @param contactjid JID to add to roster.
     * @param nickname Nickname of item. (can be null)
     * @param groups List of group the item is to be placed in. (can be null)
     * @param subtype Specific subscription setting.
     * @param asktype Specific ask setting.
     * @throws UserNotFoundException if userjid not found.
     */
public void addOrUpdateRosterItem(JID userjid, JID contactjid, String nickname, Collection<String> groups, RosterItem.SubType subtype, RosterItem.AskType asktype) throws UserNotFoundException {
    Log.debug("add or update roster item " + contactjid + " for: " + userjid);
    try {
        final Roster roster = rosterManager.getRoster(userjid.getNode());
        try {
            RosterItem gwitem = roster.getRosterItem(contactjid);
            Log.debug("Found existing roster item " + contactjid + " for: " + userjid + ". We will update if required.");
            boolean changed = false;
            if (gwitem.getSubStatus() != subtype) {
                gwitem.setSubStatus(subtype);
                changed = true;
            }
            if (gwitem.getAskStatus() != asktype) {
                gwitem.setAskStatus(asktype);
                changed = true;
            }
            // gnickname is not null, nickname is not null, if different, set gnickname to nickname
            if ((gwitem.getNickname() != null && nickname == null) || (gwitem.getNickname() == null && nickname != null) || (gwitem.getNickname() != null && nickname != null && !gwitem.getNickname().equals(nickname))) {
                gwitem.setNickname(nickname);
                changed = true;
            }
            List<String> curgroups = gwitem.getGroups();
            // curgroups is not null, groups is not null, if their sizes are different or curgroups does not contain all of groups, set curgroups to groups
            if (((curgroups != null && curgroups.size() > 0) && (groups == null || groups.size() == 0)) || ((curgroups == null || curgroups.size() == 0) && (groups != null && groups.size() > 0)) || (curgroups != null && groups != null && ((curgroups.size() != groups.size()) || !curgroups.containsAll(groups)))) {
                try {
                    gwitem.setGroups((List<String>) (groups != null ? groups : new ArrayList<String>()));
                    changed = true;
                } catch (Exception ee) {
                    Log.debug("Exception while setting groups for roster item:", ee);
                }
            }
            if (changed) {
                Log.debug("Updating existing roster item " + contactjid + " for: " + userjid);
                roster.updateRosterItem(gwitem);
            } else {
                Log.debug("Update of existing roster item " + contactjid + " for: " + userjid + " can be skipped - nothing changed.");
            }
        } catch (UserNotFoundException e) {
            try {
                // Create new roster item for the gateway service or legacy contact. Only
                // roster items related to the gateway service will be persistent. Roster
                // items of legacy users are never persisted in the DB.  (unless tweak enabled)
                Log.debug("Creating new roster item " + contactjid + " for: " + userjid + ". No existing item was found.");
                final RosterItem gwitem = roster.createRosterItem(contactjid, false, contactjid.getNode() == null || JiveGlobals.getBooleanProperty("plugin.gateway.tweak.persistentroster", false));
                gwitem.setSubStatus(subtype);
                gwitem.setAskStatus(asktype);
                gwitem.setNickname(nickname);
                try {
                    gwitem.setGroups((List<String>) groups);
                } catch (Exception ee) {
                    Log.debug("Exception while setting groups for gateway item:", ee);
                }
                roster.updateRosterItem(gwitem);
            } catch (UserAlreadyExistsException ee) {
                Log.debug("getRosterItem claims user exists, but couldn't find via getRosterItem?", ee);
            } catch (Exception ee) {
                Log.debug("Exception while creating roster item:", ee);
            }
        }
    } catch (UserNotFoundException e) {
        throw new UserNotFoundException("Could not find roster for " + userjid.toString());
    }
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) Roster(org.jivesoftware.openfire.roster.Roster) UserAlreadyExistsException(org.jivesoftware.openfire.user.UserAlreadyExistsException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) NotFoundException(org.jivesoftware.util.NotFoundException) UserAlreadyExistsException(org.jivesoftware.openfire.user.UserAlreadyExistsException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException)

Example 37 with Roster

use of org.jivesoftware.openfire.roster.Roster in project Openfire by igniterealtime.

the class PresenceManagerImpl method handleProbe.

@Override
public void handleProbe(Presence packet) throws UnauthorizedException {
    String username = packet.getTo().getNode();
    try {
        Roster roster = rosterManager.getRoster(username);
        RosterItem item = roster.getRosterItem(packet.getFrom());
        if (item.getSubStatus() == RosterItem.SUB_FROM || item.getSubStatus() == RosterItem.SUB_BOTH) {
            probePresence(packet.getFrom(), packet.getTo());
        } else {
            PacketError.Condition error = PacketError.Condition.not_authorized;
            if ((item.getSubStatus() == RosterItem.SUB_NONE && item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE) || (item.getSubStatus() == RosterItem.SUB_TO && item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE)) {
                error = PacketError.Condition.forbidden;
            }
            Presence presenceToSend = new Presence();
            presenceToSend.setError(error);
            presenceToSend.setTo(packet.getFrom());
            presenceToSend.setFrom(packet.getTo());
            deliverer.deliver(presenceToSend);
        }
    } catch (UserNotFoundException e) {
        Presence presenceToSend = new Presence();
        presenceToSend.setError(PacketError.Condition.forbidden);
        presenceToSend.setTo(packet.getFrom());
        presenceToSend.setFrom(packet.getTo());
        deliverer.deliver(presenceToSend);
    }
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) RosterItem(org.jivesoftware.openfire.roster.RosterItem) Roster(org.jivesoftware.openfire.roster.Roster) PacketError(org.xmpp.packet.PacketError) Presence(org.xmpp.packet.Presence)

Example 38 with Roster

use of org.jivesoftware.openfire.roster.Roster in project Openfire by igniterealtime.

the class IQRosterHandler method manageRoster.

/**
 * The packet is a typical 'set' or 'get' update targeted at the server.
 * Notice that the set could be a roster removal in which case we have to
 * generate a local roster removal update as well as a new roster removal
 * to send to the the roster item's owner.
 *
 * @param packet The packet that triggered this update
 * @return Either a response to the roster update or null if the packet is corrupt and the session was closed down
 */
private IQ manageRoster(org.xmpp.packet.Roster packet) throws UnauthorizedException, UserAlreadyExistsException, SharedGroupException {
    IQ returnPacket = null;
    JID sender = packet.getFrom();
    IQ.Type type = packet.getType();
    try {
        if ((sender.getNode() == null || !RosterManager.isRosterServiceEnabled() || !userManager.isRegisteredUser(sender, false)) && IQ.Type.get == type) {
            // If anonymous user asks for his roster or roster service is disabled then
            // return an empty roster
            IQ reply = IQ.createResultIQ(packet);
            reply.setChildElement("query", "jabber:iq:roster");
            return reply;
        }
        if (!localServer.isLocal(sender)) {
            // Sender belongs to a remote server so discard this IQ request
            Log.warn("Discarding IQ roster packet of remote user: " + packet);
            return null;
        }
        Roster cachedRoster = userManager.getUser(sender.getNode()).getRoster();
        if (IQ.Type.get == type) {
            if (RosterManager.isRosterVersioningEnabled()) {
                String clientVersion = packet.getChildElement().attributeValue("ver");
                String latestVersion = String.valueOf(cachedRoster.hashCode());
                // Whether or not the roster has been modified since the version ID enumerated by the client, ...
                if (!latestVersion.equals(clientVersion)) {
                    // ... the server MUST either return the complete roster
                    // (including a 'ver' attribute that signals the latest version)
                    returnPacket = cachedRoster.getReset();
                    returnPacket.getChildElement().addAttribute("ver", latestVersion);
                } else {
                    // ... or return an empty IQ-result
                    returnPacket = new org.xmpp.packet.IQ();
                }
            } else {
                returnPacket = cachedRoster.getReset();
            }
            returnPacket.setType(IQ.Type.result);
            returnPacket.setTo(sender);
            returnPacket.setID(packet.getID());
            // Force delivery of the response because we need to trigger
            // a presence probe from all contacts
            deliverer.deliver(returnPacket);
            returnPacket = null;
        } else if (IQ.Type.set == type) {
            returnPacket = IQ.createResultIQ(packet);
            // The <query/> element contains more than one <item/> child element.
            if (packet.getItems().size() > 1) {
                returnPacket.setError(new PacketError(PacketError.Condition.bad_request, PacketError.Type.modify, "Query contains more than one item"));
            } else {
                for (org.xmpp.packet.Roster.Item item : packet.getItems()) {
                    if (item.getSubscription() == org.xmpp.packet.Roster.Subscription.remove) {
                        if (removeItem(cachedRoster, packet.getFrom(), item) == null) {
                            // RFC 6121 2.5.3.  Error Cases: If the value of the 'jid' attribute specifies an item that is not in the roster, then the server MUST return an <item-not-found/> stanza error.
                            returnPacket.setError(PacketError.Condition.item_not_found);
                        }
                    } else {
                        PacketError error = checkGroups(item.getGroups());
                        if (error != null) {
                            returnPacket.setError(error);
                        } else {
                            if (cachedRoster.isRosterItem(item.getJID())) {
                                // existing item
                                RosterItem cachedItem = cachedRoster.getRosterItem(item.getJID());
                                cachedItem.setAsCopyOf(item);
                                cachedRoster.updateRosterItem(cachedItem);
                            } else {
                                // new item
                                cachedRoster.createRosterItem(item);
                            }
                        }
                    }
                }
            }
        }
    } catch (UserNotFoundException e) {
        throw new UnauthorizedException(e);
    }
    return returnPacket;
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) JID(org.xmpp.packet.JID) IQ(org.xmpp.packet.IQ) PacketError(org.xmpp.packet.PacketError) RosterItem(org.jivesoftware.openfire.roster.RosterItem) RosterItem(org.jivesoftware.openfire.roster.RosterItem) Roster(org.jivesoftware.openfire.roster.Roster) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) IQ(org.xmpp.packet.IQ)

Example 39 with Roster

use of org.jivesoftware.openfire.roster.Roster in project Openfire by igniterealtime.

the class PresenceUpdateHandler method directedPresenceSent.

/**
 * Notification method sent to this handler when a user has sent a directed
 * presence to an entity. If the sender of the presence is local (to this server)
 * and the target entity does not belong to the user's roster then update the
 * registry of sent directed presences by the user.
 *
 * @param update  the directed Presence sent by the user to an entity.
 * @param handlerJID the JID of the handler that will receive/handle/process the sent packet.
 * @param jid     the receipient specified in the packet to handle.
 */
public void directedPresenceSent(Presence update, JID handlerJID, String jid) {
    if (update.getFrom() == null) {
        return;
    }
    if (localServer.isLocal(update.getFrom())) {
        boolean keepTrack = false;
        String name = update.getFrom().getNode();
        if (name != null && !"".equals(name)) {
            // Keep track of all directed presences if roster service is disabled
            if (!RosterManager.isRosterServiceEnabled()) {
                keepTrack = true;
            } else {
                try {
                    Roster roster = rosterManager.getRoster(name);
                    // If the directed presence was sent to an entity that is not in the user's
                    // roster, keep a registry of this so that when the user goes offline we
                    // will be able to send the unavailable presence to the entity
                    RosterItem rosterItem = null;
                    try {
                        rosterItem = roster.getRosterItem(update.getTo());
                    } catch (UserNotFoundException e) {
                    // Ignore
                    }
                    if (rosterItem == null || RosterItem.SUB_NONE == rosterItem.getSubStatus() || RosterItem.SUB_TO == rosterItem.getSubStatus()) {
                        keepTrack = true;
                    }
                } catch (UserNotFoundException e) {
                    Log.warn("Presence being sent from unknown user " + name, e);
                } catch (PacketException e) {
                    Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
                }
            }
        } else if (update.getFrom().getResource() != null) {
            // Keep always track of anonymous users directed presences
            keepTrack = true;
        }
        if (keepTrack) {
            String sender = update.getFrom().toString();
            Lock lock = directedPresencesCache.getLock(sender);
            lock.lock();
            try {
                ConcurrentLinkedQueue<DirectedPresence> directedPresences = directedPresencesCache.get(sender);
                if (Presence.Type.unavailable.equals(update.getType())) {
                    if (directedPresences != null) {
                        // It's a directed unavailable presence
                        if (routingTable.hasClientRoute(handlerJID)) {
                            // address of the session) so remove the handler from the map
                            for (DirectedPresence directedPresence : directedPresences) {
                                if (directedPresence.getHandler().equals(handlerJID)) {
                                    directedPresences.remove(directedPresence);
                                    break;
                                }
                            }
                        } else {
                            // unavailable presence
                            for (DirectedPresence directedPresence : directedPresences) {
                                if (directedPresence.getHandler().equals(handlerJID)) {
                                    directedPresence.removeReceiver(jid);
                                    if (directedPresence.isEmpty()) {
                                        directedPresences.remove(directedPresence);
                                    }
                                    break;
                                }
                            }
                        }
                        if (directedPresences.isEmpty()) {
                            // Remove the user from the registry since the list of directed
                            // presences is empty
                            directedPresencesCache.remove(sender);
                            localDirectedPresences.remove(sender);
                        } else {
                            directedPresencesCache.put(sender, directedPresences);
                            localDirectedPresences.put(sender, directedPresences);
                        }
                    }
                } else {
                    if (directedPresences == null) {
                        // We are using a set to avoid duplicate jids in case the user
                        // sends several directed presences to the same handler. The Map also
                        // ensures that if the user sends several presences to the same handler
                        // we will have only one entry in the Map
                        directedPresences = new ConcurrentLinkedQueue<>();
                    }
                    // Add the handler to the list of handler that processed the directed
                    // presence sent by the user. This handler will be used to send
                    // the unavailable presence when the user goes offline
                    DirectedPresence affectedDirectedPresence = null;
                    for (DirectedPresence directedPresence : directedPresences) {
                        if (directedPresence.getHandler().equals(handlerJID)) {
                            affectedDirectedPresence = directedPresence;
                            break;
                        }
                    }
                    if (affectedDirectedPresence == null) {
                        affectedDirectedPresence = new DirectedPresence(handlerJID);
                        directedPresences.add(affectedDirectedPresence);
                    }
                    affectedDirectedPresence.addReceiver(jid);
                    directedPresencesCache.put(sender, directedPresences);
                    localDirectedPresences.put(sender, directedPresences);
                }
            } finally {
                lock.unlock();
            }
        }
    }
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) RosterItem(org.jivesoftware.openfire.roster.RosterItem) Roster(org.jivesoftware.openfire.roster.Roster) PacketException(org.jivesoftware.openfire.PacketException) Lock(java.util.concurrent.locks.Lock)

Example 40 with Roster

use of org.jivesoftware.openfire.roster.Roster in project Openfire by igniterealtime.

the class PresenceUpdateHandler method broadcastUpdate.

/**
 * Broadcast the given update to all subscribers. We need to:
 * <ul>
 * <li>Query the roster table for subscribers</li>
 * <li>Iterate through the list and send the update to each subscriber</li>
 * </ul>
 * <p/>
 * Is there a safe way to cache the query results while maintaining
 * integrity with roster changes?
 *
 * @param update The update to broadcast
 */
private void broadcastUpdate(Presence update) {
    if (update.getFrom() == null) {
        return;
    }
    if (localServer.isLocal(update.getFrom())) {
        // Do nothing if roster service is disabled
        if (!RosterManager.isRosterServiceEnabled()) {
            return;
        }
        // Local updates can simply run through the roster of the local user
        String name = update.getFrom().getNode();
        try {
            if (name != null && !"".equals(name)) {
                Roster roster = rosterManager.getRoster(name);
                roster.broadcastPresence(update);
            }
        } catch (UserNotFoundException e) {
            Log.warn("Presence being sent from unknown user " + name, e);
        } catch (PacketException e) {
            Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
        }
    } else {
        // Foreign updates will do a reverse lookup of entries in rosters
        // on the server
        Log.warn("Presence requested from server " + localServer.getServerInfo().getXMPPDomain() + " by unknown user: " + update.getFrom());
    }
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) Roster(org.jivesoftware.openfire.roster.Roster) PacketException(org.jivesoftware.openfire.PacketException)

Aggregations

Roster (org.jivesoftware.openfire.roster.Roster)42 RosterItem (org.jivesoftware.openfire.roster.RosterItem)29 UserNotFoundException (org.jivesoftware.openfire.user.UserNotFoundException)27 JID (org.xmpp.packet.JID)20 UserAlreadyExistsException (org.jivesoftware.openfire.user.UserAlreadyExistsException)13 SharedGroupException (org.jivesoftware.openfire.SharedGroupException)9 ArrayList (java.util.ArrayList)7 StringTokenizer (java.util.StringTokenizer)4 PacketException (org.jivesoftware.openfire.PacketException)4 UnauthorizedException (org.jivesoftware.openfire.auth.UnauthorizedException)4 ServiceException (org.jivesoftware.openfire.plugin.rest.exceptions.ServiceException)4 Presence (org.xmpp.packet.Presence)4 NotFoundException (org.jivesoftware.util.NotFoundException)3 IQ (org.xmpp.packet.IQ)3 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 Email (net.sf.jml.Email)2 XMPPServer (org.jivesoftware.openfire.XMPPServer)2 ServiceException (org.jivesoftware.openfire.exceptions.ServiceException)2 Group (org.jivesoftware.openfire.group.Group)2 PacketRejectedException (org.jivesoftware.openfire.interceptor.PacketRejectedException)2