Qtopia library API Documentation

vobject.cpp

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)
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             return TRUE;
01116             p++;
01117         }
01118         }
01119     }
01120     }
01121     return FALSE;
01122 }
01123         
01124 static void writeVObject_(OFile *fp, VObject *o);
01125 
01126 static void writeValue(OFile *fp, VObject *o, unsigned long size, bool nosemi)
01127 {
01128     if (o == 0) return;
01129     switch (VALUE_TYPE(o)) {
01130     case VCVT_STRINGZ: {
01131         writeEncString(fp, STRINGZ_VALUE_OF(o), nosemi);
01132         break;
01133         }
01134     case VCVT_UINT: {
01135         char buf[16];
01136         sprintf(buf,"%u", INTEGER_VALUE_OF(o));
01137         appendsOFile(fp,buf);
01138         break;
01139         }
01140     case VCVT_ULONG: {
01141         char buf[16];
01142         sprintf(buf,"%lu", LONG_VALUE_OF(o));
01143         appendsOFile(fp,buf);
01144         break;
01145         }
01146     case VCVT_RAW: {
01147         appendcOFile(fp,'\n');
01148         writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
01149         break;
01150         }
01151     case VCVT_VOBJECT:
01152         appendcOFile(fp,'\n');
01153         writeVObject_(fp,VOBJECT_VALUE_OF(o));
01154         break;
01155     }
01156 }
01157 
01158 static void writeAttrValue(OFile *fp, VObject *o)
01159 {
01160     if (NAME_OF(o)) {
01161     struct PreDefProp *pi;
01162     pi = lookupPropInfo(NAME_OF(o));
01163     if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
01164     if ( includesUnprintable(o) )
01165         appendsOFileEncCs(fp);
01166     appendcOFile(fp,';');
01167     appendsOFile(fp,NAME_OF(o));
01168     } else {
01169     appendcOFile(fp,';');
01170     }
01171     if (VALUE_TYPE(o)) {
01172     appendcOFile(fp,'=');
01173     writeValue(fp,o,0,TRUE);
01174     }
01175 }
01176 
01177 static void writeGroup(OFile *fp, VObject *o)
01178 {
01179     char buf1[256];
01180     char buf2[256];
01181     strcpy(buf1,NAME_OF(o));
01182     while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
01183     strcpy(buf2,STRINGZ_VALUE_OF(o));
01184     strcat(buf2,".");
01185     strcat(buf2,buf1);
01186     strcpy(buf1,buf2);
01187     }
01188     appendsOFile(fp,buf1);
01189 }
01190 
01191 static int inList(const char **list, const char *s)
01192 {
01193     if (list == 0) return 0;
01194     while (*list) {
01195     if (qstricmp(*list,s) == 0) return 1;
01196     list++;
01197     }
01198     return 0;
01199 }
01200 
01201 static void writeProp(OFile *fp, VObject *o)
01202 {
01203     if (NAME_OF(o)) {
01204     struct PreDefProp *pi;
01205     VObjectIterator t;
01206     const char **fields_ = 0;
01207     pi = lookupPropInfo(NAME_OF(o));
01208     if (pi && ((pi->flags & PD_BEGIN) != 0)) {
01209         writeVObject_(fp,o);
01210         return;
01211         }
01212     if (isAPropertyOf(o,VCGroupingProp))
01213         writeGroup(fp,o);
01214     else
01215         appendsOFile(fp,NAME_OF(o));
01216     if (pi) fields_ = pi->fields;
01217     initPropIterator(&t,o);
01218     while (moreIteration(&t)) {
01219         const char *s;
01220         VObject *eachProp = nextVObject(&t);
01221         s = NAME_OF(eachProp);
01222         if (qstricmp(VCGroupingProp,s) && !inList(fields_,s))
01223         writeAttrValue(fp,eachProp);
01224         }
01225     if (fields_) {
01226         int i = 0, n = 0;
01227         const char** fields = fields_;
01228         /* output prop as fields */
01229         bool printable = TRUE;
01230         while (*fields && printable) {
01231         VObject *t = isAPropertyOf(o,*fields);
01232         if (includesUnprintable(t))
01233             printable = FALSE;
01234         fields++;
01235         }
01236         fields = fields_;
01237         if (!printable)
01238         appendsOFileEncCs(fp);
01239         appendcOFile(fp,':');
01240         while (*fields) {
01241         VObject *t = isAPropertyOf(o,*fields);
01242         i++;
01243         if (t) n = i;
01244         fields++;
01245         }
01246         fields = fields_;
01247         for (i=0;i<n;i++) {
01248         writeValue(fp,isAPropertyOf(o,*fields),0,TRUE);
01249         fields++;
01250         if (i<(n-1)) appendcOFile(fp,';');
01251         }
01252         }
01253     }
01254 
01255     
01256     if (VALUE_TYPE(o)) {
01257         if ( includesUnprintable(o) )
01258             appendsOFileEncCs(fp);
01259     unsigned long size = 0;
01260         VObject *p = isAPropertyOf(o,VCDataSizeProp);
01261     if (p) size = LONG_VALUE_OF(p);
01262     appendcOFile(fp,':');
01263     writeValue(fp,o,size,FALSE);
01264     }
01265 
01266     appendcOFile(fp,'\n');
01267 }
01268 
01269 static void writeVObject_(OFile *fp, VObject *o)
01270 {
01271     if (NAME_OF(o)) {
01272     struct PreDefProp *pi;
01273     pi = lookupPropInfo(NAME_OF(o));
01274 
01275     if (pi && ((pi->flags & PD_BEGIN) != 0)) {
01276         VObjectIterator t;
01277         const char *begin = NAME_OF(o);
01278         appendsOFile(fp,"BEGIN:");
01279         appendsOFile(fp,begin);
01280         appendcOFile(fp,'\n');
01281         initPropIterator(&t,o);
01282         while (moreIteration(&t)) {
01283         VObject *eachProp = nextVObject(&t);
01284         writeProp(fp, eachProp);
01285         }
01286         appendsOFile(fp,"END:");
01287         appendsOFile(fp,begin);
01288         appendsOFile(fp,"\n\n");
01289         }
01290     }
01291 }
01292 
01293 static void initVObjectEncoding()
01294 {
01295     Config pimConfig( "Beam" );
01296     pimConfig.setGroup("Send");
01297     Config devcfg(pimConfig.readEntry("DeviceConfig"),Config::File);
01298     QString enc = "QP";
01299     QString cs = "UTF-8";
01300     if ( devcfg.isValid() ) {
01301     devcfg.setGroup("Send");
01302     enc = devcfg.readEntry("Encoding","QP"); 
01303     cs = devcfg.readEntry("CharSet","UTF-8"); 
01304     }
01305     strncpy(vobj_cs,cs.latin1(),10);
01306     if ( enc == "QP" ) {
01307     vobj_enc = QuotedPrintable;
01308     vobj_enc_s = VCQuotedPrintableProp;
01309     } else if ( enc == "B64" ) {
01310     vobj_enc = Base64;
01311     vobj_enc_s = VCBase64Prop;
01312     } else {
01313     vobj_enc = EightBit;
01314     vobj_enc_s = 0;
01315     }
01316 }
01317 
01318 void writeVObject(FILE *fp, VObject *o)
01319 {
01320     initVObjectEncoding();
01321 
01322     OFile ofp;
01323     // #####
01324     //_setmode(_fileno(fp), _O_BINARY);
01325     initOFile(&ofp,fp);
01326     writeVObject_(&ofp,o);
01327 }
01328 
01329 DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
01330 {
01331     QFileDirect f( fname);
01332     if ( !f.open( IO_WriteOnly ) ) {
01333         qWarning("Unable to open vobject write %s", fname);
01334         return;
01335     }
01336 
01337     writeVObject( f.directHandle(),o );
01338 }
01339 
01340 DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
01341 {
01342     QFileDirect f( fname);
01343     if ( !f.open( IO_WriteOnly ) ) {
01344         qWarning("Unable to open vobject write %s", fname);
01345         return;
01346     }
01347 
01348     while (list) {
01349         writeVObject(f.directHandle(),list);
01350         list = nextVObjectInList(list);
01351         }
01352 }
01353 
01354 DLLEXPORT(const char *) vObjectTypeInfo(VObject *o)
01355 {
01356     const char *type = vObjectName( o );
01357     if ( strcmp( type, "TYPE" ) == 0 )
01358     type = vObjectStringZValue( o );
01359     return type;
01360 }
01361 
01362 
01363 // end of source file vobject.c
KDE Logo
This file is part of the documentation for OPIE Version 1.5.5.
Documentation copyright © 1997-2003 the KDE developers. 2003 OPIE developers
Generated on Tue Feb 10 20:24:08 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001