- Update
This commit is contained in:
1 parent
d281d765ea
commit
5b074a5176
1261 files changed
+199158
-7303
No files matched your search
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>XMPPvCard.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// XMPPvCardAvatarCoreDataStorageObject.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Originally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
// This class is so that we don't load the photoData each time we need to touch the XMPPvCardCoreDataStorageObject.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
@class XMPPvCardCoreDataStorageObject;
|
||||
|
||||
|
||||
@interface XMPPvCardAvatarCoreDataStorageObject : NSManagedObject
|
||||
|
||||
@property (nonatomic, strong) NSData * photoData;
|
||||
@property (nonatomic, strong) XMPPvCardCoreDataStorageObject * vCard;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// XMPPvCardAvatarCoreDataStorageObject.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Originally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
|
||||
#import "XMPPvCardAvatarCoreDataStorageObject.h"
|
||||
#import "XMPPvCardCoreDataStorageObject.h"
|
||||
|
||||
|
||||
@implementation XMPPvCardAvatarCoreDataStorageObject
|
||||
|
||||
@dynamic photoData;
|
||||
@dynamic vCard;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// XMPPvCardCoreDataStorage.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Originally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
#import "XMPPCoreDataStorage.h"
|
||||
#import "XMPPvCardTempModule.h"
|
||||
#import "XMPPvCardAvatarModule.h"
|
||||
|
||||
/**
|
||||
* This class is an example implementation of XMPPCapabilitiesStorage using core data.
|
||||
* You are free to substitute your own storage class.
|
||||
**/
|
||||
|
||||
@interface XMPPvCardCoreDataStorage : XMPPCoreDataStorage <
|
||||
XMPPvCardAvatarStorage,
|
||||
XMPPvCardTempModuleStorage
|
||||
> {
|
||||
// Inherits protected variables from XMPPCoreDataStorage
|
||||
}
|
||||
|
||||
/**
|
||||
* XEP-0054 provides a mechanism for transmitting vCards via XMPP.
|
||||
* Because the JID doesn't change very often and can be large with image data,
|
||||
* it is safe to persistently store the JID and wait for a user to explicity ask for an update,
|
||||
* or use XEP-0153 to monitor for JID changes.
|
||||
*
|
||||
* For this reason, it is recommended you use this sharedInstance across all your xmppStreams.
|
||||
* This way all streams can shared a knowledgebase concerning known JIDs and Avatar photos.
|
||||
*
|
||||
* All other aspects of vCard handling (such as lookup failures, etc) are kept separate between streams.
|
||||
**/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
//
|
||||
// This class inherits from XMPPCoreDataStorage.
|
||||
//
|
||||
// Please see the XMPPCoreDataStorage header file for more information.
|
||||
//
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,235 @@
|
||||
//
|
||||
// XMPPvCardCoreDataStorage.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Originally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
|
||||
#import "XMPPvCardCoreDataStorage.h"
|
||||
#import "XMPPvCardCoreDataStorageObject.h"
|
||||
#import "XMPPvCardTempCoreDataStorageObject.h"
|
||||
#import "XMPPvCardAvatarCoreDataStorageObject.h"
|
||||
#import "XMPP.h"
|
||||
#import "XMPPCoreDataStorageProtected.h"
|
||||
#import "XMPPLogging.h"
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
// Log levels: off, error, warn, info, verbose
|
||||
#if DEBUG
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; // | XMPP_LOG_FLAG_TRACE;
|
||||
#else
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
kXMPPvCardTempNetworkFetchTimeout = 10,
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation XMPPvCardCoreDataStorage
|
||||
|
||||
static XMPPvCardCoreDataStorage *sharedInstance;
|
||||
|
||||
+ (instancetype)sharedInstance
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
sharedInstance = [[XMPPvCardCoreDataStorage alloc] initWithDatabaseFilename:nil storeOptions:nil];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Setup
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (BOOL)configureWithParent:(XMPPvCardTempModule *)aParent queue:(dispatch_queue_t)queue
|
||||
{
|
||||
return [super configureWithParent:aParent queue:queue];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Overrides
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)commonInit
|
||||
{
|
||||
autoAllowExternalBinaryDataStorage = YES;
|
||||
autoRecreateDatabaseFile = YES;
|
||||
[super commonInit];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark XMPPvCardAvatarStorage protocol
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (NSData *)photoDataForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream
|
||||
{
|
||||
// This is a public method.
|
||||
// It may be invoked on any thread/queue.
|
||||
|
||||
XMPPLogTrace();
|
||||
|
||||
__block NSData *result;
|
||||
|
||||
[self executeBlock:^{
|
||||
|
||||
XMPPvCardCoreDataStorageObject *vCard;
|
||||
vCard = [XMPPvCardCoreDataStorageObject fetchOrInsertvCardForJID:jid
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
|
||||
result = vCard.photoData;
|
||||
}];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString *)photoHashForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream
|
||||
{
|
||||
// This is a public method.
|
||||
// It may be invoked on any thread/queue.
|
||||
|
||||
XMPPLogTrace();
|
||||
|
||||
__block NSString *result;
|
||||
|
||||
[self executeBlock:^{
|
||||
|
||||
XMPPvCardCoreDataStorageObject *vCard;
|
||||
vCard = [XMPPvCardCoreDataStorageObject fetchOrInsertvCardForJID:jid
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
|
||||
result = vCard.photoHash;
|
||||
}];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)clearvCardTempForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream
|
||||
{
|
||||
// This is a public method.
|
||||
// It may be invoked on any thread/queue.
|
||||
|
||||
XMPPLogTrace();
|
||||
|
||||
[self scheduleBlock:^{
|
||||
|
||||
XMPPvCardCoreDataStorageObject *vCard;
|
||||
vCard = [XMPPvCardCoreDataStorageObject fetchOrInsertvCardForJID:jid
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
|
||||
vCard.vCardTemp = nil;
|
||||
vCard.lastUpdated = [NSDate date];
|
||||
}];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark XMPPvCardTempModuleStorage protocol
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (XMPPvCardTemp *)vCardTempForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream
|
||||
{
|
||||
// This is a public method.
|
||||
// It may be invoked on any thread/queue.
|
||||
|
||||
XMPPLogTrace();
|
||||
|
||||
__block XMPPvCardTemp *result;
|
||||
|
||||
[self executeBlock:^{
|
||||
|
||||
XMPPvCardCoreDataStorageObject *vCard;
|
||||
vCard = [XMPPvCardCoreDataStorageObject fetchOrInsertvCardForJID:jid
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
|
||||
result = vCard.vCardTemp;
|
||||
}];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)setvCardTemp:(XMPPvCardTemp *)vCardTemp forJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream
|
||||
{
|
||||
// This is a public method.
|
||||
// It may be invoked on any thread/queue.
|
||||
|
||||
XMPPLogTrace();
|
||||
|
||||
[self scheduleBlock:^{
|
||||
|
||||
XMPPvCardCoreDataStorageObject *vCard;
|
||||
vCard = [XMPPvCardCoreDataStorageObject fetchOrInsertvCardForJID:jid
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
|
||||
vCard.waitingForFetch = @NO;
|
||||
vCard.vCardTemp = vCardTemp;
|
||||
|
||||
// Update photo and photo hash
|
||||
vCard.photoData = vCardTemp.photo;
|
||||
|
||||
vCard.lastUpdated = [NSDate date];
|
||||
}];
|
||||
}
|
||||
|
||||
- (XMPPvCardTemp *)myvCardTempForXMPPStream:(XMPPStream *)stream
|
||||
{
|
||||
if(!stream) return nil;
|
||||
|
||||
return [self vCardTempForJID:[[stream myJID] bareJID] xmppStream:stream];
|
||||
}
|
||||
|
||||
- (BOOL)shouldFetchvCardTempForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream
|
||||
{
|
||||
// This is a public method.
|
||||
// It may be invoked on any thread/queue.
|
||||
|
||||
XMPPLogTrace();
|
||||
|
||||
__block BOOL result;
|
||||
|
||||
[self executeBlock:^{
|
||||
|
||||
XMPPvCardCoreDataStorageObject *vCard;
|
||||
vCard = [XMPPvCardCoreDataStorageObject fetchOrInsertvCardForJID:jid
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
|
||||
BOOL waitingForFetch = [vCard.waitingForFetch boolValue];
|
||||
|
||||
if(![stream isAuthenticated])
|
||||
{
|
||||
result = NO;
|
||||
}
|
||||
else if (!waitingForFetch)
|
||||
{
|
||||
vCard.waitingForFetch = @YES;
|
||||
vCard.lastUpdated = [NSDate date];
|
||||
|
||||
result = YES;
|
||||
}
|
||||
else if ([vCard.lastUpdated timeIntervalSinceNow] < -kXMPPvCardTempNetworkFetchTimeout)
|
||||
{
|
||||
// Our last request exceeded the timeout, send a new one
|
||||
vCard.lastUpdated = [NSDate date];
|
||||
|
||||
result = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have an outstanding request, no need to send another one.
|
||||
result = NO;
|
||||
}
|
||||
}];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// XMPPvCardCoreDataStorageObject.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Originally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
|
||||
@class XMPPJID;
|
||||
@class XMPPvCardTemp;
|
||||
@class XMPPvCardTempCoreDataStorageObject;
|
||||
@class XMPPvCardAvatarCoreDataStorageObject;
|
||||
|
||||
|
||||
@interface XMPPvCardCoreDataStorageObject : NSManagedObject
|
||||
|
||||
|
||||
/*
|
||||
* User's JID, indexed for lookups
|
||||
*/
|
||||
@property (nonatomic, strong) NSString * jidStr;
|
||||
|
||||
/*
|
||||
* User's photoHash used by XEP-0153
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) NSString * photoHash;
|
||||
|
||||
/*
|
||||
* The last time the record was modified, also used to determine if we need to fetch again
|
||||
*/
|
||||
@property (nonatomic, strong) NSDate * lastUpdated;
|
||||
|
||||
|
||||
/*
|
||||
* Flag indicating whether a get request is already pending, used in conjunction with lastUpdated
|
||||
*/
|
||||
@property (nonatomic, strong) NSNumber * waitingForFetch;
|
||||
|
||||
|
||||
/*
|
||||
* Relationship to the vCardTemp record.
|
||||
* We use a relationship, so the vCardTemp stays faulted until we really need it.
|
||||
*/
|
||||
@property (nonatomic, strong) XMPPvCardTempCoreDataStorageObject * vCardTempRel;
|
||||
|
||||
|
||||
/*
|
||||
* Relationship to the vCardAvatar record.
|
||||
* We use a relationship, so the vCardAvatar stays faulted until we really need it.
|
||||
*/
|
||||
@property (nonatomic, strong) XMPPvCardAvatarCoreDataStorageObject * vCardAvatarRel;
|
||||
|
||||
|
||||
/*
|
||||
* Accessor to retrieve photoData, so we can hide the underlying relationship implementation.
|
||||
*/
|
||||
@property (nonatomic, strong) NSData *photoData;
|
||||
|
||||
|
||||
/*
|
||||
* Accessor to retrieve vCardTemp, so we can hide the underlying relationship implementation.
|
||||
*/
|
||||
@property (nonatomic, strong) XMPPvCardTemp *vCardTemp;
|
||||
|
||||
|
||||
+ (XMPPvCardCoreDataStorageObject *)fetchOrInsertvCardForJID:(XMPPJID *)jid
|
||||
inManagedObjectContext:(NSManagedObjectContext *)moc;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,180 @@
|
||||
//
|
||||
// XMPPvCardCoreDataStorageObject.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Originally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
|
||||
#import "XMPPvCardCoreDataStorageObject.h"
|
||||
#import "XMPPvCardTempCoreDataStorageObject.h"
|
||||
#import "XMPPvCardAvatarCoreDataStorageObject.h"
|
||||
|
||||
#import "XMPPJID.h"
|
||||
#import "XMPPStream.h"
|
||||
#import "NSNumber+XMPP.h"
|
||||
#import "NSData+XMPP.h"
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
|
||||
@implementation XMPPvCardCoreDataStorageObject
|
||||
|
||||
+ (XMPPvCardCoreDataStorageObject *)fetchvCardForJID:(XMPPJID *)jid
|
||||
inManagedObjectContext:(NSManagedObjectContext *)moc
|
||||
{
|
||||
NSString *entityName = NSStringFromClass([XMPPvCardCoreDataStorageObject class]);
|
||||
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName
|
||||
inManagedObjectContext:moc];
|
||||
|
||||
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"jidStr == %@", [jid bare]];
|
||||
|
||||
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
|
||||
[fetchRequest setEntity:entity];
|
||||
[fetchRequest setPredicate:predicate];
|
||||
[fetchRequest setIncludesPendingChanges:YES];
|
||||
[fetchRequest setFetchLimit:1];
|
||||
|
||||
NSArray *results = [moc executeFetchRequest:fetchRequest error:nil];
|
||||
|
||||
|
||||
return (XMPPvCardCoreDataStorageObject *)[results lastObject];
|
||||
}
|
||||
|
||||
|
||||
+ (XMPPvCardCoreDataStorageObject *)insertEmptyvCardForJID:(XMPPJID *)jid
|
||||
inManagedObjectContext:(NSManagedObjectContext *)moc
|
||||
{
|
||||
NSString *entityName = NSStringFromClass([XMPPvCardCoreDataStorageObject class]);
|
||||
|
||||
XMPPvCardCoreDataStorageObject *vCard = [NSEntityDescription insertNewObjectForEntityForName:entityName
|
||||
inManagedObjectContext:moc];
|
||||
|
||||
vCard.jidStr = [jid bare];
|
||||
return vCard;
|
||||
}
|
||||
|
||||
+ (XMPPvCardCoreDataStorageObject *)fetchOrInsertvCardForJID:(XMPPJID *)jid
|
||||
inManagedObjectContext:(NSManagedObjectContext *)moc
|
||||
{
|
||||
XMPPvCardCoreDataStorageObject *vCard = [self fetchvCardForJID:jid inManagedObjectContext:moc];
|
||||
if (vCard == nil)
|
||||
{
|
||||
vCard = [self insertEmptyvCardForJID:jid inManagedObjectContext:moc];
|
||||
}
|
||||
|
||||
return vCard;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark NSManagedObject methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)awakeFromInsert
|
||||
{
|
||||
[super awakeFromInsert];
|
||||
[self setPrimitiveValue:[NSDate date] forKey:@"lastUpdated"];
|
||||
}
|
||||
|
||||
|
||||
- (void)willSave
|
||||
{
|
||||
/*
|
||||
if (![self isDeleted] && [self isUpdated]) {
|
||||
[self setPrimitiveValue:[NSDate date] forKey:@"lastUpdated"];
|
||||
}
|
||||
*/
|
||||
|
||||
[super willSave];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Getter/setter methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@dynamic jidStr;
|
||||
@dynamic photoHash;
|
||||
@dynamic lastUpdated;
|
||||
@dynamic waitingForFetch;
|
||||
@dynamic vCardTempRel;
|
||||
@dynamic vCardAvatarRel;
|
||||
|
||||
|
||||
- (NSData *)photoData {
|
||||
return self.vCardAvatarRel.photoData;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPhotoData:(NSData *)photoData
|
||||
{
|
||||
if ([photoData length] == 0)
|
||||
{
|
||||
if (self.vCardAvatarRel != nil)
|
||||
{
|
||||
[[self managedObjectContext] deleteObject:self.vCardAvatarRel];
|
||||
[self setPrimitiveValue:nil forKey:@"photoHash"];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.vCardAvatarRel == nil)
|
||||
{
|
||||
NSString *entityName = NSStringFromClass([XMPPvCardAvatarCoreDataStorageObject class]);
|
||||
|
||||
self.vCardAvatarRel = [NSEntityDescription insertNewObjectForEntityForName:entityName
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
}
|
||||
|
||||
[self willChangeValueForKey:@"photoData"];
|
||||
self.vCardAvatarRel.photoData = photoData;
|
||||
[self didChangeValueForKey:@"photoData"];
|
||||
|
||||
[self setPrimitiveValue:[[photoData xmpp_sha1Digest] xmpp_hexStringValue] forKey:@"photoHash"];
|
||||
}
|
||||
|
||||
|
||||
- (XMPPvCardTemp *)vCardTemp {
|
||||
return self.vCardTempRel.vCardTemp;
|
||||
}
|
||||
|
||||
|
||||
- (void)setVCardTemp:(XMPPvCardTemp *)vCardTemp
|
||||
{
|
||||
if (vCardTemp == nil && self.vCardTempRel != nil)
|
||||
{
|
||||
[[self managedObjectContext] deleteObject:self.vCardTempRel];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.vCardTempRel == nil)
|
||||
{
|
||||
NSString *entityName = NSStringFromClass([XMPPvCardTempCoreDataStorageObject class]);
|
||||
|
||||
self.vCardTempRel = [NSEntityDescription insertNewObjectForEntityForName:entityName
|
||||
inManagedObjectContext:[self managedObjectContext]];
|
||||
}
|
||||
|
||||
[self willChangeValueForKey:@"vCardTemp"];
|
||||
self.vCardTempRel.vCardTemp = vCardTemp;
|
||||
[self didChangeValueForKey:@"vCardTemp"];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark KVO methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+ (NSSet *)keyPathsForValuesAffectingPhotoHash
|
||||
{
|
||||
return [NSSet setWithObjects:@"vCardAvatarRel", @"photoData", nil];
|
||||
}
|
||||
|
||||
+ (NSSet *)keyPathsForValuesAffectingVCardTemp
|
||||
{
|
||||
return [NSSet setWithObject:@"vCardTempRel"];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// XMPPvCardTempCoreDataStorageObject.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Oringally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
// This class is so that we don't load the vCardTemp each time we need to touch the XMPPvCardCoreDataStorageObject.
|
||||
// The vCardTemp abstraction also makes it easier to eventually add support for vCard4 over XMPP (XEP-0292).
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
#import "XMPPvcardTemp.h"
|
||||
|
||||
@class XMPPvCardCoreDataStorageObject;
|
||||
|
||||
|
||||
@interface XMPPvCardTempCoreDataStorageObject : NSManagedObject
|
||||
|
||||
@property (nonatomic, strong) XMPPvCardTemp * vCardTemp;
|
||||
@property (nonatomic, strong) XMPPvCardCoreDataStorageObject * vCard;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// XMPPvCardTempCoreDataStorageObject.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Originally created by Eric Chamberlain on 3/18/11.
|
||||
//
|
||||
|
||||
#import "XMPPvCardTempCoreDataStorageObject.h"
|
||||
#import "XMPPvCardCoreDataStorageObject.h"
|
||||
|
||||
|
||||
@implementation XMPPvCardTempCoreDataStorageObject
|
||||
|
||||
@dynamic vCardTemp;
|
||||
@dynamic vCard;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// XMPPvCardTemp.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
#import "XMPPIQ.h"
|
||||
#import "XMPPJID.h"
|
||||
#import "XMPPUser.h"
|
||||
#import "XMPPvCardTempAdr.h"
|
||||
#import "XMPPvCardTempBase.h"
|
||||
#import "XMPPvCardTempEmail.h"
|
||||
#import "XMPPvCardTempLabel.h"
|
||||
#import "XMPPvCardTempTel.h"
|
||||
|
||||
|
||||
typedef enum _XMPPvCardTempClass {
|
||||
XMPPvCardTempClassNone,
|
||||
XMPPvCardTempClassPublic,
|
||||
XMPPvCardTempClassPrivate,
|
||||
XMPPvCardTempClassConfidential,
|
||||
} XMPPvCardTempClass;
|
||||
|
||||
|
||||
extern NSString *const kXMPPNSvCardTemp;
|
||||
extern NSString *const kXMPPvCardTempElement;
|
||||
|
||||
|
||||
/*
|
||||
* Note: according to the DTD, every fields bar N and FN can appear multiple times.
|
||||
* The provided accessors only support this for the field types where multiple
|
||||
* entries make sense - for the others, if required, the NSXMLElement accessors
|
||||
* must be used.
|
||||
*/
|
||||
@interface XMPPvCardTemp : XMPPvCardTempBase
|
||||
|
||||
|
||||
@property (nonatomic, strong) NSDate *bday;
|
||||
@property (nonatomic, strong) NSData *photo;
|
||||
@property (nonatomic, strong) NSString *nickname;
|
||||
@property (nonatomic, strong) NSString *formattedName;
|
||||
@property (nonatomic, strong) NSString *familyName;
|
||||
@property (nonatomic, strong) NSString *givenName;
|
||||
@property (nonatomic, strong) NSString *middleName;
|
||||
@property (nonatomic, strong) NSString *prefix;
|
||||
@property (nonatomic, strong) NSString *suffix;
|
||||
|
||||
@property (nonatomic, strong) NSArray *addresses;
|
||||
@property (nonatomic, strong) NSArray *labels;
|
||||
@property (nonatomic, strong) NSArray *telecomsAddresses;
|
||||
@property (nonatomic, strong) NSArray *emailAddresses;
|
||||
|
||||
@property (nonatomic, strong) XMPPJID *jid;
|
||||
@property (nonatomic, strong) NSString *mailer;
|
||||
|
||||
@property (nonatomic, strong) NSTimeZone *timeZone;
|
||||
@property (nonatomic, strong) CLLocation *location;
|
||||
|
||||
@property (nonatomic, strong) NSString *title;
|
||||
@property (nonatomic, strong) NSString *role;
|
||||
@property (nonatomic, strong) NSData *logo;
|
||||
@property (nonatomic, strong) XMPPvCardTemp *agent;
|
||||
@property (nonatomic, strong) NSString *orgName;
|
||||
|
||||
/*
|
||||
* ORGUNITs can only be set if there is already an ORGNAME. Otherwise, changes are ignored.
|
||||
*/
|
||||
@property (nonatomic, strong) NSArray *orgUnits;
|
||||
|
||||
@property (nonatomic, strong) NSArray *categories;
|
||||
@property (nonatomic, strong) NSString *note;
|
||||
@property (nonatomic, strong) NSString *prodid;
|
||||
@property (nonatomic, strong) NSDate *revision;
|
||||
@property (nonatomic, strong) NSString *sortString;
|
||||
@property (nonatomic, strong) NSString *phoneticSound;
|
||||
@property (nonatomic, strong) NSData *sound;
|
||||
@property (nonatomic, strong) NSString *uid;
|
||||
@property (nonatomic, strong) NSString *url;
|
||||
@property (nonatomic, strong) NSString *version;
|
||||
@property (nonatomic, strong) NSString *desc;
|
||||
|
||||
@property (nonatomic, assign) XMPPvCardTempClass privacyClass;
|
||||
@property (nonatomic, strong) NSData *key;
|
||||
@property (nonatomic, strong) NSString *keyType;
|
||||
|
||||
+ (XMPPvCardTemp *)vCardTempFromElement:(NSXMLElement *)element;
|
||||
+ (XMPPvCardTemp *)vCardTemp;
|
||||
+ (XMPPvCardTemp *)vCardTempSubElementFromIQ:(XMPPIQ *)iq;
|
||||
+ (XMPPvCardTemp *)vCardTempCopyFromIQ:(XMPPIQ *)iq;
|
||||
+ (XMPPIQ *)iqvCardRequestForJID:(XMPPJID *)jid;
|
||||
|
||||
|
||||
- (void)addAddress:(XMPPvCardTempAdr *)adr;
|
||||
- (void)removeAddress:(XMPPvCardTempAdr *)adr;
|
||||
- (void)clearAddresses;
|
||||
|
||||
|
||||
- (void)addLabel:(XMPPvCardTempLabel *)label;
|
||||
- (void)removeLabel:(XMPPvCardTempLabel *)label;
|
||||
- (void)clearLabels;
|
||||
|
||||
|
||||
- (void)addTelecomsAddress:(XMPPvCardTempTel *)tel;
|
||||
- (void)removeTelecomsAddress:(XMPPvCardTempTel *)tel;
|
||||
- (void)clearTelecomsAddresses;
|
||||
|
||||
|
||||
- (void)addEmailAddress:(XMPPvCardTempEmail *)email;
|
||||
- (void)removeEmailAddress:(XMPPvCardTempEmail *)email;
|
||||
- (void)clearEmailAddresses;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,932 @@
|
||||
//
|
||||
// XMPPvCardTemp.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "XMPPvCardTemp.h"
|
||||
#import "XMPPLogging.h"
|
||||
#import "XMPPDateTimeProfiles.h"
|
||||
#import "NSData+XMPP.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR;
|
||||
#endif
|
||||
|
||||
NSString *const kXMPPNSvCardTemp = @"vcard-temp";
|
||||
NSString *const kXMPPvCardTempElement = @"vCard";
|
||||
|
||||
|
||||
@implementation XMPPvCardTemp
|
||||
|
||||
#if DEBUG
|
||||
|
||||
+ (void)initialize {
|
||||
// We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
|
||||
// The size of the two classes is expected to be the same.
|
||||
//
|
||||
// If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
|
||||
// This check is here to aid future developers who may make this mistake.
|
||||
//
|
||||
// For Fearless And Experienced Objective-C Developers:
|
||||
// It may be possible to support adding instance variables to this class if you seriously need it.
|
||||
// To do so, try realloc'ing self after altering the class, and then initialize your variables.
|
||||
|
||||
size_t superSize = class_getInstanceSize([NSXMLElement class]);
|
||||
size_t ourSize = class_getInstanceSize([XMPPvCardTemp class]);
|
||||
|
||||
if (superSize != ourSize)
|
||||
{
|
||||
XMPPLogError(@"Adding instance variables to XMPPvCardTemp is not currently supported!");
|
||||
|
||||
[DDLog flushLog];
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+ (XMPPvCardTemp *)vCardTempFromElement:(NSXMLElement *)elem {
|
||||
object_setClass(elem, [XMPPvCardTemp class]);
|
||||
|
||||
return (XMPPvCardTemp *)elem;
|
||||
}
|
||||
|
||||
+ (XMPPvCardTemp *)vCardTemp{
|
||||
NSXMLElement *vCardTempElement = [NSXMLElement elementWithName:kXMPPvCardTempElement xmlns:kXMPPNSvCardTemp];
|
||||
return [XMPPvCardTemp vCardTempFromElement:vCardTempElement];
|
||||
}
|
||||
|
||||
+ (XMPPvCardTemp *)vCardTempSubElementFromIQ:(XMPPIQ *)iq
|
||||
{
|
||||
if ([iq isResultIQ])
|
||||
{
|
||||
NSXMLElement *query = [iq elementForName:kXMPPvCardTempElement xmlns:kXMPPNSvCardTemp];
|
||||
if (query)
|
||||
{
|
||||
return [self vCardTempFromElement:query];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (XMPPvCardTemp *)vCardTempCopyFromIQ:(XMPPIQ *)iq
|
||||
{
|
||||
return [[self vCardTempSubElementFromIQ:iq] copy];
|
||||
}
|
||||
|
||||
|
||||
+ (XMPPIQ *)iqvCardRequestForJID:(XMPPJID *)jid {
|
||||
XMPPIQ *iq = [XMPPIQ iqWithType:@"get" to:[jid bareJID] elementID:[XMPPStream generateUUID]];
|
||||
NSXMLElement *vCardElem = [NSXMLElement elementWithName:kXMPPvCardTempElement xmlns:kXMPPNSvCardTemp];
|
||||
|
||||
[iq addChild:vCardElem];
|
||||
return iq;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Identification Types
|
||||
|
||||
|
||||
- (NSDate *)bday {
|
||||
NSDate *bday = nil;
|
||||
NSXMLElement *elem = [self elementForName:@"BDAY"];
|
||||
|
||||
if (elem != nil) {
|
||||
bday = [NSDate dateWithXmppDateString:[elem stringValue]];
|
||||
}
|
||||
|
||||
return bday;
|
||||
}
|
||||
|
||||
|
||||
- (void)setBday:(NSDate *)bday {
|
||||
NSXMLElement *elem = [self elementForName:@"BDAY"];
|
||||
|
||||
if (elem == nil) {
|
||||
elem = [NSXMLElement elementWithName:@"BDAY"];
|
||||
[self addChild:elem];
|
||||
}
|
||||
|
||||
[elem setStringValue:[bday xmppDateString]];
|
||||
}
|
||||
|
||||
|
||||
- (NSData *)photo {
|
||||
NSData *decodedData = nil;
|
||||
NSXMLElement *photo = [self elementForName:@"PHOTO"];
|
||||
|
||||
if (photo != nil) {
|
||||
// There is a PHOTO element. It should have a TYPE and a BINVAL
|
||||
//NSXMLElement *fileType = [photo elementForName:@"TYPE"];
|
||||
NSXMLElement *binval = [photo elementForName:@"BINVAL"];
|
||||
|
||||
if (binval) {
|
||||
NSData *base64Data = [[binval stringValue] dataUsingEncoding:NSASCIIStringEncoding];
|
||||
decodedData = [base64Data xmpp_base64Decoded];
|
||||
}
|
||||
}
|
||||
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPhoto:(NSData *)data {
|
||||
|
||||
NSXMLElement *photo = [self elementForName:@"PHOTO"];
|
||||
|
||||
if(photo)
|
||||
{
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:photo]];
|
||||
}
|
||||
|
||||
if([data length])
|
||||
{
|
||||
NSXMLElement *photo = [NSXMLElement elementWithName:@"PHOTO"];
|
||||
[self addChild:photo];
|
||||
|
||||
NSString *imageType = [data xmpp_imageType];
|
||||
|
||||
if([imageType length])
|
||||
{
|
||||
NSXMLElement *type = [NSXMLElement elementWithName:@"TYPE"];
|
||||
[photo addChild:type];
|
||||
[type setStringValue:imageType];
|
||||
}
|
||||
|
||||
NSXMLElement *binval = [NSXMLElement elementWithName:@"BINVAL"];
|
||||
[photo addChild:binval];
|
||||
[binval setStringValue:[data xmpp_base64Encoded]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)nickname {
|
||||
return [[self elementForName:@"NICKNAME"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setNickname:(NSString *)nick {
|
||||
XMPP_VCARD_SET_STRING_CHILD(nick, @"NICKNAME");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)formattedName {
|
||||
return [[self elementForName:@"FN"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setFormattedName:(NSString *)fn {
|
||||
XMPP_VCARD_SET_STRING_CHILD(fn, @"FN");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)familyName {
|
||||
NSString *result = nil;
|
||||
NSXMLElement *name = [self elementForName:@"N"];
|
||||
|
||||
if (name != nil) {
|
||||
NSXMLElement *part = [name elementForName:@"FAMILY"];
|
||||
|
||||
if (part != nil) {
|
||||
result = [part stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setFamilyName:(NSString *)family {
|
||||
XMPP_VCARD_SET_N_CHILD(family, @"FAMILY");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)givenName {
|
||||
NSString *result = nil;
|
||||
NSXMLElement *name = [self elementForName:@"N"];
|
||||
|
||||
if (name != nil) {
|
||||
NSXMLElement *part = [name elementForName:@"GIVEN"];
|
||||
|
||||
if (part != nil) {
|
||||
result = [part stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setGivenName:(NSString *)given {
|
||||
XMPP_VCARD_SET_N_CHILD(given, @"GIVEN");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)middleName {
|
||||
NSString *result = nil;
|
||||
NSXMLElement *name = [self elementForName:@"N"];
|
||||
|
||||
if (name != nil) {
|
||||
NSXMLElement *part = [name elementForName:@"MIDDLE"];
|
||||
|
||||
if (part != nil) {
|
||||
result = [part stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setMiddleName:(NSString *)middle {
|
||||
XMPP_VCARD_SET_N_CHILD(middle, @"MIDDLE");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)prefix {
|
||||
NSString *result = nil;
|
||||
NSXMLElement *name = [self elementForName:@"N"];
|
||||
|
||||
if (name != nil) {
|
||||
NSXMLElement *part = [name elementForName:@"PREFIX"];
|
||||
|
||||
if (part != nil) {
|
||||
result = [part stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPrefix:(NSString *)prefix {
|
||||
XMPP_VCARD_SET_N_CHILD(prefix, @"PREFIX");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)suffix {
|
||||
NSString *result = nil;
|
||||
NSXMLElement *name = [self elementForName:@"N"];
|
||||
|
||||
if (name != nil) {
|
||||
NSXMLElement *part = [name elementForName:@"SUFFIX"];
|
||||
|
||||
if (part != nil) {
|
||||
result = [part stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setSuffix:(NSString *)suffix {
|
||||
XMPP_VCARD_SET_N_CHILD(suffix, @"SUFFIX");
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Delivery Addressing Types
|
||||
|
||||
|
||||
- (NSArray *)addresses { return nil; }
|
||||
- (void)addAddress:(XMPPvCardTempAdr *)adr { }
|
||||
- (void)removeAddress:(XMPPvCardTempAdr *)adr { }
|
||||
- (void)setAddresses:(NSArray *)adrs { }
|
||||
- (void)clearAddresses { }
|
||||
|
||||
|
||||
- (NSArray *)labels { return nil; }
|
||||
- (void)addLabel:(XMPPvCardTempLabel *)label { }
|
||||
- (void)removeLabel:(XMPPvCardTempLabel *)label { }
|
||||
- (void)setLabels:(NSArray *)labels { }
|
||||
- (void)clearLabels { }
|
||||
|
||||
|
||||
- (NSArray *)telecomsAddresses { return nil; }
|
||||
- (void)addTelecomsAddress:(XMPPvCardTempTel *)tel { }
|
||||
- (void)removeTelecomsAddress:(XMPPvCardTempTel *)tel { }
|
||||
- (void)setTelecomsAddresses:(NSArray *)tels { }
|
||||
- (void)clearTelecomsAddresses { }
|
||||
|
||||
|
||||
- (NSArray *)emailAddresses { return nil; }
|
||||
- (void)addEmailAddress:(XMPPvCardTempEmail *)email { }
|
||||
- (void)removeEmailAddress:(XMPPvCardTempEmail *)email { }
|
||||
- (void)setEmailAddresses:(NSArray *)emails { }
|
||||
- (void)clearEmailAddresses { }
|
||||
|
||||
|
||||
- (XMPPJID *)jid {
|
||||
XMPPJID *jid = nil;
|
||||
NSXMLElement *elem = [self elementForName:@"JABBERID"];
|
||||
|
||||
if (elem != nil) {
|
||||
jid = [XMPPJID jidWithString:[elem stringValue]];
|
||||
}
|
||||
|
||||
return jid;
|
||||
}
|
||||
|
||||
|
||||
- (void)setJid:(XMPPJID *)jid {
|
||||
NSXMLElement *elem = [self elementForName:@"JABBERID"];
|
||||
|
||||
if (elem == nil && jid != nil) {
|
||||
elem = [NSXMLElement elementWithName:@"JABBERID"];
|
||||
[self addChild:elem];
|
||||
}
|
||||
|
||||
if (jid != nil) {
|
||||
[elem setStringValue:[jid full]];
|
||||
} else if (elem != nil) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:elem]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)mailer {
|
||||
return [[self elementForName:@"MAILER"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setMailer:(NSString *)mailer {
|
||||
XMPP_VCARD_SET_STRING_CHILD(mailer, @"MAILER");
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Geographical Types
|
||||
|
||||
|
||||
- (NSTimeZone *)timeZone {
|
||||
// Turns out this is hard. Being lazy for now (not like anyone actually uses this, right?)
|
||||
NSXMLElement *tz = [self elementForName:@"TZ"];
|
||||
if (tz != nil) {
|
||||
// This is unlikely to work. :-(
|
||||
return [NSTimeZone timeZoneWithName:[tz stringValue]];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)setTimeZone:(NSTimeZone *)tz {
|
||||
NSXMLElement *elem = [self elementForName:@"TZ"];
|
||||
|
||||
if (elem == nil && tz != nil) {
|
||||
elem = [NSXMLElement elementWithName:@"TZ"];
|
||||
[self addChild:elem];
|
||||
}
|
||||
|
||||
if (tz != nil) {
|
||||
NSInteger offset = [tz secondsFromGMT];
|
||||
[elem setStringValue:[NSString stringWithFormat:@"%02ld:%02ld",
|
||||
(long)(offset / 3600), (long)((offset % 3600) / 60)]];
|
||||
} else if (elem != nil) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:elem]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (CLLocation *)location {
|
||||
CLLocation *loc = nil;
|
||||
NSXMLElement *geo = [self elementForName:@"GEO"];
|
||||
|
||||
if (geo != nil) {
|
||||
NSXMLElement *lat = [geo elementForName:@"LAT"];
|
||||
NSXMLElement *lon = [geo elementForName:@"LON"];
|
||||
|
||||
loc = [[CLLocation alloc] initWithLatitude:[[lat stringValue] doubleValue] longitude:[[lon stringValue] doubleValue]];
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
|
||||
- (void)setLocation:(CLLocation *)geo {
|
||||
NSXMLElement *elem = [self elementForName:@"GEO"];
|
||||
NSXMLElement *lat;
|
||||
NSXMLElement *lon;
|
||||
|
||||
if (geo != nil) {
|
||||
CLLocationCoordinate2D coord = [geo coordinate];
|
||||
if (elem == nil) {
|
||||
elem = [NSXMLElement elementWithName:@"GEO"];
|
||||
[self addChild:elem];
|
||||
|
||||
lat = [NSXMLElement elementWithName:@"LAT"];
|
||||
[elem addChild:lat];
|
||||
lon = [NSXMLElement elementWithName:@"LON"];
|
||||
[elem addChild:lon];
|
||||
} else {
|
||||
lat = [elem elementForName:@"LAT"];
|
||||
lon = [elem elementForName:@"LON"];
|
||||
}
|
||||
|
||||
[lat setStringValue:[NSString stringWithFormat:@"%.6f", coord.latitude]];
|
||||
[lon setStringValue:[NSString stringWithFormat:@"%.6f", coord.longitude]];
|
||||
} else if (elem != nil) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:elem]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Organizational Types
|
||||
|
||||
|
||||
- (NSString *)title {
|
||||
return [[self elementForName:@"TITLE"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setTitle:(NSString *)title {
|
||||
XMPP_VCARD_SET_STRING_CHILD(title, @"TITLE");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)role {
|
||||
return [[self elementForName:@"ROLE"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setRole:(NSString *)role {
|
||||
XMPP_VCARD_SET_STRING_CHILD(role, @"ROLE");
|
||||
}
|
||||
|
||||
|
||||
- (NSData *)logo {
|
||||
NSData *decodedData = nil;
|
||||
NSXMLElement *logo = [self elementForName:@"LOGO"];
|
||||
|
||||
if (logo != nil) {
|
||||
// There is a LOGO element. It should have a TYPE and a BINVAL
|
||||
//NSXMLElement *fileType = [photo elementForName:@"TYPE"];
|
||||
NSXMLElement *binval = [logo elementForName:@"BINVAL"];
|
||||
|
||||
if (binval) {
|
||||
NSData *base64Data = [[binval stringValue] dataUsingEncoding:NSASCIIStringEncoding];
|
||||
decodedData = [base64Data xmpp_base64Decoded];
|
||||
}
|
||||
}
|
||||
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
|
||||
- (void)setLogo:(NSData *)data {
|
||||
NSXMLElement *logo = [self elementForName:@"LOGO"];
|
||||
|
||||
if (logo == nil) {
|
||||
logo = [NSXMLElement elementWithName:@"LOGO"];
|
||||
[self addChild:logo];
|
||||
}
|
||||
|
||||
NSXMLElement *binval = [logo elementForName:@"BINVAL"];
|
||||
|
||||
if (binval == nil) {
|
||||
binval = [NSXMLElement elementWithName:@"BINVAL"];
|
||||
[logo addChild:binval];
|
||||
}
|
||||
|
||||
[binval setStringValue:[data xmpp_base64Encoded]];
|
||||
}
|
||||
|
||||
|
||||
- (XMPPvCardTemp *)agent {
|
||||
XMPPvCardTemp *agent = nil;
|
||||
NSXMLElement *elem = [self elementForName:@"AGENT"];
|
||||
|
||||
if (elem != nil) {
|
||||
agent = [XMPPvCardTemp vCardTempFromElement:elem];
|
||||
}
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
||||
|
||||
- (void)setAgent:(XMPPvCardTemp *)agent {
|
||||
NSXMLElement *elem = [self elementForName:@"AGENT"];
|
||||
|
||||
if (elem != nil) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:elem]];
|
||||
}
|
||||
|
||||
if (agent != nil) {
|
||||
[self addChild:agent];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)orgName {
|
||||
NSString *result = nil;
|
||||
NSXMLElement *org = [self elementForName:@"ORG"];
|
||||
|
||||
if (org != nil) {
|
||||
NSXMLElement *orgname = [org elementForName:@"ORGNAME"];
|
||||
|
||||
if (orgname != nil) {
|
||||
result = [orgname stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setOrgName:(NSString *)orgname {
|
||||
NSXMLElement *org = [self elementForName:@"ORG"];
|
||||
NSXMLElement *elem = nil;
|
||||
|
||||
if (orgname != nil) {
|
||||
if (org == nil) {
|
||||
org = [NSXMLElement elementWithName:@"ORG"];
|
||||
[self addChild:org];
|
||||
} else {
|
||||
elem = [org elementForName:@"ORGNAME"];
|
||||
}
|
||||
|
||||
if (elem == nil) {
|
||||
elem = [NSXMLElement elementWithName:@"ORGNAME"];
|
||||
[org addChild:elem];
|
||||
}
|
||||
|
||||
[elem setStringValue:orgname];
|
||||
} else if (org != nil) {
|
||||
// This implicitly removes all orgunits too, as per the spec
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:org]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *)orgUnits {
|
||||
NSArray *result = nil;
|
||||
NSXMLElement *org = [self elementForName:@"ORG"];
|
||||
|
||||
if (org != nil) {
|
||||
NSArray *elems = [org elementsForName:@"ORGUNIT"];
|
||||
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:[elems count]];
|
||||
|
||||
for (NSXMLElement *elem in elems) {
|
||||
[arr addObject:[elem stringValue]];
|
||||
}
|
||||
|
||||
result = [NSArray arrayWithArray:arr];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setOrgUnits:(NSArray *)orgunits {
|
||||
NSXMLElement *org = [self elementForName:@"ORG"];
|
||||
|
||||
// If there is no org, then there is nothing to do (need ORGNAME first)
|
||||
if (org != nil) {
|
||||
NSArray *elems = [org elementsForName:@"ORGUNIT"];
|
||||
for (NSXMLElement *elem in elems) {
|
||||
[org removeChildAtIndex:[[org children] indexOfObject:elem]];
|
||||
}
|
||||
|
||||
for (NSString *unit in orgunits) {
|
||||
NSXMLElement *elem = [NSXMLElement elementWithName:@"ORGUNIT"];
|
||||
[elem setStringValue:unit];
|
||||
|
||||
[org addChild:elem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Explanatory Types
|
||||
|
||||
|
||||
- (NSArray *)categories {
|
||||
NSArray *result = nil;
|
||||
NSXMLElement *categories = [self elementForName:@"CATEGORIES"];
|
||||
|
||||
if (categories != nil) {
|
||||
NSArray *elems = [categories elementsForName:@"KEYWORD"];
|
||||
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:[elems count]];
|
||||
|
||||
for (NSXMLElement *elem in elems) {
|
||||
[arr addObject:[elem stringValue]];
|
||||
}
|
||||
|
||||
result = [NSArray arrayWithArray:arr];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setCategories:(NSArray *)categories {
|
||||
NSXMLElement *cat = [self elementForName:@"CATEGORIES"];
|
||||
|
||||
if (categories != nil) {
|
||||
if (cat == nil) {
|
||||
cat = [NSXMLElement elementWithName:@"CATEGORIES"];
|
||||
[self addChild:cat];
|
||||
}
|
||||
|
||||
NSArray *elems = [cat elementsForName:@"KEYWORD"];
|
||||
for (NSXMLElement *elem in elems) {
|
||||
[cat removeChildAtIndex:[[cat children] indexOfObject:elem]];
|
||||
}
|
||||
|
||||
for (NSString *kw in categories) {
|
||||
NSXMLElement *elem = [NSXMLElement elementWithName:@"KEYWORD"];
|
||||
[elem setStringValue:kw];
|
||||
|
||||
[cat addChild:elem];
|
||||
}
|
||||
} else if (cat != nil) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:cat]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)note {
|
||||
return [[self elementForName:@"NOTE"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setNote:(NSString *)note {
|
||||
XMPP_VCARD_SET_STRING_CHILD(note, @"NOTE");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)prodid {
|
||||
return [[self elementForName:@"PRODID"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setProdid:(NSString *)prodid {
|
||||
XMPP_VCARD_SET_STRING_CHILD(prodid, @"PRODID");
|
||||
}
|
||||
|
||||
|
||||
- (NSDate *)revision {
|
||||
NSDate *rev = nil;
|
||||
NSXMLElement *elem = [self elementForName:@"REV"];
|
||||
|
||||
if (elem != nil) {
|
||||
rev = [NSDate dateWithXmppDateTimeString:[elem stringValue]];
|
||||
}
|
||||
|
||||
return rev;
|
||||
}
|
||||
|
||||
|
||||
- (void)setRevision:(NSDate *)rev {
|
||||
NSXMLElement *elem = [self elementForName:@"REV"];
|
||||
|
||||
if (elem == nil) {
|
||||
elem = [NSXMLElement elementWithName:@"REV"];
|
||||
[self addChild:elem];
|
||||
}
|
||||
|
||||
[elem setStringValue:[rev xmppDateTimeString]];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)sortString {
|
||||
return [[self elementForName:@"SORT-STRING"] stringValue];
|
||||
}
|
||||
- (void)setSortString:(NSString *)sortString {
|
||||
XMPP_VCARD_SET_STRING_CHILD(sortString, @"SORT-STRING");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)phoneticSound {
|
||||
NSString *phon = nil;
|
||||
NSXMLElement *sound = [self elementForName:@"SOUND"];
|
||||
|
||||
if (sound != nil) {
|
||||
NSXMLElement *elem = [sound elementForName:@"PHONETIC"];
|
||||
|
||||
if (elem != nil) {
|
||||
phon = [elem stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return phon;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPhoneticSound:(NSString *)phonetic {
|
||||
NSXMLElement *sound = [self elementForName:@"SOUND"];
|
||||
NSXMLElement *elem = nil;
|
||||
|
||||
if (sound == nil && phonetic != nil) {
|
||||
sound = [NSXMLElement elementWithName:@"SOUND"];
|
||||
[self addChild:sound];
|
||||
}
|
||||
|
||||
if (sound != nil) {
|
||||
elem = [sound elementForName:@"PHONETIC"];
|
||||
|
||||
if (elem != nil && phonetic != nil) {
|
||||
elem = [NSXMLElement elementWithName:@"PHONETIC"];
|
||||
[sound addChild:elem];
|
||||
}
|
||||
}
|
||||
|
||||
if (phonetic != nil) {
|
||||
[elem setStringValue:phonetic];
|
||||
} else if (sound != nil) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:phonetic]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSData *)sound {
|
||||
NSData *decodedData = nil;
|
||||
NSXMLElement *sound = [self elementForName:@"SOUND"];
|
||||
|
||||
if (sound != nil) {
|
||||
NSXMLElement *binval = [sound elementForName:@"BINVAL"];
|
||||
|
||||
if (binval) {
|
||||
NSData *base64Data = [[binval stringValue] dataUsingEncoding:NSASCIIStringEncoding];
|
||||
decodedData = [base64Data xmpp_base64Decoded];
|
||||
}
|
||||
}
|
||||
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
|
||||
- (void)setSound:(NSData *)data {
|
||||
NSXMLElement *sound = [self elementForName:@"SOUND"];
|
||||
|
||||
if (sound == nil) {
|
||||
sound = [NSXMLElement elementWithName:@"SOUND"];
|
||||
[self addChild:sound];
|
||||
}
|
||||
|
||||
NSXMLElement *binval = [sound elementForName:@"BINVAL"];
|
||||
|
||||
if (binval == nil) {
|
||||
binval = [NSXMLElement elementWithName:@"BINVAL"];
|
||||
[sound addChild:binval];
|
||||
}
|
||||
|
||||
[binval setStringValue:[data xmpp_base64Encoded]];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)uid {
|
||||
return [[self elementForName:@"UID"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setUid:(NSString *)uid {
|
||||
XMPP_VCARD_SET_STRING_CHILD(uid, @"UID");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)url {
|
||||
return [[self elementForName:@"URL"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setUrl:(NSString *)url {
|
||||
XMPP_VCARD_SET_STRING_CHILD(url, @"URL");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)version {
|
||||
return [self attributeStringValueForName:@"version"];
|
||||
}
|
||||
|
||||
|
||||
- (void)setVersion:(NSString *)version {
|
||||
[self addAttributeWithName:@"version" stringValue:version];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)desc {
|
||||
return [[self elementForName:@"DESC"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setDesc:(NSString *)desc {
|
||||
XMPP_VCARD_SET_STRING_CHILD(desc, @"DESC");
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Security Types
|
||||
|
||||
|
||||
- (XMPPvCardTempClass)privacyClass {
|
||||
XMPPvCardTempClass priv = XMPPvCardTempClassNone;
|
||||
NSXMLElement *elem = [self elementForName:@"CLASS"];
|
||||
|
||||
if (elem != nil) {
|
||||
if ([elem elementForName:@"PUBLIC"] != nil) {
|
||||
priv = XMPPvCardTempClassPublic;
|
||||
} else if ([elem elementForName:@"PRIVATE"] != nil) {
|
||||
priv = XMPPvCardTempClassPrivate;
|
||||
} else if ([elem elementForName:@"CONFIDENTIAL"] != nil) {
|
||||
priv = XMPPvCardTempClassConfidential;
|
||||
}
|
||||
}
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPrivacyClass:(XMPPvCardTempClass)privacyClass {
|
||||
NSXMLElement *elem = [self elementForName:@"CLASS"];
|
||||
|
||||
if (elem == nil && privacyClass != XMPPvCardTempClassNone) {
|
||||
elem = [NSXMLElement elementWithName:@"CLASS"];
|
||||
}
|
||||
|
||||
if (elem != nil) {
|
||||
for (NSString *cls in @[@"PUBLIC", @"PRIVATE", @"CONFIDENTIAL"]) {
|
||||
NSXMLElement *priv = [elem elementForName:cls];
|
||||
if (priv != nil) {
|
||||
[elem removeChildAtIndex:[[elem children] indexOfObject:priv]];
|
||||
}
|
||||
}
|
||||
|
||||
switch (privacyClass) {
|
||||
case XMPPvCardTempClassPublic:
|
||||
[elem addChild:[NSXMLElement elementWithName:@"PUBLIC"]];
|
||||
break;
|
||||
case XMPPvCardTempClassPrivate:
|
||||
[elem addChild:[NSXMLElement elementWithName:@"PRIVATE"]];
|
||||
break;
|
||||
case XMPPvCardTempClassConfidential:
|
||||
[elem addChild:[NSXMLElement elementWithName:@"CONFIDENTIAL"]];
|
||||
break;
|
||||
default:
|
||||
case XMPPvCardTempClassNone:
|
||||
// Remove the whole element
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:elem]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSData *)key { return nil; }
|
||||
- (void)setKey:(NSData *)key { }
|
||||
|
||||
|
||||
- (NSString *)keyType {
|
||||
NSString *typ = nil;
|
||||
NSXMLElement *key = [self elementForName:@"KEY"];
|
||||
|
||||
if (key != nil) {
|
||||
NSXMLElement *elem = [key elementForName:@"TYPE"];
|
||||
|
||||
if (elem != nil) {
|
||||
typ = [elem stringValue];
|
||||
}
|
||||
}
|
||||
|
||||
return typ;
|
||||
}
|
||||
|
||||
|
||||
- (void)setKeyType:(NSString *)type {
|
||||
NSXMLElement *key = [self elementForName:@"KEY"];
|
||||
NSXMLElement *elem = nil;
|
||||
|
||||
if (key == nil && type != nil) {
|
||||
key = [NSXMLElement elementWithName:@"KEY"];
|
||||
[self addChild:key];
|
||||
}
|
||||
|
||||
if (key != nil) {
|
||||
elem = [key elementForName:@"TYPE"];
|
||||
|
||||
if (elem != nil && type != nil) {
|
||||
elem = [NSXMLElement elementWithName:@"TYPE"];
|
||||
[key addChild:elem];
|
||||
}
|
||||
}
|
||||
|
||||
if (type != nil) {
|
||||
[elem setStringValue:type];
|
||||
} else if (key != nil) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:key]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// XMPPvCardTempAdr.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "XMPPvCardTempAdrTypes.h"
|
||||
|
||||
|
||||
@interface XMPPvCardTempAdr : XMPPvCardTempAdrTypes
|
||||
|
||||
+ (XMPPvCardTempAdr *)vCardAdrFromElement:(NSXMLElement *)elem;
|
||||
|
||||
@property (nonatomic, weak) NSString *pobox;
|
||||
@property (nonatomic, weak) NSString *extendedAddress;
|
||||
@property (nonatomic, weak) NSString *street;
|
||||
@property (nonatomic, weak) NSString *locality;
|
||||
@property (nonatomic, weak) NSString *region;
|
||||
@property (nonatomic, weak) NSString *postalCode;
|
||||
@property (nonatomic, weak) NSString *country;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// XMPPvCardTempAdr.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "XMPPvCardTempAdr.h"
|
||||
#import "XMPPLogging.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR;
|
||||
#endif
|
||||
|
||||
|
||||
@implementation XMPPvCardTempAdr
|
||||
|
||||
#if DEBUG
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
// We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
|
||||
// The size of the two classes is expected to be the same.
|
||||
//
|
||||
// If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
|
||||
// This check is here to aid future developers who may make this mistake.
|
||||
//
|
||||
// For Fearless And Experienced Objective-C Developers:
|
||||
// It may be possible to support adding instance variables to this class if you seriously need it.
|
||||
// To do so, try realloc'ing self after altering the class, and then initialize your variables.
|
||||
|
||||
size_t superSize = class_getInstanceSize([NSXMLElement class]);
|
||||
size_t ourSize = class_getInstanceSize([XMPPvCardTempAdr class]);
|
||||
|
||||
if (superSize != ourSize)
|
||||
{
|
||||
XMPPLogError(@"Adding instance variables to XMPPvCardTempAdr is not currently supported!");
|
||||
|
||||
[DDLog flushLog];
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+ (XMPPvCardTempAdr *)vCardAdrFromElement:(NSXMLElement *)elem {
|
||||
object_setClass(elem, [XMPPvCardTempAdr class]);
|
||||
|
||||
return (XMPPvCardTempAdr *)elem;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getter/setter methods
|
||||
|
||||
|
||||
- (NSString *)pobox {
|
||||
return [[self elementForName:@"POBOX"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setPobox:(NSString *)pobox {
|
||||
XMPP_VCARD_SET_STRING_CHILD(pobox, @"POBOX");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)extendedAddress {
|
||||
return [[self elementForName:@"EXTADD"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setExtendedAddress:(NSString *)extadd {
|
||||
XMPP_VCARD_SET_STRING_CHILD(extadd, @"EXTADD");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)street {
|
||||
return [[self elementForName:@"STREET"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setStreet:(NSString *)street {
|
||||
XMPP_VCARD_SET_STRING_CHILD(street, @"STREET");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)locality {
|
||||
return [[self elementForName:@"LOCALITY"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setLocality:(NSString *)locality {
|
||||
XMPP_VCARD_SET_STRING_CHILD(locality, @"LOCALITY");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)region {
|
||||
return [[self elementForName:@"REGION"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setRegion:(NSString *)region {
|
||||
XMPP_VCARD_SET_STRING_CHILD(region, @"REGION");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)postalCode {
|
||||
return [[self elementForName:@"PCODE"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setPostalCode:(NSString *)pcode {
|
||||
XMPP_VCARD_SET_STRING_CHILD(pcode, @"PCODE");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)country {
|
||||
return [[self elementForName:@"CTRY"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setCountry:(NSString *)ctry {
|
||||
XMPP_VCARD_SET_STRING_CHILD(ctry, @"CTRY");
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// XMPPvCardTempAdrTypes.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "XMPPvCardTempBase.h"
|
||||
|
||||
|
||||
@interface XMPPvCardTempAdrTypes : XMPPvCardTempBase
|
||||
|
||||
|
||||
@property (nonatomic, assign, setter=setHome:) BOOL isHome;
|
||||
@property (nonatomic, assign, setter=setWork:) BOOL isWork;
|
||||
@property (nonatomic, assign, setter=setParcel:) BOOL isParcel;
|
||||
@property (nonatomic, assign, setter=setPostal:) BOOL isPostal;
|
||||
@property (nonatomic, assign, setter=setDomestic:) BOOL isDomestic;
|
||||
@property (nonatomic, assign, setter=setInternational:) BOOL isInternational;
|
||||
@property (nonatomic, assign, setter=setPreferred:) BOOL isPreferred;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// XMPPvCardTempAdrTypes.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "XMPPvCardTempAdrTypes.h"
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
|
||||
@implementation XMPPvCardTempAdrTypes
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getter/setter methods
|
||||
|
||||
|
||||
- (BOOL)isHome {
|
||||
return [self elementForName:@"HOME"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setHome:(BOOL)home {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(home && ![self isHome], @"HOME");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isWork {
|
||||
return [self elementForName:@"WORK"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setWork:(BOOL)work {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(work && ![self isWork], @"WORK");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isParcel {
|
||||
return [self elementForName:@"PARCEL"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setParcel:(BOOL)parcel {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(parcel && ![self isParcel], @"PARCEL");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isPostal {
|
||||
return [self elementForName:@"POSTAL"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPostal:(BOOL)postal {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(postal && ![self isPostal], @"POSTAL");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isDomestic {
|
||||
return [self elementForName:@"DOM"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setDomestic:(BOOL)dom {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(dom && ![self isDomestic], @"DOM");
|
||||
// INTL and DOM are mutually exclusive
|
||||
if (dom) {
|
||||
[self setInternational:NO];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isInternational {
|
||||
return [self elementForName:@"INTL"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setInternational:(BOOL)intl {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(intl && ![self isInternational], @"INTL");
|
||||
// INTL and DOM are mutually exclusive
|
||||
if (intl) {
|
||||
[self setDomestic:NO];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isPreferred {
|
||||
return [self elementForName:@"PREF"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPreferred:(BOOL)pref {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(pref && ![self isPreferred], @"PREF");
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// XMPPvCardTempBase.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "NSXMLElement+XMPP.h"
|
||||
|
||||
|
||||
#define XMPP_VCARD_SET_EMPTY_CHILD(Set, Name) \
|
||||
if (Set) { \
|
||||
[self addChild:[NSXMLElement elementWithName:(Name)]]; \
|
||||
} \
|
||||
else if (!(Set)) { \
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:[self elementForName:(Name)]]]; \
|
||||
}
|
||||
|
||||
|
||||
#define XMPP_VCARD_SET_STRING_CHILD(Value, Name) \
|
||||
NSXMLElement *elem = [self elementForName:(Name)]; \
|
||||
if ((Value) != nil) \
|
||||
{ \
|
||||
if (elem == nil) { \
|
||||
elem = [NSXMLElement elementWithName:(Name)]; \
|
||||
[self addChild:elem]; \
|
||||
} \
|
||||
[elem setStringValue:(Value)]; \
|
||||
} \
|
||||
else if (elem != nil) { \
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:elem]]; \
|
||||
}
|
||||
|
||||
|
||||
#define XMPP_VCARD_SET_N_CHILD(Value, Name) \
|
||||
NSXMLElement *name = [self elementForName:@"N"]; \
|
||||
if ((Value) != nil && name == nil) \
|
||||
{ \
|
||||
name = [NSXMLElement elementWithName:@"N"]; \
|
||||
[self addChild:name]; \
|
||||
} \
|
||||
\
|
||||
NSXMLElement *part = [name elementForName:(Name)]; \
|
||||
if ((Value) != nil && part == nil) \
|
||||
{ \
|
||||
part = [NSXMLElement elementWithName:(Name)]; \
|
||||
[name addChild:part]; \
|
||||
} \
|
||||
\
|
||||
if (Value) \
|
||||
{ \
|
||||
[part setStringValue:(Value)]; \
|
||||
} \
|
||||
else if (part != nil) \
|
||||
{ \
|
||||
/* N is mandatory, so we leave it in. */ \
|
||||
[name removeChildAtIndex:[[self children] indexOfObject:part]]; \
|
||||
}
|
||||
|
||||
|
||||
@interface XMPPvCardTempBase : NSXMLElement <NSSecureCoding, NSCopying> {
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// XMPPvCardTempBase.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
#import "XMPPvCardTempBase.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
@implementation XMPPvCardTempBase
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSCoding protocol
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if ! TARGET_OS_IPHONE
|
||||
- (id)replacementObjectForPortCoder:(NSPortCoder *)encoder
|
||||
{
|
||||
if([encoder isBycopy])
|
||||
return self;
|
||||
else
|
||||
return [super replacementObjectForPortCoder:encoder];
|
||||
// return [NSDistantObject proxyWithLocal:self connection:[encoder connection]];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
NSString *xmlString;
|
||||
if([coder allowsKeyedCoding])
|
||||
{
|
||||
if([coder respondsToSelector:@selector(requiresSecureCoding)] &&
|
||||
[coder requiresSecureCoding])
|
||||
{
|
||||
xmlString = [coder decodeObjectOfClass:[NSString class] forKey:@"xmlString"];
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlString = [coder decodeObjectForKey:@"xmlString"];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlString = [coder decodeObject];
|
||||
}
|
||||
|
||||
// The method [super initWithXMLString:error:] may return a different self.
|
||||
// In other words, it may [self release], and alloc/init/return a new self.
|
||||
//
|
||||
// So to maintain the proper class (XMPPvCardTempEmail, XMPPvCardTempTel, etc)
|
||||
// we need to get a reference to the class before invoking super.
|
||||
|
||||
Class selfClass = [self class];
|
||||
|
||||
if ((self = [super initWithXMLString:xmlString error:nil]))
|
||||
{
|
||||
object_setClass(self, selfClass);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
NSString *xmlString = [self XMLString];
|
||||
|
||||
if([coder allowsKeyedCoding])
|
||||
{
|
||||
[coder encodeObject:xmlString forKey:@"xmlString"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[coder encodeObject:xmlString];
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL) supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
NSXMLElement *elementCopy = [super copyWithZone:zone];
|
||||
object_setClass(elementCopy, [self class]);
|
||||
|
||||
return elementCopy;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// XMPPvCardTempEmail.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "XMPPvCardTempBase.h"
|
||||
|
||||
|
||||
@interface XMPPvCardTempEmail : XMPPvCardTempBase
|
||||
|
||||
+ (XMPPvCardTempEmail *)vCardEmailFromElement:(NSXMLElement *)elem;
|
||||
|
||||
@property (nonatomic, assign, setter=setHome:) BOOL isHome;
|
||||
@property (nonatomic, assign, setter=setWork:) BOOL isWork;
|
||||
@property (nonatomic, assign, setter=setInternet:) BOOL isInternet;
|
||||
@property (nonatomic, assign, setter=setX400:) BOOL isX400;
|
||||
@property (nonatomic, assign, setter=setPreferred:) BOOL isPreferred;
|
||||
|
||||
@property (nonatomic, weak) NSString *userid;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// XMPPvCardTempEmail.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "XMPPvCardTempEmail.h"
|
||||
#import "XMPPLogging.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR;
|
||||
#endif
|
||||
|
||||
|
||||
@implementation XMPPvCardTempEmail
|
||||
|
||||
#if DEBUG
|
||||
|
||||
+ (void)initialize {
|
||||
// We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
|
||||
// The size of the two classes is expected to be the same.
|
||||
//
|
||||
// If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
|
||||
// This check is here to aid future developers who may make this mistake.
|
||||
//
|
||||
// For Fearless And Experienced Objective-C Developers:
|
||||
// It may be possible to support adding instance variables to this class if you seriously need it.
|
||||
// To do so, try realloc'ing self after altering the class, and then initialize your variables.
|
||||
|
||||
size_t superSize = class_getInstanceSize([NSXMLElement class]);
|
||||
size_t ourSize = class_getInstanceSize([XMPPvCardTempEmail class]);
|
||||
|
||||
if (superSize != ourSize)
|
||||
{
|
||||
XMPPLogError(@"Adding instance variables to XMPPvCardTempEmail is not currently supported!");
|
||||
|
||||
[DDLog flushLog];
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+ (XMPPvCardTempEmail *)vCardEmailFromElement:(NSXMLElement *)elem {
|
||||
object_setClass(elem, [XMPPvCardTempEmail class]);
|
||||
|
||||
return (XMPPvCardTempEmail *)elem;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getter/setter methods
|
||||
|
||||
|
||||
- (BOOL)isHome {
|
||||
return [self elementForName:@"HOME"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setHome:(BOOL)home {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(home && ![self isHome], @"HOME");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isWork {
|
||||
return [self elementForName:@"WORK"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setWork:(BOOL)work {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(work && ![self isWork], @"WORK");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isInternet {
|
||||
return [self elementForName:@"INTERNET"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setInternet:(BOOL)internet {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(internet && ![self isInternet], @"INTERNET");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isX400 {
|
||||
return [self elementForName:@"X400"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setX400:(BOOL)x400 {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(x400 && ![self isX400], @"X400");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isPreferred {
|
||||
return [self elementForName:@"PREF"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPreferred:(BOOL)pref {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(pref && ![self isPreferred], @"PREF");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)userid {
|
||||
return [[self elementForName:@"USERID"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setUserid:(NSString *)userid {
|
||||
XMPP_VCARD_SET_STRING_CHILD(userid, @"USERID");
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// XMPPvCardTempLabel.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "XMPPvCardTempAdrTypes.h"
|
||||
|
||||
|
||||
@interface XMPPvCardTempLabel : XMPPvCardTempAdrTypes
|
||||
|
||||
|
||||
@property (nonatomic, weak) NSArray *lines;
|
||||
|
||||
|
||||
+ (XMPPvCardTempLabel *)vCardLabelFromElement:(NSXMLElement *)elem;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// XMPPvCardTempLabel.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "XMPPvCardTempLabel.h"
|
||||
#import "XMPPLogging.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR;
|
||||
#endif
|
||||
|
||||
|
||||
@implementation XMPPvCardTempLabel
|
||||
|
||||
#if DEBUG
|
||||
|
||||
+ (void)initialize {
|
||||
// We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
|
||||
// The size of the two classes is expected to be the same.
|
||||
//
|
||||
// If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
|
||||
// This check is here to aid future developers who may make this mistake.
|
||||
//
|
||||
// For Fearless And Experienced Objective-C Developers:
|
||||
// It may be possible to support adding instance variables to this class if you seriously need it.
|
||||
// To do so, try realloc'ing self after altering the class, and then initialize your variables.
|
||||
|
||||
size_t superSize = class_getInstanceSize([NSXMLElement class]);
|
||||
size_t ourSize = class_getInstanceSize([XMPPvCardTempLabel class]);
|
||||
|
||||
if (superSize != ourSize)
|
||||
{
|
||||
XMPPLogError(@"Adding instance variables to XMPPvCardTempLabel is not currently supported!");
|
||||
|
||||
[DDLog flushLog];
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+ (XMPPvCardTempLabel *)vCardLabelFromElement:(NSXMLElement *)elem {
|
||||
object_setClass(elem, [XMPPvCardTempLabel class]);
|
||||
|
||||
return (XMPPvCardTempLabel *)elem;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getter/setter methods
|
||||
|
||||
|
||||
- (NSArray *)lines {
|
||||
NSArray *elems = [self elementsForName:@"LINE"];
|
||||
NSMutableArray *lines = [[NSMutableArray alloc] initWithCapacity:[elems count]];
|
||||
|
||||
for (NSXMLElement *elem in elems) {
|
||||
[lines addObject:[elem stringValue]];
|
||||
}
|
||||
|
||||
NSArray *result = [NSArray arrayWithArray:lines];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void)setLines:(NSArray *)lines {
|
||||
NSArray *elems = [self elementsForName:@"LINE"];
|
||||
|
||||
for (NSXMLElement *elem in elems) {
|
||||
[self removeChildAtIndex:[[self children] indexOfObject:elem]];
|
||||
}
|
||||
|
||||
for (NSString *line in lines) {
|
||||
NSXMLElement *elem = [NSXMLElement elementWithName:@"LINE"];
|
||||
[elem setStringValue:line];
|
||||
[self addChild:elem];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
Executable
+117
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// XMPPvCardTempModule.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/17/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "XMPP.h"
|
||||
|
||||
@class XMPPvCardTemp;
|
||||
@class XMPPIDTracker;
|
||||
|
||||
#define _XMPP_VCARD_TEMP_MODULE_H
|
||||
|
||||
@protocol XMPPvCardTempModuleStorage;
|
||||
|
||||
|
||||
@interface XMPPvCardTempModule : XMPPModule
|
||||
{
|
||||
id <XMPPvCardTempModuleStorage> __strong _xmppvCardTempModuleStorage;
|
||||
XMPPIDTracker *_myvCardTracker;
|
||||
}
|
||||
|
||||
|
||||
@property(nonatomic, strong, readonly) id <XMPPvCardTempModuleStorage> xmppvCardTempModuleStorage;
|
||||
@property(nonatomic, strong, readonly) XMPPvCardTemp *myvCardTemp;
|
||||
|
||||
- (id)initWithvCardStorage:(id <XMPPvCardTempModuleStorage>)storage;
|
||||
- (id)initWithvCardStorage:(id <XMPPvCardTempModuleStorage>)storage dispatchQueue:(dispatch_queue_t)queue;
|
||||
|
||||
/**
|
||||
* Fetches the vCardTemp for the given JID if it is not in the storage
|
||||
**/
|
||||
- (void)fetchvCardTempForJID:(XMPPJID *)jid;
|
||||
|
||||
/**
|
||||
* Fetches the vCardTemp for the given JID, optionally ignoring the storage
|
||||
**/
|
||||
- (void)fetchvCardTempForJID:(XMPPJID *)jid ignoreStorage:(BOOL)ignoreStorage;
|
||||
|
||||
/**
|
||||
* Returns the vCardTemp for the given JID, this is the equivalent of calling the vCardTempForJID:xmppStream: on the moduleStorage
|
||||
* If there is no vCardTemp in the storage for the given jid and shouldFetch is YES, it will automatically fetch it from the network
|
||||
**/
|
||||
- (XMPPvCardTemp *)vCardTempForJID:(XMPPJID *)jid shouldFetch:(BOOL)shouldFetch;
|
||||
|
||||
/**
|
||||
* Updates myvCard in storage and sends it to the server
|
||||
**/
|
||||
- (void)updateMyvCardTemp:(XMPPvCardTemp *)vCardTemp;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@protocol XMPPvCardTempModuleDelegate
|
||||
@optional
|
||||
|
||||
- (void)xmppvCardTempModule:(XMPPvCardTempModule *)vCardTempModule
|
||||
didReceivevCardTemp:(XMPPvCardTemp *)vCardTemp
|
||||
forJID:(XMPPJID *)jid;
|
||||
|
||||
- (void)xmppvCardTempModuleDidUpdateMyvCard:(XMPPvCardTempModule *)vCardTempModule;
|
||||
|
||||
- (void)xmppvCardTempModule:(XMPPvCardTempModule *)vCardTempModule failedToUpdateMyvCard:(NSXMLElement *)error;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@protocol XMPPvCardTempModuleStorage <NSObject>
|
||||
|
||||
/**
|
||||
* Configures the storage class, passing its parent and parent's dispatch queue.
|
||||
*
|
||||
* This method is called by the init methods of the XMPPvCardTempModule class.
|
||||
* This method is designed to inform the storage class of its parent
|
||||
* and of the dispatch queue the parent will be operating on.
|
||||
*
|
||||
* The storage class may choose to operate on the same queue as its parent,
|
||||
* or it may operate on its own internal dispatch queue.
|
||||
*
|
||||
* This method should return YES if it was configured properly.
|
||||
* The parent class is configured to ignore the passed
|
||||
* storage class in its init method if this method returns NO.
|
||||
**/
|
||||
- (BOOL)configureWithParent:(XMPPvCardTempModule *)aParent queue:(dispatch_queue_t)queue;
|
||||
|
||||
/**
|
||||
* Returns a vCardTemp object or nil
|
||||
**/
|
||||
- (XMPPvCardTemp *)vCardTempForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
|
||||
|
||||
/**
|
||||
* Used to set the vCardTemp object when we get it from the XMPP server.
|
||||
**/
|
||||
- (void)setvCardTemp:(XMPPvCardTemp *)vCardTemp forJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
|
||||
|
||||
/**
|
||||
* Returns My vCardTemp object or nil
|
||||
**/
|
||||
- (XMPPvCardTemp *)myvCardTempForXMPPStream:(XMPPStream *)stream;
|
||||
|
||||
/**
|
||||
* Asks the backend if we should fetch the vCardTemp from the network.
|
||||
* This is used so that we don't request the vCardTemp multiple times.
|
||||
**/
|
||||
- (BOOL)shouldFetchvCardTempForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
|
||||
|
||||
@end
|
||||
Executable
+286
@@ -0,0 +1,286 @@
|
||||
//
|
||||
// XMPPvCardTempModule.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/17/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
//
|
||||
|
||||
#import "XMPP.h"
|
||||
#import "XMPPLogging.h"
|
||||
#import "XMPPvCardTempModule.h"
|
||||
#import "XMPPvCardTemp.h"
|
||||
#import "XMPPIDTracker.h"
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
// Log levels: off, error, warn, info, verbose
|
||||
// Log flags: trace
|
||||
#if DEBUG
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; // | XMPP_LOG_FLAG_TRACE;
|
||||
#else
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN;
|
||||
#endif
|
||||
|
||||
@interface XMPPvCardTempModule()
|
||||
|
||||
- (void)_updatevCardTemp:(XMPPvCardTemp *)vCardTemp forJID:(XMPPJID *)jid;
|
||||
- (void)_fetchvCardTempForJID:(XMPPJID *)jid;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation XMPPvCardTempModule
|
||||
|
||||
@synthesize xmppvCardTempModuleStorage = _xmppvCardTempModuleStorage;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
// This will cause a crash - it's designed to.
|
||||
// Only the init methods listed in XMPPvCardTempModule.h are supported.
|
||||
|
||||
return [self initWithvCardStorage:nil dispatchQueue:NULL];
|
||||
}
|
||||
|
||||
- (id)initWithDispatchQueue:(dispatch_queue_t)queue
|
||||
{
|
||||
// This will cause a crash - it's designed to.
|
||||
// Only the init methods listed in XMPPvCardTempModule.h are supported.
|
||||
|
||||
return [self initWithvCardStorage:nil dispatchQueue:NULL];
|
||||
}
|
||||
|
||||
- (id)initWithvCardStorage:(id <XMPPvCardTempModuleStorage>)storage
|
||||
{
|
||||
return [self initWithvCardStorage:storage dispatchQueue:NULL];
|
||||
}
|
||||
|
||||
- (id)initWithvCardStorage:(id <XMPPvCardTempModuleStorage>)storage dispatchQueue:(dispatch_queue_t)queue
|
||||
{
|
||||
NSParameterAssert(storage != nil);
|
||||
|
||||
if ((self = [super initWithDispatchQueue:queue]))
|
||||
{
|
||||
if ([storage configureWithParent:self queue:moduleQueue])
|
||||
{
|
||||
_xmppvCardTempModuleStorage = storage;
|
||||
}
|
||||
else
|
||||
{
|
||||
XMPPLogError(@"%@: %@ - Unable to configure storage!", THIS_FILE, THIS_METHOD);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)activate:(XMPPStream *)aXmppStream
|
||||
{
|
||||
if ([super activate:aXmppStream])
|
||||
{
|
||||
// Custom code goes here (if needed)
|
||||
|
||||
_myvCardTracker = [[XMPPIDTracker alloc] initWithStream:xmppStream dispatchQueue:moduleQueue];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)deactivate
|
||||
{
|
||||
// Custom code goes here (if needed)
|
||||
|
||||
dispatch_block_t block = ^{ @autoreleasepool {
|
||||
|
||||
[_myvCardTracker removeAllIDs];
|
||||
_myvCardTracker = nil;
|
||||
|
||||
}};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_sync(moduleQueue, block);
|
||||
|
||||
[super deactivate];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_xmppvCardTempModuleStorage = nil;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Fetch vCardTemp methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)fetchvCardTempForJID:(XMPPJID *)jid
|
||||
{
|
||||
return [self fetchvCardTempForJID:jid ignoreStorage:NO];
|
||||
}
|
||||
|
||||
- (void)fetchvCardTempForJID:(XMPPJID *)jid ignoreStorage:(BOOL)ignoreStorage
|
||||
{
|
||||
dispatch_block_t block = ^{ @autoreleasepool {
|
||||
|
||||
XMPPvCardTemp *vCardTemp = nil;
|
||||
|
||||
if (!ignoreStorage)
|
||||
{
|
||||
// Try loading from storage
|
||||
vCardTemp = [_xmppvCardTempModuleStorage vCardTempForJID:jid xmppStream:xmppStream];
|
||||
}
|
||||
|
||||
if (vCardTemp == nil && [_xmppvCardTempModuleStorage shouldFetchvCardTempForJID:jid xmppStream:xmppStream])
|
||||
{
|
||||
[self _fetchvCardTempForJID:jid];
|
||||
}
|
||||
|
||||
}};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_async(moduleQueue, block);
|
||||
}
|
||||
|
||||
- (XMPPvCardTemp *)vCardTempForJID:(XMPPJID *)jid shouldFetch:(BOOL)shouldFetch{
|
||||
|
||||
__block XMPPvCardTemp *result;
|
||||
|
||||
dispatch_block_t block = ^{ @autoreleasepool {
|
||||
|
||||
XMPPvCardTemp *vCardTemp = [_xmppvCardTempModuleStorage vCardTempForJID:jid xmppStream:xmppStream];
|
||||
|
||||
if (vCardTemp == nil && shouldFetch && [_xmppvCardTempModuleStorage shouldFetchvCardTempForJID:jid xmppStream:xmppStream])
|
||||
{
|
||||
[self _fetchvCardTempForJID:jid];
|
||||
}
|
||||
|
||||
result = vCardTemp;
|
||||
}};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_sync(moduleQueue, block);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (XMPPvCardTemp *)myvCardTemp
|
||||
{
|
||||
return [self vCardTempForJID:[xmppStream myJID] shouldFetch:YES];
|
||||
}
|
||||
|
||||
- (void)updateMyvCardTemp:(XMPPvCardTemp *)vCardTemp
|
||||
{
|
||||
|
||||
dispatch_block_t block = ^{ @autoreleasepool {
|
||||
|
||||
XMPPvCardTemp *newvCardTemp = [vCardTemp copy];
|
||||
|
||||
XMPPIQ *iq = [XMPPIQ iqWithType:@"set" to:nil elementID:[xmppStream generateUUID] child:newvCardTemp];
|
||||
[xmppStream sendElement:iq];
|
||||
|
||||
[_myvCardTracker addElement:iq
|
||||
target:self
|
||||
selector:@selector(handleMyvcard:withInfo:)
|
||||
timeout:600];
|
||||
|
||||
[self _updatevCardTemp:newvCardTemp forJID:[xmppStream myJID]];
|
||||
|
||||
}};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_async(moduleQueue, block);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Private
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)_updatevCardTemp:(XMPPvCardTemp *)vCardTemp forJID:(XMPPJID *)jid
|
||||
{
|
||||
if(!jid) return;
|
||||
|
||||
// this method could be called from anywhere
|
||||
dispatch_block_t block = ^{ @autoreleasepool {
|
||||
|
||||
XMPPLogVerbose(@"%@: %s %@", THIS_FILE, __PRETTY_FUNCTION__, [jid bare]);
|
||||
|
||||
[_xmppvCardTempModuleStorage setvCardTemp:vCardTemp forJID:jid xmppStream:xmppStream];
|
||||
|
||||
[(id <XMPPvCardTempModuleDelegate>)multicastDelegate xmppvCardTempModule:self
|
||||
didReceivevCardTemp:vCardTemp
|
||||
forJID:jid];
|
||||
}};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_async(moduleQueue, block);
|
||||
}
|
||||
|
||||
- (void)_fetchvCardTempForJID:(XMPPJID *)jid{
|
||||
if(!jid) return;
|
||||
|
||||
[xmppStream sendElement:[XMPPvCardTemp iqvCardRequestForJID:jid]];
|
||||
}
|
||||
|
||||
- (void)handleMyvcard:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)trackerInfo{
|
||||
|
||||
if([iq isResultIQ])
|
||||
{
|
||||
[(id <XMPPvCardTempModuleDelegate>)multicastDelegate xmppvCardTempModuleDidUpdateMyvCard:self];
|
||||
}
|
||||
else if([iq isErrorIQ])
|
||||
{
|
||||
NSXMLElement *errorElement = [iq elementForName:@"error"];
|
||||
[(id <XMPPvCardTempModuleDelegate>)multicastDelegate xmppvCardTempModule:self failedToUpdateMyvCard:errorElement];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark XMPPStreamDelegate methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
|
||||
{
|
||||
// This method is invoked on the moduleQueue.
|
||||
|
||||
[_myvCardTracker invokeForElement:iq withObject:iq];
|
||||
|
||||
// Remember XML heirarchy memory management rules.
|
||||
// The passed parameter is a subnode of the IQ, and we need to pass it to an asynchronous operation.
|
||||
//
|
||||
// Therefore we use vCardTempCopyFromIQ instead of vCardTempSubElementFromIQ.
|
||||
|
||||
|
||||
XMPPvCardTemp *vCardTemp = [XMPPvCardTemp vCardTempCopyFromIQ:iq];
|
||||
if (vCardTemp != nil)
|
||||
{
|
||||
[self _updatevCardTemp:vCardTemp forJID:[iq from]];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
|
||||
{
|
||||
[_myvCardTracker removeAllIDs];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// XMPPvCardTempTel.h
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "XMPPvCardTempBase.h"
|
||||
|
||||
|
||||
@interface XMPPvCardTempTel : XMPPvCardTempBase
|
||||
|
||||
|
||||
+ (XMPPvCardTempTel *)vCardTelFromElement:(NSXMLElement *)elem;
|
||||
|
||||
@property (nonatomic, assign, setter=setHome:) BOOL isHome;
|
||||
@property (nonatomic, assign, setter=setWork:) BOOL isWork;
|
||||
@property (nonatomic, assign, setter=setVoice:) BOOL isVoice;
|
||||
@property (nonatomic, assign, setter=setFax:) BOOL isFax;
|
||||
@property (nonatomic, assign, setter=setPager:) BOOL isPager;
|
||||
@property (nonatomic, assign, setter=setMessaging:) BOOL hasMessaging;
|
||||
@property (nonatomic, assign, setter=setCell:) BOOL isCell;
|
||||
@property (nonatomic, assign, setter=setVideo:) BOOL isVideo;
|
||||
@property (nonatomic, assign, setter=setBBS:) BOOL isBBS;
|
||||
@property (nonatomic, assign, setter=setModem:) BOOL isModem;
|
||||
@property (nonatomic, assign, setter=setISDN:) BOOL isISDN;
|
||||
@property (nonatomic, assign, setter=setPCS:) BOOL isPCS;
|
||||
@property (nonatomic, assign, setter=setPreferred:) BOOL isPreferred;
|
||||
|
||||
@property (nonatomic, weak) NSString *number;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// XMPPvCardTempTel.m
|
||||
// XEP-0054 vCard-temp
|
||||
//
|
||||
// Created by Eric Chamberlain on 3/9/11.
|
||||
// Copyright 2011 RF.com. All rights reserved.
|
||||
// Copyright 2010 Martin Morrison. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "XMPPvCardTempTel.h"
|
||||
#import "XMPPLogging.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR;
|
||||
#endif
|
||||
|
||||
|
||||
@implementation XMPPvCardTempTel
|
||||
|
||||
#if DEBUG
|
||||
|
||||
+ (void)initialize {
|
||||
// We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
|
||||
// The size of the two classes is expected to be the same.
|
||||
//
|
||||
// If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
|
||||
// This check is here to aid future developers who may make this mistake.
|
||||
//
|
||||
// For Fearless And Experienced Objective-C Developers:
|
||||
// It may be possible to support adding instance variables to this class if you seriously need it.
|
||||
// To do so, try realloc'ing self after altering the class, and then initialize your variables.
|
||||
|
||||
size_t superSize = class_getInstanceSize([NSXMLElement class]);
|
||||
size_t ourSize = class_getInstanceSize([XMPPvCardTempTel class]);
|
||||
|
||||
if (superSize != ourSize)
|
||||
{
|
||||
XMPPLogError(@"Adding instance variables to XMPPvCardTempTel is not currently supported!");
|
||||
|
||||
[DDLog flushLog];
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+ (XMPPvCardTempTel *)vCardTelFromElement:(NSXMLElement *)elem {
|
||||
object_setClass(elem, [XMPPvCardTempTel class]);
|
||||
|
||||
return (XMPPvCardTempTel *)elem;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getter/setter methods
|
||||
|
||||
- (BOOL)isHome {
|
||||
return [self elementForName:@"HOME"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setHome:(BOOL)home {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(home && ![self isHome], @"HOME");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isWork {
|
||||
return [self elementForName:@"WORK"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setWork:(BOOL)work {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(work && ![self isWork], @"WORK");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isVoice {
|
||||
return [self elementForName:@"VOICE"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setVoice:(BOOL)voice {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(voice && ![self isVoice], @"VOICE");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isFax {
|
||||
return [self elementForName:@"FAX"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setFax:(BOOL)fax {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(fax && ![self isFax], @"FAX");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isPager {
|
||||
return [self elementForName:@"PAGER"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPager:(BOOL)pager {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(pager && ![self isPager], @"PAGER");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)hasMessaging {
|
||||
return [self elementForName:@"MSG"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setMessaging:(BOOL)msg {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(msg && ![self hasMessaging], @"MSG");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isCell {
|
||||
return [self elementForName:@"CELL"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setCell:(BOOL)cell {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(cell && ![self isCell], @"CELL");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isVideo {
|
||||
return [self elementForName:@"VIDEO"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setVideo:(BOOL)video {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(video && ![self isVideo], @"VIDEO");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isBBS {
|
||||
return [self elementForName:@"BBS"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setBBS:(BOOL)bbs {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(bbs && ![self isBBS], @"BBS");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isModem {
|
||||
return [self elementForName:@"MODEM"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setModem:(BOOL)modem {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(modem && ![self isModem], @"MODEM");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isISDN {
|
||||
return [self elementForName:@"ISDN"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setISDN:(BOOL)isdn {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(isdn && ![self isISDN], @"ISDN");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isPCS {
|
||||
return [self elementForName:@"PCS"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPCS:(BOOL)pcs {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(pcs && ![self isPCS], @"PCS");
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isPreferred {
|
||||
return [self elementForName:@"PREF"] != nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)setPreferred:(BOOL)pref {
|
||||
XMPP_VCARD_SET_EMPTY_CHILD(pref && ![self isPreferred], @"PREF");
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)number {
|
||||
return [[self elementForName:@"NUMBER"] stringValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setNumber:(NSString *)number {
|
||||
XMPP_VCARD_SET_STRING_CHILD(number, @"NUMBER");
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
Reference in new issue
Block a user