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

View file

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

View file

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

View file

@ -75,13 +75,28 @@
- (void)requestRoster
{
XMPPIQ *iq;
OFXMLElement *query;
rosterRequested = YES;
iq = [XMPPIQ IQWithType: @"get"
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
withCallbackObject: self
selector: @selector(XMPP_handleInitialRosterForConnection:
@ -110,17 +125,21 @@
if (element != nil) {
rosterItem = [self XMPP_rosterItemWithXMLElement: element];
if ([[rosterItem subscription] isEqual: @"remove"])
[self XMPP_deleteRosterItem: rosterItem];
else
[self XMPP_addRosterItem: rosterItem];
[delegates broadcastSelector: @selector(
roster:didReceiveRosterItem:)
withObject: self
withObject: rosterItem];
[self XMPP_updateRosterItem: rosterItem];
}
if ([connection supportsRosterVersioning]) {
OFString *ver =
[[rosterElement attributeForName: @"ver"] stringValue];
[dataStorage setStringValue: ver
forPath: @"roster.ver"];
}
[delegates broadcastSelector: @selector(
roster:didReceiveRosterItem:)
withObject: self
withObject: rosterItem];
[connection_ sendStanza: [iq resultIQ]];
return YES;
@ -203,20 +222,41 @@
return dataStorage;
}
- (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem
{
return [self XMPP_updateRosterItem: rosterItem];
}
- (void)XMPP_updateRosterItem: (XMPPRosterItem*)rosterItem
{
[rosterItems setObject: rosterItem
forKey: [[rosterItem JID] bareJID]];
}
if ([connection supportsRosterVersioning]) {
OFMutableDictionary *items = [[[dataStorage dictionaryForPath:
@"roster.items"] mutableCopy] autorelease];
- (void)XMPP_deleteRosterItem: (XMPPRosterItem*)rosterItem
{
[rosterItems removeObjectForKey: [[rosterItem JID] bareJID]];
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
forKey: [[rosterItem JID] bareJID]];
else
[rosterItems removeObjectForKey: [[rosterItem JID] bareJID]];
}
- (XMPPRosterItem*)XMPP_rosterItemWithXMLElement: (OFXMLElement*)element
@ -255,17 +295,37 @@
return rosterItem;
}
- (void)XMPP_handleInitialRosterForConnection: (XMPPConnection*)connection
- (void)XMPP_handleInitialRosterForConnection: (XMPPConnection*)connection_
withIQ: (XMPPIQ*)iq
{
OFXMLElement *rosterElement;
OFEnumerator *enumerator;
OFXMLElement *element;
XMPPRosterItem *rosterItem = nil;
XMPPRosterItem *rosterItem;
rosterElement = [iq elementForName: @"query"
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];
while ((element = [enumerator nextObject]) != nil) {
if (![[element name] isEqual: @"item"] ||
@ -274,10 +334,14 @@
rosterItem = [self XMPP_rosterItemWithXMLElement: element];
if ([[rosterItem subscription] isEqual: @"remove"])
[self XMPP_deleteRosterItem: rosterItem];
else
[self XMPP_addRosterItem: rosterItem];
[self XMPP_updateRosterItem: rosterItem];
}
if ([connection supportsRosterVersioning]) {
OFString *ver =
[[rosterElement attributeForName: @"ver"] stringValue];
[dataStorage setStringValue: ver
forPath: @"roster.ver"];
}
[delegates broadcastSelector: @selector(rosterWasReceived:)

View file

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