-rw-r--r-- | libkcal/versit/vobject.c | 297 |
1 files changed, 159 insertions, 138 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 @@ -33,228 +33,247 @@ PURPOSE. The software is provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the government are subject to restrictions set forth in 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 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: newVObject deleteVObject 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); if (t) { memcpy(t,s,size); t[size] = 0; return t; } 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)); p->next = next; p->s = s; p->refCnt = 1; return p; } static void deleteStrItem(StrItem *p) { - if (p) free((void*)p); - p = NULL; } /*---------------------------------------------------------------------- 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} V ... p1 {next,id,prop,val} V pn --> @@ -271,114 +290,114 @@ VObject* addVObjectProp(VObject *o, VObject *p) VObject *tail = o->prop; if (tail) { p->next = tail->next; o->prop = tail->next = 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 { VObject *t = *o; while (t->next) { 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; } else { i->next = i->next->next; 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) prop(VCGrouping=a) */ char *dot = strrchr(g,'.'); if (dot) { VObject *p, *t; char *gs, *n = dot+1; @@ -401,42 +420,42 @@ VObject* addGroup(VObject *o, const char *g) * and the value may have VCGrouping property */ t = addProp(t,VCGroupingProp); setVObjectStringZValue(t,lookupProp_(n)); } while (n != gs); deleteStr(gs); 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); } /*---------------------------------------------------------------------- The following pretty print a VObject ----------------------------------------------------------------------*/ static void printVObject_(FILE *fp, VObject *o, int level); @@ -519,46 +538,46 @@ static void printVObject_(FILE *fp, VObject *o, int level) initPropIterator(&t,o); while (moreIteration(&t)) { VObject *eachProp = nextVObject(&t); printVObject_(fp,eachProp,level+1); } } 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 list -- since at some point of destruction, the reference entry for the iterator to work will not longer be valid. */ VObject *p; p = o->prop->next; @@ -574,25 +593,25 @@ void cleanVObject(VObject *o) case VCVT_STRINGZ: case VCVT_RAW: /* 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); } } /*---------------------------------------------------------------------- The following is a String Table Facilities. ----------------------------------------------------------------------*/ @@ -601,85 +620,81 @@ void cleanVObjects(VObject *list) static StrItem *strTbl[STRTBLSIZE]; static unsigned int hashStr(const char *s) { unsigned int h = 0; int i; 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) { + if (stricmp(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; + 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); + 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; } } - prev = cur; - cur = cur->next; + p = t; + t = t->next; + } while (t); } } -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); - } + } while (t); strTbl[i] = 0; } } struct PreDefProp { const char *name; const char *alias; const char** fields; unsigned int flags; }; @@ -798,25 +813,25 @@ static struct PreDefProp propNames[] = { { VCDIBProp, 0, 0, 0 }, { VCDisplayStringProp, 0, 0, 0 }, { VCDomesticProp, 0, 0, 0 }, { VCDTendProp, 0, 0, 0 }, { VCDTstartProp, 0, 0, 0 }, { VCDueProp, 0, 0, 0 }, { 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 }, { VCGeoProp, 0, 0, 0 }, { VCGIFProp, 0, 0, 0 }, { VCGivenNameProp, 0, 0, 0 }, { VCGroupingProp, 0, 0, 0 }, { VCHomeProp, 0, 0, 0 }, { VCIBMMailProp, 0, 0, 0 }, @@ -912,138 +927,129 @@ static struct PreDefProp propNames[] = { { VCX509Prop, 0, 0, 0 }, { VCXRuleProp, 0, 0, 0 }, { 0,0,0,0 } }; 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; return lookupStr(str); } /*---------------------------------------------------------------------- APIs to Output text form. ----------------------------------------------------------------------*/ #define OFILE_REALLOC_SIZE 256 typedef struct OFile { FILE *fp; char *s; 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) { fwrite(s,1,slen,fp->fp); } else { stuff: if (fp->len + slen < fp->limit) { memcpy(fp->s+fp->len,s,slen); 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; } } static void appendcOFile(OFile *fp, char c) { if (fp->fail) return; if (fp->fp) { fputc(c,fp->fp); } else { stuff: if (fp->len+1 < fp->limit) { 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); } else { stuff: if (fp->len+1 < fp->limit) { fp->s[fp->len] = c; fp->len++; return; @@ -1136,60 +1142,73 @@ static int writeBase64(OFile *fp, unsigned char *s, long len) } /* now output 'quad' with appropriate whitespace and line ending */ appendsOFile(fp, (numQuads == 0 ? " " : "")); appendsOFile(fp, quad); appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); numQuads = (numQuads + 1) % MAXQUADS; } 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="); + /* break up lines biggger than 75 chars */ + if(count >=74){ + count=0; + appendsOFile(fp,"=\n"); } - if (*p == '=' && qp) - appendsOFile(fp,"=3D"); - else + + /* 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); break; } case VCVT_ULONG: { char buf[16]; sprintf(buf,"%lu", LONG_VALUE_OF(o)); appendsOFile(fp,buf); @@ -1211,103 +1230,105 @@ static void writeAttrValue(OFile *fp, VObject *o) { if (NAME_OF(o)) { struct PreDefProp *pi; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; appendcOFile(fp,';'); 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)) { writeVObject_(fp,o); return; } if (isAPropertyOf(o,VCGroupingProp)) writeGroup(fp,o); else appendsOFile(fp,NAME_OF(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) { if (NAME_OF(o)) { struct PreDefProp *pi; pi = lookupPropInfo(NAME_OF(o)); if (pi && ((pi->flags & PD_BEGIN) != 0)) { @@ -1326,106 +1347,106 @@ static void writeVObject_(OFile *fp, VObject *o) appendsOFile(fp,"\n\n"); } } } 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); } if (len) *len = ofp.len; appendcOFile(&ofp,0); 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) *bytes = len * sizeof(wchar_t); while (*ps) { if (*ps == '\n') *pw = (wchar_t)0x2028; else if (*ps == '\r') *pw = (wchar_t)0x2029; else *pw = (wchar_t)(unsigned char)*ps; ps++; pw++; } *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 *t = (char)*u; u++; t++; } *t = 0; return s; } |