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