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 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
120
src/XMPPRoster.m
120
src/XMPPRoster.m
|
@ -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:)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue