/** * 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.getNode())) && 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) { 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) { for (org.xmpp.packet.Roster.Item item : packet.getItems()) { if (item.getSubscription() == org.xmpp.packet.Roster.Subscription.remove) { removeItem(cachedRoster, packet.getFrom(), item); } 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); } } } returnPacket = IQ.createResultIQ(packet); } } catch (UserNotFoundException e) { throw new UnauthorizedException(e); } return returnPacket; }
/** * Manage the subscription request. This method updates a user's roster state, storing any changes * made, and updating the roster owner if changes occured. * * @param target The roster target's jid (the item's jid to be changed) * @param isSending True if the request is being sent by the owner * @param type The subscription change type (subscribe, unsubscribe, etc.) * @param roster The Roster that is updated. * @return <tt>true</tt> if the subscription state has changed. */ private boolean manageSub(JID target, boolean isSending, Presence.Type type, Roster roster) throws UserAlreadyExistsException, SharedGroupException { RosterItem item = null; RosterItem.AskType oldAsk; RosterItem.SubType oldSub = null; RosterItem.RecvType oldRecv; boolean newItem = false; try { if (roster.isRosterItem(target)) { item = roster.getRosterItem(target); } else { if (Presence.Type.unsubscribed == type || Presence.Type.unsubscribe == type || Presence.Type.subscribed == type) { // Do not create a roster item when processing a confirmation of // an unsubscription or receiving an unsubscription request or a // subscription approval from an unknown user return false; } item = roster.createRosterItem(target, false, true); newItem = true; } // Get a snapshot of the item state oldAsk = item.getAskStatus(); oldSub = item.getSubStatus(); oldRecv = item.getRecvStatus(); // Update the item state based in the received presence type updateState(item, type, isSending); // Update the roster IF the item state has changed if (oldAsk != item.getAskStatus() || oldSub != item.getSubStatus() || oldRecv != item.getRecvStatus()) { roster.updateRosterItem(item); } else if (newItem) { // Do not push items with a state of "None + Pending In" if (item.getSubStatus() != RosterItem.SUB_NONE || item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE) { roster.broadcast(item, false); } } } catch (UserNotFoundException e) { // Should be there because we just checked that it's an item Log.error(LocaleUtils.getLocalizedString("admin.error"), e); } return oldSub != item.getSubStatus(); }