summaryrefslogtreecommitdiffabout
path: root/libkcal/versit/vobject.c
Unidiff
Diffstat (limited to 'libkcal/versit/vobject.c') (more/less context) (show whitespace changes)
-rw-r--r--libkcal/versit/vobject.c297
1 files changed, 159 insertions, 138 deletions
diff --git a/libkcal/versit/vobject.c b/libkcal/versit/vobject.c
index 637efb2..3fac63e 100644
--- a/libkcal/versit/vobject.c
+++ b/libkcal/versit/vobject.c
@@ -21,434 +21,453 @@ ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
21MODIFICATIONS. 21MODIFICATIONS.
22 22
23IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 23IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
24INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 24INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
25OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 25OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26DAMAGE. 26DAMAGE.
27 27
28EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 28EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
29INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 29INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31PURPOSE. 31PURPOSE.
32 32
33The software is provided with RESTRICTED RIGHTS. Use, duplication, or 33The software is provided with RESTRICTED RIGHTS. Use, duplication, or
34disclosure by the government are subject to restrictions set forth in 34disclosure by the government are subject to restrictions set forth in
35DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 35DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
36 36
37***************************************************************************/ 37***************************************************************************/
38 38
39/* 39/*
40 * src: vobject.c 40 * src: vobject.c
41 * doc: vobject and APIs to construct vobject, APIs pretty print 41 * doc: vobject and APIs to construct vobject, APIs pretty print
42 * vobject, and convert a vobject into its textual representation. 42 * vobject, and convert a vobject into its textual representation.
43 */ 43 */
44 44
45#include <stdlib.h> 45#ifdef WIN32
46#define snprintf _snprintf
47#define strcasecmp stricmp
48#endif
46 49
47#include "vobject.h" 50#include "vobject.h"
51#include <stdlib.h>
48#include <string.h> 52#include <string.h>
49#include <stdio.h> 53#include <stdio.h>
50#ifdef _WIN32_ 54#include <fcntl.h>
51 55
52 #define strcasecmp _stricmp
53
54#endif
55 56
56 #define NAME_OF(o) o->id 57 #define NAME_OF(o) o->id
57 #define VALUE_TYPE(o) o->valType 58 #define VALUE_TYPE(o) o->valType
58 #define STRINGZ_VALUE_OF(o) o->val.strs 59 #define STRINGZ_VALUE_OF(o) o->val.strs
59 #define USTRINGZ_VALUE_OF(o)o->val.ustrs 60 #define USTRINGZ_VALUE_OF(o)o->val.ustrs
60 #define INTEGER_VALUE_OF(o) o->val.i 61 #define INTEGER_VALUE_OF(o) o->val.i
61 #define LONG_VALUE_OF(o) o->val.l 62 #define LONG_VALUE_OF(o) o->val.l
62 #define ANY_VALUE_OF(o) o->val.any 63 #define ANY_VALUE_OF(o) o->val.any
63 #define VOBJECT_VALUE_OF(o) o->val.vobj 64 #define VOBJECT_VALUE_OF(o) o->val.vobj
64 65
66typedef union ValueItem {
67 const char *strs;
68 const wchar_t *ustrs;
69 unsigned int i;
70 unsigned long l;
71 void *any;
72 VObject *vobj;
73 } ValueItem;
74
75struct VObject {
76 VObject *next;
77 const char *id;
78 VObject *prop;
79 unsigned short valType;
80 ValueItem val;
81 };
82
83typedef struct StrItem StrItem;
84
85struct StrItem {
86 StrItem *next;
87 const char *s;
88 unsigned int refCnt;
89 };
90
65const char** fieldedProp; 91const char** fieldedProp;
66 92
67 93
68 94
69/*---------------------------------------------------------------------- 95/*----------------------------------------------------------------------
70 The following functions involve with memory allocation: 96 The following functions involve with memory allocation:
71 newVObject 97 newVObject
72 deleteVObject 98 deleteVObject
73 dupStr 99 dupStr
74 deleteStr 100 deleteStr
75 newStrItem 101 newStrItem
76 deleteStrItem 102 deleteStrItem
77 ----------------------------------------------------------------------*/ 103 ----------------------------------------------------------------------*/
78 104
79VObject* newVObject_(const char *id) 105DLLEXPORT(VObject*) newVObject_(const char *id)
80{ 106{
81 VObject *p = (VObject*)malloc(sizeof(VObject)); 107 VObject *p = (VObject*)malloc(sizeof(VObject));
82 p->next = 0; 108 p->next = 0;
83 p->id = id; 109 p->id = id;
84 p->prop = 0; 110 p->prop = 0;
85 VALUE_TYPE(p) = 0; 111 VALUE_TYPE(p) = 0;
86 ANY_VALUE_OF(p) = 0; 112 ANY_VALUE_OF(p) = 0;
87 return p; 113 return p;
88} 114}
89 115
90VObject* newVObject(const char *id) 116DLLEXPORT(VObject*) newVObject(const char *id)
91{ 117{
92 return newVObject_(lookupStr(id)); 118 return newVObject_(lookupStr(id));
93} 119}
94 120
95void deleteVObject(VObject *p) 121DLLEXPORT(void) deleteVObject(VObject *p)
96{ 122{
97 if (p->id)
98 unUseStr(p->id); 123 unUseStr(p->id);
99 if (p)
100 free(p); 124 free(p);
101 p = NULL;
102} 125}
103 126
104char* dupStr(const char *s, unsigned int size) 127DLLEXPORT(char*) dupStr(const char *s, unsigned int size)
105{ 128{
106 char *t; 129 char *t;
107 if (size == 0) { 130 if (size == 0) {
108 size = strlen(s); 131 size = strlen(s);
109 } 132 }
110 t = (char*)malloc(size+1); 133 t = (char*)malloc(size+1);
111 if (t) { 134 if (t) {
112 memcpy(t,s,size); 135 memcpy(t,s,size);
113 t[size] = 0; 136 t[size] = 0;
114 return t; 137 return t;
115 } 138 }
116 else { 139 else {
117 return (char*)0; 140 return (char*)0;
118 } 141 }
119} 142}
120 143
121void deleteStr(const char *p) 144DLLEXPORT(void) deleteStr(const char *p)
122{ 145{
123 if (p) 146 if (p) free((void*)p);
124 free((void*)p);
125 p = NULL;
126} 147}
127 148
128 149
129static StrItem* newStrItem(const char *s, StrItem *next) 150static StrItem* newStrItem(const char *s, StrItem *next)
130{ 151{
131 StrItem *p = (StrItem*)malloc(sizeof(StrItem)); 152 StrItem *p = (StrItem*)malloc(sizeof(StrItem));
132 p->next = next; 153 p->next = next;
133 p->s = s; 154 p->s = s;
134 p->refCnt = 1; 155 p->refCnt = 1;
135 return p; 156 return p;
136} 157}
137 158
138static void deleteStrItem(StrItem *p) 159static void deleteStrItem(StrItem *p)
139{ 160{
140 if (p)
141 free((void*)p); 161 free((void*)p);
142 p = NULL;
143} 162}
144 163
145 164
146/*---------------------------------------------------------------------- 165/*----------------------------------------------------------------------
147 The following function provide accesses to VObject's value. 166 The following function provide accesses to VObject's value.
148 ----------------------------------------------------------------------*/ 167 ----------------------------------------------------------------------*/
149 168
150const char* vObjectName(VObject *o) 169DLLEXPORT(const char*) vObjectName(VObject *o)
151{ 170{
152 return NAME_OF(o); 171 return NAME_OF(o);
153} 172}
154 173
155void setVObjectName(VObject *o, const char* id) 174DLLEXPORT(void) setVObjectName(VObject *o, const char* id)
156{ 175{
157 NAME_OF(o) = id; 176 NAME_OF(o) = id;
158} 177}
159 178
160const char* vObjectStringZValue(VObject *o) 179DLLEXPORT(const char*) vObjectStringZValue(VObject *o)
161{ 180{
162 return STRINGZ_VALUE_OF(o); 181 return STRINGZ_VALUE_OF(o);
163} 182}
164 183
165void setVObjectStringZValue(VObject *o, const char *s) 184DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s)
166{ 185{
167 STRINGZ_VALUE_OF(o) = dupStr(s,0); 186 STRINGZ_VALUE_OF(o) = dupStr(s,0);
168 VALUE_TYPE(o) = VCVT_STRINGZ; 187 VALUE_TYPE(o) = VCVT_STRINGZ;
169} 188}
170 189
171void setVObjectStringZValue_(VObject *o, const char *s) 190DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s)
172{ 191{
173 STRINGZ_VALUE_OF(o) = s; 192 STRINGZ_VALUE_OF(o) = s;
174 VALUE_TYPE(o) = VCVT_STRINGZ; 193 VALUE_TYPE(o) = VCVT_STRINGZ;
175} 194}
176 195
177const wchar_t* vObjectUStringZValue(VObject *o) 196DLLEXPORT(const wchar_t*) vObjectUStringZValue(VObject *o)
178{ 197{
179 return USTRINGZ_VALUE_OF(o); 198 return USTRINGZ_VALUE_OF(o);
180} 199}
181 200
182void setVObjectUStringZValue(VObject *o, const wchar_t *s) 201DLLEXPORT(void) setVObjectUStringZValue(VObject *o, const wchar_t *s)
183{ 202{
184 USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2); 203 USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2);
185 VALUE_TYPE(o) = VCVT_USTRINGZ; 204 VALUE_TYPE(o) = VCVT_USTRINGZ;
186} 205}
187 206
188void setVObjectUStringZValue_(VObject *o, const wchar_t *s) 207DLLEXPORT(void) setVObjectUStringZValue_(VObject *o, const wchar_t *s)
189{ 208{
190 USTRINGZ_VALUE_OF(o) = s; 209 USTRINGZ_VALUE_OF(o) = s;
191 VALUE_TYPE(o) = VCVT_USTRINGZ; 210 VALUE_TYPE(o) = VCVT_USTRINGZ;
192} 211}
193 212
194unsigned int vObjectIntegerValue(VObject *o) 213DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o)
195{ 214{
196 return INTEGER_VALUE_OF(o); 215 return INTEGER_VALUE_OF(o);
197} 216}
198 217
199void setVObjectIntegerValue(VObject *o, unsigned int i) 218DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i)
200{ 219{
201 INTEGER_VALUE_OF(o) = i; 220 INTEGER_VALUE_OF(o) = i;
202 VALUE_TYPE(o) = VCVT_UINT; 221 VALUE_TYPE(o) = VCVT_UINT;
203} 222}
204 223
205unsigned long vObjectLongValue(VObject *o) 224DLLEXPORT(unsigned long) vObjectLongValue(VObject *o)
206{ 225{
207 return LONG_VALUE_OF(o); 226 return LONG_VALUE_OF(o);
208} 227}
209 228
210void setVObjectLongValue(VObject *o, unsigned long l) 229DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l)
211{ 230{
212 LONG_VALUE_OF(o) = l; 231 LONG_VALUE_OF(o) = l;
213 VALUE_TYPE(o) = VCVT_ULONG; 232 VALUE_TYPE(o) = VCVT_ULONG;
214} 233}
215 234
216void* vObjectAnyValue(VObject *o) 235DLLEXPORT(void*) vObjectAnyValue(VObject *o)
217{ 236{
218 return ANY_VALUE_OF(o); 237 return ANY_VALUE_OF(o);
219} 238}
220 239
221void setVObjectAnyValue(VObject *o, void *t) 240DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t)
222{ 241{
223 ANY_VALUE_OF(o) = t; 242 ANY_VALUE_OF(o) = t;
224 VALUE_TYPE(o) = VCVT_RAW; 243 VALUE_TYPE(o) = VCVT_RAW;
225} 244}
226 245
227VObject* vObjectVObjectValue(VObject *o) 246DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o)
228{ 247{
229 return VOBJECT_VALUE_OF(o); 248 return VOBJECT_VALUE_OF(o);
230} 249}
231 250
232void setVObjectVObjectValue(VObject *o, VObject *p) 251DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p)
233{ 252{
234 VOBJECT_VALUE_OF(o) = p; 253 VOBJECT_VALUE_OF(o) = p;
235 VALUE_TYPE(o) = VCVT_VOBJECT; 254 VALUE_TYPE(o) = VCVT_VOBJECT;
236} 255}
237 256
238int vObjectValueType(VObject *o) 257DLLEXPORT(int) vObjectValueType(VObject *o)
239{ 258{
240 return VALUE_TYPE(o); 259 return VALUE_TYPE(o);
241} 260}
242 261
243 262
244/*---------------------------------------------------------------------- 263/*----------------------------------------------------------------------
245 The following functions can be used to build VObject. 264 The following functions can be used to build VObject.
246 ----------------------------------------------------------------------*/ 265 ----------------------------------------------------------------------*/
247 266
248VObject* addVObjectProp(VObject *o, VObject *p) 267DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p)
249{ 268{
250 /* circular link list pointed to tail */ 269 /* circular link list pointed to tail */
251 /* 270 /*
252 o {next,id,prop,val} 271 o {next,id,prop,val}
253 V 272 V
254 pn {next,id,prop,val} 273 pn {next,id,prop,val}
255 V 274 V
256 ... 275 ...
257 p1 {next,id,prop,val} 276 p1 {next,id,prop,val}
258 V 277 V
259 pn 278 pn
260 --> 279 -->
261 o {next,id,prop,val} 280 o {next,id,prop,val}
262 V 281 V
263 pn {next,id,prop,val} 282 pn {next,id,prop,val}
264 V 283 V
265 p {next,id,prop,val} 284 p {next,id,prop,val}
266 ... 285 ...
267 p1 {next,id,prop,val} 286 p1 {next,id,prop,val}
268 V 287 V
269 pn 288 pn
270 */ 289 */
271 290
272 VObject *tail = o->prop; 291 VObject *tail = o->prop;
273 if (tail) { 292 if (tail) {
274 p->next = tail->next; 293 p->next = tail->next;
275 o->prop = tail->next = p; 294 o->prop = tail->next = p;
276 } 295 }
277 else { 296 else {
278 o->prop = p->next = p; 297 o->prop = p->next = p;
279 } 298 }
280 return p; 299 return p;
281} 300}
282 301
283VObject* addProp(VObject *o, const char *id) 302DLLEXPORT(VObject*) addProp(VObject *o, const char *id)
284{ 303{
285 return addVObjectProp(o,newVObject(id)); 304 return addVObjectProp(o,newVObject(id));
286} 305}
287 306
288VObject* addProp_(VObject *o, const char *id) 307DLLEXPORT(VObject*) addProp_(VObject *o, const char *id)
289{ 308{
290 return addVObjectProp(o,newVObject_(id)); 309 return addVObjectProp(o,newVObject_(id));
291} 310}
292 311
293void addList(VObject **o, VObject *p) 312DLLEXPORT(void) addList(VObject **o, VObject *p)
294{ 313{
295 p->next = 0; 314 p->next = 0;
296 if (*o == 0) { 315 if (*o == 0) {
297 *o = p; 316 *o = p;
298 } 317 }
299 else { 318 else {
300 VObject *t = *o; 319 VObject *t = *o;
301 while (t->next) { 320 while (t->next) {
302 t = t->next; 321 t = t->next;
303 } 322 }
304 t->next = p; 323 t->next = p;
305 } 324 }
306} 325}
307 326
308VObject* nextVObjectInList(VObject *o) 327DLLEXPORT(VObject*) nextVObjectInList(VObject *o)
309{ 328{
310 return o->next; 329 return o->next;
311} 330}
312 331
313VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size) 332DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size)
314{ 333{
315 VObject *sizeProp; 334 VObject *sizeProp;
316 setVObjectAnyValue(prop, val); 335 setVObjectAnyValue(prop, val);
317 sizeProp = addProp(prop,VCDataSizeProp); 336 sizeProp = addProp(prop,VCDataSizeProp);
318 setVObjectLongValue(sizeProp, size); 337 setVObjectLongValue(sizeProp, size);
319 return prop; 338 return prop;
320} 339}
321 340
322VObject* setValueWithSize(VObject *prop, void *val, unsigned int size) 341DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size)
323{ 342{
324 void *p = dupStr(val,size); 343 void *p = dupStr((const char *)val,size);
325 return setValueWithSize_(prop,p,p?size:0); 344 return setValueWithSize_(prop,p,p?size:0);
326} 345}
327 346
328void initPropIterator(VObjectIterator *i, VObject *o) 347DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o)
329{ 348{
330 i->start = o->prop; 349 i->start = o->prop;
331 i->next = 0; 350 i->next = 0;
332} 351}
333 352
334void initVObjectIterator(VObjectIterator *i, VObject *o) 353DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o)
335{ 354{
336 i->start = o->next; 355 i->start = o->next;
337 i->next = 0; 356 i->next = 0;
338} 357}
339 358
340int moreIteration(VObjectIterator *i) 359DLLEXPORT(int) moreIteration(VObjectIterator *i)
341{ 360{
342 return (i->start && (i->next==0 || i->next!=i->start)); 361 return (i->start && (i->next==0 || i->next!=i->start));
343} 362}
344 363
345VObject* nextVObject(VObjectIterator *i) 364DLLEXPORT(VObject*) nextVObject(VObjectIterator *i)
346{ 365{
347 if (i->start && i->next != i->start) { 366 if (i->start && i->next != i->start) {
348 if (i->next == 0) { 367 if (i->next == 0) {
349 i->next = i->start->next; 368 i->next = i->start->next;
350 return i->next; 369 return i->next;
351 } 370 }
352 else { 371 else {
353 i->next = i->next->next; 372 i->next = i->next->next;
354 return i->next; 373 return i->next;
355 } 374 }
356 } 375 }
357 else return (VObject*)0; 376 else return (VObject*)0;
358} 377}
359 378
360VObject* isAPropertyOf(VObject *o, const char *id) 379DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id)
361{ 380{
362 VObjectIterator i; 381 VObjectIterator i;
363 initPropIterator(&i,o); 382 initPropIterator(&i,o);
364 while (moreIteration(&i)) { 383 while (moreIteration(&i)) {
365 VObject *each = nextVObject(&i); 384 VObject *each = nextVObject(&i);
366 if (!strcasecmp(id,each->id)) 385 if (!stricmp(id,each->id))
367 return each; 386 return each;
368 } 387 }
369 return (VObject*)0; 388 return (VObject*)0;
370} 389}
371 390
372VObject* addGroup(VObject *o, const char *g) 391DLLEXPORT(VObject*) addGroup(VObject *o, const char *g)
373{ 392{
374 /* 393 /*
375 a.b.c 394 a.b.c
376 --> 395 -->
377 prop(c) 396 prop(c)
378 prop(VCGrouping=b) 397 prop(VCGrouping=b)
379 prop(VCGrouping=a) 398 prop(VCGrouping=a)
380 */ 399 */
381 char *dot = strrchr(g,'.'); 400 char *dot = strrchr(g,'.');
382 if (dot) { 401 if (dot) {
383 VObject *p, *t; 402 VObject *p, *t;
384 char *gs, *n = dot+1; 403 char *gs, *n = dot+1;
385 gs = dupStr(g,0);/* so we can write to it. */ 404 gs = dupStr(g,0);/* so we can write to it. */
386 /* used to be 405 /* used to be
387 * t = p = addProp_(o,lookupProp_(n)); 406 * t = p = addProp_(o,lookupProp_(n));
388 */ 407 */
389 t = p = addProp_(o,lookupProp(n)); 408 t = p = addProp_(o,lookupProp(n));
390 dot = strrchr(gs,'.'); 409 dot = strrchr(gs,'.');
391 *dot = 0; 410 *dot = 0;
392 do { 411 do {
393 dot = strrchr(gs,'.'); 412 dot = strrchr(gs,'.');
394 if (dot) { 413 if (dot) {
395 n = dot+1; 414 n = dot+1;
396 *dot=0; 415 *dot=0;
397 } 416 }
398 else 417 else
399 n = gs; 418 n = gs;
400 /* property(VCGroupingProp=n); 419 /* property(VCGroupingProp=n);
401 *and the value may have VCGrouping property 420 *and the value may have VCGrouping property
402 */ 421 */
403 t = addProp(t,VCGroupingProp); 422 t = addProp(t,VCGroupingProp);
404 setVObjectStringZValue(t,lookupProp_(n)); 423 setVObjectStringZValue(t,lookupProp_(n));
405 } while (n != gs); 424 } while (n != gs);
406 deleteStr(gs); 425 deleteStr(gs);
407 return p; 426 return p;
408 } 427 }
409 else 428 else
410 return addProp_(o,lookupProp(g)); 429 return addProp_(o,lookupProp(g));
411} 430}
412 431
413VObject* addPropValue(VObject *o, const char *p, const char *v) 432DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v)
414{ 433{
415 VObject *prop; 434 VObject *prop;
416 prop = addProp(o,p); 435 prop = addProp(o,p);
417 setVObjectUStringZValue_(prop, fakeUnicode(v,0)); 436 setVObjectUStringZValue_(prop, fakeUnicode(v,0));
418 return prop; 437 return prop;
419} 438}
420 439
421VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, 440DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v,
422 unsigned int size) 441 unsigned int size)
423{ 442{
424 VObject *prop; 443 VObject *prop;
425 prop = addProp(o,p); 444 prop = addProp(o,p);
426 setValueWithSize_(prop, (void*)v, size); 445 setValueWithSize_(prop, (void*)v, size);
427 return prop; 446 return prop;
428} 447}
429 448
430VObject* addPropSizedValue(VObject *o, const char *p, const char *v, 449DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v,
431 unsigned int size) 450 unsigned int size)
432{ 451{
433 return addPropSizedValue_(o,p,dupStr(v,size),size); 452 return addPropSizedValue_(o,p,dupStr(v,size),size);
434} 453}
435 454
436 455
437 456
438/*---------------------------------------------------------------------- 457/*----------------------------------------------------------------------
439 The following pretty print a VObject 458 The following pretty print a VObject
440 ----------------------------------------------------------------------*/ 459 ----------------------------------------------------------------------*/
441 460
442static void printVObject_(FILE *fp, VObject *o, int level); 461static void printVObject_(FILE *fp, VObject *o, int level);
443 462
444static void indent(FILE *fp, int level) 463static void indent(FILE *fp, int level)
445{ 464{
446 int i; 465 int i;
447 for (i=0;i<level*4;i++) { 466 for (i=0;i<level*4;i++) {
448 fputc(' ', fp); 467 fputc(' ', fp);
449 } 468 }
450} 469}
451 470
452static void printValue(FILE *fp, VObject *o, int level) 471static void printValue(FILE *fp, VObject *o, int level)
453{ 472{
454 switch (VALUE_TYPE(o)) { 473 switch (VALUE_TYPE(o)) {
@@ -507,191 +526,187 @@ static void printNameValue(FILE *fp,VObject *o, int level)
507 } 526 }
508 fprintf(fp,"\n"); 527 fprintf(fp,"\n");
509} 528}
510 529
511static void printVObject_(FILE *fp, VObject *o, int level) 530static void printVObject_(FILE *fp, VObject *o, int level)
512 { 531 {
513 VObjectIterator t; 532 VObjectIterator t;
514 if (o == 0) { 533 if (o == 0) {
515 fprintf(fp,"[NULL]\n"); 534 fprintf(fp,"[NULL]\n");
516 return; 535 return;
517 } 536 }
518 printNameValue(fp,o,level); 537 printNameValue(fp,o,level);
519 initPropIterator(&t,o); 538 initPropIterator(&t,o);
520 while (moreIteration(&t)) { 539 while (moreIteration(&t)) {
521 VObject *eachProp = nextVObject(&t); 540 VObject *eachProp = nextVObject(&t);
522 printVObject_(fp,eachProp,level+1); 541 printVObject_(fp,eachProp,level+1);
523 } 542 }
524 } 543 }
525 544
526void printVObject(FILE *fp,VObject *o) 545void printVObject(FILE *fp,VObject *o)
527{ 546{
528 printVObject_(fp,o,0); 547 printVObject_(fp,o,0);
529} 548}
530 549
531void printVObjectToFile(char *fname,VObject *o) 550DLLEXPORT(void) printVObjectToFile(char *fname,VObject *o)
532{ 551{
533 FILE *fp = fopen(fname,"w"); 552 FILE *fp = fopen(fname,"w");
534 if (fp) { 553 if (fp) {
535 printVObject(fp,o); 554 printVObject(fp,o);
536 fclose(fp); 555 fclose(fp);
537 } 556 }
538} 557}
539 558
540void printVObjectsToFile(char *fname,VObject *list) 559DLLEXPORT(void) printVObjectsToFile(char *fname,VObject *list)
541{ 560{
542 FILE *fp = fopen(fname,"w"); 561 FILE *fp = fopen(fname,"w");
543 if (fp) { 562 if (fp) {
544 while (list) { 563 while (list) {
545 printVObject(fp,list); 564 printVObject(fp,list);
546 list = nextVObjectInList(list); 565 list = nextVObjectInList(list);
547 } 566 }
548 fclose(fp); 567 fclose(fp);
549 } 568 }
550} 569}
551 570
552void cleanVObject(VObject *o) 571DLLEXPORT(void) cleanVObject(VObject *o)
553{ 572{
554 if (o == 0) return; 573 if (o == 0) return;
555 if (o->prop) { 574 if (o->prop) {
556 /* destroy time: cannot use the iterator here. 575 /* destroy time: cannot use the iterator here.
557 Have to break the cycle in the circular link 576 Have to break the cycle in the circular link
558 list and turns it into regular NULL-terminated 577 list and turns it into regular NULL-terminated
559 list -- since at some point of destruction, 578 list -- since at some point of destruction,
560 the reference entry for the iterator to work 579 the reference entry for the iterator to work
561 will not longer be valid. 580 will not longer be valid.
562 */ 581 */
563 VObject *p; 582 VObject *p;
564 p = o->prop->next; 583 p = o->prop->next;
565 o->prop->next = 0; 584 o->prop->next = 0;
566 do { 585 do {
567 VObject *t = p->next; 586 VObject *t = p->next;
568 cleanVObject(p); 587 cleanVObject(p);
569 p = t; 588 p = t;
570 } while (p); 589 } while (p);
571 } 590 }
572 switch (VALUE_TYPE(o)) { 591 switch (VALUE_TYPE(o)) {
573 case VCVT_USTRINGZ: 592 case VCVT_USTRINGZ:
574 case VCVT_STRINGZ: 593 case VCVT_STRINGZ:
575 case VCVT_RAW: 594 case VCVT_RAW:
576 /* assume they are all allocated by malloc. */ 595 /* assume they are all allocated by malloc. */
577 free((char*)STRINGZ_VALUE_OF(o)); 596 free((char*)STRINGZ_VALUE_OF(o));
578 break; 597 break;
579 case VCVT_VOBJECT: 598 case VCVT_VOBJECT:
580 cleanVObject(VOBJECT_VALUE_OF(o)); 599 cleanVObject(VOBJECT_VALUE_OF(o));
581 break; 600 break;
582 } 601 }
583 deleteVObject(o); 602 deleteVObject(o);
584} 603}
585 604
586void cleanVObjects(VObject *list) 605DLLEXPORT(void) cleanVObjects(VObject *list)
587{ 606{
588 while (list) { 607 while (list) {
589 VObject *t = list; 608 VObject *t = list;
590 list = nextVObjectInList(list); 609 list = nextVObjectInList(list);
591 cleanVObject(t); 610 cleanVObject(t);
592 } 611 }
593} 612}
594 613
595/*---------------------------------------------------------------------- 614/*----------------------------------------------------------------------
596 The following is a String Table Facilities. 615 The following is a String Table Facilities.
597 ----------------------------------------------------------------------*/ 616 ----------------------------------------------------------------------*/
598 617
599#define STRTBLSIZE 255 618#define STRTBLSIZE 255
600 619
601static StrItem *strTbl[STRTBLSIZE]; 620static StrItem *strTbl[STRTBLSIZE];
602 621
603static unsigned int hashStr(const char *s) 622static unsigned int hashStr(const char *s)
604{ 623{
605 unsigned int h = 0; 624 unsigned int h = 0;
606 int i; 625 int i;
607 for (i=0;s[i];i++) { 626 for (i=0;s[i];i++) {
608 h += s[i]*i; 627 h += s[i]*i;
609 } 628 }
610 return h % STRTBLSIZE; 629 return h % STRTBLSIZE;
611} 630}
612 631
613const char* lookupStr(const char *s) 632DLLEXPORT(const char*) lookupStr(const char *s)
614{ 633{
615 char *newS;
616
617 StrItem *t; 634 StrItem *t;
618 unsigned int h = hashStr(s); 635 unsigned int h = hashStr(s);
619 if ((t = strTbl[h]) != 0) { 636 if ((t = strTbl[h]) != 0) {
620 do { 637 do {
621 if (strcasecmp(t->s,s) == 0) { 638 if (stricmp(t->s,s) == 0) {
622 t->refCnt++; 639 t->refCnt++;
623 return t->s; 640 return t->s;
624 } 641 }
625 t = t->next; 642 t = t->next;
626 } while (t); 643 } while (t);
627 } 644 }
628 newS = dupStr(s,0); 645 s = dupStr(s,0);
629 strTbl[h] = newStrItem(newS,strTbl[h]); 646 strTbl[h] = newStrItem(s,strTbl[h]);
630 return newS; 647 return s;
631} 648}
632 649
633void unUseStr(const char *s) 650DLLEXPORT(void) unUseStr(const char *s)
634{ 651{
635 StrItem *cur, *prev; 652 StrItem *t, *p;
636
637 unsigned int h = hashStr(s); 653 unsigned int h = hashStr(s);
638 cur = strTbl[h]; 654 if ((t = strTbl[h]) != 0) {
639 prev = cur; 655 p = t;
640 while (cur != 0) { 656 do {
641 if (strcasecmp(cur->s,s) == 0) { 657 if (stricmp(t->s,s) == 0) {
642 cur->refCnt--; 658 t->refCnt--;
643 /* if that was the last reference to this string, kill it. */ 659 if (t->refCnt == 0) {
644 if (cur->refCnt == 0) { 660 if (p == strTbl[h]) {
645 if (cur == strTbl[h]) { 661 strTbl[h] = t->next;
646 strTbl[h] = cur->next; 662 }
647 deleteStr(prev->s); 663 else {
648 deleteStrItem(prev); 664 p->next = t->next;
649 } else {
650 prev->next = cur->next;
651 deleteStr(cur->s);
652 deleteStrItem(cur);
653 } 665 }
666 deleteStr(t->s);
667 deleteStrItem(t);
654 return; 668 return;
655 } 669 }
656 } 670 }
657 prev = cur; 671 p = t;
658 cur = cur->next; 672 t = t->next;
673 } while (t);
659 } 674 }
660} 675}
661 676
662void cleanStrTbl() 677DLLEXPORT(void) cleanStrTbl()
663{ 678{
664 int i; 679 int i;
665 for (i=0; i<STRTBLSIZE;i++) { 680 for (i=0; i<STRTBLSIZE;i++) {
666 StrItem *t = strTbl[i]; 681 StrItem *t = strTbl[i];
667 while (t) { 682 while (t) {
668 StrItem *p; 683 StrItem *p;
669 deleteStr(t->s); 684 deleteStr(t->s);
670 p = t; 685 p = t;
671 t = t->next; 686 t = t->next;
672 deleteStrItem(p); 687 deleteStrItem(p);
673 } 688 } while (t);
674 strTbl[i] = 0; 689 strTbl[i] = 0;
675 } 690 }
676} 691}
677 692
678 693
679struct PreDefProp { 694struct PreDefProp {
680 const char *name; 695 const char *name;
681 const char *alias; 696 const char *alias;
682 const char** fields; 697 const char** fields;
683 unsigned int flags; 698 unsigned int flags;
684 }; 699 };
685 700
686/* flags in PreDefProp */ 701/* flags in PreDefProp */
687 #define PD_BEGIN0x1 702 #define PD_BEGIN0x1
688 #define PD_INTERNAL0x2 703 #define PD_INTERNAL0x2
689 704
690static const char *adrFields[] = { 705static const char *adrFields[] = {
691 VCPostalBoxProp, 706 VCPostalBoxProp,
692 VCExtAddressProp, 707 VCExtAddressProp,
693 VCStreetAddressProp, 708 VCStreetAddressProp,
694 VCCityProp, 709 VCCityProp,
695 VCRegionProp, 710 VCRegionProp,
696 VCPostalCodeProp, 711 VCPostalCodeProp,
697 VCCountryNameProp, 712 VCCountryNameProp,
@@ -786,49 +801,49 @@ static struct PreDefProp propNames[] = {
786 { VCCityProp, 0, 0, 0 }, 801 { VCCityProp, 0, 0, 0 },
787 { VCClassProp, 0, 0, 0 }, 802 { VCClassProp, 0, 0, 0 },
788 { VCCommentProp, 0, 0, 0 }, 803 { VCCommentProp, 0, 0, 0 },
789 { VCCompletedProp, 0, 0, 0 }, 804 { VCCompletedProp, 0, 0, 0 },
790 { VCContentIDProp, 0, 0, 0 }, 805 { VCContentIDProp, 0, 0, 0 },
791 { VCCountryNameProp, 0, 0, 0 }, 806 { VCCountryNameProp, 0, 0, 0 },
792 { VCDAlarmProp, 0, DAlarmFields, 0 }, 807 { VCDAlarmProp, 0, DAlarmFields, 0 },
793 { VCDataSizeProp, 0, 0, PD_INTERNAL }, 808 { VCDataSizeProp, 0, 0, PD_INTERNAL },
794 { VCDayLightProp, 0, 0, 0 }, 809 { VCDayLightProp, 0, 0, 0 },
795 { VCDCreatedProp, 0, 0, 0 }, 810 { VCDCreatedProp, 0, 0, 0 },
796 { VCDeliveryLabelProp, 0, 0, 0 }, 811 { VCDeliveryLabelProp, 0, 0, 0 },
797 { VCDescriptionProp, 0, 0, 0 }, 812 { VCDescriptionProp, 0, 0, 0 },
798 { VCDIBProp, 0, 0, 0 }, 813 { VCDIBProp, 0, 0, 0 },
799 { VCDisplayStringProp, 0, 0, 0 }, 814 { VCDisplayStringProp, 0, 0, 0 },
800 { VCDomesticProp, 0, 0, 0 }, 815 { VCDomesticProp, 0, 0, 0 },
801 { VCDTendProp, 0, 0, 0 }, 816 { VCDTendProp, 0, 0, 0 },
802 { VCDTstartProp, 0, 0, 0 }, 817 { VCDTstartProp, 0, 0, 0 },
803 { VCDueProp, 0, 0, 0 }, 818 { VCDueProp, 0, 0, 0 },
804 { VCEmailAddressProp, 0, 0, 0 }, 819 { VCEmailAddressProp, 0, 0, 0 },
805 { VCEncodingProp, 0, 0, 0 }, 820 { VCEncodingProp, 0, 0, 0 },
806 { VCEndProp, 0, 0, 0 }, 821 { VCEndProp, 0, 0, 0 },
807 { VCEventProp, 0, 0, PD_BEGIN }, 822 { VCEventProp, 0, 0, PD_BEGIN },
808 { VCEWorldProp, 0, 0, 0 }, 823 { VCEWorldProp, 0, 0, 0 },
809 { VCExNumProp, 0, 0, 0 }, 824 { VCExNumProp, 0, 0, 0 },
810 { VCExDateProp, 0, 0, 0 }, 825 { VCExpDateProp, 0, 0, 0 },
811 { VCExpectProp, 0, 0, 0 }, 826 { VCExpectProp, 0, 0, 0 },
812 { VCExtAddressProp, 0, 0, 0 }, 827 { VCExtAddressProp, 0, 0, 0 },
813 { VCFamilyNameProp, 0, 0, 0 }, 828 { VCFamilyNameProp, 0, 0, 0 },
814 { VCFaxProp, 0, 0, 0 }, 829 { VCFaxProp, 0, 0, 0 },
815 { VCFullNameProp, 0, 0, 0 }, 830 { VCFullNameProp, 0, 0, 0 },
816 { VCGeoLocationProp, 0, 0, 0 }, 831 { VCGeoLocationProp, 0, 0, 0 },
817 { VCGeoProp, 0, 0, 0 }, 832 { VCGeoProp, 0, 0, 0 },
818 { VCGIFProp, 0, 0, 0 }, 833 { VCGIFProp, 0, 0, 0 },
819 { VCGivenNameProp, 0, 0, 0 }, 834 { VCGivenNameProp, 0, 0, 0 },
820 { VCGroupingProp, 0, 0, 0 }, 835 { VCGroupingProp, 0, 0, 0 },
821 { VCHomeProp, 0, 0, 0 }, 836 { VCHomeProp, 0, 0, 0 },
822 { VCIBMMailProp, 0, 0, 0 }, 837 { VCIBMMailProp, 0, 0, 0 },
823 { VCInlineProp, 0, 0, 0 }, 838 { VCInlineProp, 0, 0, 0 },
824 { VCInternationalProp, 0, 0, 0 }, 839 { VCInternationalProp, 0, 0, 0 },
825 { VCInternetProp, 0, 0, 0 }, 840 { VCInternetProp, 0, 0, 0 },
826 { VCISDNProp, 0, 0, 0 }, 841 { VCISDNProp, 0, 0, 0 },
827 { VCJPEGProp, 0, 0, 0 }, 842 { VCJPEGProp, 0, 0, 0 },
828 { VCLanguageProp, 0, 0, 0 }, 843 { VCLanguageProp, 0, 0, 0 },
829 { VCLastModifiedProp, 0, 0, 0 }, 844 { VCLastModifiedProp, 0, 0, 0 },
830 { VCLastRevisedProp, 0, 0, 0 }, 845 { VCLastRevisedProp, 0, 0, 0 },
831 { VCLocationProp, 0, 0, 0 }, 846 { VCLocationProp, 0, 0, 0 },
832 { VCLogoProp, 0, 0, 0 }, 847 { VCLogoProp, 0, 0, 0 },
833 { VCMailerProp, 0, 0, 0 }, 848 { VCMailerProp, 0, 0, 0 },
834 { VCMAlarmProp, 0, MAlarmFields, 0 }, 849 { VCMAlarmProp, 0, MAlarmFields, 0 },
@@ -900,162 +915,153 @@ static struct PreDefProp propNames[] = {
900 { VCTranspProp, 0, 0, 0 }, 915 { VCTranspProp, 0, 0, 0 },
901 { VCUniqueStringProp, 0, 0, 0 }, 916 { VCUniqueStringProp, 0, 0, 0 },
902 { VCURLProp, 0, 0, 0 }, 917 { VCURLProp, 0, 0, 0 },
903 { VCURLValueProp, 0, 0, 0 }, 918 { VCURLValueProp, 0, 0, 0 },
904 { VCValueProp, 0, 0, 0 }, 919 { VCValueProp, 0, 0, 0 },
905 { VCVersionProp, 0, 0, 0 }, 920 { VCVersionProp, 0, 0, 0 },
906 { VCVideoProp, 0, 0, 0 }, 921 { VCVideoProp, 0, 0, 0 },
907 { VCVoiceProp, 0, 0, 0 }, 922 { VCVoiceProp, 0, 0, 0 },
908 { VCWAVEProp, 0, 0, 0 }, 923 { VCWAVEProp, 0, 0, 0 },
909 { VCWMFProp, 0, 0, 0 }, 924 { VCWMFProp, 0, 0, 0 },
910 { VCWorkProp, 0, 0, 0 }, 925 { VCWorkProp, 0, 0, 0 },
911 { VCX400Prop, 0, 0, 0 }, 926 { VCX400Prop, 0, 0, 0 },
912 { VCX509Prop, 0, 0, 0 }, 927 { VCX509Prop, 0, 0, 0 },
913 { VCXRuleProp, 0, 0, 0 }, 928 { VCXRuleProp, 0, 0, 0 },
914 { 0,0,0,0 } 929 { 0,0,0,0 }
915 }; 930 };
916 931
917 932
918static struct PreDefProp* lookupPropInfo(const char* str) 933static struct PreDefProp* lookupPropInfo(const char* str)
919{ 934{
920 /* brute force for now, could use a hash table here. */ 935 /* brute force for now, could use a hash table here. */
921 int i; 936 int i;
922 937
923 for (i = 0; propNames[i].name; i++) 938 for (i = 0; propNames[i].name; i++)
924 if (strcasecmp(str, propNames[i].name) == 0) { 939 if (stricmp(str, propNames[i].name) == 0) {
925 return &propNames[i]; 940 return &propNames[i];
926 } 941 }
927 942
928 return 0; 943 return 0;
929} 944}
930 945
931 946
932const char* lookupProp_(const char* str) 947DLLEXPORT(const char*) lookupProp_(const char* str)
933{ 948{
934 int i; 949 int i;
935 950
936 for (i = 0; propNames[i].name; i++) 951 for (i = 0; propNames[i].name; i++)
937 if (strcasecmp(str, propNames[i].name) == 0) { 952 if (stricmp(str, propNames[i].name) == 0) {
938 const char* s; 953 const char* s;
939 s = propNames[i].alias?propNames[i].alias:propNames[i].name; 954 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
940 return lookupStr(s); 955 return lookupStr(s);
941 } 956 }
942 return lookupStr(str); 957 return lookupStr(str);
943} 958}
944 959
945 960
946const char* lookupProp(const char* str) 961DLLEXPORT(const char*) lookupProp(const char* str)
947{ 962{
948 int i; 963 int i;
949 964
950 for (i = 0; propNames[i].name; i++) 965 for (i = 0; propNames[i].name; i++)
951 if (strcasecmp(str, propNames[i].name) == 0) { 966 if (stricmp(str, propNames[i].name) == 0) {
952 const char *s; 967 const char *s;
953 fieldedProp = propNames[i].fields; 968 fieldedProp = propNames[i].fields;
954 s = propNames[i].alias?propNames[i].alias:propNames[i].name; 969 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
955 return lookupStr(s); 970 return lookupStr(s);
956 } 971 }
957 fieldedProp = 0; 972 fieldedProp = 0;
958 return lookupStr(str); 973 return lookupStr(str);
959} 974}
960 975
961 976
962/*---------------------------------------------------------------------- 977/*----------------------------------------------------------------------
963 APIs to Output text form. 978 APIs to Output text form.
964 ----------------------------------------------------------------------*/ 979 ----------------------------------------------------------------------*/
965#define OFILE_REALLOC_SIZE 256 980#define OFILE_REALLOC_SIZE 256
966typedef struct OFile { 981typedef struct OFile {
967 FILE *fp; 982 FILE *fp;
968 char *s; 983 char *s;
969 int len; 984 int len;
970 int limit; 985 int limit;
971 int alloc:1; 986 int alloc:1;
972 int fail:1; 987 int fail:1;
973 } OFile; 988 } OFile;
974 989
975
976/* vCalendar files need crlf linebreaks. The disabled functions didn't provide
977 that. */
978#if 0 990#if 0
979
980static void appendsOFile(OFile *fp, const char *s) 991static void appendsOFile(OFile *fp, const char *s)
981{ 992{
982 int slen; 993 int slen;
983 if (fp->fail) return; 994 if (fp->fail) return;
984 slen = strlen(s); 995 slen = strlen(s);
985 if (fp->fp) { 996 if (fp->fp) {
986 fwrite(s,1,slen,fp->fp); 997 fwrite(s,1,slen,fp->fp);
987 } 998 }
988 else { 999 else {
989stuff: 1000stuff:
990 if (fp->len + slen < fp->limit) { 1001 if (fp->len + slen < fp->limit) {
991 memcpy(fp->s+fp->len,s,slen); 1002 memcpy(fp->s+fp->len,s,slen);
992 fp->len += slen; 1003 fp->len += slen;
993 return; 1004 return;
994 } 1005 }
995 else if (fp->alloc) { 1006 else if (fp->alloc) {
996 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 1007 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
997 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen; 1008 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
998 if (fp->s) 1009 fp->s = (char *) realloc(fp->s,fp->limit);
999 fp->s = realloc(fp->s,fp->limit);
1000 else
1001 fp->s = malloc(fp->limit);
1002 if (fp->s) goto stuff; 1010 if (fp->s) goto stuff;
1003 } 1011 }
1004 if (fp->alloc) 1012 if (fp->alloc)
1005 free(fp->s); 1013 free(fp->s);
1006 fp->s = 0; 1014 fp->s = 0;
1007 fp->fail = 1; 1015 fp->fail = 1;
1008 } 1016 }
1009} 1017}
1010 1018
1011static void appendcOFile(OFile *fp, char c) 1019static void appendcOFile(OFile *fp, char c)
1012{ 1020{
1013 if (fp->fail) return; 1021 if (fp->fail) return;
1014 if (fp->fp) { 1022 if (fp->fp) {
1015 fputc(c,fp->fp); 1023 fputc(c,fp->fp);
1016 } 1024 }
1017 else { 1025 else {
1018stuff: 1026stuff:
1019 if (fp->len+1 < fp->limit) { 1027 if (fp->len+1 < fp->limit) {
1020 fp->s[fp->len] = c; 1028 fp->s[fp->len] = c;
1021 fp->len++; 1029 fp->len++;
1022 return; 1030 return;
1023 } 1031 }
1024 else if (fp->alloc) { 1032 else if (fp->alloc) {
1025 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 1033 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
1026 fp->s = realloc(fp->s,fp->limit); 1034 fp->s = (char *) realloc(fp->s,fp->limit);
1027 if (fp->s) goto stuff; 1035 if (fp->s) goto stuff;
1028 } 1036 }
1029 if (fp->alloc) 1037 if (fp->alloc)
1030 free(fp->s); 1038 free(fp->s);
1031 fp->s = 0; 1039 fp->s = 0;
1032 fp->fail = 1; 1040 fp->fail = 1;
1033 } 1041 }
1034} 1042}
1035
1036#else 1043#else
1037
1038static void appendcOFile_(OFile *fp, char c) 1044static void appendcOFile_(OFile *fp, char c)
1039{ 1045{
1040 if (fp->fail) return; 1046 if (fp->fail) return;
1041 if (fp->fp) { 1047 if (fp->fp) {
1042 fputc(c,fp->fp); 1048 fputc(c,fp->fp);
1043 } 1049 }
1044 else { 1050 else {
1045stuff: 1051stuff:
1046 if (fp->len+1 < fp->limit) { 1052 if (fp->len+1 < fp->limit) {
1047 fp->s[fp->len] = c; 1053 fp->s[fp->len] = c;
1048 fp->len++; 1054 fp->len++;
1049 return; 1055 return;
1050 } 1056 }
1051 else if (fp->alloc) { 1057 else if (fp->alloc) {
1052 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 1058 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
1053 fp->s = realloc(fp->s,fp->limit); 1059 fp->s = realloc(fp->s,fp->limit);
1054 if (fp->s) goto stuff; 1060 if (fp->s) goto stuff;
1055 } 1061 }
1056 if (fp->alloc) 1062 if (fp->alloc)
1057 free(fp->s); 1063 free(fp->s);
1058 fp->s = 0; 1064 fp->s = 0;
1059 fp->fail = 1; 1065 fp->fail = 1;
1060 } 1066 }
1061} 1067}
@@ -1124,310 +1130,325 @@ static int writeBase64(OFile *fp, unsigned char *s, long len)
1124 } 1130 }
1125 /* fill in 'quad' with the appropriate four characters */ 1131 /* fill in 'quad' with the appropriate four characters */
1126 for (i = 3; i >= 0; i--) { 1132 for (i = 3; i >= 0; i--) {
1127 b = (unsigned char)(trip & 0x3F); 1133 b = (unsigned char)(trip & 0x3F);
1128 trip = trip >> 6; 1134 trip = trip >> 6;
1129 if ((3 - i) < (cur - len)) 1135 if ((3 - i) < (cur - len))
1130 quad[i] = '='; /* pad char */ 1136 quad[i] = '='; /* pad char */
1131 else if (b < 26) quad[i] = (char)b + 'A'; 1137 else if (b < 26) quad[i] = (char)b + 'A';
1132 else if (b < 52) quad[i] = (char)(b - 26) + 'a'; 1138 else if (b < 52) quad[i] = (char)(b - 26) + 'a';
1133 else if (b < 62) quad[i] = (char)(b - 52) + '0'; 1139 else if (b < 62) quad[i] = (char)(b - 52) + '0';
1134 else if (b == 62) quad[i] = '+'; 1140 else if (b == 62) quad[i] = '+';
1135 else quad[i] = '/'; 1141 else quad[i] = '/';
1136 } 1142 }
1137 /* now output 'quad' with appropriate whitespace and line ending */ 1143 /* now output 'quad' with appropriate whitespace and line ending */
1138 appendsOFile(fp, (numQuads == 0 ? " " : "")); 1144 appendsOFile(fp, (numQuads == 0 ? " " : ""));
1139 appendsOFile(fp, quad); 1145 appendsOFile(fp, quad);
1140 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); 1146 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
1141 numQuads = (numQuads + 1) % MAXQUADS; 1147 numQuads = (numQuads + 1) % MAXQUADS;
1142 } 1148 }
1143 appendcOFile(fp,'\n'); 1149 appendcOFile(fp,'\n');
1144 1150
1145 return 1; 1151 return 1;
1146} 1152}
1147 1153
1148/* this function really sucks. Too basic. */ 1154static void writeString(OFile *fp, const char *s)
1149static void writeQPString(OFile *fp, const char *s, int qp) 1155{
1156 appendsOFile(fp,s);
1157}
1158
1159static void writeQPString(OFile *fp, const char *s)
1150{ 1160{
1161 char buf[4];
1162 int count=0;
1151 const char *p = s; 1163 const char *p = s;
1164
1152 while (*p) { 1165 while (*p) {
1153 if (*p == '\n') { 1166 /* break up lines biggger than 75 chars */
1154 if (p[1]) appendsOFile(fp,"=0A="); 1167 if(count >=74){
1168 count=0;
1169 appendsOFile(fp,"=\n");
1155 } 1170 }
1156 if (*p == '=' && qp) 1171
1157 appendsOFile(fp,"=3D"); 1172 /* escape any non ASCII characters and '=' as per rfc1521 */
1158 else 1173 if (*p<= 0x1f || *p >=0x7f || *p == '=' ) {
1174 sprintf(buf,"=%02X",(unsigned char)*p);
1175 appendsOFile(fp,buf);
1176 count+=3;
1177 } else {
1159 appendcOFile(fp,*p); 1178 appendcOFile(fp,*p);
1179 count++;
1180 }
1160 p++; 1181 p++;
1161 } 1182 }
1162} 1183}
1163 1184
1185
1186
1164static void writeVObject_(OFile *fp, VObject *o); 1187static void writeVObject_(OFile *fp, VObject *o);
1165 1188
1166static void writeValue(OFile *fp, VObject *o, unsigned long size) 1189static void writeValue(OFile *fp, VObject *o, unsigned long size,int quote)
1167{ 1190{
1168 if (o == 0) return; 1191 if (o == 0) return;
1169 switch (VALUE_TYPE(o)) { 1192 switch (VALUE_TYPE(o)) {
1170 case VCVT_USTRINGZ: { 1193 case VCVT_USTRINGZ: {
1171 char *s = fakeCString(USTRINGZ_VALUE_OF(o)); 1194 char *s = fakeCString(USTRINGZ_VALUE_OF(o));
1172 if (isAPropertyOf(o, VCQuotedPrintableProp)) 1195 if(quote) writeQPString(fp, s);
1173 writeQPString(fp, s, 1); 1196 else writeString(fp,s);
1174 else
1175 writeQPString(fp, s, 0);
1176 deleteStr(s); 1197 deleteStr(s);
1177 break; 1198 break;
1178 } 1199 }
1179 case VCVT_STRINGZ: { 1200 case VCVT_STRINGZ: {
1180 if (isAPropertyOf(o, VCQuotedPrintableProp)) 1201 if(quote) writeQPString(fp, STRINGZ_VALUE_OF(o));
1181 writeQPString(fp, STRINGZ_VALUE_OF(o), 1); 1202 else writeString(fp,STRINGZ_VALUE_OF(o));
1182 else
1183 writeQPString(fp, STRINGZ_VALUE_OF(o), 0);
1184 break; 1203 break;
1185 } 1204 }
1186 case VCVT_UINT: { 1205 case VCVT_UINT: {
1187 char buf[16]; 1206 char buf[16];
1188 sprintf(buf,"%u", INTEGER_VALUE_OF(o)); 1207 sprintf(buf,"%u", INTEGER_VALUE_OF(o));
1189 appendsOFile(fp,buf); 1208 appendsOFile(fp,buf);
1190 break; 1209 break;
1191 } 1210 }
1192 case VCVT_ULONG: { 1211 case VCVT_ULONG: {
1193 char buf[16]; 1212 char buf[16];
1194 sprintf(buf,"%lu", LONG_VALUE_OF(o)); 1213 sprintf(buf,"%lu", LONG_VALUE_OF(o));
1195 appendsOFile(fp,buf); 1214 appendsOFile(fp,buf);
1196 break; 1215 break;
1197 } 1216 }
1198 case VCVT_RAW: { 1217 case VCVT_RAW: {
1199 appendcOFile(fp,'\n'); 1218 appendcOFile(fp,'\n');
1200 writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size); 1219 writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
1201 break; 1220 break;
1202 } 1221 }
1203 case VCVT_VOBJECT: 1222 case VCVT_VOBJECT:
1204 appendcOFile(fp,'\n'); 1223 appendcOFile(fp,'\n');
1205 writeVObject_(fp,VOBJECT_VALUE_OF(o)); 1224 writeVObject_(fp,VOBJECT_VALUE_OF(o));
1206 break; 1225 break;
1207 } 1226 }
1208} 1227}
1209 1228
1210static void writeAttrValue(OFile *fp, VObject *o) 1229static void writeAttrValue(OFile *fp, VObject *o)
1211{ 1230{
1212 if (NAME_OF(o)) { 1231 if (NAME_OF(o)) {
1213 struct PreDefProp *pi; 1232 struct PreDefProp *pi;
1214 pi = lookupPropInfo(NAME_OF(o)); 1233 pi = lookupPropInfo(NAME_OF(o));
1215 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; 1234 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
1216 appendcOFile(fp,';'); 1235 appendcOFile(fp,';');
1217 appendsOFile(fp,NAME_OF(o)); 1236 appendsOFile(fp,NAME_OF(o));
1218 } 1237 }
1219 else 1238 else
1220 appendcOFile(fp,';'); 1239 appendcOFile(fp,';');
1221 if (VALUE_TYPE(o)) { 1240 if (VALUE_TYPE(o)) {
1222 appendcOFile(fp,'='); 1241 appendcOFile(fp,'=');
1223 writeValue(fp,o,0); 1242 writeValue(fp,o,0,0);
1224 } 1243 }
1225} 1244}
1226 1245
1227static void writeGroup(OFile *fp, VObject *o) 1246static void writeGroup(OFile *fp, VObject *o)
1228{ 1247{
1229 char buf1[256]; 1248 char buf1[256];
1230 char buf2[256]; 1249 char buf2[256];
1231 strcpy(buf1,NAME_OF(o)); 1250 strcpy(buf1,NAME_OF(o));
1232 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { 1251 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
1233 strncpy(buf2,STRINGZ_VALUE_OF(o),sizeof(buf2)); 1252 strcpy(buf2,STRINGZ_VALUE_OF(o));
1234 buf2[sizeof(buf2)] = '\0'; 1253 strcat(buf2,".");
1235 strncat(buf2,".",sizeof(buf2)-strlen(buf2)-1); 1254 strcat(buf2,buf1);
1236 strncat(buf2,buf1,sizeof(buf2)-strlen(buf2)-1);
1237 strcpy(buf1,buf2); 1255 strcpy(buf1,buf2);
1238 } 1256 }
1239 appendsOFile(fp,buf1); 1257 appendsOFile(fp,buf1);
1240} 1258}
1241 1259
1242static int inList(const char **list, const char *s) 1260static int inList(const char **list, const char *s)
1243{ 1261{
1244 if (list == 0) return 0; 1262 if (list == 0) return 0;
1245 while (*list) { 1263 while (*list) {
1246 if (strcasecmp(*list,s) == 0) return 1; 1264 if (stricmp(*list,s) == 0) return 1;
1247 list++; 1265 list++;
1248 } 1266 }
1249 return 0; 1267 return 0;
1250} 1268}
1251 1269
1252static void writeProp(OFile *fp, VObject *o) 1270static void writeProp(OFile *fp, VObject *o)
1253{ 1271{
1272 int isQuoted=0;
1254 if (NAME_OF(o)) { 1273 if (NAME_OF(o)) {
1255 struct PreDefProp *pi; 1274 struct PreDefProp *pi;
1256 VObjectIterator t; 1275 VObjectIterator t;
1257 const char **fields_ = 0; 1276 const char **fields_ = 0;
1258 pi = lookupPropInfo(NAME_OF(o)); 1277 pi = lookupPropInfo(NAME_OF(o));
1259 if (pi && ((pi->flags & PD_BEGIN) != 0)) { 1278 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1260 writeVObject_(fp,o); 1279 writeVObject_(fp,o);
1261 return; 1280 return;
1262 } 1281 }
1263 if (isAPropertyOf(o,VCGroupingProp)) 1282 if (isAPropertyOf(o,VCGroupingProp))
1264 writeGroup(fp,o); 1283 writeGroup(fp,o);
1265 else 1284 else
1266 appendsOFile(fp,NAME_OF(o)); 1285 appendsOFile(fp,NAME_OF(o));
1267 if (pi) fields_ = pi->fields; 1286 if (pi) fields_ = pi->fields;
1268 initPropIterator(&t,o); 1287 initPropIterator(&t,o);
1269 while (moreIteration(&t)) { 1288 while (moreIteration(&t)) {
1270 const char *s; 1289 const char *s;
1271 VObject *eachProp = nextVObject(&t); 1290 VObject *eachProp = nextVObject(&t);
1272 s = NAME_OF(eachProp); 1291 s = NAME_OF(eachProp);
1273 if (strcasecmp(VCGroupingProp,s) && !inList(fields_,s)) 1292 if (stricmp(VCGroupingProp,s) && !inList(fields_,s))
1274 writeAttrValue(fp,eachProp); 1293 writeAttrValue(fp,eachProp);
1294 if (stricmp(VCQPProp,s)==0 || stricmp(VCQuotedPrintableProp,s)==0)
1295 isQuoted=1;
1275 } 1296 }
1276 if (fields_) { 1297 if (fields_) {
1277 int i = 0, n = 0; 1298 int i = 0, n = 0;
1278 const char** fields = fields_; 1299 const char** fields = fields_;
1279 /* output prop as fields */ 1300 /* output prop as fields */
1280 appendcOFile(fp,':'); 1301 appendcOFile(fp,':');
1281 while (*fields) { 1302 while (*fields) {
1282 VObject *tl = isAPropertyOf(o,*fields); 1303 VObject *t = isAPropertyOf(o,*fields);
1283 i++; 1304 i++;
1284 if (tl) n = i; 1305 if (t) n = i;
1285 fields++; 1306 fields++;
1286 } 1307 }
1287 fields = fields_; 1308 fields = fields_;
1288 for (i=0;i<n;i++) { 1309 for (i=0;i<n;i++) {
1289 writeValue(fp,isAPropertyOf(o,*fields),0); 1310 writeValue(fp,isAPropertyOf(o,*fields),0,isQuoted);
1290 fields++; 1311 fields++;
1291 if (i<(n-1)) appendcOFile(fp,';'); 1312 if (i<(n-1)) appendcOFile(fp,';');
1292 } 1313 }
1293 } 1314 }
1294 } 1315 }
1295 1316
1296 if (VALUE_TYPE(o)) { 1317 if (VALUE_TYPE(o)) {
1297 unsigned long size = 0; 1318 unsigned long size = 0;
1298 VObject *p = isAPropertyOf(o,VCDataSizeProp); 1319 VObject *p = isAPropertyOf(o,VCDataSizeProp);
1299 if (p) size = LONG_VALUE_OF(p); 1320 if (p) size = LONG_VALUE_OF(p);
1300 appendcOFile(fp,':'); 1321 appendcOFile(fp,':');
1301 writeValue(fp,o,size); 1322 writeValue(fp,o,size,isQuoted);
1302 } 1323 }
1303 1324
1304 appendcOFile(fp,'\n'); 1325 appendcOFile(fp,'\n');
1305} 1326}
1306 1327
1307static void writeVObject_(OFile *fp, VObject *o) 1328static void writeVObject_(OFile *fp, VObject *o)
1308{ 1329{
1309 if (NAME_OF(o)) { 1330 if (NAME_OF(o)) {
1310 struct PreDefProp *pi; 1331 struct PreDefProp *pi;
1311 pi = lookupPropInfo(NAME_OF(o)); 1332 pi = lookupPropInfo(NAME_OF(o));
1312 1333
1313 if (pi && ((pi->flags & PD_BEGIN) != 0)) { 1334 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1314 VObjectIterator t; 1335 VObjectIterator t;
1315 const char *begin = NAME_OF(o); 1336 const char *begin = NAME_OF(o);
1316 appendsOFile(fp,"BEGIN:"); 1337 appendsOFile(fp,"BEGIN:");
1317 appendsOFile(fp,begin); 1338 appendsOFile(fp,begin);
1318 appendcOFile(fp,'\n'); 1339 appendcOFile(fp,'\n');
1319 initPropIterator(&t,o); 1340 initPropIterator(&t,o);
1320 while (moreIteration(&t)) { 1341 while (moreIteration(&t)) {
1321 VObject *eachProp = nextVObject(&t); 1342 VObject *eachProp = nextVObject(&t);
1322 writeProp(fp, eachProp); 1343 writeProp(fp, eachProp);
1323 } 1344 }
1324 appendsOFile(fp,"END:"); 1345 appendsOFile(fp,"END:");
1325 appendsOFile(fp,begin); 1346 appendsOFile(fp,begin);
1326 appendsOFile(fp,"\n\n"); 1347 appendsOFile(fp,"\n\n");
1327 } 1348 }
1328 } 1349 }
1329} 1350}
1330 1351
1331void writeVObject(FILE *fp, VObject *o) 1352void writeVObject(FILE *fp, VObject *o)
1332{ 1353{
1333 OFile ofp; 1354 OFile ofp;
1334 initOFile(&ofp,fp); 1355 initOFile(&ofp,fp);
1335 writeVObject_(&ofp,o); 1356 writeVObject_(&ofp,o);
1336} 1357}
1337 1358
1338void writeVObjectToFile(char *fname, VObject *o) 1359DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
1339{ 1360{
1340 FILE *fp = fopen(fname,"w"); 1361 FILE *fp = fopen(fname,"w");
1341 if (fp) { 1362 if (fp) {
1342 writeVObject(fp,o); 1363 writeVObject(fp,o);
1343 fclose(fp); 1364 fclose(fp);
1344 } 1365 }
1345} 1366}
1346 1367
1347void writeVObjectsToFile(char *fname, VObject *list) 1368DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
1348{ 1369{
1349 FILE *fp = fopen(fname,"w"); 1370 FILE *fp = fopen(fname,"w");
1350 if (fp) { 1371 if (fp) {
1351 while (list) { 1372 while (list) {
1352 writeVObject(fp,list); 1373 writeVObject(fp,list);
1353 list = nextVObjectInList(list); 1374 list = nextVObjectInList(list);
1354 } 1375 }
1355 fclose(fp); 1376 fclose(fp);
1356 } 1377 }
1357} 1378}
1358 1379
1359char* writeMemVObject(char *s, int *len, VObject *o) 1380DLLEXPORT(char*) writeMemVObject(char *s, int *len, VObject *o)
1360{ 1381{
1361 OFile ofp; 1382 OFile ofp;
1362 initMemOFile(&ofp,s,len?*len:0); 1383 initMemOFile(&ofp,s,len?*len:0);
1363 writeVObject_(&ofp,o); 1384 writeVObject_(&ofp,o);
1364 if (len) *len = ofp.len; 1385 if (len) *len = ofp.len;
1365 appendcOFile(&ofp,0); 1386 appendcOFile(&ofp,0);
1366 return ofp.s; 1387 return ofp.s;
1367} 1388}
1368 1389
1369char* writeMemVObjects(char *s, int *len, VObject *list) 1390DLLEXPORT(char*) writeMemVObjects(char *s, int *len, VObject *list)
1370{ 1391{
1371 OFile ofp; 1392 OFile ofp;
1372 initMemOFile(&ofp,s,len?*len:0); 1393 initMemOFile(&ofp,s,len?*len:0);
1373 while (list) { 1394 while (list) {
1374 writeVObject_(&ofp,list); 1395 writeVObject_(&ofp,list);
1375 list = nextVObjectInList(list); 1396 list = nextVObjectInList(list);
1376 } 1397 }
1377 if (len) *len = ofp.len; 1398 if (len) *len = ofp.len;
1378 appendcOFile(&ofp,0); 1399 appendcOFile(&ofp,0);
1379 return ofp.s; 1400 return ofp.s;
1380} 1401}
1381 1402
1382/*---------------------------------------------------------------------- 1403/*----------------------------------------------------------------------
1383 APIs to do fake Unicode stuff. 1404 APIs to do fake Unicode stuff.
1384 ----------------------------------------------------------------------*/ 1405 ----------------------------------------------------------------------*/
1385wchar_t* fakeUnicode(const char *ps, int *bytes) 1406DLLEXPORT(wchar_t*) fakeUnicode(const char *ps, int *bytes)
1386{ 1407{
1387 wchar_t *r, *pw; 1408 wchar_t *r, *pw;
1388 int len = strlen(ps)+1; 1409 int len = strlen(ps)+1;
1389 1410
1390 pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len); 1411 pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len);
1391 if (bytes) 1412 if (bytes)
1392 *bytes = len * sizeof(wchar_t); 1413 *bytes = len * sizeof(wchar_t);
1393 1414
1394 while (*ps) { 1415 while (*ps) {
1395 if (*ps == '\n') 1416 if (*ps == '\n')
1396 *pw = (wchar_t)0x2028; 1417 *pw = (wchar_t)0x2028;
1397 else if (*ps == '\r') 1418 else if (*ps == '\r')
1398 *pw = (wchar_t)0x2029; 1419 *pw = (wchar_t)0x2029;
1399 else 1420 else
1400 *pw = (wchar_t)(unsigned char)*ps; 1421 *pw = (wchar_t)(unsigned char)*ps;
1401 ps++; pw++; 1422 ps++; pw++;
1402 } 1423 }
1403 *pw = (wchar_t)0; 1424 *pw = (wchar_t)0;
1404 1425
1405 return r; 1426 return r;
1406} 1427}
1407 1428
1408int uStrLen(const wchar_t *u) 1429DLLEXPORT(int) uStrLen(const wchar_t *u)
1409{ 1430{
1410 int i = 0; 1431 int i = 0;
1411 while (*u != (wchar_t)0) { u++; i++; } 1432 while (*u != (wchar_t)0) { u++; i++; }
1412 return i; 1433 return i;
1413} 1434}
1414 1435
1415char* fakeCString(const wchar_t *u) 1436DLLEXPORT(char*) fakeCString(const wchar_t *u)
1416{ 1437{
1417 char *s, *t; 1438 char *s, *t;
1418 int len = uStrLen(u) + 1; 1439 int len = uStrLen(u) + 1;
1419 t = s = (char*)malloc(len+1); 1440 t = s = (char*)malloc(len);
1420 while (*u) { 1441 while (*u) {
1421 if (*u == (wchar_t)0x2028) 1442 if (*u == (wchar_t)0x2028)
1422 *t = '\n'; 1443 *t = '\n';
1423 else if (*u == (wchar_t)0x2029) 1444 else if (*u == (wchar_t)0x2029)
1424 *t = '\r'; 1445 *t = '\r';
1425 else 1446 else
1426 *t = (char)*u; 1447 *t = (char)*u;
1427 u++; t++; 1448 u++; t++;
1428 } 1449 }
1429 *t = 0; 1450 *t = 0;
1430 return s; 1451 return s;
1431} 1452}
1432 1453
1433/* end of source file vobject.c */ 1454/* end of source file vobject.c */