This commit is contained in:
giuseppenuc committed 2016-02-24 16:56:39 +01:00
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>
@@ -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
+120
View File
@@ -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
+932
View File
@@ -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
+28
View File
@@ -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
+136
View File
@@ -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
+103
View File
@@ -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
+69
View File
@@ -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
+102
View File
@@ -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
+29
View File
@@ -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
+125
View File
@@ -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
+25
View File
@@ -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
+93
View File
@@ -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
+117
View File
@@ -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
+286
View File
@@ -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
+37
View File
@@ -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
+204
View File
@@ -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