Merge lp:~isoschiz/xmppframework/vcard-temp into lp:xmppframework

Proposed by Martin Morrison
Status: Needs review
Proposed branch: lp:~isoschiz/xmppframework/vcard-temp
Merge into: lp:xmppframework
Diff against target: 1663 lines (+1652/-0)
2 files modified
Extensions/XMPPvCardTemp.h (+294/-0)
Extensions/XMPPvCardTemp.m (+1358/-0)
To merge this branch: bzr merge lp:~isoschiz/xmppframework/vcard-temp
Reviewer Review Type Date Requested Status
XMPPFramework Developers Pending
Review via email: mp+33988@code.launchpad.net

Description of the change

Implementation of XEP-0054.

(Note: there are a few missing functions. Pushing this out for review of the API).

To post a comment you must log in.

Unmerged revisions

148. By Martin Morrison <email address hidden>

Implementation of XEP-0054. Note there are a few missing functions still, to be completed in a future commit.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'Extensions'
=== added file 'Extensions/XMPPvCardTemp.h'
--- Extensions/XMPPvCardTemp.h 1970-01-01 00:00:00 +0000
+++ Extensions/XMPPvCardTemp.h 2010-08-28 10:45:53 +0000
@@ -0,0 +1,294 @@
1//
2// XMPPvCardTemp.h
3// Jibberer
4//
5// Created by Martin Morrison on 24/07/2010.
6// Copyright 2010 __MyCompanyName__. All rights reserved.
7//
8
9#import <Foundation/Foundation.h>
10#import <CoreLocation/CoreLocation.h>
11#if TARGET_OS_IPHONE
12#import "DDXML.h"
13#endif
14
15#import "XMPPJID.h"
16#import "XMPPModule.h"
17#import "XMPPStream.h"
18#import "NSXMLElementAdditions.h"
19
20/*
21 * Implementation of XEP-0054 vCard-temp
22 *
23 * Consists of the following classes/protocols:
24 * - XMPPvCard - the XMPPModule. Instantiate one of these to fetch vCards.
25 * - XMPPvCardStorage - protocol for persistence of vCards. A default in-memory implementation is provided.
26 * - XMPPvCardDelegate - protocol for objects wishing to be notified of new vCards.
27 *
28 * The following are all NSXMLElement subclasses providing accessor methods for the supported fields:
29 * - XMPPvCard - represents a <vCard/> element.
30 * - XMPPvCardEmail - an <EMAIL/> child of a <vCard/> element.
31 * - XMPPvCardTel - a <TEL/> child of a <vCard/> element.
32 * - XMPPvCardAdr - an <ADR/> child of a <vCard/> element.
33 * - XMPPvCardLabel - a <LABEL/> child of a <vCard/> element.
34 * - (XMPPvCardAdrTypes - superclass of XMPPvCardAdr and XMPPvCardLabel providing common accessors).
35 */
36
37#define XMPP_VCARD_NS @"vcard-temp"
38
39@protocol XMPPvCardTempDelegate;
40@class XMPPvCard;
41
42#pragma mark -
43#pragma mark XMPPvCardStorage
44
45@protocol XMPPvCardStorage <NSObject>
46
47/*
48 * Return whether a vCard for the given JID is saved.
49 */
50- (BOOL)havevCardForJID:(XMPPJID *)jid;
51
52/*
53 * Get the vCard for the given JID.
54 */
55- (XMPPvCard *)getvCardForJID:(XMPPJID *)jid;
56
57/*
58 * Save the given vCard for the given JID.
59 */
60- (void)savevCard:(XMPPvCard *)vCard forJID:(XMPPJID *)jid;
61
62/*
63 * Clear any stored vCard for the given JID.
64 */
65- (void)clearvCardForJID:(XMPPJID *)jid;
66
67@end
68
69/*
70 * Basic storage implementation.
71 */
72@interface XMPPvCardMemoryStorage : NSObject <XMPPvCardStorage> {
73 NSMutableDictionary *vcards;
74}
75@end
76
77#pragma mark -
78#pragma mark XMPPvCardTemp
79
80/*
81 * Provides a wrapper for XEP-0054
82 */
83@interface XMPPvCardTemp : XMPPModule <XMPPStreamDelegate> {
84 XMPPvCard *myvCard;
85 id <XMPPvCardStorage> storage;
86 BOOL autoFetchvCards;
87}
88
89@property (nonatomic, retain, readonly) id <XMPPvCardStorage> storage;
90@property (nonatomic, assign) BOOL autoFetchvCards;
91
92/*
93 * If storage is unspecified, uses a default memory backed cacher.
94 */
95- (id)initWithStream:(XMPPStream *)stream;
96- (id)initWithStream:(XMPPStream *)stream storage:(id <XMPPvCardStorage>)storage;
97
98/*
99 * Initiate a fetch for the vCard for the given user. If the storage object
100 * already has a vCard for the given JID, then this has no effect.
101 */
102- (void)fetchvCardForJID:(XMPPJID *)jid;
103
104@end
105
106#pragma mark -
107#pragma mark XMPPvCardAdrTypes
108
109@interface XMPPvCardAdrTypes : NSXMLElement
110
111@property (nonatomic, assign, setter=setHome) BOOL isHome;
112@property (nonatomic, assign, setter=setWork) BOOL isWork;
113@property (nonatomic, assign, setter=setParcel) BOOL isParcel;
114@property (nonatomic, assign, setter=setPostal) BOOL isPostal;
115@property (nonatomic, assign, setter=setDomestic) BOOL isDomestic;
116@property (nonatomic, assign, setter=setInternational) BOOL isInternational;
117@property (nonatomic, assign, setter=setPreferred) BOOL isPreferred;
118
119@end
120
121#pragma mark -
122#pragma mark XMPPvCardAdr
123
124@interface XMPPvCardAdr : XMPPvCardAdrTypes
125
126+ (XMPPvCardAdr *)vCardAdrFromElement:(NSXMLElement *)elem;
127
128@property (nonatomic, assign) NSString *pobox;
129@property (nonatomic, assign) NSString *extendedAddress;
130@property (nonatomic, assign) NSString *street;
131@property (nonatomic, assign) NSString *locality;
132@property (nonatomic, assign) NSString *region;
133@property (nonatomic, assign) NSString *postalCode;
134@property (nonatomic, assign) NSString *country;
135
136@end
137
138#pragma mark -
139#pragma mark XMPPvCardLabel
140
141@interface XMPPvCardLabel : XMPPvCardAdrTypes
142
143+ (XMPPvCardLabel *)vCardLabelFromElement:(NSXMLElement *)elem;
144
145@property (nonatomic, assign) NSArray *lines;
146
147@end
148
149#pragma mark -
150#pragma mark XMPPvCardTel
151
152@interface XMPPvCardTel : NSXMLElement
153
154+ (XMPPvCardTel *)vCardTelFromElement:(NSXMLElement *)elem;
155
156@property (nonatomic, assign, setter=setHome) BOOL isHome;
157@property (nonatomic, assign, setter=setWork) BOOL isWork;
158@property (nonatomic, assign, setter=setVoice) BOOL isVoice;
159@property (nonatomic, assign, setter=setFax) BOOL isFax;
160@property (nonatomic, assign, setter=setPager) BOOL isPager;
161@property (nonatomic, assign, setter=setMessaging) BOOL hasMessaging;
162@property (nonatomic, assign, setter=setCell) BOOL isCell;
163@property (nonatomic, assign, setter=setVideo) BOOL isVideo;
164@property (nonatomic, assign, setter=setBBS) BOOL isBBS;
165@property (nonatomic, assign, setter=setModem) BOOL isModem;
166@property (nonatomic, assign, setter=setISDN) BOOL isISDN;
167@property (nonatomic, assign, setter=setPCS) BOOL isPCS;
168@property (nonatomic, assign, setter=setPreferred) BOOL isPreferred;
169@property (nonatomic, assign) NSString *number;
170
171@end
172
173#pragma mark -
174#pragma mark XMPPvCardEmail
175
176@interface XMPPvCardEmail : NSXMLElement
177
178+ (XMPPvCardEmail *)vCardEmailFromElement:(NSXMLElement *)elem;
179
180@property (nonatomic, assign, setter=setHome) BOOL isHome;
181@property (nonatomic, assign, setter=setWork) BOOL isWork;
182@property (nonatomic, assign, setter=setInternet) BOOL isInternet;
183@property (nonatomic, assign, setter=setX400) BOOL isX400;
184@property (nonatomic, assign, setter=setPreferred) BOOL isPreferred;
185@property (nonatomic, assign) NSString *userid;
186
187@end
188
189#pragma mark -
190#pragma mark XMPPvCard
191
192typedef enum _XMPPvCardClass {
193 XMPPvCardClassNone,
194 XMPPvCardClassPublic,
195 XMPPvCardClassPrivate,
196 XMPPvCardClassConfidential,
197} XMPPvCardClass;
198
199/*
200 * Note: according to the DTD, every fields bar N and FN can appear multiple times.
201 * The provided accessors only support this for the field types where multiple
202 * entries make sense - for the others, if required, the NSXMLElement accessors
203 * must be used.
204 */
205@interface XMPPvCard : NSXMLElement
206
207+ (XMPPvCard *)vCardFromElement:(NSXMLElement *)element;
208
209#pragma mark Identification Types
210
211@property (nonatomic, assign) NSDate *bday;
212@property (nonatomic, assign) NSData *photo;
213@property (nonatomic, assign) NSString *nickname;
214@property (nonatomic, assign) NSString *formattedName;
215@property (nonatomic, assign) NSString *familyName;
216@property (nonatomic, assign) NSString *givenName;
217@property (nonatomic, assign) NSString *middleName;
218@property (nonatomic, assign) NSString *prefix;
219@property (nonatomic, assign) NSString *suffix;
220
221#pragma mark Delivery Addressing Types
222
223@property (nonatomic, assign) NSArray *addresses;
224- (void)addAddress:(XMPPvCardAdr *)adr;
225- (void)removeAddress:(XMPPvCardAdr *)adr;
226- (void)clearAddresses;
227
228@property (nonatomic, assign) NSArray *labels;
229- (void)addLabel:(XMPPvCardLabel *)label;
230- (void)removeLabel:(XMPPvCardLabel *)label;
231- (void)clearLabels;
232
233@property (nonatomic, assign) NSArray *telecomsAddresses;
234- (void)addTelecomsAddress:(XMPPvCardTel *)tel;
235- (void)removeTelecomsAddress:(XMPPvCardTel *)tel;
236- (void)clearTelecomsAddresses;
237
238@property (nonatomic, assign) NSArray *emailAddresses;
239- (void)addEmailAddress:(XMPPvCardEmail *)email;
240- (void)removeEmailAddress:(XMPPvCardEmail *)email;
241- (void)clearEmailAddresses;
242
243@property (nonatomic, assign) XMPPJID *jid;
244@property (nonatomic, assign) NSString *mailer;
245
246#pragma mark Geographical Types
247
248@property (nonatomic, assign) NSTimeZone *timeZone;
249@property (nonatomic, assign) CLLocation *location;
250
251#pragma mark Organizational Types
252
253@property (nonatomic, assign) NSString *title;
254@property (nonatomic, assign) NSString *role;
255@property (nonatomic, assign) NSData *logo;
256@property (nonatomic, assign) XMPPvCard *agent;
257@property (nonatomic, assign) NSString *orgName;
258
259/*
260 * ORGUNITs can only be set if there is already an ORGNAME. Otherwise, changes are ignored.
261 */
262@property (nonatomic, assign) NSArray *orgUnits;
263
264#pragma mark Explanatory Types
265
266@property (nonatomic, assign) NSArray *categories;
267@property (nonatomic, assign) NSString *note;
268@property (nonatomic, assign) NSString *prodid;
269@property (nonatomic, assign) NSDate *revision;
270@property (nonatomic, assign) NSString *sortString;
271@property (nonatomic, assign) NSString *phoneticSound;
272@property (nonatomic, assign) NSData *sound;
273@property (nonatomic, assign) NSString *uid;
274@property (nonatomic, assign) NSString *url;
275@property (nonatomic, assign) NSString *version;
276@property (nonatomic, assign) NSString *description;
277
278#pragma mark Security Types
279
280@property (nonatomic, assign) XMPPvCardClass privacyClass;
281@property (nonatomic, assign) NSData *key;
282@property (nonatomic, assign) NSString *keyType;
283
284@end
285
286#pragma mark -
287#pragma mark XMPPvCardTempDelegate
288
289@protocol XMPPvCardTempDelegate
290@optional
291
292- (void)xmppvCard:(XMPPvCardTemp *)vCardMod didReceivevCard:(XMPPvCard *)vCard forJID:(XMPPJID *)jid;
293
294@end
0\ No newline at end of file295\ No newline at end of file
1296
=== added file 'Extensions/XMPPvCardTemp.m'
--- Extensions/XMPPvCardTemp.m 1970-01-01 00:00:00 +0000
+++ Extensions/XMPPvCardTemp.m 2010-08-28 10:45:53 +0000
@@ -0,0 +1,1358 @@
1//
2// XMPPvCardTemp.m
3// Jibberer
4//
5// Created by Martin Morrison on 24/07/2010.
6// Copyright 2010 __MyCompanyName__. All rights reserved.
7//
8
9#import <objc/runtime.h>
10
11#import "XMPPvCardTemp.h"
12#import "XMPPIQ.h"
13#import "XMPPJID.h"
14#import "XMPPPresence.h"
15#import "XMPPStream.h"
16#import "NSDataAdditions.h"
17#import "XMPPDateTimeProfiles.h"
18
19#import "NSXMLElementAdditions.h"
20
21#define XMPP_VCARD_SET_EMPTY_CHILD(Set, Name) \
22 if (Set) { \
23 NSXMLElement *elem = [NSXMLElement elementWithName:(Name)]; \
24 [self addChild:elem]; \
25 } else if (!(Set)) { \
26 [self removeChildAtIndex:[[self children] indexOfObject:[self elementForName:(Name)]]]; \
27 }
28
29#define XMPP_VCARD_SET_STRING_CHILD(Value, Name) \
30 NSXMLElement *elem = [self elementForName:(Name)]; \
31 if ((Value) != nil) { \
32 if (elem == nil) { \
33 elem = [NSXMLElement elementWithName:(Name)]; \
34 } \
35 [elem setStringValue:(Value)]; \
36 } else if (elem != nil) { \
37 [self removeChildAtIndex:[[self children] indexOfObject:elem]]; \
38 }
39
40#define XMPP_VCARD_SET_N_CHILD(Value, Name) \
41 NSXMLElement *name = [self elementForName:@"N"]; \
42 if ((Value) != nil && name == nil) { \
43 name = [NSXMLElement elementWithName:@"N"]; \
44 [self addChild:name]; \
45 } \
46 NSXMLElement *part = [name elementForName:(Name)]; \
47 if ((Value) != nil && part == nil) { \
48 part = [NSXMLElement elementWithName:(Name)]; \
49 [name addChild:part]; \
50 } \
51 if (Value) { \
52 [part setStringValue:(Value)]; \
53 } else if (part != nil) { \
54 /* N is mandatory, so we leave it in. */ \
55 [name removeChildAtIndex:[[self children] indexOfObject:part]]; \
56 }
57
58#pragma mark -
59#pragma mark XMPPvCardMemoryStorage
60
61@implementation XMPPvCardMemoryStorage
62
63- (id)init {
64 if (self == [super init]) {
65 vcards = [[NSMutableDictionary alloc] init];
66 }
67
68 return self;
69}
70
71- (void)dealloc {
72 [vcards release];
73 [super dealloc];
74}
75
76- (BOOL)havevCardForJID:(XMPPJID *)jid {
77 return [vcards objectForKey:jid] != nil;
78}
79
80- (XMPPvCard *)getvCardForJID:(XMPPJID *)jid {
81 NSLog(@"+++++ Fetching vCard for %@: %@", jid, [[vcards objectForKey:jid] compactXMLString]);
82 return [vcards objectForKey:jid];
83}
84
85- (void)savevCard:(XMPPvCard *)vCard forJID:(XMPPJID *)jid {
86 NSLog(@"+++++ Storing vCard for %@: %@", jid, [vCard compactXMLString]);
87 [vcards setObject:vCard forKey:jid];
88}
89
90- (void)clearvCardForJID:(XMPPJID *)jid {
91 [vcards removeObjectForKey:jid];
92}
93
94@end
95
96#pragma mark -
97#pragma mark XMPPvCardTemp
98
99@implementation XMPPvCardTemp
100
101@synthesize autoFetchvCards;
102@synthesize storage;
103
104- (id)initWithStream:(XMPPStream *)stream {
105 return [self initWithStream:stream storage:[[[XMPPvCardMemoryStorage alloc] init] autorelease]];
106}
107
108- (id)initWithStream:(XMPPStream *)stream storage:(id <XMPPvCardStorage>)aStorage {
109 if (self == [super initWithStream:stream]) {
110 storage = [aStorage retain];
111 autoFetchvCards = NO;
112 }
113 return self;
114}
115
116/*- (UIImage *)photoForJID:(XMPPJID *)jid {
117 UIImage *image = nil;
118
119 NSXMLElement *vCard = [storage vCardForJID:jid];
120 NSXMLElement *photo = [vCard elementForName:@"PHOTO"];
121
122 if (photo) {
123 // There is a PHOTO element. It should have a TYPE and a BINVAL
124 //NSXMLElement *fileType = [photo elementForName:@"TYPE"];
125 NSXMLElement *binval = [photo elementForName:@"BINVAL"];
126
127 if (binval) {
128 NSData *base64Data = [[binval stringValue] dataUsingEncoding:NSASCIIStringEncoding];
129 NSData *decodedData = [base64Data base64Decoded];
130
131 image = [UIImage imageWithData:decodedData];
132 }
133 }
134
135 if (!image) {
136 image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"user_48x48" ofType:@"png"]];
137 }
138
139 return image;
140}*/
141
142- (void)dealloc {
143 [storage release];
144 storage = nil;
145
146 [super dealloc];
147}
148
149- (void)fetchvCardForJID:(XMPPJID *)jid {
150 // Check whether we already have a vCard
151 jid = [jid bareJID];
152 if (![storage havevCardForJID:jid]) {
153 // Not got it yet. Let's make a request for the vCard
154 XMPPIQ *iq = [XMPPIQ iqWithType:@"get" to:jid];
155 NSXMLElement *vCardElem = [NSXMLElement elementWithName:@"vCard" xmlns:XMPP_VCARD_NS];
156
157 [iq addChild:vCardElem];
158
159 [xmppStream sendElement:iq];
160 }
161}
162
163// Delegate protocol
164
165- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
166 NSXMLElement *elem = [iq elementForName:@"vCard" xmlns:XMPP_VCARD_NS];
167 NSLog(@"Received IQ in vCard module with elem: %@", elem);
168 if (elem != nil) {
169 XMPPvCard *vCard = [XMPPvCard vCardFromElement:elem];
170 [storage savevCard:vCard forJID:[iq from]];
171
172 [multicastDelegate xmppvCard:self didReceivevCard:vCard forJID:[iq from]];
173 }
174
175 return NO;
176}
177
178- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
179 // We use this to track online buddies
180 if (autoFetchvCards &&
181 [presence from] != [xmppStream myJID] &&
182 [presence status] != @"unavailable" &&
183 [presence from] != nil) {
184
185 [self fetchvCardForJID:[presence from]];
186 }
187}
188
189@end
190
191#pragma mark -
192#pragma mark XMPPvCardAdrTypes
193
194@implementation XMPPvCardAdrTypes
195
196- (BOOL)isHome {
197 return [self elementForName:@"HOME"] != nil;
198}
199
200- (void)setHome:(BOOL)home {
201 XMPP_VCARD_SET_EMPTY_CHILD(home && ![self isHome], @"HOME");
202}
203
204- (BOOL)isWork {
205 return [self elementForName:@"WORK"] != nil;
206}
207
208- (void)setWork:(BOOL)work {
209 XMPP_VCARD_SET_EMPTY_CHILD(work && ![self isWork], @"WORK");
210}
211
212- (BOOL)isParcel {
213 return [self elementForName:@"PARCEL"] != nil;
214}
215- (void)setParcel:(BOOL)parcel {
216 XMPP_VCARD_SET_EMPTY_CHILD(parcel && ![self isParcel], @"PARCEL");
217}
218
219- (BOOL)isPostal {
220 return [self elementForName:@"POSTAL"] != nil;
221}
222- (void)setPostal:(BOOL)postal {
223 XMPP_VCARD_SET_EMPTY_CHILD(postal && ![self isPostal], @"POSTAL");
224}
225
226- (BOOL)isDomestic {
227 return [self elementForName:@"DOM"] != nil;
228}
229- (void)setDomestic:(BOOL)dom {
230 XMPP_VCARD_SET_EMPTY_CHILD(dom && ![self isDomestic], @"DOM");
231 // INTL and DOM are mutually exclusive
232 if (dom) {
233 [self setInternational:NO];
234 }
235}
236
237- (BOOL)isInternational {
238 return [self elementForName:@"INTL"] != nil;
239}
240- (void)setInternational:(BOOL)intl {
241 XMPP_VCARD_SET_EMPTY_CHILD(intl && ![self isInternational], @"INTL");
242 // INTL and DOM are mutually exclusive
243 if (intl) {
244 [self setDomestic:NO];
245 }
246}
247
248- (BOOL)isPreferred {
249 return [self elementForName:@"PREF"] != nil;
250}
251- (void)setPreferred:(BOOL)pref {
252 XMPP_VCARD_SET_EMPTY_CHILD(pref && ![self isPreferred], @"PREF");
253}
254
255@end
256
257#pragma mark -
258#pragma mark XMPPvCardAdr
259
260@implementation XMPPvCardAdr
261
262+ (void)initialize {
263 // We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
264 // The size of the two classes is expected to be the same.
265 //
266 // If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
267 // This check is here to aid future developers who may make this mistake.
268 //
269 // For Fearless And Experienced Objective-C Developers:
270 // It may be possible to support adding instance variables to this class if you seriously need it.
271 // To do so, try realloc'ing self after altering the class, and then initialize your variables.
272
273 size_t superSize = class_getInstanceSize([NSXMLElement class]);
274 size_t ourSize = class_getInstanceSize([XMPPvCardAdr class]);
275
276 if (superSize != ourSize)
277 {
278 NSLog(@"Adding instance variables to XMPPvCardAdr is not currently supported!");
279 exit(15);
280 }
281}
282
283+ (XMPPvCardAdr *)vCardAdrFromElement:(NSXMLElement *)elem {
284 object_setClass(elem, [XMPPvCardAdr class]);
285
286 return (XMPPvCardAdr *)elem;
287}
288
289- (NSString *)pobox {
290 return [[self elementForName:@"POBOX"] stringValue];
291}
292- (void)setPobox:(NSString *)pobox {
293 XMPP_VCARD_SET_STRING_CHILD(pobox, @"POBOX");
294}
295
296- (NSString *)extendedAddress {
297 return [[self elementForName:@"EXTADD"] stringValue];
298}
299- (void)setExtendedAddress:(NSString *)extadd {
300 XMPP_VCARD_SET_STRING_CHILD(extadd, @"EXTADD");
301}
302
303- (NSString *)street {
304 return [[self elementForName:@"STREET"] stringValue];
305}
306- (void)setStreet:(NSString *)street {
307 XMPP_VCARD_SET_STRING_CHILD(street, @"STREET");
308}
309
310- (NSString *)locality {
311 return [[self elementForName:@"LOCALITY"] stringValue];
312}
313- (void)setLocality:(NSString *)locality {
314 XMPP_VCARD_SET_STRING_CHILD(locality, @"LOCALITY");
315}
316
317- (NSString *)region {
318 return [[self elementForName:@"REGION"] stringValue];
319}
320- (void)setRegion:(NSString *)region {
321 XMPP_VCARD_SET_STRING_CHILD(region, @"REGION");
322}
323
324- (NSString *)postalCode {
325 return [[self elementForName:@"PCODE"] stringValue];
326}
327- (void)setPostalCode:(NSString *)pcode {
328 XMPP_VCARD_SET_STRING_CHILD(pcode, @"PCODE");
329}
330
331- (NSString *)country {
332 return [[self elementForName:@"CTRY"] stringValue];
333}
334- (void)setCountry:(NSString *)ctry {
335 XMPP_VCARD_SET_STRING_CHILD(ctry, @"CTRY");
336}
337
338@end
339
340#pragma mark -
341#pragma mark XMPPvCardLabel
342
343@implementation XMPPvCardLabel
344
345+ (void)initialize {
346 // We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
347 // The size of the two classes is expected to be the same.
348 //
349 // If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
350 // This check is here to aid future developers who may make this mistake.
351 //
352 // For Fearless And Experienced Objective-C Developers:
353 // It may be possible to support adding instance variables to this class if you seriously need it.
354 // To do so, try realloc'ing self after altering the class, and then initialize your variables.
355
356 size_t superSize = class_getInstanceSize([NSXMLElement class]);
357 size_t ourSize = class_getInstanceSize([XMPPvCardLabel class]);
358
359 if (superSize != ourSize)
360 {
361 NSLog(@"Adding instance variables to XMPPvCardLabel is not currently supported!");
362 exit(15);
363 }
364}
365
366+ (XMPPvCardLabel *)vCardLabelFromElement:(NSXMLElement *)elem {
367 object_setClass(elem, [XMPPvCardLabel class]);
368
369 return (XMPPvCardLabel *)elem;
370}
371
372- (NSArray *)lines {
373 NSArray *elems = [self elementsForName:@"LINE"];
374 NSMutableArray *lines = [[NSMutableArray alloc] initWithCapacity:[elems count]];
375
376 for (NSXMLElement *elem in elems) {
377 [lines addObject:[elem stringValue]];
378 }
379
380 NSArray *result = [NSArray arrayWithArray:lines];
381 [lines release];
382 return result;
383}
384- (void)setLines:(NSArray *)lines {
385 NSArray *elems = [self elementsForName:@"LINE"];
386
387 for (NSXMLElement *elem in elems) {
388 [self removeChildAtIndex:[[self children] indexOfObject:elem]];
389 }
390
391 for (NSString *line in lines) {
392 NSXMLElement *elem = [NSXMLElement elementWithName:@"LINE"];
393 [elem setStringValue:line];
394 [self addChild:elem];
395 }
396}
397
398@end
399
400#pragma mark -
401#pragma mark XMPPvCardTel
402
403@implementation XMPPvCardTel
404
405+ (void)initialize {
406 // We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
407 // The size of the two classes is expected to be the same.
408 //
409 // If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
410 // This check is here to aid future developers who may make this mistake.
411 //
412 // For Fearless And Experienced Objective-C Developers:
413 // It may be possible to support adding instance variables to this class if you seriously need it.
414 // To do so, try realloc'ing self after altering the class, and then initialize your variables.
415
416 size_t superSize = class_getInstanceSize([NSXMLElement class]);
417 size_t ourSize = class_getInstanceSize([XMPPvCardTel class]);
418
419 if (superSize != ourSize)
420 {
421 NSLog(@"Adding instance variables to XMPPvCardTel is not currently supported!");
422 exit(15);
423 }
424}
425
426+ (XMPPvCardTel *)vCardTelFromElement:(NSXMLElement *)elem {
427 object_setClass(elem, [XMPPvCardTel class]);
428
429 return (XMPPvCardTel *)elem;
430}
431
432- (BOOL)isHome {
433 return [self elementForName:@"HOME"] != nil;
434}
435- (void)setHome:(BOOL)home {
436 XMPP_VCARD_SET_EMPTY_CHILD(home && ![self isHome], @"HOME");
437}
438
439- (BOOL)isWork {
440 return [self elementForName:@"WORK"] != nil;
441}
442- (void)setWork:(BOOL)work {
443 XMPP_VCARD_SET_EMPTY_CHILD(work && ![self isWork], @"WORK");
444}
445
446- (BOOL)isVoice {
447 return [self elementForName:@"VOICE"] != nil;
448}
449- (void)setVoice:(BOOL)voice {
450 XMPP_VCARD_SET_EMPTY_CHILD(voice && ![self isVoice], @"VOICE");
451}
452
453- (BOOL)isFax {
454 return [self elementForName:@"FAX"] != nil;
455}
456- (void)setFax:(BOOL)fax {
457 XMPP_VCARD_SET_EMPTY_CHILD(fax && ![self isFax], @"FAX");
458}
459
460- (BOOL)isPager {
461 return [self elementForName:@"PAGER"] != nil;
462}
463- (void)setPager:(BOOL)pager {
464 XMPP_VCARD_SET_EMPTY_CHILD(pager && ![self isPager], @"PAGER");
465}
466
467- (BOOL)hasMessaging {
468 return [self elementForName:@"MSG"] != nil;
469}
470- (void)setMessaging:(BOOL)msg {
471 XMPP_VCARD_SET_EMPTY_CHILD(msg && ![self hasMessaging], @"MSG");
472}
473
474- (BOOL)isCell {
475 return [self elementForName:@"CELL"] != nil;
476}
477- (void)setCell:(BOOL)cell {
478 XMPP_VCARD_SET_EMPTY_CHILD(cell && ![self isCell], @"CELL");
479}
480
481- (BOOL)isVideo {
482 return [self elementForName:@"VIDEO"] != nil;
483}
484- (void)setVideo:(BOOL)video {
485 XMPP_VCARD_SET_EMPTY_CHILD(video && ![self isVideo], @"VIDEO");
486}
487
488- (BOOL)isBBS {
489 return [self elementForName:@"BBS"] != nil;
490}
491- (void)setBBS:(BOOL)bbs {
492 XMPP_VCARD_SET_EMPTY_CHILD(bbs && ![self isBBS], @"BBS");
493}
494
495- (BOOL)isModem {
496 return [self elementForName:@"MODEM"] != nil;
497}
498- (void)setModem:(BOOL)modem {
499 XMPP_VCARD_SET_EMPTY_CHILD(modem && ![self isModem], @"MODEM");
500}
501
502- (BOOL)isISDN {
503 return [self elementForName:@"ISDN"] != nil;
504}
505- (void)setISDN:(BOOL)isdn {
506 XMPP_VCARD_SET_EMPTY_CHILD(isdn && ![self isISDN], @"ISDN");
507}
508
509- (BOOL)isPCS {
510 return [self elementForName:@"PCS"] != nil;
511}
512- (void)setPCS:(BOOL)pcs {
513 XMPP_VCARD_SET_EMPTY_CHILD(pcs && ![self isPCS], @"PCS");
514}
515
516- (BOOL)isPreferred {
517 return [self elementForName:@"PREF"] != nil;
518}
519- (void)setPreferred:(BOOL)pref {
520 XMPP_VCARD_SET_EMPTY_CHILD(pref && ![self isPreferred], @"PREF");
521}
522
523- (NSString *)number {
524 return [[self elementForName:@"NUMBER"] stringValue];
525}
526- (void)setNumber:(NSString *)number {
527 XMPP_VCARD_SET_STRING_CHILD(number, @"NUMBER");
528}
529
530@end
531
532#pragma mark -
533#pragma mark XMPPvCardEmail
534
535@implementation XMPPvCardEmail
536
537+ (void)initialize {
538 // We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
539 // The size of the two classes is expected to be the same.
540 //
541 // If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
542 // This check is here to aid future developers who may make this mistake.
543 //
544 // For Fearless And Experienced Objective-C Developers:
545 // It may be possible to support adding instance variables to this class if you seriously need it.
546 // To do so, try realloc'ing self after altering the class, and then initialize your variables.
547
548 size_t superSize = class_getInstanceSize([NSXMLElement class]);
549 size_t ourSize = class_getInstanceSize([XMPPvCardEmail class]);
550
551 if (superSize != ourSize)
552 {
553 NSLog(@"Adding instance variables to XMPPvCardEmail is not currently supported!");
554 exit(15);
555 }
556}
557
558+ (XMPPvCardEmail *)vCardEmailFromElement:(NSXMLElement *)elem {
559 object_setClass(elem, [XMPPvCardEmail class]);
560
561 return (XMPPvCardEmail *)elem;
562}
563
564- (BOOL)isHome {
565 return [self elementForName:@"HOME"] != nil;
566}
567- (void)setHome:(BOOL)home {
568 XMPP_VCARD_SET_EMPTY_CHILD(home && ![self isHome], @"HOME");
569}
570
571- (BOOL)isWork {
572 return [self elementForName:@"WORK"] != nil;
573}
574- (void)setWork:(BOOL)work {
575 XMPP_VCARD_SET_EMPTY_CHILD(work && ![self isWork], @"WORK");
576}
577
578- (BOOL)isInternet {
579 return [self elementForName:@"INTERNET"] != nil;
580}
581- (void)setInternet:(BOOL)internet {
582 XMPP_VCARD_SET_EMPTY_CHILD(internet && ![self isInternet], @"INTERNET");
583}
584
585- (BOOL)isX400 {
586 return [self elementForName:@"X400"] != nil;
587}
588- (void)setX400:(BOOL)x400 {
589 XMPP_VCARD_SET_EMPTY_CHILD(x400 && ![self isX400], @"X400");
590}
591
592- (BOOL)isPreferred {
593 return [self elementForName:@"PREF"] != nil;
594}
595- (void)setPreferred:(BOOL)pref {
596 XMPP_VCARD_SET_EMPTY_CHILD(pref && ![self isPreferred], @"PREF");
597}
598
599- (NSString *)userid {
600 return [[self elementForName:@"USERID"] stringValue];
601}
602- (void)setUserid:(NSString *)userid {
603 XMPP_VCARD_SET_STRING_CHILD(userid, @"USERID");
604}
605
606@end
607
608#pragma mark -
609#pragma mark XMPPvCard
610
611@implementation XMPPvCard
612
613+ (void)initialize {
614 // We use the object_setClass method below to dynamically change the class from a standard NSXMLElement.
615 // The size of the two classes is expected to be the same.
616 //
617 // If a developer adds instance methods to this class, bad things happen at runtime that are very hard to debug.
618 // This check is here to aid future developers who may make this mistake.
619 //
620 // For Fearless And Experienced Objective-C Developers:
621 // It may be possible to support adding instance variables to this class if you seriously need it.
622 // To do so, try realloc'ing self after altering the class, and then initialize your variables.
623
624 size_t superSize = class_getInstanceSize([NSXMLElement class]);
625 size_t ourSize = class_getInstanceSize([XMPPvCard class]);
626
627 if (superSize != ourSize)
628 {
629 NSLog(@"Adding instance variables to XMPPvCard is not currently supported!");
630 exit(15);
631 }
632}
633
634+ (XMPPvCard *)vCardFromElement:(NSXMLElement *)elem {
635 object_setClass(elem, [XMPPvCard class]);
636
637 return (XMPPvCard *)elem;
638}
639
640#pragma mark Identification Types
641
642- (NSDate *)bday {
643 NSDate *bday = nil;
644 NSXMLElement *elem = [self elementForName:@"BDAY"];
645
646 if (elem != nil) {
647 bday = [NSDate dateWithXmppDateString:[elem stringValue]];
648 }
649
650 return bday;
651}
652- (void)setBday:(NSDate *)bday {
653 NSXMLElement *elem = [self elementForName:@"BDAY"];
654
655 if (elem == nil) {
656 elem = [NSXMLElement elementWithName:@"BDAY"];
657 [self addChild:elem];
658 }
659
660 [elem setStringValue:[bday xmppDateString]];
661}
662
663- (NSData *)photo {
664 NSData *decodedData = nil;
665 NSXMLElement *photo = [self elementForName:@"PHOTO"];
666
667 if (photo != nil) {
668 // There is a PHOTO element. It should have a TYPE and a BINVAL
669 //NSXMLElement *fileType = [photo elementForName:@"TYPE"];
670 NSXMLElement *binval = [photo elementForName:@"BINVAL"];
671
672 if (binval) {
673 NSData *base64Data = [[binval stringValue] dataUsingEncoding:NSASCIIStringEncoding];
674 decodedData = [base64Data base64Decoded];
675 }
676 }
677
678 return decodedData;
679}
680- (void)setPhoto:(NSData *)data {
681 NSXMLElement *photo = [self elementForName:@"PHOTO"];
682
683 if (photo == nil) {
684 photo = [NSXMLElement elementWithName:@"PHOTO"];
685 [self addChild:photo];
686 }
687
688 NSXMLElement *binval = [photo elementForName:@"BINVAL"];
689
690 if (binval == nil) {
691 binval = [NSXMLElement elementWithName:@"BINVAL"];
692 [photo addChild:binval];
693 }
694
695 [binval setStringValue:[data base64Encoded]];
696}
697
698- (NSString *)nickname {
699 return [[self elementForName:@"NICKNAME"] stringValue];
700}
701- (void)setNickname:(NSString *)nick {
702 XMPP_VCARD_SET_STRING_CHILD(nick, @"NICKNAME");
703}
704
705- (NSString *)formattedName {
706 return [[self elementForName:@"FN"] stringValue];
707}
708- (void)setFormattedName:(NSString *)fn {
709 XMPP_VCARD_SET_STRING_CHILD(fn, @"FN");
710}
711
712- (NSString *)familyName {
713 NSString *result = nil;
714 NSXMLElement *name = [self elementForName:@"N"];
715
716 if (name != nil) {
717 NSXMLElement *part = [name elementForName:@"FAMILY"];
718
719 if (part != nil) {
720 result = [part stringValue];
721 }
722 }
723
724 return result;
725}
726- (void)setFamilyName:(NSString *)family {
727 XMPP_VCARD_SET_N_CHILD(family, @"FAMILY");
728}
729
730- (NSString *)givenName {
731 NSString *result = nil;
732 NSXMLElement *name = [self elementForName:@"N"];
733
734 if (name != nil) {
735 NSXMLElement *part = [name elementForName:@"GIVEN"];
736
737 if (part != nil) {
738 result = [part stringValue];
739 }
740 }
741
742 return result;
743}
744- (void)setGivenName:(NSString *)given {
745 XMPP_VCARD_SET_N_CHILD(given, @"GIVEN");
746}
747
748- (NSString *)middleName {
749 NSString *result = nil;
750 NSXMLElement *name = [self elementForName:@"N"];
751
752 if (name != nil) {
753 NSXMLElement *part = [name elementForName:@"MIDDLE"];
754
755 if (part != nil) {
756 result = [part stringValue];
757 }
758 }
759
760 return result;
761}
762- (void)setMiddleName:(NSString *)middle {
763 XMPP_VCARD_SET_N_CHILD(middle, @"MIDDLE");
764}
765
766- (NSString *)prefix {
767 NSString *result = nil;
768 NSXMLElement *name = [self elementForName:@"N"];
769
770 if (name != nil) {
771 NSXMLElement *part = [name elementForName:@"PREFIX"];
772
773 if (part != nil) {
774 result = [part stringValue];
775 }
776 }
777
778 return result;
779}
780- (void)setPrefix:(NSString *)prefix {
781 XMPP_VCARD_SET_N_CHILD(prefix, @"PREFIX");
782}
783
784- (NSString *)suffix {
785 NSString *result = nil;
786 NSXMLElement *name = [self elementForName:@"N"];
787
788 if (name != nil) {
789 NSXMLElement *part = [name elementForName:@"SUFFIC"];
790
791 if (part != nil) {
792 result = [part stringValue];
793 }
794 }
795
796 return result;
797}
798- (void)setSuffix:(NSString *)suffix {
799 XMPP_VCARD_SET_N_CHILD(suffix, @"SUFFIX");
800}
801
802#pragma mark Delivery Addressing Types
803
804- (NSArray *)addresses { return nil; }
805- (void)addAddress:(XMPPvCardAdr *)adr { }
806- (void)removeAddress:(XMPPvCardAdr *)adr { }
807- (void)setAddresses:(NSArray *)adrs { }
808- (void)clearAddresses { }
809
810- (NSArray *)labels { return nil; }
811- (void)addLabel:(XMPPvCardLabel *)label { }
812- (void)removeLabel:(XMPPvCardLabel *)label { }
813- (void)setLabels:(NSArray *)labels { }
814- (void)clearLabels { }
815
816- (NSArray *)telecomsAddresses { return nil; }
817- (void)addTelecomsAddress:(XMPPvCardTel *)tel { }
818- (void)removeTelecomsAddress:(XMPPvCardTel *)tel { }
819- (void)setTelecomsAddresses:(NSArray *)tels { }
820- (void)clearTelecomsAddresses { }
821
822- (NSArray *)emailAddresses { return nil; }
823- (void)addEmailAddress:(XMPPvCardEmail *)email { }
824- (void)removeEmailAddress:(XMPPvCardEmail *)email { }
825- (void)setEmailAddresses:(NSArray *)emails { }
826- (void)clearEmailAddresses { }
827
828- (XMPPJID *)jid {
829 XMPPJID *jid = nil;
830 NSXMLElement *elem = [self elementForName:@"JABBERID"];
831
832 if (elem != nil) {
833 jid = [XMPPJID jidWithString:[elem stringValue]];
834 }
835
836 return jid;
837}
838- (void)setJid:(XMPPJID *)jid {
839 NSXMLElement *elem = [self elementForName:@"JABBERID"];
840
841 if (elem == nil && jid != nil) {
842 elem = [NSXMLElement elementWithName:@"JABBERID"];
843 [self addChild:elem];
844 }
845
846 if (jid != nil) {
847 [elem setStringValue:[jid full]];
848 } else if (elem != nil) {
849 [self removeChildAtIndex:[[self children] indexOfObject:elem]];
850 }
851}
852
853- (NSString *)mailer {
854 return [[self elementForName:@"MAILER"] stringValue];
855}
856- (void)setMailer:(NSString *)mailer {
857 XMPP_VCARD_SET_STRING_CHILD(mailer, @"MAILER");
858}
859
860#pragma mark Geographical Types
861
862- (NSTimeZone *)timeZone {
863 // Turns out this is hard. Being lazy for now (not like anyone actually uses this, right?)
864 NSXMLElement *tz = [self elementForName:@"TZ"];
865 if (tz != nil) {
866 // This is unlikely to work. :-(
867 return [NSTimeZone timeZoneWithName:[tz stringValue]];
868 } else {
869 return nil;
870 }
871}
872- (void)setTimeZone:(NSTimeZone *)tz {
873 NSXMLElement *elem = [self elementForName:@"TZ"];
874
875 if (elem == nil && tz != nil) {
876 elem = [NSXMLElement elementWithName:@"TZ"];
877 [self addChild:elem];
878 }
879
880 if (tz != nil) {
881 NSInteger offset = [tz secondsFromGMT];
882 [elem setStringValue:[NSString stringWithFormat:@"%02d:%02d", offset / 3600, (offset % 3600) / 60]];
883 } else if (elem != nil) {
884 [self removeChildAtIndex:[[self children] indexOfObject:elem]];
885 }
886}
887
888- (CLLocation *)location {
889 CLLocation *loc = nil;
890 NSXMLElement *geo = [self elementForName:@"GEO"];
891
892 if (geo != nil) {
893 NSXMLElement *lat = [geo elementForName:@"LAT"];
894 NSXMLElement *lon = [geo elementForName:@"LON"];
895
896 loc = [[[CLLocation alloc] initWithLatitude:[[lat stringValue] doubleValue] longitude:[[lon stringValue] doubleValue]] autorelease];
897 }
898
899 return loc;
900}
901- (void)setLocation:(CLLocation *)geo {
902 NSXMLElement *elem = [self elementForName:@"GEO"];
903 NSXMLElement *lat;
904 NSXMLElement *lon;
905
906 if (geo != nil) {
907 CLLocationCoordinate2D coord = [geo coordinate];
908 if (elem == nil) {
909 elem = [NSXMLElement elementWithName:@"GEO"];
910 [self addChild:elem];
911
912 lat = [NSXMLElement elementWithName:@"LAT"];
913 [elem addChild:lat];
914 lon = [NSXMLElement elementWithName:@"LON"];
915 [elem addChild:lon];
916 } else {
917 lat = [elem elementForName:@"LAT"];
918 lon = [elem elementForName:@"LON"];
919 }
920
921 [lat setStringValue:[NSString stringWithFormat:@"%.6f", coord.latitude]];
922 [lon setStringValue:[NSString stringWithFormat:@"%.6f", coord.longitude]];
923 } else if (elem != nil) {
924 [self removeChildAtIndex:[[self children] indexOfObject:elem]];
925 }
926}
927
928#pragma mark Organizational Types
929
930- (NSString *)title {
931 return [[self elementForName:@"TITLE"] stringValue];
932}
933- (void)setTitle:(NSString *)title {
934 XMPP_VCARD_SET_STRING_CHILD(title, @"TITLE");
935}
936
937- (NSString *)role {
938 return [[self elementForName:@"ROLE"] stringValue];
939}
940- (void)setRole:(NSString *)role {
941 XMPP_VCARD_SET_STRING_CHILD(role, @"ROLE");
942}
943
944- (NSData *)logo {
945 NSData *decodedData = nil;
946 NSXMLElement *logo = [self elementForName:@"LOGO"];
947
948 if (logo != nil) {
949 // There is a LOGO element. It should have a TYPE and a BINVAL
950 //NSXMLElement *fileType = [photo elementForName:@"TYPE"];
951 NSXMLElement *binval = [logo elementForName:@"BINVAL"];
952
953 if (binval) {
954 NSData *base64Data = [[binval stringValue] dataUsingEncoding:NSASCIIStringEncoding];
955 decodedData = [base64Data base64Decoded];
956 }
957 }
958
959 return decodedData;
960}
961- (void)setLogo:(NSData *)data {
962 NSXMLElement *logo = [self elementForName:@"LOGO"];
963
964 if (logo == nil) {
965 logo = [NSXMLElement elementWithName:@"LOGO"];
966 [self addChild:logo];
967 }
968
969 NSXMLElement *binval = [logo elementForName:@"BINVAL"];
970
971 if (binval == nil) {
972 binval = [NSXMLElement elementWithName:@"BINVAL"];
973 [logo addChild:binval];
974 }
975
976 [binval setStringValue:[data base64Encoded]];
977}
978
979- (XMPPvCard *)agent {
980 XMPPvCard *agent = nil;
981 NSXMLElement *elem = [self elementForName:@"AGENT"];
982
983 if (elem != nil) {
984 agent = [XMPPvCard vCardFromElement:elem];
985 }
986
987 return agent;
988}
989- (void)setAgent:(XMPPvCard *)agent {
990 NSXMLElement *elem = [self elementForName:@"AGENT"];
991
992 if (elem != nil) {
993 [self removeChildAtIndex:[[self children] indexOfObject:elem]];
994 }
995
996 if (agent != nil) {
997 [self addChild:agent];
998 }
999}
1000
1001- (NSString *)orgName {
1002 NSString *result = nil;
1003 NSXMLElement *org = [self elementForName:@"ORG"];
1004
1005 if (org != nil) {
1006 NSXMLElement *orgname = [org elementForName:@"ORGNAME"];
1007
1008 if (orgname != nil) {
1009 result = [orgname stringValue];
1010 }
1011 }
1012
1013 return result;
1014}
1015- (void)setOrgName:(NSString *)orgname {
1016 NSXMLElement *org = [self elementForName:@"ORG"];
1017 NSXMLElement *elem = nil;
1018
1019 if (orgname != nil) {
1020 if (org == nil) {
1021 org = [NSXMLElement elementWithName:@"ORG"];
1022 [self addChild:org];
1023 } else {
1024 elem = [org elementForName:@"ORGNAME"];
1025 }
1026
1027 if (elem == nil) {
1028 elem = [NSXMLElement elementWithName:@"ORGNAME"];
1029 [org addChild:elem];
1030 }
1031
1032 [elem setStringValue:orgname];
1033 } else if (org != nil) {
1034 // This implicitly removes all orgunits too, as per the spec
1035 [self removeChildAtIndex:[[self children] indexOfObject:org]];
1036 }
1037}
1038
1039- (NSArray *)orgUnits {
1040 NSArray *result = nil;
1041 NSXMLElement *org = [self elementForName:@"ORG"];
1042
1043 if (org != nil) {
1044 NSArray *elems = [org elementsForName:@"ORGUNIT"];
1045 NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:[elems count]];
1046
1047 for (NSXMLElement *elem in elems) {
1048 [arr addObject:[elem stringValue]];
1049 }
1050
1051 result = [NSArray arrayWithArray:arr];
1052 [arr release];
1053 }
1054
1055 return result;
1056}
1057- (void)setOrgUnits:(NSArray *)orgunits {
1058 NSXMLElement *org = [self elementForName:@"ORG"];
1059
1060 // If there is no org, then there is nothing to do (need ORGNAME first)
1061 if (org != nil) {
1062 NSArray *elems = [org elementsForName:@"ORGUNIT"];
1063 for (NSXMLElement *elem in elems) {
1064 [org removeChildAtIndex:[[org children] indexOfObject:elem]];
1065 }
1066
1067 for (NSString *unit in orgunits) {
1068 NSXMLElement *elem = [NSXMLElement elementWithName:@"ORGUNIT"];
1069 [elem setStringValue:unit];
1070
1071 [org addChild:elem];
1072 }
1073 }
1074}
1075
1076#pragma mark Explanatory Types
1077
1078- (NSArray *)categories {
1079 NSArray *result = nil;
1080 NSXMLElement *categories = [self elementForName:@"CATEGORIES"];
1081
1082 if (categories != nil) {
1083 NSArray *elems = [categories elementsForName:@"KEYWORD"];
1084 NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:[elems count]];
1085
1086 for (NSXMLElement *elem in elems) {
1087 [arr addObject:[elem stringValue]];
1088 }
1089
1090 result = [NSArray arrayWithArray:arr];
1091 [arr release];
1092 }
1093
1094 return result;
1095}
1096- (void)setCategories:(NSArray *)categories {
1097 NSXMLElement *cat = [self elementForName:@"CATEGORIES"];
1098
1099 if (categories != nil) {
1100 if (cat == nil) {
1101 cat = [NSXMLElement elementWithName:@"CATEGORIES"];
1102 [self addChild:cat];
1103 }
1104
1105 NSArray *elems = [cat elementsForName:@"KEYWORD"];
1106 for (NSXMLElement *elem in elems) {
1107 [cat removeChildAtIndex:[[cat children] indexOfObject:elem]];
1108 }
1109
1110 for (NSString *kw in categories) {
1111 NSXMLElement *elem = [NSXMLElement elementWithName:@"KEYWORD"];
1112 [elem setStringValue:kw];
1113
1114 [cat addChild:elem];
1115 }
1116 } else if (cat != nil) {
1117 [self removeChildAtIndex:[[self children] indexOfObject:cat]];
1118 }
1119}
1120
1121- (NSString *)note {
1122 return [[self elementForName:@"NOTE"] stringValue];
1123}
1124- (void)setNote:(NSString *)note {
1125 XMPP_VCARD_SET_STRING_CHILD(note, @"NOTE");
1126}
1127
1128- (NSString *)prodid {
1129 return [[self elementForName:@"PRODID"] stringValue];
1130}
1131- (void)setProdid:(NSString *)prodid {
1132 XMPP_VCARD_SET_STRING_CHILD(prodid, @"PRODID");
1133}
1134
1135- (NSDate *)revision {
1136 NSDate *rev = nil;
1137 NSXMLElement *elem = [self elementForName:@"REV"];
1138
1139 if (elem != nil) {
1140 rev = [NSDate dateWithXmppDateTimeString:[elem stringValue]];
1141 }
1142
1143 return rev;
1144}
1145- (void)setRevision:(NSDate *)rev {
1146 NSXMLElement *elem = [self elementForName:@"REV"];
1147
1148 if (elem == nil) {
1149 elem = [NSXMLElement elementWithName:@"REV"];
1150 [self addChild:elem];
1151 }
1152
1153 [elem setStringValue:[rev xmppDateTimeString]];
1154}
1155
1156- (NSString *)sortString {
1157 return [[self elementForName:@"SORT-STRING"] stringValue];
1158}
1159- (void)setSortString:(NSString *)sortString {
1160 XMPP_VCARD_SET_STRING_CHILD(sortString, @"SORT-STRING");
1161}
1162
1163- (NSString *)phoneticSound {
1164 NSString *phon = nil;
1165 NSXMLElement *sound = [self elementForName:@"SOUND"];
1166
1167 if (sound != nil) {
1168 NSXMLElement *elem = [sound elementForName:@"PHONETIC"];
1169
1170 if (elem != nil) {
1171 phon = [elem stringValue];
1172 }
1173 }
1174
1175 return phon;
1176}
1177- (void)setPhoneticSound:(NSString *)phonetic {
1178 NSXMLElement *sound = [self elementForName:@"SOUND"];
1179 NSXMLElement *elem;
1180
1181 if (sound == nil && phonetic != nil) {
1182 sound = [NSXMLElement elementWithName:@"SOUND"];
1183 [self addChild:sound];
1184 }
1185
1186 if (sound != nil) {
1187 elem = [sound elementForName:@"PHONETIC"];
1188
1189 if (elem != nil && phonetic != nil) {
1190 elem = [NSXMLElement elementWithName:@"PHONETIC"];
1191 [sound addChild:elem];
1192 }
1193 }
1194
1195 if (phonetic != nil) {
1196 [elem setStringValue:phonetic];
1197 } else if (sound != nil) {
1198 [self removeChildAtIndex:[[self children] indexOfObject:phonetic]];
1199 }
1200}
1201
1202- (NSData *)sound {
1203 NSData *decodedData = nil;
1204 NSXMLElement *sound = [self elementForName:@"SOUND"];
1205
1206 if (sound != nil) {
1207 NSXMLElement *binval = [sound elementForName:@"BINVAL"];
1208
1209 if (binval) {
1210 NSData *base64Data = [[binval stringValue] dataUsingEncoding:NSASCIIStringEncoding];
1211 decodedData = [base64Data base64Decoded];
1212 }
1213 }
1214
1215 return decodedData;
1216}
1217- (void)setSound:(NSData *)data {
1218 NSXMLElement *sound = [self elementForName:@"SOUND"];
1219
1220 if (sound == nil) {
1221 sound = [NSXMLElement elementWithName:@"SOUND"];
1222 [self addChild:sound];
1223 }
1224
1225 NSXMLElement *binval = [sound elementForName:@"BINVAL"];
1226
1227 if (binval == nil) {
1228 binval = [NSXMLElement elementWithName:@"BINVAL"];
1229 [sound addChild:binval];
1230 }
1231
1232 [binval setStringValue:[data base64Encoded]];
1233}
1234
1235- (NSString *)uid {
1236 return [[self elementForName:@"UID"] stringValue];
1237}
1238- (void)setUid:(NSString *)uid {
1239 XMPP_VCARD_SET_STRING_CHILD(uid, @"UID");
1240}
1241
1242- (NSString *)url {
1243 return [[self elementForName:@"URL"] stringValue];
1244}
1245- (void)setUrl:(NSString *)url {
1246 XMPP_VCARD_SET_STRING_CHILD(url, @"URL");
1247}
1248
1249- (NSString *)version {
1250 return [self attributeStringValueForName:@"version"];
1251}
1252- (void)setVersion:(NSString *)version {
1253 [self addAttributeWithName:@"version" stringValue:version];
1254}
1255
1256- (NSString *)description {
1257 return [[self elementForName:@"DESC"] stringValue];
1258}
1259- (void)setDescription:(NSString *)desc {
1260 XMPP_VCARD_SET_STRING_CHILD(desc, @"DESC");
1261}
1262
1263#pragma mark Security Types
1264
1265- (XMPPvCardClass)privacyClass {
1266 XMPPvCardClass priv = XMPPvCardClassNone;
1267 NSXMLElement *elem = [self elementForName:@"CLASS"];
1268
1269 if (elem != nil) {
1270 if ([elem elementForName:@"PUBLIC"] != nil) {
1271 priv = XMPPvCardClassPublic;
1272 } else if ([elem elementForName:@"PRIVATE"] != nil) {
1273 priv = XMPPvCardClassPrivate;
1274 } else if ([elem elementForName:@"CONFIDENTIAL"] != nil) {
1275 priv = XMPPvCardClassConfidential;
1276 }
1277 }
1278
1279 return priv;
1280}
1281- (void)setPrivacyClass:(XMPPvCardClass)privacyClass {
1282 NSXMLElement *elem = [self elementForName:@"CLASS"];
1283
1284 if (elem == nil && privacyClass != XMPPvCardClassNone) {
1285 elem = [NSXMLElement elementWithName:@"CLASS"];
1286 }
1287
1288 if (elem != nil) {
1289 for (NSString *cls in [NSArray arrayWithObjects:@"PUBLIC", @"PRIVATE", @"CONFIDENTIAL", nil]) {
1290 NSXMLElement *priv = [elem elementForName:cls];
1291 if (priv != nil) {
1292 [elem removeChildAtIndex:[[elem children] indexOfObject:priv]];
1293 }
1294 }
1295
1296 switch (privacyClass) {
1297 case XMPPvCardClassPublic:
1298 [elem addChild:[NSXMLElement elementWithName:@"PUBLIC"]];
1299 break;
1300 case XMPPvCardClassPrivate:
1301 [elem addChild:[NSXMLElement elementWithName:@"PRIVATE"]];
1302 break;
1303 case XMPPvCardClassConfidential:
1304 [elem addChild:[NSXMLElement elementWithName:@"CONFIDENTIAL"]];
1305 break;
1306 default:
1307 case XMPPvCardClassNone:
1308 // Remove the whole element
1309 [self removeChildAtIndex:[[self children] indexOfObject:elem]];
1310 break;
1311 }
1312 }
1313}
1314
1315- (NSData *)key { return nil; }
1316- (void)setKey:(NSData *)key { }
1317
1318- (NSString *)keyType {
1319 NSString *typ = nil;
1320 NSXMLElement *key = [self elementForName:@"KEY"];
1321
1322 if (key != nil) {
1323 NSXMLElement *elem = [key elementForName:@"TYPE"];
1324
1325 if (elem != nil) {
1326 typ = [elem stringValue];
1327 }
1328 }
1329
1330 return typ;
1331}
1332- (void)setKeyType:(NSString *)type {
1333 NSXMLElement *key = [self elementForName:@"KEY"];
1334 NSXMLElement *elem;
1335
1336 if (key == nil && type != nil) {
1337 key = [NSXMLElement elementWithName:@"KEY"];
1338 [self addChild:key];
1339 }
1340
1341 if (key != nil) {
1342 elem = [key elementForName:@"TYPE"];
1343
1344 if (elem != nil && type != nil) {
1345 elem = [NSXMLElement elementWithName:@"TYPE"];
1346 [key addChild:elem];
1347 }
1348 }
1349
1350 if (type != nil) {
1351 [elem setStringValue:type];
1352 } else if (key != nil) {
1353 [self removeChildAtIndex:[[self children] indexOfObject:key]];
1354 }
1355}
1356
1357@end
1358

Subscribers

People subscribed via source and target branches

to all changes: