summaryrefslogtreecommitdiffabout
path: root/libkcal/versit/vobject.c
Unidiff
Diffstat (limited to 'libkcal/versit/vobject.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/versit/vobject.c1433
1 files changed, 1433 insertions, 0 deletions
diff --git a/libkcal/versit/vobject.c b/libkcal/versit/vobject.c
new file mode 100644
index 0000000..637efb2
--- a/dev/null
+++ b/libkcal/versit/vobject.c
@@ -0,0 +1,1433 @@
1/***************************************************************************
2(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
3Business Machines Corporation and Siemens Rolm Communications Inc.
4
5For purposes of this license notice, the term Licensors shall mean,
6collectively, Apple Computer, Inc., AT&T Corp., International
7Business Machines Corporation and Siemens Rolm Communications Inc.
8The term Licensor shall mean any of the Licensors.
9
10Subject to acceptance of the following conditions, permission is hereby
11granted by Licensors without the need for written agreement and without
12license or royalty fees, to use, copy, modify and distribute this
13software for any purpose.
14
15The above copyright notice and the following four paragraphs must be
16reproduced in all copies of this software and any software including
17this software.
18
19THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
20ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
21MODIFICATIONS.
22
23IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
24INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
25OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26DAMAGE.
27
28EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
29INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31PURPOSE.
32
33The software is provided with RESTRICTED RIGHTS. Use, duplication, or
34disclosure by the government are subject to restrictions set forth in
35DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
36
37***************************************************************************/
38
39/*
40 * src: vobject.c
41 * doc: vobject and APIs to construct vobject, APIs pretty print
42 * vobject, and convert a vobject into its textual representation.
43 */
44
45#include <stdlib.h>
46
47#include "vobject.h"
48#include <string.h>
49#include <stdio.h>
50#ifdef _WIN32_
51
52 #define strcasecmp _stricmp
53
54#endif
55
56 #define NAME_OF(o) o->id
57 #define VALUE_TYPE(o) o->valType
58 #define STRINGZ_VALUE_OF(o) o->val.strs
59 #define USTRINGZ_VALUE_OF(o)o->val.ustrs
60 #define INTEGER_VALUE_OF(o) o->val.i
61 #define LONG_VALUE_OF(o) o->val.l
62 #define ANY_VALUE_OF(o) o->val.any
63 #define VOBJECT_VALUE_OF(o) o->val.vobj
64
65const char** fieldedProp;
66
67
68
69/*----------------------------------------------------------------------
70 The following functions involve with memory allocation:
71 newVObject
72 deleteVObject
73 dupStr
74 deleteStr
75 newStrItem
76 deleteStrItem
77 ----------------------------------------------------------------------*/
78
79VObject* newVObject_(const char *id)
80{
81 VObject *p = (VObject*)malloc(sizeof(VObject));
82 p->next = 0;
83 p->id = id;
84 p->prop = 0;
85 VALUE_TYPE(p) = 0;
86 ANY_VALUE_OF(p) = 0;
87 return p;
88}
89
90VObject* newVObject(const char *id)
91{
92 return newVObject_(lookupStr(id));
93}
94
95void deleteVObject(VObject *p)
96{
97 if (p->id)
98 unUseStr(p->id);
99 if (p)
100 free(p);
101 p = NULL;
102}
103
104char* dupStr(const char *s, unsigned int size)
105{
106 char *t;
107 if (size == 0) {
108 size = strlen(s);
109 }
110 t = (char*)malloc(size+1);
111 if (t) {
112 memcpy(t,s,size);
113 t[size] = 0;
114 return t;
115 }
116 else {
117 return (char*)0;
118 }
119}
120
121void deleteStr(const char *p)
122{
123 if (p)
124 free((void*)p);
125 p = NULL;
126}
127
128
129static StrItem* newStrItem(const char *s, StrItem *next)
130{
131 StrItem *p = (StrItem*)malloc(sizeof(StrItem));
132 p->next = next;
133 p->s = s;
134 p->refCnt = 1;
135 return p;
136}
137
138static void deleteStrItem(StrItem *p)
139{
140 if (p)
141 free((void*)p);
142 p = NULL;
143}
144
145
146/*----------------------------------------------------------------------
147 The following function provide accesses to VObject's value.
148 ----------------------------------------------------------------------*/
149
150const char* vObjectName(VObject *o)
151{
152 return NAME_OF(o);
153}
154
155void setVObjectName(VObject *o, const char* id)
156{
157 NAME_OF(o) = id;
158}
159
160const char* vObjectStringZValue(VObject *o)
161{
162 return STRINGZ_VALUE_OF(o);
163}
164
165void setVObjectStringZValue(VObject *o, const char *s)
166{
167 STRINGZ_VALUE_OF(o) = dupStr(s,0);
168 VALUE_TYPE(o) = VCVT_STRINGZ;
169}
170
171void setVObjectStringZValue_(VObject *o, const char *s)
172{
173 STRINGZ_VALUE_OF(o) = s;
174 VALUE_TYPE(o) = VCVT_STRINGZ;
175}
176
177const wchar_t* vObjectUStringZValue(VObject *o)
178{
179 return USTRINGZ_VALUE_OF(o);
180}
181
182void setVObjectUStringZValue(VObject *o, const wchar_t *s)
183{
184 USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2);
185 VALUE_TYPE(o) = VCVT_USTRINGZ;
186}
187
188void setVObjectUStringZValue_(VObject *o, const wchar_t *s)
189{
190 USTRINGZ_VALUE_OF(o) = s;
191 VALUE_TYPE(o) = VCVT_USTRINGZ;
192}
193
194unsigned int vObjectIntegerValue(VObject *o)
195{
196 return INTEGER_VALUE_OF(o);
197}
198
199void setVObjectIntegerValue(VObject *o, unsigned int i)
200{
201 INTEGER_VALUE_OF(o) = i;
202 VALUE_TYPE(o) = VCVT_UINT;
203}
204
205unsigned long vObjectLongValue(VObject *o)
206{
207 return LONG_VALUE_OF(o);
208}
209
210void setVObjectLongValue(VObject *o, unsigned long l)
211{
212 LONG_VALUE_OF(o) = l;
213 VALUE_TYPE(o) = VCVT_ULONG;
214}
215
216void* vObjectAnyValue(VObject *o)
217{
218 return ANY_VALUE_OF(o);
219}
220
221void setVObjectAnyValue(VObject *o, void *t)
222{
223 ANY_VALUE_OF(o) = t;
224 VALUE_TYPE(o) = VCVT_RAW;
225}
226
227VObject* vObjectVObjectValue(VObject *o)
228{
229 return VOBJECT_VALUE_OF(o);
230}
231
232void setVObjectVObjectValue(VObject *o, VObject *p)
233{
234 VOBJECT_VALUE_OF(o) = p;
235 VALUE_TYPE(o) = VCVT_VOBJECT;
236}
237
238int vObjectValueType(VObject *o)
239{
240 return VALUE_TYPE(o);
241}
242
243
244/*----------------------------------------------------------------------
245 The following functions can be used to build VObject.
246 ----------------------------------------------------------------------*/
247
248VObject* addVObjectProp(VObject *o, VObject *p)
249{
250 /* circular link list pointed to tail */
251 /*
252 o {next,id,prop,val}
253 V
254 pn {next,id,prop,val}
255 V
256 ...
257 p1 {next,id,prop,val}
258 V
259 pn
260 -->
261 o {next,id,prop,val}
262 V
263 pn {next,id,prop,val}
264 V
265 p {next,id,prop,val}
266 ...
267 p1 {next,id,prop,val}
268 V
269 pn
270 */
271
272 VObject *tail = o->prop;
273 if (tail) {
274 p->next = tail->next;
275 o->prop = tail->next = p;
276 }
277 else {
278 o->prop = p->next = p;
279 }
280 return p;
281}
282
283VObject* addProp(VObject *o, const char *id)
284{
285 return addVObjectProp(o,newVObject(id));
286}
287
288VObject* addProp_(VObject *o, const char *id)
289{
290 return addVObjectProp(o,newVObject_(id));
291}
292
293void addList(VObject **o, VObject *p)
294{
295 p->next = 0;
296 if (*o == 0) {
297 *o = p;
298 }
299 else {
300 VObject *t = *o;
301 while (t->next) {
302 t = t->next;
303 }
304 t->next = p;
305 }
306}
307
308VObject* nextVObjectInList(VObject *o)
309{
310 return o->next;
311}
312
313VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size)
314{
315 VObject *sizeProp;
316 setVObjectAnyValue(prop, val);
317 sizeProp = addProp(prop,VCDataSizeProp);
318 setVObjectLongValue(sizeProp, size);
319 return prop;
320}
321
322VObject* setValueWithSize(VObject *prop, void *val, unsigned int size)
323{
324 void *p = dupStr(val,size);
325 return setValueWithSize_(prop,p,p?size:0);
326}
327
328void initPropIterator(VObjectIterator *i, VObject *o)
329{
330 i->start = o->prop;
331 i->next = 0;
332}
333
334void initVObjectIterator(VObjectIterator *i, VObject *o)
335{
336 i->start = o->next;
337 i->next = 0;
338}
339
340int moreIteration(VObjectIterator *i)
341{
342 return (i->start && (i->next==0 || i->next!=i->start));
343}
344
345VObject* nextVObject(VObjectIterator *i)
346{
347 if (i->start && i->next != i->start) {
348 if (i->next == 0) {
349 i->next = i->start->next;
350 return i->next;
351 }
352 else {
353 i->next = i->next->next;
354 return i->next;
355 }
356 }
357 else return (VObject*)0;
358}
359
360VObject* isAPropertyOf(VObject *o, const char *id)
361{
362 VObjectIterator i;
363 initPropIterator(&i,o);
364 while (moreIteration(&i)) {
365 VObject *each = nextVObject(&i);
366 if (!strcasecmp(id,each->id))
367 return each;
368 }
369 return (VObject*)0;
370}
371
372VObject* addGroup(VObject *o, const char *g)
373{
374 /*
375 a.b.c
376 -->
377 prop(c)
378 prop(VCGrouping=b)
379 prop(VCGrouping=a)
380 */
381 char *dot = strrchr(g,'.');
382 if (dot) {
383 VObject *p, *t;
384 char *gs, *n = dot+1;
385 gs = dupStr(g,0);/* so we can write to it. */
386 /* used to be
387 * t = p = addProp_(o,lookupProp_(n));
388 */
389 t = p = addProp_(o,lookupProp(n));
390 dot = strrchr(gs,'.');
391 *dot = 0;
392 do {
393 dot = strrchr(gs,'.');
394 if (dot) {
395 n = dot+1;
396 *dot=0;
397 }
398 else
399 n = gs;
400 /* property(VCGroupingProp=n);
401 *and the value may have VCGrouping property
402 */
403 t = addProp(t,VCGroupingProp);
404 setVObjectStringZValue(t,lookupProp_(n));
405 } while (n != gs);
406 deleteStr(gs);
407 return p;
408 }
409 else
410 return addProp_(o,lookupProp(g));
411}
412
413VObject* addPropValue(VObject *o, const char *p, const char *v)
414{
415 VObject *prop;
416 prop = addProp(o,p);
417 setVObjectUStringZValue_(prop, fakeUnicode(v,0));
418 return prop;
419}
420
421VObject* addPropSizedValue_(VObject *o, const char *p, const char *v,
422 unsigned int size)
423{
424 VObject *prop;
425 prop = addProp(o,p);
426 setValueWithSize_(prop, (void*)v, size);
427 return prop;
428}
429
430VObject* addPropSizedValue(VObject *o, const char *p, const char *v,
431 unsigned int size)
432{
433 return addPropSizedValue_(o,p,dupStr(v,size),size);
434}
435
436
437
438/*----------------------------------------------------------------------
439 The following pretty print a VObject
440 ----------------------------------------------------------------------*/
441
442static void printVObject_(FILE *fp, VObject *o, int level);
443
444static void indent(FILE *fp, int level)
445{
446 int i;
447 for (i=0;i<level*4;i++) {
448 fputc(' ', fp);
449 }
450}
451
452static void printValue(FILE *fp, VObject *o, int level)
453{
454 switch (VALUE_TYPE(o)) {
455 case VCVT_USTRINGZ: {
456 char c;
457 char *t,*s;
458 s = t = fakeCString(USTRINGZ_VALUE_OF(o));
459 fputc('"',fp);
460 while (c=*t,c) {
461 fputc(c,fp);
462 if (c == '\n') indent(fp,level+2);
463 t++;
464 }
465 fputc('"',fp);
466 deleteStr(s);
467 break;
468 }
469 case VCVT_STRINGZ: {
470 char c;
471 const char *s = STRINGZ_VALUE_OF(o);
472 fputc('"',fp);
473 while (c=*s,c) {
474 fputc(c,fp);
475 if (c == '\n') indent(fp,level+2);
476 s++;
477 }
478 fputc('"',fp);
479 break;
480 }
481 case VCVT_UINT:
482 fprintf(fp,"%d", INTEGER_VALUE_OF(o)); break;
483 case VCVT_ULONG:
484 fprintf(fp,"%ld", LONG_VALUE_OF(o)); break;
485 case VCVT_RAW:
486 fprintf(fp,"[raw data]"); break;
487 case VCVT_VOBJECT:
488 fprintf(fp,"[vobject]\n");
489 printVObject_(fp,VOBJECT_VALUE_OF(o),level+1);
490 break;
491 case 0:
492 fprintf(fp,"[none]"); break;
493 default:
494 fprintf(fp,"[unknown]"); break;
495 }
496}
497
498static void printNameValue(FILE *fp,VObject *o, int level)
499{
500 indent(fp,level);
501 if (NAME_OF(o)) {
502 fprintf(fp,"%s", NAME_OF(o));
503 }
504 if (VALUE_TYPE(o)) {
505 fputc('=',fp);
506 printValue(fp,o, level);
507 }
508 fprintf(fp,"\n");
509}
510
511static void printVObject_(FILE *fp, VObject *o, int level)
512 {
513 VObjectIterator t;
514 if (o == 0) {
515 fprintf(fp,"[NULL]\n");
516 return;
517 }
518 printNameValue(fp,o,level);
519 initPropIterator(&t,o);
520 while (moreIteration(&t)) {
521 VObject *eachProp = nextVObject(&t);
522 printVObject_(fp,eachProp,level+1);
523 }
524 }
525
526void printVObject(FILE *fp,VObject *o)
527{
528 printVObject_(fp,o,0);
529}
530
531void printVObjectToFile(char *fname,VObject *o)
532{
533 FILE *fp = fopen(fname,"w");
534 if (fp) {
535 printVObject(fp,o);
536 fclose(fp);
537 }
538}
539
540void printVObjectsToFile(char *fname,VObject *list)
541{
542 FILE *fp = fopen(fname,"w");
543 if (fp) {
544 while (list) {
545 printVObject(fp,list);
546 list = nextVObjectInList(list);
547 }
548 fclose(fp);
549 }
550}
551
552void cleanVObject(VObject *o)
553{
554 if (o == 0) return;
555 if (o->prop) {
556 /* destroy time: cannot use the iterator here.
557 Have to break the cycle in the circular link
558 list and turns it into regular NULL-terminated
559 list -- since at some point of destruction,
560 the reference entry for the iterator to work
561 will not longer be valid.
562 */
563 VObject *p;
564 p = o->prop->next;
565 o->prop->next = 0;
566 do {
567 VObject *t = p->next;
568 cleanVObject(p);
569 p = t;
570 } while (p);
571 }
572 switch (VALUE_TYPE(o)) {
573 case VCVT_USTRINGZ:
574 case VCVT_STRINGZ:
575 case VCVT_RAW:
576 /* assume they are all allocated by malloc. */
577 free((char*)STRINGZ_VALUE_OF(o));
578 break;
579 case VCVT_VOBJECT:
580 cleanVObject(VOBJECT_VALUE_OF(o));
581 break;
582 }
583 deleteVObject(o);
584}
585
586void cleanVObjects(VObject *list)
587{
588 while (list) {
589 VObject *t = list;
590 list = nextVObjectInList(list);
591 cleanVObject(t);
592 }
593}
594
595/*----------------------------------------------------------------------
596 The following is a String Table Facilities.
597 ----------------------------------------------------------------------*/
598
599#define STRTBLSIZE 255
600
601static StrItem *strTbl[STRTBLSIZE];
602
603static unsigned int hashStr(const char *s)
604{
605 unsigned int h = 0;
606 int i;
607 for (i=0;s[i];i++) {
608 h += s[i]*i;
609 }
610 return h % STRTBLSIZE;
611}
612
613const char* lookupStr(const char *s)
614{
615 char *newS;
616
617 StrItem *t;
618 unsigned int h = hashStr(s);
619 if ((t = strTbl[h]) != 0) {
620 do {
621 if (strcasecmp(t->s,s) == 0) {
622 t->refCnt++;
623 return t->s;
624 }
625 t = t->next;
626 } while (t);
627 }
628 newS = dupStr(s,0);
629 strTbl[h] = newStrItem(newS,strTbl[h]);
630 return newS;
631}
632
633void unUseStr(const char *s)
634{
635 StrItem *cur, *prev;
636
637 unsigned int h = hashStr(s);
638 cur = strTbl[h];
639 prev = cur;
640 while (cur != 0) {
641 if (strcasecmp(cur->s,s) == 0) {
642 cur->refCnt--;
643 /* if that was the last reference to this string, kill it. */
644 if (cur->refCnt == 0) {
645 if (cur == strTbl[h]) {
646 strTbl[h] = cur->next;
647 deleteStr(prev->s);
648 deleteStrItem(prev);
649 } else {
650 prev->next = cur->next;
651 deleteStr(cur->s);
652 deleteStrItem(cur);
653 }
654 return;
655 }
656 }
657 prev = cur;
658 cur = cur->next;
659 }
660}
661
662void cleanStrTbl()
663{
664 int i;
665 for (i=0; i<STRTBLSIZE;i++) {
666 StrItem *t = strTbl[i];
667 while (t) {
668 StrItem *p;
669 deleteStr(t->s);
670 p = t;
671 t = t->next;
672 deleteStrItem(p);
673 }
674 strTbl[i] = 0;
675 }
676}
677
678
679struct PreDefProp {
680 const char *name;
681 const char *alias;
682 const char** fields;
683 unsigned int flags;
684 };
685
686/* flags in PreDefProp */
687 #define PD_BEGIN0x1
688 #define PD_INTERNAL0x2
689
690static const char *adrFields[] = {
691 VCPostalBoxProp,
692 VCExtAddressProp,
693 VCStreetAddressProp,
694 VCCityProp,
695 VCRegionProp,
696 VCPostalCodeProp,
697 VCCountryNameProp,
698 0
699};
700
701static const char *nameFields[] = {
702 VCFamilyNameProp,
703 VCGivenNameProp,
704 VCAdditionalNamesProp,
705 VCNamePrefixesProp,
706 VCNameSuffixesProp,
707 NULL
708 };
709
710static const char *orgFields[] = {
711 VCOrgNameProp,
712 VCOrgUnitProp,
713 VCOrgUnit2Prop,
714 VCOrgUnit3Prop,
715 VCOrgUnit4Prop,
716 NULL
717 };
718
719static const char *AAlarmFields[] = {
720 VCRunTimeProp,
721 VCSnoozeTimeProp,
722 VCRepeatCountProp,
723 VCAudioContentProp,
724 0
725 };
726
727/* ExDate -- has unamed fields */
728/* RDate -- has unamed fields */
729
730static const char *DAlarmFields[] = {
731 VCRunTimeProp,
732 VCSnoozeTimeProp,
733 VCRepeatCountProp,
734 VCDisplayStringProp,
735 0
736 };
737
738static const char *MAlarmFields[] = {
739 VCRunTimeProp,
740 VCSnoozeTimeProp,
741 VCRepeatCountProp,
742 VCEmailAddressProp,
743 VCNoteProp,
744 0
745 };
746
747static const char *PAlarmFields[] = {
748 VCRunTimeProp,
749 VCSnoozeTimeProp,
750 VCRepeatCountProp,
751 VCProcedureNameProp,
752 0
753 };
754
755static struct PreDefProp propNames[] = {
756 { VC7bitProp, 0, 0, 0 },
757 { VC8bitProp, 0, 0, 0 },
758 { VCAAlarmProp, 0, AAlarmFields, 0 },
759 { VCAdditionalNamesProp, 0, 0, 0 },
760 { VCAdrProp, 0, adrFields, 0 },
761 { VCAgentProp, 0, 0, 0 },
762 { VCAIFFProp, 0, 0, 0 },
763 { VCAOLProp, 0, 0, 0 },
764 { VCAppleLinkProp, 0, 0, 0 },
765 { VCAttachProp, 0, 0, 0 },
766 { VCAttendeeProp, 0, 0, 0 },
767 { VCATTMailProp, 0, 0, 0 },
768 { VCAudioContentProp, 0, 0, 0 },
769 { VCAVIProp, 0, 0, 0 },
770 { VCBase64Prop, 0, 0, 0 },
771 { VCBBSProp, 0, 0, 0 },
772 { VCBirthDateProp, 0, 0, 0 },
773 { VCBMPProp, 0, 0, 0 },
774 { VCBodyProp, 0, 0, 0 },
775 { VCBusinessRoleProp, 0, 0, 0 },
776 { VCCalProp, 0, 0, PD_BEGIN },
777 { VCCaptionProp, 0, 0, 0 },
778 { VCCardProp, 0, 0, PD_BEGIN },
779 { VCCarProp, 0, 0, 0 },
780 { VCCategoriesProp, 0, 0, 0 },
781 { VCCellularProp, 0, 0, 0 },
782 { VCCGMProp, 0, 0, 0 },
783 { VCCharSetProp, 0, 0, 0 },
784 { VCCIDProp, VCContentIDProp, 0, 0 },
785 { VCCISProp, 0, 0, 0 },
786 { VCCityProp, 0, 0, 0 },
787 { VCClassProp, 0, 0, 0 },
788 { VCCommentProp, 0, 0, 0 },
789 { VCCompletedProp, 0, 0, 0 },
790 { VCContentIDProp, 0, 0, 0 },
791 { VCCountryNameProp, 0, 0, 0 },
792 { VCDAlarmProp, 0, DAlarmFields, 0 },
793 { VCDataSizeProp, 0, 0, PD_INTERNAL },
794 { VCDayLightProp, 0, 0, 0 },
795 { VCDCreatedProp, 0, 0, 0 },
796 { VCDeliveryLabelProp, 0, 0, 0 },
797 { VCDescriptionProp, 0, 0, 0 },
798 { VCDIBProp, 0, 0, 0 },
799 { VCDisplayStringProp, 0, 0, 0 },
800 { VCDomesticProp, 0, 0, 0 },
801 { VCDTendProp, 0, 0, 0 },
802 { VCDTstartProp, 0, 0, 0 },
803 { VCDueProp, 0, 0, 0 },
804 { VCEmailAddressProp, 0, 0, 0 },
805 { VCEncodingProp, 0, 0, 0 },
806 { VCEndProp, 0, 0, 0 },
807 { VCEventProp, 0, 0, PD_BEGIN },
808 { VCEWorldProp, 0, 0, 0 },
809 { VCExNumProp, 0, 0, 0 },
810 { VCExDateProp, 0, 0, 0 },
811 { VCExpectProp, 0, 0, 0 },
812 { VCExtAddressProp, 0, 0, 0 },
813 { VCFamilyNameProp, 0, 0, 0 },
814 { VCFaxProp, 0, 0, 0 },
815 { VCFullNameProp, 0, 0, 0 },
816 { VCGeoLocationProp, 0, 0, 0 },
817 { VCGeoProp, 0, 0, 0 },
818 { VCGIFProp, 0, 0, 0 },
819 { VCGivenNameProp, 0, 0, 0 },
820 { VCGroupingProp, 0, 0, 0 },
821 { VCHomeProp, 0, 0, 0 },
822 { VCIBMMailProp, 0, 0, 0 },
823 { VCInlineProp, 0, 0, 0 },
824 { VCInternationalProp, 0, 0, 0 },
825 { VCInternetProp, 0, 0, 0 },
826 { VCISDNProp, 0, 0, 0 },
827 { VCJPEGProp, 0, 0, 0 },
828 { VCLanguageProp, 0, 0, 0 },
829 { VCLastModifiedProp, 0, 0, 0 },
830 { VCLastRevisedProp, 0, 0, 0 },
831 { VCLocationProp, 0, 0, 0 },
832 { VCLogoProp, 0, 0, 0 },
833 { VCMailerProp, 0, 0, 0 },
834 { VCMAlarmProp, 0, MAlarmFields, 0 },
835 { VCMCIMailProp, 0, 0, 0 },
836 { VCMessageProp, 0, 0, 0 },
837 { VCMETProp, 0, 0, 0 },
838 { VCModemProp, 0, 0, 0 },
839 { VCMPEG2Prop, 0, 0, 0 },
840 { VCMPEGProp, 0, 0, 0 },
841 { VCMSNProp, 0, 0, 0 },
842 { VCNamePrefixesProp, 0, 0, 0 },
843 { VCNameProp, 0, nameFields, 0 },
844 { VCNameSuffixesProp, 0, 0, 0 },
845 { VCNoteProp, 0, 0, 0 },
846 { VCOrgNameProp, 0, 0, 0 },
847 { VCOrgProp, 0, orgFields, 0 },
848 { VCOrgUnit2Prop, 0, 0, 0 },
849 { VCOrgUnit3Prop, 0, 0, 0 },
850 { VCOrgUnit4Prop, 0, 0, 0 },
851 { VCOrgUnitProp, 0, 0, 0 },
852 { VCPagerProp, 0, 0, 0 },
853 { VCPAlarmProp, 0, PAlarmFields, 0 },
854 { VCParcelProp, 0, 0, 0 },
855 { VCPartProp, 0, 0, 0 },
856 { VCPCMProp, 0, 0, 0 },
857 { VCPDFProp, 0, 0, 0 },
858 { VCPGPProp, 0, 0, 0 },
859 { VCPhotoProp, 0, 0, 0 },
860 { VCPICTProp, 0, 0, 0 },
861 { VCPMBProp, 0, 0, 0 },
862 { VCPostalBoxProp, 0, 0, 0 },
863 { VCPostalCodeProp, 0, 0, 0 },
864 { VCPostalProp, 0, 0, 0 },
865 { VCPowerShareProp, 0, 0, 0 },
866 { VCPreferredProp, 0, 0, 0 },
867 { VCPriorityProp, 0, 0, 0 },
868 { VCProcedureNameProp, 0, 0, 0 },
869 { VCProdIdProp, 0, 0, 0 },
870 { VCProdigyProp, 0, 0, 0 },
871 { VCPronunciationProp, 0, 0, 0 },
872 { VCPSProp, 0, 0, 0 },
873 { VCPublicKeyProp, 0, 0, 0 },
874 { VCQPProp, VCQuotedPrintableProp, 0, 0 },
875 { VCQuickTimeProp, 0, 0, 0 },
876 { VCQuotedPrintableProp, 0, 0, 0 },
877 { VCRDateProp, 0, 0, 0 },
878 { VCRegionProp, 0, 0, 0 },
879 { VCRelatedToProp, 0, 0, 0 },
880 { VCRepeatCountProp, 0, 0, 0 },
881 { VCResourcesProp, 0, 0, 0 },
882 { VCRNumProp, 0, 0, 0 },
883 { VCRoleProp, 0, 0, 0 },
884 { VCRRuleProp, 0, 0, 0 },
885 { VCRSVPProp, 0, 0, 0 },
886 { VCRunTimeProp, 0, 0, 0 },
887 { VCSequenceProp, 0, 0, 0 },
888 { VCSnoozeTimeProp, 0, 0, 0 },
889 { VCStartProp, 0, 0, 0 },
890 { VCStatusProp, 0, 0, 0 },
891 { VCStreetAddressProp, 0, 0, 0 },
892 { VCSubTypeProp, 0, 0, 0 },
893 { VCSummaryProp, 0, 0, 0 },
894 { VCTelephoneProp, 0, 0, 0 },
895 { VCTIFFProp, 0, 0, 0 },
896 { VCTimeZoneProp, 0, 0, 0 },
897 { VCTitleProp, 0, 0, 0 },
898 { VCTLXProp, 0, 0, 0 },
899 { VCTodoProp, 0, 0, PD_BEGIN },
900 { VCTranspProp, 0, 0, 0 },
901 { VCUniqueStringProp, 0, 0, 0 },
902 { VCURLProp, 0, 0, 0 },
903 { VCURLValueProp, 0, 0, 0 },
904 { VCValueProp, 0, 0, 0 },
905 { VCVersionProp, 0, 0, 0 },
906 { VCVideoProp, 0, 0, 0 },
907 { VCVoiceProp, 0, 0, 0 },
908 { VCWAVEProp, 0, 0, 0 },
909 { VCWMFProp, 0, 0, 0 },
910 { VCWorkProp, 0, 0, 0 },
911 { VCX400Prop, 0, 0, 0 },
912 { VCX509Prop, 0, 0, 0 },
913 { VCXRuleProp, 0, 0, 0 },
914 { 0,0,0,0 }
915 };
916
917
918static struct PreDefProp* lookupPropInfo(const char* str)
919{
920 /* brute force for now, could use a hash table here. */
921 int i;
922
923 for (i = 0; propNames[i].name; i++)
924 if (strcasecmp(str, propNames[i].name) == 0) {
925 return &propNames[i];
926 }
927
928 return 0;
929}
930
931
932const char* lookupProp_(const char* str)
933{
934 int i;
935
936 for (i = 0; propNames[i].name; i++)
937 if (strcasecmp(str, propNames[i].name) == 0) {
938 const char* s;
939 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
940 return lookupStr(s);
941 }
942 return lookupStr(str);
943}
944
945
946const char* lookupProp(const char* str)
947{
948 int i;
949
950 for (i = 0; propNames[i].name; i++)
951 if (strcasecmp(str, propNames[i].name) == 0) {
952 const char *s;
953 fieldedProp = propNames[i].fields;
954 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
955 return lookupStr(s);
956 }
957 fieldedProp = 0;
958 return lookupStr(str);
959}
960
961
962/*----------------------------------------------------------------------
963 APIs to Output text form.
964 ----------------------------------------------------------------------*/
965#define OFILE_REALLOC_SIZE 256
966typedef struct OFile {
967 FILE *fp;
968 char *s;
969 int len;
970 int limit;
971 int alloc:1;
972 int fail:1;
973 } OFile;
974
975
976/* vCalendar files need crlf linebreaks. The disabled functions didn't provide
977 that. */
978#if 0
979
980static void appendsOFile(OFile *fp, const char *s)
981{
982 int slen;
983 if (fp->fail) return;
984 slen = strlen(s);
985 if (fp->fp) {
986 fwrite(s,1,slen,fp->fp);
987 }
988 else {
989stuff:
990 if (fp->len + slen < fp->limit) {
991 memcpy(fp->s+fp->len,s,slen);
992 fp->len += slen;
993 return;
994 }
995 else if (fp->alloc) {
996 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
997 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
998 if (fp->s)
999 fp->s = realloc(fp->s,fp->limit);
1000 else
1001 fp->s = malloc(fp->limit);
1002 if (fp->s) goto stuff;
1003 }
1004 if (fp->alloc)
1005 free(fp->s);
1006 fp->s = 0;
1007 fp->fail = 1;
1008 }
1009}
1010
1011static void appendcOFile(OFile *fp, char c)
1012{
1013 if (fp->fail) return;
1014 if (fp->fp) {
1015 fputc(c,fp->fp);
1016 }
1017 else {
1018stuff:
1019 if (fp->len+1 < fp->limit) {
1020 fp->s[fp->len] = c;
1021 fp->len++;
1022 return;
1023 }
1024 else if (fp->alloc) {
1025 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
1026 fp->s = realloc(fp->s,fp->limit);
1027 if (fp->s) goto stuff;
1028 }
1029 if (fp->alloc)
1030 free(fp->s);
1031 fp->s = 0;
1032 fp->fail = 1;
1033 }
1034}
1035
1036#else
1037
1038static void appendcOFile_(OFile *fp, char c)
1039{
1040 if (fp->fail) return;
1041 if (fp->fp) {
1042 fputc(c,fp->fp);
1043 }
1044 else {
1045stuff:
1046 if (fp->len+1 < fp->limit) {
1047 fp->s[fp->len] = c;
1048 fp->len++;
1049 return;
1050 }
1051 else if (fp->alloc) {
1052 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
1053 fp->s = realloc(fp->s,fp->limit);
1054 if (fp->s) goto stuff;
1055 }
1056 if (fp->alloc)
1057 free(fp->s);
1058 fp->s = 0;
1059 fp->fail = 1;
1060 }
1061}
1062
1063static void appendcOFile(OFile *fp, char c)
1064{
1065 if (c == '\n') {
1066 /* write out as <CR><LF> */
1067 appendcOFile_(fp,0xd);
1068 appendcOFile_(fp,0xa);
1069 }
1070 else
1071 appendcOFile_(fp,c);
1072}
1073
1074static void appendsOFile(OFile *fp, const char *s)
1075{
1076 int i, slen;
1077 slen = strlen(s);
1078 for (i=0; i<slen; i++) {
1079 appendcOFile(fp,s[i]);
1080 }
1081}
1082
1083#endif
1084
1085static void initOFile(OFile *fp, FILE *ofp)
1086{
1087 fp->fp = ofp;
1088 fp->s = 0;
1089 fp->len = 0;
1090 fp->limit = 0;
1091 fp->alloc = 0;
1092 fp->fail = 0;
1093}
1094
1095static void initMemOFile(OFile *fp, char *s, int len)
1096{
1097 fp->fp = 0;
1098 fp->s = s;
1099 fp->len = 0;
1100 fp->limit = s?len:0;
1101 fp->alloc = s?0:1;
1102 fp->fail = 0;
1103}
1104
1105
1106static int writeBase64(OFile *fp, unsigned char *s, long len)
1107{
1108 long cur = 0;
1109 int i, numQuads = 0;
1110 unsigned long trip;
1111 unsigned char b;
1112 char quad[5];
1113#define MAXQUADS 16
1114
1115 quad[4] = 0;
1116
1117 while (cur < len) {
1118 /* collect the triplet of bytes into 'trip' */
1119 trip = 0;
1120 for (i = 0; i < 3; i++) {
1121 b = (cur < len) ? *(s + cur) : 0;
1122 cur++;
1123 trip = trip << 8 | b;
1124 }
1125 /* fill in 'quad' with the appropriate four characters */
1126 for (i = 3; i >= 0; i--) {
1127 b = (unsigned char)(trip & 0x3F);
1128 trip = trip >> 6;
1129 if ((3 - i) < (cur - len))
1130 quad[i] = '='; /* pad char */
1131 else if (b < 26) quad[i] = (char)b + 'A';
1132 else if (b < 52) quad[i] = (char)(b - 26) + 'a';
1133 else if (b < 62) quad[i] = (char)(b - 52) + '0';
1134 else if (b == 62) quad[i] = '+';
1135 else quad[i] = '/';
1136 }
1137 /* now output 'quad' with appropriate whitespace and line ending */
1138 appendsOFile(fp, (numQuads == 0 ? " " : ""));
1139 appendsOFile(fp, quad);
1140 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
1141 numQuads = (numQuads + 1) % MAXQUADS;
1142 }
1143 appendcOFile(fp,'\n');
1144
1145 return 1;
1146}
1147
1148/* this function really sucks. Too basic. */
1149static void writeQPString(OFile *fp, const char *s, int qp)
1150{
1151 const char *p = s;
1152 while (*p) {
1153 if (*p == '\n') {
1154 if (p[1]) appendsOFile(fp,"=0A=");
1155 }
1156 if (*p == '=' && qp)
1157 appendsOFile(fp,"=3D");
1158 else
1159 appendcOFile(fp,*p);
1160 p++;
1161 }
1162}
1163
1164static void writeVObject_(OFile *fp, VObject *o);
1165
1166static void writeValue(OFile *fp, VObject *o, unsigned long size)
1167{
1168 if (o == 0) return;
1169 switch (VALUE_TYPE(o)) {
1170 case VCVT_USTRINGZ: {
1171 char *s = fakeCString(USTRINGZ_VALUE_OF(o));
1172 if (isAPropertyOf(o, VCQuotedPrintableProp))
1173 writeQPString(fp, s, 1);
1174 else
1175 writeQPString(fp, s, 0);
1176 deleteStr(s);
1177 break;
1178 }
1179 case VCVT_STRINGZ: {
1180 if (isAPropertyOf(o, VCQuotedPrintableProp))
1181 writeQPString(fp, STRINGZ_VALUE_OF(o), 1);
1182 else
1183 writeQPString(fp, STRINGZ_VALUE_OF(o), 0);
1184 break;
1185 }
1186 case VCVT_UINT: {
1187 char buf[16];
1188 sprintf(buf,"%u", INTEGER_VALUE_OF(o));
1189 appendsOFile(fp,buf);
1190 break;
1191 }
1192 case VCVT_ULONG: {
1193 char buf[16];
1194 sprintf(buf,"%lu", LONG_VALUE_OF(o));
1195 appendsOFile(fp,buf);
1196 break;
1197 }
1198 case VCVT_RAW: {
1199 appendcOFile(fp,'\n');
1200 writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
1201 break;
1202 }
1203 case VCVT_VOBJECT:
1204 appendcOFile(fp,'\n');
1205 writeVObject_(fp,VOBJECT_VALUE_OF(o));
1206 break;
1207 }
1208}
1209
1210static void writeAttrValue(OFile *fp, VObject *o)
1211{
1212 if (NAME_OF(o)) {
1213 struct PreDefProp *pi;
1214 pi = lookupPropInfo(NAME_OF(o));
1215 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
1216 appendcOFile(fp,';');
1217 appendsOFile(fp,NAME_OF(o));
1218 }
1219 else
1220 appendcOFile(fp,';');
1221 if (VALUE_TYPE(o)) {
1222 appendcOFile(fp,'=');
1223 writeValue(fp,o,0);
1224 }
1225}
1226
1227static void writeGroup(OFile *fp, VObject *o)
1228{
1229 char buf1[256];
1230 char buf2[256];
1231 strcpy(buf1,NAME_OF(o));
1232 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
1233 strncpy(buf2,STRINGZ_VALUE_OF(o),sizeof(buf2));
1234 buf2[sizeof(buf2)] = '\0';
1235 strncat(buf2,".",sizeof(buf2)-strlen(buf2)-1);
1236 strncat(buf2,buf1,sizeof(buf2)-strlen(buf2)-1);
1237 strcpy(buf1,buf2);
1238 }
1239 appendsOFile(fp,buf1);
1240}
1241
1242static int inList(const char **list, const char *s)
1243{
1244 if (list == 0) return 0;
1245 while (*list) {
1246 if (strcasecmp(*list,s) == 0) return 1;
1247 list++;
1248 }
1249 return 0;
1250}
1251
1252static void writeProp(OFile *fp, VObject *o)
1253{
1254 if (NAME_OF(o)) {
1255 struct PreDefProp *pi;
1256 VObjectIterator t;
1257 const char **fields_ = 0;
1258 pi = lookupPropInfo(NAME_OF(o));
1259 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1260 writeVObject_(fp,o);
1261 return;
1262 }
1263 if (isAPropertyOf(o,VCGroupingProp))
1264 writeGroup(fp,o);
1265 else
1266 appendsOFile(fp,NAME_OF(o));
1267 if (pi) fields_ = pi->fields;
1268 initPropIterator(&t,o);
1269 while (moreIteration(&t)) {
1270 const char *s;
1271 VObject *eachProp = nextVObject(&t);
1272 s = NAME_OF(eachProp);
1273 if (strcasecmp(VCGroupingProp,s) && !inList(fields_,s))
1274 writeAttrValue(fp,eachProp);
1275 }
1276 if (fields_) {
1277 int i = 0, n = 0;
1278 const char** fields = fields_;
1279 /* output prop as fields */
1280 appendcOFile(fp,':');
1281 while (*fields) {
1282 VObject *tl = isAPropertyOf(o,*fields);
1283 i++;
1284 if (tl) n = i;
1285 fields++;
1286 }
1287 fields = fields_;
1288 for (i=0;i<n;i++) {
1289 writeValue(fp,isAPropertyOf(o,*fields),0);
1290 fields++;
1291 if (i<(n-1)) appendcOFile(fp,';');
1292 }
1293 }
1294 }
1295
1296 if (VALUE_TYPE(o)) {
1297 unsigned long size = 0;
1298 VObject *p = isAPropertyOf(o,VCDataSizeProp);
1299 if (p) size = LONG_VALUE_OF(p);
1300 appendcOFile(fp,':');
1301 writeValue(fp,o,size);
1302 }
1303
1304 appendcOFile(fp,'\n');
1305}
1306
1307static void writeVObject_(OFile *fp, VObject *o)
1308{
1309 if (NAME_OF(o)) {
1310 struct PreDefProp *pi;
1311 pi = lookupPropInfo(NAME_OF(o));
1312
1313 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1314 VObjectIterator t;
1315 const char *begin = NAME_OF(o);
1316 appendsOFile(fp,"BEGIN:");
1317 appendsOFile(fp,begin);
1318 appendcOFile(fp,'\n');
1319 initPropIterator(&t,o);
1320 while (moreIteration(&t)) {
1321 VObject *eachProp = nextVObject(&t);
1322 writeProp(fp, eachProp);
1323 }
1324 appendsOFile(fp,"END:");
1325 appendsOFile(fp,begin);
1326 appendsOFile(fp,"\n\n");
1327 }
1328 }
1329}
1330
1331void writeVObject(FILE *fp, VObject *o)
1332{
1333 OFile ofp;
1334 initOFile(&ofp,fp);
1335 writeVObject_(&ofp,o);
1336}
1337
1338void writeVObjectToFile(char *fname, VObject *o)
1339{
1340 FILE *fp = fopen(fname,"w");
1341 if (fp) {
1342 writeVObject(fp,o);
1343 fclose(fp);
1344 }
1345}
1346
1347void writeVObjectsToFile(char *fname, VObject *list)
1348{
1349 FILE *fp = fopen(fname,"w");
1350 if (fp) {
1351 while (list) {
1352 writeVObject(fp,list);
1353 list = nextVObjectInList(list);
1354 }
1355 fclose(fp);
1356 }
1357}
1358
1359char* writeMemVObject(char *s, int *len, VObject *o)
1360{
1361 OFile ofp;
1362 initMemOFile(&ofp,s,len?*len:0);
1363 writeVObject_(&ofp,o);
1364 if (len) *len = ofp.len;
1365 appendcOFile(&ofp,0);
1366 return ofp.s;
1367}
1368
1369char* writeMemVObjects(char *s, int *len, VObject *list)
1370{
1371 OFile ofp;
1372 initMemOFile(&ofp,s,len?*len:0);
1373 while (list) {
1374 writeVObject_(&ofp,list);
1375 list = nextVObjectInList(list);
1376 }
1377 if (len) *len = ofp.len;
1378 appendcOFile(&ofp,0);
1379 return ofp.s;
1380}
1381
1382/*----------------------------------------------------------------------
1383 APIs to do fake Unicode stuff.
1384 ----------------------------------------------------------------------*/
1385wchar_t* fakeUnicode(const char *ps, int *bytes)
1386{
1387 wchar_t *r, *pw;
1388 int len = strlen(ps)+1;
1389
1390 pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len);
1391 if (bytes)
1392 *bytes = len * sizeof(wchar_t);
1393
1394 while (*ps) {
1395 if (*ps == '\n')
1396 *pw = (wchar_t)0x2028;
1397 else if (*ps == '\r')
1398 *pw = (wchar_t)0x2029;
1399 else
1400 *pw = (wchar_t)(unsigned char)*ps;
1401 ps++; pw++;
1402 }
1403 *pw = (wchar_t)0;
1404
1405 return r;
1406}
1407
1408int uStrLen(const wchar_t *u)
1409{
1410 int i = 0;
1411 while (*u != (wchar_t)0) { u++; i++; }
1412 return i;
1413}
1414
1415char* fakeCString(const wchar_t *u)
1416{
1417 char *s, *t;
1418 int len = uStrLen(u) + 1;
1419 t = s = (char*)malloc(len+1);
1420 while (*u) {
1421 if (*u == (wchar_t)0x2028)
1422 *t = '\n';
1423 else if (*u == (wchar_t)0x2029)
1424 *t = '\r';
1425 else
1426 *t = (char)*u;
1427 u++; t++;
1428 }
1429 *t = 0;
1430 return s;
1431}
1432
1433/* end of source file vobject.c */