powered by Jive Software

RosterListener problem (don''t hate me!)

If an item is stored in the Roster in mixed case (IE. syNIC@linuxhelp.HOMEUNIX.com) or if a user signs on with a mixed case JID, it is possible that RosterListener.presenceChanged() will never get fired.

If the item is stored in my Roster like this: SyNIC@linuxhelp.homeunix.com and that person signs on with synic@linuxhelp.homeunix.com then only the presence for synic@linuxhelp.homeunix.com will be recieved, and RosterListener.presenceChanged() will never be fired. This is because the PresencePacketListener inner class of org.jivesoftware.smack.Roster does not compensate for this.

This minor edit does fix it:

/**
     * Listens for all presence packets and processes them.
     */
    private class PresencePacketListener implements PacketListener {
        public void processPacket(Packet packet) {
            Presence presence = (Presence)packet;
            String from = presence.getFrom();
            String key = StringUtils.parseBareAddress(from);
            // If an "available" packet, add it to the presence map. Each presence map will hold
            // for a particular user a map with the presence packets saved for each resource.
            if (presence.getType() == Presence.Type.AVAILABLE) {
                Map userPresences;
                // Get the user presence map
                if (presenceMap.get(key) == null) {
                    userPresences = new HashMap();
                    presenceMap.put(key, userPresences);
                } else {
                    userPresences = (Map) presenceMap.get(key);
                }
                // Add the new presence taking in consideration the presence�s resource
                userPresences.put(StringUtils.parseResource(from), presence);
                // If the user is in the roster, fire an event.
                synchronized (entries) {
                    for (Iterator i = entries.iterator(); i.hasNext();) {
                        RosterEntry entry = (RosterEntry) i.next();
                        if (entry.getUser().toLowerCase().equals(key.toLowerCase())) {
                            fireRosterPresenceEvent(key);
                        }
                    }
                }
            }
            // If an "unavailable" packet, remove any entries in the presence map.
            else if (presence.getType() == Presence.Type.UNAVAILABLE) {
                if (presenceMap.get(key) != null) {
                    Map userPresences = (Map) presenceMap.get(key);
                    userPresences.remove(StringUtils.parseResource(from));
                    if (userPresences.isEmpty()) {
                        presenceMap.remove(key);
                    }
                }
                // If the user is in the roster, fire an event.
                synchronized (entries) {
                    for (Iterator i=entries.iterator(); i.hasNext(); ) {
                        RosterEntry entry = (RosterEntry)i.next();
                        if (entry.getUser().toLowerCase().equals(key.toLowerCase())) {
                            fireRosterPresenceEvent(key);
                        }
                    }
                }
            }
            else if (presence.getType() == Presence.Type.SUBSCRIBE) {
                if (subscriptionMode == SUBSCRIPTION_ACCEPT_ALL) {
                    // Accept all subscription requests.
                    Presence response = new Presence(Presence.Type.SUBSCRIBED);
                    response.setTo(presence.getFrom());
                    connection.sendPacket(response);
                }
                else if (subscriptionMode == SUBSCRIPTION_REJECT_ALL) {
                    // Reject all subscription requests.
                    Presence response = new Presence(Presence.Type.UNSUBSCRIBED);
                    response.setTo(presence.getFrom());
                    connection.sendPacket(response);
                }
                // Otherwise, in manual mode so ignore.
            }
        }
    }

I just change the lines that say:

if(entry.getUser().equals(key))

to say:

if(entry.getUser().toLowerCase().equals(key.toLowerCase()))

What do you think?

Adam,

Thanks for the bug report. It seems that XMPPAddresses must be case insensitive. Iā€™'ll file a bug issue for the next release.

Thanks again,

ā€“ Gato