-rw-r--r-- | libkcal/versit/vobject.c | 363 |
1 files changed, 192 insertions, 171 deletions
diff --git a/libkcal/versit/vobject.c b/libkcal/versit/vobject.c index 637efb2..3fac63e 100644 --- a/libkcal/versit/vobject.c +++ b/libkcal/versit/vobject.c @@ -39,32 +39,58 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. /* * src: vobject.c * doc: vobject and APIs to construct vobject, APIs pretty print * vobject, and convert a vobject into its textual representation. */ -#include <stdlib.h> +#ifdef WIN32 +#define snprintf _snprintf +#define strcasecmp stricmp +#endif #include "vobject.h" +#include <stdlib.h> #include <string.h> #include <stdio.h> -#ifdef _WIN32_ +#include <fcntl.h> - #define strcasecmp _stricmp -#endif - -#define NAME_OF(o) o->id +#define NAME_OF(o) o->id #define VALUE_TYPE(o) o->valType #define STRINGZ_VALUE_OF(o) o->val.strs #define USTRINGZ_VALUE_OF(o) o->val.ustrs #define INTEGER_VALUE_OF(o) o->val.i #define LONG_VALUE_OF(o) o->val.l #define ANY_VALUE_OF(o) o->val.any #define VOBJECT_VALUE_OF(o) o->val.vobj +typedef union ValueItem { + const char *strs; + const wchar_t *ustrs; + unsigned int i; + unsigned long l; + void *any; + VObject *vobj; + } ValueItem; + +struct VObject { + VObject *next; + const char *id; + VObject *prop; + unsigned short valType; + ValueItem val; + }; + +typedef struct StrItem StrItem; + +struct StrItem { + StrItem *next; + const char *s; + unsigned int refCnt; + }; + const char** fieldedProp; /*---------------------------------------------------------------------- The following functions involve with memory allocation: @@ -73,38 +99,35 @@ const char** fieldedProp; dupStr deleteStr newStrItem deleteStrItem ----------------------------------------------------------------------*/ -VObject* newVObject_(const char *id) +DLLEXPORT(VObject*) newVObject_(const char *id) { VObject *p = (VObject*)malloc(sizeof(VObject)); p->next = 0; p->id = id; p->prop = 0; VALUE_TYPE(p) = 0; ANY_VALUE_OF(p) = 0; return p; } -VObject* newVObject(const char *id) +DLLEXPORT(VObject*) newVObject(const char *id) { return newVObject_(lookupStr(id)); } -void deleteVObject(VObject *p) +DLLEXPORT(void) deleteVObject(VObject *p) { - if (p->id) unUseStr(p->id); - if (p) free(p); - p = NULL; } -char* dupStr(const char *s, unsigned int size) +DLLEXPORT(char*) dupStr(const char *s, unsigned int size) { char *t; if (size == 0) { size = strlen(s); } t = (char*)malloc(size+1); @@ -115,17 +138,15 @@ char* dupStr(const char *s, unsigned int size) } else { return (char*)0; } } -void deleteStr(const char *p) +DLLEXPORT(void) deleteStr(const char *p) { - if (p) - free((void*)p); - p = NULL; + if (p) free((void*)p); } static StrItem* newStrItem(const char *s, StrItem *next) { StrItem *p = (StrItem*)malloc(sizeof(StrItem)); @@ -134,121 +155,119 @@ static StrItem* newStrItem(const char *s, StrItem *next) p->refCnt = 1; return p; } static void deleteStrItem(StrItem *p) { - if (p) - free((void*)p); - p = NULL; + free((void*)p); } /*---------------------------------------------------------------------- The following function provide accesses to VObject's value. ----------------------------------------------------------------------*/ -const char* vObjectName(VObject *o) +DLLEXPORT(const char*) vObjectName(VObject *o) { return NAME_OF(o); } -void setVObjectName(VObject *o, const char* id) +DLLEXPORT(void) setVObjectName(VObject *o, const char* id) { NAME_OF(o) = id; } -const char* vObjectStringZValue(VObject *o) +DLLEXPORT(const char*) vObjectStringZValue(VObject *o) { return STRINGZ_VALUE_OF(o); } -void setVObjectStringZValue(VObject *o, const char *s) +DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s) { STRINGZ_VALUE_OF(o) = dupStr(s,0); VALUE_TYPE(o) = VCVT_STRINGZ; } -void setVObjectStringZValue_(VObject *o, const char *s) +DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s) { STRINGZ_VALUE_OF(o) = s; VALUE_TYPE(o) = VCVT_STRINGZ; } -const wchar_t* vObjectUStringZValue(VObject *o) +DLLEXPORT(const wchar_t*) vObjectUStringZValue(VObject *o) { return USTRINGZ_VALUE_OF(o); } -void setVObjectUStringZValue(VObject *o, const wchar_t *s) +DLLEXPORT(void) setVObjectUStringZValue(VObject *o, const wchar_t *s) { USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2); VALUE_TYPE(o) = VCVT_USTRINGZ; } -void setVObjectUStringZValue_(VObject *o, const wchar_t *s) +DLLEXPORT(void) setVObjectUStringZValue_(VObject *o, const wchar_t *s) { USTRINGZ_VALUE_OF(o) = s; VALUE_TYPE(o) = VCVT_USTRINGZ; } -unsigned int vObjectIntegerValue(VObject *o) +DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o) { return INTEGER_VALUE_OF(o); } -void setVObjectIntegerValue(VObject *o, unsigned int i) +DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i) { INTEGER_VALUE_OF(o) = i; VALUE_TYPE(o) = VCVT_UINT; } -unsigned long vObjectLongValue(VObject *o) +DLLEXPORT(unsigned long) vObjectLongValue(VObject *o) { return LONG_VALUE_OF(o); } -void setVObjectLongValue(VObject *o, unsigned long l) +DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l) { LONG_VALUE_OF(o) = l; VALUE_TYPE(o) = VCVT_ULONG; } -void* vObjectAnyValue(VObject *o) +DLLEXPORT(void*) vObjectAnyValue(VObject *o) { return ANY_VALUE_OF(o); } -void setVObjectAnyValue(VObject *o, void *t) +DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t) { ANY_VALUE_OF(o) = t; VALUE_TYPE(o) = VCVT_RAW; } -VObject* vObjectVObjectValue(VObject *o) +DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o) { return VOBJECT_VALUE_OF(o); } -void setVObjectVObjectValue(VObject *o, VObject *p) +DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p) { VOBJECT_VALUE_OF(o) = p; VALUE_TYPE(o) = VCVT_VOBJECT; } -int vObjectValueType(VObject *o) +DLLEXPORT(int) vObjectValueType(VObject *o) { return VALUE_TYPE(o); } /*---------------------------------------------------------------------- The following functions can be used to build VObject. ----------------------------------------------------------------------*/ -VObject* addVObjectProp(VObject *o, VObject *p) +DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p) { /* circular link list pointed to tail */ /* o {next,id,prop,val} V pn {next,id,prop,val} @@ -277,23 +296,23 @@ VObject* addVObjectProp(VObject *o, VObject *p) else { o->prop = p->next = p; } return p; } -VObject* addProp(VObject *o, const char *id) +DLLEXPORT(VObject*) addProp(VObject *o, const char *id) { return addVObjectProp(o,newVObject(id)); } -VObject* addProp_(VObject *o, const char *id) +DLLEXPORT(VObject*) addProp_(VObject *o, const char *id) { return addVObjectProp(o,newVObject_(id)); } -void addList(VObject **o, VObject *p) +DLLEXPORT(void) addList(VObject **o, VObject *p) { p->next = 0; if (*o == 0) { *o = p; } else { @@ -302,50 +321,50 @@ void addList(VObject **o, VObject *p) t = t->next; } t->next = p; } } -VObject* nextVObjectInList(VObject *o) +DLLEXPORT(VObject*) nextVObjectInList(VObject *o) { return o->next; } -VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size) +DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size) { VObject *sizeProp; setVObjectAnyValue(prop, val); sizeProp = addProp(prop,VCDataSizeProp); setVObjectLongValue(sizeProp, size); return prop; } -VObject* setValueWithSize(VObject *prop, void *val, unsigned int size) +DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size) { - void *p = dupStr(val,size); + void *p = dupStr((const char *)val,size); return setValueWithSize_(prop,p,p?size:0); } -void initPropIterator(VObjectIterator *i, VObject *o) +DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o) { i->start = o->prop; i->next = 0; } -void initVObjectIterator(VObjectIterator *i, VObject *o) +DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o) { i->start = o->next; i->next = 0; } -int moreIteration(VObjectIterator *i) +DLLEXPORT(int) moreIteration(VObjectIterator *i) { return (i->start && (i->next==0 || i->next!=i->start)); } -VObject* nextVObject(VObjectIterator *i) +DLLEXPORT(VObject*) nextVObject(VObjectIterator *i) { if (i->start && i->next != i->start) { if (i->next == 0) { i->next = i->start->next; return i->next; } @@ -354,25 +373,25 @@ VObject* nextVObject(VObjectIterator *i) return i->next; } } else return (VObject*)0; } -VObject* isAPropertyOf(VObject *o, const char *id) +DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id) { VObjectIterator i; initPropIterator(&i,o); while (moreIteration(&i)) { VObject *each = nextVObject(&i); - if (!strcasecmp(id,each->id)) + if (!stricmp(id,each->id)) return each; } return (VObject*)0; } -VObject* addGroup(VObject *o, const char *g) +DLLEXPORT(VObject*) addGroup(VObject *o, const char *g) { /* a.b.c --> prop(c) prop(VCGrouping=b) @@ -407,30 +426,30 @@ VObject* addGroup(VObject *o, const char *g) return p; } else return addProp_(o,lookupProp(g)); } -VObject* addPropValue(VObject *o, const char *p, const char *v) +DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v) { VObject *prop; prop = addProp(o,p); setVObjectUStringZValue_(prop, fakeUnicode(v,0)); return prop; } -VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, +DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size) { VObject *prop; prop = addProp(o,p); setValueWithSize_(prop, (void*)v, size); return prop; } -VObject* addPropSizedValue(VObject *o, const char *p, const char *v, +DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size) { return addPropSizedValue_(o,p,dupStr(v,size),size); } @@ -525,34 +544,34 @@ static void printVObject_(FILE *fp, VObject *o, int level) void printVObject(FILE *fp,VObject *o) { printVObject_(fp,o,0); } -void printVObjectToFile(char *fname,VObject *o) +DLLEXPORT(void) printVObjectToFile(char *fname,VObject *o) { FILE *fp = fopen(fname,"w"); if (fp) { printVObject(fp,o); fclose(fp); } } -void printVObjectsToFile(char *fname,VObject *list) +DLLEXPORT(void) printVObjectsToFile(char *fname,VObject *list) { FILE *fp = fopen(fname,"w"); if (fp) { while (list) { printVObject(fp,list); list = nextVObjectInList(list); } fclose(fp); } } -void cleanVObject(VObject *o) +DLLEXPORT(void) cleanVObject(VObject *o) { if (o == 0) return; if (o->prop) { /* destroy time: cannot use the iterator here. Have to break the cycle in the circular link list and turns it into regular NULL-terminated @@ -570,23 +589,23 @@ void cleanVObject(VObject *o) } while (p); } switch (VALUE_TYPE(o)) { case VCVT_USTRINGZ: case VCVT_STRINGZ: case VCVT_RAW: - /* assume they are all allocated by malloc. */ + /* assume they are all allocated by malloc. */ free((char*)STRINGZ_VALUE_OF(o)); break; case VCVT_VOBJECT: cleanVObject(VOBJECT_VALUE_OF(o)); break; } deleteVObject(o); } -void cleanVObjects(VObject *list) +DLLEXPORT(void) cleanVObjects(VObject *list) { while (list) { VObject *t = list; list = nextVObjectInList(list); cleanVObject(t); } @@ -607,75 +626,71 @@ static unsigned int hashStr(const char *s) for (i=0;s[i];i++) { h += s[i]*i; } return h % STRTBLSIZE; } -const char* lookupStr(const char *s) +DLLEXPORT(const char*) lookupStr(const char *s) { - char *newS; - - StrItem *t; - unsigned int h = hashStr(s); - if ((t = strTbl[h]) != 0) { - do { - if (strcasecmp(t->s,s) == 0) { - t->refCnt++; - return t->s; - } - t = t->next; - } while (t); - } - newS = dupStr(s,0); - strTbl[h] = newStrItem(newS,strTbl[h]); - return newS; + StrItem *t; + unsigned int h = hashStr(s); + if ((t = strTbl[h]) != 0) { + do { + if (stricmp(t->s,s) == 0) { + t->refCnt++; + return t->s; + } + t = t->next; + } while (t); + } + s = dupStr(s,0); + strTbl[h] = newStrItem(s,strTbl[h]); + return s; } -void unUseStr(const char *s) +DLLEXPORT(void) unUseStr(const char *s) { - StrItem *cur, *prev; - + StrItem *t, *p; unsigned int h = hashStr(s); - cur = strTbl[h]; - prev = cur; - while (cur != 0) { - if (strcasecmp(cur->s,s) == 0) { - cur->refCnt--; - /* if that was the last reference to this string, kill it. */ - if (cur->refCnt == 0) { - if (cur == strTbl[h]) { - strTbl[h] = cur->next; - deleteStr(prev->s); - deleteStrItem(prev); - } else { - prev->next = cur->next; - deleteStr(cur->s); - deleteStrItem(cur); - } - return; + if ((t = strTbl[h]) != 0) { + p = t; + do { + if (stricmp(t->s,s) == 0) { + t->refCnt--; + if (t->refCnt == 0) { + if (p == strTbl[h]) { + strTbl[h] = t->next; + } + else { + p->next = t->next; + } + deleteStr(t->s); + deleteStrItem(t); + return; + } + } + p = t; + t = t->next; + } while (t); } - } - prev = cur; - cur = cur->next; - } } -void cleanStrTbl() +DLLEXPORT(void) cleanStrTbl() { - int i; - for (i=0; i<STRTBLSIZE;i++) { - StrItem *t = strTbl[i]; - while (t) { - StrItem *p; - deleteStr(t->s); - p = t; - t = t->next; - deleteStrItem(p); - } - strTbl[i] = 0; - } + int i; + for (i=0; i<STRTBLSIZE;i++) { + StrItem *t = strTbl[i]; + while (t) { + StrItem *p; + deleteStr(t->s); + p = t; + t = t->next; + deleteStrItem(p); + } while (t); + strTbl[i] = 0; + } } struct PreDefProp { const char *name; const char *alias; @@ -804,13 +819,13 @@ static struct PreDefProp propNames[] = { { VCEmailAddressProp, 0, 0, 0 }, { VCEncodingProp, 0, 0, 0 }, { VCEndProp, 0, 0, 0 }, { VCEventProp, 0, 0, PD_BEGIN }, { VCEWorldProp, 0, 0, 0 }, { VCExNumProp, 0, 0, 0 }, - { VCExDateProp, 0, 0, 0 }, + { VCExpDateProp, 0, 0, 0 }, { VCExpectProp, 0, 0, 0 }, { VCExtAddressProp, 0, 0, 0 }, { VCFamilyNameProp, 0, 0, 0 }, { VCFaxProp, 0, 0, 0 }, { VCFullNameProp, 0, 0, 0 }, { VCGeoLocationProp, 0, 0, 0 }, @@ -918,40 +933,40 @@ static struct PreDefProp propNames[] = { static struct PreDefProp* lookupPropInfo(const char* str) { /* brute force for now, could use a hash table here. */ int i; for (i = 0; propNames[i].name; i++) - if (strcasecmp(str, propNames[i].name) == 0) { + if (stricmp(str, propNames[i].name) == 0) { return &propNames[i]; } return 0; } -const char* lookupProp_(const char* str) +DLLEXPORT(const char*) lookupProp_(const char* str) { int i; for (i = 0; propNames[i].name; i++) - if (strcasecmp(str, propNames[i].name) == 0) { + if (stricmp(str, propNames[i].name) == 0) { const char* s; s = propNames[i].alias?propNames[i].alias:propNames[i].name; return lookupStr(s); } return lookupStr(str); } -const char* lookupProp(const char* str) +DLLEXPORT(const char*) lookupProp(const char* str) { int i; for (i = 0; propNames[i].name; i++) - if (strcasecmp(str, propNames[i].name) == 0) { + if (stricmp(str, propNames[i].name) == 0) { const char *s; fieldedProp = propNames[i].fields; s = propNames[i].alias?propNames[i].alias:propNames[i].name; return lookupStr(s); } fieldedProp = 0; @@ -969,17 +984,13 @@ typedef struct OFile { int len; int limit; int alloc:1; int fail:1; } OFile; - -/* vCalendar files need crlf linebreaks. The disabled functions didn't provide - that. */ #if 0 - static void appendsOFile(OFile *fp, const char *s) { int slen; if (fp->fail) return; slen = strlen(s); if (fp->fp) { @@ -992,16 +1003,13 @@ stuff: fp->len += slen; return; } else if (fp->alloc) { fp->limit = fp->limit + OFILE_REALLOC_SIZE; if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen; - if (fp->s) - fp->s = realloc(fp->s,fp->limit); - else - fp->s = malloc(fp->limit); + fp->s = (char *) realloc(fp->s,fp->limit); if (fp->s) goto stuff; } if (fp->alloc) free(fp->s); fp->s = 0; fp->fail = 1; @@ -1020,24 +1028,22 @@ stuff: fp->s[fp->len] = c; fp->len++; return; } else if (fp->alloc) { fp->limit = fp->limit + OFILE_REALLOC_SIZE; - fp->s = realloc(fp->s,fp->limit); + fp->s = (char *) realloc(fp->s,fp->limit); if (fp->s) goto stuff; } if (fp->alloc) free(fp->s); fp->s = 0; fp->fail = 1; } } - #else - static void appendcOFile_(OFile *fp, char c) { if (fp->fail) return; if (fp->fp) { fputc(c,fp->fp); } @@ -1112,25 +1118,25 @@ static int writeBase64(OFile *fp, unsigned char *s, long len) char quad[5]; #define MAXQUADS 16 quad[4] = 0; while (cur < len) { - /* collect the triplet of bytes into 'trip' */ + /* collect the triplet of bytes into 'trip' */ trip = 0; for (i = 0; i < 3; i++) { b = (cur < len) ? *(s + cur) : 0; cur++; trip = trip << 8 | b; } /* fill in 'quad' with the appropriate four characters */ for (i = 3; i >= 0; i--) { b = (unsigned char)(trip & 0x3F); trip = trip >> 6; if ((3 - i) < (cur - len)) - quad[i] = '='; /* pad char */ + quad[i] = '='; /* pad char */ else if (b < 26) quad[i] = (char)b + 'A'; else if (b < 52) quad[i] = (char)(b - 26) + 'a'; else if (b < 62) quad[i] = (char)(b - 52) + '0'; else if (b == 62) quad[i] = '+'; else quad[i] = '/'; } @@ -1142,48 +1148,61 @@ static int writeBase64(OFile *fp, unsigned char *s, long len) } appendcOFile(fp,'\n'); return 1; } -/* this function really sucks. Too basic. */ -static void writeQPString(OFile *fp, const char *s, int qp) +static void writeString(OFile *fp, const char *s) +{ + appendsOFile(fp,s); +} + +static void writeQPString(OFile *fp, const char *s) { + char buf[4]; + int count=0; const char *p = s; + while (*p) { - if (*p == '\n') { - if (p[1]) appendsOFile(fp,"=0A="); - } - if (*p == '=' && qp) - appendsOFile(fp,"=3D"); - else - appendcOFile(fp,*p); - p++; + /* break up lines biggger than 75 chars */ + if(count >=74){ + count=0; + appendsOFile(fp,"=\n"); + } + + /* escape any non ASCII characters and '=' as per rfc1521 */ + if (*p<= 0x1f || *p >=0x7f || *p == '=' ) { + sprintf(buf,"=%02X",(unsigned char)*p); + appendsOFile(fp,buf); + count+=3; + } else { + appendcOFile(fp,*p); + count++; + } + p++; } } + + static void writeVObject_(OFile *fp, VObject *o); -static void writeValue(OFile *fp, VObject *o, unsigned long size) +static void writeValue(OFile *fp, VObject *o, unsigned long size,int quote) { if (o == 0) return; switch (VALUE_TYPE(o)) { case VCVT_USTRINGZ: { char *s = fakeCString(USTRINGZ_VALUE_OF(o)); - if (isAPropertyOf(o, VCQuotedPrintableProp)) - writeQPString(fp, s, 1); - else - writeQPString(fp, s, 0); + if(quote) writeQPString(fp, s); + else writeString(fp,s); deleteStr(s); break; } case VCVT_STRINGZ: { - if (isAPropertyOf(o, VCQuotedPrintableProp)) - writeQPString(fp, STRINGZ_VALUE_OF(o), 1); - else - writeQPString(fp, STRINGZ_VALUE_OF(o), 0); + if(quote) writeQPString(fp, STRINGZ_VALUE_OF(o)); + else writeString(fp,STRINGZ_VALUE_OF(o)); break; } case VCVT_UINT: { char buf[16]; sprintf(buf,"%u", INTEGER_VALUE_OF(o)); appendsOFile(fp,buf); @@ -1217,43 +1236,43 @@ static void writeAttrValue(OFile *fp, VObject *o) appendsOFile(fp,NAME_OF(o)); } else appendcOFile(fp,';'); if (VALUE_TYPE(o)) { appendcOFile(fp,'='); - writeValue(fp,o,0); + writeValue(fp,o,0,0); } } static void writeGroup(OFile *fp, VObject *o) { char buf1[256]; char buf2[256]; strcpy(buf1,NAME_OF(o)); while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { - strncpy(buf2,STRINGZ_VALUE_OF(o),sizeof(buf2)); - buf2[sizeof(buf2)] = '\0'; - strncat(buf2,".",sizeof(buf2)-strlen(buf2)-1); - strncat(buf2,buf1,sizeof(buf2)-strlen(buf2)-1); + strcpy(buf2,STRINGZ_VALUE_OF(o)); + strcat(buf2,"."); + strcat(buf2,buf1); strcpy(buf1,buf2); } appendsOFile(fp,buf1); } static int inList(const char **list, const char *s) { if (list == 0) return 0; while (*list) { - if (strcasecmp(*list,s) == 0) return 1; + if (stricmp(*list,s) == 0) return 1; list++; } return 0; } static void writeProp(OFile *fp, VObject *o) { + int isQuoted=0; if (NAME_OF(o)) { struct PreDefProp *pi; VObjectIterator t; const char **fields_ = 0; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_BEGIN) != 0)) { @@ -1267,41 +1286,43 @@ static void writeProp(OFile *fp, VObject *o) if (pi) fields_ = pi->fields; initPropIterator(&t,o); while (moreIteration(&t)) { const char *s; VObject *eachProp = nextVObject(&t); s = NAME_OF(eachProp); - if (strcasecmp(VCGroupingProp,s) && !inList(fields_,s)) + if (stricmp(VCGroupingProp,s) && !inList(fields_,s)) writeAttrValue(fp,eachProp); + if (stricmp(VCQPProp,s)==0 || stricmp(VCQuotedPrintableProp,s)==0) + isQuoted=1; } if (fields_) { int i = 0, n = 0; const char** fields = fields_; /* output prop as fields */ appendcOFile(fp,':'); while (*fields) { - VObject *tl = isAPropertyOf(o,*fields); + VObject *t = isAPropertyOf(o,*fields); i++; - if (tl) n = i; + if (t) n = i; fields++; } fields = fields_; for (i=0;i<n;i++) { - writeValue(fp,isAPropertyOf(o,*fields),0); + writeValue(fp,isAPropertyOf(o,*fields),0,isQuoted); fields++; if (i<(n-1)) appendcOFile(fp,';'); } } } if (VALUE_TYPE(o)) { unsigned long size = 0; VObject *p = isAPropertyOf(o,VCDataSizeProp); if (p) size = LONG_VALUE_OF(p); appendcOFile(fp,':'); - writeValue(fp,o,size); + writeValue(fp,o,size,isQuoted); } appendcOFile(fp,'\n'); } static void writeVObject_(OFile *fp, VObject *o) @@ -1332,44 +1353,44 @@ void writeVObject(FILE *fp, VObject *o) { OFile ofp; initOFile(&ofp,fp); writeVObject_(&ofp,o); } -void writeVObjectToFile(char *fname, VObject *o) +DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o) { FILE *fp = fopen(fname,"w"); if (fp) { writeVObject(fp,o); fclose(fp); } } -void writeVObjectsToFile(char *fname, VObject *list) +DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list) { FILE *fp = fopen(fname,"w"); if (fp) { while (list) { writeVObject(fp,list); list = nextVObjectInList(list); } fclose(fp); } } -char* writeMemVObject(char *s, int *len, VObject *o) +DLLEXPORT(char*) writeMemVObject(char *s, int *len, VObject *o) { OFile ofp; initMemOFile(&ofp,s,len?*len:0); writeVObject_(&ofp,o); if (len) *len = ofp.len; appendcOFile(&ofp,0); return ofp.s; } -char* writeMemVObjects(char *s, int *len, VObject *list) +DLLEXPORT(char*) writeMemVObjects(char *s, int *len, VObject *list) { OFile ofp; initMemOFile(&ofp,s,len?*len:0); while (list) { writeVObject_(&ofp,list); list = nextVObjectInList(list); @@ -1379,13 +1400,13 @@ char* writeMemVObjects(char *s, int *len, VObject *list) return ofp.s; } /*---------------------------------------------------------------------- APIs to do fake Unicode stuff. ----------------------------------------------------------------------*/ -wchar_t* fakeUnicode(const char *ps, int *bytes) +DLLEXPORT(wchar_t*) fakeUnicode(const char *ps, int *bytes) { wchar_t *r, *pw; int len = strlen(ps)+1; pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len); if (bytes) @@ -1402,24 +1423,24 @@ wchar_t* fakeUnicode(const char *ps, int *bytes) } *pw = (wchar_t)0; return r; } -int uStrLen(const wchar_t *u) +DLLEXPORT(int) uStrLen(const wchar_t *u) { int i = 0; while (*u != (wchar_t)0) { u++; i++; } return i; } -char* fakeCString(const wchar_t *u) +DLLEXPORT(char*) fakeCString(const wchar_t *u) { char *s, *t; int len = uStrLen(u) + 1; - t = s = (char*)malloc(len+1); + t = s = (char*)malloc(len); while (*u) { if (*u == (wchar_t)0x2028) *t = '\n'; else if (*u == (wchar_t)0x2029) *t = '\r'; else |