/** * Adds the new user to others roster. * * @param newUser the new user * @param otherItem the other item * @param currentUser the current user * @throws ServiceException the service exception */ private static void addNewUserToOthersRoster( User newUser, RosterItem otherItem, String currentUser) throws ServiceException { otherItem.getJid(); UserManager userManager = UserManager.getInstance(); // Is this user registered with our OF server? String username = otherItem.getJid().getNode(); if (username != null && username.length() > 0 && userManager.isRegisteredUser(username) && XMPPServer.getInstance() .isLocal(XMPPServer.getInstance().createJID(currentUser, null))) { try { User otherUser = userManager.getUser(username); Roster otherRoster = otherUser.getRoster(); RosterItem oldUserOnOthersRoster = otherRoster.getRosterItem(XMPPServer.getInstance().createJID(currentUser, null)); try { if (!oldUserOnOthersRoster.isOnlyShared()) { RosterItem justCreated = otherRoster.createRosterItem( XMPPServer.getInstance().createJID(newUser.getUsername(), null), oldUserOnOthersRoster.getNickname(), oldUserOnOthersRoster.getGroups(), true, true); justCreated.setAskStatus(oldUserOnOthersRoster.getAskStatus()); justCreated.setRecvStatus(oldUserOnOthersRoster.getRecvStatus()); justCreated.setSubStatus(oldUserOnOthersRoster.getSubStatus()); otherRoster.updateRosterItem(justCreated); } } catch (UserAlreadyExistsException e) { throw new ServiceException( "Could not create roster item for user ", newUser.getUsername(), ExceptionType.USER_ALREADY_EXISTS_EXCEPTION, Response.Status.CONFLICT, e); } catch (SharedGroupException e) { throw new ServiceException( "Could not create roster item, because it is a contact from a shared group", newUser.getUsername(), ExceptionType.USER_ALREADY_EXISTS_EXCEPTION, Response.Status.BAD_REQUEST, e); } } catch (UserNotFoundException e) { throw new ServiceException( "Could not create roster item for user " + newUser.getUsername() + " because it is a contact from a shared group.", newUser.getUsername(), ExceptionType.USER_NOT_FOUND_EXCEPTION, Response.Status.NOT_FOUND, e); } } }
/** * 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; }
/** * Copy roster. * * @param currentUser the current user * @param newUser the new user * @param currentUserName the current user name * @throws ServiceException the service exception */ private static void copyRoster(User currentUser, User newUser, String currentUserName) throws ServiceException { Roster newRoster = newUser.getRoster(); Roster currentRoster = currentUser.getRoster(); for (RosterItem item : currentRoster.getRosterItems()) { try { List<String> groups = item.getGroups(); RosterItem justCreated = newRoster.createRosterItem(item.getJid(), item.getNickname(), groups, true, true); justCreated.setAskStatus(item.getAskStatus()); justCreated.setRecvStatus(item.getRecvStatus()); justCreated.setSubStatus(item.getSubStatus()); for (Group gr : item.getSharedGroups()) { justCreated.addSharedGroup(gr); } for (Group gr : item.getInvisibleSharedGroups()) { justCreated.addInvisibleSharedGroup(gr); } newRoster.updateRosterItem(justCreated); addNewUserToOthersRoster(newUser, item, currentUserName); } catch (UserAlreadyExistsException e) { throw new ServiceException( "Could not create roster item for user ", newUser.getUsername(), ExceptionType.USER_ALREADY_EXISTS_EXCEPTION, Response.Status.CONFLICT, e); } catch (SharedGroupException e) { throw new ServiceException( "Could not create roster item, because it is a contact from a shared group", newUser.getUsername(), ExceptionType.USER_ALREADY_EXISTS_EXCEPTION, Response.Status.BAD_REQUEST, e); } catch (UserNotFoundException e) { throw new ServiceException( "Could not update roster item for user " + newUser.getUsername() + " because it was not properly created.", newUser.getUsername(), ExceptionType.USER_NOT_FOUND_EXCEPTION, Response.Status.NOT_FOUND, e); } } }
/** * 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(); }