Index: src/XMPPConnection.h ================================================================== --- src/XMPPConnection.h +++ src/XMPPConnection.h @@ -82,11 +82,11 @@ uint16_t port; id delegate; XMPPAuthenticator *authModule; BOOL needsSession; unsigned int lastID; - OFString *bindID, *sessionID, *rosterID; + OFString *bindID, *sessionID; XMPPRoster *roster; } #ifdef OF_HAVE_PROPERTIES @property (copy) OFString *username, *password, *server, *resource; @@ -141,15 +141,10 @@ * * \return A new, generated, unique stanza ID. */ - (OFString*)generateStanzaID; -/** - * Requests the roster. - */ -- (void)requestRoster; - - (void)setUsername: (OFString*)username; - (OFString*)username; - (void)setPassword: (OFString*)password; - (OFString*)password; - (void)setServer: (OFString*)server; @@ -175,10 +170,9 @@ - (void)XMPP_handleFeatures: (OFXMLElement*)element; - (void)XMPP_sendResourceBind; - (void)XMPP_handleResourceBind: (XMPPIQ*)iq; - (void)XMPP_sendSession; - (void)XMPP_handleSession: (XMPPIQ*)iq; -- (void)XMPP_handleRoster: (XMPPIQ*)iq; @end @interface OFObject (XMPPConnectionDelegate) @end Index: src/XMPPConnection.m ================================================================== --- src/XMPPConnection.m +++ src/XMPPConnection.m @@ -75,11 +75,10 @@ [JID release]; [delegate release]; [authModule release]; [bindID release]; [sessionID release]; - [rosterID release]; [roster release]; [super dealloc]; } @@ -229,19 +228,15 @@ [delegate connectionWasClosed: self]; [parser parseBuffer: buffer withLength: length]; - if (oldParser != nil) { - [oldParser release]; - oldParser = nil; - } - - if (oldElementBuilder != nil) { - [oldElementBuilder release]; - oldElementBuilder = nil; - } + [oldParser release]; + [oldElementBuilder release]; + + oldParser = nil; + oldElementBuilder = nil; } - (OFTCPSocket*)socket { return [[sock retain] autorelease]; @@ -566,14 +561,13 @@ [self XMPP_handleSession: iq]; return; } if ([iq elementForName: @"query" - namespace: XMPP_NS_ROSTER]) { - [self XMPP_handleRoster: iq]; - return; - } + namespace: XMPP_NS_ROSTER]) + if ([roster handleIQ: iq]) + return; if ([delegate respondsToSelector: @selector(connection:didReceiveIQ:)]) handled = [delegate connection: self didReceiveIQ: iq]; @@ -760,105 +754,10 @@ [sessionID release]; sessionID = nil; } -- (void)requestRoster -{ - XMPPIQ *iq; - - if (rosterID != nil) - assert(0); - - rosterID = [[self generateStanzaID] retain]; - iq = [XMPPIQ IQWithType: @"get" - ID: rosterID]; - [iq addChild: [OFXMLElement elementWithName: @"query" - namespace: XMPP_NS_ROSTER]]; - [self sendStanza: iq]; -} - -- (void)XMPP_handleRoster: (XMPPIQ*)iq -{ - OFXMLElement *rosterElement; - OFXMLElement *element; - XMPPRosterItem *rosterItem = nil; - OFString *subscription; - OFEnumerator *enumerator; - BOOL isPush = ![[iq ID] isEqual: rosterID]; - - rosterElement = [iq elementForName: @"query" - namespace: XMPP_NS_ROSTER]; - - if (isPush) - assert([[iq type] isEqual: @"set"]); - else - assert([[iq type] isEqual: @"result"]); - - enumerator = [[rosterElement children] objectEnumerator]; - while ((element = [enumerator nextObject]) != nil) { - OFMutableArray *groups = [OFMutableArray array]; - OFEnumerator *groupEnumerator; - OFXMLElement *groupElement; - - if (![[element name] isEqual: @"item"] || - ![[element namespace] isEqual: XMPP_NS_ROSTER]) - continue; - - rosterItem = [XMPPRosterItem rosterItem]; - [rosterItem setJID: [XMPPJID JIDWithString: - [[element attributeForName: @"jid"] stringValue]]]; - [rosterItem setName: - [[element attributeForName: @"name"] stringValue]]; - - subscription = [[element attributeForName: - @"subscription"] stringValue]; - - if (![subscription isEqual: @"none"] && - ![subscription isEqual: @"to"] && - ![subscription isEqual: @"from"] && - ![subscription isEqual: @"both"] && - (![subscription isEqual: @"remove"] || !isPush)) - subscription = @"none"; - - [rosterItem setSubscription: subscription]; - - groupEnumerator = [[element - elementsForName: @"group" - namespace: XMPP_NS_ROSTER] objectEnumerator]; - while ((groupElement = [groupEnumerator nextObject]) != nil) - [groups addObject: [groupElement stringValue]]; - - if ([groups count] > 0) - [rosterItem setGroups: groups]; - - if ([subscription isEqual: @"remove"]) - [roster XMPP_deleteRosterItem: rosterItem]; - else - [roster XMPP_addRosterItem: rosterItem]; - - if (isPush && [delegate respondsToSelector: - @selector(connection:didReceiveRosterItem:)]) - [delegate connection:self - didReceiveRosterItem: rosterItem]; - } - - if (isPush) { - XMPPIQ *response = [XMPPIQ IQWithType: @"result" - ID: [iq ID]]; - [response setTo: [iq from]]; - [self sendStanza: response]; - } else { - if ([delegate respondsToSelector: - @selector(connectionDidReceiveRoster:)]) - [delegate connectionDidReceiveRoster: self]; - - [rosterID release]; - rosterID = nil; - } -} - - (XMPPJID*)JID { return [[JID copy] autorelease]; } Index: src/XMPPRoster.h ================================================================== --- src/XMPPRoster.h +++ src/XMPPRoster.h @@ -22,21 +22,25 @@ #import @class XMPPConnection; @class XMPPRosterItem; +@class XMPPIQ; @interface XMPPRoster: OFObject { XMPPConnection *connection; OFMutableDictionary *rosterItems; + OFString *rosterID; } - initWithConnection: (XMPPConnection*)conn; - (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem; - (void)XMPP_updateRosterItem: (XMPPRosterItem*)rosterItem; - (void)XMPP_deleteRosterItem: (XMPPRosterItem*)rosterItem; - (OFDictionary*)rosterItems; +- (BOOL)handleIQ: (XMPPIQ*)iq; +- (void)requestRoster; - (void)addRosterItem: (XMPPRosterItem*)rosterItem; - (void)updateRosterItem: (XMPPRosterItem*)rosterItem; - (void)deleteRosterItem: (XMPPRosterItem*)rosterItem; @end Index: src/XMPPRoster.m ================================================================== --- src/XMPPRoster.m +++ src/XMPPRoster.m @@ -17,10 +17,12 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + +#include #import "XMPPRoster.h" #import "XMPPRosterItem.h" #import "XMPPConnection.h" #import "XMPPIQ.h" @@ -43,10 +45,12 @@ } - (void)dealloc { [connection release]; + [rosterItems release]; + [rosterID release]; [super dealloc]; } - (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem @@ -67,10 +71,114 @@ - (OFDictionary*)rosterItems { return [[rosterItems copy] autorelease]; } + +- (void)requestRoster +{ + XMPPIQ *iq; + + if (rosterID != nil) + assert(0); + + rosterID = [[connection generateStanzaID] retain]; + iq = [XMPPIQ IQWithType: @"get" + ID: rosterID]; + [iq addChild: [OFXMLElement elementWithName: @"query" + namespace: XMPP_NS_ROSTER]]; + [connection sendStanza: iq]; +} + +- (BOOL)handleIQ: (XMPPIQ*)iq +{ + OFXMLElement *rosterElement; + OFXMLElement *element; + XMPPRosterItem *rosterItem = nil; + OFString *subscription; + OFEnumerator *enumerator; + BOOL isPush = ![[iq ID] isEqual: rosterID]; + + rosterElement = [iq elementForName: @"query" + namespace: XMPP_NS_ROSTER]; + + if (rosterElement == nil) + return NO; + + if (isPush) { + if (![[iq type] isEqual: @"set"]) + return NO; + } else { + if (![[iq type] isEqual: @"result"]) + return NO; + } + + enumerator = [[rosterElement children] objectEnumerator]; + while ((element = [enumerator nextObject]) != nil) { + OFMutableArray *groups = [OFMutableArray array]; + OFEnumerator *groupEnumerator; + OFXMLElement *groupElement; + + if (![[element name] isEqual: @"item"] || + ![[element namespace] isEqual: XMPP_NS_ROSTER]) + continue; + + rosterItem = [XMPPRosterItem rosterItem]; + [rosterItem setJID: [XMPPJID JIDWithString: + [[element attributeForName: @"jid"] stringValue]]]; + [rosterItem setName: + [[element attributeForName: @"name"] stringValue]]; + + subscription = [[element attributeForName: + @"subscription"] stringValue]; + + if (![subscription isEqual: @"none"] && + ![subscription isEqual: @"to"] && + ![subscription isEqual: @"from"] && + ![subscription isEqual: @"both"] && + (![subscription isEqual: @"remove"] || !isPush)) + subscription = @"none"; + + [rosterItem setSubscription: subscription]; + + groupEnumerator = [[element + elementsForName: @"group" + namespace: XMPP_NS_ROSTER] objectEnumerator]; + while ((groupElement = [groupEnumerator nextObject]) != nil) + [groups addObject: [groupElement stringValue]]; + + if ([groups count] > 0) + [rosterItem setGroups: groups]; + + if ([subscription isEqual: @"remove"]) + [self XMPP_deleteRosterItem: rosterItem]; + else + [self XMPP_addRosterItem: rosterItem]; + + if (isPush && [[connection delegate] respondsToSelector: + @selector(connection:didReceiveRosterItem:)]) + [[connection delegate] connection: connection + didReceiveRosterItem: rosterItem]; + } + + if (isPush) { + XMPPIQ *response = [XMPPIQ IQWithType: @"result" + ID: [iq ID]]; + [response setTo: [iq from]]; + [connection sendStanza: response]; + } else { + if ([[connection delegate] respondsToSelector: + @selector(connectionDidReceiveRoster:)]) + [[connection delegate] + connectionDidReceiveRoster: connection]; + + [rosterID release]; + rosterID = nil; + } + + return YES; +} - (void)addRosterItem: (XMPPRosterItem*)rosterItem { [self updateRosterItem: rosterItem]; } Index: tests/test.m ================================================================== --- tests/test.m +++ tests/test.m @@ -118,11 +118,11 @@ - (void)connection: (XMPPConnection*)conn wasBoundToJID: (XMPPJID*)jid { of_log(@"Bound to JID: %@", [jid fullJID]); - [conn requestRoster]; + [[conn roster] requestRoster]; } - (void)connectionDidReceiveRoster: (XMPPConnection*)conn { XMPPPresence *pres;