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