Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

vobject.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002 (C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International             
00003 Business Machines Corporation and Siemens Rolm Communications Inc.             
00004                                                                                
00005 For purposes of this license notice, the term Licensors shall mean,            
00006 collectively, Apple Computer, Inc., AT&T Corp., International                  
00007 Business Machines Corporation and Siemens Rolm Communications Inc.             
00008 The term Licensor shall mean any of the Licensors.                             
00009                                                                                
00010 Subject to acceptance of the following conditions, permission is hereby        
00011 granted by Licensors without the need for written agreement and without        
00012 license or royalty fees, to use, copy, modify and distribute this              
00013 software for any purpose.                                                      
00014                                                                                
00015 The above copyright notice and the following four paragraphs must be           
00016 reproduced in all copies of this software and any software including           
00017 this software.                                                                 
00018                                                                                
00019 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE       
00020 ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR       
00021 MODIFICATIONS.                                                                 
00022                                                                                
00023 IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,              
00024 INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT         
00025 OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH         
00026 DAMAGE.                                                                        
00027                                                                                
00028 EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,       
00029 INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE            
00030 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR             
00031 PURPOSE.                                                                       
00032 
00033 The software is provided with RESTRICTED RIGHTS.  Use, duplication, or         
00034 disclosure by the government are subject to restrictions set forth in          
00035 DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.                         
00036 
00037 ***************************************************************************/
00038 
00039 /*
00040  * src: vobject.c
00041  * doc: vobject and APIs to construct vobject, APIs pretty print 
00042  * vobject, and convert a vobject into its textual representation.
00043  */
00044 
00045 #include <stdlib.h>
00046 
00047 #include <qtopia/config.h>
00048 #include "vobject_p.h"
00049 #include "qfiledirect_p.h"
00050 #include <string.h>
00051 #include <stdio.h>
00052 #include <fcntl.h>
00053 //#include <io.h>
00054 
00055 
00056 #define NAME_OF(o)                              o->id
00057 #define VALUE_TYPE(o)                   o->valType
00058 #define STRINGZ_VALUE_OF(o)             o->val.strs
00059 #define INTEGER_VALUE_OF(o)             o->val.i
00060 #define LONG_VALUE_OF(o)                o->val.l
00061 #define ANY_VALUE_OF(o)                 o->val.any
00062 #define VOBJECT_VALUE_OF(o)             o->val.vobj
00063 
00064 static char vobj_cs[10];
00065 static enum { EightBit, QuotedPrintable, Base64 } vobj_enc=EightBit;
00066 static const char *vobj_enc_s=0;
00067 
00068 typedef union ValueItem {
00069     const char *strs;
00070     unsigned int i;
00071     unsigned long l;
00072     void *any;
00073     VObject *vobj;
00074     } ValueItem;
00075 
00076 struct VObject {
00077     VObject *next;
00078     const char *id;
00079     VObject *prop;
00080     unsigned short valType;
00081     ValueItem val;
00082     };
00083 
00084 typedef struct StrItem StrItem;
00085 
00086 struct StrItem {
00087     StrItem *next;
00088     const char *s;
00089     unsigned int refCnt;
00090     };
00091 
00092 DLLEXPORT(const char**) fieldedProp;
00093 
00094 
00095 
00096 /*----------------------------------------------------------------------
00097    The following functions involve with memory allocation:
00098         newVObject
00099         deleteVObject
00100         dupStr
00101         deleteStr
00102         newStrItem
00103         deleteStrItem
00104    ----------------------------------------------------------------------*/
00105 
00106 DLLEXPORT(VObject*) newVObject_(const char *id)
00107 {
00108     VObject *p = (VObject*)malloc(sizeof(VObject));
00109     p->next = 0;
00110     p->id = id;
00111     p->prop = 0;
00112     VALUE_TYPE(p) = 0;
00113     ANY_VALUE_OF(p) = 0;
00114     return p;
00115 }
00116 
00117 DLLEXPORT(VObject*) newVObject(const char *id)
00118 {
00119     return newVObject_(lookupStr(id));
00120 }
00121 
00122 DLLEXPORT(void) deleteVObject(VObject *p)
00123 {
00124     unUseStr(p->id);
00125     free(p);
00126 }
00127 
00128 DLLEXPORT(char*) dupStr(const char *s, unsigned int size)
00129 {
00130     char *t;
00131     if  (size == 0) {
00132         size = strlen(s);
00133         }
00134     t = (char*)malloc(size+1);
00135     if (t) {
00136         memcpy(t,s,size);
00137         t[size] = 0;
00138         return t;
00139         }
00140     else {
00141         return (char*)0;
00142         }
00143 }
00144 
00145 DLLEXPORT(void) deleteStr(const char *p)
00146 {
00147     if (p) free((void*)p);
00148 }
00149 
00150 
00151 static StrItem* newStrItem(const char *s, StrItem *next)
00152 {
00153     StrItem *p = (StrItem*)malloc(sizeof(StrItem));
00154     p->next = next;
00155     p->s = s;
00156     p->refCnt = 1;
00157     return p;
00158 }
00159 
00160 static void deleteStrItem(StrItem *p)
00161 {
00162     free((void*)p);
00163 }
00164 
00165 
00166 /*----------------------------------------------------------------------
00167   The following function provide accesses to VObject's value.
00168   ----------------------------------------------------------------------*/
00169 
00170 DLLEXPORT(const char*) vObjectName(VObject *o)
00171 {
00172     return NAME_OF(o);
00173 }
00174 
00175 DLLEXPORT(void) setVObjectName(VObject *o, const char* id)
00176 {
00177     NAME_OF(o) = id;
00178 }
00179 
00180 DLLEXPORT(const char*) vObjectStringZValue(VObject *o)
00181 {
00182     return STRINGZ_VALUE_OF(o);
00183 }
00184 
00185 DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s)
00186 {
00187     STRINGZ_VALUE_OF(o) = dupStr(s,0);
00188     VALUE_TYPE(o) = VCVT_STRINGZ;
00189 }
00190 
00191 DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s)
00192 {
00193     STRINGZ_VALUE_OF(o) = s;
00194     VALUE_TYPE(o) = VCVT_STRINGZ;
00195 }
00196 
00197 DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o)
00198 {
00199     return INTEGER_VALUE_OF(o);
00200 }
00201 
00202 DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i)
00203 {
00204     INTEGER_VALUE_OF(o) = i;
00205     VALUE_TYPE(o) = VCVT_UINT;
00206 }
00207 
00208 DLLEXPORT(unsigned long) vObjectLongValue(VObject *o)
00209 {
00210     return LONG_VALUE_OF(o);
00211 }
00212 
00213 DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l)
00214 {
00215     LONG_VALUE_OF(o) = l;
00216     VALUE_TYPE(o) = VCVT_ULONG;
00217 }
00218 
00219 DLLEXPORT(void*) vObjectAnyValue(VObject *o)
00220 {
00221     return ANY_VALUE_OF(o);
00222 }
00223 
00224 DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t)
00225 {
00226     ANY_VALUE_OF(o) = t;
00227     VALUE_TYPE(o) = VCVT_RAW;
00228 }
00229 
00230 DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o)
00231 {
00232     return VOBJECT_VALUE_OF(o);
00233 }
00234 
00235 DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p)
00236 {
00237     VOBJECT_VALUE_OF(o) = p;
00238     VALUE_TYPE(o) = VCVT_VOBJECT;
00239 }
00240 
00241 DLLEXPORT(int) vObjectValueType(VObject *o)
00242 {
00243     return VALUE_TYPE(o);
00244 }
00245 
00246 
00247 /*----------------------------------------------------------------------
00248   The following functions can be used to build VObject.
00249   ----------------------------------------------------------------------*/
00250 
00251 DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p)
00252 {
00253     /* circular link list pointed to tail */
00254     /*
00255     o {next,id,prop,val}
00256                 V
00257         pn {next,id,prop,val}
00258              V
00259             ...
00260         p1 {next,id,prop,val}
00261              V
00262              pn
00263     -->
00264     o {next,id,prop,val}
00265                 V
00266         pn {next,id,prop,val}
00267              V
00268         p {next,id,prop,val}
00269             ...
00270         p1 {next,id,prop,val}
00271              V
00272              pn
00273     */
00274 
00275     VObject *tail = o->prop;
00276     if (tail) {
00277         p->next = tail->next;
00278         o->prop = tail->next = p;
00279         }
00280     else {
00281         o->prop = p->next = p;
00282         }
00283     return p;
00284 }
00285 
00286 DLLEXPORT(VObject*) addProp(VObject *o, const char *id)
00287 {
00288     return addVObjectProp(o,newVObject(id));
00289 }
00290 
00291 DLLEXPORT(VObject*) addProp_(VObject *o, const char *id)
00292 {
00293     return addVObjectProp(o,newVObject_(id));
00294 }
00295 
00296 DLLEXPORT(void) addList(VObject **o, VObject *p)
00297 {
00298     p->next = 0;
00299     if (*o == 0) {
00300         *o = p;
00301         }
00302     else {
00303         VObject *t = *o;
00304         while (t->next) {
00305            t = t->next;
00306            }
00307         t->next = p;
00308         }
00309 }
00310 
00311 DLLEXPORT(VObject*) nextVObjectInList(VObject *o)
00312 {
00313     return o->next;
00314 }
00315 
00316 DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size)
00317 {
00318     VObject *sizeProp;
00319     setVObjectAnyValue(prop, val);
00320     sizeProp = addProp(prop,VCDataSizeProp);
00321     setVObjectLongValue(sizeProp, size);
00322     return prop;
00323 }
00324 
00325 DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size)
00326 {
00327     void *p = dupStr((const char *)val,size);
00328     return setValueWithSize_(prop,p,p?size:0);
00329 }
00330 
00331 DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o)
00332 {
00333     i->start = o->prop; 
00334     i->next = 0;
00335 }
00336 
00337 DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o)
00338 {
00339     i->start = o->next; 
00340     i->next = 0;
00341 }
00342 
00343 DLLEXPORT(int) moreIteration(VObjectIterator *i)
00344 { 
00345     return (i->start && (i->next==0 || i->next!=i->start));
00346 }
00347 
00348 DLLEXPORT(VObject*) nextVObject(VObjectIterator *i)
00349 {
00350     if (i->start && i->next != i->start) {
00351         if (i->next == 0) {
00352             i->next = i->start->next;
00353             return i->next;
00354             }
00355         else {
00356             i->next = i->next->next;
00357             return i->next;
00358             }
00359         }
00360     else return (VObject*)0;
00361 }
00362 
00363 DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id)
00364 {
00365     VObjectIterator i;
00366     initPropIterator(&i,o);
00367     while (moreIteration(&i)) {
00368         VObject *each = nextVObject(&i);
00369         if (!qstricmp(id,each->id))
00370             return each;
00371         }
00372     return (VObject*)0;
00373 }
00374 
00375 DLLEXPORT(VObject*) addGroup(VObject *o, const char *g)
00376 {
00377     /*
00378         a.b.c
00379         -->
00380         prop(c)
00381             prop(VCGrouping=b)
00382                 prop(VCGrouping=a)
00383      */
00384     char *dot = strrchr(g,'.');
00385     if (dot) {
00386         VObject *p, *t;
00387         char *gs, *n = dot+1;
00388         gs = dupStr(g,0);       /* so we can write to it. */
00389         /* used to be
00390         * t = p = addProp_(o,lookupProp_(n));
00391         */
00392         t = p = addProp_(o,lookupProp(n));
00393         dot = strrchr(gs,'.');
00394         *dot = 0;
00395         do {
00396             dot = strrchr(gs,'.');
00397             if (dot) {
00398                 n = dot+1;
00399                 *dot=0;
00400                 }
00401             else
00402                 n = gs;
00403             /* property(VCGroupingProp=n);
00404              *  and the value may have VCGrouping property
00405              */
00406             t = addProp(t,VCGroupingProp);
00407             setVObjectStringZValue(t,lookupProp_(n));
00408             } while (n != gs);
00409         deleteStr(gs);  
00410         return p;
00411         }
00412     else
00413         return addProp_(o,lookupProp(g));
00414 }
00415 
00416 DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v)
00417 {
00418     VObject *prop;
00419     prop = addProp(o,p);
00420     setVObjectStringZValue_(prop, strdup( v ) );
00421     return prop;
00422 }
00423 
00424 DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v,
00425         unsigned int size)
00426 {
00427     VObject *prop;
00428     prop = addProp(o,p);
00429     setValueWithSize_(prop, (void*)v, size);
00430     return prop;
00431 }
00432 
00433 DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v,
00434         unsigned int size)
00435 {
00436     return addPropSizedValue_(o,p,dupStr(v,size),size);
00437 }
00438 
00439 
00440 DLLEXPORT(void) cleanVObject(VObject *o)
00441 {
00442     if (o == 0) return;
00443     if (o->prop) {
00444         /* destroy time: cannot use the iterator here.
00445            Have to break the cycle in the circular link
00446            list and turns it into regular NULL-terminated
00447            list -- since at some point of destruction,
00448            the reference entry for the iterator to work
00449            will not longer be valid.
00450            */
00451         VObject *p;
00452         p = o->prop->next;
00453         o->prop->next = 0;
00454         do {
00455            VObject *t = p->next;
00456            cleanVObject(p);
00457            p = t;
00458            } while (p);
00459         }
00460     switch (VALUE_TYPE(o)) {
00461         case VCVT_STRINGZ:
00462         case VCVT_RAW:
00463             // assume they are all allocated by malloc.
00464             free((char*)STRINGZ_VALUE_OF(o));
00465             break;
00466         case VCVT_VOBJECT:
00467             cleanVObject(VOBJECT_VALUE_OF(o));
00468             break;
00469         }
00470     deleteVObject(o);
00471 }
00472 
00473 DLLEXPORT(void) cleanVObjects(VObject *list)
00474 {
00475     while (list) {
00476         VObject *t = list;
00477         list = nextVObjectInList(list);
00478         cleanVObject(t);
00479         }
00480 }
00481 
00482 /*----------------------------------------------------------------------
00483   The following is a String Table Facilities.
00484   ----------------------------------------------------------------------*/
00485 
00486 #define STRTBLSIZE 255
00487 
00488 static StrItem *strTbl[STRTBLSIZE];
00489 
00490 static unsigned int hashStr(const char *s)
00491 {
00492     unsigned int h = 0;
00493     int i;
00494     for (i=0;s[i];i++) {
00495         h += s[i]*i;
00496         }
00497     return h % STRTBLSIZE;
00498 }
00499 
00500 DLLEXPORT(const char*) lookupStr(const char *s)
00501 {
00502     StrItem *t;
00503     unsigned int h = hashStr(s);
00504     if ((t = strTbl[h]) != 0) {
00505         do {
00506             if (qstricmp(t->s,s) == 0) {
00507                 t->refCnt++;
00508                 return t->s;
00509                 }
00510             t = t->next;
00511             } while (t);
00512         }
00513     s = dupStr(s,0);
00514     strTbl[h] = newStrItem(s,strTbl[h]);
00515     return s;
00516 }
00517 
00518 DLLEXPORT(void) unUseStr(const char *s)
00519 {
00520     StrItem *t, *p;
00521     unsigned int h = hashStr(s);
00522     if ((t = strTbl[h]) != 0) {
00523         p = t;
00524         do {
00525             if (qstricmp(t->s,s) == 0) {
00526                 t->refCnt--;
00527                 if (t->refCnt == 0) {
00528                     if (p == strTbl[h]) {
00529                         strTbl[h] = t->next;
00530                         }
00531                     else {
00532                         p->next = t->next;
00533                         }
00534                     deleteStr(t->s);
00535                     deleteStrItem(t);
00536                     return;
00537                     }
00538                 }
00539             p = t;
00540             t = t->next;
00541             } while (t);
00542         }
00543 }
00544 
00545 DLLEXPORT(void) cleanStrTbl()
00546 {
00547     int i;
00548     for (i=0; i<STRTBLSIZE;i++) {
00549         StrItem *t = strTbl[i];
00550         while (t) {
00551             StrItem *p;
00552             deleteStr(t->s);
00553             p = t;
00554             t = t->next;
00555             deleteStrItem(p);
00556             } while (t);
00557         strTbl[i] = 0;
00558         }
00559 }
00560 
00561 
00562 struct PreDefProp {
00563     const char *name;
00564     const char *alias;
00565     const char** fields;
00566     unsigned int flags;
00567     };
00568 
00569 /* flags in PreDefProp */
00570 #define PD_BEGIN        0x1
00571 #define PD_INTERNAL     0x2
00572 
00573 static const char *adrFields[] = {
00574     VCPostalBoxProp,
00575     VCExtAddressProp,
00576     VCStreetAddressProp,
00577     VCCityProp,
00578     VCRegionProp,
00579     VCPostalCodeProp,
00580     VCCountryNameProp,
00581     0
00582 };
00583 
00584 static const char *nameFields[] = {
00585     VCFamilyNameProp,
00586     VCGivenNameProp,
00587     VCAdditionalNamesProp,
00588     VCNamePrefixesProp,
00589     VCNameSuffixesProp,
00590     NULL
00591     };
00592 
00593 static const char *orgFields[] = {
00594     VCOrgNameProp,
00595     VCOrgUnitProp,
00596     VCOrgUnit2Prop,
00597     VCOrgUnit3Prop,
00598     VCOrgUnit4Prop,
00599     NULL
00600     };
00601 
00602 static const char *AAlarmFields[] = {
00603     VCRunTimeProp,
00604     VCSnoozeTimeProp,
00605     VCRepeatCountProp,
00606     VCAudioContentProp,
00607     0
00608     };
00609 
00610 /* ExDate -- has unamed fields */
00611 /* RDate -- has unamed fields */
00612 
00613 static const char *DAlarmFields[] = {
00614     VCRunTimeProp,
00615     VCSnoozeTimeProp,
00616     VCRepeatCountProp,
00617     VCDisplayStringProp,
00618     0
00619     };
00620 
00621 static const char *MAlarmFields[] = {
00622     VCRunTimeProp,
00623     VCSnoozeTimeProp,
00624     VCRepeatCountProp,
00625     VCEmailAddressProp,
00626     VCNoteProp,
00627     0
00628     };
00629 
00630 static const char *PAlarmFields[] = {
00631     VCRunTimeProp,
00632     VCSnoozeTimeProp,
00633     VCRepeatCountProp,
00634     VCProcedureNameProp,
00635     0
00636     };
00637 
00638 static struct PreDefProp propNames[] = {
00639     { VC7bitProp, 0, 0, 0 },
00640     { VC8bitProp, 0, 0, 0 },
00641     { VCAAlarmProp, 0, AAlarmFields, 0 },
00642     { VCAdditionalNamesProp, 0, 0, 0 },
00643     { VCAdrProp, 0, adrFields, 0 },
00644     { VCAgentProp, 0, 0, 0 },
00645     { VCAIFFProp, 0, 0, 0 },
00646     { VCAOLProp, 0, 0, 0 },
00647     { VCAppleLinkProp, 0, 0, 0 },
00648     { VCAttachProp, 0, 0, 0 },
00649     { VCAttendeeProp, 0, 0, 0 },
00650     { VCATTMailProp, 0, 0, 0 },
00651     { VCAudioContentProp, 0, 0, 0 },
00652     { VCAVIProp, 0, 0, 0 },
00653     { VCBase64Prop, 0, 0, 0 },
00654     { VCBBSProp, 0, 0, 0 },
00655     { VCBirthDateProp, 0, 0, 0 },
00656     { VCBMPProp, 0, 0, 0 },
00657     { VCBodyProp, 0, 0, 0 },
00658     { VCBusinessRoleProp, 0, 0, 0 },
00659     { VCCalProp, 0, 0, PD_BEGIN },
00660     { VCCaptionProp, 0, 0, 0 },
00661     { VCCardProp, 0, 0, PD_BEGIN },
00662     { VCCarProp, 0, 0, 0 },
00663     { VCCategoriesProp, 0, 0, 0 },
00664     { VCCellularProp, 0, 0, 0 },
00665     { VCCGMProp, 0, 0, 0 },
00666     { VCCharSetProp, 0, 0, 0 },
00667     { VCCIDProp, VCContentIDProp, 0, 0 },
00668     { VCCISProp, 0, 0, 0 },
00669     { VCCityProp, 0, 0, 0 },
00670     { VCClassProp, 0, 0, 0 },
00671     { VCCommentProp, 0, 0, 0 },
00672     { VCCompletedProp, 0, 0, 0 },
00673     { VCContentIDProp, 0, 0, 0 },
00674     { VCCountryNameProp, 0, 0, 0 },
00675     { VCDAlarmProp, 0, DAlarmFields, 0 },
00676     { VCDataSizeProp, 0, 0, PD_INTERNAL },
00677     { VCDayLightProp, 0, 0, 0 },
00678     { VCDCreatedProp, 0, 0, 0 },
00679     { VCDeliveryLabelProp, 0, 0, 0 },
00680     { VCDescriptionProp, 0, 0, 0 },
00681     { VCDIBProp, 0, 0, 0 },
00682     { VCDisplayStringProp, 0, 0, 0 },
00683     { VCDomesticProp, 0, 0, 0 },
00684     { VCDTendProp, 0, 0, 0 },
00685     { VCDTstartProp, 0, 0, 0 },
00686     { VCDueProp, 0, 0, 0 },
00687     { VCEmailAddressProp, 0, 0, 0 },
00688     { VCEncodingProp, 0, 0, 0 },
00689     { VCEndProp, 0, 0, 0 },
00690     { VCEventProp, 0, 0, PD_BEGIN },
00691     { VCEWorldProp, 0, 0, 0 },
00692     { VCExNumProp, 0, 0, 0 },
00693     { VCExpDateProp, 0, 0, 0 },
00694     { VCExpectProp, 0, 0, 0 },
00695     { VCExtAddressProp, 0, 0, 0 },
00696     { VCFamilyNameProp, 0, 0, 0 },
00697     { VCFaxProp, 0, 0, 0 },
00698     { VCFullNameProp, 0, 0, 0 },
00699     { VCGeoLocationProp, 0, 0, 0 },
00700     { VCGeoProp, 0, 0, 0 },
00701     { VCGIFProp, 0, 0, 0 },
00702     { VCGivenNameProp, 0, 0, 0 },
00703     { VCGroupingProp, 0, 0, 0 },
00704     { VCHomeProp, 0, 0, 0 },
00705     { VCIBMMailProp, 0, 0, 0 },
00706     { VCInlineProp, 0, 0, 0 },
00707     { VCInternationalProp, 0, 0, 0 },
00708     { VCInternetProp, 0, 0, 0 },
00709     { VCISDNProp, 0, 0, 0 },
00710     { VCJPEGProp, 0, 0, 0 },
00711     { VCLanguageProp, 0, 0, 0 },
00712     { VCLastModifiedProp, 0, 0, 0 },
00713     { VCLastRevisedProp, 0, 0, 0 },
00714     { VCLocationProp, 0, 0, 0 },
00715     { VCLogoProp, 0, 0, 0 },
00716     { VCMailerProp, 0, 0, 0 },
00717     { VCMAlarmProp, 0, MAlarmFields, 0 },
00718     { VCMCIMailProp, 0, 0, 0 },
00719     { VCMessageProp, 0, 0, 0 },
00720     { VCMETProp, 0, 0, 0 },
00721     { VCModemProp, 0, 0, 0 },
00722     { VCMPEG2Prop, 0, 0, 0 },
00723     { VCMPEGProp, 0, 0, 0 },
00724     { VCMSNProp, 0, 0, 0 },
00725     { VCNamePrefixesProp, 0, 0, 0 },
00726     { VCNameProp, 0, nameFields, 0 },
00727     { VCNameSuffixesProp, 0, 0, 0 },
00728     { VCNoteProp, 0, 0, 0 },
00729     { VCOrgNameProp, 0, 0, 0 },
00730     { VCOrgProp, 0, orgFields, 0 },
00731     { VCOrgUnit2Prop, 0, 0, 0 },
00732     { VCOrgUnit3Prop, 0, 0, 0 },
00733     { VCOrgUnit4Prop, 0, 0, 0 },
00734     { VCOrgUnitProp, 0, 0, 0 },
00735     { VCPagerProp, 0, 0, 0 },
00736     { VCPAlarmProp, 0, PAlarmFields, 0 },
00737     { VCParcelProp, 0, 0, 0 },
00738     { VCPartProp, 0, 0, 0 },
00739     { VCPCMProp, 0, 0, 0 },
00740     { VCPDFProp, 0, 0, 0 },
00741     { VCPGPProp, 0, 0, 0 },
00742     { VCPhotoProp, 0, 0, 0 },
00743     { VCPICTProp, 0, 0, 0 },
00744     { VCPMBProp, 0, 0, 0 },
00745     { VCPostalBoxProp, 0, 0, 0 },
00746     { VCPostalCodeProp, 0, 0, 0 },
00747     { VCPostalProp, 0, 0, 0 },
00748     { VCPowerShareProp, 0, 0, 0 },
00749     { VCPreferredProp, 0, 0, 0 },
00750     { VCPriorityProp, 0, 0, 0 },
00751     { VCProcedureNameProp, 0, 0, 0 },
00752     { VCProdIdProp, 0, 0, 0 },
00753     { VCProdigyProp, 0, 0, 0 },
00754     { VCPronunciationProp, 0, 0, 0 },
00755     { VCPSProp, 0, 0, 0 },
00756     { VCPublicKeyProp, 0, 0, 0 },
00757     { VCQPProp, VCQuotedPrintableProp, 0, 0 },
00758     { VCQuickTimeProp, 0, 0, 0 },
00759     { VCQuotedPrintableProp, 0, 0, 0 },
00760     { VCRDateProp, 0, 0, 0 },
00761     { VCRegionProp, 0, 0, 0 },
00762     { VCRelatedToProp, 0, 0, 0 },
00763     { VCRepeatCountProp, 0, 0, 0 },
00764     { VCResourcesProp, 0, 0, 0 },
00765     { VCRNumProp, 0, 0, 0 },
00766     { VCRoleProp, 0, 0, 0 },
00767     { VCRRuleProp, 0, 0, 0 },
00768     { VCRSVPProp, 0, 0, 0 },
00769     { VCRunTimeProp, 0, 0, 0 },
00770     { VCSequenceProp, 0, 0, 0 },
00771     { VCSnoozeTimeProp, 0, 0, 0 },
00772     { VCStartProp, 0, 0, 0 },
00773     { VCStatusProp, 0, 0, 0 },
00774     { VCStreetAddressProp, 0, 0, 0 },
00775     { VCSubTypeProp, 0, 0, 0 },
00776     { VCSummaryProp, 0, 0, 0 },
00777     { VCTelephoneProp, 0, 0, 0 },
00778     { VCTIFFProp, 0, 0, 0 },
00779     { VCTimeZoneProp, 0, 0, 0 },
00780     { VCTitleProp, 0, 0, 0 },
00781     { VCTLXProp, 0, 0, 0 },
00782     { VCTodoProp, 0, 0, PD_BEGIN },
00783     { VCTranspProp, 0, 0, 0 },
00784     { VCUniqueStringProp, 0, 0, 0 },
00785     { VCURLProp, 0, 0, 0 },
00786     { VCURLValueProp, 0, 0, 0 },
00787     { VCValueProp, 0, 0, 0 },
00788     { VCVersionProp, 0, 0, 0 },
00789     { VCVideoProp, 0, 0, 0 },
00790     { VCVoiceProp, 0, 0, 0 },
00791     { VCWAVEProp, 0, 0, 0 },
00792     { VCWMFProp, 0, 0, 0 },
00793     { VCWorkProp, 0, 0, 0 },
00794     { VCX400Prop, 0, 0, 0 },
00795     { VCX509Prop, 0, 0, 0 },
00796     { VCXRuleProp, 0, 0, 0 },
00797     { 0,0,0,0 }
00798     };
00799 
00800 
00801 static struct PreDefProp* lookupPropInfo(const char* str)
00802 {
00803     /* brute force for now, could use a hash table here. */
00804     int i;
00805         
00806     for (i = 0; propNames[i].name; i++)
00807         if (qstricmp(str, propNames[i].name) == 0) {
00808             return &propNames[i];
00809             }
00810     
00811     return 0;
00812 }
00813 
00814 
00815 DLLEXPORT(const char*) lookupProp_(const char* str)
00816 {
00817     int i;
00818         
00819     for (i = 0; propNames[i].name; i++)
00820         if (qstricmp(str, propNames[i].name) == 0) {
00821             const char* s;
00822             s = propNames[i].alias?propNames[i].alias:propNames[i].name;
00823             return lookupStr(s);
00824             }
00825     return lookupStr(str);
00826 }
00827 
00828 
00829 DLLEXPORT(const char*) lookupProp(const char* str)
00830 {
00831     int i;
00832         
00833     for (i = 0; propNames[i].name; i++)
00834         if (qstricmp(str, propNames[i].name) == 0) {
00835             const char *s;
00836             fieldedProp = propNames[i].fields;
00837             s = propNames[i].alias?propNames[i].alias:propNames[i].name;
00838             return lookupStr(s);
00839             }
00840     fieldedProp = 0;
00841     return lookupStr(str);
00842 }
00843 
00844 
00845 /*----------------------------------------------------------------------
00846   APIs to Output text form.
00847   ----------------------------------------------------------------------*/
00848 #define OFILE_REALLOC_SIZE 256
00849 typedef struct OFile {
00850     FILE *fp;
00851     char *s;
00852     int len;
00853     int limit;
00854     int alloc:1;
00855     int fail:1;
00856     } OFile;
00857 
00858 #if 0
00859 static void appendsOFile(OFile *fp, const char *s)
00860 {
00861     int slen;
00862     if (fp->fail) return;
00863     slen  = strlen(s);
00864     if (fp->fp) {
00865         fwrite(s,1,slen,fp->fp);
00866         }
00867     else {
00868 stuff:
00869         if (fp->len + slen < fp->limit) {
00870             memcpy(fp->s+fp->len,s,slen);
00871             fp->len += slen;
00872             return;
00873             }
00874         else if (fp->alloc) {
00875             fp->limit = fp->limit + OFILE_REALLOC_SIZE;
00876             if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
00877             fp->s = (char *) realloc(fp->s,fp->limit);
00878             if (fp->s) goto stuff;
00879             }
00880         if (fp->alloc)
00881             free(fp->s);
00882         fp->s = 0;
00883         fp->fail = 1;
00884         }
00885 }
00886 
00887 static void appendcOFile(OFile *fp, char c)
00888 {
00889     if (fp->fail) return;
00890     if (fp->fp) {
00891         fputc(c,fp->fp);
00892         }
00893     else {
00894 stuff:
00895         if (fp->len+1 < fp->limit) {
00896             fp->s[fp->len] = c;
00897             fp->len++;
00898             return;
00899             }
00900         else if (fp->alloc) {
00901             fp->limit = fp->limit + OFILE_REALLOC_SIZE;
00902             fp->s = (char *) realloc(fp->s,fp->limit);
00903             if (fp->s) goto stuff;
00904             }
00905         if (fp->alloc)
00906             free(fp->s);
00907         fp->s = 0;
00908         fp->fail = 1;
00909         }
00910 }
00911 #else
00912 static void appendcOFile_(OFile *fp, char c)
00913 {
00914     if (fp->fail) return;
00915     if (fp->fp) {
00916         fputc(c,fp->fp);
00917         }
00918     else {
00919 stuff:
00920         if (fp->len+1 < fp->limit) {
00921             fp->s[fp->len] = c;
00922             fp->len++;
00923             return;
00924             }
00925         else if (fp->alloc) {
00926             fp->limit = fp->limit + OFILE_REALLOC_SIZE;
00927             fp->s = (char *)realloc(fp->s,fp->limit);
00928             if (fp->s) goto stuff;
00929             }
00930         if (fp->alloc)
00931             free(fp->s);
00932         fp->s = 0;
00933         fp->fail = 1;
00934         }
00935 }
00936 
00937 static void appendcOFile(OFile *fp, char c)
00938 {
00939     if (c == '\n') {
00940         /* write out as <CR><LF> */
00941         appendcOFile_(fp,0xd);
00942         appendcOFile_(fp,0xa);
00943         }
00944     else
00945         appendcOFile_(fp,c);
00946 }
00947 
00948 static void appendsOFile(OFile *fp, const char *s)
00949 {
00950     int i, slen;
00951     slen  = strlen(s);
00952     for (i=0; i<slen; i++) {
00953         appendcOFile(fp,s[i]);
00954         }
00955 }
00956 
00957 #endif
00958 
00959 static void appendsOFileEncCs(OFile *fp)
00960 {
00961     if ( vobj_enc_s ) {
00962         appendsOFile(fp, ";" VCEncodingProp "=");
00963         appendsOFile(fp, vobj_enc_s);
00964     }
00965     appendsOFile(fp, ";" VCCharSetProp "=");
00966     appendsOFile(fp, vobj_cs);
00967 }
00968 
00969 
00970 static void initOFile(OFile *fp, FILE *ofp)
00971 {
00972     fp->fp = ofp;
00973     fp->s = 0;
00974     fp->len = 0;
00975     fp->limit = 0;
00976     fp->alloc = 0;
00977     fp->fail = 0;
00978 }
00979 
00980 static int writeBase64(OFile *fp, unsigned char *s, long len)
00981 {
00982     long cur = 0;
00983     int i, numQuads = 0;
00984     unsigned long trip;
00985     unsigned char b;
00986     char quad[5];
00987 #define MAXQUADS 16
00988 
00989     quad[4] = 0;
00990 
00991     while (cur < len) {
00992         // collect the triplet of bytes into 'trip'
00993         trip = 0;
00994         for (i = 0; i < 3; i++) {
00995             b = (cur < len) ? *(s + cur) : 0;
00996             cur++;
00997             trip = trip << 8 | b;
00998             }
00999         // fill in 'quad' with the appropriate four characters
01000         for (i = 3; i >= 0; i--) {
01001             b = (unsigned char)(trip & 0x3F);
01002             trip = trip >> 6;
01003             if ((3 - i) < (cur - len))
01004                 quad[i] = '='; // pad char
01005             else if (b < 26) quad[i] = (char)b + 'A';
01006             else if (b < 52) quad[i] = (char)(b - 26) + 'a';
01007             else if (b < 62) quad[i] = (char)(b - 52) + '0';
01008             else if (b == 62) quad[i] = '+';
01009             else quad[i] = '/';
01010             }
01011         // now output 'quad' with appropriate whitespace and line ending
01012         appendsOFile(fp, (numQuads == 0 ? "    " : ""));
01013         appendsOFile(fp, quad);
01014         appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
01015         numQuads = (numQuads + 1) % MAXQUADS;
01016         }
01017     appendcOFile(fp,'\n');
01018 
01019     return 1;
01020 }
01021 
01022 static const char *qpReplaceChar(unsigned char c) 
01023 {
01024     if (c == '\n') {
01025         return "=0A=\n";
01026     } else if (
01027             // RFC 1521
01028             (c >= 32 && c <= 60) // Note: " " not allowed at EOL
01029             ||
01030             (c >= 62 && c <= 126)
01031         )
01032     { 
01033         return 0;
01034     }
01035 
01036     static char trans[4];
01037     trans[0] = '=';
01038     trans[3] = '\0';
01039     int rem = c % 16;
01040     int div = c / 16;
01041 
01042     if (div < 10)
01043         trans[1] = '0' + div;
01044     else
01045         trans[1] = 'A' + (div - 10);
01046 
01047     if (rem < 10)
01048         trans[2] = '0' + rem;
01049     else
01050         trans[2] = 'A' + (rem - 10);
01051 
01052     return trans;
01053 }
01054 
01055 static void writeEncString(OFile *fp, const char *s, bool nosemi)
01056 {
01057     /*
01058         only A-Z, 0-9 and 
01059        "'"  (ASCII code 39)
01060        "("  (ASCII code 40)
01061        ")"  (ASCII code 41)
01062        "+"  (ASCII code 43)
01063        ","  (ASCII code 44)
01064        "-"  (ASCII code 45)
01065        "/"  (ASCII code 47)
01066        "?"  (ASCII code 63)
01067        
01068        should remain un-encoded.
01069        '=' needs to be encoded as it is the escape character.
01070        ';' needs to be as it is a field separator.
01071 
01072      */
01073     const char *p = s;
01074     switch ( vobj_enc ) {
01075         case EightBit:
01076             while (*p) {
01077                 if ( *p == '\n' || nosemi && ( *p == '\\' || *p == ';' ) )
01078                     appendcOFile(fp, '\\');
01079                 appendcOFile(fp, *p);
01080                 p++;
01081             }
01082             break;
01083         case QuotedPrintable:
01084             while (*p) {
01085                 const char *rep = qpReplaceChar(*p);
01086                 if (rep)
01087                     appendsOFile(fp, rep);
01088                 else if ( *p == ';' && nosemi )
01089                     appendsOFile(fp, "=3B");
01090                 else if ( *p == ' ' ) {
01091                     if ( !p[1] || p[1] == '\n' ) // RFC 1521
01092                         appendsOFile(fp, "=20");
01093                     else
01094                         appendcOFile(fp, *p);
01095                 } else
01096                     appendcOFile(fp, *p);
01097                 p++;
01098             }
01099             break;
01100         case Base64:
01101             writeBase64(fp, (unsigned char*)p, strlen(p));
01102             break;
01103     }
01104 }
01105 
01106 static bool includesUnprintable(VObject *o, bool nosemi)
01107 {
01108     if (o) {
01109         if (VALUE_TYPE(o) == VCVT_STRINGZ) {
01110             const char *p = STRINGZ_VALUE_OF(o);
01111             if (p) {
01112                 while (*p) {
01113                     if (*p==' ' && (!p[1] || p[1]=='\n') // RFC 1521: spaces at ends need quoting
01114                             || qpReplaceChar(*p)
01115                             || *p==';' && nosemi )
01116                         return TRUE;
01117                     p++;
01118                 }
01119             }
01120         }
01121     }
01122     return FALSE;
01123 }
01124             
01125 static void writeVObject_(OFile *fp, VObject *o);
01126 
01127 static void writeValue(OFile *fp, VObject *o, unsigned long size, bool nosemi)
01128 {
01129     if (o == 0) return;
01130     switch (VALUE_TYPE(o)) {
01131         case VCVT_STRINGZ: {
01132             writeEncString(fp, STRINGZ_VALUE_OF(o), nosemi);
01133             break;
01134             }
01135         case VCVT_UINT: {
01136             char buf[16];
01137             sprintf(buf,"%u", INTEGER_VALUE_OF(o));
01138             appendsOFile(fp,buf);
01139             break;
01140             }
01141         case VCVT_ULONG: {
01142             char buf[16];
01143             sprintf(buf,"%lu", LONG_VALUE_OF(o));
01144             appendsOFile(fp,buf);
01145             break;
01146             }
01147         case VCVT_RAW: {
01148             appendcOFile(fp,'\n');
01149             writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
01150             break;
01151             }
01152         case VCVT_VOBJECT:
01153             appendcOFile(fp,'\n');
01154             writeVObject_(fp,VOBJECT_VALUE_OF(o));
01155             break;
01156         }
01157 }
01158 
01159 static void writeAttrValue(OFile *fp, VObject *o)
01160 {
01161     if (NAME_OF(o)) {
01162         struct PreDefProp *pi;
01163         pi = lookupPropInfo(NAME_OF(o));
01164         if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
01165         if ( includesUnprintable(o,TRUE) )
01166             appendsOFileEncCs(fp);
01167         appendcOFile(fp,';');
01168         appendsOFile(fp,NAME_OF(o));
01169     } else {
01170         appendcOFile(fp,';');
01171     }
01172     if (VALUE_TYPE(o)) {
01173         appendcOFile(fp,'=');
01174         writeValue(fp,o,0,TRUE);
01175     }
01176 }
01177 
01178 static void writeGroup(OFile *fp, VObject *o)
01179 {
01180     char buf1[256];
01181     char buf2[256];
01182     strcpy(buf1,NAME_OF(o));
01183     while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
01184         strcpy(buf2,STRINGZ_VALUE_OF(o));
01185         strcat(buf2,".");
01186         strcat(buf2,buf1);
01187         strcpy(buf1,buf2);
01188         }
01189     appendsOFile(fp,buf1);
01190 }
01191 
01192 static int inList(const char **list, const char *s)
01193 {
01194     if (list == 0) return 0;
01195     while (*list) {
01196         if (qstricmp(*list,s) == 0) return 1;
01197         list++;
01198         }
01199     return 0;
01200 }
01201 
01202 static void writeProp(OFile *fp, VObject *o)
01203 {
01204     if (NAME_OF(o)) {
01205         struct PreDefProp *pi;
01206         VObjectIterator t;
01207         const char **fields_ = 0;
01208         pi = lookupPropInfo(NAME_OF(o));
01209         if (pi && ((pi->flags & PD_BEGIN) != 0)) {
01210             writeVObject_(fp,o);
01211             return;
01212             }
01213         if (isAPropertyOf(o,VCGroupingProp))
01214             writeGroup(fp,o);
01215         else
01216             appendsOFile(fp,NAME_OF(o));
01217         if (pi) fields_ = pi->fields;
01218         initPropIterator(&t,o);
01219         while (moreIteration(&t)) {
01220             const char *s;
01221             VObject *eachProp = nextVObject(&t);
01222             s = NAME_OF(eachProp);
01223             if (qstricmp(VCGroupingProp,s) && !inList(fields_,s))
01224                 writeAttrValue(fp,eachProp);
01225             }
01226         if (fields_) {
01227             int i = 0, n = 0;
01228             const char** fields = fields_;
01229             /* output prop as fields */
01230             bool printable = TRUE;
01231             while (*fields && printable) {
01232                 VObject *t = isAPropertyOf(o,*fields);
01233                 if (includesUnprintable(t,TRUE))
01234                     printable = FALSE;
01235                 fields++;
01236             }
01237             fields = fields_;
01238             if (!printable)
01239                 appendsOFileEncCs(fp);
01240             appendcOFile(fp,':');
01241             while (*fields) {
01242                 VObject *t = isAPropertyOf(o,*fields);
01243                 i++;
01244                 if (t) n = i;
01245                 fields++;
01246             }
01247             fields = fields_;
01248             for (i=0;i<n;i++) {
01249                 writeValue(fp,isAPropertyOf(o,*fields),0,TRUE);
01250                 fields++;
01251                 if (i<(n-1)) appendcOFile(fp,';');
01252             }
01253             }
01254         }
01255 
01256         
01257     if (VALUE_TYPE(o)) {
01258             if ( includesUnprintable(o,FALSE) )
01259                         appendsOFileEncCs(fp);
01260         unsigned long size = 0;
01261         VObject *p = isAPropertyOf(o,VCDataSizeProp);
01262         if (p) size = LONG_VALUE_OF(p);
01263         appendcOFile(fp,':');
01264         writeValue(fp,o,size,FALSE);
01265         }
01266 
01267     appendcOFile(fp,'\n');
01268 }
01269 
01270 static void writeVObject_(OFile *fp, VObject *o)
01271 {
01272     if (NAME_OF(o)) {
01273         struct PreDefProp *pi;
01274         pi = lookupPropInfo(NAME_OF(o));
01275 
01276         if (pi && ((pi->flags & PD_BEGIN) != 0)) {
01277             VObjectIterator t;
01278             const char *begin = NAME_OF(o);
01279             appendsOFile(fp,"BEGIN:");
01280             appendsOFile(fp,begin);
01281             appendcOFile(fp,'\n');
01282             initPropIterator(&t,o);
01283             while (moreIteration(&t)) {
01284                 VObject *eachProp = nextVObject(&t);
01285                 writeProp(fp, eachProp);
01286                 }
01287             appendsOFile(fp,"END:");
01288             appendsOFile(fp,begin);
01289             appendsOFile(fp,"\n\n");
01290             }
01291         }
01292 }
01293 
01294 static void initVObjectEncoding()
01295 {
01296     Config pimConfig( "Beam" );
01297     pimConfig.setGroup("Send");
01298     Config devcfg(pimConfig.readEntry("DeviceConfig"),Config::File);
01299     QString enc = "QP";
01300     QString cs = "UTF-8";
01301     if ( devcfg.isValid() ) {
01302         devcfg.setGroup("Send");
01303         enc = devcfg.readEntry("Encoding","QP"); 
01304         cs = devcfg.readEntry("CharSet","UTF-8"); 
01305     }
01306     strncpy(vobj_cs,cs.latin1(),10);
01307     if ( enc == "QP" ) {
01308         vobj_enc = QuotedPrintable;
01309         vobj_enc_s = VCQuotedPrintableProp;
01310     } else if ( enc == "B64" ) {
01311         vobj_enc = Base64;
01312         vobj_enc_s = VCBase64Prop;
01313     } else {
01314         vobj_enc = EightBit;
01315         vobj_enc_s = 0;
01316     }
01317 }
01318 
01319 void writeVObject(FILE *fp, VObject *o)
01320 {
01321     initVObjectEncoding();
01322 
01323     OFile ofp;
01324     // #####
01325     //_setmode(_fileno(fp), _O_BINARY);
01326     initOFile(&ofp,fp);
01327     writeVObject_(&ofp,o);
01328 }
01329 
01330 DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
01331 {
01332         QFileDirect f( fname);
01333         if ( !f.open( IO_WriteOnly ) ) {
01334                 qWarning("Unable to open vobject write %s", fname);
01335                 return;
01336         }
01337 
01338     writeVObject( f.directHandle(),o );
01339 }
01340 
01341 DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
01342 {
01343         QFileDirect f( fname);
01344         if ( !f.open( IO_WriteOnly ) ) {
01345                 qWarning("Unable to open vobject write %s", fname);
01346                 return;
01347         }
01348 
01349         while (list) {
01350             writeVObject(f.directHandle(),list);
01351             list = nextVObjectInList(list);
01352             }
01353 }
01354 
01355 DLLEXPORT(const char *) vObjectTypeInfo(VObject *o)
01356 {
01357     const char *type = vObjectName( o );
01358     if ( strcmp( type, "type" ) == 0 || 
01359          strcmp( type, "TYPE" ) == 0 ||
01360          strcmp( type, "Type" ) == 0 )
01361             type = vObjectStringZValue( o );
01362     return type;
01363 }
01364 
01365 
01366 // end of source file vobject.c

Generated on Sat Nov 5 16:16:34 2005 for OPIE by  doxygen 1.4.2