Implement roster versioning.
Still needs some testing.
This commit is contained in:
parent
04b9740263
commit
cf420076c2
5 changed files with 102 additions and 40 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
108
src/XMPPRoster.m
108
src/XMPPRoster.m
|
@ -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:)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue