From b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 Mon Sep 17 00:00:00 2001 From: zautrix Date: Sat, 26 Jun 2004 19:01:18 +0000 Subject: Initial revision --- (limited to 'libkcal/versit/vobject.c') diff --git a/libkcal/versit/vobject.c b/libkcal/versit/vobject.c new file mode 100644 index 0000000..637efb2 --- a/dev/null +++ b/libkcal/versit/vobject.c @@ -0,0 +1,1433 @@ +/*************************************************************************** +(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. + +For purposes of this license notice, the term Licensors shall mean, +collectively, Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. +The term Licensor shall mean any of the Licensors. + +Subject to acceptance of the following conditions, permission is hereby +granted by Licensors without the need for written agreement and without +license or royalty fees, to use, copy, modify and distribute this +software for any purpose. + +The above copyright notice and the following four paragraphs must be +reproduced in all copies of this software and any software including +this software. + +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE +ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR +MODIFICATIONS. + +IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, +INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT +OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +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 + +#include "vobject.h" +#include +#include +#ifdef _WIN32_ + + #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 + +const char** fieldedProp; + + + +/*---------------------------------------------------------------------- + The following functions involve with memory allocation: + newVObject + deleteVObject + dupStr + deleteStr + newStrItem + deleteStrItem + ----------------------------------------------------------------------*/ + +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) +{ + return newVObject_(lookupStr(id)); +} + +void deleteVObject(VObject *p) +{ + if (p->id) + unUseStr(p->id); + if (p) + free(p); + p = NULL; +} + +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) +{ + if (p) + free((void*)p); + p = NULL; +} + + +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) +{ + return NAME_OF(o); +} + +void setVObjectName(VObject *o, const char* id) +{ + NAME_OF(o) = id; +} + +const char* vObjectStringZValue(VObject *o) +{ + return STRINGZ_VALUE_OF(o); +} + +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) +{ + STRINGZ_VALUE_OF(o) = s; + VALUE_TYPE(o) = VCVT_STRINGZ; +} + +const wchar_t* vObjectUStringZValue(VObject *o) +{ + return USTRINGZ_VALUE_OF(o); +} + +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) +{ + USTRINGZ_VALUE_OF(o) = s; + VALUE_TYPE(o) = VCVT_USTRINGZ; +} + +unsigned int vObjectIntegerValue(VObject *o) +{ + return INTEGER_VALUE_OF(o); +} + +void setVObjectIntegerValue(VObject *o, unsigned int i) +{ + INTEGER_VALUE_OF(o) = i; + VALUE_TYPE(o) = VCVT_UINT; +} + +unsigned long vObjectLongValue(VObject *o) +{ + return LONG_VALUE_OF(o); +} + +void setVObjectLongValue(VObject *o, unsigned long l) +{ + LONG_VALUE_OF(o) = l; + VALUE_TYPE(o) = VCVT_ULONG; +} + +void* vObjectAnyValue(VObject *o) +{ + return ANY_VALUE_OF(o); +} + +void setVObjectAnyValue(VObject *o, void *t) +{ + ANY_VALUE_OF(o) = t; + VALUE_TYPE(o) = VCVT_RAW; +} + +VObject* vObjectVObjectValue(VObject *o) +{ + return VOBJECT_VALUE_OF(o); +} + +void setVObjectVObjectValue(VObject *o, VObject *p) +{ + VOBJECT_VALUE_OF(o) = p; + VALUE_TYPE(o) = VCVT_VOBJECT; +} + +int vObjectValueType(VObject *o) +{ + return VALUE_TYPE(o); +} + + +/*---------------------------------------------------------------------- + The following functions can be used to build VObject. + ----------------------------------------------------------------------*/ + +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 + --> + o {next,id,prop,val} + V + pn {next,id,prop,val} + V + p {next,id,prop,val} + ... + p1 {next,id,prop,val} + V + pn + */ + + 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) +{ + return addVObjectProp(o,newVObject(id)); +} + +VObject* addProp_(VObject *o, const char *id) +{ + return addVObjectProp(o,newVObject_(id)); +} + +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) +{ + return o->next; +} + +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) +{ + void *p = dupStr(val,size); + return setValueWithSize_(prop,p,p?size:0); +} + +void initPropIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->prop; + i->next = 0; +} + +void initVObjectIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->next; + i->next = 0; +} + +int moreIteration(VObjectIterator *i) +{ + return (i->start && (i->next==0 || i->next!=i->start)); +} + +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) +{ + VObjectIterator i; + initPropIterator(&i,o); + while (moreIteration(&i)) { + VObject *each = nextVObject(&i); + if (!strcasecmp(id,each->id)) + return each; + } + return (VObject*)0; +} + +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; + gs = dupStr(g,0); /* so we can write to it. */ + /* used to be + * t = p = addProp_(o,lookupProp_(n)); + */ + t = p = addProp_(o,lookupProp(n)); + dot = strrchr(gs,'.'); + *dot = 0; + do { + dot = strrchr(gs,'.'); + if (dot) { + n = dot+1; + *dot=0; + } + else + n = gs; + /* property(VCGroupingProp=n); + * 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) +{ + VObject *prop; + prop = addProp(o,p); + setVObjectUStringZValue_(prop, fakeUnicode(v,0)); + return prop; +} + +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, + 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); + +static void indent(FILE *fp, int level) +{ + int i; + for (i=0;ifail) 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); + 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); + 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; + } + else if (fp->alloc) { + fp->limit = fp->limit + OFILE_REALLOC_SIZE; + fp->s = 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 (c == '\n') { + /* write out as */ + appendcOFile_(fp,0xd); + appendcOFile_(fp,0xa); + } + else + appendcOFile_(fp,c); +} + +static void appendsOFile(OFile *fp, const char *s) +{ + int i, slen; + slen = strlen(s); + for (i=0; ifp = ofp; + fp->s = 0; + fp->len = 0; + fp->limit = 0; + fp->alloc = 0; + fp->fail = 0; +} + +static void initMemOFile(OFile *fp, char *s, int len) +{ + fp->fp = 0; + fp->s = s; + fp->len = 0; + fp->limit = s?len:0; + fp->alloc = s?0:1; + fp->fail = 0; +} + + +static int writeBase64(OFile *fp, unsigned char *s, long len) +{ + long cur = 0; + int i, numQuads = 0; + unsigned long trip; + unsigned char b; + char quad[5]; +#define MAXQUADS 16 + + quad[4] = 0; + + while (cur < len) { + /* 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 */ + 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] = '/'; + } + /* 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) +{ + 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++; + } +} + +static void writeVObject_(OFile *fp, VObject *o); + +static void writeValue(OFile *fp, VObject *o, unsigned long size) +{ + 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); + 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); + 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); + break; + } + case VCVT_RAW: { + appendcOFile(fp,'\n'); + writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size); + break; + } + case VCVT_VOBJECT: + appendcOFile(fp,'\n'); + writeVObject_(fp,VOBJECT_VALUE_OF(o)); + break; + } +} + +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); + } +} + +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(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; + list++; + } + return 0; +} + +static void writeProp(OFile *fp, VObject *o) +{ + 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)) + writeAttrValue(fp,eachProp); + } + if (fields_) { + int i = 0, n = 0; + const char** fields = fields_; + /* output prop as fields */ + appendcOFile(fp,':'); + while (*fields) { + VObject *tl = isAPropertyOf(o,*fields); + i++; + if (tl) n = i; + fields++; + } + fields = fields_; + for (i=0;iflags & PD_BEGIN) != 0)) { + VObjectIterator t; + const char *begin = NAME_OF(o); + appendsOFile(fp,"BEGIN:"); + appendsOFile(fp,begin); + appendcOFile(fp,'\n'); + initPropIterator(&t,o); + while (moreIteration(&t)) { + VObject *eachProp = nextVObject(&t); + writeProp(fp, eachProp); + } + appendsOFile(fp,"END:"); + appendsOFile(fp,begin); + appendsOFile(fp,"\n\n"); + } + } +} + +void writeVObject(FILE *fp, VObject *o) +{ + OFile ofp; + initOFile(&ofp,fp); + writeVObject_(&ofp,o); +} + +void writeVObjectToFile(char *fname, VObject *o) +{ + FILE *fp = fopen(fname,"w"); + if (fp) { + writeVObject(fp,o); + fclose(fp); + } +} + +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) +{ + 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) +{ + 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) +{ + 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) +{ + int i = 0; + while (*u != (wchar_t)0) { u++; i++; } + return i; +} + +char* fakeCString(const wchar_t *u) +{ + char *s, *t; + int len = uStrLen(u) + 1; + t = s = (char*)malloc(len+1); + 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; +} + +/* end of source file vobject.c */ -- cgit v0.9.0.2