summaryrefslogtreecommitdiff
path: root/library/backend/vobject.cpp
Unidiff
Diffstat (limited to 'library/backend/vobject.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/backend/vobject.cpp1210
1 files changed, 1210 insertions, 0 deletions
diff --git a/library/backend/vobject.cpp b/library/backend/vobject.cpp
new file mode 100644
index 0000000..af112a7
--- a/dev/null
+++ b/library/backend/vobject.cpp
@@ -0,0 +1,1210 @@
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 #ifndef MWERKS
46#include <malloc.h>
47#endif
48
49#include "vobject_p.h"
50#include "qfiledirect_p.h"
51#include <string.h>
52#include <stdio.h>
53#include <fcntl.h>
54//#include <io.h>
55
56
57 #define NAME_OF(o) o->id
58 #define VALUE_TYPE(o) o->valType
59 #define STRINGZ_VALUE_OF(o) o->val.strs
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
65typedef union ValueItem {
66 const char *strs;
67 unsigned int i;
68 unsigned long l;
69 void *any;
70 VObject *vobj;
71 } ValueItem;
72
73struct VObject {
74 VObject *next;
75 const char *id;
76 VObject *prop;
77 unsigned short valType;
78 ValueItem val;
79 };
80
81typedef struct StrItem StrItem;
82
83struct StrItem {
84 StrItem *next;
85 const char *s;
86 unsigned int refCnt;
87 };
88
89const char** fieldedProp;
90
91
92
93/*----------------------------------------------------------------------
94 The following functions involve with memory allocation:
95 newVObject
96 deleteVObject
97 dupStr
98 deleteStr
99 newStrItem
100 deleteStrItem
101 ----------------------------------------------------------------------*/
102
103DLLEXPORT(VObject*) newVObject_(const char *id)
104{
105 VObject *p = (VObject*)malloc(sizeof(VObject));
106 p->next = 0;
107 p->id = id;
108 p->prop = 0;
109 VALUE_TYPE(p) = 0;
110 ANY_VALUE_OF(p) = 0;
111 return p;
112}
113
114DLLEXPORT(VObject*) newVObject(const char *id)
115{
116 return newVObject_(lookupStr(id));
117}
118
119DLLEXPORT(void) deleteVObject(VObject *p)
120{
121 unUseStr(p->id);
122 free(p);
123}
124
125DLLEXPORT(char*) dupStr(const char *s, unsigned int size)
126{
127 char *t;
128 if (size == 0) {
129 size = strlen(s);
130 }
131 t = (char*)malloc(size+1);
132 if (t) {
133 memcpy(t,s,size);
134 t[size] = 0;
135 return t;
136 }
137 else {
138 return (char*)0;
139 }
140}
141
142DLLEXPORT(void) deleteStr(const char *p)
143{
144 if (p) free((void*)p);
145}
146
147
148static StrItem* newStrItem(const char *s, StrItem *next)
149{
150 StrItem *p = (StrItem*)malloc(sizeof(StrItem));
151 p->next = next;
152 p->s = s;
153 p->refCnt = 1;
154 return p;
155}
156
157static void deleteStrItem(StrItem *p)
158{
159 free((void*)p);
160}
161
162
163/*----------------------------------------------------------------------
164 The following function provide accesses to VObject's value.
165 ----------------------------------------------------------------------*/
166
167DLLEXPORT(const char*) vObjectName(VObject *o)
168{
169 return NAME_OF(o);
170}
171
172DLLEXPORT(void) setVObjectName(VObject *o, const char* id)
173{
174 NAME_OF(o) = id;
175}
176
177DLLEXPORT(const char*) vObjectStringZValue(VObject *o)
178{
179 return STRINGZ_VALUE_OF(o);
180}
181
182DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s)
183{
184 STRINGZ_VALUE_OF(o) = dupStr(s,0);
185 VALUE_TYPE(o) = VCVT_STRINGZ;
186}
187
188DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s)
189{
190 STRINGZ_VALUE_OF(o) = s;
191 VALUE_TYPE(o) = VCVT_STRINGZ;
192}
193
194DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o)
195{
196 return INTEGER_VALUE_OF(o);
197}
198
199DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i)
200{
201 INTEGER_VALUE_OF(o) = i;
202 VALUE_TYPE(o) = VCVT_UINT;
203}
204
205DLLEXPORT(unsigned long) vObjectLongValue(VObject *o)
206{
207 return LONG_VALUE_OF(o);
208}
209
210DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l)
211{
212 LONG_VALUE_OF(o) = l;
213 VALUE_TYPE(o) = VCVT_ULONG;
214}
215
216DLLEXPORT(void*) vObjectAnyValue(VObject *o)
217{
218 return ANY_VALUE_OF(o);
219}
220
221DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t)
222{
223 ANY_VALUE_OF(o) = t;
224 VALUE_TYPE(o) = VCVT_RAW;
225}
226
227DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o)
228{
229 return VOBJECT_VALUE_OF(o);
230}
231
232DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p)
233{
234 VOBJECT_VALUE_OF(o) = p;
235 VALUE_TYPE(o) = VCVT_VOBJECT;
236}
237
238DLLEXPORT(int) 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
248DLLEXPORT(VObject*) 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
283DLLEXPORT(VObject*) addProp(VObject *o, const char *id)
284{
285 return addVObjectProp(o,newVObject(id));
286}
287
288DLLEXPORT(VObject*) addProp_(VObject *o, const char *id)
289{
290 return addVObjectProp(o,newVObject_(id));
291}
292
293DLLEXPORT(void) 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
308DLLEXPORT(VObject*) nextVObjectInList(VObject *o)
309{
310 return o->next;
311}
312
313DLLEXPORT(VObject*) 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
322DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size)
323{
324 void *p = dupStr((const char *)val,size);
325 return setValueWithSize_(prop,p,p?size:0);
326}
327
328DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o)
329{
330 i->start = o->prop;
331 i->next = 0;
332}
333
334DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o)
335{
336 i->start = o->next;
337 i->next = 0;
338}
339
340DLLEXPORT(int) moreIteration(VObjectIterator *i)
341{
342 return (i->start && (i->next==0 || i->next!=i->start));
343}
344
345DLLEXPORT(VObject*) 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
360DLLEXPORT(VObject*) 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 (!qstricmp(id,each->id))
367 return each;
368 }
369 return (VObject*)0;
370}
371
372DLLEXPORT(VObject*) 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
413DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v)
414{
415 VObject *prop;
416 prop = addProp(o,p);
417 setVObjectStringZValue_(prop, strdup( v ) );
418 return prop;
419}
420
421DLLEXPORT(VObject*) 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
430DLLEXPORT(VObject*) 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
437DLLEXPORT(void) cleanVObject(VObject *o)
438{
439 if (o == 0) return;
440 if (o->prop) {
441 /* destroy time: cannot use the iterator here.
442 Have to break the cycle in the circular link
443 list and turns it into regular NULL-terminated
444 list -- since at some point of destruction,
445 the reference entry for the iterator to work
446 will not longer be valid.
447 */
448 VObject *p;
449 p = o->prop->next;
450 o->prop->next = 0;
451 do {
452 VObject *t = p->next;
453 cleanVObject(p);
454 p = t;
455 } while (p);
456 }
457 switch (VALUE_TYPE(o)) {
458 case VCVT_STRINGZ:
459 case VCVT_RAW:
460 // assume they are all allocated by malloc.
461 free((char*)STRINGZ_VALUE_OF(o));
462 break;
463 case VCVT_VOBJECT:
464 cleanVObject(VOBJECT_VALUE_OF(o));
465 break;
466 }
467 deleteVObject(o);
468}
469
470DLLEXPORT(void) cleanVObjects(VObject *list)
471{
472 while (list) {
473 VObject *t = list;
474 list = nextVObjectInList(list);
475 cleanVObject(t);
476 }
477}
478
479/*----------------------------------------------------------------------
480 The following is a String Table Facilities.
481 ----------------------------------------------------------------------*/
482
483#define STRTBLSIZE 255
484
485static StrItem *strTbl[STRTBLSIZE];
486
487static unsigned int hashStr(const char *s)
488{
489 unsigned int h = 0;
490 int i;
491 for (i=0;s[i];i++) {
492 h += s[i]*i;
493 }
494 return h % STRTBLSIZE;
495}
496
497DLLEXPORT(const char*) lookupStr(const char *s)
498{
499 StrItem *t;
500 unsigned int h = hashStr(s);
501 if ((t = strTbl[h]) != 0) {
502 do {
503 if (qstricmp(t->s,s) == 0) {
504 t->refCnt++;
505 return t->s;
506 }
507 t = t->next;
508 } while (t);
509 }
510 s = dupStr(s,0);
511 strTbl[h] = newStrItem(s,strTbl[h]);
512 return s;
513}
514
515DLLEXPORT(void) unUseStr(const char *s)
516{
517 StrItem *t, *p;
518 unsigned int h = hashStr(s);
519 if ((t = strTbl[h]) != 0) {
520 p = t;
521 do {
522 if (qstricmp(t->s,s) == 0) {
523 t->refCnt--;
524 if (t->refCnt == 0) {
525 if (p == strTbl[h]) {
526 strTbl[h] = t->next;
527 }
528 else {
529 p->next = t->next;
530 }
531 deleteStr(t->s);
532 deleteStrItem(t);
533 return;
534 }
535 }
536 p = t;
537 t = t->next;
538 } while (t);
539 }
540}
541
542DLLEXPORT(void) cleanStrTbl()
543{
544 int i;
545 for (i=0; i<STRTBLSIZE;i++) {
546 StrItem *t = strTbl[i];
547 while (t) {
548 StrItem *p;
549 deleteStr(t->s);
550 p = t;
551 t = t->next;
552 deleteStrItem(p);
553 } while (t);
554 strTbl[i] = 0;
555 }
556}
557
558
559struct PreDefProp {
560 const char *name;
561 const char *alias;
562 const char** fields;
563 unsigned int flags;
564 };
565
566/* flags in PreDefProp */
567 #define PD_BEGIN0x1
568 #define PD_INTERNAL0x2
569
570static const char *adrFields[] = {
571 VCPostalBoxProp,
572 VCExtAddressProp,
573 VCStreetAddressProp,
574 VCCityProp,
575 VCRegionProp,
576 VCPostalCodeProp,
577 VCCountryNameProp,
578 0
579};
580
581static const char *nameFields[] = {
582 VCFamilyNameProp,
583 VCGivenNameProp,
584 VCAdditionalNamesProp,
585 VCNamePrefixesProp,
586 VCNameSuffixesProp,
587 NULL
588 };
589
590static const char *orgFields[] = {
591 VCOrgNameProp,
592 VCOrgUnitProp,
593 VCOrgUnit2Prop,
594 VCOrgUnit3Prop,
595 VCOrgUnit4Prop,
596 NULL
597 };
598
599static const char *AAlarmFields[] = {
600 VCRunTimeProp,
601 VCSnoozeTimeProp,
602 VCRepeatCountProp,
603 VCAudioContentProp,
604 0
605 };
606
607/* ExDate -- has unamed fields */
608/* RDate -- has unamed fields */
609
610static const char *DAlarmFields[] = {
611 VCRunTimeProp,
612 VCSnoozeTimeProp,
613 VCRepeatCountProp,
614 VCDisplayStringProp,
615 0
616 };
617
618static const char *MAlarmFields[] = {
619 VCRunTimeProp,
620 VCSnoozeTimeProp,
621 VCRepeatCountProp,
622 VCEmailAddressProp,
623 VCNoteProp,
624 0
625 };
626
627static const char *PAlarmFields[] = {
628 VCRunTimeProp,
629 VCSnoozeTimeProp,
630 VCRepeatCountProp,
631 VCProcedureNameProp,
632 0
633 };
634
635static struct PreDefProp propNames[] = {
636 { VC7bitProp, 0, 0, 0 },
637 { VC8bitProp, 0, 0, 0 },
638 { VCAAlarmProp, 0, AAlarmFields, 0 },
639 { VCAdditionalNamesProp, 0, 0, 0 },
640 { VCAdrProp, 0, adrFields, 0 },
641 { VCAgentProp, 0, 0, 0 },
642 { VCAIFFProp, 0, 0, 0 },
643 { VCAOLProp, 0, 0, 0 },
644 { VCAppleLinkProp, 0, 0, 0 },
645 { VCAttachProp, 0, 0, 0 },
646 { VCAttendeeProp, 0, 0, 0 },
647 { VCATTMailProp, 0, 0, 0 },
648 { VCAudioContentProp, 0, 0, 0 },
649 { VCAVIProp, 0, 0, 0 },
650 { VCBase64Prop, 0, 0, 0 },
651 { VCBBSProp, 0, 0, 0 },
652 { VCBirthDateProp, 0, 0, 0 },
653 { VCBMPProp, 0, 0, 0 },
654 { VCBodyProp, 0, 0, 0 },
655 { VCBusinessRoleProp, 0, 0, 0 },
656 { VCCalProp, 0, 0, PD_BEGIN },
657 { VCCaptionProp, 0, 0, 0 },
658 { VCCardProp, 0, 0, PD_BEGIN },
659 { VCCarProp, 0, 0, 0 },
660 { VCCategoriesProp, 0, 0, 0 },
661 { VCCellularProp, 0, 0, 0 },
662 { VCCGMProp, 0, 0, 0 },
663 { VCCharSetProp, 0, 0, 0 },
664 { VCCIDProp, VCContentIDProp, 0, 0 },
665 { VCCISProp, 0, 0, 0 },
666 { VCCityProp, 0, 0, 0 },
667 { VCClassProp, 0, 0, 0 },
668 { VCCommentProp, 0, 0, 0 },
669 { VCCompletedProp, 0, 0, 0 },
670 { VCContentIDProp, 0, 0, 0 },
671 { VCCountryNameProp, 0, 0, 0 },
672 { VCDAlarmProp, 0, DAlarmFields, 0 },
673 { VCDataSizeProp, 0, 0, PD_INTERNAL },
674 { VCDayLightProp, 0, 0, 0 },
675 { VCDCreatedProp, 0, 0, 0 },
676 { VCDeliveryLabelProp, 0, 0, 0 },
677 { VCDescriptionProp, 0, 0, 0 },
678 { VCDIBProp, 0, 0, 0 },
679 { VCDisplayStringProp, 0, 0, 0 },
680 { VCDomesticProp, 0, 0, 0 },
681 { VCDTendProp, 0, 0, 0 },
682 { VCDTstartProp, 0, 0, 0 },
683 { VCDueProp, 0, 0, 0 },
684 { VCEmailAddressProp, 0, 0, 0 },
685 { VCEncodingProp, 0, 0, 0 },
686 { VCEndProp, 0, 0, 0 },
687 { VCEventProp, 0, 0, PD_BEGIN },
688 { VCEWorldProp, 0, 0, 0 },
689 { VCExNumProp, 0, 0, 0 },
690 { VCExpDateProp, 0, 0, 0 },
691 { VCExpectProp, 0, 0, 0 },
692 { VCExtAddressProp, 0, 0, 0 },
693 { VCFamilyNameProp, 0, 0, 0 },
694 { VCFaxProp, 0, 0, 0 },
695 { VCFullNameProp, 0, 0, 0 },
696 { VCGeoLocationProp, 0, 0, 0 },
697 { VCGeoProp, 0, 0, 0 },
698 { VCGIFProp, 0, 0, 0 },
699 { VCGivenNameProp, 0, 0, 0 },
700 { VCGroupingProp, 0, 0, 0 },
701 { VCHomeProp, 0, 0, 0 },
702 { VCIBMMailProp, 0, 0, 0 },
703 { VCInlineProp, 0, 0, 0 },
704 { VCInternationalProp, 0, 0, 0 },
705 { VCInternetProp, 0, 0, 0 },
706 { VCISDNProp, 0, 0, 0 },
707 { VCJPEGProp, 0, 0, 0 },
708 { VCLanguageProp, 0, 0, 0 },
709 { VCLastModifiedProp, 0, 0, 0 },
710 { VCLastRevisedProp, 0, 0, 0 },
711 { VCLocationProp, 0, 0, 0 },
712 { VCLogoProp, 0, 0, 0 },
713 { VCMailerProp, 0, 0, 0 },
714 { VCMAlarmProp, 0, MAlarmFields, 0 },
715 { VCMCIMailProp, 0, 0, 0 },
716 { VCMessageProp, 0, 0, 0 },
717 { VCMETProp, 0, 0, 0 },
718 { VCModemProp, 0, 0, 0 },
719 { VCMPEG2Prop, 0, 0, 0 },
720 { VCMPEGProp, 0, 0, 0 },
721 { VCMSNProp, 0, 0, 0 },
722 { VCNamePrefixesProp, 0, 0, 0 },
723 { VCNameProp, 0, nameFields, 0 },
724 { VCNameSuffixesProp, 0, 0, 0 },
725 { VCNoteProp, 0, 0, 0 },
726 { VCOrgNameProp, 0, 0, 0 },
727 { VCOrgProp, 0, orgFields, 0 },
728 { VCOrgUnit2Prop, 0, 0, 0 },
729 { VCOrgUnit3Prop, 0, 0, 0 },
730 { VCOrgUnit4Prop, 0, 0, 0 },
731 { VCOrgUnitProp, 0, 0, 0 },
732 { VCPagerProp, 0, 0, 0 },
733 { VCPAlarmProp, 0, PAlarmFields, 0 },
734 { VCParcelProp, 0, 0, 0 },
735 { VCPartProp, 0, 0, 0 },
736 { VCPCMProp, 0, 0, 0 },
737 { VCPDFProp, 0, 0, 0 },
738 { VCPGPProp, 0, 0, 0 },
739 { VCPhotoProp, 0, 0, 0 },
740 { VCPICTProp, 0, 0, 0 },
741 { VCPMBProp, 0, 0, 0 },
742 { VCPostalBoxProp, 0, 0, 0 },
743 { VCPostalCodeProp, 0, 0, 0 },
744 { VCPostalProp, 0, 0, 0 },
745 { VCPowerShareProp, 0, 0, 0 },
746 { VCPreferredProp, 0, 0, 0 },
747 { VCPriorityProp, 0, 0, 0 },
748 { VCProcedureNameProp, 0, 0, 0 },
749 { VCProdIdProp, 0, 0, 0 },
750 { VCProdigyProp, 0, 0, 0 },
751 { VCPronunciationProp, 0, 0, 0 },
752 { VCPSProp, 0, 0, 0 },
753 { VCPublicKeyProp, 0, 0, 0 },
754 { VCQPProp, VCQuotedPrintableProp, 0, 0 },
755 { VCQuickTimeProp, 0, 0, 0 },
756 { VCQuotedPrintableProp, 0, 0, 0 },
757 { VCRDateProp, 0, 0, 0 },
758 { VCRegionProp, 0, 0, 0 },
759 { VCRelatedToProp, 0, 0, 0 },
760 { VCRepeatCountProp, 0, 0, 0 },
761 { VCResourcesProp, 0, 0, 0 },
762 { VCRNumProp, 0, 0, 0 },
763 { VCRoleProp, 0, 0, 0 },
764 { VCRRuleProp, 0, 0, 0 },
765 { VCRSVPProp, 0, 0, 0 },
766 { VCRunTimeProp, 0, 0, 0 },
767 { VCSequenceProp, 0, 0, 0 },
768 { VCSnoozeTimeProp, 0, 0, 0 },
769 { VCStartProp, 0, 0, 0 },
770 { VCStatusProp, 0, 0, 0 },
771 { VCStreetAddressProp, 0, 0, 0 },
772 { VCSubTypeProp, 0, 0, 0 },
773 { VCSummaryProp, 0, 0, 0 },
774 { VCTelephoneProp, 0, 0, 0 },
775 { VCTIFFProp, 0, 0, 0 },
776 { VCTimeZoneProp, 0, 0, 0 },
777 { VCTitleProp, 0, 0, 0 },
778 { VCTLXProp, 0, 0, 0 },
779 { VCTodoProp, 0, 0, PD_BEGIN },
780 { VCTranspProp, 0, 0, 0 },
781 { VCUniqueStringProp, 0, 0, 0 },
782 { VCURLProp, 0, 0, 0 },
783 { VCURLValueProp, 0, 0, 0 },
784 { VCValueProp, 0, 0, 0 },
785 { VCVersionProp, 0, 0, 0 },
786 { VCVideoProp, 0, 0, 0 },
787 { VCVoiceProp, 0, 0, 0 },
788 { VCWAVEProp, 0, 0, 0 },
789 { VCWMFProp, 0, 0, 0 },
790 { VCWorkProp, 0, 0, 0 },
791 { VCX400Prop, 0, 0, 0 },
792 { VCX509Prop, 0, 0, 0 },
793 { VCXRuleProp, 0, 0, 0 },
794 { 0,0,0,0 }
795 };
796
797
798static struct PreDefProp* lookupPropInfo(const char* str)
799{
800 /* brute force for now, could use a hash table here. */
801 int i;
802
803 for (i = 0; propNames[i].name; i++)
804 if (qstricmp(str, propNames[i].name) == 0) {
805 return &propNames[i];
806 }
807
808 return 0;
809}
810
811
812DLLEXPORT(const char*) lookupProp_(const char* str)
813{
814 int i;
815
816 for (i = 0; propNames[i].name; i++)
817 if (qstricmp(str, propNames[i].name) == 0) {
818 const char* s;
819 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
820 return lookupStr(s);
821 }
822 return lookupStr(str);
823}
824
825
826DLLEXPORT(const char*) lookupProp(const char* str)
827{
828 int i;
829
830 for (i = 0; propNames[i].name; i++)
831 if (qstricmp(str, propNames[i].name) == 0) {
832 const char *s;
833 fieldedProp = propNames[i].fields;
834 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
835 return lookupStr(s);
836 }
837 fieldedProp = 0;
838 return lookupStr(str);
839}
840
841
842/*----------------------------------------------------------------------
843 APIs to Output text form.
844 ----------------------------------------------------------------------*/
845#define OFILE_REALLOC_SIZE 256
846typedef struct OFile {
847 FILE *fp;
848 char *s;
849 int len;
850 int limit;
851 int alloc:1;
852 int fail:1;
853 } OFile;
854
855#if 0
856static void appendsOFile(OFile *fp, const char *s)
857{
858 int slen;
859 if (fp->fail) return;
860 slen = strlen(s);
861 if (fp->fp) {
862 fwrite(s,1,slen,fp->fp);
863 }
864 else {
865stuff:
866 if (fp->len + slen < fp->limit) {
867 memcpy(fp->s+fp->len,s,slen);
868 fp->len += slen;
869 return;
870 }
871 else if (fp->alloc) {
872 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
873 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
874 fp->s = (char *) realloc(fp->s,fp->limit);
875 if (fp->s) goto stuff;
876 }
877 if (fp->alloc)
878 free(fp->s);
879 fp->s = 0;
880 fp->fail = 1;
881 }
882}
883
884static void appendcOFile(OFile *fp, char c)
885{
886 if (fp->fail) return;
887 if (fp->fp) {
888 fputc(c,fp->fp);
889 }
890 else {
891stuff:
892 if (fp->len+1 < fp->limit) {
893 fp->s[fp->len] = c;
894 fp->len++;
895 return;
896 }
897 else if (fp->alloc) {
898 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
899 fp->s = (char *) realloc(fp->s,fp->limit);
900 if (fp->s) goto stuff;
901 }
902 if (fp->alloc)
903 free(fp->s);
904 fp->s = 0;
905 fp->fail = 1;
906 }
907}
908#else
909static void appendcOFile_(OFile *fp, char c)
910{
911 if (fp->fail) return;
912 if (fp->fp) {
913 fputc(c,fp->fp);
914 }
915 else {
916stuff:
917 if (fp->len+1 < fp->limit) {
918 fp->s[fp->len] = c;
919 fp->len++;
920 return;
921 }
922 else if (fp->alloc) {
923 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
924 fp->s = (char *)realloc(fp->s,fp->limit);
925 if (fp->s) goto stuff;
926 }
927 if (fp->alloc)
928 free(fp->s);
929 fp->s = 0;
930 fp->fail = 1;
931 }
932}
933
934static void appendcOFile(OFile *fp, char c)
935{
936 if (c == '\n') {
937 /* write out as <CR><LF> */
938 appendcOFile_(fp,0xd);
939 appendcOFile_(fp,0xa);
940 }
941 else
942 appendcOFile_(fp,c);
943}
944
945static void appendsOFile(OFile *fp, const char *s)
946{
947 int i, slen;
948 slen = strlen(s);
949 for (i=0; i<slen; i++) {
950 appendcOFile(fp,s[i]);
951 }
952}
953
954#endif
955
956static void initOFile(OFile *fp, FILE *ofp)
957{
958 fp->fp = ofp;
959 fp->s = 0;
960 fp->len = 0;
961 fp->limit = 0;
962 fp->alloc = 0;
963 fp->fail = 0;
964}
965
966static int writeBase64(OFile *fp, unsigned char *s, long len)
967{
968 long cur = 0;
969 int i, numQuads = 0;
970 unsigned long trip;
971 unsigned char b;
972 char quad[5];
973#define MAXQUADS 16
974
975 quad[4] = 0;
976
977 while (cur < len) {
978 // collect the triplet of bytes into 'trip'
979 trip = 0;
980 for (i = 0; i < 3; i++) {
981 b = (cur < len) ? *(s + cur) : 0;
982 cur++;
983 trip = trip << 8 | b;
984 }
985 // fill in 'quad' with the appropriate four characters
986 for (i = 3; i >= 0; i--) {
987 b = (unsigned char)(trip & 0x3F);
988 trip = trip >> 6;
989 if ((3 - i) < (cur - len))
990 quad[i] = '='; // pad char
991 else if (b < 26) quad[i] = (char)b + 'A';
992 else if (b < 52) quad[i] = (char)(b - 26) + 'a';
993 else if (b < 62) quad[i] = (char)(b - 52) + '0';
994 else if (b == 62) quad[i] = '+';
995 else quad[i] = '/';
996 }
997 // now output 'quad' with appropriate whitespace and line ending
998 appendsOFile(fp, (numQuads == 0 ? " " : ""));
999 appendsOFile(fp, quad);
1000 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
1001 numQuads = (numQuads + 1) % MAXQUADS;
1002 }
1003 appendcOFile(fp,'\n');
1004
1005 return 1;
1006}
1007
1008static void writeQPString(OFile *fp, const char *s)
1009{
1010 const char *p = s;
1011 while (*p) {
1012 if (*p == '\n') {
1013 if (p[1]) appendsOFile(fp,"=0A=");
1014 }
1015 appendcOFile(fp,*p);
1016 p++;
1017 }
1018}
1019
1020
1021
1022static void writeVObject_(OFile *fp, VObject *o);
1023
1024static void writeValue(OFile *fp, VObject *o, unsigned long size)
1025{
1026 if (o == 0) return;
1027 switch (VALUE_TYPE(o)) {
1028 case VCVT_STRINGZ: {
1029 writeQPString(fp, STRINGZ_VALUE_OF(o));
1030 break;
1031 }
1032 case VCVT_UINT: {
1033 char buf[16];
1034 sprintf(buf,"%u", INTEGER_VALUE_OF(o));
1035 appendsOFile(fp,buf);
1036 break;
1037 }
1038 case VCVT_ULONG: {
1039 char buf[16];
1040 sprintf(buf,"%lu", LONG_VALUE_OF(o));
1041 appendsOFile(fp,buf);
1042 break;
1043 }
1044 case VCVT_RAW: {
1045 appendcOFile(fp,'\n');
1046 writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
1047 break;
1048 }
1049 case VCVT_VOBJECT:
1050 appendcOFile(fp,'\n');
1051 writeVObject_(fp,VOBJECT_VALUE_OF(o));
1052 break;
1053 }
1054}
1055
1056static void writeAttrValue(OFile *fp, VObject *o)
1057{
1058 if (NAME_OF(o)) {
1059 struct PreDefProp *pi;
1060 pi = lookupPropInfo(NAME_OF(o));
1061 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
1062 appendcOFile(fp,';');
1063 appendsOFile(fp,NAME_OF(o));
1064 }
1065 else
1066 appendcOFile(fp,';');
1067 if (VALUE_TYPE(o)) {
1068 appendcOFile(fp,'=');
1069 writeValue(fp,o,0);
1070 }
1071}
1072
1073static void writeGroup(OFile *fp, VObject *o)
1074{
1075 char buf1[256];
1076 char buf2[256];
1077 strcpy(buf1,NAME_OF(o));
1078 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
1079 strcpy(buf2,STRINGZ_VALUE_OF(o));
1080 strcat(buf2,".");
1081 strcat(buf2,buf1);
1082 strcpy(buf1,buf2);
1083 }
1084 appendsOFile(fp,buf1);
1085}
1086
1087static int inList(const char **list, const char *s)
1088{
1089 if (list == 0) return 0;
1090 while (*list) {
1091 if (qstricmp(*list,s) == 0) return 1;
1092 list++;
1093 }
1094 return 0;
1095}
1096
1097static void writeProp(OFile *fp, VObject *o)
1098{
1099 if (NAME_OF(o)) {
1100 struct PreDefProp *pi;
1101 VObjectIterator t;
1102 const char **fields_ = 0;
1103 pi = lookupPropInfo(NAME_OF(o));
1104 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1105 writeVObject_(fp,o);
1106 return;
1107 }
1108 if (isAPropertyOf(o,VCGroupingProp))
1109 writeGroup(fp,o);
1110 else
1111 appendsOFile(fp,NAME_OF(o));
1112 if (pi) fields_ = pi->fields;
1113 initPropIterator(&t,o);
1114 while (moreIteration(&t)) {
1115 const char *s;
1116 VObject *eachProp = nextVObject(&t);
1117 s = NAME_OF(eachProp);
1118 if (qstricmp(VCGroupingProp,s) && !inList(fields_,s))
1119 writeAttrValue(fp,eachProp);
1120 }
1121 if (fields_) {
1122 int i = 0, n = 0;
1123 const char** fields = fields_;
1124 /* output prop as fields */
1125 appendcOFile(fp,':');
1126 while (*fields) {
1127 VObject *t = isAPropertyOf(o,*fields);
1128 i++;
1129 if (t) n = i;
1130 fields++;
1131 }
1132 fields = fields_;
1133 for (i=0;i<n;i++) {
1134 writeValue(fp,isAPropertyOf(o,*fields),0);
1135 fields++;
1136 if (i<(n-1)) appendcOFile(fp,';');
1137 }
1138 }
1139 }
1140
1141 if (VALUE_TYPE(o)) {
1142 unsigned long size = 0;
1143 VObject *p = isAPropertyOf(o,VCDataSizeProp);
1144 if (p) size = LONG_VALUE_OF(p);
1145 appendcOFile(fp,':');
1146 writeValue(fp,o,size);
1147 }
1148
1149 appendcOFile(fp,'\n');
1150}
1151
1152static void writeVObject_(OFile *fp, VObject *o)
1153{
1154 if (NAME_OF(o)) {
1155 struct PreDefProp *pi;
1156 pi = lookupPropInfo(NAME_OF(o));
1157
1158 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1159 VObjectIterator t;
1160 const char *begin = NAME_OF(o);
1161 appendsOFile(fp,"BEGIN:");
1162 appendsOFile(fp,begin);
1163 appendcOFile(fp,'\n');
1164 initPropIterator(&t,o);
1165 while (moreIteration(&t)) {
1166 VObject *eachProp = nextVObject(&t);
1167 writeProp(fp, eachProp);
1168 }
1169 appendsOFile(fp,"END:");
1170 appendsOFile(fp,begin);
1171 appendsOFile(fp,"\n\n");
1172 }
1173 }
1174}
1175
1176void writeVObject(FILE *fp, VObject *o)
1177{
1178 OFile ofp;
1179 // #####
1180 //_setmode(_fileno(fp), _O_BINARY);
1181 initOFile(&ofp,fp);
1182 writeVObject_(&ofp,o);
1183}
1184
1185DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
1186{
1187 QFileDirect f( fname);
1188 if ( !f.open( IO_WriteOnly ) ) {
1189 qWarning("Unable to open vobject write %s", fname);
1190 return;
1191 }
1192
1193 writeVObject( f.directHandle(),o );
1194}
1195
1196DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
1197{
1198 QFileDirect f( fname);
1199 if ( !f.open( IO_WriteOnly ) ) {
1200 qWarning("Unable to open vobject write %s", fname);
1201 return;
1202 }
1203
1204 while (list) {
1205 writeVObject(f.directHandle(),list);
1206 list = nextVObjectInList(list);
1207 }
1208}
1209
1210// end of source file vobject.c