Index: ObjXMPP.xcodeproj/project.pbxproj ================================================================== --- ObjXMPP.xcodeproj/project.pbxproj +++ ObjXMPP.xcodeproj/project.pbxproj @@ -31,10 +31,12 @@ 4BC559FB1337AC0900E345C7 /* XMPPPresence.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC559E91337AC0900E345C7 /* XMPPPresence.m */; }; 4BC559FC1337AC0900E345C7 /* XMPPSCRAMAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC559EA1337AC0900E345C7 /* XMPPSCRAMAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BC55A001337AC1800E345C7 /* XMPPSCRAMAuth.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC559FD1337AC1800E345C7 /* XMPPSCRAMAuth.m */; }; 4BC55A011337AC1800E345C7 /* XMPPStanza.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC559FE1337AC1800E345C7 /* XMPPStanza.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BC55A021337AC1800E345C7 /* XMPPStanza.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC559FF1337AC1800E345C7 /* XMPPStanza.m */; }; + 4BD9BF59134003F700DAB43A /* XMPPRosterItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BD9BF57134003F700DAB43A /* XMPPRosterItem.h */; }; + 4BD9BF5A134003F700DAB43A /* XMPPRosterItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BD9BF58134003F700DAB43A /* XMPPRosterItem.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 4B1295DE1337BD2D00154B25 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -73,10 +75,12 @@ 4BC559EA1337AC0900E345C7 /* XMPPSCRAMAuth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPSCRAMAuth.h; path = src/XMPPSCRAMAuth.h; sourceTree = SOURCE_ROOT; }; 4BC559FD1337AC1800E345C7 /* XMPPSCRAMAuth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPSCRAMAuth.m; path = src/XMPPSCRAMAuth.m; sourceTree = SOURCE_ROOT; }; 4BC559FE1337AC1800E345C7 /* XMPPStanza.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPStanza.h; path = src/XMPPStanza.h; sourceTree = SOURCE_ROOT; }; 4BC559FF1337AC1800E345C7 /* XMPPStanza.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPStanza.m; path = src/XMPPStanza.m; sourceTree = SOURCE_ROOT; }; 4BC55A051337ADA800E345C7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 4BD9BF57134003F700DAB43A /* XMPPRosterItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPRosterItem.h; path = src/XMPPRosterItem.h; sourceTree = SOURCE_ROOT; }; + 4BD9BF58134003F700DAB43A /* XMPPRosterItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPRosterItem.m; path = src/XMPPRosterItem.m; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 4B1295DD1337BD2D00154B25 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -153,10 +157,12 @@ 4BC559E51337AC0900E345C7 /* XMPPMessage.m */, 4BC559E61337AC0900E345C7 /* XMPPPLAINAuth.h */, 4BC559E71337AC0900E345C7 /* XMPPPLAINAuth.m */, 4BC559E81337AC0900E345C7 /* XMPPPresence.h */, 4BC559E91337AC0900E345C7 /* XMPPPresence.m */, + 4BD9BF57134003F700DAB43A /* XMPPRosterItem.h */, + 4BD9BF58134003F700DAB43A /* XMPPRosterItem.m */, 4BC559EA1337AC0900E345C7 /* XMPPSCRAMAuth.h */, 4BC559FD1337AC1800E345C7 /* XMPPSCRAMAuth.m */, 4BC559FE1337AC1800E345C7 /* XMPPStanza.h */, 4BC559FF1337AC1800E345C7 /* XMPPStanza.m */, 4BC559D91337AC0900E345C7 /* arc4random_uniform.m */, @@ -187,10 +193,11 @@ 4BC559F61337AC0900E345C7 /* XMPPMessage.h in Headers */, 4BC559F81337AC0900E345C7 /* XMPPPLAINAuth.h in Headers */, 4BC559FA1337AC0900E345C7 /* XMPPPresence.h in Headers */, 4BC559FC1337AC0900E345C7 /* XMPPSCRAMAuth.h in Headers */, 4BC55A011337AC1800E345C7 /* XMPPStanza.h in Headers */, + 4BD9BF59134003F700DAB43A /* XMPPRosterItem.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ @@ -285,10 +292,11 @@ 4BC559F71337AC0900E345C7 /* XMPPMessage.m in Sources */, 4BC559F91337AC0900E345C7 /* XMPPPLAINAuth.m in Sources */, 4BC559FB1337AC0900E345C7 /* XMPPPresence.m in Sources */, 4BC55A001337AC1800E345C7 /* XMPPSCRAMAuth.m in Sources */, 4BC55A021337AC1800E345C7 /* XMPPStanza.m in Sources */, + 4BD9BF5A134003F700DAB43A /* XMPPRosterItem.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ Index: src/XMPPConnection.m ================================================================== --- src/XMPPConnection.m +++ src/XMPPConnection.m @@ -34,10 +34,11 @@ #import "XMPPStanza.h" #import "XMPPJID.h" #import "XMPPIQ.h" #import "XMPPMessage.h" #import "XMPPPresence.h" +#import "XMPPRosterItem.h" #import "XMPPExceptions.h" #define NS_BIND @"urn:ietf:params:xml:ns:xmpp-bind" #define NS_CLIENT @"jabber:client" #define NS_ROSTER @"jabber:iq:roster" @@ -629,32 +630,41 @@ if (![rosterElem.name isEqual: @"query"] || ![rosterElem.namespace isEqual: NS_ROSTER]) assert(0); for (OFXMLElement *elem in rosterElem.children) { - OFArray *groups; + XMPPRosterItem *rosterItem; + OFMutableArray *groups = [OFMutableArray array]; if (![elem.name isEqual: @"item"] || ![elem.ns isEqual: NS_ROSTER]) continue; - groups = [elem elementsForName: @"group" - namespace: NS_ROSTER]; + rosterItem = [XMPPRosterItem rosterItem]; + rosterItem.JID = [XMPPJID JIDWithString: + [rosterElem attributeForName: @"jid"].stringValue]; + rosterItem.name = + [rosterElem attributeForName: @"name"].stringValue; + rosterItem.subscription = + [rosterElem attributeForName: @"subscription"].stringValue; - for (OFXMLElement *groupElem in groups) { - OFString *group = groupElem.stringValue; + for (OFXMLElement *groupElem in + [elem elementsForName: @"group" + namespace: NS_ROSTER]) { OFMutableArray *rosterGroup = - [roster objectForKey: group]; + [roster objectForKey: rosterElem.stringValue]; if (rosterGroup == nil) { rosterGroup = [OFMutableArray array]; [roster setObject: rosterGroup - forKey: group]; + forKey: rosterElem.stringValue]; } - [rosterGroup addObject: elem]; + [rosterGroup addObject: rosterItem]; } + + rosterItem.groups = groups; if (groups.count == 0) { OFMutableArray *rosterGroup = [roster objectForKey: @""]; @@ -662,11 +672,11 @@ rosterGroup = [OFMutableArray array]; [roster setObject: rosterGroup forKey: @""]; } - [rosterGroup addObject: elem]; + [rosterGroup addObject: rosterItem]; } } if ([delegate respondsToSelector: @selector(connectionDidReceiveRoster:)]) Index: src/XMPPJID.m ================================================================== --- src/XMPPJID.m +++ src/XMPPJID.m @@ -37,13 +37,19 @@ return [[[self alloc] initWithString: str] autorelease]; } - initWithString: (OFString*)str { + size_t nodesep, resourcesep; + self = [super init]; - size_t nodesep, resourcesep; + if (str == nil) { + [self release]; + return nil; + } + nodesep = [str indexOfFirstOccurrenceOfString: @"@"]; resourcesep = [str indexOfFirstOccurrenceOfString: @"/"]; if (nodesep == SIZE_MAX) [self setNode: nil]; Index: src/XMPPStanza.m ================================================================== --- src/XMPPStanza.m +++ src/XMPPStanza.m @@ -160,11 +160,11 @@ if (from_ != nil) [self addAttributeWithName: @"from" stringValue: from_.fullJID]; } -- (OFString*)from +- (XMPPJID*)from { return [[from copy] autorelease]; } - (void)setTo: (XMPPJID*)to_ @@ -178,11 +178,11 @@ if (to_ != nil) [self addAttributeWithName: @"to" stringValue: to_.fullJID]; } -- (OFString*)to +- (XMPPJID*)to { return [[to copy] autorelease]; } - (void)setType: (OFString*)type_