]> err.no Git - scalable-opengroupware.org/blob - SOPE/NGCards/NGCardsSaxHandler.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1178 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SOPE / NGCards / NGCardsSaxHandler.m
1 /*
2   Copyright (C) 2005 Helge Hess
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #import <string.h>
23 #import <Foundation/NSArray.h>
24 #import <Foundation/NSString.h>
25
26 #import "NGCardsSaxHandler.h"
27
28 #import "CardGroup.h"
29
30 #ifndef XMLNS_VCARD_XML_03
31 #  define XMLNS_VCARD_XML_03 \
32      @"http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-03.txt"
33 #endif
34
35 @implementation NGCardsSaxHandler
36
37 - (id) init
38 {
39   if ((self = [super init]))
40     topGroupClass = nil;
41
42   return self;
43 }
44
45 - (void) dealloc
46 {
47   if (content)
48     free (content);
49   [cards release];
50   [currentGroup release];
51   [super dealloc];
52 }
53
54 /* results */
55
56 - (NSArray *) cards
57 {
58   return [[cards copy] autorelease];;
59 }
60
61 /* state */
62
63 - (void) resetExceptResult
64 {
65   if (content)
66     {
67       free (content);
68       content = NULL;
69     }
70
71   vcs.isInVCardSet   = 0;
72   vcs.collectContent = 0;
73 }
74
75 - (void) reset
76 {
77   [self resetExceptResult];
78   [cards removeAllObjects];
79 }
80
81 /* document events */
82
83 - (void) startDocument
84 {
85   if (!cards)
86     cards = [[NSMutableArray alloc] initWithCapacity:16];
87   [self reset];
88 }
89
90 - (void) endDocument
91 {
92   [self resetExceptResult];
93 }
94
95 /* common tags */
96
97 - (void) startValueTag: (NSString *) _tag
98             attributes: (id<SaxAttributes>) _attrs
99 {
100   /* a tag with types and attributes */
101   unsigned i, count;
102   
103   [types removeAllObjects];
104   [args  removeAllObjects];
105   
106   for (i = 0, count = [_attrs count]; i < count; i++) {
107     NSString *n, *v;
108     
109     n = [_attrs nameAtIndex:i];
110     v = [_attrs valueAtIndex:i];
111     
112     if ([n hasSuffix:@".type"] || [n isEqualToString:@"TYPE"]) {
113       /*
114         Note: types cannot be separated by comma! Its indeed always a space,eg
115                 "work pref voice"
116               If you find commas, usually the vCard is broken.
117       */
118       NSEnumerator *e;
119       NSString *k;
120       
121       e = [[v componentsSeparatedByString:@" "] objectEnumerator];
122       while ((k = [e nextObject]) != nil) {
123         k = [k uppercaseString];
124         if ([types containsObject:k]) continue;
125         [types addObject:k];
126       }
127     }
128     else
129       [args setObject:v forKey:n];
130   }
131 }
132
133 - (void) endValueTag
134 {
135   [types removeAllObjects];
136   [args  removeAllObjects];
137 }
138
139 /* handle elements */
140
141 - (void) startGroup: (NSString *)_name
142 {
143   vcs.isInGroup = 1;
144   ASSIGNCOPY(currentGroup, _name);
145 }
146
147 - (void) endGroup
148 {
149   vcs.isInGroup = 0;
150   [currentGroup release];
151   currentGroup = nil;
152 }
153
154 - (void) startVCardSet
155 {
156   currentCardGroup = nil;
157   currentGroup = nil;
158   vcs.isInVCardSet = 1;
159 }
160
161 - (void) endVCardSet
162 {
163   vcs.isInVCardSet = 0;
164 }
165
166 /* element events */
167
168 - (void) startElement:(NSString *)_localName
169             namespace:(NSString *)_ns
170               rawName:(NSString *)_rawName
171            attributes:(id<SaxAttributes>)_attrs
172 {
173   unsigned int count, max;
174   Class elementClass;
175
176 //   NSLog (@"startElement localName: '%@'", _localName);
177
178   if ([_localName isEqualToString: @"vCardSet"])
179     [self startVCardSet];
180   else if ([_localName isEqualToString: @"group"])
181     [self startGroup: [_attrs valueAtIndex: 0]];
182   else if ([_localName isEqualToString: @"container"])
183     [self startGroupElement: [_attrs valueAtIndex: 0]];
184   else
185     {
186       if (currentCardGroup)
187         elementClass
188           = [currentCardGroup classForTag: [_localName uppercaseString]];
189       else
190         elementClass = topGroupClass;
191       
192       if (!elementClass)
193         elementClass = [CardElement class];
194
195       currentElement = [elementClass elementWithTag: _localName];
196       [currentElement setTag: _localName];
197       if (currentGroup)
198         [currentElement setGroup: currentGroup];
199
200       max = [_attrs count];
201       for (count = 0; count < max; count++)
202         [currentElement addAttribute: [_attrs nameAtIndex: count]
203                         value: [_attrs valueAtIndex: count]];
204
205       [currentCardGroup addChild: currentElement];
206       [self startCollectingContent];
207     }
208 }
209
210 - (void) endElement: (NSString *)_localName
211           namespace: (NSString *)_ns
212             rawName: (NSString *)_rawName
213 {
214 //   NSLog (@"endElement localName: '%@'", _localName);
215   if ([_localName isEqualToString: @"vCardSet"])
216     [self endVCardSet];
217   else if ([_localName isEqualToString: @"group"])
218     [self endGroup];
219   else if ([_localName isEqualToString: @"container"])
220     [self endGroupElement];
221   else
222     [currentElement addValues: [self finishCollectingContent]];
223 }
224
225 /* content */
226
227 - (void) startCollectingContent
228 {
229   if (content) {
230     free (content);
231     content = NULL;
232   }
233   vcs.collectContent = 1;
234 }
235
236 - (NSArray *) finishCollectingContent
237 {
238   NSArray *contentValues;
239   NSString *s;
240
241   vcs.collectContent = 0;
242
243   if (content && contentLength)
244     {
245       s = [NSString stringWithCharacters: content
246                     length: contentLength];
247       free (content);
248       content = NULL;
249 //       NSLog (@"content: '%@'", s);
250       contentValues = [s componentsSeparatedByString: @";"];
251     }
252   else
253     contentValues = nil;
254
255   return contentValues;
256 }
257
258 - (void) characters:(unichar *)_chars
259              length:(int)_len
260 {
261   if (_len && _chars)
262     {
263       if (!content)
264         {
265           /* first content */
266           contentLength = _len;
267           content = calloc (_len + 1, sizeof(unichar));
268           memcpy (content, _chars, (_len * sizeof(unichar)));
269         }
270       else
271         {
272           /* increase content */
273           content = 
274             realloc (content, (contentLength + _len+2) * sizeof(unichar));
275           memcpy (&(content[contentLength]), _chars, 
276                   (_len * sizeof(unichar)));
277           contentLength += _len;
278         }
279       content[contentLength] = 0;
280     }
281 }
282
283 - (void) startGroupElement: (NSString *) _localName
284 {
285   CardGroup *newGroup;
286   Class groupClass;
287
288 //   NSLog (@"startGroupElement localName: '%@'", _localName);
289
290   if (currentCardGroup)
291     {
292       groupClass
293         = [currentCardGroup classForTag: [_localName uppercaseString]];
294       if (!groupClass)
295         groupClass = [CardGroup class];
296
297       newGroup = [groupClass groupWithTag: _localName];
298       [currentCardGroup addChild: newGroup];
299     }
300   else
301     {
302       if (topGroupClass)
303         groupClass = topGroupClass;
304       else
305         groupClass = [CardGroup class];
306
307       newGroup = [groupClass groupWithTag: _localName];
308       [cards addObject: newGroup];
309     }
310
311   currentCardGroup = newGroup;
312 }
313
314 - (void) endGroupElement
315 {
316 //   NSLog (@"endGroupElement localName: '%@'", _localName);
317
318   if (currentCardGroup)
319     currentCardGroup = [currentCardGroup parent];
320 }
321
322 - (void) setTopElementClass: (Class) aGroupClass
323 {
324   topGroupClass = aGroupClass;
325 }
326
327 @end /* NGCardsSaxHandler */