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