Index: src/XMPPConnection.h ================================================================== --- src/XMPPConnection.h +++ src/XMPPConnection.h @@ -28,10 +28,11 @@ @class XMPPIQ; @class XMPPMessage; @class XMPPPresence; @class XMPPAuthenticator; @class XMPPRoster; +@class XMPPRosterItem; #define XMPP_NS_BIND @"urn:ietf:params:xml:ns:xmpp-bind" #define XMPP_NS_CLIENT @"jabber:client" #define XMPP_NS_ROSTER @"jabber:iq:roster" #define XMPP_NS_SASL @"urn:ietf:params:xml:ns:xmpp-sasl" @@ -49,10 +50,12 @@ #endif - (void)connectionWasAuthenticated: (XMPPConnection*)conn; - (void)connection: (XMPPConnection*)conn wasBoundToJID: (XMPPJID*)jid; - (void)connectionDidReceiveRoster: (XMPPConnection*)conn; +- (void)connection: (XMPPConnection*)conn + didReceiveRosterItem: (XMPPRosterItem*)rosterItem; - (BOOL)connection: (XMPPConnection*)conn didReceiveIQ: (XMPPIQ*)iq; - (void)connection: (XMPPConnection*)conn didReceivePresence: (XMPPPresence*)pres; - (void)connection: (XMPPConnection*)conn Index: src/XMPPConnection.m ================================================================== --- src/XMPPConnection.m +++ src/XMPPConnection.m @@ -435,11 +435,12 @@ if ([[iq ID] isEqual: sessionID]) { [self XMPP_handleSession: iq]; return; } - if ([[iq ID] isEqual: rosterID]) { + if ([iq elementForName: @"query" + namespace: XMPP_NS_ROSTER]) { [self XMPP_handleRoster: iq]; return; } if ([delegate respondsToSelector: @selector(connection:didReceiveIQ:)]) @@ -646,38 +647,90 @@ } - (void)XMPP_handleRoster: (XMPPIQ*)iq { OFXMLElement *rosterElem; - OFEnumerator *enumerator; OFXMLElement *elem; - - assert([[iq type] isEqual: @"result"]); + OFString *subscription; rosterElem = [iq elementForName: @"query" namespace: XMPP_NS_ROSTER]; - assert(rosterElem != nil); + if ([[iq ID] isEqual: rosterID]) { + OFEnumerator *enumerator; + + assert([[iq type] isEqual: @"result"]); + + enumerator = [[rosterElem children] objectEnumerator]; + while ((elem = [enumerator nextObject]) != nil) { + XMPPRosterItem *rosterItem; + OFMutableArray *groups = [OFMutableArray array]; + OFEnumerator *groupEnumerator; + OFXMLElement *groupElem; + + if (![[elem name] isEqual: @"item"] || + ![[elem namespace] isEqual: XMPP_NS_ROSTER]) + continue; + + rosterItem = [XMPPRosterItem rosterItem]; + [rosterItem setJID: [XMPPJID JIDWithString: + [[elem attributeForName: @"jid"] stringValue]]]; + [rosterItem setName: + [[elem attributeForName: @"name"] stringValue]]; + + subscription = [[elem attributeForName: + @"subscription"] stringValue]; + if ([subscription isEqual: @"none"] || + [subscription isEqual: @"to"] || + [subscription isEqual: @"from"] || + [subscription isEqual: @"both"]) + [rosterItem setSubscription: subscription]; + + groupEnumerator = + [[elem elementsForName: @"group" + namespace: XMPP_NS_ROSTER] + objectEnumerator]; + while ((groupElem = [groupEnumerator nextObject]) + != nil) + [groups addObject: [groupElem stringValue]]; + + if ([groups count] > 0) + [rosterItem setGroups: groups]; + + [roster XMPP_addRosterItem: rosterItem]; + } + + if ([delegate respondsToSelector: + @selector(connectionDidReceiveRoster:)]) + [delegate connectionDidReceiveRoster: self]; - enumerator = [[rosterElem children] objectEnumerator]; - while ((elem = [enumerator nextObject]) != nil) { + [rosterID release]; + rosterID = nil; + } else { XMPPRosterItem *rosterItem; OFMutableArray *groups = [OFMutableArray array]; OFEnumerator *groupEnumerator; OFXMLElement *groupElem; + XMPPIQ *response; - if (![[elem name] isEqual: @"item"] || - ![[elem namespace] isEqual: XMPP_NS_ROSTER]) - continue; + assert([[iq type] isEqual: @"set"]); + elem = [[rosterElem children] firstObject]; rosterItem = [XMPPRosterItem rosterItem]; [rosterItem setJID: [XMPPJID JIDWithString: [[elem attributeForName: @"jid"] stringValue]]]; [rosterItem setName: [[elem attributeForName: @"name"] stringValue]]; - [rosterItem setSubscription: - [[elem attributeForName: @"subscription"] stringValue]]; + + subscription = [[elem attributeForName: + @"subscription"] stringValue]; + if ([subscription isEqual: @"none"] || + [subscription isEqual: @"to"] || + [subscription isEqual: @"from"] || + [subscription isEqual: @"both"] || + [subscription isEqual: @"remove"]) + [rosterItem setSubscription: subscription]; groupEnumerator = [[elem elementsForName: @"group" namespace: XMPP_NS_ROSTER] objectEnumerator]; while ((groupElem = [groupEnumerator nextObject]) != nil) @@ -684,19 +737,22 @@ [groups addObject: [groupElem stringValue]]; if ([groups count] > 0) [rosterItem setGroups: groups]; - [roster XMPP_addRosterItem: rosterItem]; - } - - if ([delegate respondsToSelector: - @selector(connectionDidReceiveRoster:)]) - [delegate connectionDidReceiveRoster: self]; - - [rosterID release]; - rosterID = nil; + [roster XMPP_updateRosterItem: rosterItem]; + + response = [XMPPIQ IQWithType: @"result" + ID: [iq ID]]; + [response setTo: [iq from]]; + [self sendStanza: response]; + + if ([delegate respondsToSelector: + @selector(connection:didReceiveRosterItem:)]) + [delegate connection:self + didReceiveRosterItem: rosterItem]; + } } - (XMPPJID*)JID { return [[JID copy] autorelease]; Index: tests/test.m ================================================================== --- tests/test.m +++ tests/test.m @@ -133,10 +133,16 @@ [pres addPriority: 10]; [pres addStatus: @"ObjXMPP test is working!"]; [conn sendStanza: pres]; } + +- (void)connection: (XMPPConnection*)conn + didReceiveRosterItem: (XMPPRosterItem*)rosterItem +{ + of_log(@"Got roster push: %@", rosterItem); +} - (BOOL)connection: (XMPPConnection*)conn didReceiveIQ: (XMPPIQ*)iq { of_log(@"IQ: %@", iq);