Implement roster versioning.

Still needs some testing.
This commit is contained in:
Jonathan Schleifer 2012-02-06 16:17:37 +01:00
parent 04b9740263
commit cf420076c2
5 changed files with 102 additions and 40 deletions

View file

@ -157,7 +157,7 @@
BOOL streamOpen; BOOL streamOpen;
BOOL needsSession; BOOL needsSession;
BOOL encryptionRequired, encrypted; BOOL encryptionRequired, encrypted;
BOOL rosterVersioningSupported; BOOL supportsRosterVersioning;
unsigned int lastID; unsigned int lastID;
/// \endcond /// \endcond
} }
@ -196,7 +196,7 @@
/// \brief Whether the connection is encrypted /// \brief Whether the connection is encrypted
@property (readonly) BOOL encrypted; @property (readonly) BOOL encrypted;
/// \brief Whether roster versioning is supported /// \brief Whether roster versioning is supported
@property (readonly) BOOL rosterVersioningSupported; @property (readonly) BOOL supportsRosterVersioning;
#endif #endif
/** /**
@ -338,7 +338,7 @@
- (id <XMPPStorage>)dataStorage; - (id <XMPPStorage>)dataStorage;
- (void)setLanguage: (OFString*)language; - (void)setLanguage: (OFString*)language;
- (OFString*)language; - (OFString*)language;
- (BOOL)rosterVersioningSupported; - (BOOL)supportsRosterVersioning;
/// \cond internal /// \cond internal
- (void)XMPP_startStream; - (void)XMPP_startStream;

View file

@ -350,9 +350,9 @@
return streamOpen; return streamOpen;
} }
- (BOOL)rosterVersioningSupported - (BOOL)supportsRosterVersioning
{ {
return rosterVersioningSupported; return supportsRosterVersioning;
} }
- (BOOL)checkCertificateAndGetReason: (OFString**)reason - (BOOL)checkCertificateAndGetReason: (OFString**)reason
@ -852,7 +852,7 @@
if ([element elementForName: @"ver" if ([element elementForName: @"ver"
namespace: XMPP_NS_ROSTERVER] != nil) namespace: XMPP_NS_ROSTERVER] != nil)
rosterVersioningSupported = YES; supportsRosterVersioning = YES;
if (mechs != nil) { if (mechs != nil) {
OFEnumerator *enumerator; OFEnumerator *enumerator;

View file

@ -147,9 +147,7 @@
- (id <XMPPStorage>)dataStorage; - (id <XMPPStorage>)dataStorage;
/// \cond internal /// \cond internal
- (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem;
- (void)XMPP_updateRosterItem: (XMPPRosterItem*)rosterItem; - (void)XMPP_updateRosterItem: (XMPPRosterItem*)rosterItem;
- (void)XMPP_deleteRosterItem: (XMPPRosterItem*)rosterItem;
- (void)XMPP_handleInitialRosterForConnection: (XMPPConnection*)connection - (void)XMPP_handleInitialRosterForConnection: (XMPPConnection*)connection
withIQ: (XMPPIQ*)iq; withIQ: (XMPPIQ*)iq;
- (XMPPRosterItem*)XMPP_rosterItemWithXMLElement: (OFXMLElement*)element; - (XMPPRosterItem*)XMPP_rosterItemWithXMLElement: (OFXMLElement*)element;

View file

@ -75,13 +75,28 @@
- (void)requestRoster - (void)requestRoster
{ {
XMPPIQ *iq; XMPPIQ *iq;
OFXMLElement *query;
rosterRequested = YES; rosterRequested = YES;
iq = [XMPPIQ IQWithType: @"get" iq = [XMPPIQ IQWithType: @"get"
ID: [connection generateStanzaID]]; ID: [connection generateStanzaID]];
[iq addChild: [OFXMLElement elementWithName: @"query"
namespace: XMPP_NS_ROSTER]]; query = [OFXMLElement elementWithName: @"query"
namespace: XMPP_NS_ROSTER];
if ([connection supportsRosterVersioning]) {
OFString *ver = [dataStorage stringValueForPath: @"roster.ver"];
if (ver == nil)
ver = @"";
[query addAttributeWithName: @"ver"
stringValue: ver];
}
[iq addChild: query];
[connection sendIQ: iq [connection sendIQ: iq
withCallbackObject: self withCallbackObject: self
selector: @selector(XMPP_handleInitialRosterForConnection: selector: @selector(XMPP_handleInitialRosterForConnection:
@ -110,16 +125,20 @@
if (element != nil) { if (element != nil) {
rosterItem = [self XMPP_rosterItemWithXMLElement: element]; rosterItem = [self XMPP_rosterItemWithXMLElement: element];
if ([[rosterItem subscription] isEqual: @"remove"]) [self XMPP_updateRosterItem: rosterItem];
[self XMPP_deleteRosterItem: rosterItem]; }
else
[self XMPP_addRosterItem: rosterItem]; if ([connection supportsRosterVersioning]) {
OFString *ver =
[[rosterElement attributeForName: @"ver"] stringValue];
[dataStorage setStringValue: ver
forPath: @"roster.ver"];
}
[delegates broadcastSelector: @selector( [delegates broadcastSelector: @selector(
roster:didReceiveRosterItem:) roster:didReceiveRosterItem:)
withObject: self withObject: self
withObject: rosterItem]; withObject: rosterItem];
}
[connection_ sendStanza: [iq resultIQ]]; [connection_ sendStanza: [iq resultIQ]];
@ -203,19 +222,40 @@
return dataStorage; return dataStorage;
} }
- (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem
{
return [self XMPP_updateRosterItem: rosterItem];
}
- (void)XMPP_updateRosterItem: (XMPPRosterItem*)rosterItem - (void)XMPP_updateRosterItem: (XMPPRosterItem*)rosterItem
{ {
if ([connection supportsRosterVersioning]) {
OFMutableDictionary *items = [[[dataStorage dictionaryForPath:
@"roster.items"] mutableCopy] autorelease];
if (![[rosterItem subscription] isEqual: @"remove"]) {
OFMutableDictionary *item = [OFMutableDictionary
dictionaryWithKeysAndObjects:
@"JID", [[rosterItem JID] bareJID],
@"subscription", [rosterItem subscription],
nil];
if ([rosterItem name] != nil)
[item setObject: [rosterItem name]
forKey: @"name"];
if ([rosterItem groups] != nil)
[item setObject: [rosterItem groups]
forKey: @"groups"];
[items setObject: item
forKey: [[rosterItem JID] bareJID]];
} else
[items removeObjectForKey: [[rosterItem JID] bareJID]];
[dataStorage setDictionary: items
forPath: @"roster.items"];
}
if (![[rosterItem subscription] isEqual: @"remove"])
[rosterItems setObject: rosterItem [rosterItems setObject: rosterItem
forKey: [[rosterItem JID] bareJID]]; forKey: [[rosterItem JID] bareJID]];
} else
- (void)XMPP_deleteRosterItem: (XMPPRosterItem*)rosterItem
{
[rosterItems removeObjectForKey: [[rosterItem JID] bareJID]]; [rosterItems removeObjectForKey: [[rosterItem JID] bareJID]];
} }
@ -255,17 +295,37 @@
return rosterItem; return rosterItem;
} }
- (void)XMPP_handleInitialRosterForConnection: (XMPPConnection*)connection - (void)XMPP_handleInitialRosterForConnection: (XMPPConnection*)connection_
withIQ: (XMPPIQ*)iq withIQ: (XMPPIQ*)iq
{ {
OFXMLElement *rosterElement; OFXMLElement *rosterElement;
OFEnumerator *enumerator; OFEnumerator *enumerator;
OFXMLElement *element; OFXMLElement *element;
XMPPRosterItem *rosterItem = nil; XMPPRosterItem *rosterItem;
rosterElement = [iq elementForName: @"query" rosterElement = [iq elementForName: @"query"
namespace: XMPP_NS_ROSTER]; namespace: XMPP_NS_ROSTER];
if ([connection supportsRosterVersioning]) {
OFDictionary *items = [dataStorage
dictionaryForPath: @"roster.items"];
OFEnumerator *enumerator = [items objectEnumerator];
OFDictionary *item;
while ((item = [enumerator nextObject]) != nil) {
rosterItem = [XMPPRosterItem rosterItem];
[rosterItem setJID: [XMPPJID JIDWithString:
[item objectForKey: @"JID"]]];
[rosterItem setName: [item objectForKey: @"name"]];
[rosterItem setSubscription:
[item objectForKey: @"subscription"]];
[rosterItem setGroups: [item objectForKey: @"groups"]];
[rosterItems setObject: rosterItem
forKey: [[rosterItem JID] bareJID]];
}
}
enumerator = [[rosterElement children] objectEnumerator]; enumerator = [[rosterElement children] objectEnumerator];
while ((element = [enumerator nextObject]) != nil) { while ((element = [enumerator nextObject]) != nil) {
if (![[element name] isEqual: @"item"] || if (![[element name] isEqual: @"item"] ||
@ -274,10 +334,14 @@
rosterItem = [self XMPP_rosterItemWithXMLElement: element]; rosterItem = [self XMPP_rosterItemWithXMLElement: element];
if ([[rosterItem subscription] isEqual: @"remove"]) [self XMPP_updateRosterItem: rosterItem];
[self XMPP_deleteRosterItem: rosterItem]; }
else
[self XMPP_addRosterItem: rosterItem]; if ([connection supportsRosterVersioning]) {
OFString *ver =
[[rosterElement attributeForName: @"ver"] stringValue];
[dataStorage setStringValue: ver
forPath: @"roster.ver"];
} }
[delegates broadcastSelector: @selector(rosterWasReceived:) [delegates broadcastSelector: @selector(rosterWasReceived:)

View file

@ -26,6 +26,8 @@
#import "XMPPRosterItem.h" #import "XMPPRosterItem.h"
#import <ObjFW/macros.h>
@implementation XMPPRosterItem @implementation XMPPRosterItem
+ rosterItem + rosterItem
{ {
@ -104,13 +106,11 @@
- (void)setGroups: (OFArray*)groups_ - (void)setGroups: (OFArray*)groups_
{ {
OFArray *old = groups; OF_SETTER(groups, groups_, YES, YES)
groups = [groups_ copy];
[old release];
} }
- (OFArray*)groups - (OFArray*)groups
{ {
return [[groups copy] autorelease]; OF_GETTER(groups, YES)
} }
@end @end